11 Replies - 6685 Views - Last Post: 06 January 2010 - 06:15 AM Rate Topic: -----

#1 Amrykid  Icon User is offline

  • 4+1=Moo
  • member icon

Reputation: 146
  • View blog
  • Posts: 1,567
  • Joined: 16-December 08

dwmapi - Getting the glass like Paint.NET's

Posted 31 December 2009 - 03:02 PM

Hello everyone! Recently i've been trying to get the glass on my form to go around menubar on the top like Paint.NETs and FireIRC.
I know how to extend the glass using the api. My problem is how do i get my menubar to be in front of it. (See screenshot below) Below is a picture of fireirc.
Posted Image
Is This A Good Question/Topic? 0
  • +

Replies To: dwmapi - Getting the glass like Paint.NET's

#2 X@MPP  Icon User is offline

  • 僕わ馬鹿ですね?
  • member icon

Reputation: 32
  • View blog
  • Posts: 1,010
  • Joined: 20-February 09

Re: dwmapi - Getting the glass like Paint.NET's

Posted 31 December 2009 - 03:24 PM

This might Help its got a lot to it but i think its got what you need
NOTE: i think some or most of it is in C++ but i think you can manage
if i find something in C# ill post it
http://weblogs.asp.n...ow-manager.aspx
EDIT Found an MSDN Article Hope it helps
http://msdn.microsof...e/cc163435.aspx
EDIT2 I was digging in MSDN
and found this

Quote

Most GDI functions produce incorrect alpha values in the destination surface, and therefore are not suitable to draw on glass. So if you want to use controls, you need to make sure they don't use GDI calls other than drawing bitmaps (bitmaps are OK to use with GDI, as long as they're 32-bit with a proper alpha channel). 32-bit icons and image lists also work.

GDIPlus generates proper alpha, but lacks support for high-quality ClearType text on glass.

WPF has both proper alpha support and high-quality text.

To draw text properly, you need to use the DrawThemeTextEx() function with DTT_COMPOSITED. It only works if the HDC passed contains a top-down 32-bit DIB section, that you can easily get by calling BeginBufferedPaint() with BPBF_COMPOSITED (or BPBF_TOPDOWNDIB).

There's a sample in the Windows SDK that shows how to do this, soon to be published to MSDN.



So you have two ways to use controls on top of glass:

