有没有一种方法可以在不按ALT键的情况下强制显示助记符键?

5
我正在开发一个WinForms应用程序,我想使用助记键。由于Windows参数的限制,您只能在按下ALT键后使用应用程序时选择显示助记键(默认情况下是这样)。我通过这个问题了解到了这个选项(顺便说一句,这个问题与本问题相关但不重复)。
我更改了这个选项,开始时助记符下划线正确显示。但我希望避免用户必须打开此选项或按ALT键才能看到带下划线的键。
因此我的问题是:是否有在应用程序内强制显示助记键下划线的方法而无需更改设置或按ALT键?

1
通常,对于“我想以与选项明确设置相反的方式进行操作,我可以吗”的问题,无论您是否喜欢Microsoft正在做的事情,答案通常是“不行”或“你不应该”。基于各种窗口消息,决定是否强调加速键。理论上,即使没有适当的用户输入,也可以诱使控件这样做;但在实践中,这将是复杂和容易出错的。除非您想要完全自定义控件,否则这可能是一场失败的战斗。 - Jeroen Mostert
用户“知道”,如果他们知道这些键,他们会按ALT键来查看或更改其首选项。为什么您要试图颠覆用户的期望呢? - Damien_The_Unbeliever
@JeroenMostert 我有点这么想,但我想检查是否有其他办法。我猜我只需在创建表单时模拟一次ALT键按下即可显示它。感谢您的确认。达米安,因为一些人知道,但有些人经常使用这种应用程序,但并不真正了解计算机。 - Zoma
此外,显然地(?)为了完整性 -- 键盘快捷键的存在或缺失不应该对您的应用程序产生重大影响。如果需要显示它们,因为用户否则很难或无法访问某些内容,那么您肯定做错了。 - Jeroen Mostert
我从未尝试过任何键盘仿真技巧,这就是为什么我说“可能”的原因。在我的Windows上,实际按键的行为是只有在“Alt模式”下才会出现下划线。但这需要按下键并松开;如果你只模拟向下的按键,效果可能会不同。即便如此,在打开子菜单和对话框窗口等方面要做好潜在问题的准备,并进行彻底的测试。如果在某些情况下显示下划线对于您的应用程序绝对至关重要,则自定义方法更好--标签中的下划线不会切换,菜单也不是强制性的。 - Jeroen Mostert
显示剩余6条评论
1个回答

6
对于 MenuStrip,您需要创建一个自定义渲染器,以始终显示助记符,而不管是否按下 Alt 键。为此,请从 ToolStripProfessionalRenderer 派生,并重写其 OnRenderItemText 方法,从 e.TextFormat 中删除 NoPrefixHidePrefix 标志。然后将渲染器注册到 ToolStripManager.Renderer
对于其他控件显示助记符,您可以重写窗体的 WndProc 方法,并处理 WM_UPDATEUISTATE 消息,并将 WParam 设置为 UISF_HIDEACCEL 作为高位字和 UIS_CLEAR 作为低位字的组合。这样,所有控件都将显示助记符下划线。 示例 只需将以下代码复制并粘贴到您的表单中,然后运行您的应用程序。该表单将显示所有助记符的下划线,无需按下 Alt:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
const int WM_UPDATEUISTATE = 0x0128;
const int UISF_HIDEACCEL = 0x2;
const int UIS_CLEAR = 0x2;
protected override void OnShown(EventArgs e)
{
    base.OnShown(e);
    ToolStripManager.Renderer = new MyRenderer();
}
protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_UPDATEUISTATE)
        m.WParam = (IntPtr)((UISF_HIDEACCEL & 0x0000FFFF) | (UIS_CLEAR << 16));
    base.WndProc(ref m);
}
public class MyRenderer : ToolStripProfessionalRenderer
{
    protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
    {
        e.TextFormat &= ~TextFormatFlags.NoPrefix;
        e.TextFormat &= ~TextFormatFlags.HidePrefix;
        base.OnRenderItemText(e);
    }
}

enter image description here


2
非常好的答案,完美地满足了我的需求。非常感谢。 - Zoma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接