1/////////////////////////////////////////////////////////////////////////////// 2// Name: src/os2/utilsgui.cpp 3// Purpose: Various utility functions only available in GUI 4// Author: David Webster 5// Modified by: 6// Created: 20.08.2003 (extracted from os2/utils.cpp) 7// RCS-ID: $Id: utilsgui.cpp 41127 2006-09-10 12:25:54Z VZ $ 8// Copyright: (c) David Webster 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#ifndef WX_PRECOMP 28 #include "wx/utils.h" 29 #include "wx/app.h" 30 #include "wx/cursor.h" 31 #include "wx/font.h" 32 #include "wx/timer.h" 33#endif //WX_PRECOMP 34 35#include "wx/apptrait.h" 36 37#include "wx/os2/private.h" // includes <windows.h> 38 39// ============================================================================ 40// implementation 41// ============================================================================ 42 43// ---------------------------------------------------------------------------- 44// functions to work with .INI files 45// ---------------------------------------------------------------------------- 46 47// Sleep for nSecs seconds. Attempt a Windows implementation using timers. 48static bool inTimer = false; 49 50class wxSleepTimer: public wxTimer 51{ 52public: 53 inline void Notify() 54 { 55 inTimer = false; 56 Stop(); 57 } 58}; 59 60// Reading and writing resources (eg WIN.INI, .Xdefaults) 61#if wxUSE_RESOURCES 62bool wxWriteResource( const wxString& rSection, 63 const wxString& rEntry, 64 const wxString& rValue, 65 const wxString& rFile ) 66{ 67 HAB hab = 0; 68 HINI hIni = 0; 69 70 if (!rFile.empty()) 71 { 72 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile); 73 if (hIni != 0L) 74 { 75 return (::PrfWriteProfileString( hIni 76 ,(PSZ)WXSTRINGCAST rSection 77 ,(PSZ)WXSTRINGCAST rEntry 78 ,(PSZ)WXSTRINGCAST rValue 79 )); 80 } 81 } 82 else 83 return (::PrfWriteProfileString( HINI_PROFILE 84 ,(PSZ)WXSTRINGCAST rSection 85 ,(PSZ)WXSTRINGCAST rEntry 86 ,(PSZ)WXSTRINGCAST rValue 87 )); 88 return false; 89} 90 91bool wxWriteResource( 92 const wxString& rSection 93, const wxString& rEntry 94, float fValue 95, const wxString& rFile 96) 97{ 98 wxChar zBuf[50]; 99 100 wxSprintf(zBuf, "%.4f", fValue); 101 return wxWriteResource( rSection 102 ,rEntry 103 ,zBuf 104 ,rFile 105 ); 106} 107 108bool wxWriteResource( 109 const wxString& rSection 110, const wxString& rEntry 111, long lValue 112, const wxString& rFile 113) 114{ 115 wxChar zBuf[50]; 116 117 wxSprintf(zBuf, "%ld", lValue); 118 return wxWriteResource( rSection 119 ,rEntry 120 ,zBuf 121 ,rFile 122 ); 123} 124 125bool wxWriteResource( const wxString& rSection, 126 const wxString& rEntry, 127 int lValue, 128 const wxString& rFile ) 129{ 130 wxChar zBuf[50]; 131 132 wxSprintf(zBuf, "%d", lValue); 133 return wxWriteResource( rSection, rEntry, zBuf, rFile ); 134} 135 136bool wxGetResource( const wxString& rSection, 137 const wxString& rEntry, 138 wxChar** ppValue, 139 const wxString& rFile ) 140{ 141 HAB hab = 0; 142 HINI hIni = 0; 143 wxChar zDefunkt[] = _T("$$default"); 144 char zBuf[1000]; 145 146 if (!rFile.empty()) 147 { 148 hIni = ::PrfOpenProfile(hab, (PSZ)WXSTRINGCAST rFile); 149 if (hIni != 0L) 150 { 151 ULONG n = ::PrfQueryProfileString( hIni 152 ,(PSZ)WXSTRINGCAST rSection 153 ,(PSZ)WXSTRINGCAST rEntry 154 ,(PSZ)zDefunkt 155 ,(PVOID)zBuf 156 ,1000 157 ); 158 if (zBuf == NULL) 159 return false; 160 if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0) 161 return false; 162 zBuf[n-1] = '\0'; 163 } 164 else 165 return false; 166 } 167 else 168 { 169 ULONG n = ::PrfQueryProfileString( HINI_PROFILE 170 ,(PSZ)WXSTRINGCAST rSection 171 ,(PSZ)WXSTRINGCAST rEntry 172 ,(PSZ)zDefunkt 173 ,(PVOID)zBuf 174 ,1000 175 ); 176 if (zBuf == NULL) 177 return false; 178 if (n == 0L || wxStrcmp(zBuf, zDefunkt) == 0) 179 return false; 180 zBuf[n-1] = '\0'; 181 } 182 strcpy((char*)*ppValue, zBuf); 183 return true; 184} 185 186bool wxGetResource( const wxString& rSection, 187 const wxString& rEntry, 188 float* pValue, 189 const wxString& rFile ) 190{ 191 wxChar* zStr = NULL; 192 193 zStr = new wxChar[1000]; 194 bool bSucc = wxGetResource( rSection, rEntry, (wxChar **)&zStr, rFile ); 195 196 if (bSucc) 197 { 198 *pValue = (float)wxStrtod(zStr, NULL); 199 } 200 201 delete[] zStr; 202 return bSucc; 203} 204 205bool wxGetResource( const wxString& rSection, 206 const wxString& rEntry, 207 long* pValue, 208 const wxString& rFile ) 209{ 210 wxChar* zStr = NULL; 211 212 zStr = new wxChar[1000]; 213 bool bSucc = wxGetResource( rSection, rEntry, (wxChar **)&zStr, rFile ); 214 215 if (bSucc) 216 { 217 *pValue = wxStrtol(zStr, NULL, 10); 218 } 219 220 delete[] zStr; 221 return bSucc; 222} 223 224bool wxGetResource( const wxString& rSection, 225 const wxString& rEntry, 226 int* pValue, 227 const wxString& rFile ) 228{ 229 wxChar* zStr = NULL; 230 231 zStr = new wxChar[1000]; 232 bool bSucc = wxGetResource( rSection, rEntry, (wxChar **)&zStr, rFile ); 233 234 if (bSucc) 235 { 236 *pValue = (int)wxStrtol(zStr, NULL, 10); 237 } 238 239 delete[] zStr; 240 return bSucc; 241} 242#endif // wxUSE_RESOURCES 243 244// --------------------------------------------------------------------------- 245// helper functions for showing a "busy" cursor 246// --------------------------------------------------------------------------- 247 248HCURSOR gs_wxBusyCursor = 0; // new, busy cursor 249HCURSOR gs_wxBusyCursorOld = 0; // old cursor 250static int gs_wxBusyCursorCount = 0; 251 252// Set the cursor to the busy cursor for all windows 253void wxBeginBusyCursor(const wxCursor* pCursor) 254{ 255 if ( gs_wxBusyCursorCount++ == 0 ) 256 { 257 gs_wxBusyCursor = (HCURSOR)pCursor->GetHCURSOR(); 258 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursor); 259 } 260 //else: nothing to do, already set 261} 262 263// Restore cursor to normal 264void wxEndBusyCursor() 265{ 266 wxCHECK_RET( gs_wxBusyCursorCount > 0 267 ,_T("no matching wxBeginBusyCursor() for wxEndBusyCursor()") 268 ); 269 270 if (--gs_wxBusyCursorCount == 0) 271 { 272 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)gs_wxBusyCursorOld); 273 gs_wxBusyCursorOld = 0; 274 } 275} 276 277// true if we're between the above two calls 278bool wxIsBusy() 279{ 280 return (gs_wxBusyCursorCount > 0); 281} 282 283// Check whether this window wants to process messages, e.g. Stop button 284// in long calculations. 285bool wxCheckForInterrupt( wxWindow* pWnd ) 286{ 287 if(pWnd) 288 { 289 QMSG vMsg; 290 HAB hab = 0; 291 HWND hwndFilter = NULLHANDLE; 292 293 while(::WinPeekMsg(hab, &vMsg, hwndFilter, 0, 0, PM_REMOVE)) 294 { 295 ::WinDispatchMsg(hab, &vMsg); 296 } 297 return true;//*** temporary? 298 } 299 else 300 { 301 wxFAIL_MSG(_T("pWnd==NULL !!!")); 302 return false;//*** temporary? 303 } 304} 305 306// ---------------------------------------------------------------------------- 307// get display info 308// ---------------------------------------------------------------------------- 309 310// See also the wxGetMousePosition in window.cpp 311// Deprecated: use wxPoint wxGetMousePosition() instead 312void wxGetMousePosition( 313 int* pX 314, int* pY 315) 316{ 317 POINTL vPt; 318 319 ::WinQueryPointerPos(HWND_DESKTOP, &vPt); 320 *pX = vPt.x; 321 *pY = vPt.y; 322}; 323 324// Return true if we have a colour display 325bool wxColourDisplay() 326{ 327#if 0 328 HPS hpsScreen; 329 HDC hdcScreen; 330 LONG lColors; 331 332 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP); 333 hdcScreen = ::GpiQueryDevice(hpsScreen); 334 ::DevQueryCaps(hdcScreen, CAPS_COLORS, 1L, &lColors); 335 return(lColors > 1L); 336#else 337 // I don't see how the PM display could not be color. Besides, this 338 // was leaking DCs and PSs!!! MN 339 return true; 340#endif 341} 342 343// Returns depth of screen 344int wxDisplayDepth() 345{ 346 HPS hpsScreen; 347 HDC hdcScreen; 348 LONG lPlanes; 349 LONG lBitsPerPixel; 350 static LONG nDepth = 0; 351 352 // The screen colordepth ain't gonna change. No reason to query 353 // it over and over! 354 if (!nDepth) { 355 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP); 356 hdcScreen = ::GpiQueryDevice(hpsScreen); 357 ::DevQueryCaps(hdcScreen, CAPS_COLOR_PLANES, 1L, &lPlanes); 358 ::DevQueryCaps(hdcScreen, CAPS_COLOR_BITCOUNT, 1L, &lBitsPerPixel); 359 360 nDepth = (int)(lPlanes * lBitsPerPixel); 361 ::DevCloseDC(hdcScreen); 362 ::WinReleasePS(hpsScreen); 363 } 364 return (nDepth); 365} 366 367// Get size of display 368void wxDisplaySize( 369 int* pWidth 370, int* pHeight 371) 372{ 373 HPS hpsScreen; 374 HDC hdcScreen; 375 static LONG lWidth = 0; 376 static LONG lHeight = 0; 377 378 // The screen size ain't gonna change either so just cache the values 379 if (!lWidth) { 380 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP); 381 hdcScreen = ::GpiQueryDevice(hpsScreen); 382 ::DevQueryCaps(hdcScreen, CAPS_WIDTH, 1L, &lWidth); 383 ::DevQueryCaps(hdcScreen, CAPS_HEIGHT, 1L, &lHeight); 384 ::DevCloseDC(hdcScreen); 385 ::WinReleasePS(hpsScreen); 386 } 387 if (pWidth) 388 *pWidth = (int)lWidth; 389 if (pHeight) 390 *pHeight = (int)lHeight; 391} 392 393void wxDisplaySizeMM( 394 int* pWidth 395, int* pHeight 396) 397{ 398 HPS hpsScreen; 399 HDC hdcScreen; 400 401 hpsScreen = ::WinGetScreenPS(HWND_DESKTOP); 402 hdcScreen = ::GpiQueryDevice(hpsScreen); 403 404 if (pWidth) 405 ::DevQueryCaps( hdcScreen 406 ,CAPS_HORIZONTAL_RESOLUTION 407 ,1L 408 ,(PLONG)pWidth 409 ); 410 if (pHeight) 411 ::DevQueryCaps( hdcScreen 412 ,CAPS_VERTICAL_RESOLUTION 413 ,1L 414 ,(PLONG)pHeight 415 ); 416 ::DevCloseDC(hdcScreen); 417 ::WinReleasePS(hpsScreen); 418} 419 420void wxClientDisplayRect(int *x, int *y, int *width, int *height) 421{ 422 // This is supposed to return desktop dimensions minus any window 423 // manager panels, menus, taskbars, etc. If there is a way to do that 424 // for this platform please fix this function, otherwise it defaults 425 // to the entire desktop. 426 if (x) *x = 0; 427 if (y) *y = 0; 428 wxDisplaySize(width, height); 429} 430 431void wxGUIAppTraits::InitializeGui(unsigned long &ulHab) 432{ 433 ulHab = ::WinInitialize(0); 434} 435 436void wxGUIAppTraits::TerminateGui(unsigned long ulHab) 437{ 438 ::WinTerminate(ulHab); 439} 440 441wxPortId wxGUIAppTraits::GetToolkitVersion(int *verMaj, int *verMin) const 442{ 443 // How to get version of PM ? I guess, just reusing the OS version is OK. 444 (void) wxGetOsVersion(verMaj, verMin); 445 return wxPORT_OS2; 446} 447 448 449// --------------------------------------------------------------------------- 450// window information functions 451// --------------------------------------------------------------------------- 452 453wxString WXDLLEXPORT wxGetWindowText( WXHWND hWnd ) 454{ 455 wxString vStr; 456 457 if ( hWnd ) 458 { 459 long lLen = ::WinQueryWindowTextLength((HWND)hWnd) + 1; 460 ::WinQueryWindowText((HWND)hWnd, lLen, (PSZ)(wxChar*)wxStringBuffer(vStr, lLen)); 461 } 462 463 return vStr; 464} 465 466wxString WXDLLEXPORT wxGetWindowClass( WXHWND hWnd ) 467{ 468 wxString vStr; 469 if ( hWnd ) 470 { 471 int nLen = 256; // some starting value 472 473 for ( ;; ) 474 { 475 int nCount = ::WinQueryClassName((HWND)hWnd, nLen, (PSZ)(wxChar*)wxStringBuffer(vStr, nLen)); 476 477 if (nCount == nLen ) 478 { 479 // the class name might have been truncated, retry with larger 480 // buffer 481 nLen *= 2; 482 } 483 else 484 { 485 break; 486 } 487 } 488 } 489 return vStr; 490} 491 492WXWORD WXDLLEXPORT wxGetWindowId( 493 WXHWND hWnd 494) 495{ 496 return ::WinQueryWindowUShort((HWND)hWnd, QWS_ID); 497} 498 499void wxDrawBorder( 500 HPS hPS 501, RECTL& rRect 502, WXDWORD dwStyle 503) 504{ 505 POINTL vPoint[2]; 506 507 vPoint[0].x = rRect.xLeft; 508 vPoint[0].y = rRect.yBottom; 509 ::GpiMove(hPS, &vPoint[0]); 510 if (dwStyle & wxSIMPLE_BORDER || 511 dwStyle & wxSTATIC_BORDER) 512 { 513 vPoint[1].x = rRect.xRight - 1; 514 vPoint[1].y = rRect.yTop - 1; 515 ::GpiBox( hPS 516 ,DRO_OUTLINE 517 ,&vPoint[1] 518 ,0L 519 ,0L 520 ); 521 } 522 if (dwStyle & wxSUNKEN_BORDER) 523 { 524 LINEBUNDLE vLineBundle; 525 526 vLineBundle.lColor = 0x00FFFFFF; // WHITE 527 vLineBundle.usMixMode = FM_OVERPAINT; 528 vLineBundle.fxWidth = 2; 529 vLineBundle.lGeomWidth = 2; 530 vLineBundle.usType = LINETYPE_SOLID; 531 vLineBundle.usEnd = 0; 532 vLineBundle.usJoin = 0; 533 ::GpiSetAttrs( hPS 534 ,PRIM_LINE 535 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE 536 ,0L 537 ,&vLineBundle 538 ); 539 vPoint[1].x = rRect.xRight - 1; 540 vPoint[1].y = rRect.yTop - 1; 541 ::GpiBox( hPS 542 ,DRO_OUTLINE 543 ,&vPoint[1] 544 ,0L 545 ,0L 546 ); 547 vPoint[0].x = rRect.xLeft + 1; 548 vPoint[0].y = rRect.yBottom + 1; 549 ::GpiMove(hPS, &vPoint[0]); 550 vPoint[1].x = rRect.xRight - 2; 551 vPoint[1].y = rRect.yTop - 2; 552 ::GpiBox( hPS 553 ,DRO_OUTLINE 554 ,&vPoint[1] 555 ,0L 556 ,0L 557 ); 558 559 vLineBundle.lColor = 0x00000000; // BLACK 560 vLineBundle.usMixMode = FM_OVERPAINT; 561 vLineBundle.fxWidth = 2; 562 vLineBundle.lGeomWidth = 2; 563 vLineBundle.usType = LINETYPE_SOLID; 564 vLineBundle.usEnd = 0; 565 vLineBundle.usJoin = 0; 566 ::GpiSetAttrs( hPS 567 ,PRIM_LINE 568 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE 569 ,0L 570 ,&vLineBundle 571 ); 572 vPoint[0].x = rRect.xLeft + 2; 573 vPoint[0].y = rRect.yBottom + 2; 574 ::GpiMove(hPS, &vPoint[0]); 575 vPoint[1].x = rRect.xLeft + 2; 576 vPoint[1].y = rRect.yTop - 3; 577 ::GpiLine(hPS, &vPoint[1]); 578 vPoint[1].x = rRect.xRight - 3; 579 vPoint[1].y = rRect.yTop - 3; 580 ::GpiLine(hPS, &vPoint[1]); 581 582 vPoint[0].x = rRect.xLeft + 3; 583 vPoint[0].y = rRect.yBottom + 3; 584 ::GpiMove(hPS, &vPoint[0]); 585 vPoint[1].x = rRect.xLeft + 3; 586 vPoint[1].y = rRect.yTop - 4; 587 ::GpiLine(hPS, &vPoint[1]); 588 vPoint[1].x = rRect.xRight - 4; 589 vPoint[1].y = rRect.yTop - 4; 590 ::GpiLine(hPS, &vPoint[1]); 591 } 592 if (dwStyle & wxDOUBLE_BORDER) 593 { 594 LINEBUNDLE vLineBundle; 595 596 vLineBundle.lColor = 0x00FFFFFF; // WHITE 597 vLineBundle.usMixMode = FM_OVERPAINT; 598 vLineBundle.fxWidth = 2; 599 vLineBundle.lGeomWidth = 2; 600 vLineBundle.usType = LINETYPE_SOLID; 601 vLineBundle.usEnd = 0; 602 vLineBundle.usJoin = 0; 603 ::GpiSetAttrs( hPS 604 ,PRIM_LINE 605 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE 606 ,0L 607 ,&vLineBundle 608 ); 609 vPoint[1].x = rRect.xRight - 1; 610 vPoint[1].y = rRect.yTop - 1; 611 ::GpiBox( hPS 612 ,DRO_OUTLINE 613 ,&vPoint[1] 614 ,0L 615 ,0L 616 ); 617 vLineBundle.lColor = 0x00000000; // WHITE 618 vLineBundle.usMixMode = FM_OVERPAINT; 619 vLineBundle.fxWidth = 2; 620 vLineBundle.lGeomWidth = 2; 621 vLineBundle.usType = LINETYPE_SOLID; 622 vLineBundle.usEnd = 0; 623 vLineBundle.usJoin = 0; 624 ::GpiSetAttrs( hPS 625 ,PRIM_LINE 626 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE 627 ,0L 628 ,&vLineBundle 629 ); 630 vPoint[0].x = rRect.xLeft + 2; 631 vPoint[0].y = rRect.yBottom + 2; 632 ::GpiMove(hPS, &vPoint[0]); 633 vPoint[1].x = rRect.xRight - 2; 634 vPoint[1].y = rRect.yTop - 2; 635 ::GpiBox( hPS 636 ,DRO_OUTLINE 637 ,&vPoint[1] 638 ,0L 639 ,0L 640 ); 641 vLineBundle.lColor = 0x00FFFFFF; // BLACK 642 vLineBundle.usMixMode = FM_OVERPAINT; 643 vLineBundle.fxWidth = 2; 644 vLineBundle.lGeomWidth = 2; 645 vLineBundle.usType = LINETYPE_SOLID; 646 vLineBundle.usEnd = 0; 647 vLineBundle.usJoin = 0; 648 ::GpiSetAttrs( hPS 649 ,PRIM_LINE 650 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE 651 ,0L 652 ,&vLineBundle 653 ); 654 vPoint[0].x = rRect.xLeft + 3; 655 vPoint[0].y = rRect.yBottom + 3; 656 ::GpiMove(hPS, &vPoint[0]); 657 vPoint[1].x = rRect.xRight - 3; 658 vPoint[1].y = rRect.yTop - 3; 659 ::GpiBox( hPS 660 ,DRO_OUTLINE 661 ,&vPoint[1] 662 ,0L 663 ,0L 664 ); 665 } 666 if (dwStyle & wxRAISED_BORDER) 667 { 668 LINEBUNDLE vLineBundle; 669 670 vLineBundle.lColor = 0x00000000; // BLACK 671 vLineBundle.usMixMode = FM_OVERPAINT; 672 vLineBundle.fxWidth = 2; 673 vLineBundle.lGeomWidth = 2; 674 vLineBundle.usType = LINETYPE_SOLID; 675 vLineBundle.usEnd = 0; 676 vLineBundle.usJoin = 0; 677 ::GpiSetAttrs( hPS 678 ,PRIM_LINE 679 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE 680 ,0L 681 ,&vLineBundle 682 ); 683 vPoint[1].x = rRect.xRight - 1; 684 vPoint[1].y = rRect.yTop - 1; 685 ::GpiBox( hPS 686 ,DRO_OUTLINE 687 ,&vPoint[1] 688 ,0L 689 ,0L 690 ); 691 vPoint[0].x = rRect.xLeft + 1; 692 vPoint[0].y = rRect.yBottom + 1; 693 ::GpiMove(hPS, &vPoint[0]); 694 vPoint[1].x = rRect.xRight - 2; 695 vPoint[1].y = rRect.yTop - 2; 696 ::GpiBox( hPS 697 ,DRO_OUTLINE 698 ,&vPoint[1] 699 ,0L 700 ,0L 701 ); 702 703 vLineBundle.lColor = 0x00FFFFFF; // WHITE 704 vLineBundle.usMixMode = FM_OVERPAINT; 705 vLineBundle.fxWidth = 2; 706 vLineBundle.lGeomWidth = 2; 707 vLineBundle.usType = LINETYPE_SOLID; 708 vLineBundle.usEnd = 0; 709 vLineBundle.usJoin = 0; 710 ::GpiSetAttrs( hPS 711 ,PRIM_LINE 712 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE 713 ,0L 714 ,&vLineBundle 715 ); 716 vPoint[0].x = rRect.xLeft + 2; 717 vPoint[0].y = rRect.yBottom + 2; 718 ::GpiMove(hPS, &vPoint[0]); 719 vPoint[1].x = rRect.xLeft + 2; 720 vPoint[1].y = rRect.yTop - 3; 721 ::GpiLine(hPS, &vPoint[1]); 722 vPoint[1].x = rRect.xRight - 3; 723 vPoint[1].y = rRect.yTop - 3; 724 ::GpiLine(hPS, &vPoint[1]); 725 726 vPoint[0].x = rRect.xLeft + 3; 727 vPoint[0].y = rRect.yBottom + 3; 728 ::GpiMove(hPS, &vPoint[0]); 729 vPoint[1].x = rRect.xLeft + 3; 730 vPoint[1].y = rRect.yTop - 4; 731 ::GpiLine(hPS, &vPoint[1]); 732 vPoint[1].x = rRect.xRight - 4; 733 vPoint[1].y = rRect.yTop - 4; 734 ::GpiLine(hPS, &vPoint[1]); 735 } 736} // end of wxDrawBorder 737 738void wxOS2SetFont( 739 HWND hWnd 740, const wxFont& rFont 741) 742{ 743 char zFont[128]; 744 char zFacename[30]; 745 char zWeight[30]; 746 char zStyle[30]; 747 748 if (hWnd == NULLHANDLE) 749 return; 750 751 // 752 // The fonts available for Presentation Params are just a few 753 // outline fonts, the rest are available to the GPI, so we must 754 // map the families to one of these three 755 // 756 switch(rFont.GetFamily()) 757 { 758 case wxSCRIPT: 759 strcpy(zFacename, "Script"); 760 break; 761 762 case wxDECORATIVE: 763 strcpy(zFacename, "WarpSans"); 764 break; 765 766 case wxROMAN: 767 strcpy(zFacename,"Times New Roman"); 768 break; 769 770 case wxTELETYPE: 771 strcpy(zFacename, "Courier New"); 772 break; 773 774 case wxMODERN: 775 strcpy(zFacename, "Courier New"); 776 break; 777 778 case wxDEFAULT: 779 default: 780 case wxSWISS: 781 strcpy(zFacename, "Helvetica"); 782 break; 783 } 784 785 switch(rFont.GetWeight()) 786 { 787 default: 788 case wxNORMAL: 789 case wxLIGHT: 790 zWeight[0] = '\0'; 791 break; 792 793 case wxBOLD: 794 case wxFONTWEIGHT_MAX: 795 strcpy(zWeight, "Bold"); 796 break; 797 } 798 799 switch(rFont.GetStyle()) 800 { 801 case wxITALIC: 802 case wxSLANT: 803 strcpy(zStyle, "Italic"); 804 break; 805 806 default: 807 zStyle[0] = '\0'; 808 break; 809 } 810 sprintf(zFont, "%d.%s", rFont.GetPointSize(), zFacename); 811 if (zWeight[0] != '\0') 812 { 813 strcat(zFont, " "); 814 strcat(zFont, zWeight); 815 } 816 if (zStyle[0] != '\0') 817 { 818 strcat(zFont, " "); 819 strcat(zFont, zStyle); 820 } 821 ::WinSetPresParam(hWnd, PP_FONTNAMESIZE, strlen(zFont) + 1, (PVOID)zFont); 822} // end of wxOS2SetFont 823 824// --------------------------------------------------------------------------- 825// Helper for taking a regular bitmap and giving it a disabled look 826// --------------------------------------------------------------------------- 827wxBitmap wxDisableBitmap( 828 const wxBitmap& rBmp 829, long lColor 830) 831{ 832 wxMask* pMask = rBmp.GetMask(); 833 834 if (!pMask) 835 return(wxNullBitmap); 836 837 DEVOPENSTRUC vDop = {0L, "DISPLAY", NULL, 0L, 0L, 0L, 0L, 0L, 0L}; 838 SIZEL vSize = {0, 0}; 839 HDC hDC = ::DevOpenDC(vHabmain, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&vDop, NULLHANDLE); 840 HPS hPS = ::GpiCreatePS(vHabmain, hDC, &vSize, PU_PELS | GPIA_ASSOC); 841 BITMAPINFOHEADER2 vHeader; 842 BITMAPINFO2 vInfo; 843 ERRORID vError; 844 wxString sError; 845 HBITMAP hBitmap = (HBITMAP)rBmp.GetHBITMAP(); 846 HBITMAP hOldBitmap = NULLHANDLE; 847 HBITMAP hOldMask = NULLHANDLE; 848 HBITMAP hMask = (HBITMAP)rBmp.GetMask()->GetMaskBitmap(); 849 unsigned char* pucBits; // buffer that will contain the bitmap data 850 unsigned char* pucData; // pointer to use to traverse bitmap data 851 unsigned char* pucBitsMask; // buffer that will contain the mask data 852 unsigned char* pucDataMask; // pointer to use to traverse mask data 853 LONG lScans = 0L; 854 LONG lScansSet = 0L; 855 bool bpp16 = (wxDisplayDepth() == 16); 856 857 memset(&vHeader, '\0', 16); 858 vHeader.cbFix = 16; 859 860 memset(&vInfo, '\0', 16); 861 vInfo.cbFix = 16; 862 vInfo.cx = (ULONG)rBmp.GetWidth(); 863 vInfo.cy = (ULONG)rBmp.GetHeight(); 864 vInfo.cPlanes = 1; 865 vInfo.cBitCount = 24; // Set to desired count going in 866 867 // 868 // Create the buffers for data....all wxBitmaps are 24 bit internally 869 // 870 int nBytesPerLine = rBmp.GetWidth() * 3; 871 int nSizeDWORD = sizeof(DWORD); 872 int nLineBoundary = nBytesPerLine % nSizeDWORD; 873 int nPadding = 0; 874 int i; 875 int j; 876 877 // 878 // Bitmap must be in a double-word aligned address so we may 879 // have some padding to worry about 880 // 881 if (nLineBoundary > 0) 882 { 883 nPadding = nSizeDWORD - nLineBoundary; 884 nBytesPerLine += nPadding; 885 } 886 pucBits = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight()); 887 memset(pucBits, '\0', (nBytesPerLine * rBmp.GetHeight())); 888 pucBitsMask = (unsigned char *)malloc(nBytesPerLine * rBmp.GetHeight()); 889 memset(pucBitsMask, '\0', (nBytesPerLine * rBmp.GetHeight())); 890 891 // 892 // Extract the bitmap and mask data 893 // 894 if ((hOldBitmap = ::GpiSetBitmap(hPS, hBitmap)) == HBM_ERROR) 895 { 896 vError = ::WinGetLastError(vHabmain); 897 sError = wxPMErrorToStr(vError); 898 } 899 ::GpiQueryBitmapInfoHeader(hBitmap, &vHeader); 900 vInfo.cBitCount = 24; 901 if ((lScans = ::GpiQueryBitmapBits( hPS 902 ,0L 903 ,(LONG)rBmp.GetHeight() 904 ,(PBYTE)pucBits 905 ,&vInfo 906 )) == GPI_ALTERROR) 907 { 908 vError = ::WinGetLastError(vHabmain); 909 sError = wxPMErrorToStr(vError); 910 } 911 if ((hOldMask = ::GpiSetBitmap(hPS, hMask)) == HBM_ERROR) 912 { 913 vError = ::WinGetLastError(vHabmain); 914 sError = wxPMErrorToStr(vError); 915 } 916 ::GpiQueryBitmapInfoHeader(hMask, &vHeader); 917 vInfo.cBitCount = 24; 918 if ((lScans = ::GpiQueryBitmapBits( hPS 919 ,0L 920 ,(LONG)rBmp.GetHeight() 921 ,(PBYTE)pucBitsMask 922 ,&vInfo 923 )) == GPI_ALTERROR) 924 { 925 vError = ::WinGetLastError(vHabmain); 926 sError = wxPMErrorToStr(vError); 927 } 928 if (( hMask = ::GpiSetBitmap(hPS, hOldMask)) == HBM_ERROR) 929 { 930 vError = ::WinGetLastError(vHabmain); 931 sError = wxPMErrorToStr(vError); 932 } 933 pucData = pucBits; 934 pucDataMask = pucBitsMask; 935 936 // 937 // Get the mask value 938 // 939 for (i = 0; i < rBmp.GetHeight(); i++) 940 { 941 for (j = 0; j < rBmp.GetWidth(); j++) 942 { 943 // Byte 1 944 if (bpp16 && *pucDataMask == 0xF8) // 16 bit display gobblygook 945 { 946 *pucData = 0x7F; 947 pucData++; 948 } 949 else if (*pucDataMask == 0xFF) // set to grey 950 { 951 *pucData = 0x7F; 952 pucData++; 953 } 954 else 955 { 956 *pucData = ((unsigned char)(lColor >> 16)); 957 pucData++; 958 } 959 960 // Byte 2 961 if (bpp16 && *(pucDataMask + 1) == 0xFC) // 16 bit display gobblygook 962 { 963 *pucData = 0x7F; 964 pucData++; 965 } 966 else if (*(pucDataMask + 1) == 0xFF) // set to grey 967 { 968 *pucData = 0x7F; 969 pucData++; 970 } 971 else 972 { 973 *pucData = ((unsigned char)(lColor >> 8)); 974 pucData++; 975 } 976 977 // Byte 3 978 if (bpp16 && *(pucDataMask + 2) == 0xF8) // 16 bit display gobblygook 979 { 980 *pucData = 0x7F; 981 pucData++; 982 } 983 else if (*(pucDataMask + 2) == 0xFF) // set to grey 984 { 985 *pucData = 0x7F; 986 pucData++; 987 } 988 else 989 { 990 *pucData = ((unsigned char)lColor); 991 pucData++; 992 } 993 pucDataMask += 3; 994 } 995 for (j = 0; j < nPadding; j++) 996 { 997 pucData++; 998 pucDataMask++; 999 } 1000 } 1001 1002 // 1003 // Create a new bitmap and set the modified bits 1004 // 1005 wxBitmap vNewBmp( rBmp.GetWidth() 1006 ,rBmp.GetHeight() 1007 ,24 1008 ); 1009 HBITMAP hNewBmp = (HBITMAP)vNewBmp.GetHBITMAP(); 1010 1011 if ((hOldBitmap = ::GpiSetBitmap(hPS, hNewBmp)) == HBM_ERROR) 1012 { 1013 vError = ::WinGetLastError(vHabmain); 1014 sError = wxPMErrorToStr(vError); 1015 } 1016 if ((lScansSet = ::GpiSetBitmapBits( hPS 1017 ,0L 1018 ,(LONG)rBmp.GetHeight() 1019 ,(PBYTE)pucBits 1020 ,&vInfo 1021 )) == GPI_ALTERROR) 1022 1023 { 1024 vError = ::WinGetLastError(vHabmain); 1025 sError = wxPMErrorToStr(vError); 1026 } 1027 wxMask* pNewMask; 1028 1029 pNewMask = new wxMask(pMask->GetMaskBitmap()); 1030 vNewBmp.SetMask(pNewMask); 1031 free(pucBits); 1032 ::GpiSetBitmap(hPS, NULLHANDLE); 1033 ::GpiDestroyPS(hPS); 1034 ::DevCloseDC(hDC); 1035 if (vNewBmp.Ok()) 1036 return(vNewBmp); 1037 return(wxNullBitmap); 1038} // end of wxDisableBitmap 1039 1040COLORREF wxColourToRGB( 1041 const wxColour& rColor 1042) 1043{ 1044 return(OS2RGB(rColor.Red(), rColor.Green(), rColor.Blue())); 1045} // end of wxColourToRGB 1046