2014-01-06 51 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