1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/msw/toplevel.cpp 
   3 // Purpose:     implements wxTopLevelWindow for MSW 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2001 SciTech Software, Inc. (www.scitechsoft.com) 
   9 // License:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // For compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  27 #include "wx/toplevel.h" 
  31     #include "wx/dialog.h" 
  32     #include "wx/string.h" 
  36     #include "wx/containr.h"        // wxSetFocusToChild() 
  37     #include "wx/module.h" 
  40 #include "wx/dynlib.h" 
  42 #include "wx/msw/private.h" 
  43 #if defined(__WXWINCE__) && !defined(__HANDHELDPC__) 
  46     // Standard SDK doesn't have aygshell.dll: see include/wx/msw/wince/libraries.h 
  47     #if _WIN32_WCE < 400 || !defined(__WINCE_STANDARDSDK__) 
  52 #include "wx/msw/winundef.h" 
  53 #include "wx/msw/missing.h" 
  55 #include "wx/display.h" 
  65 // ---------------------------------------------------------------------------- 
  66 // stubs for missing functions under MicroWindows 
  67 // ---------------------------------------------------------------------------- 
  71 // static inline bool IsIconic(HWND WXUNUSED(hwnd)) { return false; } 
  72 static inline bool IsZoomed(HWND 
WXUNUSED(hwnd
)) { return false; } 
  74 #endif // __WXMICROWIN__ 
  76 // NB: wxDlgProc must be defined here and not in dialog.cpp because the latter 
  77 //     is not included by wxUniv build which does need wxDlgProc 
  79 wxDlgProc(HWND hDlg
, UINT message
, WPARAM wParam
, LPARAM lParam
); 
  81 // ---------------------------------------------------------------------------- 
  82 // wxTLWHiddenParentModule: used to manage the hidden parent window (we need a 
  83 // module to ensure that the window is always deleted) 
  84 // ---------------------------------------------------------------------------- 
  86 class wxTLWHiddenParentModule 
: public wxModule
 
  89     // module init/finalize 
  90     virtual bool OnInit(); 
  91     virtual void OnExit(); 
  93     // get the hidden window (creates on demand) 
  94     static HWND 
GetHWND(); 
  97     // the HWND of the hidden parent 
 100     // the class used to create it 
 101     static const wxChar 
*ms_className
; 
 103     DECLARE_DYNAMIC_CLASS(wxTLWHiddenParentModule
) 
 106 IMPLEMENT_DYNAMIC_CLASS(wxTLWHiddenParentModule
, wxModule
) 
 108 // ============================================================================ 
 109 // wxTopLevelWindowMSW implementation 
 110 // ============================================================================ 
 112 BEGIN_EVENT_TABLE(wxTopLevelWindowMSW
, wxTopLevelWindowBase
) 
 113     EVT_ACTIVATE(wxTopLevelWindowMSW::OnActivate
) 
 116 // ---------------------------------------------------------------------------- 
 117 // wxTopLevelWindowMSW creation 
 118 // ---------------------------------------------------------------------------- 
 120 void wxTopLevelWindowMSW::Init() 
 123     m_maximizeOnShow 
= false; 
 125     // Data to save/restore when calling ShowFullScreen 
 127     m_fsOldWindowStyle 
= 0; 
 128     m_fsIsMaximized 
= false; 
 129     m_fsIsShowing 
= false; 
 131     m_winLastFocused 
= NULL
; 
 133 #if defined(__SMARTPHONE__) && defined(__WXWINCE__) 
 137 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
 138     SHACTIVATEINFO
* info 
= new SHACTIVATEINFO
; 
 140     info
->cbSize 
= sizeof(SHACTIVATEINFO
); 
 142     m_activateInfo 
= (void*) info
; 
 146 WXDWORD 
wxTopLevelWindowMSW::MSWGetStyle(long style
, WXDWORD 
*exflags
) const 
 148     // let the base class deal with the common styles but fix the ones which 
 149     // don't make sense for us (we also deal with the borders ourselves) 
 150     WXDWORD msflags 
= wxWindow::MSWGetStyle
 
 152                         (style 
& ~wxBORDER_MASK
) | wxBORDER_NONE
, exflags
 
 153                       ) & ~WS_CHILD 
& ~WS_VISIBLE
; 
 155     // For some reason, WS_VISIBLE needs to be defined on creation for 
 156     // SmartPhone 2003. The title can fail to be displayed otherwise. 
 157 #if defined(__SMARTPHONE__) || (defined(__WXWINCE__) && _WIN32_WCE < 400) 
 158     msflags 
|= WS_VISIBLE
; 
 159     ((wxTopLevelWindowMSW
*)this)->wxWindowBase::Show(true); 
 162     // first select the kind of window being created 
 164     // note that if we don't set WS_POPUP, Windows assumes WS_OVERLAPPED and 
 165     // creates a window with both caption and border, hence we need to use 
 166     // WS_POPUP in a few cases just to avoid having caption/border which we 
 169     // border and caption styles 
 170     if ( ( style 
& wxRESIZE_BORDER 
) && !IsAlwaysMaximized()) 
 171         msflags 
|= WS_THICKFRAME
; 
 172     else if ( exflags 
&& ((style 
& wxBORDER_DOUBLE
) || (style 
& wxBORDER_RAISED
)) ) 
 173         *exflags 
|= WS_EX_DLGMODALFRAME
; 
 174     else if ( !(style 
& wxBORDER_NONE
) ) 
 175         msflags 
