WPF Handedness with Popups

前端 未结 3 2039
灰色年华
灰色年华 2020-11-28 09:45

I just moved my PC to Windows 8 from Windows 7 and while running our WPF application I noticed that our WPF popups and/or tool tips are now in the lower-left by default inst

3条回答
  •  迷失自我
    2020-11-28 10:14

    Ok, for those that do not want this to occur at all in their app (which was our desire), We have created a nice little hack for WPF. This works well for us.

    First:

    This code will be what runs which fixes the issue:

    public static void SetAlignment()
    {
        var ifLeft = SystemParameters.MenuDropAlignment;
    
        if (ifLeft)
        {
            // change to false
            var t = typeof(SystemParameters);
            var field = t.GetField("_menuDropAlignment", BindingFlags.NonPublic | BindingFlags.Static);
            field.SetValue(null, false);
    
            ifLeft = SystemParameters.MenuDropAlignment;
        }
    }
    

    However, the environment can de-validate microsofts internal cache of these values, so we have to hook into WinProc to get this. I wont post the WinProc code, just the messages that are needed:

    These are the Win32 messages that will de-validate the internal cache:

    private const int WM_WININICHANGE = 0x001A;
    private const int WM_DEVICECHANGE = 0x219;
    private const int WM_DISPLAYCHANGE = 0x7E;
    private const int WM_THEMECHANGED = 0x031A;
    private const int WM_SYSCOLORCHANGE = 0x15;
    

    And the quick snippit that will set your preference back. Because we are hooked into WinProc, you will want to change this value after WinProc is finished with the message on other handlers. We have a delay to re-set the preference value back to what we want.

    if (msg == WM_WININICHANGE || msg == WM_DEVICECHANGE || msg == WM_DISPLAYCHANGE || msg == WM_THEMECHANGED || msg == WM_SYSCOLORCHANGE)
    {
        Timer timer = null;
        timer = new Timer((x) =>
            {
                WpfHelperHacks.SetAlignment();
                timer.Dispose();
            },null, TimeSpan.FromMilliseconds(2), TimeSpan.FromMilliseconds(-1));
    }
    

    And just like that its complete. I hope this helps someone else!

提交回复
热议问题