Click here to Skip to main content
14,491,065 members

Taskbar with Window Maximized and WindowState to None in WPF

Rate this:
5.00 (3 votes)
Please Sign up or sign in to vote.
5.00 (3 votes)
31 Jan 2020CPOL
Solution to an issue when Taskbar needs to be shown even though the application should be maximized

Introduction

Say you want your WPF application to have no Title bar, and will be maximized to Full Screen, what do you think of first? It's the easiest to do.

  • Set WindowStyle to Maximized: By this, the Window will not show up any title bar. The window style will be transformed to a Box with border in it.
  • Set WindowState to None: By this, the window will be maximized to the whole screen and will show only the window and nothing else.

As I say, it hides the whole screen, it means it even will not show up the Taskbar or any external gadgets applied to your desktop if it is not set to Always on Top attribute.

Yes, this is the problem that I faced recently, when people wanted me to show the TaskBar even though the application should be maximized.

Background

Is it a Bug?

If I am not wrong, WPF builds application based on the Screen Resolution. It produces DPI independent pixels. If you specify it to be full screen, it first gets the resolution of the screen, and draws the pixel based on its own algorithm. Hence, when you specify it to Maximized, it takes up the whole screen, as otherwise some portion of the screen will be hidden outside the range of the boundary.

When you restore a WPF screen, it will also recalculate the work area based on the distance between the resolution boundaries and resize itself accordingly. Now, do you think Microsoft should really have an alternative state which shows up the Taskbar as it does with normal windows? I think yes.

Using the Code

The Solution

As I needed to do this, I have just tried out few workarounds to this myself.

I have to use this code:

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

    return (System.IntPtr)0;
}

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

    // Adjust the maximized size and position to fit the work area of the correct monitor
    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);
}

The call to API WmGetMinMaxInfo gets you the size of Maximize window for the current desktop.

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

The call to GetMonitorInfo gets you a MONITORINFO object and if you see the code carefully, it actually positions the window in such a way that it absolutely resizes itself to the height and width of the rectangular area.

A better way to get the handle to the window is to use the SourceInitialized event. This would also avoid calling ApplyTemplate every time the window template is changed on the fly.

public override void OnApplyTemplate()
       {
           System.IntPtr handle = (new WinInterop.WindowInteropHelper(this)).Handle;
           WinInterop.HwndSource.FromHwnd(handle).AddHook
                                  (new WinInterop.HwndSourceHook(WindowProc));
       }

To call this method, I can use SourceInitialized event which will eventually be called whenever the WindowState is modified.

win.SourceInitialized += new EventHandler(win_SourceInitialized);

void win_SourceInitialized(object sender, EventArgs e)
{
    System.IntPtr handle = (new WinInterop.WindowInteropHelper(this)).Handle;
    WinInterop.HwndSource.FromHwnd(handle).AddHook(new WinInterop.HwndSourceHook(WindowProc));
}

Set Properties for Your Window

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

Go to your code and just resize your window based on PrimaryScreen width and height. Also make sure you do set the Left and Top of the window as well.

this.Width = System.Windows.SystemParameters.WorkArea.Width;
this.Height = System.Windows.SystemParameters.WorkArea.Height;
this.Left = 0;
this.Top = 0;
this.WindowState = WindowState.Normal;

Normal will ensure that the default behaviour of the window is overridden and also makes the Taskbar reappear.

History

  • 31st January, 2020: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Deepak_Sharma_20
Software Developer (Senior) Systweak
India India
Hello, I am Deepak Sharma. My Passion always revolves around Microsoft Technologies. I’m a total fun geek you might not know about. I’m currently working as a senior software engineer in the area of Microsoft .NET technologies , Web Services and Desktop Application.Has a very good skill over C#, XAML, Silver light, WPF and Share Point. He never hesitates to take up challenges & work on the latest technologies in Microsoft platform. He has the ability to give a customer satisfaction.

Comments and Discussions

 
QuestionMONITORINFO should be passed by reference Pin
W. Kleinschmit3-Feb-20 3:21
MemberW. Kleinschmit3-Feb-20 3:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Tip/Trick
Posted 31 Jan 2020

Stats

10.4K views
2 bookmarked