|= WS_BORDER
; 
 181     // normally we consider that all windows without a caption must be popups, 
 182     // but CE is an exception: there windows normally do not have the caption 
 183     // but shouldn't be made popups as popups can't have menus and don't look 
 184     // like normal windows anyhow 
 186     // TODO: Smartphone appears to like wxCAPTION, but we should check that 
 188 #if defined(__SMARTPHONE__) || !defined(__WXWINCE__) 
 189     if ( style 
& wxCAPTION 
) 
 190         msflags 
|= WS_CAPTION
; 
 194 #endif // !__WXWINCE__ 
 197     // next translate the individual flags 
 199     // WS_EX_CONTEXTHELP is incompatible with WS_MINIMIZEBOX and WS_MAXIMIZEBOX 
 200     // and is ignored if we specify both of them, but chances are that if we 
 201     // use wxWS_EX_CONTEXTHELP, we really do want to have the context help 
 202     // button while wxMINIMIZE/wxMAXIMIZE are included by default, so the help 
 204     if ( !(GetExtraStyle() & wxWS_EX_CONTEXTHELP
) ) 
 206         if ( style 
& wxMINIMIZE_BOX 
) 
 207             msflags 
|= WS_MINIMIZEBOX
; 
 208         if ( style 
& wxMAXIMIZE_BOX 
) 
 209             msflags 
|= WS_MAXIMIZEBOX
; 
 213     // notice that if wxCLOSE_BOX is specified we need to use WS_SYSMENU too as 
 214     // otherwise the close box doesn't appear 
 215     if ( style 
& (wxSYSTEM_MENU 
| wxCLOSE_BOX
) ) 
 216         msflags 
|= WS_SYSMENU
; 
 217 #endif // !__WXWINCE__ 
 219     // NB: under CE these 2 styles are not supported currently, we should 
 220     //     call Minimize()/Maximize() "manually" if we want to support them 
 221     if ( style 
& wxMINIMIZE 
) 
 222         msflags 
|= WS_MINIMIZE
; 
 224     if ( style 
& wxMAXIMIZE 
) 
 225         msflags 
|= WS_MAXIMIZE
; 
 227     // Keep this here because it saves recoding this function in wxTinyFrame 
 228     if ( style 
& (wxTINY_CAPTION_VERT 
| wxTINY_CAPTION_HORIZ
) ) 
 229         msflags 
|= WS_CAPTION
; 
 233         // there is no taskbar under CE, so omit all this 
 234 #if !defined(__WXWINCE__) 
 235         if ( !(GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) ) 
 237             if ( style 
& wxFRAME_TOOL_WINDOW 
) 
 239                 // create the palette-like window 
 240                 *exflags 
|= WS_EX_TOOLWINDOW
; 
 242                 // tool windows shouldn't appear on the taskbar (as documented) 
 243                 style 
|= wxFRAME_NO_TASKBAR
; 
 246             // We have to solve 2 different problems here: 
 248             // 1. frames with wxFRAME_NO_TASKBAR flag shouldn't appear in the 
 249             //    taskbar even if they don't have a parent 
 251             // 2. frames without this style should appear in the taskbar even 
 252             //    if they're owned (Windows only puts non owned windows into 
 253             //    the taskbar normally) 
 255             // The second one is solved here by using WS_EX_APPWINDOW flag, the 
 256             // first one is dealt with in our MSWGetParent() method 
 258             if ( !(style 
& wxFRAME_NO_TASKBAR
) && GetParent() ) 
 260                 // need to force the frame to appear in the taskbar 
 261                 *exflags 
|= WS_EX_APPWINDOW
; 
 263             //else: nothing to do [here] 
 266         if ( GetExtraStyle() & wxWS_EX_CONTEXTHELP 
) 
 267             *exflags 
|= WS_EX_CONTEXTHELP
; 
 268 #endif // !__WXWINCE__ 
 270         if ( style 
& wxSTAY_ON_TOP 
) 
 271             *exflags 
|= WS_EX_TOPMOST
; 
 277 WXHWND 
wxTopLevelWindowMSW::MSWGetParent() const 
 279     // for the frames without wxFRAME_FLOAT_ON_PARENT style we should use NULL 
 280     // parent HWND or it would be always on top of its parent which is not what 
 281     // we usually want (in fact, we only want it for frames with the 
 282     // wxFRAME_FLOAT_ON_PARENT flag) 
 283     HWND hwndParent 
= NULL
; 
 284     if ( HasFlag(wxFRAME_FLOAT_ON_PARENT
) ) 
 286         const wxWindow 
*parent 
= GetParent(); 
 290             // this flag doesn't make sense then and will be ignored 
 291             wxFAIL_MSG( _T("wxFRAME_FLOAT_ON_PARENT but no parent?") ); 
 295             hwndParent 
= GetHwndOf(parent
); 
 298     //else: don't float on parent, must not be owned 
 300     // now deal with the 2nd taskbar-related problem (see comments above in 
 302     if ( HasFlag(wxFRAME_NO_TASKBAR
) && !hwndParent 
) 
 305         hwndParent 
= wxTLWHiddenParentModule::GetHWND(); 
 308     return (WXHWND
)hwndParent
; 
 311 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
 312 bool wxTopLevelWindowMSW::HandleSettingChange(WXWPARAM wParam
, WXLPARAM lParam
) 
 314     SHACTIVATEINFO 
*info 
= (SHACTIVATEINFO
*) m_activateInfo
; 
 317         SHHandleWMSettingChange(GetHwnd(), wParam
, lParam
, info
); 
 320     return wxWindowMSW::HandleSettingChange(wParam
, lParam
); 
 324 WXLRESULT 
wxTopLevelWindowMSW::MSWWindowProc(WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
) 
 327     bool processed 
= false; 
 329 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
 334             SHACTIVATEINFO
