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     wxWindow 
*parent 
= GetParent(); 
 378     // for the dialogs without wxDIALOG_NO_PARENT style, use the top level 
 379     // app window as parent - this avoids creating modal dialogs without 
 381     if ( !parent 
&& !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT
) ) 
 383         parent 
= wxTheApp
->GetTopWindow(); 
 387             // don't use transient windows as parents, this is dangerous as it 
 388             // can lead to a crash if the parent is destroyed before the child 
 390             // also don't use the window which is currently hidden as then the 
 391             // dialog would be hidden as well 
 392             if ( (parent
->GetExtraStyle() & wxWS_EX_TRANSIENT
) || 
 400     m_hWnd 
= (WXHWND
)::CreateDialogIndirect
 
 403                         (DLGTEMPLATE
*)dlgTemplate
, 
 404                         parent 
? GetHwndOf(parent
) : NULL
, 
 410         wxFAIL_MSG(wxT("Failed to create dialog. Incorrect DLGTEMPLATE?")); 
 412         wxLogSysError(wxT("Can't create dialog using memory template")); 
 417 #if !defined(__WXWINCE__) 
 418     // For some reason, the system menu is activated when we use the 
 419     // WS_EX_CONTEXTHELP style, so let's set a reasonable icon 
 420     if ( HasExtraStyle(wxWS_EX_CONTEXTHELP
) ) 
 422         wxFrame 
*winTop 
= wxDynamicCast(wxTheApp
->GetTopWindow(), wxFrame
); 
 425             wxIcon icon 
= winTop
->GetIcon(); 
 428                 ::SendMessage(GetHwnd(), WM_SETICON
, 
 430                               (LPARAM
)GetHiconOf(icon
)); 
 434 #endif // !__WXWINCE__ 
 436     // move the dialog to its initial position without forcing repainting 
 438     (void)MSWGetCreateWindowCoords(pos
, size
, x
, y
, w
, h
); 
 440     if ( x 
== (int)CW_USEDEFAULT 
) 
 442         // centre it on the screen - what else can we do? 
 443         wxSize sizeDpy 
= wxGetDisplaySize(); 
 445         x 
= (sizeDpy
.x 
- w
) / 2; 
 446         y 
= (sizeDpy
.y 
- h
) / 2; 
 449 #if !defined(__WXWINCE__) || defined(__WINCE_STANDARDSDK__) 
 450     if ( !::MoveWindow(GetHwnd(), x
, y
, w
, h
, FALSE
) ) 
 452         wxLogLastError(wxT("MoveWindow")); 
 456     if ( !title
.empty() ) 
 458         ::SetWindowText(GetHwnd(), title
.wx_str()); 
 463 #ifdef __SMARTPHONE__ 
 464     // Work around title non-display glitch 
 469 #endif // __WXMICROWIN__/!__WXMICROWIN__ 
 472 bool wxTopLevelWindowMSW::CreateFrame(const wxString
& title
, 
 477     WXDWORD flags 
= MSWGetCreateWindowFlags(&exflags
); 
 479     const wxSize sz 
= IsAlwaysMaximized() ? wxDefaultSize 
: size
; 
 482     if ( wxTheApp
->GetLayoutDirection() == wxLayout_RightToLeft 
) 
 483         exflags 
|= WS_EX_LAYOUTRTL
; 
 486     return MSWCreate(MSWGetRegisteredClassName(), 
 487                      title
.wx_str(), pos
, sz
, flags
, exflags
); 
 490 bool wxTopLevelWindowMSW::Create(wxWindow 
*parent
, 
 492                                  const wxString
& title
, 
 496                                  const wxString
& name
) 
 498     bool ret 
wxDUMMY_INITIALIZE(false); 
 500     wxSize sizeReal 
= size
; 
 501     if ( !sizeReal
.IsFullySpecified() ) 
 503         sizeReal
.SetDefaults(GetDefaultSize()); 
 506     m_windowStyle 
= style
; 
 510     m_windowId 
= id 
== wxID_ANY 
? NewControlId() : id
; 
 512     wxTopLevelWindows
.Append(this); 
 515         parent
->AddChild(this); 
 517     if ( GetExtraStyle() & wxTOPLEVEL_EX_DIALOG 
) 
 519         // we have different dialog templates to allows creation of dialogs 
 520         // with & without captions under MSWindows, resizeable or not (but a 
 521         // resizeable dialog always has caption - otherwise it would look too 
 524         // we need 3 additional WORDs for dialog menu, class and title (as we 
 525         // don't use DS_SETFONT we don't need the fourth WORD for the font) 
 526         static const int dlgsize 
= sizeof(DLGTEMPLATE
) + (sizeof(WORD
) * 3); 
 527         DLGTEMPLATE 
*dlgTemplate 
= (DLGTEMPLATE 
*)malloc(dlgsize
); 
 528         memset(dlgTemplate
, 0, dlgsize
); 
 530         // these values are arbitrary, they won't be used normally anyhow 
 533         dlgTemplate
->cx 
= 144; 
 534         dlgTemplate
->cy 
= 75; 
 536         // reuse the code in MSWGetStyle() but correct the results slightly for 
 539         // NB: we need a temporary variable as we can't pass pointer to 
 540         //     dwExtendedStyle directly, it's not aligned correctly for 64 bit 
 542         WXDWORD dwExtendedStyle
; 
 543         dlgTemplate
->style 
= MSWGetStyle(style
, &dwExtendedStyle
); 
 544         dlgTemplate
->dwExtendedStyle 
= dwExtendedStyle
; 
 546         // all dialogs are popups 
 547         dlgTemplate
->style 
|= WS_POPUP
; 
 550         if ( wxTheApp
->GetLayoutDirection() == wxLayout_RightToLeft 
) 
 552             dlgTemplate
->dwExtendedStyle 
|= WS_EX_LAYOUTRTL
; 
 555         // force 3D-look if necessary, it looks impossibly ugly otherwise 
 556         if ( style 
& (wxRESIZE_BORDER 
| wxCAPTION
) ) 
 557             dlgTemplate
->style 
|= DS_MODALFRAME
; 
 560         ret 
= CreateDialog(dlgTemplate
, title
, pos
, sizeReal
); 
 565         ret 
= CreateFrame(title
, pos
, sizeReal
); 
 569     if ( ret 
&& !(GetWindowStyleFlag() & wxCLOSE_BOX
) ) 
 571         EnableCloseButton(false); 
 575     // for standard dialogs the dialog manager generates WM_CHANGEUISTATE 
 576     // itself but for custom windows we have to do it ourselves in order to 
 577     // make the keyboard indicators (such as underlines for accelerators and 
 578     // focus rectangles) work under Win2k+ 
 581         MSWUpdateUIState(UIS_INITIALIZE
); 
 584     // Note: if we include PocketPC in this test, dialogs can fail to show up, 
 585     // for example the text entry dialog in the dialogs sample. Problem with Maximise()? 
 586 #if defined(__WXWINCE__) && (defined(__SMARTPHONE__) || defined(__WINCE_STANDARDSDK__)) 
 587     if ( ( style 
& wxMAXIMIZE 
) || IsAlwaysMaximized() ) 
 593 #if defined(__SMARTPHONE__) && defined(__WXWINCE__) 
 594     SetRightMenu(); // to nothing for initialization 
 600 wxTopLevelWindowMSW::~wxTopLevelWindowMSW() 
 604 #if defined(__SMARTPHONE__) || defined(__POCKETPC__) 
 605     SHACTIVATEINFO
* info 
= (SHACTIVATEINFO
*) m_activateInfo
; 
 607     m_activateInfo 
= NULL
; 
 610     // after destroying an owned window, Windows activates the next top level 
 611     // window in Z order but it may be different from our owner (to reproduce 
 612     // this simply Alt-TAB to another application and back before closing the 
 613     // owned frame) whereas we always want to yield activation to our parent 
 614     if ( HasFlag(wxFRAME_FLOAT_ON_PARENT
) ) 
 616         wxWindow 
*parent 
= GetParent(); 
 619             ::BringWindowToTop(GetHwndOf(parent
)); 
 624 // ---------------------------------------------------------------------------- 
 625 // wxTopLevelWindowMSW showing 
 626 // ---------------------------------------------------------------------------- 
 628 void wxTopLevelWindowMSW::DoShowWindow(int nShowCmd
) 
 630     ::ShowWindow(GetHwnd(), nShowCmd
); 
 632     m_iconized 
= nShowCmd 
== SW_MINIMIZE
; 
 635 bool wxTopLevelWindowMSW::Show(bool show
) 
 637     // don't use wxWindow version as we want to call DoShowWindow() ourselves 
 638     if ( !wxWindowBase::Show(show
) ) 
 644         if ( m_maximizeOnShow 
) 
 647             nShowCmd 
= SW_MAXIMIZE
; 
 649             // This is necessary, or no window appears 
 650 #if defined( __WINCE_STANDARDSDK__) || defined(__SMARTPHONE__) 
 651             DoShowWindow(SW_SHOW
); 
 654             m_maximizeOnShow 
= false; 
 656         else if ( m_iconized 
) 
 659             nShowCmd 
= SW_MINIMIZE
; 
 663             // we shouldn't use SW_SHOW which also activates the window for 
 664             // tool frames (as they shouldn't steal focus from the main window) 
 665             // nor for the currently disabled windows as they would be enabled 
 667             if ( HasFlag(wxFRAME_TOOL_WINDOW
) || !IsEnabled() ) 
 668                 nShowCmd 
= SW_SHOWNA
; 
 678     DoShowWindow(nShowCmd
); 
 680 #if defined(__WXWINCE__) && (_WIN32_WCE >= 400 && !defined(__POCKETPC__) && !defined(__SMARTPHONE__)) 
 681     // Addornments have to be added when the frame is the correct size 
 682     wxFrame
* frame 
= wxDynamicCast(this, wxFrame
); 
 683     if (frame 
&& frame
->GetMenuBar()) 
 684         frame
->GetMenuBar()->AddAdornments(GetWindowStyleFlag()); 
 687     // we only set pending size if we're maximized before being shown, now that 
 688     // we're shown we don't need it any more (it is reset in size event handler 
 689     // for child windows but we have to do it ourselves for this parent window) 
 690     m_pendingSize 
= wxDefaultSize
; 
 695 // ---------------------------------------------------------------------------- 
 696 // wxTopLevelWindowMSW maximize/minimize 
 697 // ---------------------------------------------------------------------------- 
 699 void wxTopLevelWindowMSW::Maximize(bool maximize
) 
 703         // just maximize it directly 
 704         DoShowWindow(maximize 
? SW_MAXIMIZE 
: SW_RESTORE
); 
 708         // we can't maximize the hidden frame because it shows it as well, 
 709         // so just remember that we should do it later in this case 
 710         m_maximizeOnShow 
= maximize
; 
 712         // after calling Maximize() the client code expects to get the frame 
 713         // "real" size and doesn't want to know that, because of implementation 
 714         // details, the frame isn't really maximized yet but will be only once 
 715         // it's shown, so return our size as it will be then in this case 
 718             // we must only change pending size here, and not call SetSize() 
 719             // because otherwise Windows would think that this (full screen) 
 720             // size is the natural size for the frame and so would use it when 
 721             // the user clicks on "restore" title bar button instead of the 
 722             // correct initial frame size 
 724             // NB: unfortunately we don't know which display we're on yet so we 
 725             //     have to use the default one 
 726             m_pendingSize 
= wxGetClientDisplayRect().GetSize(); 
 728         //else: can't do anything in this case, we don't have the old size 
 732 bool wxTopLevelWindowMSW::IsMaximized() const 
 734     return IsAlwaysMaximized() || 
 735 #if !defined(__SMARTPHONE__) && !defined(__POCKETPC__) && !defined(__WINCE_STANDARDSDK__) 
 737            (::IsZoomed(GetHwnd()) != 0) || 
 742 void wxTopLevelWindowMSW::Iconize(bool iconize
) 
 746         // change the window state immediately 
 747         DoShowWindow(iconize 
? SW_MINIMIZE 
: SW_RESTORE
); 
 751         // iconizing the window shouldn't show it so just remember that we need 
 752         // to become iconized when shown later 
 757 bool wxTopLevelWindowMSW::IsIconized() const 
 765     // don't use m_iconized, it may be briefly out of sync with the real state 
 766     // as it's only modified when we receive a WM_SIZE and we could be called 
 767     // from an event handler from one of the messages we receive before it, 
 769     return ::IsIconic(GetHwnd()) != 0; 
 773 void wxTopLevelWindowMSW::Restore() 
 775     DoShowWindow(SW_RESTORE
); 
 778 void wxTopLevelWindowMSW::SetLayoutDirection(wxLayoutDirection dir
) 
 780     if ( dir 
== wxLayout_Default 
) 
 781         dir 
= wxTheApp
->GetLayoutDirection(); 
 783     if ( dir 
!= wxLayout_Default 
) 
 784         wxTopLevelWindowBase::SetLayoutDirection(dir
); 
 787 // ---------------------------------------------------------------------------- 
 788 // wxTopLevelWindowMSW geometry 
 789 // ---------------------------------------------------------------------------- 
 793 void wxTopLevelWindowMSW::DoGetPosition(int *x
, int *y
) const 
 798         wp
.length 
= sizeof(WINDOWPLACEMENT
); 
 799         if ( ::GetWindowPlacement(GetHwnd(), &wp
) ) 
 801             RECT
& rc 
= wp
.rcNormalPosition
; 
 803             // the position returned by GetWindowPlacement() is in workspace 
 804             // coordinates except for windows with WS_EX_TOOLWINDOW style 
 805             if ( !HasFlag(wxFRAME_TOOL_WINDOW
) ) 
 807                 // we must use the correct display for the translation as the 
 808                 // task bar might be shown on one display but not the other one 
 809                 int n 
= wxDisplay::GetFromWindow(this); 
 810                 wxDisplay 
dpy(n 
== wxNOT_FOUND 
? 0 : n
); 
 811                 const wxPoint ptOfs 
= dpy
.GetClientArea().GetPosition() - 
 812                                       dpy
.GetGeometry().GetPosition(); 
 826         wxLogLastError(_T("GetWindowPlacement")); 
 830     wxTopLevelWindowBase::DoGetPosition(x
, y
); 
 833 void wxTopLevelWindowMSW::DoGetSize(int *width
, int *height
) const 
 838         wp
.length 
= sizeof(WINDOWPLACEMENT
); 
 839         if ( ::GetWindowPlacement(GetHwnd(), &wp
) ) 
 841             const RECT
& rc 
= wp
.rcNormalPosition
; 
 844                 *width 
= rc
.right 
- rc
.left
; 
 846                 *height 
= rc
.bottom 
- rc
.top
; 
 851         wxLogLastError(_T("GetWindowPlacement")); 
 855     wxTopLevelWindowBase::DoGetSize(width
, height
); 
 858 #endif // __WXWINCE__ 
 860 // ---------------------------------------------------------------------------- 
 861 // wxTopLevelWindowMSW fullscreen 
 862 // ---------------------------------------------------------------------------- 
 864 bool wxTopLevelWindowMSW::ShowFullScreen(bool show
, long style
) 
 866     if ( show 
== IsFullScreen() ) 
 872     m_fsIsShowing 
= show
; 
 878         // zap the frame borders 
 880         // save the 'normal' window style 
 881         m_fsOldWindowStyle 
= GetWindowLong(GetHwnd(), GWL_STYLE
); 
 883         // save the old position, width & height, maximize state 
 884         m_fsOldSize 
= GetRect(); 
 885         m_fsIsMaximized 
= IsMaximized(); 
 887         // decide which window style flags to turn off 
 888         LONG newStyle 
= m_fsOldWindowStyle
; 
 891         if (style 
& wxFULLSCREEN_NOBORDER
) 
 893             offFlags 
|= WS_BORDER
; 
 895             offFlags 
|= WS_THICKFRAME
; 
 898         if (style 
& wxFULLSCREEN_NOCAPTION
) 
 899             offFlags 
|= WS_CAPTION 
| WS_SYSMENU
; 
 901         newStyle 
&= ~offFlags
; 
 903         // change our window style to be compatible with full-screen mode 
 904         ::SetWindowLong(GetHwnd(), GWL_STYLE
, newStyle
); 
 908         // resize to the size of the display containing us 
 909         int dpy 
= wxDisplay::GetFromWindow(this); 
 910         if ( dpy 
!= wxNOT_FOUND 
) 
 912             rect 
= wxDisplay(dpy
).GetGeometry(); 
 914         else // fall back to the main desktop 
 915 #endif // wxUSE_DISPLAY 
 917             // resize to the size of the desktop 
 918             wxCopyRECTToRect(wxGetWindowRect(::GetDesktopWindow()), rect
); 
 920             // FIXME: size of the bottom menu (toolbar) 
 921             // should be taken in account 
 922             rect
.height 
+= rect
.y
; 
 929         // now flush the window style cache and actually go full-screen 
 930         long flags 
= SWP_FRAMECHANGED
; 
 932         // showing the frame full screen should also show it if it's still 
 936             // don't call wxWindow version to avoid flicker from calling 
 937             // ::ShowWindow() -- we're going to show the window at the correct 
 938             // location directly below -- but do call the wxWindowBase version 
 939             // to sync the internal m_isShown flag 
 940             wxWindowBase::Show(); 
 942             flags 
|= SWP_SHOWWINDOW
; 
 945         SetWindowPos(GetHwnd(), HWND_TOP
, 
 946                      rect
.x
, rect
.y
, rect
.width
, rect
.height
, 
 949 #if !defined(__HANDHELDPC__) && (defined(__WXWINCE__) && (_WIN32_WCE < 400)) 
 950         ::SHFullScreen(GetHwnd(), SHFS_HIDETASKBAR 
| SHFS_HIDESIPBUTTON
); 
 953         // finally send an event allowing the window to relayout itself &c 
 954         wxSizeEvent 
event(rect
.GetSize(), GetId()); 
 955         HandleWindowEvent(event
); 
 957     else // stop showing full screen 
 959 #if !defined(__HANDHELDPC__) && (defined(__WXWINCE__) && (_WIN32_WCE < 400)) 
 960         ::SHFullScreen(GetHwnd(), SHFS_SHOWTASKBAR 
| SHFS_SHOWSIPBUTTON
); 
 962         Maximize(m_fsIsMaximized
); 
 963         SetWindowLong(GetHwnd(),GWL_STYLE
, m_fsOldWindowStyle
); 
 964         SetWindowPos(GetHwnd(),HWND_TOP
,m_fsOldSize
.x
, m_fsOldSize
.y
, 
 965             m_fsOldSize
.width
, m_fsOldSize
.height
, SWP_FRAMECHANGED
); 
 971 // ---------------------------------------------------------------------------- 
 972 // wxTopLevelWindowMSW misc 
 973 // ---------------------------------------------------------------------------- 
 975 void wxTopLevelWindowMSW::SetTitle( const wxString
& title
) 
 980 wxString 
wxTopLevelWindowMSW::GetTitle() const 
 985 bool wxTopLevelWindowMSW::DoSelectAndSetIcon(const wxIconBundle
& icons
, 
 990     const wxSize 
size(::GetSystemMetrics(smX
), ::GetSystemMetrics(smY
)); 
 992     const wxIcon icon 
= icons
.GetIconOfExactSize(size
); 
 995         ::SendMessage(GetHwnd(), WM_SETICON
, i
, (LPARAM
)GetHiconOf(icon
)); 
1002 void wxTopLevelWindowMSW::SetIcons(const wxIconBundle
& icons
) 
1004     wxTopLevelWindowBase::SetIcons(icons
); 
1006     if ( icons
.IsEmpty() ) 
1008         // FIXME: SetIcons(wxNullIconBundle) should unset existing icons, 
1009         //        but we currently don't do that 
1010         wxASSERT_MSG( m_icons
.IsEmpty(), "unsetting icons doesn't work" ); 
1015         DoSelectAndSetIcon(icons
, SM_CXSMICON
, SM_CYSMICON
, ICON_SMALL
); 
1016     if ( DoSelectAndSetIcon(icons
, SM_CXICON
, SM_CYICON
, ICON_BIG
) ) 
1021         wxFAIL_MSG( "icon bundle doesn't contain any suitable icon" ); 
1025 bool wxTopLevelWindowMSW::EnableCloseButton(bool enable
) 
1027 #if !defined(__WXMICROWIN__) 
1028     // get system (a.k.a. window) menu 
1029     HMENU hmenu 
= GetSystemMenu(GetHwnd(), FALSE 
/* get it */); 
1032         // no system menu at all -- ok if we want to remove the close button 
1033         // anyhow, but bad if we want to show it 
1037     // enabling/disabling the close item from it also automatically 
1038     // disables/enables the close title bar button 
1039     if ( ::EnableMenuItem(hmenu
, SC_CLOSE
, 
1041                           (enable 
? MF_ENABLED 
: MF_GRAYED
)) == -1 ) 
1043         wxLogLastError(_T("EnableMenuItem(SC_CLOSE)")); 
1048     // update appearance immediately 
1049     if ( !::DrawMenuBar(GetHwnd()) ) 
1051         wxLogLastError(_T("DrawMenuBar")); 
1054 #endif // !__WXMICROWIN__ 
1061 bool wxTopLevelWindowMSW::SetShape(const wxRegion
& region
) 
1063     wxCHECK_MSG( HasFlag(wxFRAME_SHAPED
), false, 
1064                  _T("Shaped windows must be created with the wxFRAME_SHAPED style.")); 
1066     // The empty region signifies that the shape should be removed from the 
1068     if ( region
.IsEmpty() ) 
1070         if (::SetWindowRgn(GetHwnd(), NULL
, TRUE
) == 0) 
1072             wxLogLastError(_T("SetWindowRgn")); 
1078     // Windows takes ownership of the region, so 
1079     // we'll have to make a copy of the region to give to it. 
1080     DWORD noBytes 
= ::GetRegionData(GetHrgnOf(region
), 0, NULL
); 
1081     RGNDATA 
*rgnData 
= (RGNDATA
*) new char[noBytes
]; 
1082     ::GetRegionData(GetHrgnOf(region
), noBytes
, rgnData
); 
1083     HRGN hrgn 
= ::ExtCreateRegion(NULL
, noBytes
, rgnData
); 
1084     delete[] (char*) rgnData
; 
1086     // SetWindowRgn expects the region to be in coordinants 
1087     // relative to the window, not the client area.  Figure 
1088     // out the offset, if any. 
1090     DWORD dwStyle 
=   ::GetWindowLong(GetHwnd(), GWL_STYLE
); 
1091     DWORD dwExStyle 
= ::GetWindowLong(GetHwnd(), GWL_EXSTYLE
); 
1092     ::GetClientRect(GetHwnd(), &rect
); 
1093     ::AdjustWindowRectEx(&rect
, dwStyle
, FALSE
, dwExStyle
); 
1094     ::OffsetRgn(hrgn
, -rect
.left
, -rect
.top
); 
1096     // Now call the shape API with the new region. 
1097     if (::SetWindowRgn(GetHwnd(), hrgn
, TRUE
) == 0) 
1099         wxLogLastError(_T("SetWindowRgn")); 
1105 #endif // !__WXWINCE__ 
1107 void wxTopLevelWindowMSW::RequestUserAttention(int flags
) 
1109     // check if we can use FlashWindowEx(): unfortunately a simple test for 
1110     // FLASHW_STOP doesn't work because MSVC6 headers do #define it but don't 
1111     // provide FlashWindowEx() declaration, so try to detect whether we have 
1112     // real headers for WINVER 0x0500 by checking for existence of a symbol not 
1113     // declated in MSVC6 header 
1114 #if defined(FLASHW_STOP) && defined(VK_XBUTTON1) && wxUSE_DYNLIB_CLASS 
1115     // available in the headers, check if it is supported by the system 
1116     typedef BOOL (WINAPI 
*FlashWindowEx_t
)(FLASHWINFO 
*pfwi
); 
1117     static FlashWindowEx_t s_pfnFlashWindowEx 
= NULL
; 
1118     if ( !s_pfnFlashWindowEx 
) 
1120         wxDynamicLibrary 
dllUser32(_T("user32.dll")); 
1121         s_pfnFlashWindowEx 
= (FlashWindowEx_t
) 
1122                                 dllUser32
.GetSymbol(_T("FlashWindowEx")); 
1124         // we can safely unload user32.dll here, it's going to remain loaded as 
1125         // long as the program is running anyhow 
1128     if ( s_pfnFlashWindowEx 
) 
1130         WinStruct
<FLASHWINFO
> fwi
; 
1131         fwi
.hwnd 
= GetHwnd(); 
1132         fwi
.dwFlags 
= FLASHW_ALL
; 
1133         if ( flags 
& wxUSER_ATTENTION_INFO 
) 
1135             // just flash a few times 
1138         else // wxUSER_ATTENTION_ERROR 
1140             // flash until the user notices it 
1141             fwi
.dwFlags 
|= FLASHW_TIMERNOFG
; 
1144         s_pfnFlashWindowEx(&fwi
); 
1146     else // FlashWindowEx() not available 
1147 #endif // FlashWindowEx() defined 
1151         ::FlashWindow(GetHwnd(), TRUE
); 
1152 #endif // __WXWINCE__ 
1156 // --------------------------------------------------------------------------- 
1158 bool wxTopLevelWindowMSW::SetTransparent(wxByte alpha
) 
1160 #if wxUSE_DYNLIB_CLASS 
1161     typedef DWORD (WINAPI 
*PSETLAYEREDWINDOWATTR
)(HWND
, DWORD
, BYTE
, DWORD
); 
1162     static PSETLAYEREDWINDOWATTR
 
1163         pSetLayeredWindowAttributes 
= (PSETLAYEREDWINDOWATTR
)-1; 
1165     if ( pSetLayeredWindowAttributes 
== (PSETLAYEREDWINDOWATTR
)-1 ) 
1167         wxDynamicLibrary 
dllUser32(_T("user32.dll")); 
1169         // use RawGetSymbol() and not GetSymbol() to avoid error messages under 
1170         // Windows 95: there is nothing the user can do about this anyhow 
1171         pSetLayeredWindowAttributes 
= (PSETLAYEREDWINDOWATTR
) 
1172             dllUser32
.RawGetSymbol(wxT("SetLayeredWindowAttributes")); 
1174         // it's ok to destroy dllUser32 here, we link statically to user32.dll 
1175         // anyhow so it won't be unloaded 
1178     if ( !pSetLayeredWindowAttributes 
) 
1180 #endif // wxUSE_DYNLIB_CLASS 
1182     LONG exstyle 
= GetWindowLong(GetHwnd(), GWL_EXSTYLE
); 
1184     // if setting alpha to fully opaque then turn off the layered style 
1187         SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyle 
& ~WS_EX_LAYERED
); 
1192 #if wxUSE_DYNLIB_CLASS 
1193     // Otherwise, set the layered style if needed and set the alpha value 
1194     if ((exstyle 
& WS_EX_LAYERED
) == 0 ) 
1195         SetWindowLong(GetHwnd(), GWL_EXSTYLE
, exstyle 
| WS_EX_LAYERED
); 
1197     if ( pSetLayeredWindowAttributes(GetHwnd(), 0, (BYTE
)alpha
, LWA_ALPHA
) ) 
1199 #endif // wxUSE_DYNLIB_CLASS 
1204 bool wxTopLevelWindowMSW::CanSetTransparent() 
1206     // The API is available on win2k and above 
1208     static int os_type 
= -1; 
1209     static int ver_major 
= -1; 
1212         os_type 
= ::wxGetOsVersion(&ver_major
); 
1214     return (os_type 
== wxOS_WINDOWS_NT 
&& ver_major 
>= 5); 
1218 void wxTopLevelWindowMSW::DoFreeze() 
1220     // do nothing: freezing toplevel window causes paint and mouse events 
1221     // to go through it any TLWs under it, so the best we can do is to freeze 
1222     // all children -- and wxWindowBase::Freeze() does that 
1225 void wxTopLevelWindowMSW::DoThaw() 
1227     // intentionally empty -- see DoFreeze() 
1231 // ---------------------------------------------------------------------------- 
1232 // wxTopLevelWindow event handling 
1233 // ---------------------------------------------------------------------------- 
1235 // Default activation behaviour - set the focus for the first child 
1237 void wxTopLevelWindowMSW::OnActivate(wxActivateEvent
& event
) 
1239     if ( event
.GetActive() ) 
1241         // restore focus to the child which was last focused unless we already 
1243         wxLogTrace(_T("focus"), _T("wxTLW %p activated."), m_hWnd
); 
1245         wxWindow 
*winFocus 
= FindFocus(); 
1246         if ( !winFocus 
|| wxGetTopLevelParent(winFocus
) != this ) 
1248             wxWindow 
*parent 
= m_winLastFocused 
? m_winLastFocused
->GetParent() 
1255             wxSetFocusToChild(parent
, &m_winLastFocused
); 
1258     else // deactivating 
1260         // remember the last focused child if it is our child 
1261         m_winLastFocused 
= FindFocus(); 
1263         if ( m_winLastFocused 
) 
1265             // let it know that it doesn't have focus any more 
1266             // But this will already be done via WM_KILLFOCUS, so we'll get two kill 
1267             // focus events if we call it explicitly. 
1268             // m_winLastFocused->HandleKillFocus((WXHWND)NULL); 
1270             // and don't remember it if it's a child from some other frame 
1271             if ( wxGetTopLevelParent(m_winLastFocused
) != this ) 
1273                 m_winLastFocused 
= NULL
; 
1277         wxLogTrace(_T("focus"), 
1278                    _T("wxTLW %p deactivated, last focused: %p."), 
1280                    m_winLastFocused 
? GetHwndOf(m_winLastFocused
) : NULL
); 
1286 // the DialogProc for all wxWidgets dialogs 
1287 LONG APIENTRY _EXPORT
 
1288 wxDlgProc(HWND hDlg
, 
1290           WPARAM 
WXUNUSED(wParam
), 
1291           LPARAM 
WXUNUSED(lParam
)) 
1297             // under CE, add a "Ok" button in the dialog title bar and make it full 
1300             // TODO: find the window for this HWND, and take into account 
1301             // wxMAXIMIZE and wxCLOSE_BOX. For now, assume both are present. 
1303             // Standard SDK doesn't have aygshell.dll: see 
1304             // include/wx/msw/wince/libraries.h 
1305 #if defined(__WXWINCE__) && !defined(__WINCE_STANDARDSDK__) && !defined(__HANDHELDPC__) 
1306             SHINITDLGINFO shidi
; 
1307             shidi
.dwMask 
= SHIDIM_FLAGS
; 
1308             shidi
.dwFlags 
= SHIDIF_SIZEDLG 
// take account of the SIP or menubar 
1309 #ifndef __SMARTPHONE__ 
1314             SHInitDialog( &shidi 
); 
1315 #else // no SHInitDialog() 
1318             // for WM_INITDIALOG, returning TRUE tells system to set focus to 
1319             // the first control in the dialog box, but as we set the focus 
1320             // ourselves, we return FALSE for it as well 
1325     // for almost all messages, returning FALSE means that we didn't process 
1330 // ============================================================================ 
1331 // wxTLWHiddenParentModule implementation 
1332 // ============================================================================ 
1334 HWND 
wxTLWHiddenParentModule::ms_hwnd 
= NULL
; 
1336 const wxChar 
*wxTLWHiddenParentModule::ms_className 
= NULL
; 
1338 bool wxTLWHiddenParentModule::OnInit() 
1341     ms_className 
= NULL
; 
1346 void wxTLWHiddenParentModule::OnExit() 
1350         if ( !::DestroyWindow(ms_hwnd
) ) 
1352             wxLogLastError(_T("DestroyWindow(hidden TLW parent)")); 
1360         if ( !::UnregisterClass(ms_className
, wxGetInstance()) ) 
1362             wxLogLastError(_T("UnregisterClass(\"wxTLWHiddenParent\")")); 
1365         ms_className 
= NULL
; 
1370 HWND 
wxTLWHiddenParentModule::GetHWND() 
1374         if ( !ms_className 
) 
1376             static const wxChar 
*HIDDEN_PARENT_CLASS 
= _T("wxTLWHiddenParent"); 
1379             wxZeroMemory(wndclass
); 
1381             wndclass
.lpfnWndProc   
= DefWindowProc
; 
1382             wndclass
.hInstance     
= wxGetInstance(); 
1383             wndclass
.lpszClassName 
= HIDDEN_PARENT_CLASS
; 
1385             if ( !::RegisterClass(&wndclass
) ) 
1387                 wxLogLastError(_T("RegisterClass(\"wxTLWHiddenParent\")")); 
1391                 ms_className 
= HIDDEN_PARENT_CLASS
; 
1395         ms_hwnd 
= ::CreateWindow(ms_className
, wxEmptyString
, 0, 0, 0, 0, 0, NULL
, 
1396                                  (HMENU
)NULL
, wxGetInstance(), NULL
); 
1399             wxLogLastError(_T("CreateWindow(hidden TLW parent)"));