且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

DLL嵌入网页的一个棘手问题

更新时间:2023-12-06 15:14:04

不需要覆盖WndProc.您确实需要对控件进行双重缓冲,这在.NET中非常简单.您没有说使用什么语言,所以google double buffer和您用来查找示例的语言.
Overriding the WndProc should not be needed. You DO need to double buffer your control, which is done quite soimply in .NET. You don''t say anything about what language you use, so google double buffer and the language you''re using to find examples.


Graus,

非常感谢您的回复.我的情况有点复杂,所以我没有清楚地描述我的问题.

我必须重写WndProc(),因为我必须重新绘制控件,至少它们的边框.我已经尝试过双缓冲.但是我的控件仍然闪烁,此外,组合框的下拉区域变为透明.
现在,我尝试了另一种方法,即使用Windows XP主题更改控件的外观.因为我在richtextbox上采用了该方法,所以它确实有效并且看起来没有闪烁.源代码来自codeproject.所以我尝试自己将其应用到命令按钮上作为测试.但它无法正常工作.使用Windows XP主题有两种方法:一种是添加清单文件,Windows会自动处理控件外观,并且在代码项目中有很多讨论它的文章.另一种方法是手动调用uxtheme.dll中的相关API.我遵循后者,因为我的目标是.dll,清单文件仅适用于.exe.

我在代码中忘记了什么吗?如果您有任何想法,请告诉我.谢谢您的时间.我将在下一篇文章中粘贴我的代码.
Hi, Graus,

thanks a lot for your reply. my situation is a little bit complex, so i didn''t describe my problem clearly.

i had to override WndProc() cause i must redraw the controls, their borders at least. i have tried double buffer. but my controls still flicker and besides, the dropdown area of combobox turns transparent.
now i tried another way that is to use windows xp theme to change the appearance of controls. because i take that method on richtextbox and it does work and looks no flicker. the source code is from codeproject. so i tried to apply it on a commandbutton by myself as a test. but it failed to work. there are two ways to use windows xp theme: one is to add a manifest file, Windows will handle the controls appearance automaticlly and there are many articles discussing it in codeproject; the other way is to call the related API in uxtheme.dll manualy. i follow the latter cause my target is a .dll, manifest file only works with .exe.

did i forget something in my code? if you have any idea, pls tell me. thank you for you time. i will paste my code in the next post.


