Maximizing window (with WindowStyle=None) considering Taskbar

Sainuu ... for people wondering what that is - its HI in Mongolian.. So here I am in Mongolia on my vacation and its going great... My blog will be neglected by me for the next couple of weeks..:)

Ok now back to WPF.. One interesting problem that comes to mind is the Window occupying all screen space on Maximizing when the WindowStyle is set to None. So this means that even if we do have the taskbar visible the window would appear on top of that. This would not happen in the case of the normal window with the TitleBar. To get this scenario working, we would have to include a small piece of code (by Josh Zana) in the Window.

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

        private static System.IntPtr WindowProc(
              System.IntPtr hwnd,
              int msg,
              System.IntPtr wParam,
              System.IntPtr lParam,
              ref bool handled)
        {
            switch (msg)
            {
                case 0x0024:/* WM_GETMINMAXINFO */
                    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);
        }

As seen above the code basically handles the WM_GETMINMAXINFO message. The sample project code is also included. Have Fun. :)

 

Update: A better way to get the handle to the window is to use the SourceInitialized event. This would also avoid calling ApplyTemplate everytime the window template is changedon the fly. Thanks to Hamid for pointing out the better solution. The attached project is now updated.

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));
}

WindowsApplication5.zip