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"
37 #include "wx/os2/private.h" // includes <windows.h>
39 // ============================================================================
41 // ============================================================================
43 // ----------------------------------------------------------------------------
44 // functions to work with .INI files
45 // ----------------------------------------------------------------------------
47 // Sleep for nSecs seconds. Attempt a Windows implementation using timers.
48 static bool inTimer
= false;
50 class wxSleepTimer
: public wxTimer
60 // ---------------------------------------------------------------------------
61 // helper functions for showing a "busy" cursor
62 // ---------------------------------------------------------------------------
64 HCURSOR gs_wxBusyCursor
= 0; // new, busy cursor
65 HCURSOR gs_wxBusyCursorOld
= 0; // old cursor
66 static int gs_wxBusyCursorCount
= 0;
68 // Set the cursor to the busy cursor for all windows
69 void wxBeginBusyCursor(const wxCursor
* pCursor
)
71 if ( gs_wxBusyCursorCount
++ == 0 )
73 gs_wxBusyCursor
= (HCURSOR
)pCursor
->GetHCURSOR();
74 ::WinSetPointer(HWND_DESKTOP
, (HPOINTER
)gs_wxBusyCursor
);
76 //else: nothing to do, already set
79 // Restore cursor to normal
80 void wxEndBusyCursor()
82 wxCHECK_RET( gs_wxBusyCursorCount
> 0
83 ,_T("no matching wxBeginBusyCursor() for wxEndBusyCursor()")
86 if (--gs_wxBusyCursorCount
== 0)
88 ::WinSetPointer(HWND_DESKTOP
, (HPOINTER
)gs_wxBusyCursorOld
);
89 gs_wxBusyCursorOld
= 0;
93 // true if we're between the above two calls
96 return (gs_wxBusyCursorCount
> 0);
99 // Check whether this window wants to process messages, e.g. Stop button
100 // in long calculations.
101 bool wxCheckForInterrupt( wxWindow
* pWnd
)
107 HWND hwndFilter
= NULLHANDLE
;
109 while(::WinPeekMsg(hab
, &vMsg
, hwndFilter
, 0, 0, PM_REMOVE
))
111 ::WinDispatchMsg(hab
, &vMsg
);
113 return true;//*** temporary?
117 wxFAIL_MSG(_T("pWnd==NULL !!!"));
118 return false;//*** temporary?
122 // ----------------------------------------------------------------------------
124 // ----------------------------------------------------------------------------
126 // See also the wxGetMousePosition in window.cpp
127 // Deprecated: use wxPoint wxGetMousePosition() instead
128 void wxGetMousePosition(
135 ::WinQueryPointerPos(HWND_DESKTOP
, &vPt
);
140 // Return true if we have a colour display
141 bool wxColourDisplay()
148 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
149 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
150 ::DevQueryCaps(hdcScreen
, CAPS_COLORS
, 1L, &lColors
);
151 return(lColors
> 1L);
153 // I don't see how the PM display could not be color. Besides, this
154 // was leaking DCs and PSs!!! MN
159 // Returns depth of screen
166 static LONG nDepth
= 0;
168 // The screen colordepth ain't gonna change. No reason to query
171 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
172 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
173 ::DevQueryCaps(hdcScreen
, CAPS_COLOR_PLANES
, 1L, &lPlanes
);
174 ::DevQueryCaps(hdcScreen
, CAPS_COLOR_BITCOUNT
, 1L, &lBitsPerPixel
);
176 nDepth
= (int)(lPlanes
* lBitsPerPixel
);
177 ::DevCloseDC(hdcScreen
);
178 ::WinReleasePS(hpsScreen
);
183 // Get size of display
191 static LONG lWidth
= 0;
192 static LONG lHeight
= 0;
194 // The screen size ain't gonna change either so just cache the values
196 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
197 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
198 ::DevQueryCaps(hdcScreen
, CAPS_WIDTH
, 1L, &lWidth
);
199 ::DevQueryCaps(hdcScreen
, CAPS_HEIGHT
, 1L, &lHeight
);
200 ::DevCloseDC(hdcScreen
);
201 ::WinReleasePS(hpsScreen
);
204 *pWidth
= (int)lWidth
;
206 *pHeight
= (int)lHeight
;
209 void wxDisplaySizeMM(
217 hpsScreen
= ::WinGetScreenPS(HWND_DESKTOP
);
218 hdcScreen
= ::GpiQueryDevice(hpsScreen
);
221 ::DevQueryCaps( hdcScreen
222 ,CAPS_HORIZONTAL_RESOLUTION
227 ::DevQueryCaps( hdcScreen
228 ,CAPS_VERTICAL_RESOLUTION
232 ::DevCloseDC(hdcScreen
);
233 ::WinReleasePS(hpsScreen
);
236 void wxClientDisplayRect(int *x
, int *y
, int *width
, int *height
)
238 // This is supposed to return desktop dimensions minus any window
239 // manager panels, menus, taskbars, etc. If there is a way to do that
240 // for this platform please fix this function, otherwise it defaults
241 // to the entire desktop.
244 wxDisplaySize(width
, height
);
247 void wxGUIAppTraits::InitializeGui(unsigned long &ulHab
)
249 ulHab
= ::WinInitialize(0);
252 void wxGUIAppTraits::TerminateGui(unsigned long ulHab
)
254 ::WinTerminate(ulHab
);
257 wxPortId
wxGUIAppTraits::GetToolkitVersion(int *verMaj
, int *verMin
) const
259 // How to get version of PM ? I guess, just reusing the OS version is OK.
260 (void) wxGetOsVersion(verMaj
, verMin
);
265 // ---------------------------------------------------------------------------
266 // window information functions
267 // ---------------------------------------------------------------------------
269 wxString WXDLLEXPORT
wxGetWindowText( WXHWND hWnd
)
275 long lLen
= ::WinQueryWindowTextLength((HWND
)hWnd
) + 1;
276 ::WinQueryWindowText((HWND
)hWnd
, lLen
, (PSZ
)(wxChar
*)wxStringBuffer(vStr
, lLen
));
282 wxString WXDLLEXPORT
wxGetWindowClass( WXHWND hWnd
)
287 int nLen
= 256; // some starting value
291 int nCount
= ::WinQueryClassName((HWND
)hWnd
, nLen
, (PSZ
)(wxChar
*)wxStringBuffer(vStr
, nLen
));
295 // the class name might have been truncated, retry with larger
308 WXWORD WXDLLEXPORT
wxGetWindowId(
312 return ::WinQueryWindowUShort((HWND
)hWnd
, QWS_ID
);
323 vPoint
[0].x
= rRect
.xLeft
;
324 vPoint
[0].y
= rRect
.yBottom
;
325 ::GpiMove(hPS
, &vPoint
[0]);
326 if (dwStyle
& wxSIMPLE_BORDER
||
327 dwStyle
& wxSTATIC_BORDER
)
329 vPoint
[1].x
= rRect
.xRight
- 1;
330 vPoint
[1].y
= rRect
.yTop
- 1;
338 if (dwStyle
& wxSUNKEN_BORDER
)
340 LINEBUNDLE vLineBundle
;
342 vLineBundle
.lColor
= 0x00FFFFFF; // WHITE
343 vLineBundle
.usMixMode
= FM_OVERPAINT
;
344 vLineBundle
.fxWidth
= 2;
345 vLineBundle
.lGeomWidth
= 2;
346 vLineBundle
.usType
= LINETYPE_SOLID
;
347 vLineBundle
.usEnd
= 0;
348 vLineBundle
.usJoin
= 0;
351 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
355 vPoint
[1].x
= rRect
.xRight
- 1;
356 vPoint
[1].y
= rRect
.yTop
- 1;
363 vPoint
[0].x
= rRect
.xLeft
+ 1;
364 vPoint
[0].y
= rRect
.yBottom
+ 1;
365 ::GpiMove(hPS
, &vPoint
[0]);
366 vPoint
[1].x
= rRect
.xRight
- 2;
367 vPoint
[1].y
= rRect
.yTop
- 2;
375 vLineBundle
.lColor
= 0x00000000; // BLACK
376 vLineBundle
.usMixMode
= FM_OVERPAINT
;
377 vLineBundle
.fxWidth
= 2;
378 vLineBundle
.lGeomWidth
= 2;
379 vLineBundle
.usType
= LINETYPE_SOLID
;
380 vLineBundle
.usEnd
= 0;
381 vLineBundle
.usJoin
= 0;
384 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
388 vPoint
[0].x
= rRect
.xLeft
+ 2;
389 vPoint
[0].y
= rRect
.yBottom
+ 2;
390 ::GpiMove(hPS
, &vPoint
[0]);
391 vPoint
[1].x
= rRect
.xLeft
+ 2;
392 vPoint
[1].y
= rRect
.yTop
- 3;
393 ::GpiLine(hPS
, &vPoint
[1]);
394 vPoint
[1].x
= rRect
.xRight
- 3;
395 vPoint
[1].y
= rRect
.yTop
- 3;
396 ::GpiLine(hPS
, &vPoint
[1]);
398 vPoint
[0].x
= rRect
.xLeft
+ 3;
399 vPoint
[0].y
= rRect
.yBottom
+ 3;
400 ::GpiMove(hPS
, &vPoint
[0]);
401 vPoint
[1].x
= rRect
.xLeft
+ 3;
402 vPoint
[1].y
= rRect
.yTop
- 4;
403 ::GpiLine(hPS
, &vPoint
[1]);
404 vPoint
[1].x
= rRect
.xRight
- 4;
405 vPoint
[1].y
= rRect
.yTop
- 4;
406 ::GpiLine(hPS
, &vPoint
[1]);
408 if (dwStyle
& wxDOUBLE_BORDER
)
410 LINEBUNDLE vLineBundle
;
412 vLineBundle
.lColor
= 0x00FFFFFF; // WHITE
413 vLineBundle
.usMixMode
= FM_OVERPAINT
;
414 vLineBundle
.fxWidth
= 2;
415 vLineBundle
.lGeomWidth
= 2;
416 vLineBundle
.usType
= LINETYPE_SOLID
;
417 vLineBundle
.usEnd
= 0;
418 vLineBundle
.usJoin
= 0;
421 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
425 vPoint
[1].x
= rRect
.xRight
- 1;
426 vPoint
[1].y
= rRect
.yTop
- 1;
433 vLineBundle
.lColor
= 0x00000000; // WHITE
434 vLineBundle
.usMixMode
= FM_OVERPAINT
;
435 vLineBundle
.fxWidth
= 2;
436 vLineBundle
.lGeomWidth
= 2;
437 vLineBundle
.usType
= LINETYPE_SOLID
;
438 vLineBundle
.usEnd
= 0;
439 vLineBundle
.usJoin
= 0;
442 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
446 vPoint
[0].x
= rRect
.xLeft
+ 2;
447 vPoint
[0].y
= rRect
.yBottom
+ 2;
448 ::GpiMove(hPS
, &vPoint
[0]);
449 vPoint
[1].x
= rRect
.xRight
- 2;
450 vPoint
[1].y
= rRect
.yTop
- 2;
457 vLineBundle
.lColor
= 0x00FFFFFF; // BLACK
458 vLineBundle
.usMixMode
= FM_OVERPAINT
;
459 vLineBundle
.fxWidth
= 2;
460 vLineBundle
.lGeomWidth
= 2;
461 vLineBundle
.usType
= LINETYPE_SOLID
;
462 vLineBundle
.usEnd
= 0;
463 vLineBundle
.usJoin
= 0;
466 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
470 vPoint
[0].x
= rRect
.xLeft
+ 3;
471 vPoint
[0].y
= rRect
.yBottom
+ 3;
472 ::GpiMove(hPS
, &vPoint
[0]);
473 vPoint
[1].x
= rRect
.xRight
- 3;
474 vPoint
[1].y
= rRect
.yTop
- 3;
482 if (dwStyle
& wxRAISED_BORDER
)
484 LINEBUNDLE vLineBundle
;
486 vLineBundle
.lColor
= 0x00000000; // BLACK
487 vLineBundle
.usMixMode
= FM_OVERPAINT
;
488 vLineBundle
.fxWidth
= 2;
489 vLineBundle
.lGeomWidth
= 2;
490 vLineBundle
.usType
= LINETYPE_SOLID
;
491 vLineBundle
.usEnd
= 0;
492 vLineBundle
.usJoin
= 0;
495 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
499 vPoint
[1].x
= rRect
.xRight
- 1;
500 vPoint
[1].y
= rRect
.yTop
- 1;
507 vPoint
[0].x
= rRect
.xLeft
+ 1;
508 vPoint
[0].y
= rRect
.yBottom
+ 1;
509 ::GpiMove(hPS
, &vPoint
[0]);
510 vPoint
[1].x
= rRect
.xRight
- 2;
511 vPoint
[1].y
= rRect
.yTop
- 2;
519 vLineBundle
.lColor
= 0x00FFFFFF; // WHITE
520 vLineBundle
.usMixMode
= FM_OVERPAINT
;
521 vLineBundle
.fxWidth
= 2;
522 vLineBundle
.lGeomWidth
= 2;
523 vLineBundle
.usType
= LINETYPE_SOLID
;
524 vLineBundle
.usEnd
= 0;
525 vLineBundle
.usJoin
= 0;
528 ,LBB_COLOR
| LBB_MIX_MODE
| LBB_WIDTH
| LBB_GEOM_WIDTH
| LBB_TYPE
532 vPoint
[0].x
= rRect
.xLeft
+ 2;
533 vPoint
[0].y
= rRect
.yBottom
+ 2;
534 ::GpiMove(hPS
, &vPoint
[0]);
535 vPoint
[1].x
= rRect
.xLeft
+ 2;
536 vPoint
[1].y
= rRect
.yTop
- 3;
537 ::GpiLine(hPS
, &vPoint
[1]);
538 vPoint
[1].x
= rRect
.xRight
- 3;
539 vPoint
[1].y
= rRect
.yTop
- 3;
540 ::GpiLine(hPS
, &vPoint
[1]);
542 vPoint
[0].x
= rRect
.xLeft
+ 3;
543 vPoint
[0].y
= rRect
.yBottom
+ 3;
544 ::GpiMove(hPS
, &vPoint
[0]);
545 vPoint
[1].x
= rRect
.xLeft
+ 3;
546 vPoint
[1].y
= rRect
.yTop
- 4;
547 ::GpiLine(hPS
, &vPoint
[1]);
548 vPoint
[1].x
= rRect
.xRight
- 4;
549 vPoint
[1].y
= rRect
.yTop
- 4;
550 ::GpiLine(hPS
, &vPoint
[1]);
552 } // end of wxDrawBorder
556 , const wxFont
& rFont
564 if (hWnd
== NULLHANDLE
)
568 // The fonts available for Presentation Params are just a few
569 // outline fonts, the rest are available to the GPI, so we must
570 // map the families to one of these three
572 switch(rFont
.GetFamily())
575 strcpy(zFacename
, "Script");
579 strcpy(zFacename
, "WarpSans");
583 strcpy(zFacename
,"Times New Roman");
587 strcpy(zFacename
, "Courier New");
591 strcpy(zFacename
, "Courier New");
597 strcpy(zFacename
, "Helvetica");
601 switch(rFont
.GetWeight())
610 case wxFONTWEIGHT_MAX
:
611 strcpy(zWeight
, "Bold");
615 switch(rFont
.GetStyle())
619 strcpy(zStyle
, "Italic");
626 sprintf(zFont
, "%d.%s", rFont
.GetPointSize(), zFacename
);
627 if (zWeight
[0] != '\0')
630 strcat(zFont
, zWeight
);
632 if (zStyle
[0] != '\0')
635 strcat(zFont
, zStyle
);
637 ::WinSetPresParam(hWnd
, PP_FONTNAMESIZE
, strlen(zFont
) + 1, (PVOID
)zFont
);
638 } // end of wxOS2SetFont
640 // ---------------------------------------------------------------------------
641 // Helper for taking a regular bitmap and giving it a disabled look
642 // ---------------------------------------------------------------------------
643 wxBitmap
wxDisableBitmap(
648 wxMask
* pMask
= rBmp
.GetMask();
651 return(wxNullBitmap
);
653 DEVOPENSTRUC vDop
= {0L, "DISPLAY", NULL
, 0L, 0L, 0L, 0L, 0L, 0L};
654 SIZEL vSize
= {0, 0};
655 HDC hDC
= ::DevOpenDC(vHabmain
, OD_MEMORY
, "*", 5L, (PDEVOPENDATA
)&vDop
, NULLHANDLE
);
656 HPS hPS
= ::GpiCreatePS(vHabmain
, hDC
, &vSize
, PU_PELS
| GPIA_ASSOC
);
657 BITMAPINFOHEADER2 vHeader
;
661 HBITMAP hBitmap
= (HBITMAP
)rBmp
.GetHBITMAP();
662 HBITMAP hOldBitmap
= NULLHANDLE
;
663 HBITMAP hOldMask
= NULLHANDLE
;
664 HBITMAP hMask
= (HBITMAP
)rBmp
.GetMask()->GetMaskBitmap();
665 unsigned char* pucBits
; // buffer that will contain the bitmap data
666 unsigned char* pucData
; // pointer to use to traverse bitmap data
667 unsigned char* pucBitsMask
; // buffer that will contain the mask data
668 unsigned char* pucDataMask
; // pointer to use to traverse mask data
671 bool bpp16
= (wxDisplayDepth() == 16);
673 memset(&vHeader
, '\0', 16);
676 memset(&vInfo
, '\0', 16);
678 vInfo
.cx
= (ULONG
)rBmp
.GetWidth();
679 vInfo
.cy
= (ULONG
)rBmp
.GetHeight();
681 vInfo
.cBitCount
= 24; // Set to desired count going in
684 // Create the buffers for data....all wxBitmaps are 24 bit internally
686 int nBytesPerLine
= rBmp
.GetWidth() * 3;
687 int nSizeDWORD
= sizeof(DWORD
);
688 int nLineBoundary
= nBytesPerLine
% nSizeDWORD
;
694 // Bitmap must be in a double-word aligned address so we may
695 // have some padding to worry about
697 if (nLineBoundary
> 0)
699 nPadding
= nSizeDWORD
- nLineBoundary
;
700 nBytesPerLine
+= nPadding
;
702 pucBits
= (unsigned char *)malloc(nBytesPerLine
* rBmp
.GetHeight());
703 memset(pucBits
, '\0', (nBytesPerLine
* rBmp
.GetHeight()));
704 pucBitsMask
= (unsigned char *)malloc(nBytesPerLine
* rBmp
.GetHeight());
705 memset(pucBitsMask
, '\0', (nBytesPerLine
* rBmp
.GetHeight()));
708 // Extract the bitmap and mask data
710 if ((hOldBitmap
= ::GpiSetBitmap(hPS
, hBitmap
)) == HBM_ERROR
)
712 vError
= ::WinGetLastError(vHabmain
);
713 sError
= wxPMErrorToStr(vError
);
715 ::GpiQueryBitmapInfoHeader(hBitmap
, &vHeader
);
716 vInfo
.cBitCount
= 24;
717 if ((lScans
= ::GpiQueryBitmapBits( hPS
719 ,(LONG
)rBmp
.GetHeight()
724 vError
= ::WinGetLastError(vHabmain
);
725 sError
= wxPMErrorToStr(vError
);
727 if ((hOldMask
= ::GpiSetBitmap(hPS
, hMask
)) == HBM_ERROR
)
729 vError
= ::WinGetLastError(vHabmain
);
730 sError
= wxPMErrorToStr(vError
);
732 ::GpiQueryBitmapInfoHeader(hMask
, &vHeader
);
733 vInfo
.cBitCount
= 24;
734 if ((lScans
= ::GpiQueryBitmapBits( hPS
736 ,(LONG
)rBmp
.GetHeight()
741 vError
= ::WinGetLastError(vHabmain
);
742 sError
= wxPMErrorToStr(vError
);
744 if (( hMask
= ::GpiSetBitmap(hPS
, hOldMask
)) == HBM_ERROR
)
746 vError
= ::WinGetLastError(vHabmain
);
747 sError
= wxPMErrorToStr(vError
);
750 pucDataMask
= pucBitsMask
;
753 // Get the mask value
755 for (i
= 0; i
< rBmp
.GetHeight(); i
++)
757 for (j
= 0; j
< rBmp
.GetWidth(); j
++)
760 if (bpp16
&& *pucDataMask
== 0xF8) // 16 bit display gobblygook
765 else if (*pucDataMask
== 0xFF) // set to grey
772 *pucData
= ((unsigned char)(lColor
>> 16));
777 if (bpp16
&& *(pucDataMask
+ 1) == 0xFC) // 16 bit display gobblygook
782 else if (*(pucDataMask
+ 1) == 0xFF) // set to grey
789 *pucData
= ((unsigned char)(lColor
>> 8));
794 if (bpp16
&& *(pucDataMask
+ 2) == 0xF8) // 16 bit display gobblygook
799 else if (*(pucDataMask
+ 2) == 0xFF) // set to grey
806 *pucData
= ((unsigned char)lColor
);
811 for (j
= 0; j
< nPadding
; j
++)
819 // Create a new bitmap and set the modified bits
821 wxBitmap
vNewBmp( rBmp
.GetWidth()
825 HBITMAP hNewBmp
= (HBITMAP
)vNewBmp
.GetHBITMAP();
827 if ((hOldBitmap
= ::GpiSetBitmap(hPS
, hNewBmp
)) == HBM_ERROR
)
829 vError
= ::WinGetLastError(vHabmain
);
830 sError
= wxPMErrorToStr(vError
);
832 if ((lScansSet
= ::GpiSetBitmapBits( hPS
834 ,(LONG
)rBmp
.GetHeight()
840 vError
= ::WinGetLastError(vHabmain
);
841 sError
= wxPMErrorToStr(vError
);
845 pNewMask
= new wxMask(pMask
->GetMaskBitmap());
846 vNewBmp
.SetMask(pNewMask
);
848 ::GpiSetBitmap(hPS
, NULLHANDLE
);
853 return(wxNullBitmap
);
854 } // end of wxDisableBitmap
856 COLORREF
wxColourToRGB(
857 const wxColour
& rColor
860 return(OS2RGB(rColor
.Red(), rColor
.Green(), rColor
.Blue()));
861 } // end of wxColourToRGB