Search code examples
c#.netwinformsmnemonics

Is there a way to force mnemonic key to show out without pressing ALT?


I'm working on a WinForms app and I'd like to use Mnemonics key. It appears that due to a Windows parameter, you can choose to show them while using the application only after pressing ALT (this option is like it as default). I got aware of this option thanks to this question (btw related but not duplicate).

I changed this option, and the Mnemonics underline shows properly at the start. But I'd like to avoid users have to either turn this option on or have to press ALT in order to see the underlined keys.

So my question is : Is there anyway in-app to force the underline of an Mnemonic key without changing settings or pressing ALT ?


Solution

  • For MenuStrip, you need to create a custom renderer to always show mnemonics regardless of pressing or not pressing Alt key. To do so derive from ToolStripProfessionalRenderer and override its OnRenderItemText, removing NoPrefix and HidePrefix flags from e.TextFormat. Then register the renderer for ToolStripManager.Renderer.

    For other controls to show mnemonics, you can override WndProc method of the form and handle WM_UPDATEUISTATE message and set WParam to combination of UISF_HIDEACCEL as high order word and UIS_CLEAR as low order words. This way all the controls will show mnemonic underline.

    Example

    Just copy and paste the following code in your form and run your application. The form will show underlines for all mnemonics without needing to press 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