Help for Tune Smithy Koch snowflake icon.gif

How to show a dialog full screen

From Tune Smithy

(Difference between revisions)
Jump to: navigation, search
Line 1: Line 1:
 +
[[C-code]]
 +
First, the problem. It is easy to show a normal window full screen, in various ways. But for a dialog created using e.g. CreateDialog, then the problem is that it normally gets created with a border and title bar. So how to show it full screen without them?
First, the problem. It is easy to show a normal window full screen, in various ways. But for a dialog created using e.g. CreateDialog, then the problem is that it normally gets created with a border and title bar. So how to show it full screen without them?

Revision as of 09:00, 23 February 2010

C-code

First, the problem. It is easy to show a normal window full screen, in various ways. But for a dialog created using e.g. CreateDialog, then the problem is that it normally gets created with a border and title bar. So how to show it full screen without them?

The idea is to resize the dialog so that its edges and title bar go outside the monitor. Then - so that you can't see the extra bits of it on a multiple monitor setup - clip the window to the client area.

First of all, we need to tell Windows that our dialog can be resized larger than the screen, otherwise it will helpfully resize it to fit the screen whenever we try.

So - in the dialog proc for the window use:

switch(message)
 {
 case WM_GETMINMAXINFO:
  // bIsFullScreenDialog(..)
  // returns TRUE if the 
  // dialog has been set to full screen
  if(!bIsFullScreenDialog(hDlg))
   break;
  {
   // http://msdn.microsoft.com/en-us/library/ms632626%28VS.85%29.aspx
   // see also http://msdn.microsoft.com/en-us/magazine/cc188910.aspx
   MINMAXINFO *pmmi=(MINMAXINFO *)lParam;
   // Pointer to a MINMAXINFO structure that contains the default maximized position and dimensions, and the default minimum and maximum tracking sizes. An application can override the defaults by setting the members of this structure.
   // Now work out the border size - this will depend on your dialog - and you can over estimate
   // since this is only for situation bIsFullScreenDialog(hDlg);
   int xborder=GetSystemMetrics(SM_CXEDGE)+GetSystemMetrics(SM_CXSIZEFRAME);
   int yborder=GetSystemMetrics(SM_CYEDGE)+GetSystemMetrics(SM_CYSIZEFRAME);
   int ytitle_bar=GetSystemMetrics(SM_CYCAPTION)+(GetMenu(hDlg)?GetSystemMetrics(SM_CYMENU):0);
   // The maximum tracking size is the largest window size that can be produced by using the borders to size the window. The minimum tracking size is the smallest window size that can be produced by using the borders to size the window.
   pmmi->ptMaxTrackSize.x=GetSystemMetrics(SM_CXVIRTUALSCREEN)+xborder*2;
   pmmi->ptMaxTrackSize.y=GetSystemMetrics(SM_CYVIRTUALSCREEN)+yborder*2+ytitle_bar;
   pmmi->ptMaxPosition.x=-xborder;
   pmmi->ptMaxPosition.y=-yborder;
  }
  break;
 }

Now resize the dialog so that it is larger than the screen. To take account of multiple monitors, detect which monitor the dialog is in first

char hide_start_menu_for_full_screen=1;
char do_full_screen_dialogs_topmost=1;
...
 switch(message)
 {
 case WM_INITDIALOG:
  if(bIsFullScreenDialog(hDlg))
  {
   RECT rcmon;
   char do_topmost=0;
   RECT rcNewWin;
   rcNewWin=rcmon=rcRectMonitorForRect(&rcWas,MONITOR_WORKAREA);
   if(hide_start_menu_for_full_screen)
   {
    rcmon=rcRectMonitorForRect(&rcWas,MONITOR_AREA);
    if(!SameRect(&rcmon,&rcNewWin))
     do_topmost=1;// Must be topmost anyway to hide the start menu
    rcNewWin=rcmon;
   }
   rcNewWin.top-=GetSystemMetrics(SM_CYSIZEFRAME);
   rcNewWin.bottom+=GetSystemMetrics(SM_CYSIZEFRAME);
   rcNewWin.left-=GetSystemMetrics(SM_CXSIZEFRAME);
   rcNewWin.right+=GetSystemMetrics(SM_CXSIZEFRAME);
   rcNewWin.top-=GetSystemMetrics(SM_CYEDGE);
   rcNewWin.bottom+=GetSystemMetrics(SM_CYEDGE);
   rcNewWin.left-=GetSystemMetrics(SM_CXEDGE);
   rcNewWin.right+=GetSystemMetrics(SM_CXEDGE);
   rcNewWin.top-=GetSystemMetrics(SM_CYCAPTION);
   if(GetMenu(hDlg)&&bHideMenuForFullScreenDialog(hDlg))
   {
    int cy_menu=GetSystemMetrics(SM_CYMENU);
    rcNewWin.top-=cy_menu;
   }
   MoveWindow(hDlg,rcNewWin.left,rcNewWin.top,rcNewWin.right-rcNewWin.left,rcNewWin.bottom-rcNewWin.top,bTF);
   if(clip_to_monitor_for_full_screen_dialog)
   {
    // Clip by edges showing outside the window
    HRGN hRgn=CreateRectRgn(rcmon.left-rcNewWin.left,rcmon.top-rcNewWin.top,rcmon.right-rcNewWin.left
     ,rcmon.bottom-rcNewWin.top);
    SetWindowRgn(hDlg,hRgn,FALSE);
   }
   if(do_topmost&&do_full_screen_dialogs_topmost)
    SetWindowPos(hwnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
   break;
  }
 }

Now just need to supply the extra routines we need for boilerplate type stuff - there's only one, to detect the size and position of the monitor nearest to the dialog:

#include <multimon.h>
#define MONITOR_WORKAREA 0x0002        // use monitor work area
#define MONITOR_AREA     0x0000        // use monitor entire area
 
RECT rcRectMonitorForRect(RECT *prc,DWORD flags)
{
 HMONITOR hMonitor;
 MONITORINFO mi;
 RECT        rc;
 // get the nearest monitor to the passed rect.
 //
 hMonitor = MonitorFromRect(prc, MONITOR_DEFAULTTONEAREST);
 
 //
 // get the work area or entire monitor rect.
 //
 mi.cbSize = sizeof(mi);
 GetMonitorInfo(hMonitor, &mi);
 
 if (flags & MONITOR_WORKAREA)
     rc = mi.rcWork;
 else
     rc = mi.rcMonitor;
 return rc;
}

If you want to do this in C++ then Full Screen Display and Implementing Drag to Move Dialogs may be helpful. That's where I learnt about WM_GETMINMAXINFO in fact.

The clip to window technique used here can also be used to make a dialog that is draggable without a title bar - clip in the same way, and make it draggable using the HTCAPTION trick - see How to make any part of a window or dialog draggable

Personal tools
Namespaces
Variants
Actions
Navigation
How to use the wiki
More
Toolbox