* info 
= (SHACTIVATEINFO
*) m_activateInfo
; 
 338                 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG
) flags 
= SHA_INPUTDIALOG
; 
 339                 SHHandleWMActivate(GetHwnd(), wParam
, lParam
, info
, flags
); 
 342             // This implicitly sends a wxEVT_ACTIVATE_APP event 
 344                 wxTheApp
->SetActive(wParam 
!= 0, FindFocus()); 
 352                 wxActivateEvent 
event(wxEVT_HIBERNATE
, true, wxID_ANY
); 
 353                 event
.SetEventObject(wxTheApp
); 
 354                 processed 
= wxTheApp
->ProcessEvent(event
); 
 362         rc 
= wxTopLevelWindowBase::MSWWindowProc(message
, wParam
, lParam
); 
 367 bool wxTopLevelWindowMSW::CreateDialog(const void *dlgTemplate
, 
 368                                        const wxString
& title
, 
 372 #ifdef __WXMICROWIN__ 
 373     // no dialogs support under MicroWin yet 
 374     return CreateFrame(title
, pos
, size
); 
 375 #else // !__WXMICROWIN__ 
 376     // static cast is valid as we're only ever called for dialogs 
 378         parent 
= static_cast<wxDialog 
*>(this)->GetParentForModalDialog(); 
 380     m_hWnd 
= (WXHWND
)::CreateDialogIndirect
 
 383                         (DLGTEMPLATE
*)dlgTemplate
, 
 384                         parent 
? GetHwndOf(parent
) : NULL
, 
 390         wxFAIL_MSG(wxT("Failed to create dialog. Incorrect DLGTEMPLATE?")); 
 392         wxLogSysError(wxT("Can't create dialog using memory template")); 
 397 #if !defined(__WXWINCE__) 
 398     // For some reason, the system menu is activated when we use the 
 399     // WS_EX_CONTEXTHELP style, so let's set a reasonable icon 
 400     if ( HasExtraStyle(wxWS_EX_CONTEXTHELP
) ) 
 402         wxFrame 
*winTop 
= wxDynamicCast(wxTheApp
->GetTopWindow(), wxFrame
); 
 405             wxIcon icon 
= winTop
->GetIcon(); 
 408                 ::SendMessage(GetHwnd(), WM_SETICON
, 
 410                               (LPARAM
)GetHiconOf(icon
)); 
 414 #endif // !__WXWINCE__ 
 416     // move the dialog to its initial position without forcing repainting 
 418     (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
); 
 420     if ( x 
== (int)CW_USEDEFAULT 
) 
 422         // centre it on the screen - what else can we do? 
 423         wxSize sizeDpy 
= wxGetDisplaySize(); 
 425         x 
= (sizeDpy
.x 
- w
) / 2; 
 426         y 
= (sizeDpy
.y 
- h
) / 2; 
 429 #if !defined(__WXWINCE__) || defined(__WINCE_STANDARDSDK__) 
 430     if ( !::MoveWindow(GetHwnd(), x
, y
, w
, h
, FALSE
) ) 
 432         wxLogLastError(wxT("MoveWindow")); 
 436     if ( !title
.empty() ) 
 438         ::SetWindowText(GetHwnd(), title
.wx_str()); 
 443 #ifdef __SMARTPHONE__ 
 444     // Work around title non-display glitch 
 449 #endif // __WXMICROWIN__/!__WXMICROWIN__ 
 452 bool wxTopLevelWindowMSW::CreateFrame(const wxString
& title
, 
 457     WXDWORD flags 
= MSWGetCreateWindowFlags(&exflags
); 
 459     const wxSize sz 
= IsAlwaysMaximized() ? wxDefaultSize 
: size
; 
 462     if ( wxTheApp
->GetLayoutDirection() == wxLayout_RightToLeft 
) 
 463         exflags 
|= WS_EX_LAYOUTRTL
; 
 466     return MSWCreate(MSWGetRegisteredClassName(), 
 467                      title
.wx_str(), pos
, sz
, flags
, exflags
); 
 470 bool wxTopLevelWindowMSW::Create(wxWindow 
*parent
, 
 472                                  const wxString
& title
, 
 476                                  const wxString
& name
) 
 478     bool ret 
wxDUMMY_INITIALIZE(false); 
 480     wxSize sizeReal 
= size
; 
 481     if ( !sizeReal
.IsFullySpecified() ) 
 483         sizeReal
.SetDefaults(GetDefaultSize()); 
 486     m_windowStyle 
= style
; 
 490     m_windowId 
= id 
== wxID_ANY 
? NewControlId() : id
; 
 492     wxTopLevelWindows
.Append(this); 
 495         parent
->AddChild(this); 
 497     if ( GetExtraStyle() & wxTOPLEVEL_EX_DIALOG 
) 
 499         // we have different dialog templates to allows creation of dialogs 
 500         // with & without captions under MSWindows, resizeable or not (but a 
 501         // resizeable dialog always has caption - otherwise it would look too 
 504         // we need 3 additional WORDs for dialog menu, class and title (as we 
 505         // don't use DS_SETFONT we don't need the fourth WORD for the font) 
 506         static const int dlgsize 
= sizeof(DLGTEMPLATE
) + (sizeof(WORD
) * 3); 
 507         DLGTEMPLATE 
*dlgTemplate 
= (DLGTEMPLATE 
*)malloc(dlgsize
); 
 508         memset(dlgTemplate
, 0, dlgsize
); 
 510         // these values are arbitrary, they won't be used normally anyhow 
 513         dlgTemplate
->cx 
= 144; 
 514         dlgTemplate
->cy 
= 75; 
 516         // reuse the code in MSWGetStyle() but correct the results slightly for 
 519         // NB: we need a temporary variable as we can't pass pointer to 
 520         //     dwExtendedStyle directly, it's not aligned correctly for 64 bit 
 522         WXDWORD dwExtendedStyle
; 
 523         dlgTemplate
->style 
= MSWGetStyle(style
, &dwExtendedStyle
); 
 524         dlgTemplate
->dwExtendedStyle 
= dwExtendedStyle
; 
 526         // all dialogs are popups 
 527         dlgTemplate
->style 
|= WS_POPUP
; 
 530         if ( wxTheApp
->GetLayoutDirection() == wxLayout_RightToLeft 
) 
 532             dlgTemplate
->dwExtendedStyle 
|= WS_EX_LAYOUTRTL
; 
 535         // force 3D-look if necessary, it looks impossibly ugly otherwise 
 536         if ( style 
& (wxRESIZE_BORDER 
| wxCAPTION
) ) 
 537             dlgTemplate
->style 
|= DS_MODALFRAME
; 
 540         ret 
= CreateDialog(dlgTemplate
, title
, pos
, sizeReal
); 
 545         ret 
= CreateFrame(title
, pos
, sizeReal
); 
 549     if ( ret 
&& !(GetWindowStyleFlag() & wxCLOSE_BOX
) ) 
 551         EnableCloseButton(false); 
 555     // for standard dialogs the dialog manager generates WM_CHANGEUISTATE 
 556     // itself but for custom windows we have to do it ourselves in order to 
 557     // make the keyboard indicators (such as underlines for accelerators and 
 558     // focus rectangles) work under Win2k+ 
 561         MSWUpdateUIState(UIS_INITIALIZE
); 
 564     // Note: if we include PocketPC in this test, dialogs can fail to show up, 
 565     // for example the text entry dialog in the dialogs sample. Problem with Maximise()? 
 566 #if defined(__WXWINCE__) && (defined(__SMARTPHONE__) || defined(__WINCE_STANDARDSDK__)) 
 567     if ( ( style 
& wxMAXIMIZE 
) || IsAlwaysMaximized() ) 
 573 #if defined(__SMARTPHONE__) && defined(__WXWINCE__) 
 574     SetRightMenu(); // to nothing for initialization 
 580 wxTopLevelWindowMSW::~wxTopLevelWindowMSW() 
 584 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
 585     SHACTIVATEINFO
* info 
= (SHACTIVATEINFO
*) m_activateInfo
; 
 587     m_activateInfo 
= NULL
; 
 590     // after destroying an owned window, Windows activates the next top level 
 591     // window in Z order but it may be different from our owner (to reproduce 
 592     // this simply Alt-TAB to another application and back before closing the 
 593     // owned frame) whereas we always want to yield activation to our parent 
 594     if ( HasFlag(wxFRAME_FLOAT_ON_PARENT
) ) 
 596         wxWindow 
*parent 
= GetParent(); 
 599             ::BringWindowToTop(GetHwndOf(parent
)); 
 604 // ---------------------------------------------------------------------------- 
 605 // wxTopLevelWindowMSW showing 
 606 // ---------------------------------------------------------------------------- 
 608 void wxTopLevelWindowMSW::DoShowWindow(int nShowCmd
) 
 610     ::ShowWindow(GetHwnd(), nShowCmd
); 
 612     m_iconized 
= nShowCmd 
== SW_MINIMIZE
; 
 615 bool wxTopLevelWindowMSW::Show(bool show
) 
 617     // don't use wxWindow version as we want to call DoShowWindow() ourselves 
 618     if ( !wxWindowBase::Show(show
) ) 
 624         if ( m_maximizeOnShow 
) 
 627             nShowCmd 
= SW_MAXIMIZE
; 
 629             // This is necessary, or no window appears 
 630 #if defined( __WINCE_STANDARDSDK__) || defined(__SMARTPHONE__) 
 631             DoShowWindow(SW_SHOW
); 
 634             m_maximizeOnShow 
= false; 
 636         else if ( m_iconized 
) 
 639             nShowCmd 
= SW_MINIMIZE
; 
 643             // we shouldn't use SW_SHOW which also activates the window for 
 644             // tool frames (as they shouldn't steal focus from the main window) 
 645             // nor for the currently disabled windows as they would be enabled 
 647             if ( HasFlag(wxFRAME_TOOL_WINDOW
) || !IsEnabled() ) 
 648                 nShowCmd 
= SW_SHOWNA
; 
 658     DoShowWindow(nShowCmd
); 
 660 #if defined(__WXWINCE__) && (_WIN32_WCE >= 400 && !defined(__POCKETPC__) && !defined(__SMARTPHONE__)) 
 661     // Addornments have to be added when the frame is the correct size 
 662     wxFrame
* frame 
= wxDynamicCast(this, wxFrame
); 
 663     if (frame 
&& frame
->GetMenuBar()) 
 664         frame
->GetMenuBar()->AddAdornments(GetWindowStyleFlag()); 
 667     // we only set pending size if we're maximized before being shown, now that 
 668     // we're shown we don't need it any more (it is reset in size event handler 
 669     // for child windows but we have to do it ourselves for this parent window) 
 670     m_pendingSize 
= wxDefaultSize
; 
 675 // ---------------------------------------------------------------------------- 
 676 // wxTopLevelWindowMSW maximize/minimize 
 677 // ---------------------------------------------------------------------------- 
 679 void wxTopLevelWindowMSW::Maximize(bool maximize
) 
 683         // just maximize it directly 
 684         DoShowWindow(maximize 
? SW_MAXIMIZE 
: SW_RESTORE
); 
 688         // we can't maximize the hidden frame because it shows it as well, 
 689         // so just remember that we should do it later in this case 
 690         m_maximizeOnShow 
= maximize
; 
 692         // after calling Maximize() the client code expects to get the frame 
 693         // "real" size and doesn't want to know that, because of implementation 
 694         // details, the frame isn't really maximized yet but will be only once 
 695         // it's shown, so return our size as it will be then in this case 
 698             // we must only change pending size here, and not call SetSize() 
 699             // because otherwise Windows would think that this (full screen) 
 700             // size is the natural size for the frame and so would use it when 
 701             // the user clicks on "restore" title bar button instead of the 
 702             // correct initial frame size 
 704             // NB: unfortunately we don't know which display we're on yet so we 
 705             //     have to use the default one 
 706             m_pendingSize 
= wxGetClientDisplayRect().GetSize(); 
 708         //else: can't do anything in this case, we don't have the old size 
 712 bool wxTopLevelWindowMSW::IsMaximized() const 
 714     return IsAlwaysMaximized() || 
 715 #if !defined(__SMARTPHONE__) && !defined(__POCKETPC__) && !defined(__WINCE_STANDARDSDK__) 
 717            (::IsZoomed(GetHwnd()) != 0) || 
 722 void wxTopLevelWindowMSW::Iconize(bool iconize
) 
 726         // change the window state immediately 
 727         DoShowWindow(iconize 
? SW_MINIMIZE 
: SW_RESTORE
); 
 731         // iconizing the window shouldn't show it so just remember that we need 
 732         // to become iconized when shown later 
 737 bool wxTopLevelWindowMSW::IsIconized() const 
 745     // don't use m_iconized, it may be briefly out of sync with the real state 
 746     // as it's only modified when we receive a WM_SIZE and we could be called 
 747     // from an event handler from one of the messages we receive before it, 
 749     return ::IsIconic(GetHwnd()) != 0; 
 753 void wxTopLevelWindowMSW::Restore() 
 755     DoShowWindow(SW_RESTORE
); 
 758 void wxTopLevelWindowMSW::SetLayoutDirection(wxLayoutDirection dir
) 
 760     if ( dir 
== wxLayout_Default 
) 
 761         dir 
= wxTheApp
->GetLayoutDirection(); 
 763     if ( dir 
!= wxLayout_Default 
) 
 764         wxTopLevelWindowBase::SetLayoutDirection(dir
); 
 767 // ---------------------------------------------------------------------------- 
 768 // wxTopLevelWindowMSW geometry 
 769 // ---------------------------------------------------------------------------- 
 773 void wxTopLevelWindowMSW::DoGetPosition(int *x
, int *y
) const 
 778         wp
.length 
= sizeof(WINDOWPLACEMENT
); 
 779         if ( ::GetWindowPlacement(GetHwnd(), &wp
) ) 
 781             RECT
& rc 
= wp
.rcNormalPosition
; 
 783             // the position returned by GetWindowPlacement() is in workspace 
 784             // coordinates except for windows with WS_EX_TOOLWINDOW style 
 785             if ( !HasFlag(wxFRAME_TOOL_WINDOW
) ) 
 787                 // we must use the correct display for the translation as the 
 788                 // task bar might be shown on one display but not the other one 
 789                 int n 
= wxDisplay::GetFromWindow(this); 
 790                 wxDisplay 
dpy(n 
== wxNOT_FOUND 
? 0 : n
); 
 791                 const wxPoint ptOfs 
= dpy
.GetClientArea().GetPosition() - 
 792                                       dpy
.GetGeometry().GetPosition(); 
 806         wxLogLastError(_T("GetWindowPlacement")); 
 810     wxTopLevelWindowBase::DoGetPosition(x
, y
); 
 813 void wxTopLevelWindowMSW::DoGetSize(int *width
, int *height
) const 
 818         wp
.length 
= sizeof(WINDOWPLACEMENT
); 
 819         if ( ::GetWindowPlacement(GetHwnd(), &wp
) ) 
 821             const RECT
& rc 
= wp
.rcNormalPosition
; 
 824                 *width 
= rc
.right 
- rc
.left
; 
 826                 *height 
= rc
.bottom 
- rc
.top
; 
 831         wxLogLastError(_T("GetWindowPlacement")); 
 835     wxTopLevelWindowBase::DoGetSize(width
, height
); 
 838 #endif // __WXWINCE__ 
 840 // ---------------------------------------------------------------------------- 
 841 // wxTopLevelWindowMSW fullscreen 
 842 // ---------------------------------------------------------------------------- 
 844 bool wxTopLevelWindowMSW::ShowFullScreen(bool show
, long style
) 
 846     if ( show 
== IsFullScreen() ) 
 852     m_fsIsShowing 
= show
; 
 858         // zap the frame borders 
 860         // save the 'normal' window style 
 861         m_fsOldWindowStyle 
= GetWindowLong(GetHwnd(), GWL_STYLE
); 
 863         // save the old position, width & height, maximize state 
 864         m_fsOldSize 
= GetRect(); 
 865         m_fsIsMaximized 
= IsMaximized(); 
 867         // decide which window style flags to turn off 
 868         LONG newStyle 
= m_fsOldWindowStyle
; 
 871         if (style 
& wxFULLSCREEN_NOBORDER
) 
 873             offFlags 
|= WS_BORDER
; 
 875             offFlags 
|= WS_THICKFRAME
; 
 878         if (style 
& wxFULLSCREEN_NOCAPTION
) 
 879             offFlags 
|= WS_CAPTION 
| WS_SYSMENU
; 
 881         newStyle 
&= ~offFlags
; 
 883         // change our window style to be compatible with full-screen mode 
 884         ::SetWindowLong(GetHwnd(), GWL_STYLE
, newStyle
); 
 888         // resize to the size of the display containing us 
 889         int dpy 
= wxDisplay::GetFromWindow(this); 
 890         if ( dpy 
!= wxNOT_FOUND 
) 
 892             rect 
= wxDisplay(dpy
).GetGeometry(); 
 894         else // fall back to the main desktop 
 895 #endif // wxUSE_DISPLAY 
 897             // resize to the size of the desktop 
 898             wxCopyRECTToRect(wxGetWindowRect(::GetDesktopWindow()), rect
); 
 900             // FIXME: size of the bottom menu (toolbar) 
 901             // should be taken in account 
 902             rect
.height 
+= rect
.y
; 
 909         // now flush the window style cache and actually go full-screen 
 910         long flags 
= SWP_FRAMECHANGED
; 
 912         // showing the frame full screen should also show it if it's still 
 916             // don't call wxWindow version to avoid flicker from calling 
 917             // ::ShowWindow() -- we're going to show the window at the correct 
 918             // location directly below -- but do call the wxWindowBase version 
 919             // to sync the internal m_isShown flag 
 920             wxWindowBase::Show(); 
 922             flags 
|= SWP_SHOWWINDOW
; 
 925         SetWindowPos(GetHwnd(), HWND_TOP
, 
 926                      rect
.x
, rect
.y
, rect
.width
, rect
.height
, 
 929 #if !defined(__HANDHELDPC__) && (defined(__WXWINCE__) && (_WIN32_WCE < 400)) 
 930         ::SHFullScreen(GetHwnd(), SHFS_HIDETASKBAR 
| SHFS_HIDESIPBUTTON
); 
 933         // finally send an event allowing the window to relayout itself &c 
 934         wxSizeEvent 
event(rect
.GetSize(), GetId()); 
 935         HandleWindowEvent(event
); 
 937     else // stop showing full screen 
 939 #if !defined(__HANDHELDPC__) && (defined(__WXWINCE__) && (_WIN32_WCE < 400)) 
 940         ::SHFullScreen(GetHwnd(), SHFS_SHOWTASKBAR 
| SHFS_SHOWSIPBUTTON
); 
 942         Maximize(m_fsIsMaximized
); 
 943         SetWindowLong(GetHwnd(),GWL_STYLE
, m_fsOldWindowStyle
); 
 944         SetWindowPos(GetHwnd(),HWND_TOP
,m_fsOldSize
.x
, m_fsOldSize
.y
, 
 945             m_fsOldSize
.width
, m_fsOldSize
.height
, SWP_FRAMECHANGED
); 
 951 // ---------------------------------------------------------------------------- 
 952 // wxTopLevelWindowMSW misc 
 953 // ---------------------------------------------------------------------------- 
 955 void wxTopLevelWindowMSW::SetTitle( const wxString
& title
) 
 960 wxString 
wxTopLevelWindowMSW::GetTitle() const 
 965 bool wxTopLevelWindowMSW::DoSelectAndSetIcon(const wxIconBundle
& icons
, 
 970     const wxSize 
size(::GetSystemMetrics(smX
), ::GetSystemMetrics(smY
)); 
 972     const wxIcon icon 
= icons
.GetIconOfExactSize(size
); 
 975         ::SendMessage(GetHwnd(), WM_SETICON
, i
, (LPARAM
)GetHiconOf(icon
)); 
 982 void wxTopLevelWindowMSW::SetIcons(const wxIconBundle
& icons
) 
 984     wxTopLevelWindowBase::SetIcons(icons
); 
 986     if ( icons
.IsEmpty() ) 
 988         // FIXME: SetIcons(wxNullIconBundle) should unset existing icons, 
 989         //        but we currently don't do that 
 990         wxASSERT_MSG( m_icons
.IsEmpty(), "unsetting icons doesn't work" ); 
 995         DoSelectAndSetIcon(icons
, SM_CXSMICON
, SM_CYSMICON
, ICON_SMALL
); 
 996     if ( DoSelectAndSetIcon(icons
, SM_CXICON
, SM_CYICON
, ICON_BIG
) ) 
1001         wxFAIL_MSG( "icon bundle doesn't contain any suitable icon" ); 
1005 bool wxTopLevelWindowMSW::EnableCloseButton(bool enable
) 
1007 #if !defined(__WXMICROWIN__) 
1008     // get system (a.k.a. window) menu 
1009     HMENU hmenu 
= GetSystemMenu(GetHwnd(), FALSE 
/* get it */); 
1012         // no system menu at all -- ok if we want to remove the close button 
1013         // anyhow, but bad if we want to show it 
1017     // enabling/disabling the close item from it also automatically 
1018     // disables/enables the close title bar button 
1019     if ( ::EnableMenuItem(hmenu
, SC_CLOSE
, 
1021                           (enable 
? MF_ENABLED 
: MF_GRAYED
)) == -1 ) 
1023         wxLogLastError(_T("EnableMenuItem(SC_CLOSE)")); 
1028     // update appearance immediately 
1029     if ( !::DrawMenuBar(GetHwnd()) ) 
1031         wxLogLastError(_T("DrawMenuBar")); 
1034 #endif // !__WXMICROWIN__ 
1041 bool wxTopLevelWindowMSW::SetShape(const wxRegion
& region
) 
1043     wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false, 
1044                  _T("Shaped windows must be created with the wxFRAME_SHAPED style.")); 
1046     // The empty region signifies that the shape should be removed from the 
1048     if ( region
.IsEmpty() ) 
1050         if (::SetWindowRgn(GetHwnd(), NULL
, TRUE
) == 0) 
1052             wxLogLastError(_T("SetWindowRgn")); 
1058     // Windows takes ownership of the region, so 
1059     // we'll have to make a copy of the region to give to it. 
1060     DWORD noBytes 
= ::GetRegionData(GetHrgnOf(region
), 0, NULL
); 
1061     RGNDATA 
*rgnData 
= (RGNDATA
*) new char[noBytes
]; 
1062     ::GetRegionData(GetHrgnOf(region
), noBytes
, rgnData
); 
1063     HRGN hrgn 
= ::ExtCreateRegion(NULL
, noBytes
, rgnData
); 
1064     delete[] (char*) rgnData
; 
1066     // SetWindowRgn expects the region to be in coordinants 
1067     // relative to the window, not the client area.  Figure 
1068     // out the offset, if any. 
1070     DWORD dwStyle 
=   ::GetWindowLong(GetHwnd(), GWL_STYLE
); 
1071     DWORD dwExStyle 
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
); 
1072     ::GetClientRect(GetHwnd(), &rect
); 
1073     ::AdjustWindowRectEx(&rect
, dwStyle
, FALSE
, dwExStyle
); 
1074     ::OffsetRgn(hrgn
, -rect
.left
, -rect
.top
); 
1076     // Now call the shape API with the new region. 
1077     if (::SetWindowRgn(GetHwnd(), hrgn
, TRUE
) == 0) 
1079         wxLogLastError(_T("SetWindowRgn")); 
1085 #endif // !__WXWINCE__ 
1087 void wxTopLevelWindowMSW::RequestUserAttention(int flags
) 
1089     // check if we can use FlashWindowEx(): unfortunately a simple test for 
1090     // FLASHW_STOP doesn't work because MSVC6 headers do #define it but don't 
1091     // provide FlashWindowEx() declaration, so try to detect whether we have 
1092     // real headers for WINVER 0x0500 by checking for existence of a symbol not 
1093     // declated in MSVC6 header 
1094 #if defined(FLASHW_STOP) && defined(VK_XBUTTON1) && wxUSE_DYNLIB_CLASS 
1095     // available in the headers, check if it is supported by the system 
1096     typedef BOOL (WINAPI 
*FlashWindowEx_t
)(FLASHWINFO 
*pfwi
); 
1097     static FlashWindowEx_t s_pfnFlashWindowEx 
= NULL
; 
1098     if ( !s_pfnFlashWindowEx 
) 
1100         wxDynamicLibrary 
dllUser32(_T("user32.dll")); 
1101         s_pfnFlashWindowEx 
= (FlashWindowEx_t
) 
1102                                 dllUser32
.GetSymbol(_T("FlashWindowEx")); 
1104         // we can safely unload user32.dll here, it's going to remain loaded as 
1105         // long as the program is running anyhow 
1108     if ( s_pfnFlashWindowEx 
) 
1110         WinStruct
<FLASHWINFO
> fwi
; 
1111         fwi
.hwnd 
= GetHwnd(); 
1112         fwi
.dwFlags 
= FLASHW_ALL
; 
1113         if ( flags 
& wxUSER_ATTENTION_INFO 
) 
1115             // just flash a few times 
1118         else // wxUSER_ATTENTION_ERROR 
1120             // flash until the user notices it 
1121             fwi
.dwFlags 
|= FLASHW_TIMERNOFG
; 
1124         s_pfnFlashWindowEx(&fwi
); 
1126     else // FlashWindowEx() not available 
1127 #endif // FlashWindowEx() defined 
1131         ::FlashWindow(GetHwnd(), TRUE
); 
1132 #endif // __WXWINCE__ 
1136 // --------------------------------------------------------------------------- 
1138 bool wxTopLevelWindowMSW::SetTransparent(wxByte alpha
) 
1140 #if wxUSE_DYNLIB_CLASS 
1141     typedef DWORD (WINAPI 
*PSETLAYEREDWINDOWATTR
)(HWND
, DWORD
, BYTE
, DWORD
); 
1142     static PSETLAYEREDWINDOWATTR
 
1143         pSetLayeredWindowAttributes 
= (PSETLAYEREDWINDOWATTR
)-1; 
1145     if ( pSetLayeredWindowAttributes 
== (PSETLAYEREDWINDOWATTR
)-1 ) 
1147         wxDynamicLibrary 
dllUser32(_T("user32.dll")); 
1149         // use RawGetSymbol() and not GetSymbol() to avoid error messages under 
1150         // Windows 95: there is nothing the user can do about this anyhow 
1151         pSetLayeredWindowAttributes 
= (PSETLAYEREDWINDOWATTR
) 
1152             dllUser32
.RawGetSymbol(wxT("SetLayeredWindowAttributes")); 
1154         // it's ok to destroy dllUser32 here, we link statically to user32.dll 
1155         // anyhow so it won't be unloaded 
1158     if ( !pSetLayeredWindowAttributes 
) 
1160 #endif // wxUSE_DYNLIB_CLASS 
1162     LONG exstyle 
= GetWindowLong(GetHwnd(), GWL_EXSTYLE
); 
1164     // if setting alpha to fully opaque then turn off the layered style 
1167         SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyle 
& ~WS_EX_LAYERED
); 
1172 #if wxUSE_DYNLIB_CLASS 
1173     // Otherwise, set the layered style if needed and set the alpha value 
1174     if ((exstyle 
& WS_EX_LAYERED
) == 0 ) 
1175         SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyle 
| WS_EX_LAYERED
); 
1177     if ( pSetLayeredWindowAttributes(GetHwnd(), 0, (BYTE
)alpha
, LWA_ALPHA
) ) 
1179 #endif // wxUSE_DYNLIB_CLASS 
1184 bool wxTopLevelWindowMSW::CanSetTransparent() 
1186     // The API is available on win2k and above 
1188     static int os_type 
= -1; 
1189     static int ver_major 
= -1; 
1192         os_type 
= ::wxGetOsVersion(&ver_major
); 
1194     return (os_type 
== wxOS_WINDOWS_NT 
&& ver_major 
>= 5); 
1198 void wxTopLevelWindowMSW::DoFreeze() 
1200     // do nothing: freezing toplevel window causes paint and mouse events 
1201     // to go through it any TLWs under it, so the best we can do is to freeze 
1202     // all children -- and wxWindowBase::Freeze() does that 
1205 void wxTopLevelWindowMSW::DoThaw() 
1207     // intentionally empty -- see DoFreeze() 
1211 // ---------------------------------------------------------------------------- 
1212 // wxTopLevelWindow event handling 
1213 // ---------------------------------------------------------------------------- 
1215 // Default activation behaviour - set the focus for the first child 
1217 void wxTopLevelWindowMSW::OnActivate(wxActivateEvent
& event
) 
1219     if ( event
.GetActive() ) 
1221         // restore focus to the child which was last focused unless we already 
1223         wxLogTrace(_T("focus"), _T("wxTLW %p activated."), m_hWnd
); 
1225         wxWindow 
*winFocus 
= FindFocus(); 
1226         if ( !winFocus 
|| wxGetTopLevelParent(winFocus
) != this ) 
1228             wxWindow 
*parent 
= m_winLastFocused 
? m_winLastFocused
->GetParent() 
1235             wxSetFocusToChild(parent
, &m_winLastFocused
); 
1238     else // deactivating 
1240         // remember the last focused child if it is our child 
1241         m_winLastFocused 
= FindFocus(); 
1243         if ( m_winLastFocused 
) 
1245             // let it know that it doesn't have focus any more 
1246             // But this will already be done via WM_KILLFOCUS, so we'll get two kill 
1247             // focus events if we call it explicitly. 
1248             // m_winLastFocused->HandleKillFocus((WXHWND)NULL); 
1250             // and don't remember it if it's a child from some other frame 
1251             if ( wxGetTopLevelParent(m_winLastFocused
) != this ) 
1253                 m_winLastFocused 
= NULL
; 
1257         wxLogTrace(_T("focus"), 
1258                    _T("wxTLW %p deactivated, last focused: %p."), 
1260                    m_winLastFocused 
? GetHwndOf(m_winLastFocused
) : NULL
); 
1266 // the DialogProc for all wxWidgets dialogs 
1267 LONG APIENTRY _EXPORT
 
1268 wxDlgProc(HWND hDlg
, 
1270           WPARAM 
WXUNUSED(wParam
), 
1271           LPARAM 
WXUNUSED(lParam
)) 
1277             // under CE, add a "Ok" button in the dialog title bar and make it full 
1280             // TODO: find the window for this HWND, and take into account 
1281             // wxMAXIMIZE and wxCLOSE_BOX. For now, assume both are present. 
1283             // Standard SDK doesn't have aygshell.dll: see 
1284             // include/wx/msw/wince/libraries.h 
1285 #if defined(__WXWINCE__) && !defined(__WINCE_STANDARDSDK__) && !defined(__HANDHELDPC__) 
1286             SHINITDLGINFO shidi
; 
1287             shidi
.dwMask 
= SHIDIM_FLAGS
; 
1288             shidi
.dwFlags 
= SHIDIF_SIZEDLG 
// take account of the SIP or menubar 
1289 #ifndef __SMARTPHONE__ 
1294             SHInitDialog( &shidi 
); 
1295 #else // no SHInitDialog() 
1298             // for WM_INITDIALOG, returning TRUE tells system to set focus to 
1299             // the first control in the dialog box, but as we set the focus 
1300             // ourselves, we return FALSE for it as well 
1305     // for almost all messages, returning FALSE means that we didn't process 
1310 // ============================================================================ 
1311 // wxTLWHiddenParentModule implementation 
1312 // ============================================================================ 
1314 HWND 
wxTLWHiddenParentModule::ms_hwnd 
= NULL
; 
1316 const wxChar 
*wxTLWHiddenParentModule::ms_className 
= NULL
; 
1318 bool wxTLWHiddenParentModule::OnInit() 
1321     ms_className 
= NULL
; 
1326 void wxTLWHiddenParentModule::OnExit() 
1330         if ( !::DestroyWindow(ms_hwnd
) ) 
1332             wxLogLastError(_T("DestroyWindow(hidden TLW parent)")); 
1340         if ( !::UnregisterClass(ms_className
, wxGetInstance()) ) 
1342             wxLogLastError(_T("UnregisterClass(\"wxTLWHiddenParent\")")); 
1345         ms_className 
= NULL
; 
1350 HWND 
wxTLWHiddenParentModule::GetHWND() 
1354         if ( !ms_className 
) 
1356             static const wxChar 
*HIDDEN_PARENT_CLASS 
= _T("wxTLWHiddenParent"); 
1359             wxZeroMemory(wndclass
); 
1361             wndclass
.lpfnWndProc   
= DefWindowProc
; 
1362             wndclass
.hInstance     
= wxGetInstance(); 
1363             wndclass
.lpszClassName 
= HIDDEN_PARENT_CLASS
; 
1365             if ( !::RegisterClass(&wndclass
) ) 
1367                 wxLogLastError(_T("RegisterClass(\"wxTLWHiddenParent\")")); 
1371                 ms_className 
= HIDDEN_PARENT_CLASS
; 
1375         ms_hwnd 
= ::CreateWindow(ms_className
, wxEmptyString
, 0, 0, 0, 0, 0, NULL
, 
1376                                  (HMENU
)NULL
, wxGetInstance(), NULL
); 
1379             wxLogLastError(_T("CreateWindow(hidden TLW parent)"));