Changeset 2242 for trunk/eraser
- Timestamp:
- 8/8/2010 7:02:56 AM (3 years ago)
- Location:
- trunk/eraser/Eraser.Util
- Files:
-
- 2 edited
-
NativeMethods/UxTheme.cs (modified) (2 diffs)
-
Theming.cs (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/eraser/Eraser.Util/NativeMethods/UxTheme.cs
r1802 r2242 52 52 string pszSubIdList); 53 53 54 [DllImport("UxTheme.dll", CharSet = CharSet.Unicode)] 55 public static extern SafeThemeHandle OpenThemeData(IntPtr hwnd, string pszClassList); 56 57 [DllImport("UxTheme.dll", CharSet = CharSet.Unicode)] 58 public static extern IntPtr CloseThemeData(IntPtr hwndTeme); 59 60 [DllImport("UxTheme.dll", CharSet = CharSet.Unicode)] 61 public static extern IntPtr DrawThemeParentBackground(IntPtr hwnd, 62 IntPtr hdc, ref Rectangle prc); 63 64 [DllImport("UxTheme.dll", CharSet = CharSet.Unicode)] 65 [return: MarshalAs(UnmanagedType.Bool)] 66 public static extern bool IsThemeBackgroundPartiallyTransparent( 67 SafeThemeHandle hTheme, int iPartId, int iStateId); 68 69 [DllImport("UxTheme.dll", CharSet = CharSet.Unicode)] 70 public static extern IntPtr DrawThemeBackground( 71 SafeThemeHandle hTheme, IntPtr hdc, int iPartId, int iStateId, 72 ref Rectangle pRect, ref Rectangle pClipRect); 73 74 [DllImport("UxTheme.dll", CharSet = CharSet.Unicode)] 75 public extern static int DrawThemeText(SafeThemeHandle hTheme, 76 IntPtr hDC, int iPartId, int iStateId, 77 [MarshalAs(UnmanagedType.LPWStr)] string pszText, int iCharCount, 78 TextFormatFlags dwTextFlag, int dwTextFlags2, ref Rectangle pRect); 79 80 [DllImport("UxTheme.dll", CharSet = CharSet.Unicode)] 81 public static extern IntPtr GetThemeMargins(SafeThemeHandle hTheme, 82 IntPtr hdc, int iPartId, int iStateId, int iPropId, ref Rectangle prc, 83 ref Rectangle pMargins); 84 85 [DllImport("UxTheme.dll", CharSet = CharSet.Unicode)] 86 public static extern IntPtr GetThemeMargins(SafeThemeHandle hTheme, 87 IntPtr hdc, int iPartId, int iStateId, int iPropId, IntPtr prc, 88 ref Rectangle pMargins); 89 90 [DllImport("UxTheme.dll", CharSet = CharSet.Unicode)] 91 public static extern IntPtr GetThemePartSize(SafeThemeHandle hTheme, 92 IntPtr hdc, int iPartId, int iStateId, ref Rectangle prc, 93 THEMESIZE eSize, ref Size psz); 94 95 [DllImport("UxTheme.dll", CharSet = CharSet.Unicode)] 96 public static extern IntPtr GetThemePartSize(SafeThemeHandle hTheme, 97 IntPtr hdc, int iPartId, int iStateId, IntPtr prc, 98 THEMESIZE eSize, ref Size psz); 99 100 public enum MENUPARTS 54 public enum MENUPARTS : int 101 55 { 102 56 MENU_MENUITEM_TMSCHEMA = 1, … … 151 105 } 152 106 153 public enum TMT_MARGINS154 {155 TMT_SIZINGMARGINS = 3601,156 TMT_CONTENTMARGINS,157 TMT_CAPTIONMARGINS158 }159 160 public enum THEMESIZE161 {162 TS_MIN,163 TS_TRUE,164 TS_DRAW165 }166 167 107 public const int WM_THEMECHANGED = 0x031A; 168 108 public const int WM_DWMCOMPOSITIONCHANGED = 0x031E; -
trunk/eraser/Eraser.Util/Theming.cs
r1802 r2242 27 27 using System.Drawing; 28 28 using System.IO; 29 using System.Windows.Forms.VisualStyles; 29 30 using Microsoft.Win32.SafeHandles; 30 31 … … 252 253 public class UXThemeMenuRenderer : ToolStripRenderer 253 254 { 254 ~UXThemeMenuRenderer()255 {256 if (hTheme != null)257 hTheme.Close();258 }259 260 255 protected override void Initialize(ToolStrip toolStrip) 261 256 { 262 257 base.Initialize(toolStrip); 263 hTheme = NativeMethods.OpenThemeData(toolStrip.Handle, "MENU"); 258 ToolStrip = toolStrip; 259 Renderer = new VisualStyleRenderer(VisualStyleElement.Button.PushButton.Default); 260 261 //Hook the item added event to inflate the height of every item by 2px. 262 ToolStrip.ItemAdded += new ToolStripItemEventHandler(OnToolStripItemAdded); 263 foreach (ToolStripItem item in toolStrip.Items) 264 item.Height += 2; 265 } 266 267 void OnToolStripItemAdded(object sender, ToolStripItemEventArgs e) 268 { 269 //Inflate the height of every item by 2px. 270 e.Item.Height += 2; 264 271 } 265 272 266 273 protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) 267 274 { 268 IntPtr hDC = e.Graphics.GetHdc();269 275 Rectangle rect = e.AffectedBounds; 270 271 if (NativeMethods.IsThemeBackgroundPartiallyTransparent(hTheme,272 (int)NativeMethods.MENUPARTS.MENU_POPUPITEM, 0))273 {274 NativeMethods.DrawThemeBackground(hTheme, hDC,275 (int)NativeMethods.MENUPARTS.MENU_POPUPBACKGROUND, 0, ref rect, ref rect);276 }277 276 278 NativeMethods.DrawThemeBackground(hTheme, hDC, (int) 279 NativeMethods.MENUPARTS.MENU_POPUPBORDERS, 0, ref rect, ref rect); 280 281 e.Graphics.ReleaseHdc(); 282 rect.Inflate(-Margin, -Margin); 283 using (SolidBrush brush = new SolidBrush(e.BackColor)) 284 e.Graphics.FillRectangle(brush, rect); 277 Renderer.SetParameters(MenuPopupBackground); 278 if (Renderer.IsBackgroundPartiallyTransparent()) 279 Renderer.DrawParentBackground(e.Graphics, e.ToolStrip.ClientRectangle, e.ToolStrip); 280 281 Renderer.DrawBackground(e.Graphics, e.ToolStrip.ClientRectangle, e.AffectedBounds); 282 } 283 284 protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e) 285 { 286 //Strange, borders are drawn after the content. So, clip to only the borders 287 //so that the internals will be retained. 288 Region oldClip = e.Graphics.Clip; 289 Rectangle insideRect = e.ToolStrip.ClientRectangle; 290 291 //The correct (Windows) size is actually 3px, but that will cut into our items. 292 insideRect.Inflate(-2, -2); 293 e.Graphics.ExcludeClip(insideRect); 294 295 Renderer.SetParameters(MenuPopupBorders); 296 Renderer.DrawBackground(e.Graphics, e.ToolStrip.ClientRectangle, e.AffectedBounds); 297 298 //Restore the old clipping. 299 e.Graphics.IntersectClip(insideRect); 285 300 } 286 301 287 302 protected override void OnRenderImageMargin(ToolStripRenderEventArgs e) 288 303 { 289 IntPtr hDC = e.Graphics.GetHdc();304 //Compute the rectangle to draw the gutter. 290 305 Rectangle rect = e.AffectedBounds; 291 rect.Inflate(-2, -2); 292 rect.Offset(1, 1); 293 rect.Size = new Size(GutterWidth, rect.Height + 1); 294 295 NativeMethods.DrawThemeBackground(hTheme, hDC, 296 (int)NativeMethods.MENUPARTS.MENU_POPUPGUTTER, 0, ref rect, ref rect); 297 298 e.Graphics.ReleaseHdc(); 306 rect.X = 0; 307 Size gutterImageSize = Renderer.GetPartSize(e.Graphics, ThemeSizeType.True); 308 rect.Width = GutterWidth - gutterImageSize.Width + 1; 309 310 Renderer.SetParameters(MenuPopupGutter); 311 Renderer.DrawBackground(e.Graphics, rect); 299 312 } 300 313 301 314 protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) 302 315 { 303 Rectangle rect = Rectangle.Truncate(e.Graphics.VisibleClipBounds); 304 rect.Inflate(-1, 0); 305 rect.Offset(2, 0); 306 IntPtr hDC = e.Graphics.GetHdc(); 307 308 int itemState = (int)(e.Item.Selected ? 309 (e.Item.Enabled ? NativeMethods.POPUPITEMSTATES.MPI_HOT : 310 NativeMethods.POPUPITEMSTATES.MPI_DISABLEDHOT) : 311 (e.Item.Enabled ? NativeMethods.POPUPITEMSTATES.MPI_NORMAL : 312 NativeMethods.POPUPITEMSTATES.MPI_DISABLED)); 313 NativeMethods.DrawThemeBackground(hTheme, hDC, 314 (int)NativeMethods.MENUPARTS.MENU_POPUPITEM, itemState, ref rect, ref rect); 315 316 e.Graphics.ReleaseHdc(); 316 //Compute the rectangle of the background. 317 Rectangle rect = e.Item.ContentRectangle; 318 rect.Inflate(0, 1); 319 320 Renderer.SetParameters(GetItemElement(e.Item)); 321 Renderer.DrawBackground(e.Graphics, rect, rect); 317 322 } 318 323 319 324 protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e) 320 325 { 321 IntPtr hDC = e.Graphics.GetHdc();322 Re ctangle rect = new Rectangle(GutterWidth, 0, e.Item.Width, e.Item.Height);323 rect.Inflate(4, 0);324 325 NativeMethods.DrawThemeBackground(hTheme, hDC,326 (int)NativeMethods.MENUPARTS.MENU_POPUPSEPARATOR, 0, ref rect, ref rect);327 328 e.Graphics.ReleaseHdc();326 //Get the size of the gutter image 327 Renderer.SetParameters(MenuPopupGutter); 328 Size gutterImageSize = Renderer.GetPartSize(e.Graphics, ThemeSizeType.True); 329 330 Renderer.SetParameters(MenuSeparator); 331 Renderer.DrawBackground(e.Graphics, new Rectangle( 332 GutterWidth - gutterImageSize.Width, 0, e.ToolStrip.DisplayRectangle.Width, 333 e.Item.Height)); 329 334 } 330 335 … … 337 342 } 338 343 339 //Create the rectangle for the checkmark: 340 // 1. Offset by 2px 341 // 2. Inflate by (4, 3) 342 // 3. Increase width by 1px to fall on even x-coordinate (correction for odd pixel offset) 343 Rectangle imgRect = new Rectangle(e.ImageRectangle.Left + 2 - 4, 344 e.ImageRectangle.Top - 3, 345 e.ImageRectangle.Width + 4 * 2 + 1, e.ImageRectangle.Height + 3 * 2); 346 347 IntPtr hDC = e.Graphics.GetHdc(); 344 //Get the menu item. 348 345 ToolStripMenuItem item = (ToolStripMenuItem)e.Item; 349 346 350 int bgState = (int)(e.Item.Enabled ? NativeMethods.POPUPCHECKBACKGROUNDSTATES.MCB_NORMAL : 351 NativeMethods.POPUPCHECKBACKGROUNDSTATES.MCB_DISABLED); 352 NativeMethods.DrawThemeBackground(hTheme, hDC, 353 (int)NativeMethods.MENUPARTS.MENU_POPUPCHECKBACKGROUND, bgState, 354 ref imgRect, ref imgRect); 355 356 int checkState = (int)(item.Checked ? 357 (item.Enabled ? NativeMethods.POPUPCHECKSTATES.MC_CHECKMARKNORMAL : 358 NativeMethods.POPUPCHECKSTATES.MC_CHECKMARKDISABLED) : 0); 359 NativeMethods.DrawThemeBackground(hTheme, hDC, 360 (int)NativeMethods.MENUPARTS.MENU_POPUPCHECK, checkState, 361 ref imgRect, ref imgRect); 362 363 e.Graphics.ReleaseHdc(); 347 //Compute the rectangle for the background. 348 Rectangle rect = e.Item.ContentRectangle; 349 rect.Y = 0; 350 rect.Size = new Size(item.Height, item.Height); 351 352 //Draw the background 353 Renderer.SetParameters(GetCheckBackgroundElement(item)); 354 Renderer.DrawBackground(e.Graphics, rect); 355 356 //Compute the size of the checkmark 357 rect.Inflate(-3, -3); 358 359 //Draw the checkmark 360 Renderer.SetParameters(GetCheckElement(item)); 361 Renderer.DrawBackground(e.Graphics, rect); 364 362 } 365 363 366 364 protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e) 367 365 { 368 int itemState = (int)(e.Item.Selected ? 369 (e.Item.Enabled ? NativeMethods.POPUPITEMSTATES.MPI_HOT : 370 NativeMethods.POPUPITEMSTATES.MPI_DISABLEDHOT) : 371 (e.Item.Enabled ? NativeMethods.POPUPITEMSTATES.MPI_NORMAL : 372 NativeMethods.POPUPITEMSTATES.MPI_DISABLED)); 373 374 Rectangle newRect = e.TextRectangle; 375 newRect.Offset(2, 0); 376 e.TextRectangle = newRect; 377 Rectangle rect = new Rectangle(e.TextRectangle.Left, 0, 378 e.Item.Width - e.TextRectangle.Left, e.Item.Height); 379 IntPtr hFont = e.TextFont.ToHfont(); 380 IntPtr hDC = e.Graphics.GetHdc(); 381 NativeMethods.SelectObject(hDC, hFont); 382 383 NativeMethods.DrawThemeText(hTheme, hDC, 384 (int)NativeMethods.MENUPARTS.MENU_POPUPITEM, itemState, e.Text, 385 -1, e.TextFormat | TextFormatFlags.WordEllipsis | TextFormatFlags.SingleLine, 386 0, ref rect); 387 388 e.Graphics.ReleaseHdc(); 366 Renderer.SetParameters(GetItemElement(e.Item)); 367 if (e.Item.Owner.IsDropDown || e.Item.Owner is MenuStrip) 368 e.TextColor = Renderer.GetColor(ColorProperty.TextColor); 369 370 base.OnRenderItemText(e); 389 371 } 390 372 391 373 protected override void OnRenderArrow(ToolStripArrowRenderEventArgs e) 392 374 { 393 int itemState = (int)(e.Item.Enabled ? NativeMethods.POPUPSUBMENUSTATES.MSM_NORMAL : 394 NativeMethods.POPUPSUBMENUSTATES.MSM_DISABLED); 395 396 //Strangely, UxTheme won't draw any arrow once the starting coordinate 397 //is beyond 5px. So draw the arrow on a backing image then blit 398 //to the actual one. 399 using (Bitmap backBmp = new Bitmap(e.ArrowRectangle.Width, e.ArrowRectangle.Height)) 400 { 401 using (Graphics backGfx = Graphics.FromImage(backBmp)) 402 { 403 IntPtr hDC = backGfx.GetHdc(); 404 405 Rectangle backRect = new Rectangle(new Point(0, 0), backBmp.Size); 406 NativeMethods.DrawThemeBackground(hTheme, hDC, 407 (int)NativeMethods.MENUPARTS.MENU_POPUPSUBMENU, itemState, 408 ref backRect, ref backRect); 409 backGfx.ReleaseHdc(); 410 } 411 412 e.Graphics.DrawImageUnscaled(backBmp, e.ArrowRectangle); 413 } 414 } 415 375 Renderer.SetParameters(GetSubmenuElement(e.Item)); 376 Renderer.DrawBackground(e.Graphics, e.ArrowRectangle); 377 } 378 379 private VisualStyleElement GetItemElement(ToolStripItem item) 380 { 381 return item.Selected ? 382 (item.Enabled ? 383 MenuPopupItemHot : 384 MenuPopupItemDisabledHot) : 385 (item.Enabled ? 386 MenuPopupItem : 387 MenuPopupItemDisabled); 388 } 389 390 private VisualStyleElement GetCheckBackgroundElement(ToolStripItem item) 391 { 392 return item.Enabled ? MenuPopupCheckBackground : MenuPopupCheckBackgroundDisabled; 393 } 394 395 private VisualStyleElement GetCheckElement(ToolStripMenuItem item) 396 { 397 return item.Checked ? 398 (item.Enabled ? MenuPopupCheck : MenuPopupCheckDisabled) : 399 MenuPopupBitmap; 400 } 401 402 private VisualStyleElement GetSubmenuElement(ToolStripItem item) 403 { 404 return item.Enabled ? MenuSubmenu : MenuSubmenuDisabled; 405 } 406 407 /// <summary> 408 /// Gets the width of the gutter for images. 409 /// </summary> 416 410 private int GutterWidth 417 411 { 418 412 get 419 413 { 420 Rectangle margins = Rectangle.Empty; 421 Size checkSize = Size.Empty; 422 423 NativeMethods.GetThemeMargins(hTheme, IntPtr.Zero, 424 (int)NativeMethods.MENUPARTS.MENU_POPUPCHECK, 0, 425 (int)NativeMethods.TMT_MARGINS.TMT_SIZINGMARGINS, 426 IntPtr.Zero, ref margins); 427 NativeMethods.GetThemePartSize(hTheme, IntPtr.Zero, 428 (int)NativeMethods.MENUPARTS.MENU_POPUPCHECK, 0, 429 IntPtr.Zero, NativeMethods.THEMESIZE.TS_TRUE, ref checkSize); 430 return 2 * checkSize.Width + margins.Left + margins.Width - 1; 431 } 432 } 433 434 private int Margin 435 { 436 get 437 { 438 Size borderSize = Size.Empty; 439 NativeMethods.GetThemePartSize(hTheme, IntPtr.Zero, 440 (int)NativeMethods.MENUPARTS.MENU_POPUPBORDERS, 0, 441 IntPtr.Zero, NativeMethods.THEMESIZE.TS_TRUE, ref borderSize); 442 return borderSize.Width; 443 } 444 } 445 446 private SafeThemeHandle hTheme; 447 } 448 449 internal class SafeThemeHandle : SafeHandleZeroOrMinusOneIsInvalid 450 { 451 public SafeThemeHandle() 452 : base(true) 453 { 454 } 455 456 protected override bool ReleaseHandle() 457 { 458 NativeMethods.CloseThemeData(handle); 459 handle = IntPtr.Zero; 460 return true; 461 } 414 return ToolStrip.DisplayRectangle.Left; 415 } 416 } 417 418 private ToolStrip ToolStrip; 419 private VisualStyleRenderer Renderer; 420 421 private static readonly string MenuClass = "MENU"; 422 423 private static VisualStyleElement MenuPopupBackground = 424 VisualStyleElement.CreateElement( 425 MenuClass, (int)NativeMethods.MENUPARTS.MENU_POPUPBACKGROUND, 0); 426 private static VisualStyleElement MenuPopupBorders = 427 VisualStyleElement.CreateElement( 428 MenuClass, (int)NativeMethods.MENUPARTS.MENU_POPUPBORDERS, 0); 429 430 private static VisualStyleElement MenuPopupItem = 431 VisualStyleElement.CreateElement(MenuClass, 432 (int)NativeMethods.MENUPARTS.MENU_POPUPITEM, 433 (int)NativeMethods.POPUPITEMSTATES.MPI_NORMAL); 434 private static VisualStyleElement MenuPopupItemHot = 435 VisualStyleElement.CreateElement(MenuClass, 436 (int)NativeMethods.MENUPARTS.MENU_POPUPITEM, 437 (int)NativeMethods.POPUPITEMSTATES.MPI_HOT); 438 private static VisualStyleElement MenuPopupItemDisabled = 439 VisualStyleElement.CreateElement(MenuClass, 440 (int)NativeMethods.MENUPARTS.MENU_POPUPITEM, 441 (int)NativeMethods.POPUPITEMSTATES.MPI_DISABLED); 442 private static VisualStyleElement MenuPopupItemDisabledHot = 443 VisualStyleElement.CreateElement(MenuClass, 444 (int)NativeMethods.MENUPARTS.MENU_POPUPITEM, 445 (int)NativeMethods.POPUPITEMSTATES.MPI_DISABLEDHOT); 446 447 private VisualStyleElement MenuPopupCheckBackground = 448 VisualStyleElement.CreateElement(MenuClass, 449 (int)NativeMethods.MENUPARTS.MENU_POPUPCHECKBACKGROUND, 450 (int)NativeMethods.POPUPCHECKBACKGROUNDSTATES.MCB_NORMAL); 451 private VisualStyleElement MenuPopupCheckBackgroundDisabled = 452 VisualStyleElement.CreateElement(MenuClass, 453 (int)NativeMethods.MENUPARTS.MENU_POPUPCHECKBACKGROUND, 454 (int)NativeMethods.POPUPCHECKBACKGROUNDSTATES.MCB_NORMAL); 455 456 private VisualStyleElement MenuPopupBitmap = 457 VisualStyleElement.CreateElement(MenuClass, 458 (int)NativeMethods.MENUPARTS.MENU_POPUPCHECK, 0); 459 private VisualStyleElement MenuPopupCheck = 460 VisualStyleElement.CreateElement(MenuClass, 461 (int)NativeMethods.MENUPARTS.MENU_POPUPCHECK, 462 (int)NativeMethods.POPUPCHECKSTATES.MC_CHECKMARKNORMAL); 463 private VisualStyleElement MenuPopupCheckDisabled = 464 VisualStyleElement.CreateElement(MenuClass, 465 (int)NativeMethods.MENUPARTS.MENU_POPUPCHECK, 466 (int)NativeMethods.POPUPCHECKSTATES.MC_CHECKMARKDISABLED); 467 468 469 private static VisualStyleElement MenuPopupGutter = 470 VisualStyleElement.CreateElement(MenuClass, 471 (int)NativeMethods.MENUPARTS.MENU_POPUPGUTTER, 0); 472 473 private VisualStyleElement MenuSeparator = 474 VisualStyleElement.CreateElement(MenuClass, 475 (int)NativeMethods.MENUPARTS.MENU_POPUPSEPARATOR, 0); 476 477 private VisualStyleElement MenuSubmenu = 478 VisualStyleElement.CreateElement(MenuClass, 479 (int)NativeMethods.MENUPARTS.MENU_POPUPSUBMENU, 480 (int)NativeMethods.POPUPSUBMENUSTATES.MSM_NORMAL); 481 private VisualStyleElement MenuSubmenuDisabled = 482 VisualStyleElement.CreateElement(MenuClass, 483 (int)NativeMethods.MENUPARTS.MENU_POPUPSUBMENU, 484 (int)NativeMethods.POPUPSUBMENUSTATES.MSM_DISABLED); 462 485 } 463 486 }
Note: See TracChangeset
for help on using the changeset viewer.
