2012-07-28 3 views
9

WPF에서 내 사용자 지정 창 (AllowTransparency, WindowStyle = None)에 문제가 있습니다. DragMove() 메서드는 잘 작동하지만 윈도우를 최대화하거나 Windows 7 Aero Snap에 의해 자동으로 최대화되면이 메서드가 전혀 작동하지 않습니다. 따라서 마우스 드래그로 창을 비틀고 WindowState.Normal 상태로 되돌릴 수는 없습니다. 왼쪽과 오른쪽 에어로 스냅이 잘 작동하고 문제없이 창을 스냅하고 비울 수 있습니다. 그러나 최대화했을 때 Win + Down 조합을 제외하고는 아무 것도 작동하지 않습니다. 어쩌면 누군가가이 문제를 해결하는 방법을 알고 있거나 Aero Snap 기능을 사용하여 맞춤 윈도우의 적절한 DragMove를 수행 할 수있는 다른 방법을 어디에서 찾을 수 있습니까?DragMove() 및 Maximize

답변

12

내 방법입니다. 수 있도록 그것을 시도 짧은)))

private void InitHeader() 
{ 
    var border = Find<Border>("borderHeader"); 
    var restoreIfMove = false; 

    border.MouseLeftButtonDown += (s, e) => 
    { 
     if (e.ClickCount == 2) 
     { 
      if ((ResizeMode == ResizeMode.CanResize) || 
       (ResizeMode == ResizeMode.CanResizeWithGrip)) 
      { 
       SwitchState(); 
      } 
     } 
     else 
     { 
      if (WindowState == WindowState.Maximized) 
      { 
       restoreIfMove = true; 
      } 

      DragMove(); 
     } 
    }; 
    border.MouseLeftButtonUp += (s, e) => 
    { 
     restoreIfMove = false; 
    }; 
    border.MouseMove += (s, e) => 
    { 
     if (restoreIfMove) 
     { 
      restoreIfMove = false; 
      var mouseX = e.GetPosition(this).X; 
      var width = RestoreBounds.Width; 
      var x = mouseX - width/2; 

      if (x < 0) 
      { 
       x = 0; 
      } 
      else 
      if (x + width > screenSize.X) 
      { 
       x = screenSize.X - width; 
      } 

      WindowState = WindowState.Normal; 
      Left = x; 
      Top = 0; 
      DragMove(); 
     } 
    }; 
} 

private void SwitchState() 
{ 
    switch (WindowState) 
    { 
     case WindowState.Normal: 
     { 
      WindowState = WindowState.Maximized; 
      break; 
     } 
     case WindowState.Maximized: 
     { 
      WindowState = WindowState.Normal; 
      break; 
     } 
    } 
} 

(내가

+0

굉장! 고마워요! –

+0

@groaner 당신이 사용한 screenSize 네이티브 메소드를 가리킬 수 있습니까? – egfconnor

9

Groaner의 솔루션은 기본 모니터가 가장 왼쪽하지 특히 ​​경우, 다중 모니터 설정이 제대로 작동하지 않습니다) 기본 방법을 사용하여 화면 크기를 얻을 수 있습니다.

다음은 단일 또는 다중 모니터 설정을 올바르게 처리 한 내 솔루션입니다. 이 코드에서 'rctHeader'는 XAML에 정의 된 Rectangle입니다. 나는이 블로그 포스트를 작성했습니다

private bool mRestoreIfMove = false; 


    public MainWindow() 
    { 
     InitializeComponent(); 
    } 


    private void SwitchWindowState() 
    { 
     switch (WindowState) 
     { 
      case WindowState.Normal: 
       { 
        WindowState = WindowState.Maximized; 
        break; 
       } 
      case WindowState.Maximized: 
       { 
        WindowState = WindowState.Normal; 
        break; 
       } 
     } 
    } 


    private void rctHeader_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
    { 
     if (e.ClickCount == 2) 
     { 
      if ((ResizeMode == ResizeMode.CanResize) || (ResizeMode == ResizeMode.CanResizeWithGrip)) 
      { 
       SwitchWindowState(); 
      } 

      return; 
     } 

     else if (WindowState == WindowState.Maximized) 
     { 
      mRestoreIfMove = true; 
      return; 
     } 

     DragMove(); 
    } 


    private void rctHeader_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
    { 
     mRestoreIfMove = false; 
    } 


    private void rctHeader_MouseMove(object sender, MouseEventArgs e) 
    { 
     if (mRestoreIfMove) 
     { 
      mRestoreIfMove = false; 

      double percentHorizontal = e.GetPosition(this).X/ActualWidth; 
      double targetHorizontal = RestoreBounds.Width * percentHorizontal; 

      double percentVertical = e.GetPosition(this).Y/ActualHeight; 
      double targetVertical = RestoreBounds.Height * percentVertical; 

      WindowState = WindowState.Normal; 

      POINT lMousePosition; 
      GetCursorPos(out lMousePosition); 

      Left = lMousePosition.X - targetHorizontal; 
      Top = lMousePosition.Y - targetVertical; 

      DragMove(); 
     } 
    } 



    [DllImport("user32.dll")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool GetCursorPos(out POINT lpPoint); 


    [StructLayout(LayoutKind.Sequential)] 
    public struct POINT 
    { 
     public int X; 
     public int Y; 

     public POINT(int x, int y) 
     { 
      this.X = x; 
      this.Y = y; 
     } 
    } 


} 
4

WPF에서 내가보기 엔 당신의 Window.DragMove 전에 창을 복원 할 때 Control.PointToScreen를 사용하는 것이 좋습니다 것입니다. PointToScreen은 또한 여러 모니터 설정을 처리합니다. 이렇게하면 다음에 대한 복원이 간단 해집니다.

+0

이 솔루션은 완벽하게, 정확히 내가 찾고있는 솔루션입니다. 공유해 주셔서 감사합니다. – Al0x

+0

다른 솔루션과 비교하여 가장 잘 작동하고 있습니다 - 사소한 결함이 있지만 그럼에도 불구하고 실제로 작동합니다. –

2

다른 대답은 조금 늦었지만 코드는 간단하여 여기에 설명하겠습니다. 남자들은 왼쪽과 오른쪽 스냅이 잘 동작하지만 윈도우가 최대화되거나 화면 상단 경계에 스냅되어 최대화되면 DragMove 메서드가 작동하지 않습니다!


그냥이 등을 드래그 할 요소에 MOUSE_DOWN 이벤트를 처리 :

private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    if (WindowState == WindowState.Maximized) 
    { 
     var point = PointToScreen(e.MouseDevice.GetPosition(this)); 

     if (point.X <= RestoreBounds.Width/2) 
      Left = 0; 

     else if (point.X >= RestoreBounds.Width) 
      Left = point.X - (RestoreBounds.Width - (this.ActualWidth - point.X)); 

     else 
      Left = point.X - (RestoreBounds.Width/2); 

     Top = point.Y - (((FrameworkElement)sender).ActualHeight/2); 
     WindowState = WindowState.Normal; 
    } 
    DragMove(); 
} 

을 나는 희망 누군가를하는 데 도움이!

+0

가끔은 창문이 정상 상태로 돌아 오지만 실제로는 자극적 인 마우스에 고정되지 않습니다. –

관련 문제