使用WPF Window.WindowStyle = none保持任务栏可见性

时间:2012-03-16 14:38:08

标签: wpf window taskbar window-style

我正在开发一个WPF应用程序。我完全摆脱了标准的Windows边框,并通过将WindowStyle设置为None并将allowsTransparency设置为true来创建我自己的边框。唯一的问题是,当窗口最大化时,它会填满整个屏幕,覆盖任务栏。有没有办法在没有这种情况下创建自己的边界?

3 个答案:

答案 0 :(得分:1)

使用方法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;
    }
}

答案 1 :(得分:1)

更简单的方法,在你的窗口构造函数中设置

this.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;

并且窗口不会覆盖任务栏。

答案 2 :(得分:0)

看看Microsoft.Windows.Shell。它为你做了所有这一切。追踪它有点令人沮丧。我认为最好使用的是latest ribbon control附带的内容。