C# WinForm中在窗口标题栏上加按钮

来源:互联网 发布:淘宝一键发货 编辑:程序博客网 时间:2024/05/17 23:35
【摘   要】Windows   API中的HDC可以通过Graphics.FromHdc()转换为(创建出)System.Drawing.Graphics,然后就可以用.NET   Framework  GDI+提供的绘图功能方便地进行画图了。 

在窗口标题栏上加按钮本来不是什么新鲜事了,我在VC++下早也实现过了(相信很多人也都实现过了)。今天一个朋友问我C#   WinForm下可否实现,我就顺便拿C#写了一个。 

原理是一样的,都是重写窗口过程(WndProc),处理一些非客户区消息(WM_NCxxxx),可以说本来没有什么新意,可是从写这个程序的过程中,我也学到了两个技巧: 

1)、C#中重写窗口过程不用再调用SetWindowLong   API了,直接overide一个WndProc就可以了。 
2)、Windows   API中的HDC可以通过Graphics.FromHdc()转换为(创建出)System.Drawing.Graphics,然后就可以用.NET   Framework   (GID+??)提供的绘图功能方便地进行画图了。终于可以抛开讨厌的GDI   API了(说实在话,在C#中调用Windows   API真的太麻烦了:)). 
代码如下: 

using   System; 
using   System.Drawing; 
using   System.Drawing.Drawing2D; 
using   System.Collections; 
using   System.ComponentModel; 
using   System.Windows.Forms; 
using   System.Data; 
using   System.Runtime.InteropServices; 
using   System.Diagnostics; 
namespace   WindowsApplication2 

///   <summary> 
///   Form1   的摘要说明。
///   </summary> 

public   class   Form1   :   System.Windows.Forms.Form 

///   <summary> 
///   必需的设计器变量。 
///   </summary> 

private   System.ComponentModel.Container   components   =   null; 
public   Form1() 

// 
//   Windows   窗体设计器支持所必需的
// 
InitializeComponent(); 

// 
//   TODO:   在   InitializeComponent   调用后添加任何构造函数代码
// 


///   <summary> 
///   清理所有正在使用的资源。
///   </summary> 

protected   override   void   Dispose(   bool   disposing   ) 

if(   disposing   ) 

if   (components   !=   null) 

components.Dispose(); 


base.Dispose(   disposing   ); 


#region   Windows   窗体设计器生成的代码
///   <summary> 
///   设计器支持所需的方法   -   不要使用代码编辑器修改
///   此方法的内容。
///   </summary> 

private   void   InitializeComponent() 

// 
//   Form1 
// 

this.AutoScaleBaseSize   =   new   System.Drawing.Size(6,   14); 
this.ClientSize   =   new   System.Drawing.Size(292,   266); 
this.Name   =   "Form1 "; 
this.Text   =   "Form1 "; 
this.SizeChanged   +=   new   System.EventHandler(this.Form1_SizeChanged); 


#endregion 

///   <summary> 
///   应用程序的主入口点。
///   </summary> 

[STAThread] 
static   void   Main() 

Application.Run(new   Form1()); 


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


}

转载地址http://blog.163.com/da7_1@126/blog/static/104072678201001310219448/