1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/utilsgui.cpp
3 // Purpose: Various utility functions only available in GUI
4 // Author: David Webster
6 // Created: 20.08.2003 (extracted from os2/utils.cpp)
8 // Copyright: (c) David Webster
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
30 #include "wx/cursor.h"
35 #include "wx/apptrait.h"
36 #include "wx/os2/private/timer.h"
38 #include "wx/os2/private.h" // includes <windows.h>
40 // ============================================================================
42 // ============================================================================
44 // ----------------------------------------------------------------------------
45 // functions to work with .INI files
46 // ----------------------------------------------------------------------------
48 // Sleep for nSecs seconds. Attempt a Windows implementation using timers.
49 static bool inTimer
= false;
51 class wxSleepTimer
: public wxTimer
61 // ---------------------------------------------------------------------------
62 // helper functions for showing a "busy" cursor
63 // ---------------------------------------------------------------------------
65 HCURSOR gs_wxBusyCursor
= 0; // new, busy cursor
66 HCURSOR gs_wxBusyCursorOld
= 0; // old cursor
67 static int gs_wxBusyCursorCount
= 0;
69 // Set the cursor to the busy cursor for all windows
70 void wxBeginBusyCursor(const wxCursor
* pCursor
)
72 if ( gs_wxBusyCursorCount
++ == 0 )
74 gs_wxBusyCursor
= (HCURSOR
)pCursor
->GetHCURSOR();
75 ::WinSetPointer(HWND_DESKTOP
, (HPOINTER
)gs_wxBusyCursor
);
77 //else: nothing to do, already set
80 // Restore cursor to normal
81 void wxEndBusyCursor()
83 wxCHECK_RET( gs_wxBusyCursorCount
> 0
84 ,_T("no matching wxBeginBusyCursor() for wxEndBusyCursor()")
87 if (--gs_wxBusyCursorCount
== 0)
89 ::WinSetPointer(HWND_DESKTOP
, (HPOINTER
)gs_wxBusyCursorOld
);
90 gs_wxBusyCursorOld
= 0;
94 // true if we're between the above two calls
97 return (gs_wxBusyCursorCount
> 0);
100 // Check whether this window wants to process messages, e.g. Stop button
101 // in long calculations.
102 bool wxCheckForInterrupt( wxWindow
* pWnd
)
108 HWND hwndFilter
= NULLHANDLE
;
110 while(::WinPeekMsg(hab
, &vMsg
, hwndFilter
, 0, 0, PM_REMOVE
))
112 ::WinDispatchMsg(hab
, &vMsg
);
114 return true;//*** temporary?
118 wxFAIL_MSG(_T("pWnd==NULL !!!"));
119 return false;//*** temporary?
123 // ----------------------------------------------------------------------------
125 // ----------------------------------------------------------------------------
127 // See also the wxGetMousePosition in window.cpp
128 // Deprecated: use wxPoint wxGetMousePosition() instead
129 void wxGetMousePosition(
136 ::WinQueryPointerPos(HWND_DESKTOP
, &vPt
);
141 // Return true if we have a colour display
142 bool wxColourDisplay()
149 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
150 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
151 ::DevQueryCaps(hdcScreen
, CAPS_COLORS
, 1L, &lColors
);
152 return(lColors
> 1L);
154 // I don't see how the PM display could not be color. Besides, this
155 // was leaking DCs and PSs!!! MN
160 // Returns depth of screen
167 static LONG nDepth
= 0;
169 // The screen colordepth ain't gonna change. No reason to query
172 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
173 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
174 ::DevQueryCaps(hdcScreen
, CAPS_COLOR_PLANES
, 1L, &lPlanes
);
175 ::DevQueryCaps(hdcScreen
, CAPS_COLOR_BITCOUNT
, 1L, &lBitsPerPixel
);
177 nDepth
= (int)(lPlanes
* lBitsPerPixel
);
178 ::DevCloseDC(hdcScreen
);
179 ::WinReleasePS(hpsScreen
);
184 // Get size of display
192 static LONG lWidth
= 0;
193 static LONG lHeight
= 0;
195 // The screen size ain't gonna change either so just cache the values
197 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
198 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
199 ::DevQueryCaps(hdcScreen
, CAPS_WIDTH
, 1L, &lWidth
);
200 ::DevQueryCaps(hdcScreen
, CAPS_HEIGHT
, 1L, &lHeight
);
201 ::DevCloseDC(hdcScreen
);
202 ::WinReleasePS(hpsScreen
);
205 *pWidth
= (int)lWidth
;
207 *pHeight
= (int)lHeight
;
210 void wxDisplaySizeMM(
218 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
219 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
222 ::DevQueryCaps( hdcScreen
223 ,CAPS_HORIZONTAL_RESOLUTION
228 ::DevQueryCaps( hdcScreen
229 ,CAPS_VERTICAL_RESOLUTION
233 ::DevCloseDC(hdcScreen
);
234 ::WinReleasePS(hpsScreen
);
237 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
)
239 // This is supposed to return desktop dimensions minus any window
240 // manager panels, menus, taskbars, etc. If there is a way to do that
241 // for this platform please fix this function, otherwise it defaults
242 // to the entire desktop.
245 wxDisplaySize(width
, height
);
248 void wxGUIAppTraits::InitializeGui(unsigned long &ulHab
)
250 ulHab
= ::WinInitialize(0);
253 void wxGUIAppTraits::TerminateGui(unsigned long ulHab
)
255 ::WinTerminate(ulHab
);
258 wxPortId
wxGUIAppTraits::GetToolkitVersion(int *verMaj
, int *verMin
) const
260 // How to get version of PM ? I guess, just reusing the OS version is OK.
261 (void) wxGetOsVersion(verMaj
, verMin
);
265 wxTimerImpl
* wxGUIAppTraits::CreateTimerImpl(wxTimer
*timer
)
267 return new wxOS2TimerImpl(timer
);
271 // ---------------------------------------------------------------------------
272 // window information functions
273 // ---------------------------------------------------------------------------
275 wxString WXDLLEXPORT
wxGetWindowText( WXHWND hWnd
)
281 long lLen
= ::WinQueryWindowTextLength((HWND
)hWnd
) + 1;
282 ::WinQueryWindowText((HWND
)hWnd
, lLen
, (PSZ
)(wxChar
*)wxStringBuffer(vStr
, lLen
));
288 wxString WXDLLEXPORT
wxGetWindowClass( WXHWND hWnd
)
293 int nLen
= 256; // some starting value
297 int nCount
= ::WinQueryClassName((HWND
)hWnd
, nLen
, (PSZ
)(wxChar
*)wxStringBuffer(vStr
, nLen
));
301 // the class name might have been truncated, retry with larger
314 WXWORD WXDLLEXPORT
wxGetWindowId(
318 return ::WinQueryWindowUShort((HWND
)hWnd
, QWS_ID
);
329 vPoint
[0].x
= rRect
.xLeft
;
330 vPoint
[0].y
= rRect
.yBottom
;
331 ::GpiMove(hPS
, &vPoint
[0]);
332 if (dwStyle
& wxSIMPLE_BORDER
||
333 dwStyle
& wxSTATIC_BORDER
)
335 vPoint
[1].x
= rRect
.xRight
- 1;
336 vPoint
[1].y
= rRect
.yTop
- 1;
344 if (dwStyle
& wxSUNKEN_BORDER
)
346 LINEBUNDLE vLineBundle
;
348 vLineBundle
.lColor
= 0x00FFFFFF; // WHITE
349 vLineBundle
.usMixMode
= FM_OVERPAINT
;
350 vLineBundle
.fxWidth
= 2;
351 vLineBundle
.lGeomWidth
= 2;
352 vLineBundle
.usType
= LINETYPE_SOLID
;
353 vLineBundle
.usEnd
= 0;
354 vLineBundle
.usJoin
= 0;
357 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
361 vPoint
[1].x
= rRect
.xRight
- 1;
362 vPoint
[1].y
= rRect
.yTop
- 1;
369 vPoint
[0].x
= rRect
.xLeft
+ 1;
370 vPoint
[0].y
= rRect
.yBottom
+ 1;
371 ::GpiMove(hPS
, &vPoint
[0]);
372 vPoint
[1].x
= rRect
.xRight
- 2;
373 vPoint
[1].y
= rRect
.yTop
- 2;
381 vLineBundle
.lColor
= 0x00000000; // BLACK
382 vLineBundle
.usMixMode
= FM_OVERPAINT
;
383 vLineBundle
.fxWidth
= 2;
384 vLineBundle
.lGeomWidth
= 2;
385 vLineBundle
.usType
= LINETYPE_SOLID
;
386 vLineBundle
.usEnd
= 0;
387 vLineBundle
.usJoin
= 0;
390 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
394 vPoint
[0].x
= rRect
.xLeft
+ 2;
395 vPoint
[0].y
= rRect
.yBottom
+ 2;
396 ::GpiMove(hPS
, &vPoint
[0]);
397 vPoint
[1].x
= rRect
.xLeft
+ 2;
398 vPoint
[1].y
= rRect
.yTop
- 3;
399 ::GpiLine(hPS
, &vPoint
[1]);
400 vPoint
[1].x
= rRect
.xRight
- 3;
401 vPoint
[1].y
= rRect
.yTop
- 3;
402 ::GpiLine(hPS
, &vPoint
[1]);
404 vPoint
[0].x
= rRect
.xLeft
+ 3;
405 vPoint
[0].y
= rRect
.yBottom
+ 3;
406 ::GpiMove(hPS
, &vPoint
[0]);
407 vPoint
[1].x
= rRect
.xLeft
+ 3;
408 vPoint
[1].y
= rRect
.yTop
- 4;
409 ::GpiLine(hPS
, &vPoint
[1]);
410 vPoint
[1].x
= rRect
.xRight
- 4;
411 vPoint
[1].y
= rRect
.yTop
- 4;
412 ::GpiLine(hPS
, &vPoint
[1]);
414 if (dwStyle
& wxDOUBLE_BORDER
)
416 LINEBUNDLE vLineBundle
;
418 vLineBundle
.lColor
= 0x00FFFFFF; // WHITE
419 vLineBundle
.usMixMode
= FM_OVERPAINT
;
420 vLineBundle
.fxWidth
= 2;
421 vLineBundle
.lGeomWidth
= 2;
422 vLineBundle
.usType
= LINETYPE_SOLID
;
423 vLineBundle
.usEnd
= 0;
424 vLineBundle
.usJoin
= 0;
427 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
431 vPoint
[1].x
= rRect
.xRight
- 1;
432 vPoint
[1].y
= rRect
.yTop
- 1;
439 vLineBundle
.lColor
= 0x00000000; // WHITE
440 vLineBundle
.usMixMode
= FM_OVERPAINT
;
441 vLineBundle
.fxWidth
= 2;
442 vLineBundle
.lGeomWidth
= 2;
443 vLineBundle
.usType
= LINETYPE_SOLID
;
444 vLineBundle
.usEnd
= 0;
445 vLineBundle
.usJoin
= 0;
448 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
452 vPoint
[0].x
= rRect
.xLeft
+ 2;
453 vPoint
[0].y
= rRect
.yBottom
+ 2;
454 ::GpiMove(hPS
, &vPoint
[0]);
455 vPoint
[1].x
= rRect
.xRight
- 2;
456 vPoint
[1].y
= rRect
.yTop
- 2;
463 vLineBundle
.lColor
= 0x00FFFFFF; // BLACK
464 vLineBundle
.usMixMode
= FM_OVERPAINT
;
465 vLineBundle
.fxWidth
= 2;
466 vLineBundle
.lGeomWidth
= 2;
467 vLineBundle
.usType
= LINETYPE_SOLID
;
468 vLineBundle
.usEnd
= 0;
469 vLineBundle
.usJoin
= 0;
472 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
476 vPoint
[0].x
= rRect
.xLeft
+ 3;
477 vPoint
[0].y
= rRect
.yBottom
+ 3;
478 ::GpiMove(hPS
, &vPoint
[0]);
479 vPoint
[1].x
= rRect
.xRight
- 3;
480 vPoint
[1].y
= rRect
.yTop
- 3;
488 if (dwStyle
& wxRAISED_BORDER
)
490 LINEBUNDLE vLineBundle
;
492 vLineBundle
.lColor
= 0x00000000; // BLACK
493 vLineBundle
.usMixMode
= FM_OVERPAINT
;
494 vLineBundle
.fxWidth
= 2;
495 vLineBundle
.lGeomWidth
= 2;
496 vLineBundle
.usType
= LINETYPE_SOLID
;
497 vLineBundle
.usEnd
= 0;
498 vLineBundle
.usJoin
= 0;
501 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
505 vPoint
[1].x
= rRect
.xRight
- 1;
506 vPoint
[1].y
= rRect
.yTop
- 1;
513 vPoint
[0].x
= rRect
.xLeft
+ 1;
514 vPoint
[0].y
= rRect
.yBottom
+ 1;
515 ::GpiMove(hPS
, &vPoint
[0]);
516 vPoint
[1].x
= rRect
.xRight
- 2;
517 vPoint
[1].y
= rRect
.yTop
- 2;
525 vLineBundle
.lColor
= 0x00FFFFFF; // WHITE
526 vLineBundle
.usMixMode
= FM_OVERPAINT
;
527 vLineBundle
.fxWidth
= 2;
528 vLineBundle
.lGeomWidth
= 2;
529 vLineBundle
.usType
= LINETYPE_SOLID
;
530 vLineBundle
.usEnd
= 0;
531 vLineBundle
.usJoin
= 0;
534 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
538 vPoint
[0].x
= rRect
.xLeft
+ 2;
539 vPoint
[0].y
= rRect
.yBottom
+ 2;
540 ::GpiMove(hPS
, &vPoint
[0]);
541 vPoint
[1].x
= rRect
.xLeft
+ 2;
542 vPoint
[1].y
= rRect
.yTop
- 3;
543 ::GpiLine(hPS
, &vPoint
[1]);
544 vPoint
[1].x
= rRect
.xRight
- 3;
545 vPoint
[1].y
= rRect
.yTop
- 3;
546 ::GpiLine(hPS
, &vPoint
[1]);
548 vPoint
[0].x
= rRect
.xLeft
+ 3;
549 vPoint
[0].y
= rRect
.yBottom
+ 3;
550 ::GpiMove(hPS
, &vPoint
[0]);
551 vPoint
[1].x
= rRect
.xLeft
+ 3;
552 vPoint
[1].y
= rRect
.yTop
- 4;
553 ::GpiLine(hPS
, &vPoint
[1]);
554 vPoint
[1].x
= rRect
.xRight
- 4;
555 vPoint
[1].y
= rRect
.yTop
- 4;
556 ::GpiLine(hPS
, &vPoint
[1]);
558 } // end of wxDrawBorder
562 , const wxFont
& rFont
570 if (hWnd
== NULLHANDLE
)
574 // The fonts available for Presentation Params are just a few
575 // outline fonts, the rest are available to the GPI, so we must
576 // map the families to one of these three
578 switch(rFont
.GetFamily())
581 strcpy(zFacename
, "Script");
585 strcpy(zFacename
, "WarpSans");
589 strcpy(zFacename
,"Times New Roman");
593 strcpy(zFacename
, "Courier New");
597 strcpy(zFacename
, "Courier New");
603 strcpy(zFacename
, "Helvetica");
607 switch(rFont
.GetWeight())
616 case wxFONTWEIGHT_MAX
:
617 strcpy(zWeight
, "Bold");
621 switch(rFont
.GetStyle())
625 strcpy(zStyle
, "Italic");
632 sprintf(zFont
, "%d.%s", rFont
.GetPointSize(), zFacename
);
633 if (zWeight
[0] != '\0')
636 strcat(zFont
, zWeight
);
638 if (zStyle
[0] != '\0')
641 strcat(zFont
, zStyle
);
643 ::WinSetPresParam(hWnd
, PP_FONTNAMESIZE
, strlen(zFont
) + 1, (PVOID
)zFont
);
644 } // end of wxOS2SetFont
646 // ---------------------------------------------------------------------------
647 // Helper for taking a regular bitmap and giving it a disabled look
648 // ---------------------------------------------------------------------------
649 wxBitmap
wxDisableBitmap(
654 wxMask
* pMask
= rBmp
.GetMask();
657 return(wxNullBitmap
);
659 DEVOPENSTRUC vDop
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L};
660 SIZEL vSize
= {0, 0};
661 HDC hDC
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
);
662 HPS hPS
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS
| GPIA_ASSOC
);
663 BITMAPINFOHEADER2 vHeader
;
667 HBITMAP hBitmap
= (HBITMAP
)rBmp
.GetHBITMAP();
668 HBITMAP hOldBitmap
= NULLHANDLE
;
669 HBITMAP hOldMask
= NULLHANDLE
;
670 HBITMAP hMask
= (HBITMAP
)rBmp
.GetMask()->GetMaskBitmap();
671 unsigned char* pucBits
; // buffer that will contain the bitmap data
672 unsigned char* pucData
; // pointer to use to traverse bitmap data
673 unsigned char* pucBitsMask
; // buffer that will contain the mask data
674 unsigned char* pucDataMask
; // pointer to use to traverse mask data
677 bool bpp16
= (wxDisplayDepth() == 16);
679 memset(&vHeader
, '\0', 16);
682 memset(&vInfo
, '\0', 16);
684 vInfo
.cx
= (ULONG
)rBmp
.GetWidth();
685 vInfo
.cy
= (ULONG
)rBmp
.GetHeight();
687 vInfo
.cBitCount
= 24; // Set to desired count going in
690 // Create the buffers for data....all wxBitmaps are 24 bit internally
692 int nBytesPerLine
= rBmp
.GetWidth() * 3;
693 int nSizeDWORD
= sizeof(DWORD
);
694 int nLineBoundary
= nBytesPerLine
% nSizeDWORD
;
700 // Bitmap must be in a double-word aligned address so we may
701 // have some padding to worry about
703 if (nLineBoundary
> 0)
705 nPadding
= nSizeDWORD
- nLineBoundary
;
706 nBytesPerLine
+= nPadding
;
708 pucBits
= (unsigned char *)malloc(nBytesPerLine
* rBmp
.GetHeight());
709 memset(pucBits
, '\0', (nBytesPerLine
* rBmp
.GetHeight()));
710 pucBitsMask
= (unsigned char *)malloc(nBytesPerLine
* rBmp
.GetHeight());
711 memset(pucBitsMask
, '\0', (nBytesPerLine
* rBmp
.GetHeight()));
714 // Extract the bitmap and mask data
716 if ((hOldBitmap
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
)
718 vError
= ::WinGetLastError(vHabmain
);
719 sError
= wxPMErrorToStr(vError
);
721 ::GpiQueryBitmapInfoHeader(hBitmap
, &vHeader
);
722 vInfo
.cBitCount
= 24;
723 if ((lScans
= ::GpiQueryBitmapBits( hPS
725 ,(LONG
)rBmp
.GetHeight()
730 vError
= ::WinGetLastError(vHabmain
);
731 sError
= wxPMErrorToStr(vError
);
733 if ((hOldMask
= ::GpiSetBitmap(hPS
, hMask
)) == HBM_ERROR
)
735 vError
= ::WinGetLastError(vHabmain
);
736 sError
= wxPMErrorToStr(vError
);
738 ::GpiQueryBitmapInfoHeader(hMask
, &vHeader
);
739 vInfo
.cBitCount
= 24;
740 if ((lScans
= ::GpiQueryBitmapBits( hPS
742 ,(LONG
)rBmp
.GetHeight()
747 vError
= ::WinGetLastError(vHabmain
);
748 sError
= wxPMErrorToStr(vError
);
750 if (( hMask
= ::GpiSetBitmap(hPS
, hOldMask
)) == HBM_ERROR
)
752 vError
= ::WinGetLastError(vHabmain
);
753 sError
= wxPMErrorToStr(vError
);
756 pucDataMask
= pucBitsMask
;
759 // Get the mask value
761 for (i
= 0; i
< rBmp
.GetHeight(); i
++)
763 for (j
= 0; j
< rBmp
.GetWidth(); j
++)
766 if (bpp16
&& *pucDataMask
== 0xF8) // 16 bit display gobblygook
771 else if (*pucDataMask
== 0xFF) // set to grey
778 *pucData
= ((unsigned char)(lColor
>> 16));
783 if (bpp16
&& *(pucDataMask
+ 1) == 0xFC) // 16 bit display gobblygook
788 else if (*(pucDataMask
+ 1) == 0xFF) // set to grey
795 *pucData
= ((unsigned char)(lColor
>> 8));
800 if (bpp16
&& *(pucDataMask
+ 2) == 0xF8) // 16 bit display gobblygook
805 else if (*(pucDataMask
+ 2) == 0xFF) // set to grey
812 *pucData
= ((unsigned char)lColor
);
817 for (j
= 0; j
< nPadding
; j
++)
825 // Create a new bitmap and set the modified bits
827 wxBitmap
vNewBmp( rBmp
.GetWidth()
831 HBITMAP hNewBmp
= (HBITMAP
)vNewBmp
.GetHBITMAP();
833 if ((hOldBitmap
= ::GpiSetBitmap(hPS
, hNewBmp
)) == HBM_ERROR
)
835 vError
= ::WinGetLastError(vHabmain
);
836 sError
= wxPMErrorToStr(vError
);
838 if ((lScansSet
= ::GpiSetBitmapBits( hPS
840 ,(LONG
)rBmp
.GetHeight()
846 vError
= ::WinGetLastError(vHabmain
);
847 sError
= wxPMErrorToStr(vError
);
851 pNewMask
= new wxMask(pMask
->GetMaskBitmap());
852 vNewBmp
.SetMask(pNewMask
);
854 ::GpiSetBitmap(hPS
, NULLHANDLE
);
859 return(wxNullBitmap
);
860 } // end of wxDisableBitmap
862 COLORREF
wxColourToRGB(
863 const wxColour
& rColor
866 return(OS2RGB(rColor
.Red(), rColor
.Green(), rColor
.Blue()));
867 } // end of wxColourToRGB