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

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

【摘   要】Windows   API中的HDC可以通过Graphics.FromHdc()转换为(创建出)System.Drawing.Graphics,然后就可以用.NET   Framework   (GID+??)提供的绘图功能方便地进行画图了。

在窗口标题栏上加按钮本来不是什么新鲜事了,我在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;

}

}

}
posted @ 2008-03-11 09:43  zhh  阅读(1266)  评论(0编辑  收藏  举报