2012-03-16 17 views
1

我正在開發一個WPF應用程序。我完全擺脫了標準的窗口邊框,並通過將WindowStyle設置爲None和AllowsTransparency爲true來創建我自己的窗口。唯一的問題是,當窗口最大化時,它會填滿整個屏幕,覆蓋任務欄。有沒有什麼辦法可以創建自己的邊界而不發生這種情況?使用WPF維護任務欄可見性Window.WindowStyle =無

回答

0

使用方法CompatibilityMaximizedNoneWindow。

using System; 
using System.Drawing; 
using System.Runtime.InteropServices; 
using System.Windows; 
using System.Windows.Interop; 

using Point = System.Drawing.Point; 

internal static class WindowExtensions 
{ 
    public static PointF StandartDPI = new PointF(96f, 96f); 
    private static PointF? currentDpi = null; 
    public static float WidthZoom {get{return CurrentDPI.X/ StandartDPI.X; } } 
    public static float HeigthZoom { get { return CurrentDPI.Y/StandartDPI.Y; } } 

    public static PointF CurrentDPI 
    { 
     get 
     { 
      if (!currentDpi.HasValue) 
      { 
       var wiHelper = new WindowInteropHelper(App.Current.MainWindow); 
       Graphics g = Graphics.FromHwnd(wiHelper.Handle); 
       try 
       { 
        currentDpi = new PointF(g.DpiX, g.DpiY); 
       } 
       catch 
       { 
        currentDpi = StandartDPI; 
       } 
       finally 
       { 
        g.Dispose(); 
       } 
      } 
      return currentDpi.Value; 
     } 
    } 


    public static Window GetWindowFromTemplate(this object templateFrameworkElement) 
    { 
     var window = ((FrameworkElement)templateFrameworkElement).TemplatedParent as Window; 
     return window; 
    } 

    private static int minWidth; 
    private static int minHeight; 

    public static void CompatibilityMaximizedNoneWindow(this Window window) 
    { 
     var wiHelper = new WindowInteropHelper(window); 
     minHeight = (int)window.MinHeight; 
     minWidth = (int)window.MinWidth; 

     var handle = wiHelper.Handle; 
     var hwndSource = HwndSource.FromHwnd(handle); 
     if (hwndSource != null) 
     { 
      hwndSource.AddHook(CompatibilityMaximizedNoneWindowProc); 
     } 
    } 

    [DllImport("user32")] 
    private static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);[DllImport("user32")] 
    private static extern IntPtr MonitorFromWindow(IntPtr handle, int flags); 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)] 
    private 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)] 
    private struct RECT 
    { 
     public int left; 
     public int top; 
     public int right; 
     public int bottom; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct POINT 
    { 
     public int x; 
     public int y; 

     public POINT(int x, int y) 
     { 
      this.x = x; this.y = y; 
     } 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct MINMAXINFO 
    { 
     public POINT ptReserved; 
     public POINT ptMaxSize; 
     public POINT ptMaxPosition; 
     public POINT ptMinTrackSize; 
     public POINT ptMaxTrackSize; 
    } 

    private static IntPtr CompatibilityMaximizedNoneWindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
    { 
     const int WM_GETMINMAXINFO = 0x0024; 
     const int MONITOR_DEFAULTTONEAREST = 0x00000002; 
     switch (msg) 
     { 
      case WM_GETMINMAXINFO: 
       var mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); 
       var monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); 
       if (monitor != IntPtr.Zero) 
       { 
        var monitorInfo = new MONITORINFO(); 
        GetMonitorInfo(monitor, monitorInfo); 
        var rcWorkArea = monitorInfo.rcWork; 
        var 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); 
        //Hack для ограничения минимальных размеров окна 
        mmi.ptMinTrackSize.x = (int)(minWidth*WidthZoom); 
        mmi.ptMinTrackSize.y = (int)(minHeight*HeigthZoom); 
        //Hack для нормальной работы всплывающей панели задач 
        var taskbar = new TaskbarInfo(); 
        if (taskbar.AutoHide) 
        { 
         switch (taskbar.Position) 
         { 
          case TaskbarInfo.TaskbarPosition.Top: 
           mmi.ptMaxPosition.y++; 
           mmi.ptMaxSize.y--; 
           break; 
          case TaskbarInfo.TaskbarPosition.Bottom: 
           mmi.ptMaxPosition.y--; 
           mmi.ptMaxSize.y--; 
           break; 
          case TaskbarInfo.TaskbarPosition.Left: 
           mmi.ptMaxPosition.x++; 
           mmi.ptMaxSize.x--; 
           break; 
          case TaskbarInfo.TaskbarPosition.Right: 
           mmi.ptMaxPosition.x--; 
           mmi.ptMaxSize.x--; 
           break; 
         } 
        } 
       } 
       Marshal.StructureToPtr(mmi, lParam, true); handled = true; break; 
     } 
     return (IntPtr)0; 
    } 
} 
0

看看Microsoft.Windows.Shell。它爲你做了所有這些工作。跟蹤它有點令人沮喪。我認爲最好使用的是latest ribbon control

1

更簡單的方法,在窗口的構造函數只設置

this.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight; 

,窗口將不包括任務欄。