Loading a WPF Window without showing it

前端 未结 12 777
独厮守ぢ
独厮守ぢ 2020-12-12 16:14

I create a global hot key to show a window by PInvoking RegisterHotKey(). But to do this I need that window\'s HWND, which doesn\'t exist until the

相关标签:
12条回答
  • 2020-12-12 16:38

    Another option in a similar vein to setting the opacity to 0, is to set the size to 0 and set the position to be off the screen. This won't require the AllowsTransparency = True.

    Also remember that once you have shown it once you can then hide it and still get the hwnd.

    0 讨论(0)
  • 2020-12-12 16:39

    I've noticed that the last thing that happens when the window is being initialized, is the change of WindowState, if it differs from normal. So, you can actually make use of it:

    public void InitializeWindow(Window window) {
        window.Top = Int32.MinValue;
        window.Left = Int32.MinValue;
    
        window.Width = 0;
        window.Height = 0;
    
        window.ShowActivated = false;
        window.ShowInTaskbar = false;
        window.Opacity = 0;
    
        window.StateChanged += OnBackgroundStateChanged;
    
        window.WindowStyle = WindowStyle.None;
    }
    
    public void ShowWindow(Window window) {
        window.Show();
        window.WindowState = WindowState.Maximized;
    }
    
    protected bool isStateChangeFirst = true;
    protected void OnBackgroundStateChanged(object sender, EventArgs e) {
        if (isStateChangeFirst) {
            isStateChangeFirst = false;
    
            window.Top = 300;
            window.Left = 200;
    
            window.Width = 760;
            window.Height = 400;
    
            window.WindowState = WindowState.Normal;
    
            window.ShowInTaskbar = true;
            window.Opacity = 1;
            window.Activate();
        }
    }
    

    That works fair enough for me. And it does not require working with any handles and stuff, and, more importantly, does not require to have a custom class for a window. Which is great for dynamically loaded XAML. And it is also a great way if you are making a fullscreen app. You do not even need to change its state back to normal or set proper width and height. Just go with

    protected bool isStateChangeFirst = true;
    protected void OnBackgroundStateChanged(object sender, EventArgs e) {
        if (isStateChangeFirst) {
            isStateChangeFirst = false;
    
            window.ShowInTaskbar = true;
            window.Opacity = 1;
            window.Activate();
        }
    }
    

    And you're done.

    And even if I am wrong in my assumption that change of state is last thing done when window is being loaded, you can still change to any other event, it does not really matter.

    0 讨论(0)
  • 2020-12-12 16:40

    I've never tried to do what you are doing, but if you need to show the Window to get the HWND, but don't want to show it, set the Window Opacity to 0. This will also prevent any hit testing from occurring. Then you could have a public method on the Window to change the Opacity to 100 when you want to make it visible.

    0 讨论(0)
  • 2020-12-12 16:41

    I had already posted an answer to that question, but I just found a better solution.

    If you just need to make sure that the HWND is created, without actually showing the window, you can do this:

        public void InitHwnd()
        {
            var helper = new WindowInteropHelper(this);
            helper.EnsureHandle();
        }
    

    (actually the EnsureHandle method wasn't available when the question was posted, it was introduced in .NET 4.0)

    0 讨论(0)
  • 2020-12-12 16:43

    This is a dirty hack, but it should work, and doesn't have the downsides of changing the opacity :

    • set the WindowStartupLocation to Manual
    • set the Top and Left properties to somewhere outside the screen
    • set ShowInTaskbar to false so that the user doesn't realize there is a new window
    • Show and Hide the window

    You should now be able to retrieve the HWND

    EDIT: another option, probably better : set ShowInTaskBar to false and WindowState to Minimized, then show it : it won't be visible at all

    0 讨论(0)
  • 2020-12-12 16:46

    I know absolutely nothing about WPF, but could you create a message only window using other means (PInvoke for example) to receive the WM_HOTKEY message? If yes, then once you receive the WM_HOTKEY, you could launch the WPF window from there.

    0 讨论(0)
提交回复
热议问题