Question

I have created a custom window in WPF using the Microsoft.Windows.Shell DLL and .NET 4.0.

The problem is that if the taskbar is set to autohide and the window is maximized, the window completely covers the taskbar. I have tried several different solutions (the first few Google results) but none actually work.

The method the MahApps.Metro package uses will set the window 1px off of the bottom of the screen if the taskbar is not autohidden.

I need a solution that

  1. Works in .NET 4.0
  2. Works no matter which side the taskbar is docked to
  3. Works when the taskbar is set to both always show and autohide.
Était-ce utile?

La solution

A customized WPF window does not respect the area occupied by the task bar. In order to do this, you need support from the Win32 API.

The first method you will need is...

    [DllImport("user32.dll")]
    public static extern IntPtr MonitorFromWindow(IntPtr hwnd, int dwFlags);

The MonitorFromWindow function retrieves a handle to the display monitor that has the largest area of intersection with the bounding rectangle of a specified window. http://msdn.microsoft.com/en-us/library/windows/desktop/dd145064(v=vs.85).aspx

Set dwFlags = 2

The next one is...

    [DllImport("user32.dll")]
    public static extern bool GetMonitorInfo(HandleRef hmonitor, 
                       [In, Out] MonitorInfoEx monitorInfo);

The GetMonitorInfo function retrieves information about a display monitor. http://msdn.microsoft.com/en-us/library/windows/desktop/dd144901(v=vs.85).aspx

The MonitorInfoEx struct looks like...

    [StructLayout(LayoutKind.Sequential)]
    public class MonitorInfoEx
    {
        public int cbSize;
        public Rect rcMonitor;     
        public Rect rcWork;        
        public int dwFlags;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x20)]
        public char[] szDevice;
    }

The MONITORINFOEX structure contains information about a display monitor. http://msdn.microsoft.com/en-us/library/windows/desktop/dd145066(v=vs.85).aspx

The Rect being passed is...

    [StructLayout(LayoutKind.Sequential)]
    public struct Rect
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

Of particular interest here is that you are getting the working area in DPI at its current resolution.

Finally, you'll need the HwndSource.FromHwnd method from the Interop namespace of the PresentationCore (WPF)

Once you have all the info together, you can use CompositionTarget.TransformFromDevice to... Gets a matrix that can be used to transform coordinates from the rendering destination device to this target. http://msdn.microsoft.com/en-us/library/system.windows.media.compositiontarget.transformfromdevice.aspx

... and that will give you the dimensions you need to position your customized window such that it respects the status bar.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top