17

I need to change windows taskbar in my WPF application. For that I set WindowStyle="None", which means to disable the windows taskbar, and make custom taskbar with buttons for restoring, minimizing and closing the application. Now my problem is if the application is in maximize mode then I can't see the start menu on windows.

I found a similar question here, but when I tried this code it didn't compile. full screen mode, but don't cover the taskbar

How can I create my own taskbar and able to see the windows start menu when I maximized it? Is there a property window in xaml which can set it?

Community
  • 1
  • 1
Evgeni Velikov
  • 362
  • 3
  • 10
  • 28

7 Answers7

26

You may try this:

MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth;
Pikoh
  • 7,582
  • 28
  • 53
  • What about the case with more than 1 screens? – Valerii Mar 20 '18 at 19:54
  • 1
    @Valerii in that case, you may try with the `Screen.AllScreens` collection. You can loop that collection and access `screen.WorkingArea.Width` and `screen.WorkingArea.Height`. Let me know if that works so I can edit my answer. – Pikoh Mar 21 '18 at 07:58
  • @Pikoh The Screen class is part of `System.Windows.Forms` which is not compatible with WPF. The alternative is `SystemParameters.WorkAreaWidth` and `SystemParameters.WorkAreaHeight` which is helpful but not in multiple display scenarios unfortunately. – tkefauver Jun 08 '20 at 18:44
  • This solution did not work for multiple screens attached as extended screens. I have provided a solution below that works for any number of screens and each screen works perfectly. I have tested it with 3 (main laptop screen and two extended screens). – Umar Oct 22 '21 at 06:42
8

You can easily add the constraints on height in XAML by adding:

MaxHeight="{Binding Source={x:Static SystemParameters.MaximizedPrimaryScreenHeight}}"

into the Window's tag.

M Pavan Kumar
  • 101
  • 1
  • 2
5

Found a solution on CodeProject which may help: http://www.codeproject.com/Articles/107994/Taskbar-with-Window-Maximized-and-WindowState-to-N

WindowStyle="None"
WindowState="Maximized"
ResizeMode="NoResize"

and

this.Width = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width;
this.Height = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
this.Left = 0;
this.Top = 0;
this.WindowState = WindowState.Normal;
M. Schena
  • 2,039
  • 1
  • 21
  • 29
3

I have found a pretty neat solution for the problem in discussion here at the following link, https://codekong.wordpress.com/2010/11/10/custom-window-style-and-accounting-for-the-taskbar/

This works directly out of the box. Just added this here for reference to help anyone in near future.

None of the existing solutions here worked for multiple screens attached in Extended mode.

Pasting the provided solution here to save it from being removed from the blog,

Need to bind SourceInitialized event either from XAML or code behind,

this.SourceInitialized += new EventHandler(Window1_SourceInitialized);

While here's the source code for event callback,

void Window1_SourceInitialized(object sender, EventArgs e)
{
    WindowSizing.WindowInitialized(this);
}

Here's the code for WindowSizing.cs,

using System;
using System.Runtime.InteropServices;
using System.Windows;

namespace OfficeStyleWindowProject
{
   public static class WindowSizing
   {
    const int MONITOR_DEFAULTTONEAREST = 0x00000002;

    #region DLLImports

    [DllImport("shell32", CallingConvention = CallingConvention.StdCall)]
    public static extern int SHAppBarMessage(int dwMessage, ref APPBARDATA pData);

    [DllImport("user32", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32")]
    internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);

    [DllImport("user32")]
    internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);

    #endregion

    private static MINMAXINFO AdjustWorkingAreaForAutoHide(IntPtr monitorContainingApplication, MINMAXINFO mmi)
    {
        IntPtr hwnd = FindWindow("Shell_TrayWnd", null);
        if (hwnd == null) return mmi;
        IntPtr monitorWithTaskbarOnIt = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
        if (!monitorContainingApplication.Equals(monitorWithTaskbarOnIt)) return mmi;
        APPBARDATA abd = new APPBARDATA();
        abd.cbSize = Marshal.SizeOf(abd);
        abd.hWnd = hwnd;
        SHAppBarMessage((int)ABMsg.ABM_GETTASKBARPOS, ref abd);
        int uEdge = GetEdge(abd.rc);
        bool autoHide = System.Convert.ToBoolean(SHAppBarMessage((int)ABMsg.ABM_GETSTATE, ref abd));

        if (!autoHide) return mmi;

        switch (uEdge)
        {
            case (int)ABEdge.ABE_LEFT:
                mmi.ptMaxPosition.x += 2;
                mmi.ptMaxTrackSize.x -= 2;
                mmi.ptMaxSize.x -= 2;
                break;
            case (int)ABEdge.ABE_RIGHT:
                mmi.ptMaxSize.x -= 2;
                mmi.ptMaxTrackSize.x -= 2;
                break;
            case (int)ABEdge.ABE_TOP:
                mmi.ptMaxPosition.y += 2;
                mmi.ptMaxTrackSize.y -= 2;
                mmi.ptMaxSize.y -= 2;
                break;
           case (int)ABEdge.ABE_BOTTOM:
                mmi.ptMaxSize.y -= 2;
                mmi.ptMaxTrackSize.y -= 2;
                break;
            default:
                return mmi;
        }
        return mmi;
    }

