Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / WinForms / System / WinForms / Design / DesignerUtils.cs / 1 / DesignerUtils.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- /* */ namespace System.Windows.Forms.Design { using System; using System.Collections; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Design; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Windows.Forms.Design.Behavior; using System.Windows.Forms; using System.Globalization; using System.IO; using System.Runtime.Serialization.Formatters.Binary; ////// /// internal static class DesignerUtils { private static Size minDragSize = Size.Empty; //brush used to draw a 'hover' state over a designer action glyph private static SolidBrush hoverBrush = new SolidBrush(Color.FromArgb(50, SystemColors.Highlight)); //brush used to draw the resizeable selection borders around controls/components private static HatchBrush selectionBorderBrush = new HatchBrush(HatchStyle.Percent50, SystemColors.ControlDarkDark, Color.Transparent); //Pens and Brushes used via GDI to render our grabhandles private static IntPtr grabHandleFillBrushPrimary = SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.Window)); private static IntPtr grabHandleFillBrush = SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.ControlText)); private static IntPtr grabHandlePenPrimary = SafeNativeMethods.CreatePen(NativeMethods.PS_SOLID, 1, ColorTranslator.ToWin32(SystemColors.ControlText)); private static IntPtr grabHandlePen = SafeNativeMethods.CreatePen(NativeMethods.PS_SOLID, 1,ColorTranslator.ToWin32(SystemColors.Window)); //The box-like image used as the user is dragging comps from the toolbox // private static Bitmap boxImage = null; public static int BOXIMAGESIZE = 16; // selection border size // public static int SELECTIONBORDERSIZE = 1; // Although the selection border is only 1, we actually want a 3 pixel hittestarea public static int SELECTIONBORDERHITAREA = 3; // We want to make sure that the 1 pixel selectionborder is centered on the handles. // The fact that the border is actually 3 pixels wide works like magic. // If you draw a picture, then you will see why. //grabhandle size (diameter) public static int HANDLESIZE = 7; //how much should the grabhandle overlap the control public static int HANDLEOVERLAP = 2; //we want the selection border to be centered on a grabhandle, so how much do //we need to offset the border from the control to make that happen public static int SELECTIONBORDEROFFSET = ((HANDLESIZE - SELECTIONBORDERSIZE)/2) - HANDLEOVERLAP; //no-resize handle size (diameter) public static int NORESIZEHANDLESIZE = 5; //we want the selection border to be centered on a grabhandle, so how much do //we need to offset the border from the control to make that happen public static int NORESIZEBORDEROFFSET = ((NORESIZEHANDLESIZE - SELECTIONBORDERSIZE)/2); //lock handle height public static int LOCKHANDLEHEIGHT = 9; //total lock handle width public static int LOCKHANDLEWIDTH = 7; //how much should the lockhandle overlap the control public static int LOCKHANDLEOVERLAP = 2; //we want the selection border to be centered on the no-resize handle, so calculate how many pixels we need //to offset the selection border from the control -- since the handle is not square, we need one in each direction public static int LOCKEDSELECTIONBORDEROFFSET_Y = ((LOCKHANDLEHEIGHT - SELECTIONBORDERSIZE) / 2) - LOCKHANDLEOVERLAP; public static int LOCKEDSELECTIONBORDEROFFSET_X = ((LOCKHANDLEWIDTH - SELECTIONBORDERSIZE) / 2) - LOCKHANDLEOVERLAP; // upper rectangle size (diameter) public static int LOCKHANDLESIZE_UPPER = 5; // lower rectangle size public static int LOCKHANDLEHEIGHT_LOWER = 6; public static int LOCKHANDLEWIDTH_LOWER = 7; //Offset used when drawing the upper rect of a lock handle public static int LOCKHANDLEUPPER_OFFSET = (LOCKHANDLEWIDTH_LOWER - LOCKHANDLESIZE_UPPER) / 2; //Offset used when drawing the lower rect of a lock handle public static int LOCKHANDLELOWER_OFFSET = (LOCKHANDLEHEIGHT - LOCKHANDLEHEIGHT_LOWER); public static int CONTAINERGRABHANDLESIZE = 15; //delay for showing snaplines on keyboard movements public static int SNAPELINEDELAY = 1000; //min new row/col style size for the table layout panel public static int MINIMUMSTYLESIZE = 20; public static int MINIMUMSTYLEPERCENT = 50; //min width/height used to create bitmap to paint control into. public static int MINCONTROLBITMAPSIZE = 1; //min size for row/col style during a resize drag operation public static int MINUMUMSTYLESIZEDRAG = 8; //min # of rows/cols for the tablelayoutpanel when it is newly created public static int DEFAULTROWCOUNT = 2; public static int DEFAULTCOLUMNCOUNT = 2; //size of the col/row grab handle glyphs for teh table layout panel public static int RESIZEGLYPHSIZE = 4; //default value for Form padding if it has not been set in the designer (usability study request) public static int DEFAULTFORMPADDING = 9; //use these value to signify ANY of the right, top, left, center, or bottom alignments with the ContentAlignment enum. public static readonly ContentAlignment anyTopAlignment = ContentAlignment.TopLeft | ContentAlignment.TopCenter | ContentAlignment.TopRight; /* UNUSED: private static readonly ContentAlignment anyBottom = ContentAlignment.BottomLeft | ContentAlignment.BottomCenter | ContentAlignment.BottomRight;*/ public static readonly ContentAlignment anyMiddleAlignment = ContentAlignment.MiddleLeft | ContentAlignment.MiddleCenter | ContentAlignment.MiddleRight; ////// Contains designer utilities. /// ////// Used when the user clicks and drags a toolbox item /// onto the documentdesigner - this is the small box that /// is painted beneath the mouse pointer. /// public static Image BoxImage { get { if (boxImage == null) { boxImage = new Bitmap(BOXIMAGESIZE, BOXIMAGESIZE, System.Drawing.Imaging.PixelFormat.Format32bppPArgb); using (Graphics g = Graphics.FromImage(boxImage)) { g.FillRectangle(new SolidBrush(SystemColors.InactiveBorder), 0, 0, BOXIMAGESIZE, BOXIMAGESIZE); g.DrawRectangle(new Pen(SystemColors.ControlDarkDark), 0, 0, BOXIMAGESIZE-1, BOXIMAGESIZE-1); } } return boxImage; } } ////// Used by Designer action glyphs to render a /// 'mouse hover' state. /// public static Brush HoverBrush { get { return hoverBrush; } } ////// Demand created size used to determine how far the user /// needs to drag the mouse before a drag operation starts. /// public static Size MinDragSize { get { if (minDragSize == Size.Empty) { Size minDrag = SystemInformation.DragSize; Size minDblClick = SystemInformation.DoubleClickSize; minDragSize.Width = Math.Max(minDrag.Width, minDblClick.Width); minDragSize.Height = Math.Max(minDrag.Height, minDblClick.Height); } return minDragSize; } } public static Point LastCursorPoint { get { int lastXY = SafeNativeMethods.GetMessagePos(); return new Point(NativeMethods.Util.SignedLOWORD(lastXY),NativeMethods.Util.SignedHIWORD(lastXY)) ; } } // Recreate the brushes - behaviorservice calls this when the user preferences changes public static void SyncBrushes() { hoverBrush.Dispose(); hoverBrush = new SolidBrush(Color.FromArgb(50, SystemColors.Highlight)); selectionBorderBrush.Dispose(); selectionBorderBrush = new HatchBrush(HatchStyle.Percent50, SystemColors.ControlDarkDark, Color.Transparent); SafeNativeMethods.DeleteObject(new HandleRef(null, grabHandleFillBrushPrimary)); grabHandleFillBrushPrimary = SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.Window)); SafeNativeMethods.DeleteObject(new HandleRef(null, grabHandleFillBrush)); grabHandleFillBrush = SafeNativeMethods.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.ControlText)); SafeNativeMethods.DeleteObject(new HandleRef(null, grabHandlePenPrimary)); grabHandlePenPrimary = SafeNativeMethods.CreatePen(NativeMethods.PS_SOLID, 1, ColorTranslator.ToWin32(SystemColors.ControlText)); SafeNativeMethods.DeleteObject(new HandleRef(null, grabHandlePen)); grabHandlePen = SafeNativeMethods.CreatePen(NativeMethods.PS_SOLID, 1,ColorTranslator.ToWin32(SystemColors.Window)); } ////// Draws a ControlDarkDark border around the given image. /// private static void DrawDragBorder(Graphics g, Size imageSize, int borderSize, Color backColor) { Pen pen = SystemPens.ControlDarkDark; if (backColor != Color.Empty && backColor.GetBrightness() < .5) { pen = SystemPens.ControlLight; } //draw a border w/o the corners connecting g.DrawLine(pen, 1, 0, imageSize.Width -2, 0); g.DrawLine(pen, 1, imageSize.Height -1, imageSize.Width -2, imageSize.Height - 1); g.DrawLine(pen, 0, 1, 0, imageSize.Height-2); g.DrawLine(pen, imageSize.Width -1, 1, imageSize.Width - 1, imageSize.Height - 2); //loop through drawing inner-rects until we get the proper thickness for (int i =1; i < borderSize; i ++) { g.DrawRectangle(pen, i,i, imageSize.Width - (2 + i), imageSize.Height -(2 + i)); } } ////// Used for drawing the borders around controls that are being resized /// public static void DrawResizeBorder(Graphics g, Region resizeBorder, Color backColor) { Brush brush = SystemBrushes.ControlDarkDark; if (backColor != Color.Empty && backColor.GetBrightness() < .5) { brush = SystemBrushes.ControlLight; } g.FillRegion(brush, resizeBorder); } ////// Used for drawing the frame when doing a mouse drag /// public static void DrawFrame(Graphics g, Region resizeBorder, FrameStyle style, Color backColor) { Brush brush; Color color = SystemColors.ControlDarkDark; if (backColor != Color.Empty && backColor.GetBrightness() < .5) { color = SystemColors.ControlLight; } switch (style) { case FrameStyle.Dashed: brush = new HatchBrush(HatchStyle.Percent50, color, Color.Transparent); break; case FrameStyle.Thick: default: brush = new SolidBrush(color); break; } g.FillRegion(brush, resizeBorder); } ////// Used for drawing the grabhandles around sizeable selected controls and components. /// public static void DrawGrabHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph) { IntPtr hDC = graphics.GetHdc(); try { //set our pen and brush based on primary selection IntPtr oldBrush = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, isPrimary ? grabHandleFillBrushPrimary : grabHandleFillBrush)); IntPtr oldPen = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, isPrimary ? grabHandlePenPrimary: grabHandlePen)); //draw our rounded rect grabhandle SafeNativeMethods.RoundRect(new HandleRef(glyph, hDC), bounds.Left, bounds.Top, bounds.Right, bounds.Bottom, 2, 2); //restore old pen and brush SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldBrush)); SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldPen)); } finally { graphics.ReleaseHdcInternal(hDC); } } ////// Used for drawing the no-resize handle for non-resizeable selected controls and components. /// public static void DrawNoResizeHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph) { IntPtr hDC = graphics.GetHdc(); try { //set our pen and brush based on primary selection IntPtr oldBrush = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, isPrimary ? grabHandleFillBrushPrimary : grabHandleFillBrush)); IntPtr oldPen = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, grabHandlePenPrimary)); //draw our rect no-resize handle SafeNativeMethods.Rectangle(new HandleRef(glyph, hDC), bounds.Left, bounds.Top, bounds.Right, bounds.Bottom); //restore old pen and brush SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldBrush)); SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldPen)); } finally { graphics.ReleaseHdcInternal(hDC); } } ////// Used for drawing the lock handle for locked selected controls and components. /// public static void DrawLockedHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph) { IntPtr hDC = graphics.GetHdc(); try { IntPtr oldPen = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, grabHandlePenPrimary)); // Upper rect - upper rect is always filled with the primary brush IntPtr oldBrush = SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, grabHandleFillBrushPrimary)); SafeNativeMethods.RoundRect(new HandleRef(glyph, hDC), bounds.Left+LOCKHANDLEUPPER_OFFSET, bounds.Top, bounds.Left + LOCKHANDLEUPPER_OFFSET + LOCKHANDLESIZE_UPPER, bounds.Top + LOCKHANDLESIZE_UPPER,2,2); // Lower rect - its fillbrush depends on the primary selection SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, isPrimary ? grabHandleFillBrushPrimary : grabHandleFillBrush)); SafeNativeMethods.Rectangle(new HandleRef(glyph, hDC), bounds.Left, bounds.Top+LOCKHANDLELOWER_OFFSET, bounds.Right, bounds.Bottom); //restore old pen and brush SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldBrush)); SafeNativeMethods.SelectObject(new HandleRef(glyph, hDC), new HandleRef(glyph, oldPen)); } finally { graphics.ReleaseHdcInternal(hDC); } } ////// Uses the lockedBorderBrush to draw a 'locked' border on the /// given Graphics at the specified bounds. /// public static void DrawSelectionBorder(Graphics graphics, Rectangle bounds) { graphics.FillRectangle(selectionBorderBrush, bounds); } ////// Used to generate an image that represents the given control. First, this method will call /// the 'GenerateSnapShotWithWM_PRINT' method on the control. If we believe that this /// method did not return us a valid image (caused by some comctl/ax controls not properly /// responding to a wm_print) then we will attempt to do a bitblt of the control instead. /// public static void GenerateSnapShot(Control control, ref Image image, int borderSize, double opacity, Color backColor) { //GenerateSnapShot will return a boolean value indicating if the control //returned an image or not... if (!GenerateSnapShotWithWM_PRINT(control, ref image)) { //here, we failed to get the image on wmprint - so try bitblt GenerateSnapShotWithBitBlt(control, ref image) ; //if we still failed - we'll just fall though, put up a border around an empty area and //call it good enough } //set the opacity if (opacity < 1.0 && opacity > 0.0) { //make this semi-transparent SetImageAlpha((Bitmap)image, opacity); } //draw a drag border around this thing if (borderSize > 0) { using (Graphics g = Graphics.FromImage(image)) { DrawDragBorder(g, image.Size, borderSize, backColor); } } } ////// Retrieves the width and height of a selection border grab handle. /// Designers may need this to properly position their user interfaces. /// public static Size GetAdornmentDimensions(AdornmentType adornmentType) { switch (adornmentType) { case AdornmentType.GrabHandle: return new Size(HANDLESIZE, HANDLESIZE); case AdornmentType.ContainerSelector: case AdornmentType.Maximum: return new Size(CONTAINERGRABHANDLESIZE, CONTAINERGRABHANDLESIZE); } return new Size(0, 0); } public static bool UseSnapLines(IServiceProvider provider) { bool useSnapLines = true; object optionValue = null; DesignerOptionService options = provider.GetService(typeof(DesignerOptionService)) as DesignerOptionService; if (options != null) { PropertyDescriptor snaplinesProp = options.Options.Properties["UseSnapLines"]; if (snaplinesProp != null) { optionValue = snaplinesProp.GetValue(null); } } if (optionValue != null && optionValue is bool) { useSnapLines = (bool)optionValue; } return useSnapLines; } public static object GetOptionValue(IServiceProvider provider, string name) { object optionValue = null; if (provider != null) { DesignerOptionService desOpts = provider.GetService(typeof(DesignerOptionService)) as DesignerOptionService; if (desOpts != null) { PropertyDescriptor prop = desOpts.Options.Properties[name]; if (prop != null) { optionValue = prop.GetValue(null); } } else { IDesignerOptionService optSvc = provider.GetService(typeof(IDesignerOptionService)) as IDesignerOptionService; if (optSvc != null) { optionValue = optSvc.GetOptionValue("WindowsFormsDesigner\\General", name); } } } return optionValue; } ////// Uses BitBlt to geta snapshot of the control /// public static void GenerateSnapShotWithBitBlt(Control control, ref Image image) { //get the DC's and create our image HandleRef hWnd = new HandleRef(control, control.Handle); IntPtr controlDC = UnsafeNativeMethods.GetDC(hWnd); image = new Bitmap(Math.Max(control.Width, MINCONTROLBITMAPSIZE), Math.Max(control.Height, MINCONTROLBITMAPSIZE), System.Drawing.Imaging.PixelFormat.Format32bppPArgb); using (Graphics gDest = Graphics.FromImage(image)) { //VSWhidbey #378593 if (control.BackColor == Color.Transparent) { gDest.Clear(SystemColors.Control); } IntPtr destDC = gDest.GetHdc(); //perform our bitblit operation to push the image into the dest bitmap SafeNativeMethods.BitBlt(destDC, 0, 0, image.Width, image.Height, controlDC, 0, 0, 0xcc0020/*RasterOp.SOURCE*/); //clean up all our handles and what not gDest.ReleaseHdc(destDC); } } ////// Uses WM_PRINT to get a snapshot of the control. This method will return true if the control // properly responded to the wm_print message. /// public static bool GenerateSnapShotWithWM_PRINT(Control control, ref Image image) { IntPtr hWnd = control.Handle; image = new Bitmap(Math.Max(control.Width, MINCONTROLBITMAPSIZE), Math.Max(control.Height, MINCONTROLBITMAPSIZE), System.Drawing.Imaging.PixelFormat.Format32bppPArgb); //VSWhidbey #378593 //Have to do this BEFORE we set the testcolor. if (control.BackColor == Color.Transparent) { using (Graphics g = Graphics.FromImage(image)) { g.Clear(SystemColors.Control); } } //To validate that the control responded to the wm_print message, we pre-populate the //bitmap with a colored center pixel. We assume that the control _did not_ respond to //wm_print if these center pixel is still this value Color testColor = Color.FromArgb(255,252,186,238); ((Bitmap)image).SetPixel(image.Width /2, image.Height /2, testColor); using (Graphics g = Graphics.FromImage(image)) { IntPtr hDc = g.GetHdc(); //send the actual wm_print message NativeMethods.SendMessage(hWnd, NativeMethods.WM_PRINT, hDc, (IntPtr)(NativeMethods.PRF_CHILDREN | NativeMethods.PRF_CLIENT | NativeMethods.PRF_ERASEBKGND | NativeMethods.PRF_NONCLIENT)); g.ReleaseHdc(hDc); } //now check to see if our center pixel was cleared, if not then our wm_print failed if (((Bitmap)image).GetPixel(image.Width /2, image.Height / 2).Equals(testColor)) { //wm_print failed return false; } return true; } ////// Used by the Glyphs and ComponentTray to determine the Top, Left, Right, Bottom and Body /// bound rects related to their original bounds and bordersize. /// public static Rectangle GetBoundsForSelectionType(Rectangle originalBounds, SelectionBorderGlyphType type, int borderSize) { Rectangle bounds = Rectangle.Empty; switch (type) { case SelectionBorderGlyphType.Top: bounds = new Rectangle(originalBounds.Left - borderSize, originalBounds.Top - borderSize, originalBounds.Width + 2*borderSize, borderSize); break; case SelectionBorderGlyphType.Bottom: bounds = new Rectangle(originalBounds.Left - borderSize, originalBounds.Bottom, originalBounds.Width + 2*borderSize, borderSize); break; case SelectionBorderGlyphType.Left: bounds = new Rectangle(originalBounds.Left - borderSize, originalBounds.Top - borderSize, borderSize, originalBounds.Height + 2*borderSize); break; case SelectionBorderGlyphType.Right: bounds = new Rectangle(originalBounds.Right, originalBounds.Top - borderSize, borderSize, originalBounds.Height + 2*borderSize); break; case SelectionBorderGlyphType.Body: bounds = originalBounds; break; } return bounds; } ////// Used by the Glyphs and ComponentTray to determine the Top, Left, Right, Bottom and Body /// bound rects related to their original bounds and bordersize. /// /// Offset - how many pixels between the border glyph and the control /// private static Rectangle GetBoundsForSelectionType(Rectangle originalBounds, SelectionBorderGlyphType type, int bordersize, int offset) { Rectangle bounds = GetBoundsForSelectionType(originalBounds, type, bordersize); if (offset != 0) { switch (type) { case SelectionBorderGlyphType.Top: bounds.Offset(-offset, -offset); bounds.Width += 2*offset; break; case SelectionBorderGlyphType.Bottom: bounds.Offset(-offset, offset); bounds.Width += 2*offset; break; case SelectionBorderGlyphType.Left: bounds.Offset(-offset, -offset); bounds.Height += 2*offset; break; case SelectionBorderGlyphType.Right: bounds.Offset(offset, -offset); bounds.Height += 2*offset; break; case SelectionBorderGlyphType.Body: bounds = originalBounds; break; } } return bounds; } ////// Used by the Glyphs and ComponentTray to determine the Top, Left, Right, Bottom and Body /// bound rects related to their original bounds and bordersize. /// public static Rectangle GetBoundsForSelectionType(Rectangle originalBounds, SelectionBorderGlyphType type) { return GetBoundsForSelectionType(originalBounds, type, DesignerUtils.SELECTIONBORDERSIZE, SELECTIONBORDEROFFSET); } public static Rectangle GetBoundsForNoResizeSelectionType(Rectangle originalBounds, SelectionBorderGlyphType type) { return GetBoundsForSelectionType(originalBounds, type, DesignerUtils.SELECTIONBORDERSIZE, NORESIZEBORDEROFFSET); } ////// Identifes where the text baseline for our control which should be /// based on bounds, padding, font, and textalignment. /// public static int GetTextBaseline(Control ctrl, ContentAlignment alignment) { //determine the actual client area we are working in (w/padding) Rectangle face = ctrl.ClientRectangle; //get the font metrics via gdi int fontAscent = 0; int fontHeight = 0; using (Graphics g = ctrl.CreateGraphics()) { IntPtr dc = g.GetHdc(); IntPtr hFont = ctrl.Font.ToHfont(); IntPtr hFontOld; try { hFontOld = SafeNativeMethods.SelectObject(new HandleRef(ctrl, dc), new HandleRef(ctrl, hFont)); NativeMethods.TEXTMETRIC metrics = new NativeMethods.TEXTMETRIC(); SafeNativeMethods.GetTextMetrics(new HandleRef(ctrl, dc), metrics); //add the font ascent to the baseline fontAscent = metrics.tmAscent + 1; fontHeight = metrics.tmHeight; SafeNativeMethods.SelectObject(new HandleRef(ctrl, dc), new HandleRef(ctrl, hFontOld)); } finally { SafeNativeMethods.DeleteObject(new HandleRef(ctrl.Font, hFont)); g.ReleaseHdc(dc); } } //now add it all up if ((alignment & anyTopAlignment) != 0) { return face.Top + fontAscent; } else if ((alignment & anyMiddleAlignment) != 0) { return face.Top + (face.Height / 2) - (fontHeight/2) + fontAscent; } else { return face.Bottom - fontHeight + fontAscent; } } ////// Called by the ParentControlDesigner when creating a new /// control - this will update the new control's bounds with the /// proper toolbox/snapline information that has been stored /// off // /// isMirrored - Is the ParentControlDesigner mirrored? If so, we need /// to offset for that. This is because all snapline stuff is done /// using a LTR coordinate system /// public static Rectangle GetBoundsFromToolboxSnapDragDropInfo(ToolboxSnapDragDropEventArgs e, Rectangle originalBounds, bool isMirrored) { Rectangle newBounds = originalBounds; //this should always be the case 'cause we don't //create 'e' unless we have an offset if (e.Offset != Point.Empty) { //snap either up or down depending on offset if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Top) != 0) { newBounds.Y += e.Offset.Y;//snap to top - so move up our bounds } else if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Bottom) != 0) { newBounds.Y = originalBounds.Y - originalBounds.Height + e.Offset.Y; } //snap either left or right depending on offset if (!isMirrored) { if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Left) != 0) { newBounds.X += e.Offset.X;//snap to left- } else if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Right) != 0) { newBounds.X = originalBounds.X - originalBounds.Width + e.Offset.X; } } else { // ParentControlDesigner is RTL, that means that the origin is upper-right, not upper-left if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Left) != 0) { // e.Offset.X is negative when we snap to left newBounds.X = originalBounds.X - originalBounds.Width - e.Offset.X; } else if ((e.SnapDirections & ToolboxSnapDragDropEventArgs.SnapDirection.Right) != 0) { // e.Offset.X is positive when we snao to right newBounds.X -= e.Offset.X; } } } return newBounds; } ////// Determine a unique site name for a component, starting from a base name. Return value /// should be passed into the Container.Add() method. If null is returned, this just means /// "let container generate a default name based on component type". /// public static String GetUniqueSiteName(IDesignerHost host, String name) { // Item has no explicit name, so let host generate a type-based name instead if (String.IsNullOrEmpty(name)) { return null; } // Get the name creation service from the designer host INameCreationService nameCreationService = (INameCreationService) host.GetService(typeof(INameCreationService)); if (nameCreationService == null) { return null; } // See if desired name is already in use object existingComponent = host.Container.Components[name]; if (existingComponent == null) { // Name is not in use - but make sure that it contains valid characters before using it! return nameCreationService.IsValidName(name) ? name : null; } else { // Name is in use (and therefore basically valid), so start appending numbers String nameN = name; for (int i = 1; !nameCreationService.IsValidName(nameN); ++i) { nameN = name + i.ToString(CultureInfo.InvariantCulture); } return nameN; } } ////// Applies the given opacity to the image /// private static unsafe void SetImageAlpha(Bitmap b, double opacity) { if (opacity == 1.0) { return; } byte[] alphaValues = new byte[256]; // precompute all the possible alpha values // into an array so we don't do multiplications in the loop // for (int i = 0; i < alphaValues.Length; i++) { alphaValues[i] = (byte)(i * opacity); } // lock the data in ARGB format. // BitmapData data = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); try { // compute the number of pixels that we're modifying. // int pixels = data.Height * data.Width; int* pPixels = (int*)data.Scan0; // have the compiler figure out where to stop for us // by doing the pointer math // byte* maxAddr = (byte*)(pPixels + pixels); // now run through the pixels only modifyng the A byte, // for (byte* addr = (byte*)(pPixels)+3; addr < maxAddr; addr += 4) { // the new value is just an index into our precomputed // value array from above. // *addr = alphaValues[*addr]; } } finally { // now, apply the data back to the bitmap. // b.UnlockBits(data); } } ////// This method removes types that are generics from the input collection /// public static ICollection FilterGenericTypes(ICollection types) { if (types == null || types.Count == 0) return types; //now we get each Type and add it to the destination collection if its not a generic ArrayList final = new ArrayList(types.Count); foreach (Type t in types) { if (!t.ContainsGenericParameters) { final.Add(t); } } return final; } ////// Checks the given container, substituting any nested container with its owning container. /// Ensures that a SplitterPanel in a SplitContainer returns the same container as other form /// components, since SplitContainer sites its two SplitterPanels inside a nested container. /// public static IContainer CheckForNestedContainer(IContainer container) { NestedContainer nestedContainer = container as NestedContainer; if (nestedContainer != null) { return nestedContainer.Owner.Site.Container; } else { return container; } } ////// /// Used to create copies of the objects that we are dragging in a drag operation /// /// public static ICollection CopyDragObjects(ICollection objects, IServiceProvider svcProvider) { if (objects == null || svcProvider == null) { Debug.Fail("Invalid parameter passed to DesignerUtils.CopyObjects."); return null; } Cursor oldCursor = Cursor.Current; try { Cursor.Current = Cursors.WaitCursor; ComponentSerializationService css = svcProvider.GetService(typeof(ComponentSerializationService)) as ComponentSerializationService; IDesignerHost host = svcProvider.GetService(typeof(IDesignerHost)) as IDesignerHost; Debug.Assert(css != null, "No component serialization service -- we cannot copy the objects"); Debug.Assert(host != null, "No host -- we cannot copy the objects"); if (css != null && host != null) { SerializationStore store = null; store = css.CreateStore(); // Get all the objects, meaning we want the children too ICollection copyObjects = GetCopySelection(objects, host); // The serialization service does not (yet) handle serializing collections foreach (IComponent comp in copyObjects) { css.Serialize(store, comp); } store.Close(); copyObjects = css.Deserialize(store); // Now, copyObjects contains a flattened list of all the controls contained // in the original drag objects, that's not what we want to return. // We only want to return the root drag objects, so that the caller gets // an identical copy - identical in terms of objects.Count ArrayList newObjects = new ArrayList(objects.Count); foreach (IComponent comp in copyObjects) { Control c = comp as Control; if (c != null && c.Parent == null) { newObjects.Add(comp); } else if (c == null) { // this happens when we are dragging a toolstripitem // ToolStripItem item = comp as ToolStripItem; if (item != null && item.GetCurrentParent() == null) { newObjects.Add(comp); } } } Debug.Assert(newObjects.Count == objects.Count, "Why is the count of the copied objects not the same?"); return newObjects; } } finally { Cursor.Current = oldCursor; } return null; } private static ICollection GetCopySelection(ICollection objects, IDesignerHost host) { if (objects == null || host == null) { return null; } ArrayList copySelection = new ArrayList(); foreach (IComponent comp in objects) { copySelection.Add(comp); GetAssociatedComponents(comp, host, copySelection); } return copySelection; } internal static void GetAssociatedComponents(IComponent component, IDesignerHost host, ArrayList list) { if (host == null) { return; } ComponentDesigner designer = host.GetDesigner(component) as ComponentDesigner; if (designer == null) { return; } foreach (IComponent childComp in designer.AssociatedComponents) { if (childComp.Site != null) { list.Add(childComp); GetAssociatedComponents(childComp, host, list); } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ItemDragEvent.cs
- JoinCqlBlock.cs
- NullableIntSumAggregationOperator.cs
- ConnectionsZoneAutoFormat.cs
- DataSourceHelper.cs
- WebDescriptionAttribute.cs
- UserMapPath.cs
- SignatureResourceHelper.cs
- TypedTableBase.cs
- ProcessModelInfo.cs
- DocumentViewerConstants.cs
- DaylightTime.cs
- FixedSOMLineCollection.cs
- MimeMapping.cs
- Viewport3DAutomationPeer.cs
- TargetException.cs
- ColorContextHelper.cs
- WsdlBuildProvider.cs
- GridViewItemAutomationPeer.cs
- RequestCacheValidator.cs
- Substitution.cs
- DataServiceHost.cs
- TextBoxRenderer.cs
- InputMethodStateTypeInfo.cs
- IApplicationTrustManager.cs
- LinqMaximalSubtreeNominator.cs
- PropertyGridCommands.cs
- Group.cs
- HttpWrapper.cs
- HttpCapabilitiesEvaluator.cs
- CounterSample.cs
- ReferencedAssembly.cs
- WindowsStartMenu.cs
- SHA256Managed.cs
- XamlSerializationHelper.cs
- MarkupExtensionParser.cs
- FileDialogCustomPlace.cs
- TextEndOfParagraph.cs
- DesignerDataParameter.cs
- BitmapData.cs
- HandleInitializationContext.cs
- ReadWriteObjectLock.cs
- ClientBuildManager.cs
- FormattedText.cs
- DataGridTemplateColumn.cs
- CompilationSection.cs
- ResourcePool.cs
- _FtpDataStream.cs
- TaskForm.cs
- TypeDependencyAttribute.cs
- ConnectionInterfaceCollection.cs
- ForEachDesigner.xaml.cs
- PerformanceCounterPermissionEntry.cs
- Model3D.cs
- DataGridViewAutoSizeColumnsModeEventArgs.cs
- Collection.cs
- WarningException.cs
- BuildProvider.cs
- CollectionViewGroupRoot.cs
- ViewCellSlot.cs
- XdrBuilder.cs
- MetadataCacheItem.cs
- XamlSerializerUtil.cs
- ProviderException.cs
- AlphabetConverter.cs
- ContentElement.cs
- ExportException.cs
- CodeArrayCreateExpression.cs
- MatrixConverter.cs
- NavigationCommands.cs
- Cursors.cs
- TableLayoutPanelCellPosition.cs
- DataSourceControl.cs
- CalendarData.cs
- MemberMaps.cs
- ProtocolsConfigurationHandler.cs
- WsdlHelpGeneratorElement.cs
- FontFaceLayoutInfo.cs
- ProjectionRewriter.cs
- FixedPageAutomationPeer.cs
- TerminatorSinks.cs
- FormsAuthenticationUser.cs
- MouseDevice.cs
- hresults.cs
- ErrorLog.cs
- MouseActionValueSerializer.cs
- ThreadBehavior.cs
- SingleKeyFrameCollection.cs
- Predicate.cs
- XmlEnumAttribute.cs
- ResXResourceWriter.cs
- EntityClassGenerator.cs
- EntityStoreSchemaFilterEntry.cs
- QuaternionKeyFrameCollection.cs
- Dynamic.cs
- FrameSecurityDescriptor.cs
- DetailsViewModeEventArgs.cs
- ComplusEndpointConfigContainer.cs
- DataSet.cs
- BitmapSizeOptions.cs