对窗口的系统菜单(SystemMenu)的一些操作
对窗口的系统菜单(SystemMenu)的一些操作
周银辉
有时候想禁用/移除/添加一些系统菜单项目,那么你可能会用到下面的API,以C#平台调用为例:
[DllImport("User32.dll")]
internal static extern IntPtr GetSystemMenu(IntPtr hWnd, Int32 bRevert);
该函数用于获取系统菜单句柄。hwnd参数是窗口句柄,表明你想要获取哪个窗口的系统菜单;bRevert ,bool值,如果为假,那么整个函数将返回原窗口的系统菜单的句柄拷贝;如果为真,则原窗口的系统菜单将被重置,函数将返回0,很显然这个函数就演变成“重置窗口系统菜单”了。
[DllImport("User32.dll")]
internal static extern int GetMenuItemCount(IntPtr hMenu);
该函数用于获取系系统菜单中的Item数目, hMenu为系统菜单句柄
[DllImport("User32.dll")]
internal static extern bool EnableMenuItem(IntPtr hMenu, Int32 uIDEnableItem, Int32 uEnable);
该函数用于启用或禁用系统菜单。hMenu为菜单句柄。uIDEnableItem表示操作项的Id或位置等(具体的取决与第三个参数)。uEnable,一些标志它可以是:
internal const UInt32 MF_ENABLED =0x00000000;
internal const UInt32 MF_GRAYED =0x00000001;
internal const UInt32 MF_DISABLED =0x00000002;
internal const UInt32 MF_BYCOMMAND =0x00000000;
internal const UInt32 MF_BYPOSITION =0x00000400;
如果uEnable是MF_BYPOSITION则uIDEnableItem应该传入Index信息(0,1.....),如果是MF_BYCOMMAND则应该传入Id
[DllImport("user32.dll",CharSet=CharSet.Auto)]
internal static extern int AppendMenu(int hMenu, int Flagsw, int IDNewItem, string lpNewItem);
该换上用于在系统菜单中追加项目。hMenu为菜单句柄,IDNewItem参数需要你为新添加的Item创建的ID,lpNewItem则是菜单文本,而嘛则是一些标志:
下列标志可被设置在参数uFlags里:
MF_BITMAP:将一个位图用作菜单项。参数lpNewltem里含有该位图的句柄。
MF_CHECKED:在菜单项旁边放置一个选取标记。如果应用程序提供一个选取标记,位图(参见SetMenultemBitmaps),则将选取标记位图放置在菜单项旁边。
MF_DISABLED:使菜单项无效,使该项不能被选择,但不使菜单项变灰。
MF_ENABLED:使菜单项有效,使该项能被选择,并使其从变灰的状态恢复。
MF_GRAYED:使菜单项无效并变灰,使其不能被选择。
MF_MENUBARBREAK:对菜单条的功能同MF_MENUBREAK标志。对下拉式菜单、子菜单或快捷菜单,新列和旧列被垂直线分开。
MF_MENUBREAK:将菜单项放置于新行(对菜单条),或新列(对下拉式菜单、子菜单或快捷菜单)且无分割列。
MF_OWNERDRAW:指定该菜单项为自绘制菜单项。菜单第一次显示前,拥有菜单的窗口接收一个WM_MEASUREITEM消息来得到菜单项的宽和高。然后,只要菜单项被修改,都将发送WM_DRAWITEM消息给菜单拥有者的窗口程序。
MF_POPUP:指定菜单打开一个下拉式菜单或子菜单。参数uIDNewltem下拉式菜单或子菜单的句柄。此标志用来给菜单条、打开一个下拉式菜单或于菜单的菜单项、子菜单或快捷菜单加一个名字。
MF_SEPARATOR:画一条水平区分线。此标志只被下拉式菜单、于菜单或快捷菜单使用。此区分线不能被变灰、无效或加亮。参数IpNewltem和uIDNewltem无用。
MF_STRING:指定菜单项是一个正文字符串;参数lpNewltem指向该字符串。
MF_UNCHECKED:不放置选取标记在菜单项旁边(缺省)。如果应用程序提供一个选取标记位图(参见SetMenultemBitmaps),则将选取标记位图放置在菜单项旁边。
下列标志组不能被一起使用:
MF_DISABLED,MF_ENABLED和MF_GRAYED;MF_BITMAP,MF_STRING和MF_OWNERDRAW
MF_MENUBARBREAK和MF_MENUBREAK;MF_CHECKED和MF_UNCHECKED
Windows CE环境下,不支持参数fuFlags使用下列标志:
MF_BITMAP;MF_DOSABLE;MF_GRAYED
MF_GRAYED可用来代替MF_DISABLED和MFS_GRAYED。
Windows CE 1.0不支持层叠式菜单。在使用Windows CE 1.0时,不能将一个MF_POPUP菜单插入到另一个下拉式菜单中。Window CE 1.0不支持下列标志:
MF_POPUP;MF_MENUBREAK;MF_MENUBARBREAK
Windows CE 2.0或更高版本中,支持上述标志,也支持层叠式菜单。
*/
[DllImport("user32.dll")]
internal static extern bool DeleteMenu(IntPtr hMenu, uint uPosition, uint uFlags);
该函数用于删除系统菜单项。hMenu为菜单句柄。uPosition表示操作项的Id或位置等(具体的取决与第三个参数)。uFlags,一些标志它可以是:
internal const UInt32 MF_DISABLED =0x00000002;
internal const UInt32 MF_BYCOMMAND =0x00000000;
如果uEnable是MF_BYPOSITION则uIDEnableItem应该传入Index信息(0,1.....),如果是MF_BYCOMMAND则应该传入Id
[DllImport("User32.dll")]
internal static extern int DrawMenuBar(IntPtr hWnd);
该函数用于重绘菜单,hWnd的菜单句柄。禁用/移除/添加一些系统菜单项目后,别忘了调用该函数重绘一下。
下面是一段示例代码:
{
if (window == null)
{
return false;
}
var winHelper = new WindowInteropHelper(window);
IntPtr hwnd = winHelper.Handle;
IntPtr sysMenu = GetSystemMenu(hwnd, 0);
// 6 close, 5 splite line, 4 Maximize, 3 Minimize, 2 Size, 1 Move, 0 Restore
// notes that, delete from bigger index to smaller
bool deletedAll = DeleteMenu(sysMenu, 5, MF_BYPOSITION) &
DeleteMenu(sysMenu, 4, MF_BYPOSITION) &
DeleteMenu(sysMenu, 3, MF_BYPOSITION) &
DeleteMenu(sysMenu, 0, MF_BYPOSITION);
DrawMenuBar(sysMenu);
return deletedAll;
}