    private static int GetEdge(RECT rc)
    {
        int uEdge = -1;
        if (rc.top == rc.left && rc.bottom > rc.right)
            uEdge = (int)ABEdge.ABE_LEFT;
        else if (rc.top == rc.left && rc.bottom < rc.right)
            uEdge = (int)ABEdge.ABE_TOP;
        else if (rc.top > rc.left)
            uEdge = (int)ABEdge.ABE_BOTTOM;
        else
            uEdge = (int)ABEdge.ABE_RIGHT;
        return uEdge;
    }

    public static void WindowInitialized(Window window)
    {
        IntPtr handle = (new System.Windows.Interop.WindowInteropHelper(window)).Handle;
        System.Windows.Interop.HwndSource.FromHwnd(handle).AddHook(new System.Windows.Interop.HwndSourceHook(WindowProc));
    }

    private static 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;
        }

        return (IntPtr)0;
    }

    private static void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
    {
        MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
        IntPtr monitorContainingApplication = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);

        if (monitorContainingApplication != System.IntPtr.Zero)
        {
            MONITORINFO monitorInfo = new MONITORINFO();
            GetMonitorInfo(monitorContainingApplication, 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);
            mmi.ptMaxTrackSize.x = mmi.ptMaxSize.x;                                                 //maximum drag X size for the window
            mmi.ptMaxTrackSize.y = mmi.ptMaxSize.y;                                                 //maximum drag Y size for the window
            mmi.ptMinTrackSize.x = 800;                                                             //minimum drag X size for the window
            mmi.ptMinTrackSize.y = 600;                                                             //minimum drag Y size for the window
            mmi = AdjustWorkingAreaForAutoHide(monitorContainingApplication, mmi);                  //need to adjust sizing if taskbar is set to autohide
        }
        Marshal.StructureToPtr(mmi, lParam, true);
    }

    public enum ABEdge
    {
        ABE_LEFT = 0,
        ABE_TOP = 1,
        ABE_RIGHT = 2,
        ABE_BOTTOM = 3
    }

    public enum ABMsg
    {
        ABM_NEW = 0,
        ABM_REMOVE = 1,
        ABM_QUERYPOS = 2,
        ABM_SETPOS = 3,
        ABM_GETSTATE = 4,
        ABM_GETTASKBARPOS = 5,
        ABM_ACTIVATE = 6,
        ABM_GETAUTOHIDEBAR = 7,
        ABM_SETAUTOHIDEBAR = 8,
        ABM_WINDOWPOSCHANGED = 9,
        ABM_SETSTATE = 10
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct APPBARDATA
    {
        public int cbSize;
        public IntPtr hWnd;
        public int uCallbackMessage;
        public int uEdge;
        public RECT rc;
        public bool lParam;
    }

    [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 POINT
    {
        public int x;
        public int y;

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

    [StructLayout(LayoutKind.Sequential, Pack = 0)]
    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }
}
}

~Umar

Umar
  • 478
  • 3
  • 10
2
WindowStyle="None" 
AllowsTransparency="True"  

and

this.Top = 0;
this.Left = 0;
this.Width = SystemParameters.WorkArea.Width;
this.Height = SystemParameters.WorkArea.Height;
Hafizul Amri
  • 2,633
  • 7
  • 28
  • 30
2

Proposed solution worked for me but still need to correct pixel to dpi setter values for window to have correct size regardless user settings:

in xaml :

WindowStyle="None" WindowState="Maximized" ResizeMode="NoResize"

in code :

public MainWindow()
{
    InitializeComponent();
    var graphics = System.Drawing.Graphics.FromHwnd(IntPtr.Zero);
    var pixelWidth = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width ;
    var pixelHeight = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
    var pixelToDPI = 96.0 / graphics.DpiX ;
    this.Width = pixelWidth * pixelToDPI;
    this.Height = pixelHeight * pixelToDPI;
    this.Left = 0;
    this.Top = 0;
    this.WindowState = WindowState.Normal;
}
Nicolas
  • 31
  • 1
1

Solution for WPF

Let's say we want to place the mainWindow of a WPF project at the bottom-right of the screen without it covering the taskBar. We'll write this:

public MainWindow()
    {
        InitializeComponent();
        // set position of window on screen
        this.Left = SystemParameters.PrimaryScreenWidth - this.Width;
        this.Top = SystemParameters.WorkArea.Bottom - this.Height;
    }

this = our object (the MainWindow) We first get to place the left parameter when we subtract our window position (left) from the PrimarySrceenWidth. Than, we do the same to get the most lower point, by subtracting the windows height from the working area of the screen bottom. The working area of the screen does not include the task bar!

enjoy!

Avri

Dr. Avri
  • 11
  • 4