C# 绘制窗体客户非客户区要用WM_PAINT和WM_NCPAINT

窗体分为两部分:客户区(Client area)和非客户区(Non-Client area) 
WM_PAINT消息、OnPaint()方法、GetDC()API函数都是处理窗体客户区绘制的 
  
而标题栏处于非客户区中,所以WM_PAINT消息、OnPaint()方法、GetDC()API函数都用不上 
  
GetWindowDC()是获得整个窗体的画布句柄(Device Context翻译为:设备清单,我习惯称为画布句柄),包括非客户区 
  
GDI的绘制都离不开DC,因为操作系统必须知道你要在什么地方绘制图形 
  
当其他窗体遮挡或者移开,系统都会重新绘制窗体。这时就会发出WM_PAINT和WM_NCPAINT消息通知窗体重绘界面。 
  
收到WM_NCPAINT消息(非客户区绘制消息)说明非客户区正需要重新绘制 
  
重载WndProc()方法(窗体消息处理过程),处理WM_NCPAINT等消息即可.... 
  
“基本的步骤” 就是:截获WM_NCPAINT消息、得到窗体完整画布句柄、在完整画布上绘制图形。 
    WM_NCPAINT WM_NCCALCSIZE WM_NCACTIVATE WM_NCHITTEST
建议楼主搜索关键词:“C# WM_NCPAINT WndProc Graphics”得到更多的参考资料 

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

[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(); 

//标题栏按钮的矩形区域。 

Rectangle   m_rect   =   new   Rectangle(205,   6,   20,   20); 

protected   override   void   WndProc(ref   Message   m) 

{ 

base.WndProc(ref   m); 

switch(m.Msg) 

{ 

case   0x86://WM_NCACTIVATE 

goto   case   0x85; 

case   0x85://WM_NCPAINT 

{ 

IntPtr   hDC   =   GetWindowDC(m.HWnd); 

//把DC转换为.NET的Graphics就可以很方便地使用Framework提供的绘图功能了 

Graphics   gs   =   Graphics.FromHdc(hDC); 

gs.FillRectangle(new   LinearGradientBrush(m_rect,   Color.Pink,   Color.Purple,   LinearGradientMode.BackwardDiagonal),   m_rect); 

StringFormat   strFmt   =   new   StringFormat(); 

strFmt.Alignment   =   StringAlignment.Center; 

strFmt.LineAlignment   =   StringAlignment.Center; 

gs.DrawString( "√ ",   this.Font,   Brushes.BlanchedAlmond,   m_rect,   strFmt); 

gs.Dispose(); 

//释放GDI资源 

ReleaseDC(m.HWnd,   hDC); 

break; 

} 

case   0xA1://WM_NCLBUTTONDOWN 

{ 

Point   mousePoint   =   new   Point((int)m.LParam); 

mousePoint.Offset(-this.Left,   -this.Top); 

if(m_rect.Contains(mousePoint)) 

{ 

MessageBox.Show( "hello "); 

} 

break; 

} 

} 

} 

//在窗口大小改变时及时更新按钮的区域。 

private   void   Form1_SizeChanged(object   sender,   System.EventArgs   e) 

{ 

m_rect.X   =   this.Bounds.Width   -   95; 

m_rect.Y   =   6; 

m_rect.Width   =   m_rect.Height   =   20; 

} 

} 

}

  

C# 绘制窗体客户非客户区要用WM_PAINT和WM_NCPAINT,布布扣,bubuko.com

时间: 2024-12-28 14:24:26

C# 绘制窗体客户非客户区要用WM_PAINT和WM_NCPAINT的相关文章

窗体皮肤实现 - 重绘窗体非客户区(三)

窗体边框基本的绘制和控制完成,在第二篇中主要遗留的问题. 标题区域图标和按钮没绘制 缩放时客户区显示有问题 解决完下面的问题,皮肤处理基本完整.大致的效果GIF GIF中TShape的颜色表现有些问题,实际是正常的. 绘制标题区域内容 获取标题有效区域 绘制窗体图标 绘制按钮 绘制标题 标题区域主要考虑窗体是否在最大化状态,最大化后实际的标题绘制区域会有变化.可以通过 IsZoomed 或 GetWindowLong(Handle, GWL_STYLE) and WS_MAXIMIZE = WS

窗体皮肤实现 - 重绘窗体非客户区(一)

现在皮肤控件也很多,但每次装一堆控件,使用又繁琐.稍微研究一下内部机制,还是比较简单的. 主要会使用到下面几个消息 1 const 2 WM_NCUAHDRAWCAPTION = $00AE; 3 WM_NCUAHDRAWFRAME = $00AF; 4 5 // 绘制非客户区消息 6 procedure WMNCPaint(var message: TWMNCPaint); message WM_NCPAINT; 7 // 在激活程序时需要相应的消息 8 procedure WMNCActiv

窗口非客户区的绘制

1.根据需要,要改变nc区的大小. 响应WM_NCCALCSIZE可改变nc区的大小.关键在于lParam,msdn上说当wParam为True时, lParam为LPNCCALCSIZE_PARAMS的指定,当wParam为False时为LPRECT,做了些实验发现 只有第一次时wParam为False,LPNCCALCSIZE_PARAMS的语义相当复杂,不过我们只用 看第一个RECT就成.它表是窗口客户区的大小.当lParam为LPRECT时,也同样.只用改变 客户区的大小,相应的就改变了

EVT_NC_PAINT 窗口非客户区的绘制

说明 NC就是non client意思,非客户区主要包括标题栏,状态栏,工具栏和边框等区域,目前wxwidgets只是提供了EVT_NC_PAINT 唯一的一个非客户区的事件,在MFC中,还有提供WM_NCLBUTTONDOWN WM_NCLBUTTONUP WM_NCMOUSEMOVE等事件操作,如果需要关联这些事件,就必须要过滤该事件,或者在源码中实现该类事件 目前需要拖动边框的时候,客户区域不变,只是边框变大,等到边框拖动到合适的地方,鼠标弹起,客户区域重绘

Windows的三种坐标系:屏幕坐标系,非客户区坐标系,客户区坐标系

1. 屏幕坐标系:以屏幕的左上角为原点,如图所示GetWindowRect() 函数获得的 RECT 就是以屏幕坐标系算的. 2. 非客户区坐标系(窗口坐标系)包括标题栏的部分.GetWindowDC 返回的设备环境就是基于此坐标系,一般只在 WM_NCPAINT 消息中使用. 3. 客户区坐标系不包括标题栏,坐标的原点在标题栏下的客户区的左上角.BeginPaint 函数返回的设备环境是基于客户区坐标系的,只在 WM_PAINT 消息中使用,与 EndPaint 函数成对使用.GetDC 函数

浅谈C#中的模式窗体和非模式窗体

ShowDialog();// 模式窗体 Show(); // 非模式窗体差别:1.返回值不同,DialogResult/void2.模式窗体会使程序中断,直到关闭模式窗口3.打开模式窗体后不能切换到应用程序的其他窗体4.子窗体和模式窗体互斥.

成长,就是反复在自己的非舒适区磨练时再多坚持一下

记得上一次这么坚持,是在2013年11月份研一参加校运会跟大一大二的学弟比赛5000米的时候-- 那次也是很难受很难受,圈数少数了一圈,为了保持第一的位置,在倒数第二圈花了大部分力气冲到终点,结果被告知还有一圈--脱水加体力不支--本来都打算放弃了,喝了口水,很艰难地边跑边走地过了大半圈,剩下100多米,感觉体力恢复了一点点,就告诉自己,既然已经坚持了这么久,而且也还有点点体力,难得还有机会站在学校的运动赛场上,不如最后再尽力拼一把吧,于是咬着牙使出了我自己都觉得不可思议的力量,5000米的最后

实验16-14 请在testdb中:查找每个客户(包括没有订单的客户)的客户

testdb是产品销售数据库,请在testdb中:查找每个客户(包括没有订单的客户)的客户编号.名称.订单日期.订货金额,其中订单日期格式为yyyy-mm-dd,按客户编号排序,同一客户再按订单金额降序排序输出. select customer.cust_id,cust_name,CONVERT(varchar(10),order_date,121)as order_date,tot_amt from customer left outer join sales on (customer.cus

窗体皮肤实现 - 重绘窗体非客户区(二)

第一个实现了基本处理.窗体边框的宽度有些肥大,需要进行瘦身. 实现:     1.改变外框线宽度 (WM_NCCALCSIZE)     2.改变外框样式 (WM_WINDOWPOSCHANGING) 通过 WM_NCCALCSIZE 消息可以实现目的. procedure WMNCCalcSize(var message: TWMNCCalcSize); message WM_NCCALCSIZE; procedure TTest.WMNCCalcSize(var message: TWMNC