📄 flatmenuform.cs
字号:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace FlatMenuForm
{
public enum MenuStyle
{
Flat = 0,
Default = 1
}
public class Base : Form
{
private System.ComponentModel.Container components = null;
[DllImport("User32.dll",CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLong(IntPtr hwnd, int index, MyWndProc my);
[DllImport("User32.dll",CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowsHookEx(int type, HookProc hook,
IntPtr instance, int threadID);
//Function pointer to new window proc
public delegate int MyWndProc(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
//Function pointer to hook proc
public delegate int HookProc(int code, IntPtr wparam, ref Win32.CWPSTRUCT cwp);
IntPtr defaultWndProc = IntPtr.Zero;//Pointer to menu's default WndProc
MyWndProc subWndProc;//Delegate of type MyWndProc - needed to subclass the window
HookProc hookProc;//This is delegate of type HookProc - needed to process the hooked window
IntPtr hookHandle = IntPtr.Zero;//Pointer to hookProc
Color borderColor;
MenuStyle menuStyle;
public Base()
{
InitializeComponent();
//Construct the delegate that will process the hooked windows proc
hookProc = new HookProc(Hooked);
//Construct the delegate that will process the subclassed windows proc
subWndProc = new MyWndProc(SubclassWndProc);
//Set the default border color
borderColor = Color.Black;
//Default menu style
menuStyle = MenuStyle.Flat;
//Check for menu style
if(menuStyle == MenuStyle.Flat)
hookHandle = SetWindowsHookEx(4, hookProc, IntPtr.Zero ,
Win32.GetWindowThreadProcessId(Handle,0));
}
#region Subclassed wndProc
int Hooked(int code, IntPtr wparam, ref Win32.CWPSTRUCT cwp)
{
switch(code)
{
case 0://HC_ACTION -> this means that the hook procedure should process the message
//contained in CWPSTRUCT
switch(cwp.message)
{
case 0x0001://WM_CREATE - catch this before the window is created
string s = string.Empty;
char[] className = new char[10];
//Get the window class name
int length = Win32.GetClassName(cwp.hwnd,className,9);
//Convert it to string
for(int i=0;i<length;i++)
s += className[i];
//Now check if the window is a menu
if(s == "#32768")//System class for menu
//if true - subclass the window
defaultWndProc = SetWindowLong(cwp.hwnd, (-4), subWndProc);
break;
}
break;
}
return Win32.CallNextHookEx(hookHandle,code,wparam, ref cwp);
}
int SubclassWndProc(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam)
{
//tracer.Items.Add(msg.ToString());
switch(msg)
{
case 0x0085://WM_NCPAINT
IntPtr menuDC = Win32.GetWindowDC(hwnd);
Graphics g = Graphics.FromHdc(menuDC);
DrawBorder(g);
Win32.ReleaseDC(hwnd,menuDC);
g.Dispose();
return 0;
case 0x0317://WM_PRINT
int result = Win32.CallWindowProc(defaultWndProc,hwnd,msg,wparam,lparam);
menuDC = wparam;
g = Graphics.FromHdc(menuDC);
//Draw the border around the menu
DrawBorder(g);
Win32.ReleaseDC(hwnd,menuDC);
g.Dispose();
return result;
}
return Win32.CallWindowProc(defaultWndProc,hwnd,msg,wparam,lparam);
}
#endregion
#region Support methods
void DrawBorder(Graphics g)
{
Rectangle r = new Rectangle(0,0,(int)g.VisibleClipBounds.Width-1,
(int)g.VisibleClipBounds.Height-1);
Rectangle r1 = new Rectangle(1,1,(int)g.VisibleClipBounds.Width-3,
(int)g.VisibleClipBounds.Height-3);
Rectangle r2 = new Rectangle(2,2,(int)g.VisibleClipBounds.Width-5,
(int)g.VisibleClipBounds.Height-5);
g.DrawRectangle(new Pen(borderColor),r);
g.DrawRectangle(new Pen(SystemColors.Menu),r1);
g.DrawRectangle(new Pen(SystemColors.Menu),r2);
}
#endregion
#region Overriden methods
#region MainForm WndProc
protected override void WndProc(ref Message m)
{
switch(m.Msg)
{
case 0x0002://WM_DESTROY -> we have to unhook the hooked windows
Win32.UnhookWindowsHookEx(hookHandle);
base.WndProc(ref m);
break;
default:
base.WndProc(ref m);
break;
}
}
#endregion
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
base.Dispose( disposing );
}
#endregion
#region Public properties
public Color BorderColor
{
get{return borderColor;}
set{borderColor = value;}
}
public MenuStyle MenuStyle
{
get{return menuStyle;}
set
{
if(value == MenuStyle.Default)
Win32.UnhookWindowsHookEx(hookHandle);
else
hookHandle = SetWindowsHookEx(4, hookProc, IntPtr.Zero ,
Win32.GetWindowThreadProcessId(Handle,0));
menuStyle = value;
}
}
#endregion
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -