WPFのカスタムウィンドウ(AllowTransparency、WindowStyle = None)に問題があります。DragMove()メソッドは正常に機能しますが、ウィンドウを最大化するか、Windows 7 Aeroスナップによって自動的に最大化すると、このメソッドはまったく機能しません。そのため、マウスドラッグでウィンドウのスナップを解除して、その状態をWindowState.Normalに戻すことはできません。左右のエアロスナップはうまく機能し、問題なくウィンドウをスナップおよびスナップ解除できます。しかし、最大化すると、Win+Downの組み合わせ以外は機能しません。誰かがこの問題を解決する方法を知っているかもしれませんし、Aero Snap機能が機能するカスタムウィンドウの適切なDragMoveを実行する他の方法をどこで見つけることができますか?
6 に答える
これが私の方法です。短くしてみてください)))
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;
}
}
}
(screenSize を取得するには、ネイティブ メソッドを使用します)
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;
}
}
}
WPF では、 Window.DragMoveの前にウィンドウを復元するときにControl.PointToScreenを使用することを強くお勧めします。PointToScreen は、複数のモニターのセットアップも処理します。これにより、以下への復元が簡素化されます。
private void OnMouseLeftButtonDown( object sender, MouseButtonEventArgs e )
{
if( e.ClickCount == 2 )
{
if( ResizeMode != ResizeMode.CanResize &&
ResizeMode != ResizeMode.CanResizeWithGrip )
{
return;
}
WindowState = WindowState == WindowState.Maximized
? WindowState.Normal
: WindowState.Maximized;
}
else
{
mRestoreForDragMove = WindowState == WindowState.Maximized;
DragMove();
}
}
private void OnMouseMove( object sender, MouseEventArgs e )
{
if( mRestoreForDragMove )
{
mRestoreForDragMove = false;
var point = PointToScreen( e.MouseDevice.GetPosition( this ) );
Left = point.X - ( RestoreBounds.Width * 0.5 );
Top = point.Y;
WindowState = WindowState.Normal;
DragMove();
}
}
private void OnMouseLeftButtonUp( object sender, MouseButtonEventArgs e )
{
mRestoreForDragMove = false;
}
private bool mRestoreForDragMove;
別の回答には少し遅れましたが、私のコードはより単純だったので、ここに記載します。左右のスナップは正常に機能しますが、ウィンドウが最大化されているか、画面の上限にスナップして最大化すると、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();
}
誰かの役に立てば幸いです!
私はこれについてブログ記事を書きました:
http://dragablz.net/2014/12/16/getting-windows-snap-to-play-with-wpf-borderless-windows/