- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在调整 answer 时的 ygoe , 我发现可以向菜单添加图标。
我通过将此代码用于纯文本项目尝试并成功地做到了这一点:
var item = new MenuItemInfo
{
cbSize = (uint)Marshal.SizeOf(typeof(MenuItemInfo)),
cch = (uint)label.Length,
dwTypeData = label,
fMask = 0x2 | 0x10, // MIIM_ID | MIIM_TYPE
fState = 0x0, // MFS_ENABLED
fType = 0x0, // MFT_STRING
wID = id
};
InsertMenuItem(hMenu, 0, true, ref item);
对于基于图标的项目,我更改了 fMask
并添加了 hbmpItem
,如下所示:
var item = new MenuItemInfo
{
cbSize = (uint)Marshal.SizeOf(typeof(MenuItemInfo)),
cch = (uint)label.Length,
dwTypeData = label,
fMask = 0x80 | 0x2 | 0x100, // MIIM_BITMAP | MIIM_ID | MIIM_FTYPE
fState = 0x0, // MFS_ENABLED
fType = 0x0, // MFT_STRING
hbmpItem = hIcon // handle provided by Bitmap.GetHbitmap()
wID = id
};
InsertMenuItem(hMenu, 0, true, ref item);
但是通过这样做,label
的文本消失了 - 只显示图标,无论 fMask
和 fType
的组合如何> 我试试。 😞
请帮我弄清楚我做错了什么。
最佳答案
这些是声明(全部来自相关的 MSDN 文档):
MSDN 文档:
使用的主要功能:InsertMenuItem()
MENUITEMINFO结构。
使用 GetSystemMenu() 检索系统菜单句柄
As a curiosity, these are not referenced on PInvoke.net.
[DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool InsertMenuItem(IntPtr hMenu, uint uItem, bool fByPosition, ref MenuItemInfo lpmii);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
public enum MenuItemInfo_fMask : uint
{
MIIM_BITMAP = 0x00000080, //Retrieves or sets the hbmpItem member.
MIIM_CHECKMARKS = 0x00000008, //Retrieves or sets the hbmpChecked and hbmpUnchecked members.
MIIM_DATA = 0x00000020, //Retrieves or sets the dwItemData member.
MIIM_FTYPE = 0x00000100, //Retrieves or sets the fType member.
MIIM_ID = 0x00000002, //Retrieves or sets the wID member.
MIIM_STATE = 0x00000001, //Retrieves or sets the fState member.
MIIM_STRING = 0x00000040, //Retrieves or sets the dwTypeData member.
MIIM_SUBMENU = 0x00000004, //Retrieves or sets the hSubMenu member.
MIIM_TYPE = 0x00000010, //Retrieves or sets the fType and dwTypeData members.
//MIIM_TYPE is replaced by MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING.
}
public enum MenuItemInfo_fType : uint
{
MFT_BITMAP = 0x00000004, //Displays the menu item using a bitmap. The low-order word of the dwTypeData member is the bitmap handle, and the cch member is ignored.
//MFT_BITMAP is replaced by MIIM_BITMAP and hbmpItem.
MFT_MENUBARBREAK = 0x00000020, //Places the menu item on a new line (for a menu bar) or in a new column (for a drop-down menu, submenu, or shortcut menu). For a drop-down menu, submenu, or shortcut menu, a vertical line separates the new column from the old.
MFT_MENUBREAK = 0x00000040, //Places the menu item on a new line (for a menu bar) or in a new column (for a drop-down menu, submenu, or shortcut menu). For a drop-down menu, submenu, or shortcut menu, the columns are not separated by a vertical line.
MFT_OWNERDRAW = 0x00000100, //Assigns responsibility for drawing the menu item to the window that owns the menu. The window receives a WM_MEASUREITEM message before the menu is displayed for the first time, and a WM_DRAWITEM message whenever the appearance of the menu item must be updated. If this value is specified, the dwTypeData member contains an application-defined value.
MFT_RADIOCHECK = 0x00000200, //Displays selected menu items using a radio-button mark instead of a check mark if the hbmpChecked member is NULL.
MFT_RIGHTJUSTIFY = 0x00004000, //Right-justifies the menu item and any subsequent items. This value is valid only if the menu item is in a menu bar.
MFT_RIGHTORDER = 0x00002000, //Specifies that menus cascade right-to-left (the default is left-to-right). This is used to support right-to-left languages, such as Arabic and Hebrew.
MFT_SEPARATOR = 0x00000800, //Specifies that the menu item is a separator. A menu item separator appears as a horizontal dividing line. The dwTypeData and cch members are ignored. This value is valid only in a drop-down menu, submenu, or shortcut menu.
MFT_STRING = 0x00000000 //Displays the menu item using a text string. The dwTypeData member is the pointer to a null-terminated string, and the cch member is the length of the string.
//MFT_STRING is replaced by MIIM_STRING.
}
//The menu item state. This member can be one or more of these values. Set fMask to MIIM_STATE to use fState.
public enum MenuItemInfo_fState : uint
{
MFS_CHECKED = 0x00000008, //Checks the menu item. For more information about selected menu items, see the hbmpChecked member.
MFS_DEFAULT = 0x00001000, //Specifies that the menu item is the default. A menu can contain only one default menu item, which is displayed in bold.
MFS_DISABLED = 0x00000003, //Disables the menu item and grays it so that it cannot be selected. This is equivalent to MFS_GRAYED.
MFS_ENABLED = 0x00000000, //Enables the menu item so that it can be selected. This is the default state.
MFS_GRAYED = 0x00000003, //Disables the menu item and grays it so that it cannot be selected. This is equivalent to MFS_DISABLED.
MFS_HILITE = 0x00000080, //Highlights the menu item.
MFS_UNCHECKED = 0x00000000, //Unchecks the menu item. For more information about clear menu items, see the hbmpChecked member.
MFS_UNHILITE = 0x00000000, //Removes the highlight from the menu item. This is the default state.
}
//A handle to the bitmap to be displayed, or it can be one of the values in the following Enum.
//It is used when the MIIM_BITMAP flag is set in the fMask member. (ex. (hBitmap)HBMMENU_SYSTEM)
public enum MenuItemInfo_hItem
{
HBMMENU_CALLBACK = -1, //A bitmap that is drawn by the window that owns the menu. The application must process the WM_MEASUREITEM and WM_DRAWITEM messages.
HBMMENU_MBAR_CLOSE = 5, //Close button for the menu bar.
HBMMENU_MBAR_CLOSE_D = 6, //Disabled close button for the menu bar.
HBMMENU_MBAR_MINIMIZE = 3, //Minimize button for the menu bar.
HBMMENU_MBAR_MINIMIZE_D = 7, //Disabled minimize button for the menu bar.
HBMMENU_MBAR_RESTORE = 2, //Restore button for the menu bar.
HBMMENU_POPUP_CLOSE = 8, //Close button for the submenu.
HBMMENU_POPUP_MAXIMIZE = 10, //Maximize button for the submenu.
HBMMENU_POPUP_MINIMIZE = 11, //Minimize button for the submenu.
HBMMENU_POPUP_RESTORE = 9, //Restore button for the submenu.
HBMMENU_SYSTEM = 1, //Windows icon or the icon of the window specified in dwItemData.
}
public struct MenuItemInfo
{
public uint cbSize; //The size of the structure, in bytes. The caller must set this member to sizeof(MENUITEMINFO).
public MenuItemInfo_fMask fMask; //See MenuItemInfo_fMask
public MenuItemInfo_fType fType; //See MenuItemInfo_fType
public MenuItemInfo_fState fState; //See MenuItemInfo_fState
public uint wID; //An application-defined value that identifies the menu item. Set fMask to MIIM_ID to use wID.
public IntPtr hSubMenu; //A handle to the drop-down menu or submenu associated with the menu item. If the menu item is not an item that opens a drop-down menu or submenu, this member is NULL. Set fMask to MIIM_SUBMENU to use hSubMenu.
public IntPtr hbmpChecked; //A handle to the bitmap to display next to the item if it is selected. If this member is NULL, a default bitmap is used. If the MFT_RADIOCHECK type value is specified, the default bitmap is a bullet. Otherwise, it is a check mark. Set fMask to MIIM_CHECKMARKS to use hbmpChecked.
public IntPtr hbmpUnchecked; //A handle to the bitmap to display next to the item if it is not selected. If this member is NULL, no bitmap is used. Set fMask to MIIM_CHECKMARKS to use hbmpUnchecked.
public IntPtr dwItemData; //An application-defined value associated with the menu item. Set fMask to MIIM_DATA to use dwItemData.
public IntPtr dwTypeData; //The contents of the menu item. The meaning of this member depends on the value of fType and is used only if the MIIM_TYPE flag is set in the fMask member.
//To retrieve a menu item of type MFT_STRING, first find the size of the string by setting the dwTypeData member of MENUITEMINFO to NULL and then calling GetMenuItemInfo. The value of cch+1 is the size needed. Then allocate a buffer of this size, place the pointer to the buffer in dwTypeData, increment cch, and call GetMenuItemInfo once again to fill the buffer with the string. If the retrieved menu item is of some other type, then GetMenuItemInfo sets the dwTypeData member to a value whose type is specified by the fType member.
//When using with the SetMenuItemInfo function, this member should contain a value whose type is specified by the fType member.
//dwTypeData is used only if the MIIM_STRING flag is set in the fMask member
public uint cch; //The length of the menu item text, in characters, when information is received about a menu item of the MFT_STRING type. However, cch is used only if the MIIM_TYPE flag is set in the fMask member and is zero otherwise. Also, cch is ignored when the content of a menu item is set by calling SetMenuItemInfo.
//Note that, before calling GetMenuItemInfo, the application must set cch to the length of the buffer pointed to by the dwTypeData member. If the retrieved menu item is of type MFT_STRING (as indicated by the fType member), then GetMenuItemInfo changes cch to the length of the menu item text. If the retrieved menu item is of some other type, GetMenuItemInfo sets the cch field to zero.
//The cch member is used when the MIIM_STRING flag is set in the fMask member.
public IntPtr hbmpItem; //A handle to the bitmap to be displayed, or it can be one of the values MenuItemInfo_hItem Enum. It is used when the MIIM_BITMAP flag is set in the fMask member.
};
如果你想显示文本和位图:
private MenuItemInfo_fMask InsMenuFlags = MenuItemInfo_fMask.MIIM_STRING |
MenuItemInfo_fMask.MIIM_BITMAP |
MenuItemInfo_fMask.MIIM_FTYPE |
MenuItemInfo_fMask.MIIM_STATE |
MenuItemInfo_fMask.MIIM_ID;
您可以这样创建一个菜单项:
private IntPtr hSysMenu;
hSysMenu = GetSystemMenu(someform.Handle, false);
private void InsertMenu(uint id, uint icIndex, string icText, IntPtr hBitmap)
{
MenuItemInfo mInfo = new MenuItemInfo()
{
cbSize = (uint)Marshal.SizeOf(typeof(MenuItemInfo)),
fMask = InsMenuFlags,
fType = MenuItemInfo_fType.MFT_STRING,
fState = MenuItemInfo_fState.MFS_ENABLED,
wID = id,
hbmpItem = hBitmap,
hbmpChecked = hBitmap,
hbmpUnchecked = hBitmap,
dwTypeData = Marshal.StringToHGlobalAuto(icText),
dwItemData = IntPtr.Zero,
hSubMenu = IntPtr.Zero,
cch = (uint)icText.Length,
};
InsertMenuItem(hSysMenu, icIndex, true, ref mInfo);
}
更新:
由于它在 OP 中被引用,这里有一个修改后的 SystemMenu
类(致谢 ygoe )现在支持 InsertMenuItem()
以允许系统菜单中的位图。
原文GitHub source code of SystemMenu
可以这样使用这个类(插入到 Form 构造函数中):
SystemMenu systemMenu;
Bitmap menuIcon;
//In a Form contructor
{
systemMenu = new SystemMenu(this);
menuIcon = new Bitmap(Properties.Resources.[Some 16x16 Bitmap]);
systemMenu.InsertCommand(0, "Bitmap Menu", menuIcon.GetHbitmap(), OnSysBitmapMenu);
systemMenu.AddCommand("&About…", OnSysMenuAbout, true);
}
// Handle menu command click
private void OnSysMenuAbout()
{
MessageBox.Show("My about message");
}
private void OnSysBitmapMenu()
{
MessageBox.Show("My other bitmap menu message");
}
protected override void WndProc(ref Message msg)
{
base.WndProc(ref msg);
// Let it know all messages so it can handle WM_SYSCOMMAND
// (This method is inlined)
systemMenu.HandleMessage(ref msg);
}
All declarations previously posted must be inserted in the
#region Native methods
of theSystemMenu
class with the exception of theInsMenuFlags
field.
Note: The 16x16 Bitmap should be padded 2 pixels on the left.
public class SystemMenu
{
private const int WM_SYSCOMMAND = 0x112;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool AppendMenu(IntPtr hMenu, MenuItemInfo_fType uFlags, int uIDNewItem, string lpNewItem);
public enum CommandType : int
{
AppendMenu = 0,
InsertMenu
}
private MenuItemInfo_fMask InsMenuFlags = MenuItemInfo_fMask.MIIM_STRING |
MenuItemInfo_fMask.MIIM_BITMAP |
MenuItemInfo_fMask.MIIM_FTYPE |
MenuItemInfo_fMask.MIIM_STATE |
MenuItemInfo_fMask.MIIM_ID;
private Form form;
private IntPtr hSysMenu;
private int lastId = 0;
private List<Action> actions = new List<Action>();
private List<CommandInfo> pendingCommands;
/// <summary>
/// Initialises a new instance of the <see cref="SystemMenu"/> class for the specified
/// <see cref="Form"/>.
/// </summary>
/// <param name="form">The window for which the system menu is expanded.</param>
public SystemMenu(Form form)
{
this.form = form;
if (!form.IsHandleCreated) {
form.HandleCreated += OnHandleCreated;
}
else {
OnHandleCreated(null, null);
}
}
/// <summary>
/// Adds a command to the system menu.
/// </summary>
/// <param name="text">The displayed command text.</param>
/// <param name="action">The action that is executed when the user clicks on the command.</param>
/// <param name="separatorBeforeCommand">Indicates whether a separator is inserted before the command.</param>
public void AddCommand(string text, Action action, bool separatorBeforeCommand)
{
int id = ++lastId;
if (!form.IsHandleCreated) {
// The form is not yet created, queue the command for later addition
if (pendingCommands == null) {
pendingCommands = new List<CommandInfo>();
}
pendingCommands.Add(new CommandInfo() {
Id = id,
Text = text,
Action = action,
CommandType = SystemMenu.CommandType.AppendMenu,
Separator = separatorBeforeCommand
});
}
else {
// The form is created, add the command now
if (separatorBeforeCommand) {
AppendMenu(hSysMenu, MenuItemInfo_fType.MFT_SEPARATOR, 0, "");
}
AppendMenu(hSysMenu, MenuItemInfo_fType.MFT_STRING, id, text);
}
actions.Add(action);
}
/// <summary>
/// Adds a command to the system menu.
/// </summary>
/// <param name="icText">The displayed command text.</param>
/// <param name="icAction">The action that is executed when the user clicks on the command.</param>
/// <param name="separatorBeforeCommand">Indicates whether a separator is inserted before the command.</param>
public void InsertCommand(uint icIndex, string icText, IntPtr hBitmap, Action icAction)
{
int id = ++lastId;
InsertCommand(id, icIndex, icText, hBitmap, icAction);
}
private void InsertCommand(int id, uint icIndex, string icText, IntPtr hBitmap, Action icAction)
{
if (!form.IsHandleCreated) {
// The form is not yet created, queue the command for later addition
if (pendingCommands == null) {
pendingCommands = new List<CommandInfo>();
}
pendingCommands.Add(new CommandInfo() {
Id = id,
Index = (int)icIndex,
Text = icText,
Action = icAction,
CommandType = SystemMenu.CommandType.InsertMenu,
hBitmap = hBitmap,
Separator = false
});
}
else {
MenuItemInfo mInfo = new MenuItemInfo()
{
cbSize = (uint)Marshal.SizeOf(typeof(MenuItemInfo)),
fMask = InsMenuFlags,
fType = MenuItemInfo_fType.MFT_STRING,
fState = MenuItemInfo_fState.MFS_ENABLED,
wID = (uint)id,
hbmpItem = hBitmap,
hbmpChecked = hBitmap,
hbmpUnchecked = hBitmap,
dwTypeData = Marshal.StringToHGlobalAuto(icText),
dwItemData = IntPtr.Zero,
hSubMenu = IntPtr.Zero,
cch = (uint)icText.Length,
};
// The form is created, add the command now
InsertMenuItem(hSysMenu, icIndex, true, ref mInfo);
}
actions.Add(icAction);
}
/// <summary>
/// Tests a window message for system menu commands and executes the associated action. This
/// method must be called from within the Form's overridden WndProc method because it is not
/// publicly accessible.
/// </summary>
/// <param name="msg">The window message to test.</param>
public void HandleMessage(ref Message msg)
{
// This method is kept short and simple to allow inlining (verified) for improving
// performance (unverified). It will be called for every single message that is sent to
// the window.
if (msg.Msg == WM_SYSCOMMAND) {
OnSysCommandMessage(ref msg);
}
}
private void OnHandleCreated(object sender, EventArgs args)
{
form.HandleCreated -= OnHandleCreated;
hSysMenu = GetSystemMenu(form.Handle, false);
// Add all queued commands now
if (pendingCommands != null) {
foreach (CommandInfo command in pendingCommands) {
switch (command.CommandType)
{
case CommandType.AppendMenu:
if (command.Separator) {
AppendMenu(hSysMenu, MenuItemInfo_fType.MFT_SEPARATOR, 0, "");
}
AppendMenu(hSysMenu, MenuItemInfo_fType.MFT_STRING, command.Id, command.Text);
break;
case CommandType.InsertMenu:
InsertCommand(command.Id, (uint)command.Index, command.Text, command.hBitmap, command.Action);
break;
default:
break;
}
}
pendingCommands = null;
}
}
private void OnSysCommandMessage(ref Message msg)
{
if ((long)msg.WParam > 0 && (long)msg.WParam <= lastId) {
actions[(int)msg.WParam - 1]();
}
}
private class CommandInfo
{
public int Id { get; set; }
public int Index { get; set; }
public string Text { get; set; }
public Action Action { get; set; }
public IntPtr hBitmap { get; set; }
public bool Separator { get; set; }
public CommandType CommandType { get; set; }
}
}
关于c# - 如何在 WinForms 系统菜单中显示带有图标和文本的菜单项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49056495/
我想使用 li 和 ul 制作一个多级下拉列表,以便显示我博客中按年和月排序的所有文章。我希望我的下拉菜单看起来像 Google Blogspot 下拉菜单: 这是我的 CSS 和 HTML 代码 u
我在 Win 7 64 机器上将 CodeBlocks 与 gcc 4.7.2 和 gmp 5.0.5 结合使用。开始使用 gmpxx 后,我看到一个奇怪的段错误,它不会出现在 +、- 等运算符中,但
我正在使用 tern 为使用 CodeMirror 运行的窗口提供一些增强的智能感知,它工作正常,但我遇到了一个问题,我想添加一些自定义“types”,可以这么说,这样下拉列表中它们旁边就有图标了。我
我正在尝试让我的 PC 成为 Android 2.3.4 设备的 USB 主机,以便能够在不需要实际“附件”的情况下开发 API。为此,我需要将 PC 设置为 USB 主机和“设备”(在我的例子中是运
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 9
我在设置服务器方面几乎是个新手,但遇到了一个问题。我有一个 Ubuntu 16.04 VPS 并安装了 Apache2 和 Tomcat7。我正在为 SSL 使用 LetsEncrypt 和 Cert
我在一个基于谷歌地图的项目上工作了超过 6 个月。我使用的是 Google Maps API V1 及其开发人员 API key 。当我尝试发布应用程序时,我了解到 Google API V1 已被弃
我是 Python 的新手,所以如果我对一些简单的事情感到困惑,请原谅。 我有一个这样的对象: class myObject(object): def __init__(self):
这个问题已经有答案了: How can I access object properties containing special characters? (2 个回答) 已关闭 9 年前。 我正在尝
我有下面的 CSS。我想要的是一种流体/液体(因为缺乏正确的术语)css。我正在为移动设备开发,当我改变模式时 从纵向 View 到陆地 View ,我希望它流畅。现在的图像 在陆地 View 中效
我正在尝试使用可以接受参数的缓存属性装饰器。 我查看了这个实现:http://www.daniweb.com/software-development/python/code/217241/a-cac
这个问题在这里已经有了答案: Understanding slicing (36 个答案) 关闭 6 年前。 以a = [1,2,3,4,5]为例。根据我的直觉,我认为 a[::-1] 与 a[0:
mysqldump -t -u root -p mytestdb mytable --where=datetime LIKE '2014-09%' 这就是我正在做的事情,它会返回: mysqldum
我正在制作销售税计算器,除了总支付金额部分外,其他一切都正常。在我的程序中,我希望能够输入一个数字并获得该项目的税额我还希望能够获得支付的总金额,包括交易中的税金。到目前为止,我编写的代码完成了所有这
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许在 Stack Overflow 上提出有关通用计算硬件和软件的问题。您可以编辑问题,使其成为
我是否必须进行任何额外的设置才能让 apache-airflow 在任务失败时向我发送电子邮件。我的配置文件中有以下内容(与默认值保持不变): [email] email_backend = airf
这个问题在这里已经有了答案: What does the $ symbol do in VBA? (5 个回答) 3年前关闭。 使用返回字符串(如 Left)的内置函数有什么区别吗?或使用与 $ 相同
我有一个用VB6编写的应用程序,我需要使用一个用.NET编写的库。有什么方法可以在我的应用程序上使用该库吗? 谢谢 最佳答案 这取决于。您可以控制.NET库吗? 如果是这样,则可以修改您的库,以便可以
当我创建一个以 ^ 开头的类方法时,我尝试调用它,它给了我一个错误。 class C { method ^test () { "Hi" } } dd C.new.test; Too m
我已经使用 bower 安装了 angularjs 和 materialjs。 凉亭安装 Angular Material 并将“ngMaterial”注入(inject)我的应用程序,但出现此错误。
我是一名优秀的程序员,十分优秀!