2013-02-21 4 views
2

Во-первых, здесь является XAML код самого окна:Window и MinHeight оба игнорируются при повторной калибровке с ResizeGrip

<!-- Window Main --> 
<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Name="Window_Main" x:Class="WPF_Test.General_Window" 
    Title="General_Window" Height="500" Width="1000" BorderThickness="30" ResizeMode="CanResizeWithGrip" AllowsTransparency="True" WindowStyle="None" StateChanged="Window_Main_StateChanged"> 
<!-- Effects --> 
<Window.Effect> 
    <DropShadowEffect x:Name="Border_Effect" ShadowDepth="0" BlurRadius="30" Direction="0" Opacity="0.5"/> 
</Window.Effect> 
<!-- Border Main --> 
<Border x:Name="Border_Main" BorderBrush="Gray" BorderThickness="1"> 
    <!-- Panel Main --> 
    <DockPanel x:Name="Panel_Main"> 
     <DockPanel x:Name="Panel_Title" Height="25" LastChildFill="False" Background="#FFEEEEEE" MouseDown="Panel_Title_MouseDown" VerticalAlignment="Top" DockPanel.Dock="Top"> 

     </DockPanel> 
     <DockPanel x:Name="Panel_Secondary" LastChildFill="true" Background="#FFEEEEEE"/> 
    </DockPanel> 
</Border> 

Здесь является C# код конструктора, который окно, в котором я четко определить минимальные размеры окна, но они по-прежнему игнорируются при повторной калибровке:

public void Window_Init() 
    { 

     Window_Main.MinHeight = Window_Minimum_Height + Window_Thickness * 2; 
     Window_Main.MinWidth = Window_Minimum_Width + Window_Thickness * 2; 
     Window_Main.BorderThickness = new Thickness(Window_Thickness); 
    } 

Так что, когда я повторно проклейки окна с помощью ResizeGrip (предоставлено имуществом CanResizeWithGrip), само окно остановится, чтобы изменить размер в тот момент, когда он достигнет минимальной ширины и высоты. Хотя область рендеринга, которая полностью содержит окно, может быть изменена до меньших размеров, поэтому она выглядит как обрезанное изображение окна на рабочем столе.

ответ

4

Я разрешил ошибку. Вы можете использовать режущий инструмент захвата или создать свои собственные элементы управления размером, используя событие OnMouseDown, чтобы отправить сообщение HWND, чтобы изменить размер окна, пока оно не пройдет минимальные размеры, которые вы предварительно определили для окна. Этот код ограничивает размер окна, когда максимизирует, а также гарантирует, что окно никогда не будет находиться за пределами экрана или отображено над панелью задач.

