2014-01-06 76 views
10

有兩個問題與WPF窗口時,WindowStyle =無選項時使用。與WindowStyle =無正確最大化WPF窗口

  1. 窗口最大化時覆蓋任務欄。
  2. 一旦最大化,窗口不能被拖動到最大化。

如何這些問題得到糾正? 最好不使用Windows.Forms。

回答

26

在線還有其他的這些問題的答案。然而,他們都沒有考慮解決方案如何在多臺顯示器上進行設置。特別是如果主監視器不是設置中最左邊的那個。

我設計這個代碼考慮到單個和多個監視器設置。

這個解決方案也沒有而不是引入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; 
     } 
} 
+5

+1不使用蹩腳的WinForms東西 –

+1

尼斯一個,謝謝,我使用相同的代碼讓我的窗口正常工作,羞微軟不能添加一個選項來自動執行此操作。 +1 – JustAPleb

+0

這種方法使MinWidth和MinHeigth無用。任何解決方法? – SepehrM

4

我有一個很好的快速和骯髒的解決方案。試試下面的代碼時,最大限度地提高您無邊框窗口:

if (WindowState == WindowState.Normal) 
{ 
     WindowStyle = WindowStyle.SingleBorderWindow; 
     WindowState = WindowState.Maximized; 
     WindowStyle = WindowStyle.None; 
} 

關鍵是要設置WindowStyleSingleBorderWindow然後最大化窗口,設置回None

+1

只要您不使用AllowTransparency = true –

2

這樣一個不錯的代碼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); 
    } 

希望這有助於...

0

如果只使用一臺顯示器的另一個簡單的辦法是設置窗口的最大高度。 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; 
    } 
} 
+0

現在我發現MaxHeight的最佳值不取決於ResizeBorderThickness。在我的情景中,MaxHeight的最優值是MaximizedPrimaryScreenHeight - 10。 – zznobody