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 // Licence: 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"
37 #include "wx/evtloop.h"
39 #include "wx/os2/private.h" // includes <windows.h>
41 // ============================================================================
43 // ============================================================================
45 // ----------------------------------------------------------------------------
46 // functions to work with .INI files
47 // ----------------------------------------------------------------------------
49 // Sleep for nSecs seconds. Attempt a Windows implementation using timers.
50 static bool inTimer
= false;
52 class wxSleepTimer
: public wxTimer
62 // ---------------------------------------------------------------------------
63 // helper functions for showing a "busy" cursor
64 // ---------------------------------------------------------------------------
66 HCURSOR gs_wxBusyCursor
= 0; // new, busy cursor
67 HCURSOR gs_wxBusyCursorOld
= 0; // old cursor
68 static int gs_wxBusyCursorCount
= 0;
70 // Set the cursor to the busy cursor for all windows
71 void wxBeginBusyCursor(const wxCursor
* pCursor
)
73 if ( gs_wxBusyCursorCount
++ == 0 )
75 gs_wxBusyCursor
= (HCURSOR
)pCursor
->GetHCURSOR();
76 ::WinSetPointer(HWND_DESKTOP
, (HPOINTER
)gs_wxBusyCursor
);
78 //else: nothing to do, already set
81 // Restore cursor to normal
82 void wxEndBusyCursor()
84 wxCHECK_RET( gs_wxBusyCursorCount
> 0
85 ,wxT("no matching wxBeginBusyCursor() for wxEndBusyCursor()")
88 if (--gs_wxBusyCursorCount
== 0)
90 ::WinSetPointer(HWND_DESKTOP
, (HPOINTER
)gs_wxBusyCursorOld
);
91 gs_wxBusyCursorOld
= 0;
95 // true if we're between the above two calls
98 return (gs_wxBusyCursorCount
> 0);
101 // Check whether this window wants to process messages, e.g. Stop button
102 // in long calculations.
103 bool wxCheckForInterrupt( wxWindow
* pWnd
)
109 HWND hwndFilter
= NULLHANDLE
;
111 while(::WinPeekMsg(hab
, &vMsg
, hwndFilter
, 0, 0, PM_REMOVE
))
113 ::WinDispatchMsg(hab
, &vMsg
);
115 return true;//*** temporary?
119 wxFAIL_MSG(wxT("pWnd==NULL !!!"));
120 return false;//*** temporary?
124 // ----------------------------------------------------------------------------
126 // ----------------------------------------------------------------------------
128 // See also the wxGetMousePosition in window.cpp
129 // Deprecated: use wxPoint wxGetMousePosition() instead
130 void wxGetMousePosition(
137 ::WinQueryPointerPos(HWND_DESKTOP
, &vPt
);
142 // Return true if we have a colour display
143 bool wxColourDisplay()
150 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
151 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
152 ::DevQueryCaps(hdcScreen
, CAPS_COLORS
, 1L, &lColors
);
153 return(lColors
> 1L);
155 // I don't see how the PM display could not be color. Besides, this
156 // was leaking DCs and PSs!!! MN
161 // Returns depth of screen
168 static LONG nDepth
= 0;
170 // The screen colordepth ain't gonna change. No reason to query
173 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
174 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
175 ::DevQueryCaps(hdcScreen
, CAPS_COLOR_PLANES
, 1L, &lPlanes
);
176 ::DevQueryCaps(hdcScreen
, CAPS_COLOR_BITCOUNT
, 1L, &lBitsPerPixel
);
178 nDepth
= (int)(lPlanes
* lBitsPerPixel
);
179 ::DevCloseDC(hdcScreen
);
180 ::WinReleasePS(hpsScreen
);
185 // Get size of display
193 static LONG lWidth
= 0;
194 static LONG lHeight
= 0;
196 // The screen size ain't gonna change either so just cache the values
198 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
199 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
200 ::DevQueryCaps(hdcScreen
, CAPS_WIDTH
, 1L, &lWidth
);
201 ::DevQueryCaps(hdcScreen
, CAPS_HEIGHT
, 1L, &lHeight
);
202 ::DevCloseDC(hdcScreen
);
203 ::WinReleasePS(hpsScreen
);
206 *pWidth
= (int)lWidth
;
208 *pHeight
= (int)lHeight
;
211 void wxDisplaySizeMM(
219 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
220 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
223 ::DevQueryCaps( hdcScreen
224 ,CAPS_HORIZONTAL_RESOLUTION
229 ::DevQueryCaps( hdcScreen
230 ,CAPS_VERTICAL_RESOLUTION
234 ::DevCloseDC(hdcScreen
);
235 ::WinReleasePS(hpsScreen
);
238 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
)
240 // This is supposed to return desktop dimensions minus any window
241 // manager panels, menus, taskbars, etc. If there is a way to do that
242 // for this platform please fix this function, otherwise it defaults
243 // to the entire desktop.
246 wxDisplaySize(width
, height
);
249 void wxGUIAppTraits::InitializeGui(unsigned long &ulHab
)
251 ulHab
= ::WinInitialize(0);
254 void wxGUIAppTraits::TerminateGui(unsigned long ulHab
)
256 ::WinTerminate(ulHab
);
259 wxPortId
wxGUIAppTraits::GetToolkitVersion(int *verMaj
, int *verMin
) const
261 // How to get version of PM ? I guess, just reusing the OS version is OK.
262 (void) wxGetOsVersion(verMaj
, verMin
);
266 wxTimerImpl
* wxGUIAppTraits::CreateTimerImpl(wxTimer
*timer
)
268 return new wxOS2TimerImpl(timer
);
271 wxEventLoopBase
* wxGUIAppTraits::CreateEventLoop()
273 return new wxEventLoop
;
276 // ---------------------------------------------------------------------------
277 // window information functions
278 // ---------------------------------------------------------------------------
280 wxString WXDLLEXPORT
wxGetWindowText( WXHWND hWnd
)
286 long lLen
= ::WinQueryWindowTextLength((HWND
)hWnd
) + 1;
287 ::WinQueryWindowText((HWND
)hWnd
, lLen
, (PSZ
)(wxChar
*)wxStringBuffer(vStr
, lLen
));
293 wxString WXDLLEXPORT
wxGetWindowClass( WXHWND hWnd
)
298 int nLen
= 256; // some starting value
302 int nCount
= ::WinQueryClassName((HWND
)hWnd
, nLen
, (PSZ
)(wxChar
*)wxStringBuffer(vStr
, nLen
));
306 // the class name might have been truncated, retry with larger
319 WXWORD WXDLLEXPORT
wxGetWindowId(
323 return ::WinQueryWindowUShort((HWND
)hWnd
, QWS_ID
);
334 vPoint
[0].x
= rRect
.xLeft
;
335 vPoint
[0].y
= rRect
.yBottom
;
336 ::GpiMove(hPS
, &vPoint
[0]);
337 if (dwStyle
& wxSIMPLE_BORDER
||
338 dwStyle
& wxSTATIC_BORDER
)
340 vPoint
[1].x
= rRect
.xRight
- 1;
341 vPoint
[1].y
= rRect
.yTop
- 1;
349 if (dwStyle
& wxSUNKEN_BORDER
)
351 LINEBUNDLE vLineBundle
;
353 vLineBundle
.lColor
= 0x00FFFFFF; // WHITE
354 vLineBundle
.usMixMode
= FM_OVERPAINT
;
355 vLineBundle
.fxWidth
= 2;
356 vLineBundle
.lGeomWidth
= 2;
357 vLineBundle
.usType
= LINETYPE_SOLID
;
358 vLineBundle
.usEnd
= 0;
359 vLineBundle
.usJoin
= 0;
362 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
366 vPoint
[1].x
= rRect
.xRight
- 1;
367 vPoint
[1].y
= rRect
.yTop
- 1;
374 vPoint
[0].x
= rRect
.xLeft
+ 1;
375 vPoint
[0].y
= rRect
.yBottom
+ 1;
376 ::GpiMove(hPS
, &vPoint
[0]);
377 vPoint
[1].x
= rRect
.xRight
- 2;
378 vPoint
[1].y
= rRect
.yTop
- 2;
386 vLineBundle
.lColor
= 0x00000000; // BLACK
387 vLineBundle
.usMixMode
= FM_OVERPAINT
;
388 vLineBundle
.fxWidth
= 2;
389 vLineBundle
.lGeomWidth
= 2;
390 vLineBundle
.usType
= LINETYPE_SOLID
;
391 vLineBundle
.usEnd
= 0;
392 vLineBundle
.usJoin
= 0;
395 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
399 vPoint
[0].x
= rRect
.xLeft
+ 2;
400 vPoint
[0].y
= rRect
.yBottom
+ 2;
401 ::GpiMove(hPS
, &vPoint
[0]);
402 vPoint
[1].x
= rRect
.xLeft
+ 2;
403 vPoint
[1].y
= rRect
.yTop
- 3;
404 ::GpiLine(hPS
, &vPoint
[1]);
405 vPoint
[1].x
= rRect
.xRight
- 3;
406 vPoint
[1].y
= rRect
.yTop
- 3;
407 ::GpiLine(hPS
, &vPoint
[1]);
409 vPoint
[0].x
= rRect
.xLeft
+ 3;
410 vPoint
[0].y
= rRect
.yBottom
+ 3;
411 ::GpiMove(hPS
, &vPoint
[0]);
412 vPoint
[1].x
= rRect
.xLeft
+ 3;
413 vPoint
[1].y
= rRect
.yTop
- 4;
414 ::GpiLine(hPS
, &vPoint
[1]);
415 vPoint
[1].x
= rRect
.xRight
- 4;
416 vPoint
[1].y
= rRect
.yTop
- 4;
417 ::GpiLine(hPS
, &vPoint
[1]);
419 if (dwStyle
& wxDOUBLE_BORDER
)
421 LINEBUNDLE vLineBundle
;
423 vLineBundle
.lColor
= 0x00FFFFFF; // WHITE
424 vLineBundle
.usMixMode
= FM_OVERPAINT
;
425 vLineBundle
.fxWidth
= 2;
426 vLineBundle
.lGeomWidth
= 2;
427 vLineBundle
.usType
= LINETYPE_SOLID
;
428 vLineBundle
.usEnd
= 0;
429 vLineBundle
.usJoin
= 0;
432 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
436 vPoint
[1].x
= rRect
.xRight
- 1;
437 vPoint
[1].y
= rRect
.yTop
- 1;
444 vLineBundle
.lColor
= 0x00000000; // WHITE
445 vLineBundle
.usMixMode
= FM_OVERPAINT
;
446 vLineBundle
.fxWidth
= 2;
447 vLineBundle
.lGeomWidth
= 2;
448 vLineBundle
.usType
= LINETYPE_SOLID
;
449 vLineBundle
.usEnd
= 0;
450 vLineBundle
.usJoin
= 0;
453 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
457 vPoint
[0].x
= rRect
.xLeft
+ 2;
458 vPoint
[0].y
= rRect
.yBottom
+ 2;
459 ::GpiMove(hPS
, &vPoint
[0]);
460 vPoint
[1].x
= rRect
.xRight
- 2;
461 vPoint
[1].y
= rRect
.yTop
- 2;
468 vLineBundle
.lColor
= 0x00FFFFFF; // BLACK
469 vLineBundle
.usMixMode
= FM_OVERPAINT
;
470 vLineBundle
.fxWidth
= 2;
471 vLineBundle
.lGeomWidth
= 2;
472 vLineBundle
.usType
= LINETYPE_SOLID
;
473 vLineBundle
.usEnd
= 0;
474 vLineBundle
.usJoin
= 0;
477 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
481 vPoint
[0].x
= rRect
.xLeft
+ 3;
482 vPoint
[0].y
= rRect
.yBottom
+ 3;
483 ::GpiMove(hPS
, &vPoint
[0]);
484 vPoint
[1].x
= rRect
.xRight
- 3;
485 vPoint
[1].y
= rRect
.yTop
- 3;
493 if (dwStyle
& wxRAISED_BORDER
)
495 LINEBUNDLE vLineBundle
;
497 vLineBundle
.lColor
= 0x00000000; // BLACK
498 vLineBundle
.usMixMode
= FM_OVERPAINT
;
499 vLineBundle
.fxWidth
= 2;
500 vLineBundle
.lGeomWidth
= 2;
501 vLineBundle
.usType
= LINETYPE_SOLID
;
502 vLineBundle
.usEnd
= 0;
503 vLineBundle
.usJoin
= 0;
506 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
510 vPoint
[1].x
= rRect
.xRight
- 1;
511 vPoint
[1].y
= rRect
.yTop
- 1;
518 vPoint
[0].x
= rRect
.xLeft
+ 1;
519 vPoint
[0].y
= rRect
.yBottom
+ 1;
520 ::GpiMove(hPS
, &vPoint
[0]);
521 vPoint
[1].x
= rRect
.xRight
- 2;
522 vPoint
[1].y
= rRect
.yTop
- 2;
530 vLineBundle
.lColor
= 0x00FFFFFF; // WHITE
531 vLineBundle
.usMixMode
= FM_OVERPAINT
;
532 vLineBundle
.fxWidth
= 2;
533 vLineBundle
.lGeomWidth
= 2;
534 vLineBundle
.usType
= LINETYPE_SOLID
;
535 vLineBundle
.usEnd
= 0;
536 vLineBundle
.usJoin
= 0;
539 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
543 vPoint
[0].x
= rRect
.xLeft
+ 2;
544 vPoint
[0].y
= rRect
.yBottom
+ 2;
545 ::GpiMove(hPS
, &vPoint
[0]);
546 vPoint
[1].x
= rRect
.xLeft
+ 2;
547 vPoint
[1].y
= rRect
.yTop
- 3;
548 ::GpiLine(hPS
, &vPoint
[1]);
549 vPoint
[1].x
= rRect
.xRight
- 3;
550 vPoint
[1].y
= rRect
.yTop
- 3;
551 ::GpiLine(hPS
, &vPoint
[1]);
553 vPoint
[0].x
= rRect
.xLeft
+ 3;
554 vPoint
[0].y
= rRect
.yBottom
+ 3;
555 ::GpiMove(hPS
, &vPoint
[0]);
556 vPoint
[1].x
= rRect
.xLeft
+ 3;
557 vPoint
[1].y
= rRect
.yTop
- 4;
558 ::GpiLine(hPS
, &vPoint
[1]);
559 vPoint
[1].x
= rRect
.xRight
- 4;
560 vPoint
[1].y
= rRect
.yTop
- 4;
561 ::GpiLine(hPS
, &vPoint
[1]);
563 } // end of wxDrawBorder
567 , const wxFont
& rFont
575 if (hWnd
== NULLHANDLE
)
579 // The fonts available for Presentation Params are just a few
580 // outline fonts, the rest are available to the GPI, so we must
581 // map the families to one of these three
583 switch(rFont
.GetFamily())
586 strcpy(zFacename
, "Script");
590 strcpy(zFacename
, "WarpSans");
594 strcpy(zFacename
,"Times New Roman");
598 strcpy(zFacename
, "Courier New");
602 strcpy(zFacename
, "Courier New");
608 strcpy(zFacename
, "Helvetica");
612 switch(rFont
.GetWeight())
621 case wxFONTWEIGHT_MAX
:
622 strcpy(zWeight
, "Bold");
626 switch(rFont
.GetStyle())
630 strcpy(zStyle
, "Italic");
637 sprintf(zFont
, "%d.%s", rFont
.GetPointSize(), zFacename
);
638 if (zWeight
[0] != '\0')
641 strcat(zFont
, zWeight
);
643 if (zStyle
[0] != '\0')
646 strcat(zFont
, zStyle
);
648 ::WinSetPresParam(hWnd
, PP_FONTNAMESIZE
, strlen(zFont
) + 1, (PVOID
)zFont
);
649 } // end of wxOS2SetFont
651 // ---------------------------------------------------------------------------
652 // Helper for taking a regular bitmap and giving it a disabled look
653 // ---------------------------------------------------------------------------
654 wxBitmap
wxDisableBitmap(
659 wxMask
* pMask
= rBmp
.GetMask();
662 return(wxNullBitmap
);
664 DEVOPENSTRUC vDop
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L};
665 SIZEL vSize
= {0, 0};
666 HDC hDC
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
);
667 HPS hPS
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS
| GPIA_ASSOC
);
668 BITMAPINFOHEADER2 vHeader
;
672 HBITMAP hBitmap
= (HBITMAP
)rBmp
.GetHBITMAP();
673 HBITMAP hOldBitmap
= NULLHANDLE
;
674 HBITMAP hOldMask
= NULLHANDLE
;
675 HBITMAP hMask
= (HBITMAP
)rBmp
.GetMask()->GetMaskBitmap();
676 unsigned char* pucBits
; // buffer that will contain the bitmap data
677 unsigned char* pucData
; // pointer to use to traverse bitmap data
678 unsigned char* pucBitsMask
; // buffer that will contain the mask data
679 unsigned char* pucDataMask
; // pointer to use to traverse mask data
682 bool bpp16
= (wxDisplayDepth() == 16);
684 memset(&vHeader
, '\0', 16);
687 memset(&vInfo
, '\0', 16);
689 vInfo
.cx
= (ULONG
)rBmp
.GetWidth();
690 vInfo
.cy
= (ULONG
)rBmp
.GetHeight();
692 vInfo
.cBitCount
= 24; // Set to desired count going in
695 // Create the buffers for data....all wxBitmaps are 24 bit internally
697 int nBytesPerLine
= rBmp
.GetWidth() * 3;
698 int nSizeDWORD
= sizeof(DWORD
);
699 int nLineBoundary
= nBytesPerLine
% nSizeDWORD
;
705 // Bitmap must be in a double-word aligned address so we may
706 // have some padding to worry about
708 if (nLineBoundary
> 0)
710 nPadding
= nSizeDWORD
- nLineBoundary
;
711 nBytesPerLine
+= nPadding
;
713 pucBits
= (unsigned char *)malloc(nBytesPerLine
* rBmp
.GetHeight());
714 memset(pucBits
, '\0', (nBytesPerLine
* rBmp
.GetHeight()));
715 pucBitsMask
= (unsigned char *)malloc(nBytesPerLine
* rBmp
.GetHeight());
716 memset(pucBitsMask
, '\0', (nBytesPerLine
* rBmp
.GetHeight()));
719 // Extract the bitmap and mask data
721 if ((hOldBitmap
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
)
723 vError
= ::WinGetLastError(vHabmain
);
724 sError
= wxPMErrorToStr(vError
);
726 ::GpiQueryBitmapInfoHeader(hBitmap
, &vHeader
);
727 vInfo
.cBitCount
= 24;
728 if ((lScans
= ::GpiQueryBitmapBits( hPS
730 ,(LONG
)rBmp
.GetHeight()
735 vError
= ::WinGetLastError(vHabmain
);
736 sError
= wxPMErrorToStr(vError
);
738 if ((hOldMask
= ::GpiSetBitmap(hPS
, hMask
)) == HBM_ERROR
)
740 vError
= ::WinGetLastError(vHabmain
);
741 sError
= wxPMErrorToStr(vError
);
743 ::GpiQueryBitmapInfoHeader(hMask
, &vHeader
);
744 vInfo
.cBitCount
= 24;
745 if ((lScans
= ::GpiQueryBitmapBits( hPS
747 ,(LONG
)rBmp
.GetHeight()
752 vError
= ::WinGetLastError(vHabmain
);
753 sError
= wxPMErrorToStr(vError
);
755 if (( hMask
= ::GpiSetBitmap(hPS
, hOldMask
)) == HBM_ERROR
)
757 vError
= ::WinGetLastError(vHabmain
);
758 sError
= wxPMErrorToStr(vError
);
761 pucDataMask
= pucBitsMask
;
764 // Get the mask value
766 for (i
= 0; i
< rBmp
.GetHeight(); i
++)
768 for (j
= 0; j
< rBmp
.GetWidth(); j
++)
771 if (bpp16
&& *pucDataMask
== 0xF8) // 16 bit display gobblygook
776 else if (*pucDataMask
== 0xFF) // set to grey
783 *pucData
= ((unsigned char)(lColor
>> 16));
788 if (bpp16
&& *(pucDataMask
+ 1) == 0xFC) // 16 bit display gobblygook
793 else if (*(pucDataMask
+ 1) == 0xFF) // set to grey
800 *pucData
= ((unsigned char)(lColor
>> 8));
805 if (bpp16
&& *(pucDataMask
+ 2) == 0xF8) // 16 bit display gobblygook
810 else if (*(pucDataMask
+ 2) == 0xFF) // set to grey
817 *pucData
= ((unsigned char)lColor
);
822 for (j
= 0; j
< nPadding
; j
++)
830 // Create a new bitmap and set the modified bits
832 wxBitmap
vNewBmp( rBmp
.GetWidth()
836 HBITMAP hNewBmp
= (HBITMAP
)vNewBmp
.GetHBITMAP();
838 if ((hOldBitmap
= ::GpiSetBitmap(hPS
, hNewBmp
)) == HBM_ERROR
)
840 vError
= ::WinGetLastError(vHabmain
);
841 sError
= wxPMErrorToStr(vError
);
843 if ((lScansSet
= ::GpiSetBitmapBits( hPS
845 ,(LONG
)rBmp
.GetHeight()
851 vError
= ::WinGetLastError(vHabmain
);
852 sError
= wxPMErrorToStr(vError
);
856 pNewMask
= new wxMask(pMask
->GetMaskBitmap());
857 vNewBmp
.SetMask(pNewMask
);
859 ::GpiSetBitmap(hPS
, NULLHANDLE
);
864 return(wxNullBitmap
);
865 } // end of wxDisableBitmap
867 COLORREF
wxColourToRGB(
868 const wxColour
& rColor
871 return(OS2RGB(rColor
.Red(), rColor
.Green(), rColor
.Blue()));
872 } // end of wxColourToRGB