Это должно быть в нижней части кода MainWindow.cs:

 private const int WM_SYSCOMMAND = 0X112; 
    private HwndSource hwndSource; 
    enum SWP : uint 
    { 
     NOSIZE = 0x0001 , 
     NOMOVE = 0x0002 , 
     NOZORDER = 0x0004 , 
     NOREDRAW = 0x0008 , 
     NOACTIVATE = 0x0010 , 
     FRAMECHANGED = 0x0020 , 
     SHOWWINDOW = 0x0040 , 
     HIDEWINDOW = 0x0080 , 
     NOCOPYBITS = 0x0100 , 
     NOOWNERZORDER = 0x0200 , 
     NOSENDCHANGING = 0x0400 , 
    } 
    public override void OnApplyTemplate() 
    { 
     System.IntPtr handle = (new WindowInteropHelper(this)).Handle; 
     HwndSource.FromHwnd(handle).AddHook(new HwndSourceHook(WindowProc)); 
    } 
    private System.IntPtr WindowProc(System.IntPtr hwnd , int msg , System.IntPtr wParam , System.IntPtr lParam , ref bool handled) 
    { 
     switch (msg) 
     { 
      case 0x0024: 
       { 
        WmGetMinMaxInfo(hwnd , lParam); 
        handled = true; 
        break; 
       } 
      case 0x0046: 
       { 
        WINDOWPOS pos = (WINDOWPOS)Marshal.PtrToStructure(lParam , typeof(WINDOWPOS)); 
        if ((pos.flags & (int)(SWP.NOMOVE)) != 0) 
        { 
         return IntPtr.Zero; 
        } 

        Window wnd = (Window)HwndSource.FromHwnd(hwnd).RootVisual; 
        if (wnd == null) 
        { 
         return IntPtr.Zero; 
        } 

        bool changedPos = false; 
        if (pos.cx < MinWidth) { pos.cx = (int)MinWidth; changedPos = true; } 
        if (pos.cy < MinHeight) { pos.cy = (int)MinHeight; changedPos = true; } 
        if (!changedPos) 
        { 
         return IntPtr.Zero; 
        } 

        Marshal.StructureToPtr(pos , lParam , true); 
        handled = true; 
        break; 
       } 
     } 
     return (System.IntPtr)0; 
    } 
    private void WmGetMinMaxInfo(System.IntPtr hwnd , System.IntPtr lParam) 
    { 
     MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam , typeof(MINMAXINFO)); 
     int MONITOR_DEFAULTTONEAREST = 0x00000002; 
     System.IntPtr monitor = MonitorFromWindow(hwnd , MONITOR_DEFAULTTONEAREST); 
     if (monitor != System.IntPtr.Zero) 
     { 
      MONITORINFO monitorInfo = new MONITORINFO(); 
      GetMonitorInfo(monitor , monitorInfo); 
      RECT rcWorkArea = monitorInfo.rcWork; 
      RECT rcMonitorArea = monitorInfo.rcMonitor; 
      mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left); 
      mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top); 
      mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left); 
      mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top); 
     } 
     Marshal.StructureToPtr(mmi , lParam , true); 
    } 
    [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 , Pack = 0)] 
    public struct RECT 
    { 
     public int left; 
     public int top; 
     public int right; 
     public int bottom; 
     public static readonly RECT Empty = new RECT(); 
     public int Width 
     { 
      get { return Math.Abs(right - left); } 
     } 
     public int Height 
     { 
      get { return bottom - top; } 
     } 
     public RECT(int left , int top , int right , int bottom) 
     { 
      this.left = left; 
      this.top = top; 
      this.right = right; 
      this.bottom = bottom; 
     } 
     public RECT(RECT rcSrc) 
     { 
      this.left = rcSrc.left; 
      this.top = rcSrc.top; 
      this.right = rcSrc.right; 
      this.bottom = rcSrc.bottom; 
     } 
     public bool IsEmpty 
     { 
      get 
      { 
       return left >= right || top >= bottom; 
      } 
     } 
     public override string ToString() 
     { 
      if (this == RECT.Empty) { return "RECT {Empty}"; } 
      return "RECT { left : " + left + "/top : " + top + "/right : " + right + "/bottom : " + bottom + " }"; 
     } 
     public override bool Equals(object obj) 
     { 
      if (!(obj is Rect)) { return false; } 
      return (this == (RECT)obj); 
     } 
     public override int GetHashCode() 
     { 
      return left.GetHashCode() + top.GetHashCode() + right.GetHashCode() + bottom.GetHashCode(); 
     } 
     public static bool operator ==(RECT rect1 , RECT rect2) 
     { 
      return (rect1.left == rect2.left && rect1.top == rect2.top && rect1.right == rect2.right && rect1.bottom == rect2.bottom); 
     } 
     public static bool operator !=(RECT rect1 , RECT rect2) 
     { 
      return !(rect1 == rect2); 
     } 
    } 
    [DllImport("user32")] 
    internal static extern bool GetMonitorInfo(IntPtr hMonitor , MONITORINFO lpmi); 
    [DllImport("User32")] 
    internal static extern IntPtr MonitorFromWindow(IntPtr handle , int flags); 
    [StructLayout(LayoutKind.Sequential)] 
    internal struct WINDOWPOS 
    { 
     public IntPtr hwnd; 
     public IntPtr hwndInsertAfter; 
     public int x; 
     public int y; 
     public int cx; 
     public int cy; 
     public int flags; 
    } 
    private void InitializeWindowSource(object sender , EventArgs e) 
    { 
     hwndSource = PresentationSource.FromVisual((Visual)sender) as HwndSource; 
    } 
    public enum ResizeDirection 
    { 
     Left = 1 , 
     Right = 2 , 
     Top = 3 , 
     TopLeft = 4 , 
     TopRight = 5 , 
     Bottom = 6 , 
     BottomLeft = 7 , 
     BottomRight = 8 , 
    } 
    [DllImport("user32" , CharSet = CharSet.Auto)] 
    private static extern IntPtr SendMessage(IntPtr hWnd , uint Msg , IntPtr wParam , IntPtr lParam); 
    private void ResizeWindow(ResizeDirection direction) 
    { 
     SendMessage(hwndSource.Handle , WM_SYSCOMMAND , (IntPtr)(61440 + direction) , IntPtr.Zero); 

    } 

И не забудьте добавить эту строку в конструкторе вашего окна, в противном случае ничего не будет работать:

SourceInitialized += new EventHandler(InitializeWindowSource);