1/////////////////////////////////////////////////////////////////////////////// 2// Name: src/os2/toplevel.cpp 3// Purpose: implements wxTopLevelWindow for OS/2 4// Author: Vadim Zeitlin 5// Modified by: 6// Created: 30.12.01 7// RCS-ID: $Id: toplevel.cpp 40943 2006-08-31 19:31:43Z ABX $ 8// Copyright: (c) 2001 SciTech Software, Inc. (www.scitechsoft.com) 9// License: wxWindows licence 10/////////////////////////////////////////////////////////////////////////////// 11 12// ============================================================================ 13// declarations 14// ============================================================================ 15 16// ---------------------------------------------------------------------------- 17// headers 18// ---------------------------------------------------------------------------- 19 20// For compilers that support precompilation, includes "wx.h". 21#include "wx/wxprec.h" 22 23#ifdef __BORLANDC__ 24 #pragma hdrstop 25#endif 26 27#include "wx/toplevel.h" 28 29#ifndef WX_PRECOMP 30 #include "wx/app.h" 31 #include "wx/dialog.h" 32 #include "wx/string.h" 33 #include "wx/log.h" 34 #include "wx/intl.h" 35 #include "wx/frame.h" 36 #include "wx/control.h" 37 #include "wx/containr.h" // wxSetFocusToChild() 38 #include "wx/settings.h" 39 #include "wx/module.h" // wxSetFocusToChild() 40#endif //WX_PRECOMP 41 42#include "wx/os2/private.h" 43 44// ---------------------------------------------------------------------------- 45// stubs for missing functions under MicroWindows 46// ---------------------------------------------------------------------------- 47 48 49// ---------------------------------------------------------------------------- 50// globals 51// ---------------------------------------------------------------------------- 52 53// the name of the default wxWidgets class 54extern void wxAssociateWinWithHandle( HWND hWnd, wxWindowOS2* pWin ); 55 56bool wxTopLevelWindowOS2::m_sbInitialized = false; 57wxWindow* wxTopLevelWindowOS2::m_spHiddenParent = NULL; 58 59// ============================================================================ 60// wxTopLevelWindowOS2 implementation 61// ============================================================================ 62 63BEGIN_EVENT_TABLE(wxTopLevelWindowOS2, wxTopLevelWindowBase) 64 EVT_ACTIVATE(wxTopLevelWindowOS2::OnActivate) 65END_EVENT_TABLE() 66 67// ============================================================================ 68// wxTopLevelWindowMSW implementation 69// ============================================================================ 70 71// Dialog window proc 72MRESULT EXPENTRY wxDlgProc( HWND WXUNUSED(hWnd) 73 ,UINT uMessage 74 ,void * WXUNUSED(wParam) 75 ,void * WXUNUSED(lParam) 76 ) 77{ 78 switch(uMessage) 79 { 80 case WM_INITDLG: 81 // 82 // For this message, returning TRUE tells system to set focus to 83 // the first control in the dialog box, but we set the focus 84 // ourselves, however in OS/2 we must return true to enable the dialog 85 // 86 return (MRESULT)TRUE; 87 default: 88 // 89 // For all the other ones, FALSE means that we didn't process the 90 // message 91 // 92 return (MRESULT)FALSE; 93 } 94} // end of wxDlgProc 95 96// ---------------------------------------------------------------------------- 97// wxTLWHiddenParentModule: used to manage the hidden parent window (we need a 98// module to ensure that the window is always deleted) 99// ---------------------------------------------------------------------------- 100 101class wxTLWHiddenParentModule : public wxModule 102{ 103public: 104 // 105 // Module init/finalize 106 // 107 virtual bool OnInit(void); 108 virtual void OnExit(void); 109 110 // 111 // Get the hidden window (creates on demand) 112 // 113 static HWND GetHWND(void); 114 115private: 116 // 117 // The HWND of the hidden parent 118 // 119 static HWND m_shWnd; 120 121 // 122 // The class used to create it 123 // 124 static const wxChar* m_szClassName; 125 DECLARE_DYNAMIC_CLASS(wxTLWHiddenParentModule) 126}; // end of CLASS wxTLWHiddenParentModule 127 128IMPLEMENT_DYNAMIC_CLASS(wxTLWHiddenParentModule, wxModule) 129 130// ---------------------------------------------------------------------------- 131// wxTopLevelWindowOS2 creation 132// ---------------------------------------------------------------------------- 133 134void wxTopLevelWindowOS2::Init() 135{ 136 m_bIconized = m_bMaximizeOnShow = false; 137 138 // 139 // Unlike (almost?) all other windows, frames are created hidden 140 // 141 m_isShown = false; 142 143 // 144 // Data to save/restore when calling ShowFullScreen 145 m_lFsStyle = 0; 146 m_lFsOldWindowStyle = 0; 147 m_bFsIsMaximized = false; 148 m_bFsIsShowing = false; 149 150 m_hFrame = NULLHANDLE; 151 memset(&m_vSwp, 0, sizeof(SWP)); 152 memset(&m_vSwpClient, 0, sizeof(SWP)); 153 m_pWinLastFocused = (wxWindow *)NULL; 154} // end of wxTopLevelWindowIOS2::Init 155 156void wxTopLevelWindowOS2::OnActivate( 157 wxActivateEvent& rEvent 158) 159{ 160 if (rEvent.GetActive()) 161 { 162 // 163 // Restore focus to the child which was last focused 164 // 165 wxLogTrace(_T("focus"), _T("wxTLW %08lx activated."), m_hWnd); 166 167 wxWindow* pParent = m_pWinLastFocused ? m_pWinLastFocused->GetParent() 168 : NULL; 169 if (!pParent) 170 { 171 pParent = this; 172 } 173 174 wxSetFocusToChild( pParent 175 ,&m_pWinLastFocused 176 ); 177 } 178 else // deactivating 179 { 180 // 181 // Remember the last focused child if it is our child 182 // 183 m_pWinLastFocused = FindFocus(); 184 185 // 186 // So we NULL it out if it's a child from some other frame 187 // 188 wxWindow* pWin = m_pWinLastFocused; 189 190 while (pWin) 191 { 192 if (pWin->IsTopLevel()) 193 { 194 if (pWin != this) 195 { 196 m_pWinLastFocused = NULL; 197 } 198 break; 199 } 200 pWin = pWin->GetParent(); 201 } 202 203 wxLogTrace(_T("focus"), 204 _T("wxTLW %08lx deactivated, last focused: %08lx."), 205 m_hWnd, 206 m_pWinLastFocused ? GetHwndOf(m_pWinLastFocused) 207 : NULL); 208 rEvent.Skip(); 209 } 210} // end of wxTopLevelWindowOS2::OnActivate 211 212WXDWORD wxTopLevelWindowOS2::OS2GetStyle( 213 long lStyle 214, WXDWORD* pdwExflags 215) const 216{ 217 long lMsflags = wxWindow::OS2GetStyle( (lStyle & ~wxBORDER_MASK) | wxBORDER_NONE 218 ,pdwExflags 219 ); 220 221 if ((lStyle & wxDEFAULT_FRAME_STYLE) == wxDEFAULT_FRAME_STYLE) 222 lMsflags |= FCF_SIZEBORDER | FCF_TITLEBAR | FCF_SYSMENU | 223 FCF_MINMAX | FCF_TASKLIST; 224 225 if ((lStyle & wxCAPTION) == wxCAPTION) 226 lMsflags |= FCF_TASKLIST; 227 else 228 lMsflags |= FCF_NOMOVEWITHOWNER; 229 230 if ((lStyle & wxVSCROLL) == wxVSCROLL) 231 lMsflags |= FCF_VERTSCROLL; 232 if ((lStyle & wxHSCROLL) == wxHSCROLL) 233 lMsflags |= FCF_HORZSCROLL; 234 if (lStyle & wxMINIMIZE_BOX) 235 lMsflags |= FCF_MINBUTTON; 236 if (lStyle & wxMAXIMIZE_BOX) 237 lMsflags |= FCF_MAXBUTTON; 238 if (lStyle & wxRESIZE_BORDER) 239 lMsflags |= FCF_DLGBORDER; 240 if (lStyle & wxSYSTEM_MENU) 241 lMsflags |= FCF_SYSMENU; 242 if (lStyle & wxCAPTION) 243 lMsflags |= FCF_TASKLIST; 244 if (lStyle & wxCLIP_CHILDREN) 245 { 246 // Invalid for frame windows under PM 247 } 248 249 if (lStyle & wxTINY_CAPTION_VERT) 250 lMsflags |= FCF_TASKLIST; 251 if (lStyle & wxTINY_CAPTION_HORIZ) 252 lMsflags |= FCF_TASKLIST; 253 254 if ((lStyle & wxRESIZE_BORDER) == 0) 255 lMsflags |= FCF_BORDER; 256 if (lStyle & wxFRAME_TOOL_WINDOW) 257 *pdwExflags = kFrameToolWindow; 258 259 if (lStyle & wxSTAY_ON_TOP) 260 lMsflags |= FCF_SYSMODAL; 261 262 return lMsflags; 263} // end of wxTopLevelWindowOS2::OS2GetCreateWindowFlags 264 265WXHWND wxTopLevelWindowOS2::OS2GetParent() const 266{ 267 HWND hWndParent = NULL; 268 269 // 270 // For the frames without wxFRAME_FLOAT_ON_PARENT style we should use NULL 271 // parent HWND or it would be always on top of its parent which is not what 272 // we usually want (in fact, we only want it for frames with the 273 // wxFRAME_FLOAT_ON_PARENT flag) 274 // 275 if (HasFlag(wxFRAME_FLOAT_ON_PARENT) ) 276 { 277 const wxWindow* pParent = GetParent(); 278 279 if (!pParent) 280 { 281 // 282 // This flag doesn't make sense then and will be ignored 283 // 284 wxFAIL_MSG( _T("wxFRAME_FLOAT_ON_PARENT but no parent?") ); 285 } 286 else 287 { 288 hWndParent = GetHwndOf(pParent); 289 } 290 } 291 //else: don't float on parent, must not be owned 292 293 // 294 // Now deal with the 2nd taskbar-related problem (see comments above in 295 // OS2GetStyle()) 296 // 297 if (HasFlag(wxFRAME_NO_TASKBAR) && !hWndParent) 298 { 299 // 300 // Use hidden parent 301 // 302 hWndParent = wxTLWHiddenParentModule::GetHWND(); 303 } 304 return (WXHWND)hWndParent; 305} // end of wxTopLevelWindowOS2::OS2GetParent 306 307 308bool wxTopLevelWindowOS2::CreateDialog( ULONG ulDlgTemplate, 309 const wxString& WXUNUSED(rsTitle), 310 const wxPoint& rPos, 311 const wxSize& rSize ) 312{ 313 wxWindow* pParent = GetParent(); 314 315 // 316 // For the dialogs without wxDIALOG_NO_PARENT style, use the top level 317 // app window as parent - this avoids creating modal dialogs without 318 // parent 319 // 320 if (!pParent && !(GetWindowStyleFlag() & wxDIALOG_NO_PARENT)) 321 { 322 pParent = wxTheApp->GetTopWindow(); 323 324 if (pParent) 325 { 326 // 327 // Don't use transient windows as parents, this is dangerous as it 328 // can lead to a crash if the parent is destroyed before the child 329 // 330 // also don't use the window which is currently hidden as then the 331 // dialog would be hidden as well 332 if ((pParent->GetExtraStyle() & wxWS_EX_TRANSIENT) || 333 !pParent->IsShown()) 334 { 335 pParent = NULL; 336 } 337 } 338 } 339 340 HWND hWndDlg; 341 HWND hWndOwner; 342 343 if (pParent) 344 hWndOwner = GetHwndOf(pParent); 345 else 346 hWndOwner = HWND_DESKTOP; 347 348 hWndDlg = ::WinLoadDlg( HWND_DESKTOP 349 ,hWndOwner 350 ,(PFNWP)wxDlgProc 351 ,NULL 352 ,(ULONG)ulDlgTemplate 353 ,(PVOID)this 354 ); 355 356 m_hWnd = (WXHWND) hWndDlg; 357 358 if ( !m_hWnd ) 359 { 360 wxFAIL_MSG(wxT("Did you forget to include wx/os2/wx.rc in your resources?")); 361 362 wxLogSysError(wxT("Can't create dialog using template '%ld'"), ulDlgTemplate); 363 364 return false; 365 } 366 367 // 368 // Move the dialog to its initial position without forcing repainting 369 // 370 int nX; 371 int nY; 372 int nWidth; 373 int nHeight; 374 375 if (!OS2GetCreateWindowCoords( rPos 376 ,rSize 377 ,nX 378 ,nY 379 ,nWidth 380 ,nHeight 381 )) 382 { 383 nX = nWidth = (int)CW_USEDEFAULT; 384 } 385 386 // 387 // We can't use CW_USEDEFAULT here as we're not calling CreateWindow() 388 // and passing CW_USEDEFAULT to MoveWindow() results in resizing the 389 // window to (0, 0) size which breaks quite a lot of things, e.g. the 390 // sizer calculation in wxSizer::Fit() 391 // 392 if (nWidth == (int)CW_USEDEFAULT) 393 { 394 // 395 // The exact number doesn't matter, the dialog will be resized 396 // again soon anyhow but it should be big enough to allow 397 // calculation relying on "totalSize - clientSize > 0" work, i.e. 398 // at least greater than the title bar height 399 // 400 nWidth = nHeight = 100; 401 } 402 if (nX == (int)CW_USEDEFAULT) 403 { 404 // 405 // Centre it on the screen - what else can we do? 406 // 407 wxSize vSizeDpy = wxGetDisplaySize(); 408 409 nX = (vSizeDpy.x - nWidth) / 2; 410 nY = (vSizeDpy.y - nHeight) / 2; 411 } 412 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE)); 413 414 LONG lColor = (LONG)m_backgroundColour.GetPixel(); 415 416 if (!::WinSetPresParam( m_hWnd 417 ,PP_BACKGROUNDCOLOR 418 ,sizeof(LONG) 419 ,(PVOID)&lColor 420 )) 421 { 422 return false; 423 } 424 425 // Convert to OS/2 coordinates 426 nY = GetOS2ParentHeight(pParent) - nY - nHeight; 427 428 ::WinSetWindowPos( GetHwnd() 429 ,HWND_TOP 430 ,nX 431 ,nY 432 ,nWidth 433 ,nHeight 434 ,SWP_MOVE | SWP_SIZE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE 435 ); 436 ::WinQueryWindowPos(GetHwnd(), GetSwp()); 437 m_hFrame = m_hWnd; 438 SubclassWin(m_hWnd); 439 return true; 440} // end of wxTopLevelWindowOS2::CreateDialog 441 442bool wxTopLevelWindowOS2::CreateFrame( const wxString& rsTitle, 443 const wxPoint& rPos, 444 const wxSize& rSize ) 445{ 446 WXDWORD lExflags; 447 WXDWORD lFlags = OS2GetCreateWindowFlags(&lExflags); 448 long lStyle = GetWindowStyleFlag(); 449 int nX = rPos.x; 450 int nY = rPos.y; 451 int nWidth = rSize.x; 452 int nHeight = rSize.y; 453 ULONG ulStyleFlags = 0L; 454 ERRORID vError; 455 wxString sError; 456 wxWindow* pParent = GetParent(); 457 HWND hParent; 458 HWND hFrame; 459 HWND hClient; 460 461 if (pParent) 462 hParent = GetHwndOf(pParent); 463 else 464 hParent = HWND_DESKTOP; 465 466 if ((lStyle & wxMINIMIZE) || (lStyle & wxICONIZE)) 467 ulStyleFlags |= WS_MINIMIZED; 468 if (lStyle & wxMAXIMIZE) 469 ulStyleFlags |= WS_MAXIMIZED; 470 471 // 472 // Clear the visible flag, we always call show 473 // 474 ulStyleFlags &= (unsigned long)~WS_VISIBLE; 475 m_bIconized = false; 476 477 // 478 // Create the frame window: We break ranks with other ports now 479 // and instead of calling down into the base wxWindow class' OS2Create 480 // we do all our own stuff here. We will set the needed pieces 481 // of wxWindow manually, here. 482 // 483 484 hFrame = ::WinCreateStdWindow( hParent 485 ,ulStyleFlags // frame-window style 486 ,(PULONG)&lFlags // window style 487 ,(PSZ)wxFrameClassName // class name 488 ,(PSZ)rsTitle.c_str() // window title 489 ,0L // default client style 490 ,NULLHANDLE // resource in executable file 491 ,0 // resource id 492 ,&hClient // receives client window handle 493 ); 494 if (!hFrame) 495 { 496 vError = ::WinGetLastError(vHabmain); 497 sError = wxPMErrorToStr(vError); 498 wxLogError(_T("Error creating frame. Error: %s\n"), sError.c_str()); 499 return false; 500 } 501 502 // 503 // wxWindow class' m_hWnd set here and needed associations 504 // 505 m_hFrame = hFrame; 506 m_hWnd = hClient; 507 wxAssociateWinWithHandle(m_hWnd, this); 508 wxAssociateWinWithHandle(m_hFrame, this); 509 510 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE)); 511 512 LONG lColor = (LONG)m_backgroundColour.GetPixel(); 513 514 if (!::WinSetPresParam( m_hWnd 515 ,PP_BACKGROUNDCOLOR 516 ,sizeof(LONG) 517 ,(PVOID)&lColor 518 )) 519 { 520 vError = ::WinGetLastError(vHabmain); 521 sError = wxPMErrorToStr(vError); 522 wxLogError(_T("Error creating frame. Error: %s\n"), sError.c_str()); 523 return false; 524 } 525 526 // 527 // Now need to subclass window. Instead of calling the SubClassWin in wxWindow 528 // we manually subclass here because we don't want to use the main wxWndProc 529 // by default 530 // 531 m_fnOldWndProc = (WXFARPROC) ::WinSubclassWindow(m_hFrame, (PFNWP)wxFrameMainWndProc); 532 533 // 534 // Now size everything. If adding a menu the client will need to be resized. 535 // 536 537 if (!OS2GetCreateWindowCoords( rPos 538 ,rSize 539 ,nX 540 ,nY 541 ,nWidth 542 ,nHeight 543 )) 544 { 545 nX = nWidth = (int)CW_USEDEFAULT; 546 } 547 548 // 549 // We can't use CW_USEDEFAULT here as we're not calling CreateWindow() 550 // and passing CW_USEDEFAULT to MoveWindow() results in resizing the 551 // window to (0, 0) size which breaks quite a lot of things, e.g. the 552 // sizer calculation in wxSizer::Fit() 553 // 554 if (nWidth == (int)CW_USEDEFAULT) 555 { 556 // 557 // The exact number doesn't matter, the dialog will be resized 558 // again soon anyhow but it should be big enough to allow 559 // calculation relying on "totalSize - clientSize > 0" work, i.e. 560 // at least greater than the title bar height 561 // 562 nWidth = nHeight = 100; 563 } 564 if (nX == (int)CW_USEDEFAULT) 565 { 566 // 567 // Centre it on the screen for now - what else can we do? 568 // TODO: We could try FCF_SHELLPOSITION but it will require moving 569 // things around a bit. 570 // 571 wxSize vSizeDpy = wxGetDisplaySize(); 572 573 nX = (vSizeDpy.x - nWidth) / 2; 574 nY = (vSizeDpy.y - nHeight) / 2; 575 } 576 577 // Convert to OS/2 coordinates 578 nY = GetOS2ParentHeight(pParent) - nY - nHeight; 579 580 if (!::WinSetWindowPos( m_hFrame 581 ,HWND_TOP 582 ,nX 583 ,nY 584 ,nWidth 585 ,nHeight 586 ,SWP_SIZE | SWP_MOVE | SWP_ACTIVATE | SWP_ZORDER 587 )) 588 { 589 vError = ::WinGetLastError(vHabmain); 590 sError = wxPMErrorToStr(vError); 591 wxLogError(_T("Error sizing frame. Error: %s\n"), sError.c_str()); 592 return false; 593 } 594 lStyle = ::WinQueryWindowULong( m_hWnd 595 ,QWL_STYLE 596 ); 597 lStyle |= WS_CLIPCHILDREN; 598 ::WinSetWindowULong( m_hWnd 599 ,QWL_STYLE 600 ,lStyle 601 ); 602 return true; 603} // end of wxTopLevelWindowOS2::CreateFrame 604 605bool wxTopLevelWindowOS2::Create( 606 wxWindow* pParent 607, wxWindowID vId 608, const wxString& rsTitle 609, const wxPoint& rPos 610, const wxSize& rSizeOrig 611, long lStyle 612, const wxString& rsName 613) 614{ 615 // 616 // Init our fields 617 // 618 Init(); 619 m_windowStyle = lStyle; 620 SetName(rsName); 621 m_windowId = vId == -1 ? NewControlId() : vId; 622 623 // always create a frame of some reasonable, even if arbitrary, size (at 624 // least for MSW compatibility) 625 wxSize rSize = rSizeOrig; 626 if ( rSize.x == -1 || rSize.y == -1 ) 627 { 628 wxSize sizeDpy = wxGetDisplaySize(); 629 if ( rSize.x == -1 ) 630 rSize.x = sizeDpy.x / 3; 631 if ( rSize.y == -1 ) 632 rSize.y = sizeDpy.y / 5; 633 } 634 635 wxTopLevelWindows.Append(this); 636 if (pParent) 637 pParent->AddChild(this); 638 639 if (GetExtraStyle() & wxTOPLEVEL_EX_DIALOG) 640 { 641 // 642 // We have different dialog templates to allow creation of dialogs 643 // with & without captions under OS2indows, resizeable or not (but a 644 // resizeable dialog always has caption - otherwise it would look too 645 // strange) 646 // 647 ULONG ulDlgTemplate; 648 649 if (lStyle & wxRESIZE_BORDER) 650 ulDlgTemplate = (ULONG)kResizeableDialog; 651 else if (lStyle & wxCAPTION) 652 ulDlgTemplate = (ULONG)kCaptionDialog; 653 else 654 ulDlgTemplate = (ULONG)kNoCaptionDialog; 655 return CreateDialog( ulDlgTemplate 656 ,rsTitle 657 ,rPos 658 ,rSize 659 ); 660 } 661 else // !dialog 662 { 663 return CreateFrame( rsTitle 664 ,rPos 665 ,rSize 666 ); 667 } 668} // end of wxTopLevelWindowOS2::Create 669 670wxTopLevelWindowOS2::~wxTopLevelWindowOS2() 671{ 672 // 673 // After destroying an owned window, Windows activates the next top level 674 // window in Z order but it may be different from our owner (to reproduce 675 // this simply Alt-TAB to another application and back before closing the 676 // owned frame) whereas we always want to yield activation to our parent 677 // 678 if (HasFlag(wxFRAME_FLOAT_ON_PARENT)) 679 { 680 wxWindow* pParent = GetParent(); 681 682 if (pParent) 683 { 684 ::WinSetWindowPos( GetHwndOf(pParent) 685 ,HWND_TOP 686 ,0, 0, 0, 0 687 ,SWP_ZORDER 688 ); 689 } 690 } 691} // end of wxTopLevelWindowOS2::~wxTopLevelWindowOS2 692 693// ---------------------------------------------------------------------------- 694// wxTopLevelWindowOS2 client size 695// ---------------------------------------------------------------------------- 696 697void wxTopLevelWindowOS2::DoSetClientSize( 698 int nWidth 699, int nHeight 700) 701{ 702 // 703 // Call GetClientAreaOrigin() to take the toolbar into account 704 // 705 wxPoint vPt = GetClientAreaOrigin(); 706 707 nWidth += vPt.x; 708 nHeight += vPt.y; 709 710 wxWindow::DoSetClientSize( nWidth 711 ,nHeight 712 ); 713} // end of wxTopLevelWindowOS2::DoSetClientSize 714 715void wxTopLevelWindowOS2::DoGetClientSize( 716 int* pnX 717, int* pnY 718) const 719{ 720 wxWindow::DoGetClientSize( pnX 721 ,pnY 722 ); 723 724 wxPoint vPt = GetClientAreaOrigin(); 725 726 if (pnX) 727 *pnX -= vPt.x; 728 729 if (pnY) 730 *pnY += vPt.y; 731} // end of wxTopLevelWindowOS2::DoGetClientSize 732 733// ---------------------------------------------------------------------------- 734// wxTopLevelWindowOS2 showing 735// ---------------------------------------------------------------------------- 736 737void wxTopLevelWindowOS2::DoShowWindow( 738 int nShowCmd 739) 740{ 741 ::WinShowWindow(m_hFrame, (BOOL)(nShowCmd & SWP_SHOW)); 742 743 // 744 // Need to artificially send a size event as wxApps often expect to do some 745 // final child control sizing 746 SendSizeEvent(); 747 m_bIconized = nShowCmd == SWP_MINIMIZE; 748} // end of wxTopLevelWindowOS2::DoShowWindow 749 750bool wxTopLevelWindowOS2::Show( bool bShow ) 751{ 752 int nShowCmd; 753 SWP vSwp; 754 755 if (bShow != IsShown() ) 756 { 757 m_isShown = bShow; 758 } 759 else 760 { 761 return false; 762 } 763 if (bShow) 764 { 765 if (m_bMaximizeOnShow) 766 { 767 nShowCmd = SWP_MAXIMIZE; 768 m_bMaximizeOnShow = false; 769 } 770 else 771 { 772 nShowCmd = SWP_SHOW; 773 } 774 } 775 else // hide 776 { 777 nShowCmd = SWP_HIDE; 778 } 779 DoShowWindow(nShowCmd); 780 781 if (bShow) 782 { 783 wxActivateEvent vEvent(wxEVT_ACTIVATE, true, m_windowId); 784 785 ::WinQueryWindowPos(m_hFrame, &vSwp); 786 m_bIconized = ( vSwp.fl & SWP_MINIMIZE ) == SWP_MINIMIZE ; 787 ::WinQueryWindowPos(m_hWnd, &m_vSwpClient); 788 ::WinSendMsg(m_hFrame, WM_UPDATEFRAME, (MPARAM)~0, 0); 789 ::WinQueryWindowPos(m_hWnd, &vSwp); 790 ::WinEnableWindow(m_hFrame, TRUE); 791 792 vEvent.SetEventObject(this); 793 GetEventHandler()->ProcessEvent(vEvent); 794 } 795 else 796 { 797 // 798 // Try to highlight the correct window (the parent) 799 // 800 if (GetParent()) 801 { 802 HWND hWndParent = GetHwndOf(GetParent()); 803 804 ::WinQueryWindowPos(hWndParent, &vSwp); 805 m_bIconized = (vSwp.fl & SWP_MINIMIZE)==SWP_MINIMIZE; 806 ::WinEnableWindow(hWndParent, TRUE); 807 } 808 } 809 return true; 810} // end of wxTopLevelWindowOS2::Show 811 812// ---------------------------------------------------------------------------- 813// wxTopLevelWindowOS2 maximize/minimize 814// ---------------------------------------------------------------------------- 815 816void wxTopLevelWindowOS2::Maximize( 817 bool bMaximize 818) 819{ 820 if (IsShown()) 821 { 822 // 823 // Just maximize it directly 824 // 825 DoShowWindow(bMaximize ? SWP_MAXIMIZE : SWP_RESTORE); 826 } 827 else // hidden 828 { 829 // 830 // We can't maximize the hidden frame because it shows it as well, so 831 // just remember that we should do it later in this case 832 // 833 m_bMaximizeOnShow = bMaximize; 834 } 835} // end of wxTopLevelWindowOS2::Maximize 836 837bool wxTopLevelWindowOS2::IsMaximized() const 838{ 839 ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp); 840 return (m_vSwp.fl & SWP_MAXIMIZE) == SWP_MAXIMIZE; 841} // end of wxTopLevelWindowOS2::IsMaximized 842 843void wxTopLevelWindowOS2::SetTitle( const wxString& title) 844{ 845 SetLabel(title); 846} 847 848wxString wxTopLevelWindowOS2::GetTitle() const 849{ 850 return GetLabel(); 851} 852 853void wxTopLevelWindowOS2::Iconize( bool bIconize ) 854{ 855 DoShowWindow(bIconize ? SWP_MINIMIZE : SWP_RESTORE); 856} // end of wxTopLevelWindowOS2::Iconize 857 858bool wxTopLevelWindowOS2::IsIconized() const 859{ 860 // also update the current state 861 ::WinQueryWindowPos(m_hFrame, (PSWP)&m_vSwp); 862 if (m_vSwp.fl & SWP_MINIMIZE) 863 ((wxTopLevelWindow*)this)->m_bIconized = true; 864 else 865 ((wxTopLevelWindow*)this)->m_bIconized = false; 866 return m_bIconized; 867} // end of wxTopLevelWindowOS2::IsIconized 868 869void wxTopLevelWindowOS2::Restore() 870{ 871 DoShowWindow(SWP_RESTORE); 872} // end of wxTopLevelWindowOS2::Restore 873 874// generate an artificial resize event 875void wxTopLevelWindowOS2::SendSizeEvent() 876{ 877 if (!m_bIconized) 878 { 879 RECTL vRect = wxGetWindowRect(GetHwnd()); 880 881 (void)::WinPostMsg( m_hFrame 882 ,WM_SIZE 883 ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom) 884 ,MPFROM2SHORT(vRect.xRight - vRect.xLeft, vRect.yTop - vRect.yBottom) 885 ); 886 } 887} // end of wxTopLevelWindowOS2::SendSizeEvent 888 889// ---------------------------------------------------------------------------- 890// wxTopLevelWindowOS2 fullscreen 891// ---------------------------------------------------------------------------- 892 893bool wxTopLevelWindowOS2::ShowFullScreen( bool bShow, 894 long lStyle ) 895{ 896 if (bShow) 897 { 898 if (IsFullScreen()) 899 return false; 900 901 m_bFsIsShowing = true; 902 m_lFsStyle = lStyle; 903 904 // 905 // Zap the frame borders 906 // 907 908 // 909 // Save the 'normal' window lStyle 910 // 911 m_lFsOldWindowStyle = ::WinQueryWindowULong( (HWND)GetHWND() 912 ,QWL_STYLE 913 ); 914 915 // 916 // Save the old position, width & height, maximize state 917 // 918 m_vFsOldSize = GetRect(); 919 m_bFsIsMaximized = IsMaximized(); 920 921 // 922 // Decide which window lStyle flags to turn off 923 // 924 LONG lNewStyle = m_lFsOldWindowStyle; 925 LONG lOffFlags = 0; 926 927 if (lStyle & wxFULLSCREEN_NOBORDER) 928 lOffFlags |= FCF_BORDER; 929 if (lStyle & wxFULLSCREEN_NOCAPTION) 930 lOffFlags |= (FCF_TASKLIST | FCF_SYSMENU); 931 932 lNewStyle &= (~lOffFlags); 933 934 // 935 // Change our window style to be compatible with full-screen mode 936 // 937 ::WinSetWindowULong( (HWND)GetHWND() 938 ,QWL_STYLE 939 ,lNewStyle 940 ); 941 942 // 943 // Resize to the size of the desktop 944 // 945 int nWidth; 946 int nHeight; 947 RECTL vRect = wxGetWindowRect(HWND_DESKTOP); 948 949 nWidth = vRect.xRight - vRect.xLeft; 950 nHeight = vRect.yTop - vRect.yBottom; 951 952 SetSize( nWidth, nHeight ); 953 954 // 955 // Now flush the window style cache and actually go full-screen 956 // 957 ::WinSetWindowPos( m_hFrame 958 ,HWND_TOP 959 ,0 960 ,0 961 ,nWidth 962 ,nHeight 963 ,SWP_SIZE | SWP_MOVE 964 ); 965 966 wxSize full( nWidth, nHeight ); 967 wxSizeEvent vEvent( full, GetId() ); 968 GetEventHandler()->ProcessEvent(vEvent); 969 return true; 970 } 971 else 972 { 973 if (!IsFullScreen()) 974 return false; 975 976 m_bFsIsShowing = false; 977 Maximize(m_bFsIsMaximized); 978 ::WinSetWindowULong( (HWND)GetHWND() 979 ,QWL_STYLE 980 ,m_lFsOldWindowStyle 981 ); 982 ::WinSetWindowPos( m_hFrame 983 ,HWND_TOP 984 ,m_vFsOldSize.x 985 ,m_vFsOldSize.y 986 ,m_vFsOldSize.width 987 ,m_vFsOldSize.height 988 ,SWP_SIZE | SWP_MOVE 989 ); 990 return true; 991 } 992} // end of wxTopLevelWindowOS2::ShowFullScreen 993 994// ---------------------------------------------------------------------------- 995// wxTopLevelWindowOS2 misc 996// ---------------------------------------------------------------------------- 997 998void wxTopLevelWindowOS2::SetIcon( 999 const wxIcon& rIcon 1000) 1001{ 1002 SetIcons(wxIconBundle(rIcon)); 1003} // end of wxTopLevelWindowOS2::SetIcon 1004 1005void wxTopLevelWindowOS2::SetIcons( 1006 const wxIconBundle& rIcons 1007) 1008{ 1009 // 1010 // This sets m_icon 1011 // 1012 wxTopLevelWindowBase::SetIcons(rIcons); 1013 1014 const wxIcon& vIcon = rIcons.GetIcon(wxSize(32, 32)); 1015 1016 if (vIcon.Ok() && vIcon.GetWidth() == 32 && vIcon.GetHeight() == 32) 1017 { 1018 ::WinSendMsg( m_hFrame 1019 ,WM_SETICON 1020 ,(MPARAM)((HPOINTER)vIcon.GetHICON()) 1021 ,NULL 1022 ); 1023 ::WinSendMsg( m_hFrame 1024 ,WM_UPDATEFRAME 1025 ,(MPARAM)FCF_ICON 1026 ,(MPARAM)0 1027 ); 1028 } 1029} // end of wxTopLevelWindowOS2::SetIcon 1030 1031bool wxTopLevelWindowOS2::EnableCloseButton( bool bEnable ) 1032{ 1033 // 1034 // Get system (a.k.a. window) menu 1035 // 1036 HMENU hMenu = ::WinWindowFromID(m_hFrame, FID_SYSMENU); 1037 1038 if (!hMenu) 1039 { 1040 wxLogLastError(_T("GetSystemMenu")); 1041 return false; 1042 } 1043 1044 // 1045 // Enabling/disabling the close item from it also automatically 1046 // disables/enables the close title bar button 1047 // 1048 if (bEnable) 1049 (void)::WinSendMsg( hMenu 1050 ,MM_SETITEMATTR 1051 ,MPFROM2SHORT(SC_CLOSE, FALSE) 1052 ,MPFROM2SHORT(MIA_DISABLED, FALSE) 1053 ); 1054 else 1055 (void)::WinSendMsg( hMenu 1056 ,MM_SETITEMATTR 1057 ,MPFROM2SHORT(SC_CLOSE, FALSE) 1058 ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED) 1059 ); 1060 1061 // 1062 // Update appearance immediately 1063 // 1064 ::WinSendMsg( m_hFrame 1065 ,WM_UPDATEFRAME 1066 ,(MPARAM)FCF_MENU 1067 ,(MPARAM)0 1068 ); 1069 return true; 1070} // end of wxTopLevelWindowOS2::EnableCloseButton 1071 1072// ============================================================================ 1073// wxTLWHiddenParentModule implementation 1074// ============================================================================ 1075 1076HWND wxTLWHiddenParentModule::m_shWnd = NULL; 1077const wxChar* wxTLWHiddenParentModule::m_szClassName = NULL; 1078 1079bool wxTLWHiddenParentModule::OnInit() 1080{ 1081 m_shWnd = NULL; 1082 m_szClassName = NULL; 1083 return true; 1084} // end of wxTLWHiddenParentModule::OnInit 1085 1086void wxTLWHiddenParentModule::OnExit() 1087{ 1088 if (m_shWnd) 1089 { 1090 if (!::WinDestroyWindow(m_shWnd)) 1091 { 1092 wxLogLastError(_T("DestroyWindow(hidden TLW parent)")); 1093 } 1094 m_shWnd = NULL; 1095 } 1096 1097 m_szClassName = NULL; 1098} // end of wxTLWHiddenParentModule::OnExit 1099 1100/* static */ 1101HWND wxTLWHiddenParentModule::GetHWND() 1102{ 1103 if (!m_shWnd) 1104 { 1105 if (!m_szClassName) 1106 { 1107 static const wxChar* zHIDDEN_PARENT_CLASS = _T("wxTLWHiddenParent"); 1108 1109 if (!::WinRegisterClass( wxGetInstance() 1110 ,(PSZ)zHIDDEN_PARENT_CLASS 1111 ,NULL 1112 ,0 1113 ,sizeof(ULONG) 1114 )) 1115 { 1116 wxLogLastError(_T("RegisterClass(\"wxTLWHiddenParent\")")); 1117 } 1118 else 1119 { 1120 m_szClassName = zHIDDEN_PARENT_CLASS; 1121 } 1122 } 1123 m_shWnd = ::WinCreateWindow( HWND_DESKTOP, 1124 (PSZ)m_szClassName, 1125 "", 1126 0L, 1127 (LONG)0L, 1128 (LONG)0L, 1129 (LONG)0L, 1130 (LONG)0L, 1131 NULLHANDLE, 1132 HWND_TOP, 1133 0L, 1134 NULL, 1135 NULL ); 1136 if (!m_shWnd) 1137 { 1138 wxLogLastError(_T("CreateWindow(hidden TLW parent)")); 1139 } 1140 } 1141 return m_shWnd; 1142} // end of wxTLWHiddenParentModule::GetHWND 1143