Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / WinForms / Managed / System / WinForms / DataGridCaption.cs / 1 / DataGridCaption.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Windows.Forms { using System.Diagnostics; using System; using System.Windows.Forms; using System.ComponentModel; using System.Drawing; using System.Drawing.Imaging; using Microsoft.Win32; using System.Globalization; ////// internal class DataGridCaption { internal EventHandlerList events; private const int xOffset = 3; private const int yOffset = 1; private const int textPadding = 2; private const int buttonToText = 4; private static ColorMap[] colorMap = new ColorMap[] {new ColorMap()}; private static readonly Point minimumBounds = new Point(50, 30); private DataGrid dataGrid = null; private bool backButtonVisible = false; private bool downButtonVisible = false; private SolidBrush backBrush = DefaultBackBrush; private SolidBrush foreBrush = DefaultForeBrush; private Pen textBorderPen = DefaultTextBorderPen; private string text = ""; private bool textBorderVisible = false; private Font textFont = null; // use the datagridFont when the textFont is not set // we cache this font ( cause we have to make it bold every time we paint the caption ) // private Font dataGridFont = null; private bool backActive = false; private bool downActive = false; private bool backPressed = false; private bool downPressed = false; // if the downButton should point down or not private bool downButtonDown = false; private static Bitmap leftButtonBitmap; private static Bitmap leftButtonBitmap_bidi; private static Bitmap magnifyingGlassBitmap; private Rectangle backButtonRect = new Rectangle(); private Rectangle downButtonRect = new Rectangle(); private Rectangle textRect = new Rectangle(); private CaptionLocation lastMouseLocation = CaptionLocation.Nowhere; private EventEntry eventList; private static readonly object EVENT_BACKWARDCLICKED = new object(); private static readonly object EVENT_DOWNCLICKED = new object(); private static readonly object EVENT_CAPTIONCLICKED = new object(); internal DataGridCaption(DataGrid dataGrid) { this.dataGrid = dataGrid; this.downButtonVisible = dataGrid.ParentRowsVisible; colorMap[0].OldColor = Color.White; colorMap[0].NewColor = this.ForeColor; OnGridFontChanged(); } internal void OnGridFontChanged() { if (dataGridFont == null || !dataGridFont.Equals(dataGrid.Font)) { try { this.dataGridFont = new Font(dataGrid.Font, FontStyle.Bold); } catch { } } } // =----------------------------------------------------------------- // = Properties // =----------------------------------------------------------------- internal bool BackButtonActive { get { return backActive; } set { if (backActive != value) { backActive = value; InvalidateCaptionRect(backButtonRect); } } } internal bool DownButtonActive { get { return downActive; } set { if (downActive != value) { downActive = value; InvalidateCaptionRect(downButtonRect); } } } internal static SolidBrush DefaultBackBrush { get { return (SolidBrush)SystemBrushes.ActiveCaption; } } internal static Pen DefaultTextBorderPen { get { return new Pen(SystemColors.ActiveCaptionText); } } internal static SolidBrush DefaultForeBrush { get { return (SolidBrush)SystemBrushes.ActiveCaptionText; } } internal Color BackColor { get { return backBrush.Color; } set { if (!backBrush.Color.Equals(value)) { if (value.IsEmpty) throw new ArgumentException(SR.GetString(SR.DataGridEmptyColor, "Caption BackColor")); backBrush = new SolidBrush(value); Invalidate(); } } } internal EventHandlerList Events { get { if (events == null) { events = new EventHandlerList(); } return events; } } internal Font Font { get { // use the dataGridFont only if the user // did not set the CaptionFont // if (textFont == null) return this.dataGridFont; else return textFont; } set { if (textFont == null || !textFont.Equals(value)) { textFont = value; // this property gets called in the constructor before dataGrid has a caption // and we don't need this special-handling then... if (dataGrid.Caption != null) { dataGrid.RecalculateFonts(); dataGrid.PerformLayout(); dataGrid.Invalidate(); // smaller invalidate rect? } } } } internal bool ShouldSerializeFont() { return textFont != null && !textFont.Equals(this.dataGridFont); } internal bool ShouldSerializeBackColor() { return !backBrush.Equals(DefaultBackBrush); } internal void ResetBackColor() { if (ShouldSerializeBackColor()) { backBrush = DefaultBackBrush; Invalidate(); } } internal void ResetForeColor() { if (ShouldSerializeForeColor()) { foreBrush = DefaultForeBrush; Invalidate(); } } internal bool ShouldSerializeForeColor() { return !foreBrush.Equals(DefaultForeBrush); } internal void ResetFont() { textFont = null; Invalidate(); } internal string Text { get { return text; } set { if (value == null) text = ""; else text = value; Invalidate(); } } internal bool TextBorderVisible { get { return textBorderVisible; } set { textBorderVisible = value; Invalidate(); } } internal Color ForeColor { get { return foreBrush.Color; } set { if (value.IsEmpty) throw new ArgumentException(SR.GetString(SR.DataGridEmptyColor, "Caption ForeColor")); foreBrush = new SolidBrush(value); colorMap[0].NewColor = this.ForeColor; Invalidate(); } } internal Point MinimumBounds { get { return minimumBounds; } } internal bool BackButtonVisible { get { return backButtonVisible; } set { if (backButtonVisible != value) { backButtonVisible = value; Invalidate(); } } } internal bool DownButtonVisible { get { return downButtonVisible; } set { if (downButtonVisible != value) { downButtonVisible = value; Invalidate(); } } } // =------------------------------------------------------------------ // = Methods // =----------------------------------------------------------------- protected virtual void AddEventHandler(object key, Delegate handler) { // Locking 'this' here is ok since this is an internal class. See VSW#464499. lock(this) { if (handler == null) return; for (EventEntry e = eventList; e != null; e = e.next) { if (e.key == key) { e.handler = Delegate.Combine(e.handler, handler); return; } } eventList = new EventEntry(eventList, key, handler); } } ////// Represents a caption in the DataGrid control. /// ////// Adds a listener for the BackwardClicked event. /// internal event EventHandler BackwardClicked { add { Events.AddHandler(EVENT_BACKWARDCLICKED, value); } remove { Events.RemoveHandler(EVENT_BACKWARDCLICKED, value); } } ////// Adds a listener for the CaptionClicked event. /// internal event EventHandler CaptionClicked { add { Events.AddHandler(EVENT_CAPTIONCLICKED, value); } remove { Events.RemoveHandler(EVENT_CAPTIONCLICKED, value); } } internal event EventHandler DownClicked { add { Events.AddHandler(EVENT_DOWNCLICKED, value); } remove { Events.RemoveHandler(EVENT_DOWNCLICKED, value); } } private void Invalidate() { if (dataGrid != null) dataGrid.InvalidateCaption(); } private void InvalidateCaptionRect(Rectangle r) { if (dataGrid != null) dataGrid.InvalidateCaptionRect(r); } private void InvalidateLocation(CaptionLocation loc) { Rectangle r; switch (loc) { case CaptionLocation.BackButton: r = backButtonRect; r.Inflate(1,1); InvalidateCaptionRect(r); break; case CaptionLocation.DownButton: r = downButtonRect; r.Inflate(1,1); InvalidateCaptionRect(r); break; } } protected void OnBackwardClicked(EventArgs e) { if (backActive) { EventHandler handler = (EventHandler)Events[EVENT_BACKWARDCLICKED]; if (handler != null) handler(this,e); } } protected void OnCaptionClicked(EventArgs e) { EventHandler handler = (EventHandler)Events[EVENT_CAPTIONCLICKED]; if (handler != null) handler(this,e); } protected void OnDownClicked(EventArgs e) { if (downActive && downButtonVisible) { EventHandler handler = (EventHandler)Events[EVENT_DOWNCLICKED]; if (handler != null) handler(this,e); } } private Bitmap GetBitmap(string bitmapName) { Bitmap b = null; try { b = new Bitmap(typeof(DataGridCaption), bitmapName); b.MakeTransparent(); } catch (Exception e) { Debug.Fail("Failed to load bitmap: " + bitmapName, e.ToString()); } return b; } private Bitmap GetBackButtonBmp(bool alignRight) { if (alignRight) { if (leftButtonBitmap_bidi == null) leftButtonBitmap_bidi = GetBitmap("DataGridCaption.backarrow_bidi.bmp"); return leftButtonBitmap_bidi; } else { if (leftButtonBitmap == null) leftButtonBitmap = GetBitmap("DataGridCaption.backarrow.bmp"); return leftButtonBitmap; } } private Bitmap GetDetailsBmp() { if (magnifyingGlassBitmap == null) magnifyingGlassBitmap = GetBitmap("DataGridCaption.Details.bmp"); return magnifyingGlassBitmap; } protected virtual Delegate GetEventHandler(object key) { // Locking 'this' here is ok since this is an internal class. See VSW#464499. lock(this) { for (EventEntry e = eventList; e != null; e = e.next) { if (e.key == key) return e.handler; } return null; } } internal Rectangle GetBackButtonRect(Rectangle bounds, bool alignRight, int downButtonWidth) { Bitmap backButtonBmp = GetBackButtonBmp(false); Size backButtonSize; lock (backButtonBmp) { backButtonSize = backButtonBmp.Size; } return new Rectangle( bounds.Right - xOffset * 4 - downButtonWidth - backButtonSize.Width, bounds.Y + yOffset + textPadding, backButtonSize.Width, backButtonSize.Height); } internal int GetDetailsButtonWidth() { int width = 0; Bitmap detailsBmp = GetDetailsBmp(); lock (detailsBmp) { width = detailsBmp.Size.Width; } return width; } internal Rectangle GetDetailsButtonRect(Rectangle bounds, bool alignRight) { Size downButtonSize; Bitmap detailsBmp = GetDetailsBmp(); lock (detailsBmp) { downButtonSize = detailsBmp.Size; } int downButtonWidth = downButtonSize.Width; return new Rectangle( bounds.Right - xOffset * 2 - downButtonWidth, bounds.Y + yOffset + textPadding, downButtonWidth, downButtonSize.Height); } ////// Called by the dataGrid when it needs the caption /// to repaint. /// internal void Paint(Graphics g, Rectangle bounds, bool alignRight) { Size textSize = new Size((int) g.MeasureString(text, this.Font).Width + 2, this.Font.Height + 2); downButtonRect = GetDetailsButtonRect(bounds, alignRight); int downButtonWidth = GetDetailsButtonWidth(); backButtonRect = GetBackButtonRect(bounds, alignRight, downButtonWidth); int backButtonArea = backButtonVisible ? backButtonRect.Width + xOffset + buttonToText : 0; int downButtonArea = downButtonVisible && !dataGrid.ParentRowsIsEmpty() ? downButtonWidth + xOffset + buttonToText : 0; int textWidthLeft = bounds.Width - xOffset - backButtonArea - downButtonArea; textRect = new Rectangle( bounds.X, bounds.Y + yOffset, Math.Min(textWidthLeft, 2 * textPadding + textSize.Width), 2 * textPadding + textSize.Height); // align the caption text box, downButton, and backButton // if the RigthToLeft property is set to true if (alignRight) { textRect.X = bounds.Right - textRect.Width; backButtonRect.X = bounds.X + xOffset * 4 + downButtonWidth; downButtonRect.X = bounds.X + xOffset * 2; } Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "text size = " + textSize.ToString()); Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "downButtonWidth = " + downButtonWidth.ToString(CultureInfo.InvariantCulture)); Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "textWidthLeft = " + textWidthLeft.ToString(CultureInfo.InvariantCulture)); Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "backButtonRect " + backButtonRect.ToString()); Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "textRect " + textRect.ToString()); Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "downButtonRect " + downButtonRect.ToString()); // we should use the code that is commented out // with today's code, there are pixels on the backButtonRect and the downButtonRect // that are getting painted twice // g.FillRectangle(backBrush, bounds); if (backButtonVisible) { PaintBackButton(g, backButtonRect, alignRight); if (backActive) { if (lastMouseLocation == CaptionLocation.BackButton) { backButtonRect.Inflate(1,1); ControlPaint.DrawBorder3D(g, backButtonRect, backPressed ? Border3DStyle.SunkenInner : Border3DStyle.RaisedInner); } } } PaintText(g, textRect, alignRight); if (downButtonVisible && !dataGrid.ParentRowsIsEmpty()) { PaintDownButton(g, downButtonRect); // the rules have changed, yet again. // now: if we show the parent rows and the mouse is // not on top of this icon, then let the icon be depressed. // if the mouse is pressed over the icon, then show the icon pressed // if the mouse is over the icon and not pressed, then show the icon SunkenInner; // if (lastMouseLocation == CaptionLocation.DownButton) { downButtonRect.Inflate(1,1); ControlPaint.DrawBorder3D(g, downButtonRect, downPressed ? Border3DStyle.SunkenInner : Border3DStyle.RaisedInner); } } } private void PaintIcon(Graphics g, Rectangle bounds, Bitmap b) { ImageAttributes attr = new ImageAttributes(); attr.SetRemapTable(colorMap, ColorAdjustType.Bitmap); g.DrawImage(b, bounds, 0, 0, bounds.Width, bounds.Height,GraphicsUnit.Pixel, attr); attr.Dispose(); } private void PaintBackButton(Graphics g, Rectangle bounds, bool alignRight) { Bitmap backButtonBmp = GetBackButtonBmp(alignRight); lock (backButtonBmp) { PaintIcon(g, bounds, backButtonBmp); } } private void PaintDownButton(Graphics g, Rectangle bounds) { Bitmap detailsBmp = GetDetailsBmp(); lock (detailsBmp) { PaintIcon(g, bounds, detailsBmp); } } private void PaintText(Graphics g, Rectangle bounds, bool alignToRight) { Rectangle textBounds = bounds; if (textBounds.Width <= 0 || textBounds.Height <= 0) return; if (textBorderVisible) { g.DrawRectangle(this.textBorderPen, textBounds.X, textBounds.Y, textBounds.Width - 1, textBounds.Height - 1); textBounds.Inflate(-1,-1); } if (textPadding > 0) { Rectangle border = textBounds; border.Height = textPadding; g.FillRectangle(this.backBrush, border); border.Y = textBounds.Bottom - textPadding; g.FillRectangle(this.backBrush, border); border = new Rectangle(textBounds.X, textBounds.Y + textPadding, textPadding, textBounds.Height - 2*textPadding); g.FillRectangle(this.backBrush, border); border.X = textBounds.Right - textPadding; g.FillRectangle(this.backBrush, border); textBounds.Inflate(-textPadding, -textPadding); } g.FillRectangle(this.backBrush, textBounds); // Brush foreBrush = new SolidBrush(dataGrid.CaptionForeColor); StringFormat format = new StringFormat(); if (alignToRight) { format.FormatFlags |= StringFormatFlags.DirectionRightToLeft; format.Alignment = StringAlignment.Far; } g.DrawString(text, this.Font, foreBrush, textBounds, format); format.Dispose(); // foreBrush.Dispose(); } private CaptionLocation FindLocation(int x, int y) { if (!backButtonRect.IsEmpty) { if (backButtonRect.Contains(x,y)) return CaptionLocation.BackButton; } if (!downButtonRect.IsEmpty) { if (downButtonRect.Contains(x,y)) return CaptionLocation.DownButton; } if (!textRect.IsEmpty) { if (textRect.Contains(x,y)) return CaptionLocation.Text; } return CaptionLocation.Nowhere; } private bool DownButtonDown { get { return downButtonDown; } set { if (downButtonDown != value) { downButtonDown = value; InvalidateLocation(CaptionLocation.DownButton); } } } internal bool GetDownButtonDirection() { return DownButtonDown; } ////// Called by the dataGrid when the mouse is pressed /// inside the caption. /// internal void MouseDown(int x, int y) { CaptionLocation loc = FindLocation(x, y); switch (loc) { case CaptionLocation.BackButton: backPressed = true; InvalidateLocation(loc); break; case CaptionLocation.DownButton: downPressed = true; InvalidateLocation(loc); break; case CaptionLocation.Text: OnCaptionClicked(EventArgs.Empty); break; } } ////// Called by the dataGrid when the mouse is released /// inside the caption. /// internal void MouseUp(int x, int y) { CaptionLocation loc = FindLocation(x, y); switch (loc) { case CaptionLocation.DownButton: if (downPressed == true) { downPressed = false; OnDownClicked(EventArgs.Empty); } break; case CaptionLocation.BackButton: if (backPressed == true) { backPressed = false; OnBackwardClicked(EventArgs.Empty); } break; } } ////// Called by the dataGrid when the mouse leaves /// the caption area. /// internal void MouseLeft() { CaptionLocation oldLoc = lastMouseLocation; lastMouseLocation = CaptionLocation.Nowhere; InvalidateLocation(oldLoc); } ////// Called by the dataGrid when the mouse is /// inside the caption. /// internal void MouseOver(int x, int y) { CaptionLocation newLoc = FindLocation(x, y); InvalidateLocation(lastMouseLocation); InvalidateLocation(newLoc); lastMouseLocation = newLoc; } protected virtual void RaiseEvent(object key, EventArgs e) { Delegate handler = GetEventHandler(key); if (handler != null)((EventHandler)handler)(this, e); } protected virtual void RemoveEventHandler(object key, Delegate handler) { // Locking 'this' here is ok since this is an internal class. See VSW#464499. lock(this) { if (handler == null) return; for (EventEntry e = eventList, prev = null; e != null; prev = e, e = e.next) { if (e.key == key) { e.handler = Delegate.Remove(e.handler, handler); if (e.handler == null) { if (prev == null) { eventList = e.next; } else { prev.next = e.next; } } return; } } } } protected virtual void RemoveEventHandlers() { eventList = null; } internal void SetDownButtonDirection(bool pointDown) { DownButtonDown = pointDown; } ////// Toggles the direction the "Down Button" is pointing. /// internal bool ToggleDownButtonDirection() { DownButtonDown = !DownButtonDown; return DownButtonDown; } internal enum CaptionLocation { Nowhere, BackButton, DownButton, Text } private sealed class EventEntry { internal EventEntry next; internal object key; internal Delegate handler; internal EventEntry(EventEntry next, object key, Delegate handler) { this.next = next; this.key = key; this.handler = handler; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Windows.Forms { using System.Diagnostics; using System; using System.Windows.Forms; using System.ComponentModel; using System.Drawing; using System.Drawing.Imaging; using Microsoft.Win32; using System.Globalization; ////// internal class DataGridCaption { internal EventHandlerList events; private const int xOffset = 3; private const int yOffset = 1; private const int textPadding = 2; private const int buttonToText = 4; private static ColorMap[] colorMap = new ColorMap[] {new ColorMap()}; private static readonly Point minimumBounds = new Point(50, 30); private DataGrid dataGrid = null; private bool backButtonVisible = false; private bool downButtonVisible = false; private SolidBrush backBrush = DefaultBackBrush; private SolidBrush foreBrush = DefaultForeBrush; private Pen textBorderPen = DefaultTextBorderPen; private string text = ""; private bool textBorderVisible = false; private Font textFont = null; // use the datagridFont when the textFont is not set // we cache this font ( cause we have to make it bold every time we paint the caption ) // private Font dataGridFont = null; private bool backActive = false; private bool downActive = false; private bool backPressed = false; private bool downPressed = false; // if the downButton should point down or not private bool downButtonDown = false; private static Bitmap leftButtonBitmap; private static Bitmap leftButtonBitmap_bidi; private static Bitmap magnifyingGlassBitmap; private Rectangle backButtonRect = new Rectangle(); private Rectangle downButtonRect = new Rectangle(); private Rectangle textRect = new Rectangle(); private CaptionLocation lastMouseLocation = CaptionLocation.Nowhere; private EventEntry eventList; private static readonly object EVENT_BACKWARDCLICKED = new object(); private static readonly object EVENT_DOWNCLICKED = new object(); private static readonly object EVENT_CAPTIONCLICKED = new object(); internal DataGridCaption(DataGrid dataGrid) { this.dataGrid = dataGrid; this.downButtonVisible = dataGrid.ParentRowsVisible; colorMap[0].OldColor = Color.White; colorMap[0].NewColor = this.ForeColor; OnGridFontChanged(); } internal void OnGridFontChanged() { if (dataGridFont == null || !dataGridFont.Equals(dataGrid.Font)) { try { this.dataGridFont = new Font(dataGrid.Font, FontStyle.Bold); } catch { } } } // =----------------------------------------------------------------- // = Properties // =----------------------------------------------------------------- internal bool BackButtonActive { get { return backActive; } set { if (backActive != value) { backActive = value; InvalidateCaptionRect(backButtonRect); } } } internal bool DownButtonActive { get { return downActive; } set { if (downActive != value) { downActive = value; InvalidateCaptionRect(downButtonRect); } } } internal static SolidBrush DefaultBackBrush { get { return (SolidBrush)SystemBrushes.ActiveCaption; } } internal static Pen DefaultTextBorderPen { get { return new Pen(SystemColors.ActiveCaptionText); } } internal static SolidBrush DefaultForeBrush { get { return (SolidBrush)SystemBrushes.ActiveCaptionText; } } internal Color BackColor { get { return backBrush.Color; } set { if (!backBrush.Color.Equals(value)) { if (value.IsEmpty) throw new ArgumentException(SR.GetString(SR.DataGridEmptyColor, "Caption BackColor")); backBrush = new SolidBrush(value); Invalidate(); } } } internal EventHandlerList Events { get { if (events == null) { events = new EventHandlerList(); } return events; } } internal Font Font { get { // use the dataGridFont only if the user // did not set the CaptionFont // if (textFont == null) return this.dataGridFont; else return textFont; } set { if (textFont == null || !textFont.Equals(value)) { textFont = value; // this property gets called in the constructor before dataGrid has a caption // and we don't need this special-handling then... if (dataGrid.Caption != null) { dataGrid.RecalculateFonts(); dataGrid.PerformLayout(); dataGrid.Invalidate(); // smaller invalidate rect? } } } } internal bool ShouldSerializeFont() { return textFont != null && !textFont.Equals(this.dataGridFont); } internal bool ShouldSerializeBackColor() { return !backBrush.Equals(DefaultBackBrush); } internal void ResetBackColor() { if (ShouldSerializeBackColor()) { backBrush = DefaultBackBrush; Invalidate(); } } internal void ResetForeColor() { if (ShouldSerializeForeColor()) { foreBrush = DefaultForeBrush; Invalidate(); } } internal bool ShouldSerializeForeColor() { return !foreBrush.Equals(DefaultForeBrush); } internal void ResetFont() { textFont = null; Invalidate(); } internal string Text { get { return text; } set { if (value == null) text = ""; else text = value; Invalidate(); } } internal bool TextBorderVisible { get { return textBorderVisible; } set { textBorderVisible = value; Invalidate(); } } internal Color ForeColor { get { return foreBrush.Color; } set { if (value.IsEmpty) throw new ArgumentException(SR.GetString(SR.DataGridEmptyColor, "Caption ForeColor")); foreBrush = new SolidBrush(value); colorMap[0].NewColor = this.ForeColor; Invalidate(); } } internal Point MinimumBounds { get { return minimumBounds; } } internal bool BackButtonVisible { get { return backButtonVisible; } set { if (backButtonVisible != value) { backButtonVisible = value; Invalidate(); } } } internal bool DownButtonVisible { get { return downButtonVisible; } set { if (downButtonVisible != value) { downButtonVisible = value; Invalidate(); } } } // =------------------------------------------------------------------ // = Methods // =----------------------------------------------------------------- protected virtual void AddEventHandler(object key, Delegate handler) { // Locking 'this' here is ok since this is an internal class. See VSW#464499. lock(this) { if (handler == null) return; for (EventEntry e = eventList; e != null; e = e.next) { if (e.key == key) { e.handler = Delegate.Combine(e.handler, handler); return; } } eventList = new EventEntry(eventList, key, handler); } } ////// Represents a caption in the DataGrid control. /// ////// Adds a listener for the BackwardClicked event. /// internal event EventHandler BackwardClicked { add { Events.AddHandler(EVENT_BACKWARDCLICKED, value); } remove { Events.RemoveHandler(EVENT_BACKWARDCLICKED, value); } } ////// Adds a listener for the CaptionClicked event. /// internal event EventHandler CaptionClicked { add { Events.AddHandler(EVENT_CAPTIONCLICKED, value); } remove { Events.RemoveHandler(EVENT_CAPTIONCLICKED, value); } } internal event EventHandler DownClicked { add { Events.AddHandler(EVENT_DOWNCLICKED, value); } remove { Events.RemoveHandler(EVENT_DOWNCLICKED, value); } } private void Invalidate() { if (dataGrid != null) dataGrid.InvalidateCaption(); } private void InvalidateCaptionRect(Rectangle r) { if (dataGrid != null) dataGrid.InvalidateCaptionRect(r); } private void InvalidateLocation(CaptionLocation loc) { Rectangle r; switch (loc) { case CaptionLocation.BackButton: r = backButtonRect; r.Inflate(1,1); InvalidateCaptionRect(r); break; case CaptionLocation.DownButton: r = downButtonRect; r.Inflate(1,1); InvalidateCaptionRect(r); break; } } protected void OnBackwardClicked(EventArgs e) { if (backActive) { EventHandler handler = (EventHandler)Events[EVENT_BACKWARDCLICKED]; if (handler != null) handler(this,e); } } protected void OnCaptionClicked(EventArgs e) { EventHandler handler = (EventHandler)Events[EVENT_CAPTIONCLICKED]; if (handler != null) handler(this,e); } protected void OnDownClicked(EventArgs e) { if (downActive && downButtonVisible) { EventHandler handler = (EventHandler)Events[EVENT_DOWNCLICKED]; if (handler != null) handler(this,e); } } private Bitmap GetBitmap(string bitmapName) { Bitmap b = null; try { b = new Bitmap(typeof(DataGridCaption), bitmapName); b.MakeTransparent(); } catch (Exception e) { Debug.Fail("Failed to load bitmap: " + bitmapName, e.ToString()); } return b; } private Bitmap GetBackButtonBmp(bool alignRight) { if (alignRight) { if (leftButtonBitmap_bidi == null) leftButtonBitmap_bidi = GetBitmap("DataGridCaption.backarrow_bidi.bmp"); return leftButtonBitmap_bidi; } else { if (leftButtonBitmap == null) leftButtonBitmap = GetBitmap("DataGridCaption.backarrow.bmp"); return leftButtonBitmap; } } private Bitmap GetDetailsBmp() { if (magnifyingGlassBitmap == null) magnifyingGlassBitmap = GetBitmap("DataGridCaption.Details.bmp"); return magnifyingGlassBitmap; } protected virtual Delegate GetEventHandler(object key) { // Locking 'this' here is ok since this is an internal class. See VSW#464499. lock(this) { for (EventEntry e = eventList; e != null; e = e.next) { if (e.key == key) return e.handler; } return null; } } internal Rectangle GetBackButtonRect(Rectangle bounds, bool alignRight, int downButtonWidth) { Bitmap backButtonBmp = GetBackButtonBmp(false); Size backButtonSize; lock (backButtonBmp) { backButtonSize = backButtonBmp.Size; } return new Rectangle( bounds.Right - xOffset * 4 - downButtonWidth - backButtonSize.Width, bounds.Y + yOffset + textPadding, backButtonSize.Width, backButtonSize.Height); } internal int GetDetailsButtonWidth() { int width = 0; Bitmap detailsBmp = GetDetailsBmp(); lock (detailsBmp) { width = detailsBmp.Size.Width; } return width; } internal Rectangle GetDetailsButtonRect(Rectangle bounds, bool alignRight) { Size downButtonSize; Bitmap detailsBmp = GetDetailsBmp(); lock (detailsBmp) { downButtonSize = detailsBmp.Size; } int downButtonWidth = downButtonSize.Width; return new Rectangle( bounds.Right - xOffset * 2 - downButtonWidth, bounds.Y + yOffset + textPadding, downButtonWidth, downButtonSize.Height); } ////// Called by the dataGrid when it needs the caption /// to repaint. /// internal void Paint(Graphics g, Rectangle bounds, bool alignRight) { Size textSize = new Size((int) g.MeasureString(text, this.Font).Width + 2, this.Font.Height + 2); downButtonRect = GetDetailsButtonRect(bounds, alignRight); int downButtonWidth = GetDetailsButtonWidth(); backButtonRect = GetBackButtonRect(bounds, alignRight, downButtonWidth); int backButtonArea = backButtonVisible ? backButtonRect.Width + xOffset + buttonToText : 0; int downButtonArea = downButtonVisible && !dataGrid.ParentRowsIsEmpty() ? downButtonWidth + xOffset + buttonToText : 0; int textWidthLeft = bounds.Width - xOffset - backButtonArea - downButtonArea; textRect = new Rectangle( bounds.X, bounds.Y + yOffset, Math.Min(textWidthLeft, 2 * textPadding + textSize.Width), 2 * textPadding + textSize.Height); // align the caption text box, downButton, and backButton // if the RigthToLeft property is set to true if (alignRight) { textRect.X = bounds.Right - textRect.Width; backButtonRect.X = bounds.X + xOffset * 4 + downButtonWidth; downButtonRect.X = bounds.X + xOffset * 2; } Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "text size = " + textSize.ToString()); Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "downButtonWidth = " + downButtonWidth.ToString(CultureInfo.InvariantCulture)); Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "textWidthLeft = " + textWidthLeft.ToString(CultureInfo.InvariantCulture)); Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "backButtonRect " + backButtonRect.ToString()); Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "textRect " + textRect.ToString()); Debug.WriteLineIf(CompModSwitches.DGCaptionPaint.TraceVerbose, "downButtonRect " + downButtonRect.ToString()); // we should use the code that is commented out // with today's code, there are pixels on the backButtonRect and the downButtonRect // that are getting painted twice // g.FillRectangle(backBrush, bounds); if (backButtonVisible) { PaintBackButton(g, backButtonRect, alignRight); if (backActive) { if (lastMouseLocation == CaptionLocation.BackButton) { backButtonRect.Inflate(1,1); ControlPaint.DrawBorder3D(g, backButtonRect, backPressed ? Border3DStyle.SunkenInner : Border3DStyle.RaisedInner); } } } PaintText(g, textRect, alignRight); if (downButtonVisible && !dataGrid.ParentRowsIsEmpty()) { PaintDownButton(g, downButtonRect); // the rules have changed, yet again. // now: if we show the parent rows and the mouse is // not on top of this icon, then let the icon be depressed. // if the mouse is pressed over the icon, then show the icon pressed // if the mouse is over the icon and not pressed, then show the icon SunkenInner; // if (lastMouseLocation == CaptionLocation.DownButton) { downButtonRect.Inflate(1,1); ControlPaint.DrawBorder3D(g, downButtonRect, downPressed ? Border3DStyle.SunkenInner : Border3DStyle.RaisedInner); } } } private void PaintIcon(Graphics g, Rectangle bounds, Bitmap b) { ImageAttributes attr = new ImageAttributes(); attr.SetRemapTable(colorMap, ColorAdjustType.Bitmap); g.DrawImage(b, bounds, 0, 0, bounds.Width, bounds.Height,GraphicsUnit.Pixel, attr); attr.Dispose(); } private void PaintBackButton(Graphics g, Rectangle bounds, bool alignRight) { Bitmap backButtonBmp = GetBackButtonBmp(alignRight); lock (backButtonBmp) { PaintIcon(g, bounds, backButtonBmp); } } private void PaintDownButton(Graphics g, Rectangle bounds) { Bitmap detailsBmp = GetDetailsBmp(); lock (detailsBmp) { PaintIcon(g, bounds, detailsBmp); } } private void PaintText(Graphics g, Rectangle bounds, bool alignToRight) { Rectangle textBounds = bounds; if (textBounds.Width <= 0 || textBounds.Height <= 0) return; if (textBorderVisible) { g.DrawRectangle(this.textBorderPen, textBounds.X, textBounds.Y, textBounds.Width - 1, textBounds.Height - 1); textBounds.Inflate(-1,-1); } if (textPadding > 0) { Rectangle border = textBounds; border.Height = textPadding; g.FillRectangle(this.backBrush, border); border.Y = textBounds.Bottom - textPadding; g.FillRectangle(this.backBrush, border); border = new Rectangle(textBounds.X, textBounds.Y + textPadding, textPadding, textBounds.Height - 2*textPadding); g.FillRectangle(this.backBrush, border); border.X = textBounds.Right - textPadding; g.FillRectangle(this.backBrush, border); textBounds.Inflate(-textPadding, -textPadding); } g.FillRectangle(this.backBrush, textBounds); // Brush foreBrush = new SolidBrush(dataGrid.CaptionForeColor); StringFormat format = new StringFormat(); if (alignToRight) { format.FormatFlags |= StringFormatFlags.DirectionRightToLeft; format.Alignment = StringAlignment.Far; } g.DrawString(text, this.Font, foreBrush, textBounds, format); format.Dispose(); // foreBrush.Dispose(); } private CaptionLocation FindLocation(int x, int y) { if (!backButtonRect.IsEmpty) { if (backButtonRect.Contains(x,y)) return CaptionLocation.BackButton; } if (!downButtonRect.IsEmpty) { if (downButtonRect.Contains(x,y)) return CaptionLocation.DownButton; } if (!textRect.IsEmpty) { if (textRect.Contains(x,y)) return CaptionLocation.Text; } return CaptionLocation.Nowhere; } private bool DownButtonDown { get { return downButtonDown; } set { if (downButtonDown != value) { downButtonDown = value; InvalidateLocation(CaptionLocation.DownButton); } } } internal bool GetDownButtonDirection() { return DownButtonDown; } ////// Called by the dataGrid when the mouse is pressed /// inside the caption. /// internal void MouseDown(int x, int y) { CaptionLocation loc = FindLocation(x, y); switch (loc) { case CaptionLocation.BackButton: backPressed = true; InvalidateLocation(loc); break; case CaptionLocation.DownButton: downPressed = true; InvalidateLocation(loc); break; case CaptionLocation.Text: OnCaptionClicked(EventArgs.Empty); break; } } ////// Called by the dataGrid when the mouse is released /// inside the caption. /// internal void MouseUp(int x, int y) { CaptionLocation loc = FindLocation(x, y); switch (loc) { case CaptionLocation.DownButton: if (downPressed == true) { downPressed = false; OnDownClicked(EventArgs.Empty); } break; case CaptionLocation.BackButton: if (backPressed == true) { backPressed = false; OnBackwardClicked(EventArgs.Empty); } break; } } ////// Called by the dataGrid when the mouse leaves /// the caption area. /// internal void MouseLeft() { CaptionLocation oldLoc = lastMouseLocation; lastMouseLocation = CaptionLocation.Nowhere; InvalidateLocation(oldLoc); } ////// Called by the dataGrid when the mouse is /// inside the caption. /// internal void MouseOver(int x, int y) { CaptionLocation newLoc = FindLocation(x, y); InvalidateLocation(lastMouseLocation); InvalidateLocation(newLoc); lastMouseLocation = newLoc; } protected virtual void RaiseEvent(object key, EventArgs e) { Delegate handler = GetEventHandler(key); if (handler != null)((EventHandler)handler)(this, e); } protected virtual void RemoveEventHandler(object key, Delegate handler) { // Locking 'this' here is ok since this is an internal class. See VSW#464499. lock(this) { if (handler == null) return; for (EventEntry e = eventList, prev = null; e != null; prev = e, e = e.next) { if (e.key == key) { e.handler = Delegate.Remove(e.handler, handler); if (e.handler == null) { if (prev == null) { eventList = e.next; } else { prev.next = e.next; } } return; } } } } protected virtual void RemoveEventHandlers() { eventList = null; } internal void SetDownButtonDirection(bool pointDown) { DownButtonDown = pointDown; } ////// Toggles the direction the "Down Button" is pointing. /// internal bool ToggleDownButtonDirection() { DownButtonDown = !DownButtonDown; return DownButtonDown; } internal enum CaptionLocation { Nowhere, BackButton, DownButton, Text } private sealed class EventEntry { internal EventEntry next; internal object key; internal Delegate handler; internal EventEntry(EventEntry next, object key, Delegate handler) { this.next = next; this.key = key; this.handler = handler; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- FixUp.cs
- InternalResources.cs
- SqlException.cs
- MonthChangedEventArgs.cs
- TemplateContentLoader.cs
- hresults.cs
- BufferModeSettings.cs
- ConnectionManagementElement.cs
- FontStretches.cs
- SqlBuilder.cs
- ColorContextHelper.cs
- XpsFixedDocumentSequenceReaderWriter.cs
- PointValueSerializer.cs
- RegexCapture.cs
- ResourcePermissionBaseEntry.cs
- TriggerBase.cs
- Dump.cs
- ProxyWebPartManager.cs
- XmlRawWriterWrapper.cs
- MarkupProperty.cs
- WorkflowIdleBehavior.cs
- ExpressionConverter.cs
- PageClientProxyGenerator.cs
- XmlFormatWriterGenerator.cs
- DeferredRunTextReference.cs
- WindowsPen.cs
- HttpListenerResponse.cs
- ItemCollectionEditor.cs
- EncryptedPackage.cs
- ColorDialog.cs
- RefType.cs
- Privilege.cs
- DataControlPagerLinkButton.cs
- recordstate.cs
- IisNotInstalledException.cs
- FirewallWrapper.cs
- __Error.cs
- ListParaClient.cs
- ClockController.cs
- RegexStringValidatorAttribute.cs
- PriorityQueue.cs
- StaticTextPointer.cs
- TextTreeUndo.cs
- TrimSurroundingWhitespaceAttribute.cs
- EmbeddedMailObjectsCollection.cs
- CompiledXpathExpr.cs
- DeliveryRequirementsAttribute.cs
- KeyValueSerializer.cs
- ChildChangedEventArgs.cs
- XsdBuildProvider.cs
- Wrapper.cs
- BmpBitmapEncoder.cs
- TransportSecurityBindingElement.cs
- RetrieveVirtualItemEventArgs.cs
- ConfigurationManagerInternal.cs
- HttpContext.cs
- GridViewRowEventArgs.cs
- XslTransform.cs
- StorageSetMapping.cs
- UpdateCompiler.cs
- RuntimeArgument.cs
- DataListItem.cs
- GroupBox.cs
- IdleTimeoutMonitor.cs
- PreviewPrintController.cs
- QuadraticBezierSegment.cs
- SpellerInterop.cs
- MessageVersionConverter.cs
- AppDomainAttributes.cs
- ExceptionValidationRule.cs
- XPathParser.cs
- UniqueConstraint.cs
- ColorTranslator.cs
- RenderTargetBitmap.cs
- UriTemplateCompoundPathSegment.cs
- TextEffectCollection.cs
- ComponentEvent.cs
- DecoderNLS.cs
- ConsoleTraceListener.cs
- UInt32Storage.cs
- DataRelation.cs
- UncommonField.cs
- Compiler.cs
- CacheOutputQuery.cs
- ChangeInterceptorAttribute.cs
- RunInstallerAttribute.cs
- ComAdminWrapper.cs
- DataPagerFieldCollection.cs
- DataGridTable.cs
- XmlSerializableWriter.cs
- dbdatarecord.cs
- Simplifier.cs
- Filter.cs
- LabelInfo.cs
- DragSelectionMessageFilter.cs
- TextSpanModifier.cs
- Quaternion.cs
- QfeChecker.cs
- Utility.cs
- UnsafeNativeMethods.cs