* either use custom draw or owner draw to make sure you replace the GDI calls such as drawing text, solid backgrounds or focus rectangles. This approach allows you to use per-pixel antialiasing from inside the control (to get rounded corners for example), since you're drawing proper alpha values.
* or subclass the control, intercept WM_PAINT and redirect the control to paint into a DIB section by sending WM_PRINTCLIENT (don't forget to call BeginPaint()/EndPaint()), then make this DIB opaque (for example with BufferedPaintMakeOpaque()) before blitting it to the screen. This approach doesn't allow you to use per-pixel antialiasing, since you're drawing opaquely.

See uxtheme.h in the Windows Vista SDK.


to an answer for this question

Quote

Using Vista RC2, I've been digging into Aero Glass and the DwmExtendFrameIntoClientArea function. That much has worked nicely and I've got a glass area at the bottom of the form. Now I'd like to add buttons to it.

The problem is that the button is drawn with an opaque white border and transparent text. I've tried owner-drawing it using a variety of DrawThemeBackground/DrawThemeText (etc) functions, but no change.

Am I attempting the impossible, or is there a correct way to draw the button that I've missed?

Thanks!



Rob

link http://social.msdn.m...2-1ad21a7a4dbf/

This post has been edited by X@MPP: 31 December 2009 - 03:37 PM

Was This Post Helpful? 0
  • +
  • -

#3 Amrykid  Icon User is offline

  • 4+1=Moo
  • member icon

Reputation: 146
  • View blog
  • Posts: 1,567
  • Joined: 16-December 08

Re: dwmapi - Getting the glass like Paint.NET's

Posted 31 December 2009 - 03:38 PM

View PostX@MPP, on 31 Dec, 2009 - 03:24 PM, said:

This might Help its got a lot to it but i think its got what you need
NOTE: i think some or most of it is in C++ but i think you can manage
if i find something in C# ill post it
http://weblogs.asp.n...ow-manager.aspx
EDIT Found an MSDN Article Hope it helps
http://msdn.microsof...e/cc163435.aspx

Thats some good info but it still doesn't tell me how im suppose to get my menubar to go around the glass and be attached to the rest of my form.
Was This Post Helpful? 0
  • +
  • -

#4 Amrykid  Icon User is offline

  • 4+1=Moo
  • member icon

Reputation: 146
  • View blog
  • Posts: 1,567
  • Joined: 16-December 08

Re: dwmapi - Getting the glass like Paint.NET's

Posted 31 December 2009 - 03:57 PM

Bump! Anyone know how to do this?
Was This Post Helpful? 0
  • +
  • -

#5 crepitus  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 84
  • View blog
  • Posts: 383
  • Joined: 08-September 09

Re: dwmapi - Getting the glass like Paint.NET's

Posted 31 December 2009 - 07:52 PM

To attach a Toolstrip to a Panel, or whatever lies beneath, just set the top Margin of the thing below to 0.

You can use Reflector to poke around inside PDN. It's a humbling experience.

Some if it is obfuscated, only because he kept getting morons ripping his software off by changing all the "Paint.Net" strings over to "Super Wow Paint 3000", or whatever, and selling it.

If you poke around, check out PaintDotNet.Dialogs.AppWorkspace, and PaintDotNet.Core.PdnBaseForm.

The base form has glass related stuff. I didn't know that some cultures don't get glass. It does some more checks to see if it can switch on glass. It uses a padding instance variable to decide where the extension of the non-client area into the client area will be. When it paints the background it fills rectangles on these areas with Color.Transparent. These areas will be glassy. It also hooks up a message filter to check for clicks in the glassy areas, and it will alter the message to say it's a non-client area. See daniel moth: http://www.danielmot...ss-in-c_17.html

The PdnToolbar class has a PaintBackground method that checks if composition is enabled and then paints it with Color.Transparent. It also uses a custom ToolStripProfessionalRenderer to get all those nice edges, curves etc in the right places. PdnToolbar inherits Control, and has 3 stacked custom ToolStrips on it. I got lost in the code and felt dizzy at this point.

It looks like a lot of work to get it right.
Was This Post Helpful? 0
  • +
  • -

#6 Amrykid  Icon User is offline

  • 4+1=Moo
  • member icon

Reputation: 146
  • View blog
  • Posts: 1,567
  • Joined: 16-December 08

Re: dwmapi - Getting the glass like Paint.NET's

Posted 01 January 2010 - 07:43 AM

View Postcrepitus, on 31 Dec, 2009 - 07:52 PM, said:

To attach a Toolstrip to a Panel, or whatever lies beneath, just set the top Margin of the thing below to 0.

You can use Reflector to poke around inside PDN. It's a humbling experience.

Some if it is obfuscated, only because he kept getting morons ripping his software off by changing all the "Paint.Net" strings over to "Super Wow Paint 3000", or whatever, and selling it.

If you poke around, check out PaintDotNet.Dialogs.AppWorkspace, and PaintDotNet.Core.PdnBaseForm.

The base form has glass related stuff. I didn't know that some cultures don't get glass. It does some more checks to see if it can switch on glass. It uses a padding instance variable to decide where the extension of the non-client area into the client area will be. When it paints the background it fills rectangles on these areas with Color.Transparent. These areas will be glassy. It also hooks up a message filter to check for clicks in the glassy areas, and it will alter the message to say it's a non-client area. See daniel moth: http://www.danielmot...ss-in-c_17.html

The PdnToolbar class has a PaintBackground method that checks if composition is enabled and then paints it with Color.Transparent. It also uses a custom ToolStripProfessionalRenderer to get all those nice edges, curves etc in the right places. PdnToolbar inherits Control, and has 3 stacked custom ToolStrips on it. I got lost in the code and felt dizzy at this point.

It looks like a lot of work to get it right.

Thanks for the reply. Your research has got me very close. But i still don't understand how i can get my toolstrip onto the glass without that transparent/black text issue.
Was This Post Helpful? 0
  • +
  • -

#7 Ändrew  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 25
  • View blog
  • Posts: 311
  • Joined: 21-April 08

Re: dwmapi - Getting the glass like Paint.NET's

Posted 01 January 2010 - 06:15 PM

On that big artical Aero Glass Create Special Effects With The Desktop Window Manager I read some thing about black being 0x000000 and thats transparent black mabey you could change your colours to some thing like 0x010101 not sure what color that it though but give it a try :D

This post has been edited by Ändrew: 01 January 2010 - 06:17 PM

Was This Post Helpful? 0
  • +
  • -

#8 Amrykid  Icon User is offline

  • 4+1=Moo
  • member icon

Reputation: 146
  • View blog
  • Posts: 1,567
  • Joined: 16-December 08

Re: dwmapi - Getting the glass like Paint.NET's

Posted 02 January 2010 - 09:52 AM

View PostÄndrew, on 1 Jan, 2010 - 06:15 PM, said:

On that big artical Aero Glass Create Special Effects With The Desktop Window Manager I read some thing about black being 0x000000 and thats transparent black mabey you could change your colours to some thing like 0x010101 not sure what color that it though but give it a try :D

Thanks, I'll give that a shot and post be what happens when I get home.
Was This Post Helpful? 0
  • +
  • -

#9 crepitus  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 84
  • View blog
  • Posts: 383
  • Joined: 08-September 09

Re: dwmapi - Getting the glass like Paint.NET's

Posted 02 January 2010 - 11:27 AM

Ah, I had another look. It's hard to find your way around code in reflector, plus I've been ill and wasn't paying attention properly.

It cheats...

At the top of the PdnToolBar is a MenuStrip. It's rendered using a custom renderer. Inside the override that paints the item text it is basically creating a bitmap, clearing the backcolor to the backcolor for that area, and using a TextRenderer to draw the black text. It then draws the bitmap to the surface and doesn't call the base class.

My test app has:

	class TestToolStripRenderer : ToolStripProfessionalRenderer
	{

		public bool IsGlassDesired { get; set; }

		public TestToolStripRenderer()
		{
		}

		protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
		{
			if (IsGlassDesired)
			{
				using (Bitmap bm = new Bitmap(e.TextRectangle.Width, e.TextRectangle.Height))
				{
					using (Graphics g = Graphics.FromImage(bm))
					{
						g.Clear(e.ToolStrip.BackColor);
						TextRenderer.DrawText(g, e.Text, e.TextFont, new Rectangle(Point.Empty, bm.Size), e.ToolStrip.ForeColor, e.ToolStrip.BackColor, e.TextFormat);
					}
					CompositingMode temp = e.Graphics.CompositingMode;
					e.Graphics.CompositingMode = CompositingMode.SourceCopy;
					e.Graphics.DrawImageUnscaled(bm, e.TextRectangle.Location);				 
					e.Graphics.CompositingMode = temp;
					return;
				}
			}			
			base.OnRenderItemText(e);
		}

	}



So, to get the effect he's compromised, the only row of the control that is sitting on glass is the top one, which has simple text items.
Was This Post Helpful? 0
  • +
  • -

#10 Amrykid  Icon User is offline

  • 4+1=Moo
  • member icon

Reputation: 146
  • View blog
  • Posts: 1,567
  • Joined: 16-December 08

Re: dwmapi - Getting the glass like Paint.NET's

Posted 03 January 2010 - 09:09 AM

View Postcrepitus, on 2 Jan, 2010 - 11:27 AM, said:

Ah, I had another look. It's hard to find your way around code in reflector, plus I've been ill and wasn't paying attention properly.

It cheats...

At the top of the PdnToolBar is a MenuStrip. It's rendered using a custom renderer. Inside the override that paints the item text it is basically creating a bitmap, clearing the backcolor to the backcolor for that area, and using a TextRenderer to draw the black text. It then draws the bitmap to the surface and doesn't call the base class.

My test app has:

	class TestToolStripRenderer : ToolStripProfessionalRenderer
	{

		public bool IsGlassDesired { get; set; }

		public TestToolStripRenderer()
		{
		}

		protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
		{
			if (IsGlassDesired)
			{
				using (Bitmap bm = new Bitmap(e.TextRectangle.Width, e.TextRectangle.Height))
				{
					using (Graphics g = Graphics.FromImage(bm))
					{
						g.Clear(e.ToolStrip.BackColor);
						TextRenderer.DrawText(g, e.Text, e.TextFont, new Rectangle(Point.Empty, bm.Size), e.ToolStrip.ForeColor, e.ToolStrip.BackColor, e.TextFormat);
					}
					CompositingMode temp = e.Graphics.CompositingMode;
					e.Graphics.CompositingMode = CompositingMode.SourceCopy;
					e.Graphics.DrawImageUnscaled(bm, e.TextRectangle.Location);				 
					e.Graphics.CompositingMode = temp;
					return;
				}
			}			
			base.OnRenderItemText(e);
		}

	}



So, to get the effect he's compromised, the only row of the control that is sitting on glass is the top one, which has simple text items.

Well...i had to modifiy it a bit but i got it working somewhat. Now i gotta get the MenuItems to render too.
[attachment=15690:attachment]
my code is
public class GlassToolStripRenderer : ToolStripProfessionalRenderer
	{

		public bool IsGlassDesired { get; set; }

		public GlassToolStripRenderer()
		{
		}

		protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
		{
			if (IsGlassDesired)
			{
				using (Bitmap bm = new Bitmap(e.TextRectangle.Width, e.TextRectangle.Height))
				{
					using (Graphics g = Graphics.FromImage(bm))
					{
						g.Clear(Color.White);
						TextRenderer.DrawText(g, e.Text, e.TextFont, new Rectangle(Point.Empty, bm.Size), Color.Black, Color.White, e.TextFormat);
					}
					CompositingMode temp = e.Graphics.CompositingMode;
					e.Graphics.CompositingMode = CompositingMode.SourceCopy;
					e.Graphics.DrawImageUnscaled(bm, e.TextRectangle.Location);
					e.Graphics.CompositingMode = temp;
					return;
				}
			}
			base.OnRenderItemText(e);
		}

	}

Was This Post Helpful? 0
  • +
  • -

#11 Amrykid  Icon User is offline

  • 4+1=Moo
  • member icon

Reputation: 146
  • View blog
  • Posts: 1,567
  • Joined: 16-December 08

Re: dwmapi - Getting the glass like Paint.NET's

Posted 04 January 2010 - 10:08 AM

Bump! I still need help getting the dropdown items to render!
Was This Post Helpful? 0
  • +
  • -

#12 crepitus  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 84
  • View blog
  • Posts: 383
  • Joined: 08-September 09

Re: dwmapi - Getting the glass like Paint.NET's

Posted 06 January 2010 - 06:15 AM

You can check e.Item.Isondropdown, and just let the base render it if it is a dropdown item as it won't be on glass. However, then you'll get the rendering that the ToolStropProfessionalRenderer does, rather than some custom rendering like Paint.Net.

To get the highest items to show properly (the ones on glass) you need to also override the methods that draw the item background and toolstrip background. You need to check for e.Item.Pressed and e.Item.Selected so that you can give feedback for when the mouse is moving over an item or when you have dropped the list down.

If you have buttons, or comboboxes, or images, or checkboxes on glass then you'll need to override more, you might need to anyway - I only tested with simple menus.

There's also the problem of getting the round corners, you can stick the menustrip in a panel, and round the corners of the panel, drawing the class colour outside the border, and the toolstrip back color inside the border. I tried this and it worked. Paint.Net uses this technique, but it has a complex ToolBar - which has many toolstrips.

You also need to consider users who use high contrast menus for accessibility and detect when these are to be used so that you can drop back from the fancy UI.

And you'll need to detect when the user disables glass, so that you can fall back to a default menu.

Reflector helps a huge amount, look at Paint.Net and the .Net Renderer classes to see what they do. The simplest example would use nothing but plain text menu items, would override ToolStripProfessionalRenderer or ToolStripSystemRenderer, and it would just have to override OnRenderMenuItemText, OnRenderMenuItemBackGround, OnRenderToolStripBackground. Maybe OnRenderToolStripBorder too.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1