2011-06-16 11 views
15

サイズを変更できないWindowStyle="None"(カスタムボタンとタイトルなし)のWPFウィンドウを作成しようとしています。 ResizeModeからNoResizeに設定すると、空白の枠線が削除されます。WPFウィンドウでWindowsのメッセージループに繋ぐと、内側に白い枠が追加されます

Iは、最小/最大サイズ・プロパティを設定することができ、それを用いて行われる、ことを除いて:

  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を返します。

これは私がエアロウィンドウの境界線を保持し、サイズ変更カーソルを隠すことができる限り動作しますが、ウィンドウの内側に〜5ピクセルの白い境界線を追加します。

実際、WndPrcの上部にあるデフォルトのウィンドウプロシージャの結果を返しても、何もしない場合でも、境界線はです。まだです。私は窓の上に別の背景色が必要なので、これは私にとってはうまくいかないでしょう。

アイデア?いつものように事前に感謝します。

答えて

10

フックを追加するときは、必要なメッセージのみを処理し、他のメッセージは無視してください。私はあなたがDefWindowProcを呼び出すので、あなたが特定のメッセージを2回処理していると信じていますが、決して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); 
} 
+0

さあ、そうですよね。私はデフォルトの手順を2回呼びます。 Yeesh。さて、1時間ほどで作業に入ると、それを試してみるよ、ありがとう。 –

+0

そしてそれは良い先です。 Yeesh、何年ものMFCの後、私はこのような愚かな間違いをしたとは信じられません...もう一度感謝します。 –

+0

@Ed - 問題はありませんが、それはいつも問題の目の2番目のセットを得るのに役立ちます:-) – CodeNaked

3

あなたはどこからでも試すことができます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; 
       } 
      } 
     } 
    } 

希望します。:-)

関連する問題