Click here to Skip to main content
15,902,635 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
i have a dll of .net1.1 for GUI embedded into a web page using ExtJS. cause i want to make .net native control more pretty, i tried to use windows API (override the method WndProc()). but when i test, i found the controls that i changed flicker when mouse pointer moving over ExtJS elements such as button, tree nodes, and so on.

i managed to solve this problem for several days and no results. if any advice, pls tell me. thanks a lot!
Posted

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.
 
Share this answer
 
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.
 
Share this answer
 
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 />
 
Share this answer
 
There is no double buffering in this code. Without it, you will get a flicker.
 
Share this answer
 
my code override WndProc and paint the control all by myself:

<br />
using System;<br />
using System.Windows.Forms;<br />
using System.Drawing;<br />
using System.Drawing.Drawing2D;<br />
using System.Runtime.InteropServices;<br />
<br />
namespace CustomControls<br />
{<br />
	[ToolboxBitmap(typeof(System.Windows.Forms.ComboBox))]<br />
	public class CustomComboBox: ComboBox<br />
	{	<br />
		#region ComboInfoHelper<br />
		internal class ComboInfoHelper<br />
		{<br />
			[DllImport("user32")] <br />
			private static extern bool GetComboBoxInfo(IntPtr hwndCombo, ref ComboBoxInfo info);<br />
<br />
			#region RECT struct<br />
			[StructLayout(LayoutKind.Sequential)]<br />
				private struct RECT <br />
			{<br />
				public int Left;<br />
				public int Top;<br />
				public int Right;<br />
				public int Bottom;<br />
			}<br />
			#endregion<br />
<br />
			#region ComboBoxInfo Struct<br />
			[StructLayout(LayoutKind.Sequential)]<br />
				private struct ComboBoxInfo <br />
			{<br />
				public int cbSize;<br />
				public RECT rcItem;<br />
				public RECT rcButton;<br />
				public IntPtr stateButton;<br />
				public IntPtr hwndCombo;<br />
				public IntPtr hwndEdit;<br />
				public IntPtr hwndList;<br />
			}<br />
			#endregion<br />
<br />
			public static int GetComboDropDownWidth()<br />
			{<br />
				ComboBox cb = new ComboBox();<br />
				int width = GetComboDropDownWidth(cb.Handle);<br />
				cb.Dispose();<br />
				return width;<br />
			}<br />
			public static int GetComboDropDownWidth(IntPtr handle)<br />
			{<br />
				ComboBoxInfo cbi = new ComboBoxInfo();<br />
				cbi.cbSize = Marshal.SizeOf(cbi);<br />
				GetComboBoxInfo(handle, ref cbi);<br />
				int width = cbi.rcButton.Right - cbi.rcButton.Left;<br />
				return width;<br />
			}<br />
		}<br />
		#endregion<br />
<br />
		public const int WM_ERASEBKGND = 0x14;<br />
		public const int WM_PAINT = 0xF;<br />
		public const int WM_NC_PAINT = 0x85;<br />
		public const int WM_PRINTCLIENT = 0x318;<br />
		private static int DropDownButtonWidth = 17;<br />
<br />
		[DllImport("user32.dll", EntryPoint="SendMessageA")]<br />
		public static extern int SendMessage (IntPtr hwnd, int wMsg, IntPtr wParam, object lParam);<br />
<br />
		[DllImport("user32")]<br />
		public static extern IntPtr GetWindowDC (IntPtr hWnd );<br />
<br />
		[DllImport("user32")]<br />
		public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC );<br />
<br />
		static CustomComboBox()<br />
		{<br />
			DropDownButtonWidth = ComboInfoHelper.GetComboDropDownWidth() + 2;<br />
		}<br />
<br />
		public CustomComboBox()<br />
			: base()<br />
		{<br />
			//this.SetStyle(ControlStyles.DoubleBuffer, true); //looks ok and flicker<br />
			this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true); //transparent and flicker<br />
		}<br />
<br />
		protected override void OnSelectedValueChanged(EventArgs e)<br />
		{<br />
			base.OnSelectedValueChanged (e);<br />
			this.Invalidate();<br />
		}<br />
