Author: Yuan Xiaohui
Home: http://www.farproc.com
BLOGhttp: // blog.csdn.net/uoyevoli/
Adding a button to the title bar of the window is nothing new. I have already implemented it in VC ++ (I believe many people have also implemented it ). Today, a friend asked me if C # WinForm can be implemented. I wrote one by the way with C.
The principle is the same. They all rewrite the Window Process (WndProc) and process some non-customer messages (WM_NCxxxx). It can be said that there was no new idea, but in the process of writing this program, I also learned two skills:
1) in C #, you do not need to call the SetWindowLong API to rewrite the window. You can overide A WndProc directly.
2) In Windows API, HDC can be converted to (created) System. Drawing. Graphics through Graphics. FromHdc (), and then. NET Framework (GID +?) can be used ??) The drawing function is provided for easy drawing. Finally, we can discard the nasty gdi api (to be honest, Calling Windows API in C # is really too troublesome :)).
The Code is as follows: 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>
/// Summary of Form1.
/// </Summary>
Public class Form1: System. Windows. Forms. Form
{
/// <Summary>
/// Required designer variables.
/// </Summary>
Private System. ComponentModel. Container components = null;
Public Form1 ()
{
//
// Required for Windows Form Designer support
//
InitializeComponent ();
//
// TODO: add Any constructor code after InitializeComponent calls
//
}
/// <Summary>
/// Clear all resources in use.
/// </Summary>
Protected override void Dispose (bool disposing)
{
If (disposing)
{
If (components! = Null)
{
Components. Dispose ();
}
}
Base. Dispose (disposing );
}
# Region code generated by Windows Form Designer
/// <Summary>
/// The designer supports the required methods-do not use the code editor to modify
/// Content of this method.
/// </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>
/// Main entry point of the application.
/// </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 ();
// The rectangular area of the title bar button.
Rectangle m_rect = new Rectangle (205, 4, 16, 16 );
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 );
// Convert DC to. NET Graphics to easily use the drawing function provided by the 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 ();
// Release the GDI resource
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;
}
}
}
// Update the button area when the window size changes.
Private void Form1_SizeChanged (object sender, System. EventArgs e)
{
M_rect.X = this. Bounds. Width-95;
M_rect.Y = 4;
M_rect.Width = m_rect.Height = 16;
}
}
}