近日想重绘一下C# Winform窗体标题栏,以前用去掉边框的办法重绘过标题栏,那种方法虽然实现的效果较好,但终究不是一个完美的办法,我想用WndProc截取系统消息来重绘一下,但运行时发现窗体原来的按钮总会时不时的出现并遮掩了我重绘的按钮,我写的代码如下: [DllImport("User32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("User32.dll")]
private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("Kernel32.dll")]
private static extern int GetLastError();
protected override void WndProc(ref System.Windows.Forms.Message m)
{
const int WM_NCCREATE = 0x0081;
const int WM_PAINT = 0x000F;
const int WM_SIZE = 0x0005;
const int WM_CHILDACTIVATE = 0x0022;
if (m.Msg == WM_NCCREATE || m.Msg == WM_PAINT || m.Msg == WM_SIZE || m.Msg == WM_CHILDACTIVATE)
{
this.Invalidate();
IntPtr hDC = GetWindowDC(m.HWnd);
Graphics gs = Graphics.FromHdc(hDC);
TextureBrush brush = new TextureBrush(topbg,new Rectangle(0,0,1,30));
gs.FillRectangle(brush, 0, 0, this.Width, 30);
TextureBrush brushs = new TextureBrush(topCloseImg, new Rectangle(0, 0, 10, 11));
gs.FillRectangle(brushs, this.Width-20, 0, 10, 11);
gs.Dispose();
ReleaseDC(m.HWnd, hDC);//释放GDI资源 }
base.WndProc(ref m);
}
程序运行时的效果:请求高手来给出个解决方案,并讲一个窗体重绘的合理方法
private static extern IntPtr GetWindowDC(IntPtr hwnd);
[DllImport("User32.dll")]
private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
[DllImport("Kernel32.dll")]
private static extern int GetLastError();
protected override void WndProc(ref System.Windows.Forms.Message m)
{
const int WM_NCCREATE = 0x0081;
const int WM_PAINT = 0x000F;
const int WM_SIZE = 0x0005;
const int WM_CHILDACTIVATE = 0x0022;
if (m.Msg == WM_NCCREATE || m.Msg == WM_PAINT || m.Msg == WM_SIZE || m.Msg == WM_CHILDACTIVATE)
{
this.Invalidate();
IntPtr hDC = GetWindowDC(m.HWnd);
Graphics gs = Graphics.FromHdc(hDC);
TextureBrush brush = new TextureBrush(topbg,new Rectangle(0,0,1,30));
gs.FillRectangle(brush, 0, 0, this.Width, 30);
TextureBrush brushs = new TextureBrush(topCloseImg, new Rectangle(0, 0, 10, 11));
gs.FillRectangle(brushs, this.Width-20, 0, 10, 11);
gs.Dispose();
ReleaseDC(m.HWnd, hDC);//释放GDI资源 }
base.WndProc(ref m);
}
程序运行时的效果:请求高手来给出个解决方案,并讲一个窗体重绘的合理方法
解决方案 »
- C#枚举运算问题急急急!!!!!!
- 关于手写wcf的问题
- 要是执行了ListBox.Items.Add("String")该方法,有否相关的事件触发的?是哪些事件呢?我在事件里找不到相关的事件。
- ListViewItem的一个简单问题
- 请问有办法可以获取POST提交的参数吗?
- 【被基础忽悠】c#中类的创建及引用之引用地址问题
- SNMP,MIB库怎么转换成C#代码?
- c# winform 导入结束后,提示导入成功。 这个代码怎么写啊?
- 关于asp.net几个问题(1.键盘事件2.用回车控制输入焦点3.combobox)
- 求助1
- 如何在C#中绘制长方体
- winforms 如何获得listbox中每项的ValueMember值 (包括没被选中的项)
wParam
Handle to the update region of the window. The update region is clipped to the window frame. When wParam is 1, the entire window frame needs to be updated.
lParam
This parameter is not used.
Return Values
An application returns zero if it processes this message. Res
The DefWindowProc function paints the window frame. An application can intercept the WM_NCPAINT message and paint its own custom window frame. The clipping region for a window is always rectangular, even if the shape of the frame is altered. The wParam value can be passed to GetDCEx as in the following example.case WM_NCPAINT:
{
HDC hdc;
hdc = GetDCEx(hwnd, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN);
// Paint into this DC
ReleaseDC(hwnd, hdc);
}
剩下的就是重绘制标题栏
类似的地方还有很多,你的重绘应该放到默认的绘制之后,以覆盖掉原来的绘制。WM_NCCALCSIZE是让你调整非客户区尺寸的,里面的参数虽然说是表明的客户区的大小,但是你修改这个大小也间接修改了非客户区的大小,如果你想标题栏变粗一些,就要处理这个消息。最后补充一句,自绘标题栏一定要在非xp风格,即xp及以上的系统要在windows经典风格下测试,这样会看出许多问题。
像.NET这种应用程序太慢就会把系统绘制的图放出来,
因为WS_SYSMENU这个样子导致系统对标题按钮这些的绘制,你找台慢一点的电脑来试,
我想QQ窗体也会在绘制的瞬间先把系统绘制的效果呈现出来
for example :
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCACTIVATE:
base.WndProc(ref m); // here is the default process
//your nc paint code goes here
break;
.......
default :
base.WndProc(ref m);
break;
}
}