<br />
		protected override void WndProc(ref Message m)<br />
		{<br />
			if (this.DropDownStyle == ComboBoxStyle.Simple)<br />
			{<br />
				base.WndProc(ref m);<br />
				return;<br />
			}<br />
<br />
			IntPtr hDC = IntPtr.Zero;<br />
			Graphics gdc = null;<br />
			switch (m.Msg)<br />
			{<br />
				case WM_NC_PAINT:	<br />
					hDC = GetWindowDC(this.Handle);<br />
					gdc = Graphics.FromHdc(hDC);<br />
					SendMessage(this.Handle, WM_ERASEBKGND, hDC, 0);<br />
					SendPrintClientMsg();	// send to draw client area<br />
					PaintFlatControlBorder(this, gdc);<br />
					m.Result = (IntPtr) 1;	// indicate msg has been processed			<br />
					ReleaseDC(m.HWnd, hDC);<br />
					gdc.Dispose();	<br />
<br />
					break;<br />
				case WM_PAINT:	<br />
					base.WndProc(ref m);<br />
					// flatten the border area again<br />
					hDC = GetWindowDC(this.Handle);<br />
					gdc = Graphics.FromHdc(hDC);<br />
					Pen p = new Pen((this.Enabled? BackColor:SystemColors.Control), 2);	<br />
					gdc.DrawRectangle(p, new Rectangle(2, 2, this.Width-3, this.Height-3));<br />
					PaintFlatDropDown(this, gdc);<br />
					PaintFlatControlBorder(this, gdc);<br />
					ReleaseDC(m.HWnd, hDC);<br />
					gdc.Dispose();	<br />
<br />
					break;<br />
				default:<br />
					base.WndProc(ref m);<br />
					break;<br />
			}<br />
		}<br />
		private void SendPrintClientMsg()<br />
		{<br />
			// We send this message for the control to redraw the client area<br />
			Graphics gClient = this.CreateGraphics();<br />
			IntPtr ptrClientDC = gClient.GetHdc();<br />
			SendMessage(this.Handle, WM_PRINTCLIENT, ptrClientDC, 0);<br />
			gClient.ReleaseHdc(ptrClientDC);<br />
			gClient.Dispose();<br />
		}<br />
<br />
		private void PaintFlatControlBorder(Control ctrl, Graphics g)<br />
		{<br />
			Rectangle rect = new Rectangle(0, 0, ctrl.Width, ctrl.Height);<br />
			if (ctrl.Focused == false || ctrl.Enabled == false )<br />
				ControlPaint.DrawBorder(g, rect, SystemColors.ControlDark, ButtonBorderStyle.Solid);<br />
			else<br />
				ControlPaint.DrawBorder(g, rect, Color.Black, ButtonBorderStyle.Solid);<br />
			Color borderColor = Color.LightBlue;<br />
			ControlPaint.DrawBorder(g, rect, borderColor, ButtonBorderStyle.Solid);<br />
		}<br />
		public static void PaintFlatDropDown(Control ctrl, Graphics g)<br />
		{<br />
			Rectangle rect = new Rectangle(ctrl.Width-DropDownButtonWidth, 0, DropDownButtonWidth, ctrl.Height);<br />
			ControlPaint.DrawComboButton(g, rect, ButtonState.Flat);<br />
		}<br />
<br />
		protected override void OnLostFocus(System.EventArgs e)<br />
		{<br />
			base.OnLostFocus(e);<br />
			this.Invalidate();<br />
		}<br />
<br />
		protected override void OnGotFocus(System.EventArgs e)<br />
		{<br />
			base.OnGotFocus(e);<br />
			this.Invalidate();<br />
		}		<br />
		protected override void OnResize(EventArgs e)<br />
		{<br />
			base.OnResize (e);<br />
			this.Invalidate();<br />
		}<br />
<br />
	}<br />
}<br />
<br />
 
Share this answer
 
the former code using uxtheme.dll doesn't work. the latter does work but flicker.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900