我的代码在VS2003(c#)中使用uxtheme.dll
my code using uxtheme.dll in VS2003 (c#)
<br />
	using System;<br />
	using System.Collections;<br />
	using System.ComponentModel;<br />
	using System.Drawing;<br />
	using System.Data;<br />
	using System.Windows.Forms;<br />
	using System.Runtime.InteropServices;<br />
<br />
	namespace CustomControls<br />
	{<br />
		public class CustomButton : System.Windows.Forms.Button <br />
		{<br />
			private System.ComponentModel.Container components = null;<br />
<br />
			public CustomButton()<br />
			{<br />
				InitializeComponent();<br />
<br />
			}<br />
<br />
			protected override void Dispose( bool disposing )<br />
			{<br />
				if( disposing )<br />
				{<br />
					if(components != null)<br />
					{<br />
						components.Dispose();<br />
					}<br />
				}<br />
				base.Dispose( disposing );<br />
			}<br />
<br />
			private void InitializeComponent()<br />
			{<br />
				components = new System.ComponentModel.Container();<br />
			}<br />
		<br />
			private const int WM_PAINT =0x000F;<br />
			public const int WM_NCPAINT = 0x85;<br />
			public const int WM_NCCALCSIZE = 0x83;<br />
			public const int WM_THEMECHANGED = 0x031A;<br />
<br />
			private enum BUTTONPARTS:int<br />
			{<br />
				BP_UNKNOWN = 0,<br />
				BP_PUSHBUTTON = 1,<br />
				BP_RADIOBUTTON = 2,<br />
				BP_CHECKBOX = 3,<br />
				BP_GROUPBOX = 4,<br />
				BP_USERBUTTON = 5,<br />
				BP_COMMANDLINK = 6,<br />
				BP_COMMANDLINKGLYPH = 7<br />
			};<br />
<br />
			private enum PUSHBUTTONSTATES:int<br />
			{<br />
				PBS_NORMAL = 1,<br />
				PBS_HOT = 2,<br />
				PBS_PRESSED = 3,<br />
				PBS_DISABLED = 4,<br />
				PBS_DEFAULTED = 5,<br />
				PBS_DEFAULTED_ANIMATING = 6<br />
			};<br />
<br />
			public struct RECT <br />
			{<br />
				public int Left;<br />
				public int Top;<br />
				public int Right;<br />
				public int Bottom;<br />
<br />
				public RECT(int left_, int top_, int right_, int bottom_) <br />
				{<br />
					Left = left_;<br />
					Top = top_;<br />
					Right = right_;<br />
					Bottom = bottom_;<br />
				}<br />
			}<br />
<br />
			[DllImport("uxtheme.dll", ExactSpelling=true)]<br />
			public extern static bool IsThemeActive();<br />
<br />
			[DllImport("user32.dll")]<br />
			public static extern IntPtr GetWindowDC (IntPtr hWnd );<br />
<br />
			[DllImport("user32.dll")]<br />
			public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC );<br />
<br />
			[DllImport("user32.dll")]<br />
			public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);<br />
<br />
			[DllImport("uxtheme.dll", ExactSpelling=true, CharSet=CharSet.Unicode)]<br />
			public static extern IntPtr OpenThemeData(IntPtr hWnd, String classList);<br />
<br />
			[DllImport("uxtheme.dll", ExactSpelling=true)]<br />
			public extern static Int32 DrawThemeBackground(IntPtr hTheme, IntPtr hdc, int iPartId,<br />
				int iStateId, ref RECT pRect, IntPtr pClipRect);<br />
<br />
			[DllImport("uxtheme.dll", ExactSpelling=true)]<br />
			public extern static Int32 CloseThemeData(IntPtr hTheme);<br />
<br />
			protected override void WndProc(ref Message m)<br />
<br />
			{<br />
				switch(m.Msg)<br />
				{<br />
					case WM_NCPAINT:<br />
						WmPaint(ref m);<br />
						break;<br />
					default:<br />
						base.WndProc (ref m);<br />
						break;<br />
				}<br />
			}<br />
<br />
			public void WmPaint(ref Message m) {<br />
				try<br />
				{<br />
					base.WndProc(ref m);<br />
<br />
					if (!IsThemeActive()) {<br />
						return;<br />
					}<br />
<br />
					/////////////////////////////////////////////////////////////////////////////<br />
					// Get the DC of the window frame and paint the border using uxTheme API<br />
					/////////////////////////////////////////////////////////////////////////////<br />
<br />
					// set the part id to TextBox<br />
					int partId = (int)BUTTONPARTS.BP_PUSHBUTTON;<br />
					int stateId = (int)PUSHBUTTONSTATES.PBS_NORMAL;<br />
<br />
					// define the windows frame rectangle of the TextBox<br />
					RECT windowRect;<br />
					GetWindowRect(this.Handle, out windowRect);<br />
<br />
					// get the device context of the window frame<br />
					IntPtr hDC = GetWindowDC(this.Handle);<br />
<br />
					// open theme data<br />
					IntPtr hTheme = OpenThemeData(this.Handle, "Button");<br />
<br />
					// draw background<br />
					DrawThemeBackground(hTheme, hDC, partId, stateId, ref windowRect, IntPtr.Zero);<br />
          <br />
					// close theme data<br />
					CloseThemeData(hTheme);<br />
<br />
					// release dc<br />
					ReleaseDC(this.Handle, hDC);<br />
<br />
					// we have processed the message so set the result to zero<br />
					m.Result = IntPtr.Zero;<br />
<br />
				}<br />
				catch(Exception ex)<br />
				{<br />
					MessageBox.Show(ex.Message);<br />
				}<br />
			}<br />
		}<br />
	}<br />