在做拖动小窗口程序时,遇到一个问题,怎么样对标题栏进行绘制,弄了半天才弄出来。和VC中原理差不多,但在.net下需要将API中的HDC通过Graphics.FromHdc()转换为System.Drawing.Graphics
程序运行结果如下:
代码如下:
/// <summary>
/// 对窗口的标题栏进行重绘和设置
/// </summary>
/// <param name="hwnd"></param>
/// <returns></returns>
[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(3,4,194,18);
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
{
//处理OnPaint事件
IntPtr hDC = GetWindowDC(m.HWnd);
//把DC转换为.NET的Graphics就可以很方便地使用Framework提供的绘图功能了
Graphics gs = Graphics.FromHdc(hDC);
gs.FillRectangle(new LinearGradientBrush(m_rect, Color.Green, Color.Green, 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
{
//处理MouseDown事件
Point mousePoint = new Point((int)m.LParam);
mousePoint.Offset(-this.Left, -this.Top);
if (m_rect.Contains(mousePoint))
{
MessageBox.Show("这是一个对标题栏进行重绘的例子!");
}
break;
}
case 0x00A0://WM_NCMOUSEMOVE
{
//处理MouseMove事件
Point mousePoint = new Point((int)m.LParam);
mousePoint.Offset(-this.Left, -this.Top);
if (m_rect.Contains(mousePoint))
{
Cursor.Current = Cursors.SizeAll;
}
break;
}
}
}
主要事件参照表:
winuser.h中,定义如下:
#define WM_NCMOUSEMOVE 0x00A0
#define WM_NCLBUTTONDOWN 0x00A1
#define WM_NCLBUTTONUP 0x00A2
#define WM_NCLBUTTONDBLCLK 0x00A3
#define WM_NCRBUTTONDOWN 0x00A4
#define WM_NCRBUTTONUP 0x00A5
#define WM_NCRBUTTONDBLCLK 0x00A6
#define WM_NCMBUTTONDOWN 0x00A7
#define WM_NCMBUTTONUP 0x00A8
#define WM_NCMBUTTONDBLCLK 0x00A9
/// <summary>
/// 对窗口的标题栏进行重绘和设置
/// </summary>
/// <param name="hwnd"></param>
/// <returns></returns>
[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(3,4,194,18);
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
{
//处理OnPaint事件
IntPtr hDC = GetWindowDC(m.HWnd);
//把DC转换为.NET的Graphics就可以很方便地使用Framework提供的绘图功能了
Graphics gs = Graphics.FromHdc(hDC);
gs.FillRectangle(new LinearGradientBrush(m_rect, Color.Green, Color.Green, 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
{
//处理MouseDown事件
Point mousePoint = new Point((int)m.LParam);
mousePoint.Offset(-this.Left, -this.Top);
if (m_rect.Contains(mousePoint))
{
MessageBox.Show("这是一个对标题栏进行重绘的例子!");
}
break;
}
case 0x00A0://WM_NCMOUSEMOVE
{
//处理MouseMove事件
Point mousePoint = new Point((int)m.LParam);
mousePoint.Offset(-this.Left, -this.Top);
if (m_rect.Contains(mousePoint))
{
Cursor.Current = Cursors.SizeAll;
}
break;
}
}
}
主要事件参照表:
winuser.h中,定义如下:
#define WM_NCMOUSEMOVE 0x00A0
#define WM_NCLBUTTONDOWN 0x00A1
#define WM_NCLBUTTONUP 0x00A2
#define WM_NCLBUTTONDBLCLK 0x00A3
#define WM_NCRBUTTONDOWN 0x00A4
#define WM_NCRBUTTONUP 0x00A5
#define WM_NCRBUTTONDBLCLK 0x00A6
#define WM_NCMBUTTONDOWN 0x00A7
#define WM_NCMBUTTONUP 0x00A8
#define WM_NCMBUTTONDBLCLK 0x00A9
完毕。^_^