有兩個問題與WPF窗口時,WindowStyle =無選項時使用。與WindowStyle =無正確最大化WPF窗口
- 窗口最大化時覆蓋任務欄。
- 一旦最大化,窗口不能被拖動到最大化。
如何這些問題得到糾正? 最好不使用Windows.Forms。
有兩個問題與WPF窗口時,WindowStyle =無選項時使用。與WindowStyle =無正確最大化WPF窗口
如何這些問題得到糾正? 最好不使用Windows.Forms。
在線還有其他的這些問題的答案。然而,他們都沒有考慮解決方案如何在多臺顯示器上進行設置。特別是如果主監視器不是設置中最左邊的那個。
我設計這個代碼考慮到單個和多個監視器設置。
這個解決方案也沒有而不是引入Windows.Forms作爲參考,它使用了未經管理的調用。
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Background="AliceBlue" WindowStyle="None" Height="350" Width="525" SourceInitialized="Window_SourceInitialized">
<Grid>
<Rectangle Name="rctHeader" Height="40" VerticalAlignment="Top" Fill="CadetBlue" PreviewMouseLeftButtonDown="rctHeader_PreviewMouseLeftButtonDown" PreviewMouseLeftButtonUp="rctHeader_PreviewMouseLeftButtonUp" PreviewMouseMove="rctHeader_PreviewMouseMove"/>
</Grid>
</Window>
代碼隱藏
using System.Runtime.InteropServices;
using System.Windows.Interop;
private bool mRestoreIfMove = false;
public MainWindow()
{
InitializeComponent();
}
void Window_SourceInitialized(object sender, EventArgs e)
{
IntPtr mWindowHandle = (new WindowInteropHelper(this)).Handle;
HwndSource.FromHwnd(mWindowHandle).AddHook(new HwndSourceHook(WindowProc));
}
private static System.IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case 0x0024:
WmGetMinMaxInfo(hwnd, lParam);
break;
}
return IntPtr.Zero;
}
private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam)
{
POINT lMousePosition;
GetCursorPos(out lMousePosition);
IntPtr lPrimaryScreen = MonitorFromPoint(new POINT(0, 0), MonitorOptions.MONITOR_DEFAULTTOPRIMARY);
MONITORINFO lPrimaryScreenInfo = new MONITORINFO();
if (GetMonitorInfo(lPrimaryScreen, lPrimaryScreenInfo) == false)
{
return;
}
IntPtr lCurrentScreen = MonitorFromPoint(lMousePosition, MonitorOptions.MONITOR_DEFAULTTONEAREST);
MINMAXINFO lMmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
if (lPrimaryScreen.Equals(lCurrentScreen) == true)
{
lMmi.ptMaxPosition.X = lPrimaryScreenInfo.rcWork.Left;
lMmi.ptMaxPosition.Y = lPrimaryScreenInfo.rcWork.Top;
lMmi.ptMaxSize.X = lPrimaryScreenInfo.rcWork.Right - lPrimaryScreenInfo.rcWork.Left;
lMmi.ptMaxSize.Y = lPrimaryScreenInfo.rcWork.Bottom - lPrimaryScreenInfo.rcWork.Top;
}
else
{
lMmi.ptMaxPosition.X = lPrimaryScreenInfo.rcMonitor.Left;
lMmi.ptMaxPosition.Y = lPrimaryScreenInfo.rcMonitor.Top;
lMmi.ptMaxSize.X = lPrimaryScreenInfo.rcMonitor.Right - lPrimaryScreenInfo.rcMonitor.Left;
lMmi.ptMaxSize.Y = lPrimaryScreenInfo.rcMonitor.Bottom - lPrimaryScreenInfo.rcMonitor.Top;
}
Marshal.StructureToPtr(lMmi, lParam, true);
}
private void SwitchWindowState()
{
switch (WindowState)
{
case WindowState.Normal:
{
WindowState = WindowState.Maximized;
break;
}
case WindowState.Maximized:
{
WindowState = WindowState.Normal;
break;
}
}
}
private void rctHeader_PreviewMouseLeftButtonDown(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_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
mRestoreIfMove = false;
}
private void rctHeader_PreviewMouseMove(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);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr MonitorFromPoint(POINT pt, MonitorOptions dwFlags);
enum MonitorOptions : uint
{
MONITOR_DEFAULTTONULL = 0x00000000,
MONITOR_DEFAULTTOPRIMARY = 0x00000001,
MONITOR_DEFAULTTONEAREST = 0x00000002
}
[DllImport("user32.dll")]
static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MINMAXINFO
{
public POINT ptReserved;
public POINT ptMaxSize;
public POINT ptMaxPosition;
public POINT ptMinTrackSize;
public POINT ptMaxTrackSize;
};
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class MONITORINFO
{
public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
public RECT rcMonitor = new RECT();
public RECT rcWork = new RECT();
public int dwFlags = 0;
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left, Top, Right, Bottom;
public RECT(int left, int top, int right, int bottom)
{
this.Left = left;
this.Top = top;
this.Right = right;
this.Bottom = bottom;
}
}
我有一個很好的快速和骯髒的解決方案。試試下面的代碼時,最大限度地提高您無邊框窗口:
if (WindowState == WindowState.Normal)
{
WindowStyle = WindowStyle.SingleBorderWindow;
WindowState = WindowState.Maximized;
WindowStyle = WindowStyle.None;
}
關鍵是要設置WindowStyle
到SingleBorderWindow
然後最大化窗口,設置回None
。
只要您不使用AllowTransparency = true –
這樣一個不錯的代碼leebickmtu!
我曾與多個監視器有點問題,在Windows 10:因爲是每個屏幕上任務欄,如果最大化的輔助屏幕任務欄他成爲隱藏在你的窗口。
我只是修改了一下這個方法,才能從任何屏幕上的相對位置:
private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam)
{
POINT lMousePosition;
GetCursorPos(out lMousePosition);
IntPtr lCurrentScreen = MonitorFromPoint(lMousePosition, MonitorOptions.MONITOR_DEFAULTTONEAREST);
MINMAXINFO lMmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
MONITORINFO lCurrentScreenInfo = new MONITORINFO();
if (GetMonitorInfo(lCurrentScreen, lCurrentScreenInfo) == false)
{
return;
}
//Position relative pour notre fenêtre
lMmi.ptMaxPosition.X = lCurrentScreenInfo.rcWork.Left - lCurrentScreenInfo.rcMonitor.Left;
lMmi.ptMaxPosition.Y = lCurrentScreenInfo.rcWork.Top - lCurrentScreenInfo.rcMonitor.Top;
lMmi.ptMaxSize.X = lCurrentScreenInfo.rcWork.Right - lCurrentScreenInfo.rcWork.Left;
lMmi.ptMaxSize.Y = lCurrentScreenInfo.rcWork.Bottom - lCurrentScreenInfo.rcWork.Top;
Marshal.StructureToPtr(lMmi, lParam, true);
}
希望這有助於...
如果只使用一臺顯示器的另一個簡單的辦法是設置窗口的最大高度。 System.Windows.SystemParameters類提供了一些有用的值,例如PrimaryScreenHeight或MaximizedPrimaryScreenHeight。
在我的示例代碼中,我使用MaximizedPrimaryScreenHeight覈減我在WindowChrome設置ResizeBorderThickness。
using System.Windows;
using System.Windows.Shell;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Thickness resizeBorderThickness = WindowChrome.GetWindowChrome(this).ResizeBorderThickness;
this.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight - resizeBorderThickness.Top - resizeBorderThickness.Bottom;
}
}
現在我發現MaxHeight的最佳值不取決於ResizeBorderThickness。在我的情景中,MaxHeight的最優值是MaximizedPrimaryScreenHeight - 10。 – zznobody
+1不使用蹩腳的WinForms東西 –
尼斯一個,謝謝,我使用相同的代碼讓我的窗口正常工作,羞微軟不能添加一個選項來自動執行此操作。 +1 – JustAPleb
這種方法使MinWidth和MinHeigth無用。任何解決方法? – SepehrM