簡體   English   中英

在WPF窗口中掛鈎進入Windows消息循環,在內部添加白色邊框

[英]Hooking into Windows message loop in WPF window adds white border on the inside

我正在嘗試創建一個WPF窗口,其中WindowStyle="None" (對於自定義按鈕,沒有標題)無法調整大小。 ResizeMode設置為NoResize將刪除我想要保留的aero邊框。

我可以設置最小/最大尺寸屬性並完成它,除了:

  1. 調整大小的游標仍然可見,並且
  2. 顯示窗口以響應用戶操作並適合其內容。 它顯示圖像,因此大小會發生變化。

所以,我有一個簡單的方案,讓我99%的方式:

public class BorderedWindowNoResize : Window
{
    [DllImport( "DwmApi.dll" )]
    public static extern int DwmExtendFrameIntoClientArea(
        IntPtr hwnd,
        ref MARGINS pMarInset );

    [DllImport( "user32.dll", CharSet = CharSet.Auto )]
    public static extern IntPtr DefWindowProc(
        IntPtr hWnd,
        int msg,
        IntPtr wParam,
        IntPtr lParam );

    public BorderedWindowNoResize()
    {           
        Loaded += BorderedWindowNoResize_Loaded;
    }

    private void BorderedWindowNoResize_Loaded( object sender, RoutedEventArgs e )
    {           
        IntPtr mainWindowPtr = new WindowInteropHelper( this ).Handle;
        HwndSource mainWindowSrc = HwndSource.FromHwnd( mainWindowPtr );            
        mainWindowSrc.AddHook( WndProc );
    }

    private IntPtr WndProc( IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled )
    {           
        var htLocation = DefWindowProc( hwnd, msg, wParam, lParam ).ToInt32();

        if( msg == (uint)WM.NCHITTEST )
        {
            handled = true;
            switch( htLocation )
            {
                case (int)HitTestResult.HTBOTTOM:
                case (int)HitTestResult.HTBOTTOMLEFT:
                case (int)HitTestResult.HTBOTTOMRIGHT:
                case (int)HitTestResult.HTLEFT:
                case (int)HitTestResult.HTRIGHT:
                case (int)HitTestResult.HTTOP:
                case (int)HitTestResult.HTTOPLEFT:
                case (int)HitTestResult.HTTOPRIGHT:
                    htLocation = (int)HitTestResult.HTBORDER;
                    break;
            }               
        }

        return new IntPtr( htLocation );
    }
}

基本上;

  1. 覆蓋窗口過程。
  2. 調用默認窗口過程。
  3. 如果消息是WM_NCHITTEST ,請檢查邊框結果。
  4. 如果是邊框,請返回常規HTBORDER

這可以讓我保持aero窗口邊框並隱藏調整大小的光標,但它在我的窗口內部添加了一個~5像素的白色邊框。

實際上,即使我在WndPrc頂部返回默認的Windows程序結果,也沒有做其他任何事情,邊框仍然存在。 我的窗口需要不同的背景顏色,所以這對我不起作用。

有任何想法嗎? 一如既往地感謝您。

添加掛鈎時,應該只處理所需的消息,而忽略其他消息。 我相信你正在處理某些消息兩次,因為你調用了DefWindowProc,但從未將handle參數設置為true。

所以在你的情況下,你會使用:

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {

    if (msg == (uint)WM.NCHITTEST) {
        handled = true;
        var htLocation = DefWindowProc(hwnd, msg, wParam, lParam).ToInt32();
        switch (htLocation) {
            case (int)HitTestResult.HTBOTTOM:
            case (int)HitTestResult.HTBOTTOMLEFT:
            case (int)HitTestResult.HTBOTTOMRIGHT:
            case (int)HitTestResult.HTLEFT:
            case (int)HitTestResult.HTRIGHT:
            case (int)HitTestResult.HTTOP:
            case (int)HitTestResult.HTTOPLEFT:
            case (int)HitTestResult.HTTOPRIGHT:
                htLocation = (int)HitTestResult.HTBORDER;
                break;
        }
        return new IntPtr(htLocation);
    }

    return IntPtr.Zero;
}

另外,我可能會在OnSourceInitialized覆蓋中添加鈎子,如下所示:

protected override void OnSourceInitialized(EventArgs e) {
    base.OnSourceInitialized(e);

    IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
    HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
    mainWindowSrc.AddHook(WndProc);
}

您可以在WPF應用程序的任何位置嘗試

                ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);

和:

    // ******************************************************************
    private static void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled)
    {
        if (!handled)
        {
            if (msg.message == WmHotKey)
            {
                HotKey hotKey;

                if (_dictHotKeyToCalBackProc.TryGetValue((int)msg.wParam, out hotKey))
                {
                    if (hotKey.Action != null)
                    {
                        hotKey.Action.Invoke(hotKey);
                    }
                    handled = true;
                }
            }
        }
    }

希望能幫助到你... :-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM