Follow changes in common code.
[wxWidgets.git] / src / os2 / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: windows.cpp
3 // Purpose: wxWindow
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/12/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 //
13 // For compilers that support precompilation, includes "wx.h".
14 //
15 #include "wx/wxprec.h"
16
17 #ifndef WX_PRECOMP
18 #define INCL_DOS
19 #define INCL_PM
20 #include <os2.h>
21 #include "wx/window.h"
22 #include "wx/accel.h"
23 #include "wx/setup.h"
24 #include "wx/menu.h"
25 #include "wx/dc.h"
26 #include "wx/dcclient.h"
27 #include "wx/utils.h"
28 #include "wx/app.h"
29 #include "wx/panel.h"
30 #include "wx/layout.h"
31 #include "wx/checkbox.h"
32 #include "wx/combobox.h"
33 #include "wx/dialog.h"
34 #include "wx/frame.h"
35 #include "wx/listbox.h"
36 #include "wx/button.h"
37 #include "wx/bmpbuttn.h"
38 #include "wx/msgdlg.h"
39 #include "wx/scrolwin.h"
40 #include "wx/radiobox.h"
41 #include "wx/radiobut.h"
42 #include "wx/slider.h"
43 #include "wx/statbox.h"
44 #include "wx/statusbr.h"
45 #include "wx/toolbar.h"
46 #include "wx/settings.h"
47 #include <stdio.h>
48 #endif
49
50 #if wxUSE_OWNER_DRAWN
51 #include "wx/ownerdrw.h"
52 #endif
53
54 #if wxUSE_DRAG_AND_DROP
55 #include "wx/dnd.h"
56 #endif
57
58 #include "wx/menuitem.h"
59 #include "wx/log.h"
60
61 #include "wx/os2/private.h"
62
63 #if wxUSE_TOOLTIPS
64 #include "wx/tooltip.h"
65 #endif
66
67 #if wxUSE_NOTEBOOK
68 #include "wx/notebook.h"
69 #endif
70
71 #if wxUSE_CARET
72 #include "wx/caret.h"
73 #endif // wxUSE_CARET
74
75 #include "wx/intl.h"
76 #include "wx/log.h"
77
78
79 #include "wx/textctrl.h"
80
81 #include <string.h>
82
83 //
84 // Place compiler, OS specific includes here
85 //
86
87 //
88 // Standard macros -- these are for OS/2 PM, but most GUI's have something similar
89 //
90 #ifndef GET_X_LPARAM
91 //
92 // SHORT1FROMMP -- LOWORD
93 //
94 #define GET_X_LPARAM(mp) ((unsigned short)(unsigned long)(mp))
95 //
96 // SHORT2FROMMP -- HIWORD
97 //
98 #define GET_Y_LPARAM(mp) ((unsigned short)(unsigned long)(mp >> 16))
99 #endif // GET_X_LPARAM
100
101 #ifndef CW_USEDEFAULT
102 # define CW_USEDEFAULT ((int)0x80000000)
103 #endif
104
105 #ifndef VK_OEM_1
106 #define VK_OEM_1 0xBA
107 #define VK_OEM_PLUS 0xBB
108 #define VK_OEM_COMMA 0xBC
109 #define VK_OEM_MINUS 0xBD
110 #define VK_OEM_PERIOD 0xBE
111 #define VK_OEM_2 0xBF
112 #define VK_OEM_3 0xC0
113 #define VK_OEM_4 0xDB
114 #define VK_OEM_5 0xDC
115 #define VK_OEM_6 0xDD
116 #define VK_OEM_7 0xDE
117 #endif
118
119 // ---------------------------------------------------------------------------
120 // global variables
121 // ---------------------------------------------------------------------------
122
123 //
124 // The last PM message we got (MT-UNSAFE)
125 //
126 QMSG s_currentMsg;
127
128 #if wxUSE_MENUS_NATIVE
129 wxMenu* wxCurrentPopupMenu = NULL;
130 #endif // wxUSE_MENUS_NATIVE
131
132 // ---------------------------------------------------------------------------
133 // private functions
134 // ---------------------------------------------------------------------------
135
136 //
137 // the window proc for all our windows; most gui's have something similar
138 //
139 MRESULT EXPENTRY wxWndProc( HWND hWnd
140 ,ULONG message
141 ,MPARAM mp1
142 ,MPARAM mp2
143 );
144
145 #ifdef __WXDEBUG__
146 const wxChar *wxGetMessageName(int message);
147 #endif //__WXDEBUG__
148
149 wxWindowOS2* FindWindowForMouseEvent( wxWindow* pWin
150 ,short* pnX
151 ,short* pnY
152 );
153 void wxRemoveHandleAssociation(wxWindowOS2* pWin);
154 void wxAssociateWinWithHandle( HWND hWnd
155 ,wxWindowOS2* pWin
156 );
157 wxWindow* wxFindWinFromHandle(WXHWND hWnd);
158
159 //
160 // get the current state of SHIFT/CTRL keys
161 //
162 static inline bool IsShiftDown() { return (::WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x8000) != 0; }
163 static inline bool IsCtrlDown() { return (::WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x8000) != 0; }
164
165 static wxWindow* gpWinBeingCreated = NULL;
166
167 // ---------------------------------------------------------------------------
168 // event tables
169 // ---------------------------------------------------------------------------
170
171 // in wxUniv-OS/2 this class is abstract because it doesn't have DoPopupMenu()
172 // method
173 #ifdef __WXUNIVERSAL__
174 IMPLEMENT_ABSTRACT_CLASS(wxWindowOS2, wxWindowBase)
175 #else // __WXPM__
176 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
177 #endif // __WXUNIVERSAL__/__WXPM__
178
179 BEGIN_EVENT_TABLE(wxWindowOS2, wxWindowBase)
180 EVT_ERASE_BACKGROUND(wxWindowOS2::OnEraseBackground)
181 EVT_SYS_COLOUR_CHANGED(wxWindowOS2::OnSysColourChanged)
182 EVT_IDLE(wxWindowOS2::OnIdle)
183 EVT_SET_FOCUS(wxWindowOS2::OnSetFocus)
184 END_EVENT_TABLE()
185
186 // ===========================================================================
187 // implementation
188 // ===========================================================================
189
190 // ---------------------------------------------------------------------------
191 // wxWindow utility functions
192 // ---------------------------------------------------------------------------
193
194 //
195 // Find an item given the PM Window id
196 //
197 wxWindow* wxWindowOS2::FindItem(
198 long lId
199 ) const
200 {
201 #if wxUSE_CONTROLS
202 wxControl* pItem = wxDynamicCast(this, wxControl);
203
204 if (pItem)
205 {
206 //
207 // I it we or one of our "internal" children?
208 //
209 if (pItem->GetId() == lId
210 #ifndef __WXUNIVERSAL__
211 || (pItem->GetSubcontrols().Index(lId) != wxNOT_FOUND)
212 #endif
213 )
214 {
215 return pItem;
216 }
217 }
218 #endif // wxUSE_CONTROLS
219
220 wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
221
222 while (current)
223 {
224 wxWindow* pChildWin = current->GetData();
225 wxWindow* pWnd = pChildWin->FindItem(lId);
226
227 if (pWnd)
228 return pWnd;
229
230 current = current->GetNext();
231 }
232 return(NULL);
233 } // end of wxWindowOS2::FindItem
234
235 //
236 // Find an item given the PM Window handle
237 //
238 wxWindow* wxWindowOS2::FindItemByHWND(
239 WXHWND hWnd
240 , bool bControlOnly
241 ) const
242 {
243 wxWindowList::compatibility_iterator current = GetChildren().GetFirst();
244
245 while (current)
246 {
247 wxWindow* pParent = current->GetData();
248
249 //
250 // Do a recursive search.
251 //
252 wxWindow* pWnd = pParent->FindItemByHWND(hWnd);
253
254 if (pWnd)
255 return(pWnd);
256
257 if (!bControlOnly
258 #if wxUSE_CONTROLS
259 || pParent->IsKindOf(CLASSINFO(wxControl))
260 #endif // wxUSE_CONTROLS
261 )
262 {
263 wxWindow* pItem = current->GetData();
264
265 if (pItem->GetHWND() == hWnd)
266 return(pItem);
267 else
268 {
269 if (pItem->ContainsHWND(hWnd))
270 return(pItem);
271 }
272 }
273 current = current->GetNext();
274 }
275 return(NULL);
276 } // end of wxWindowOS2::FindItemByHWND
277
278 //
279 // Default command handler
280 //
281 bool wxWindowOS2::OS2Command( WXUINT WXUNUSED(uParam),
282 WXWORD WXUNUSED(uId) )
283 {
284 return false;
285 }
286
287 // ----------------------------------------------------------------------------
288 // constructors and such
289 // ----------------------------------------------------------------------------
290
291 void wxWindowOS2::Init()
292 {
293 //
294 // PM specific
295 //
296 m_bWinCaptured = false;
297
298 m_fnOldWndProc = NULL;
299 m_bUseCtl3D = false;
300 m_bMouseInWindow = false;
301 m_bLastKeydownProcessed = false;
302 m_pChildrenDisabled = NULL;
303
304 //
305 // wxWnd
306 //
307 m_hMenu = 0L;
308 m_hWnd = 0L;
309 m_hWndScrollBarHorz = 0L;
310 m_hWndScrollBarVert = 0L;
311
312 memset(&m_vWinSwp, '\0', sizeof (SWP));
313
314 //
315 // Pass WM_GETDLGCODE to DefWindowProc()
316 //
317 m_lDlgCode = 0;
318
319 m_nXThumbSize = 0;
320 m_nYThumbSize = 0;
321 m_bBackgroundTransparent = false;
322
323 //
324 // As all windows are created with WS_VISIBLE style...
325 //
326 m_isShown = true;
327
328 #if wxUSE_MOUSEEVENT_HACK
329 m_lLastMouseX =
330 m_lLastMouseY = -1;
331 m_nLastMouseEvent = -1;
332 #endif // wxUSE_MOUSEEVENT_HACK
333 } // wxWindowOS2::Init
334
335 //
336 // Destructor
337 //
338 wxWindowOS2::~wxWindowOS2()
339 {
340 m_isBeingDeleted = true;
341
342 for (wxWindow* pWin = GetParent(); pWin; pWin = pWin->GetParent())
343 {
344 wxTopLevelWindow* pFrame = wxDynamicCast(pWin, wxTopLevelWindow);
345
346 if (pFrame)
347 {
348 if (pFrame->GetLastFocus() == this)
349 pFrame->SetLastFocus(NULL);
350 }
351 }
352
353 DestroyChildren();
354
355 if (m_hWnd)
356 {
357 if(!::WinDestroyWindow(GetHWND()))
358 wxLogLastError(wxT("DestroyWindow"));
359 //
360 // remove hWnd <-> wxWindow association
361 //
362 wxRemoveHandleAssociation(this);
363 }
364 delete m_pChildrenDisabled;
365 } // end of wxWindowOS2::~wxWindowOS2
366
367 // real construction (Init() must have been called before!)
368 bool wxWindowOS2::Create( wxWindow* pParent,
369 wxWindowID vId,
370 const wxPoint& rPos,
371 const wxSize& rSize,
372 long lStyle,
373 const wxString& rName )
374 {
375 HWND hParent = NULLHANDLE;
376 ULONG ulCreateFlags = 0;
377 WXDWORD dwExStyle = 0;
378
379 wxCHECK_MSG(pParent, false, wxT("can't create wxWindow without parent"));
380
381 #if wxUSE_STATBOX
382 //
383 // wxGTK doesn't allow to create controls with static box as the parent so
384 // this will result in a crash when the program is ported to wxGTK - warn
385 // about it
386 //
387 // the correct solution is to create the controls as siblings of the
388 // static box
389 //
390 wxASSERT_MSG( !wxDynamicCast(pParent, wxStaticBox),
391 _T("wxStaticBox can't be used as a window parent!") );
392 #endif // wxUSE_STATBOX
393
394 // Ensure groupbox backgrounds are painted
395 if (IsKindOf(CLASSINFO(wxPanel)))
396 lStyle &= ~wxCLIP_CHILDREN;
397
398 if ( !CreateBase( pParent
399 ,vId
400 ,rPos
401 ,rSize
402 ,lStyle
403 ,wxDefaultValidator
404 ,rName
405 ))
406 return false;
407
408 if (pParent)
409 {
410 pParent->AddChild(this);
411 hParent = GetWinHwnd(pParent);
412
413 if (pParent->IsKindOf(CLASSINFO(wxScrolledWindow)))
414 ulCreateFlags |= WS_CLIPSIBLINGS;
415 }
416
417 //
418 // Most wxSTYLES are really PM Class specific styles and will be
419 // set in those class create procs. PM's basic windows styles are
420 // very limited.
421 //
422 ulCreateFlags |= OS2GetCreateWindowFlags(&dwExStyle);
423
424
425 #ifdef __WXUNIVERSAL__
426 // no 3d effects, we draw them ourselves
427 WXDWORD exStyle = 0;
428 #endif // !wxUniversal
429 if (lStyle & wxPOPUP_WINDOW)
430 {
431 ulCreateFlags &= ~WS_VISIBLE;
432 m_isShown = false;
433 }
434 else
435 {
436 ulCreateFlags |= WS_VISIBLE;
437 }
438
439 //
440 // Generic OS/2 Windows have no Control Data but other classes
441 // that call OS2Create may have some.
442 //
443 return(OS2Create( (PSZ)wxCanvasClassName
444 ,rName.c_str()
445 ,ulCreateFlags
446 ,rPos
447 ,rSize
448 ,NULL // Control Data
449 ,dwExStyle
450 ,true // Child
451 ));
452 } // end of wxWindowOS2::Create
453
454 // ---------------------------------------------------------------------------
455 // basic operations
456 // ---------------------------------------------------------------------------
457
458 void wxWindowOS2::SetFocus()
459 {
460 HWND hWnd = GetHwnd();
461 wxCHECK_RET( hWnd, _T("can't set focus to invalid window") );
462
463 if (hWnd)
464 ::WinSetFocus(HWND_DESKTOP, hWnd);
465 } // end of wxWindowOS2::SetFocus
466
467 void wxWindowOS2::SetFocusFromKbd()
468 {
469 //
470 // Nothing else to do under OS/2
471 //
472 wxWindowBase::SetFocusFromKbd();
473 } // end of wxWindowOS2::SetFocus
474
475 wxWindow* wxWindowBase::DoFindFocus()
476 {
477 HWND hWnd = ::WinQueryFocus(HWND_DESKTOP);
478
479 if (hWnd)
480 {
481 return wxFindWinFromHandle((WXHWND)hWnd);
482 }
483 return NULL;
484 } // wxWindowBase::DoFindFocus
485
486 bool wxWindowOS2::Enable( bool bEnable )
487 {
488 if (!wxWindowBase::Enable(bEnable))
489 return false;
490
491 HWND hWnd = GetHwnd();
492
493 if ( hWnd )
494 ::WinEnableWindow(hWnd, (BOOL)bEnable);
495
496 //
497 // The logic below doesn't apply to the top level windows -- otherwise
498 // showing a modal dialog would result in total greying out (and ungreying
499 // out later) of everything which would be really ugly
500 //
501 if (IsTopLevel())
502 return true;
503
504 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
505
506 while (node)
507 {
508 wxWindow* pChild = node->GetData();
509
510 if (bEnable)
511 {
512 //
513 // Enable the child back unless it had been disabled before us
514 //
515 if (!m_pChildrenDisabled || !m_pChildrenDisabled->Find(pChild))
516 pChild->Enable();
517 }
518 else // we're being disabled
519 {
520 if (pChild->IsEnabled())
521 {
522 //
523 // Disable it as children shouldn't stay enabled while the
524 // parent is not
525 //
526 pChild->Disable();
527 }
528 else // child already disabled, remember it
529 {
530 //
531 // Have we created the list of disabled children already?
532 //
533 if (!m_pChildrenDisabled)
534 m_pChildrenDisabled = new wxWindowList;
535 m_pChildrenDisabled->Append(pChild);
536 }
537 }
538 node = node->GetNext();
539 }
540 if (bEnable && m_pChildrenDisabled)
541 {
542 //
543 // We don't need this list any more, don't keep unused memory
544 //
545 delete m_pChildrenDisabled;
546 m_pChildrenDisabled = NULL;
547 }
548 return true;
549 } // end of wxWindowOS2::Enable
550
551 bool wxWindowOS2::Show( bool bShow )
552 {
553 if (!wxWindowBase::Show(bShow))
554 return false;
555
556 HWND hWnd = GetHwnd();
557
558 ::WinShowWindow(hWnd, bShow);
559
560 if (bShow)
561 {
562 ::WinSetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_ACTIVATE | SWP_ZORDER);
563 }
564 return true;
565 } // end of wxWindowOS2::Show
566
567 void wxWindowOS2::Raise()
568 {
569 ::WinSetWindowPos(GetHwnd(), HWND_TOP, 0, 0, 0, 0, SWP_ZORDER | SWP_ACTIVATE);
570 } // end of wxWindowOS2::Raise
571
572 void wxWindowOS2::Lower()
573 {
574 ::WinSetWindowPos(GetHwnd(), HWND_BOTTOM, 0, 0, 0, 0, SWP_ZORDER | SWP_DEACTIVATE);
575 } // end of wxWindowOS2::Lower
576
577 void wxWindowOS2::SetTitle( const wxString& rTitle )
578 {
579 ::WinSetWindowText(GetHwnd(), (PSZ)rTitle.c_str());
580 } // end of wxWindowOS2::SetTitle
581
582 wxString wxWindowOS2::GetTitle() const
583 {
584 return wxGetWindowText(GetHWND());
585 } // end of wxWindowOS2::GetTitle
586
587 void wxWindowOS2::DoCaptureMouse()
588 {
589 HWND hWnd = GetHwnd();
590
591 if (hWnd && !m_bWinCaptured)
592 {
593 ::WinSetCapture(HWND_DESKTOP, hWnd);
594 m_bWinCaptured = true;
595 }
596 } // end of wxWindowOS2::GetTitle
597
598 void wxWindowOS2::DoReleaseMouse()
599 {
600 if (m_bWinCaptured)
601 {
602 ::WinSetCapture(HWND_DESKTOP, NULLHANDLE);
603 m_bWinCaptured = false;
604 }
605 } // end of wxWindowOS2::ReleaseMouse
606
607 /* static */ wxWindow* wxWindowBase::GetCapture()
608 {
609 HWND hwnd = ::WinQueryCapture(HWND_DESKTOP);
610 return hwnd ? wxFindWinFromHandle((WXHWND)hwnd) : (wxWindow *)NULL;
611 } // end of wxWindowBase::GetCapture
612
613 bool wxWindowOS2::SetFont( const wxFont& rFont )
614 {
615 if (!wxWindowBase::SetFont(rFont))
616 {
617 // nothing to do
618 return false;
619 }
620
621 HWND hWnd = GetHwnd();
622
623 wxOS2SetFont( hWnd, rFont );
624 return true;
625 } // end of wxWindowOS2::SetFont
626
627 // check if base implementation is OK
628 bool wxWindowOS2::SetCursor( const wxCursor& rCursor)
629 {
630 if ( !wxWindowBase::SetCursor(rCursor))
631 {
632 // no change
633 return false;
634 }
635
636 if ( m_cursor.Ok() ) {
637 HWND hWnd = GetHwnd();
638 POINTL vPoint;
639 RECTL vRect;
640
641 ::WinQueryPointerPos(HWND_DESKTOP, &vPoint);
642 ::WinQueryWindowRect(hWnd, &vRect);
643
644 if (::WinPtInRect(vHabmain, &vRect, &vPoint) && !wxIsBusy())
645 {
646 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)m_cursor.GetHCURSOR());
647 }
648 }
649 return true;
650 } // end of wxWindowOS2::SetCursor
651
652 void wxWindowOS2::WarpPointer(
653 int nXPos
654 , int nYPos
655 )
656 {
657 int nX = nXPos;
658 int nY = nYPos;
659 RECTL vRect;
660
661 ::WinQueryWindowRect(GetHwnd(), &vRect);
662 nX += vRect.xLeft;
663 nY += vRect.yBottom;
664
665 ::WinSetPointerPos(HWND_DESKTOP, (LONG)nX, (LONG)(nY));
666 } // end of wxWindowOS2::WarpPointer
667
668
669 // ---------------------------------------------------------------------------
670 // scrolling stuff
671 // ---------------------------------------------------------------------------
672
673 int wxWindowOS2::GetScrollPos(
674 int nOrient
675 ) const
676 {
677 if (nOrient == wxHORIZONTAL)
678 return((int)::WinSendMsg(m_hWndScrollBarHorz, SBM_QUERYPOS, (MPARAM)NULL, (MPARAM)NULL));
679 else
680 return((int)::WinSendMsg(m_hWndScrollBarVert, SBM_QUERYPOS, (MPARAM)NULL, (MPARAM)NULL));
681 } // end of wxWindowOS2::GetScrollPos
682
683 int wxWindowOS2::GetScrollRange(
684 int nOrient
685 ) const
686 {
687 MRESULT mr;
688
689 if (nOrient == wxHORIZONTAL)
690 mr = ::WinSendMsg(m_hWndScrollBarHorz, SBM_QUERYRANGE, (MPARAM)NULL, (MPARAM)NULL);
691 else
692 mr = ::WinSendMsg(m_hWndScrollBarVert, SBM_QUERYRANGE, (MPARAM)NULL, (MPARAM)NULL);
693 return((int)SHORT2FROMMR(mr));
694 } // end of wxWindowOS2::GetScrollRange
695
696 int wxWindowOS2::GetScrollThumb(
697 int nOrient
698 ) const
699 {
700 if (nOrient == wxHORIZONTAL )
701 return m_nXThumbSize;
702 else
703 return m_nYThumbSize;
704 } // end of wxWindowOS2::GetScrollThumb
705
706 void wxWindowOS2::SetScrollPos(
707 int nOrient
708 , int nPos
709 , bool WXUNUSED(bRefresh)
710 )
711 {
712 if (nOrient == wxHORIZONTAL )
713 ::WinSendMsg(m_hWndScrollBarHorz, SBM_SETPOS, (MPARAM)nPos, (MPARAM)NULL);
714 else
715 ::WinSendMsg(m_hWndScrollBarVert, SBM_SETPOS, (MPARAM)nPos, (MPARAM)NULL);
716 } // end of wxWindowOS2::SetScrollPos
717
718 void wxWindowOS2::SetScrollbar( int nOrient,
719 int nPos,
720 int nThumbVisible,
721 int nRange,
722 bool WXUNUSED(bRefresh) )
723 {
724 HWND hWnd = GetHwnd();
725 int nOldRange = nRange - nThumbVisible;
726 int nRange1 = nOldRange;
727 int nPageSize = nThumbVisible;
728
729 SBCDATA vInfo;
730 ULONG ulStyle = WS_VISIBLE | WS_SYNCPAINT;
731 SWP vSwp;
732 SWP vSwpOwner;
733 HWND hWndParent;
734 HWND hWndClient;
735 wxWindow* pParent = GetParent();
736
737 if (pParent && pParent->IsKindOf(CLASSINFO(wxFrame)))
738 {
739 wxFrame* pFrame;
740
741 pFrame = wxDynamicCast(pParent, wxFrame);
742 hWndParent = pFrame->GetFrame();
743 hWndClient = GetHwndOf(pParent);
744 }
745 else
746 {
747 if (pParent)
748 hWndParent = GetHwndOf(pParent);
749 else
750 hWndParent = GetHwnd();
751 hWndClient = hWndParent;
752 }
753 ::WinQueryWindowPos(hWndClient, &vSwp);
754 ::WinQueryWindowPos(hWnd, &vSwpOwner);
755
756 if (nPageSize > 1 && nRange > 0)
757 {
758 nRange1 += (nPageSize - 1);
759 }
760
761 vInfo.cb = sizeof(SBCDATA);
762 vInfo.posFirst = 0;
763 vInfo.posLast = (SHORT)nRange1;
764 vInfo.posThumb = (SHORT)nPos;
765
766 if (nOrient == wxHORIZONTAL )
767 {
768 ulStyle |= SBS_HORZ;
769 if (m_hWndScrollBarHorz == 0L)
770 {
771 //
772 // Since the scrollbars are usually created before the owner is
773 // sized either via an OnSize event directly or via sizers or
774 // layout constraints, we will initially just use the coords of
775 // the parent window (this is usually a frame client window). But
776 // the bars themselves, are children of the parent frame (i.e
777 // siblings of the frame client. The owner, however is the actual
778 // window being scrolled (or at least the one responsible for
779 // handling the scroll events). The owner will be resized later,
780 // as it is usually a child of a top level window, and when that
781 // is done its scrollbars will be resized and repositioned as well.
782 //
783 m_hWndScrollBarHorz = ::WinCreateWindow( hWndParent
784 ,WC_SCROLLBAR
785 ,(PSZ)NULL
786 ,ulStyle
787 ,vSwp.x
788 ,vSwp.y
789 ,vSwp.cx - 20
790 ,20
791 ,hWnd
792 ,HWND_TOP
793 ,60000
794 ,&vInfo
795 ,NULL
796 );
797 }
798 else
799 {
800 //
801 // The owner (the scrolled window) is a child of the Frame's
802 // client window, usually. The scrollbars are children of the
803 // frame, itself, and thus are positioned relative to the frame's
804 // origin, not the frame's client window origin.
805 // The starting x position is the same as the starting x position
806 // of the owner, but in terms of the parent frame.
807 // The starting y position is 20 pels below the origin of the
808 // owner in terms of the parent frame.
809 // The horz bar is the same width as the owner and 20 pels high.
810 //
811 if (nRange1 >= nThumbVisible)
812 {
813 ::WinSetWindowPos( m_hWndScrollBarHorz
814 ,HWND_TOP
815 ,vSwp.x + vSwpOwner.x
816 ,(vSwp.y + vSwpOwner.y) - 20
817 ,vSwpOwner.cx
818 ,20
819 ,SWP_MOVE | SWP_SIZE | SWP_SHOW | SWP_ACTIVATE | SWP_ZORDER
820 );
821 ::WinSendMsg( m_hWndScrollBarHorz
822 ,SBM_SETSCROLLBAR
823 ,(MPARAM)nPos
824 ,MPFROM2SHORT(0, (SHORT)nRange1)
825 );
826 ::WinSendMsg( m_hWndScrollBarHorz
827 ,SBM_SETTHUMBSIZE
828 ,MPFROM2SHORT( (SHORT)nThumbVisible
829 ,(SHORT)nRange1
830 )
831 ,(MPARAM)0
832 );
833 }
834 else
835 ::WinShowWindow(m_hWndScrollBarHorz, FALSE);
836 }
837 }
838 else
839 {
840 ulStyle |= SBS_VERT;
841 if (m_hWndScrollBarVert == 0L)
842 {
843 //
844 // Since the scrollbars are usually created before the owner is
845 // sized either via an OnSize event directly or via sizers or
846 // layout constraints, we will initially just use the coords of
847 // the parent window (this is usually a frame client window). But
848 // the bars themselves, are children of the parent frame (i.e
849 // siblings of the frame client. The owner, however is the actual
850 // window being scrolled (or at least the one responsible for
851 // handling the scroll events). The owner will be resized later,
852 // as it is usually a child of a top level window, and when that
853 // is done its scrollbars will be resized and repositioned as well.
854 //
855 m_hWndScrollBarVert = ::WinCreateWindow( hWndParent
856 ,WC_SCROLLBAR
857 ,(PSZ)NULL
858 ,ulStyle
859 ,vSwp.x + vSwp.cx - 20
860 ,vSwp.y + 20
861 ,20
862 ,vSwp.cy - 20
863 ,hWnd
864 ,HWND_TOP
865 ,60001
866 ,&vInfo
867 ,NULL
868 );
869 }
870 else
871 {
872 //
873 // The owner (the scrolled window) is a child of the Frame's
874 // client window, usually. The scrollbars are children of the
875 // frame, itself and thus are positioned relative to the frame's
876 // origin, not the frame's client window's origin.
877 // Thus, the x position will be frame client's x (usually a few
878 // pels inside the parent frame, plus the width of the owner.
879 // Since we may be using sizers or layout constraints for multiple
880 // child scrolled windows, the y position will be the frame client's
881 // y pos plus the scrolled windows y position, yielding the y
882 // position of the scrollbar relative to the parent frame (the vert
883 // scrollbar is on the right and starts at the bottom of the
884 // owner window).
885 // It is 20 pels wide and the same height as the owner.
886 //
887 if (nRange1 >= nThumbVisible)
888 {
889 ::WinSetWindowPos( m_hWndScrollBarVert
890 ,HWND_TOP
891 ,vSwp.x + vSwpOwner.x + vSwpOwner.cx
892 ,vSwp.y + vSwpOwner.y
893 ,20
894 ,vSwpOwner.cy
895 ,SWP_ACTIVATE | SWP_MOVE | SWP_SIZE | SWP_SHOW
896 );
897 ::WinSendMsg( m_hWndScrollBarVert
898 ,SBM_SETSCROLLBAR
899 ,(MPARAM)nPos
900 ,MPFROM2SHORT(0, (SHORT)nRange1)
901 );
902 ::WinSendMsg( m_hWndScrollBarVert
903 ,SBM_SETTHUMBSIZE
904 ,MPFROM2SHORT( (SHORT)nThumbVisible
905 ,(SHORT)nRange1
906 )
907 ,(MPARAM)0
908 );
909 }
910 else
911 ::WinShowWindow(m_hWndScrollBarVert, FALSE);
912 }
913 m_nYThumbSize = nThumbVisible;
914 }
915 } // end of wxWindowOS2::SetScrollbar
916
917
918 void wxWindowOS2::ScrollWindow( int nDx,
919 int nDy,
920 const wxRect* pRect )
921 {
922 RECTL vRect;
923
924 ::WinQueryWindowRect(GetHwnd(), &vRect);
925 int height = vRect.yTop;
926 if (pRect)
927 {
928 vRect.xLeft = pRect->x;
929 vRect.yTop = height - pRect->y;
930 vRect.xRight = pRect->x + pRect->width;
931 vRect.yBottom = vRect.yTop - pRect->height;
932 }
933 nDy *= -1; // flip the sign of Dy as OS/2 is opposite Windows.
934 ::WinScrollWindow( GetHwnd()
935 ,(LONG)nDx
936 ,(LONG)nDy
937 ,&vRect
938 ,&vRect
939 ,NULL
940 ,NULL
941 ,SW_SCROLLCHILDREN | SW_INVALIDATERGN
942 );
943 } // end of wxWindowOS2::ScrollWindow
944
945 // ---------------------------------------------------------------------------
946 // subclassing
947 // ---------------------------------------------------------------------------
948
949 void wxWindowOS2::SubclassWin(
950 WXHWND hWnd
951 )
952 {
953 HWND hwnd = (HWND)hWnd;
954
955 wxCHECK_RET(::WinIsWindow(vHabmain, hwnd), wxT("invalid HWND in SubclassWin") );
956 wxAssociateWinWithHandle( hWnd
957 ,(wxWindow*)this
958 );
959 if (!wxCheckWindowWndProc( hWnd
960 ,(WXFARPROC)wxWndProc
961 ))
962 {
963 m_fnOldWndProc = (WXFARPROC) ::WinSubclassWindow(hwnd, (PFNWP)wxWndProc);
964 }
965 else
966 {
967 m_fnOldWndProc = (WXFARPROC)NULL;
968 }
969 } // end of wxWindowOS2::SubclassWin
970
971 void wxWindowOS2::UnsubclassWin()
972 {
973 //
974 // Restore old Window proc
975 //
976 HWND hwnd = GetHWND();
977
978 if (m_hWnd)
979 {
980 wxCHECK_RET( ::WinIsWindow(vHabmain, hwnd), wxT("invalid HWND in UnsubclassWin") );
981
982 PFNWP fnProc = (PFNWP)::WinQueryWindowPtr(hwnd, QWP_PFNWP);
983
984 if ( (m_fnOldWndProc != 0) && (fnProc != (PFNWP) m_fnOldWndProc))
985 {
986 WinSubclassWindow(hwnd, (PFNWP)m_fnOldWndProc);
987 m_fnOldWndProc = 0;
988 }
989 }
990 } // end of wxWindowOS2::UnsubclassWin
991
992 bool wxCheckWindowWndProc(
993 WXHWND hWnd
994 , WXFARPROC fnWndProc
995 )
996 {
997 static char zBuffer[512];
998 CLASSINFO vCls;
999
1000 ::WinQueryClassName((HWND)hWnd, (LONG)512, (PCH)zBuffer);
1001 ::WinQueryClassInfo(wxGetInstance(), (PSZ)zBuffer, &vCls);
1002 return(fnWndProc == (WXFARPROC)vCls.pfnWindowProc);
1003 } // end of WinGuiBase_CheckWindowWndProc
1004
1005 void wxWindowOS2::SetWindowStyleFlag(
1006 long lFlags
1007 )
1008 {
1009 long lFlagsOld = GetWindowStyleFlag();
1010
1011 if (lFlags == lFlagsOld)
1012 return;
1013
1014 //
1015 // Update the internal variable
1016 //
1017 wxWindowBase::SetWindowStyleFlag(lFlags);
1018
1019 //
1020 // Now update the Windows style as well if needed - and if the window had
1021 // been already created
1022 //
1023 if (!GetHwnd())
1024 return;
1025
1026 WXDWORD dwExstyle;
1027 WXDWORD dwExstyleOld;
1028 long lStyle = OS2GetStyle( lFlags
1029 ,&dwExstyle
1030 );
1031 long lStyleOld = OS2GetStyle( lFlagsOld
1032 ,&dwExstyleOld
1033 );
1034
1035 if (lStyle != lStyleOld)
1036 {
1037 //
1038 // Some flags (e.g. WS_VISIBLE or WS_DISABLED) should not be changed by
1039 // this function so instead of simply setting the style to the new
1040 // value we clear the bits which were set in styleOld but are set in
1041 // the new one and set the ones which were not set before
1042 //
1043 long lStyleReal = ::WinQueryWindowULong(GetHwnd(), QWL_STYLE);
1044
1045 lStyleReal &= ~lStyleOld;
1046 lStyleReal |= lStyle;
1047
1048 ::WinSetWindowULong(GetHwnd(), QWL_STYLE, lStyleReal);
1049 }
1050 } // end of wxWindowOS2::SetWindowStyleFlag
1051
1052 WXDWORD wxWindowOS2::OS2GetStyle( long lFlags,
1053 WXDWORD* WXUNUSED(pdwExstyle) ) const
1054 {
1055 WXDWORD dwStyle = 0L;
1056
1057 if (lFlags & wxCLIP_CHILDREN )
1058 dwStyle |= WS_CLIPCHILDREN;
1059
1060 if (lFlags & wxCLIP_SIBLINGS )
1061 dwStyle |= WS_CLIPSIBLINGS;
1062
1063 return dwStyle;
1064 } // end of wxWindowOS2::OS2GetStyle
1065
1066 //
1067 // Make a Windows extended style from the given wxWidgets window style
1068 //
1069 WXDWORD wxWindowOS2::MakeExtendedStyle(
1070 long lStyle
1071 , bool bEliminateBorders
1072 )
1073 {
1074 //
1075 // Simply fill out with wxWindow extended styles. We'll conjure
1076 // something up in OS2Create and all window redrawing pieces later
1077 //
1078 WXDWORD dwStyle = 0;
1079
1080 if (lStyle & wxTRANSPARENT_WINDOW )
1081 dwStyle |= wxTRANSPARENT_WINDOW;
1082
1083 if (!bEliminateBorders)
1084 {
1085 if (lStyle & wxSUNKEN_BORDER)
1086 dwStyle |= wxSUNKEN_BORDER;
1087 if (lStyle & wxDOUBLE_BORDER)
1088 dwStyle |= wxDOUBLE_BORDER;
1089 if (lStyle & wxRAISED_BORDER )
1090 dwStyle |= wxRAISED_BORDER;
1091 if (lStyle & wxSTATIC_BORDER)
1092 dwStyle |= wxSTATIC_BORDER;
1093 }
1094 return dwStyle;
1095 } // end of wxWindowOS2::MakeExtendedStyle
1096
1097 //
1098 // Setup background and foreground colours correctly
1099 //
1100 void wxWindowOS2::SetupColours()
1101 {
1102 if ( GetParent() )
1103 SetBackgroundColour(GetParent()->GetBackgroundColour());
1104 } // end of wxWindowOS2::SetupColours
1105
1106 void wxWindowOS2::OnIdle(
1107 wxIdleEvent& WXUNUSED(rEvent)
1108 )
1109 {
1110 //
1111 // Check if we need to send a LEAVE event
1112 //
1113 if (m_bMouseInWindow)
1114 {
1115 POINTL vPoint;
1116
1117 ::WinQueryPointerPos(HWND_DESKTOP, &vPoint);
1118 if (::WinWindowFromPoint(HWND_DESKTOP, &vPoint, FALSE) != (HWND)GetHwnd())
1119 {
1120 //
1121 // Generate a LEAVE event
1122 //
1123 m_bMouseInWindow = false;
1124
1125 //
1126 // Unfortunately the mouse button and keyboard state may have changed
1127 // by the time the OnIdle function is called, so 'state' may be
1128 // meaningless.
1129 //
1130 int nState = 0;
1131
1132 if (IsShiftDown())
1133 nState |= KC_SHIFT;
1134 if (IsCtrlDown())
1135 nState |= KC_CTRL;
1136
1137 wxMouseEvent rEvent(wxEVT_LEAVE_WINDOW);
1138
1139 InitMouseEvent( rEvent
1140 ,vPoint.x
1141 ,vPoint.y
1142 ,nState
1143 );
1144 (void)GetEventHandler()->ProcessEvent(rEvent);
1145 }
1146 }
1147 if (wxUpdateUIEvent::CanUpdate(this))
1148 UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
1149 } // end of wxWindowOS2::OnIdle
1150
1151 //
1152 // Set this window to be the child of 'parent'.
1153 //
1154 bool wxWindowOS2::Reparent( wxWindow* pParent)
1155 {
1156 if (!wxWindowBase::Reparent(pParent))
1157 return false;
1158
1159 HWND hWndChild = GetHwnd();
1160 HWND hWndParent = GetParent() ? GetWinHwnd(GetParent()) : (HWND)0;
1161
1162 ::WinSetParent(hWndChild, hWndParent, TRUE);
1163 return true;
1164 } // end of wxWindowOS2::Reparent
1165
1166 void wxWindowOS2::Update()
1167 {
1168 ::WinUpdateWindow(GetHwnd());
1169 } // end of wxWindowOS2::Update
1170
1171 void wxWindowOS2::Freeze()
1172 {
1173 ::WinSendMsg(GetHwnd(), WM_VRNDISABLED, (MPARAM)0, (MPARAM)0);
1174 } // end of wxWindowOS2::Freeze
1175
1176 void wxWindowOS2::Thaw()
1177 {
1178 ::WinSendMsg(GetHwnd(), WM_VRNENABLED, (MPARAM)TRUE, (MPARAM)0);
1179
1180 //
1181 // We need to refresh everything or otherwise he invalidated area is not
1182 // repainted.
1183 //
1184 Refresh();
1185 } // end of wxWindowOS2::Thaw
1186
1187 void wxWindowOS2::Refresh( bool bEraseBack,
1188 const wxRect* pRect )
1189 {
1190 HWND hWnd = GetHwnd();
1191
1192 if (hWnd)
1193 {
1194 if (pRect)
1195 {
1196 RECTL vOs2Rect;
1197 int height;
1198
1199 ::WinQueryWindowRect(GetHwnd(), &vOs2Rect);
1200 height = vOs2Rect.yTop;
1201 vOs2Rect.xLeft = pRect->x;
1202 vOs2Rect.yTop = height - pRect->y;
1203 vOs2Rect.xRight = pRect->x + pRect->width;
1204 vOs2Rect.yBottom = vOs2Rect.yTop - pRect->height;
1205
1206 ::WinInvalidateRect(hWnd, &vOs2Rect, bEraseBack);
1207 }
1208 else
1209 ::WinInvalidateRect(hWnd, NULL, bEraseBack);
1210 if (m_hWndScrollBarHorz != NULLHANDLE)
1211 ::WinInvalidateRect(m_hWndScrollBarHorz, NULL, TRUE);
1212 if (m_hWndScrollBarVert != NULLHANDLE)
1213 ::WinInvalidateRect(m_hWndScrollBarVert, NULL, TRUE);
1214 }
1215 } // end of wxWindowOS2::Refresh
1216
1217 // ---------------------------------------------------------------------------
1218 // drag and drop
1219 // ---------------------------------------------------------------------------
1220
1221 #if wxUSE_DRAG_AND_DROP
1222 void wxWindowOS2::SetDropTarget(
1223 wxDropTarget* pDropTarget
1224 )
1225 {
1226 m_dropTarget = pDropTarget;
1227 } // end of wxWindowOS2::SetDropTarget
1228 #endif
1229
1230 //
1231 // old style file-manager drag&drop support: we retain the old-style
1232 // DragAcceptFiles in parallel with SetDropTarget.
1233 //
1234 void wxWindowOS2::DragAcceptFiles(
1235 bool bAccept
1236 )
1237 {
1238 HWND hWnd = GetHwnd();
1239
1240 if (hWnd && bAccept)
1241 ::DrgAcceptDroppedFiles(hWnd, NULL, NULL, DO_COPY, 0L);
1242 } // end of wxWindowOS2::DragAcceptFiles
1243
1244 // ----------------------------------------------------------------------------
1245 // tooltips
1246 // ----------------------------------------------------------------------------
1247
1248 #if wxUSE_TOOLTIPS
1249
1250 void wxWindowOS2::DoSetToolTip(
1251 wxToolTip* pTooltip
1252 )
1253 {
1254 wxWindowBase::DoSetToolTip(pTooltip);
1255
1256 if (m_tooltip)
1257 m_tooltip->SetWindow(this);
1258 } // end of wxWindowOS2::DoSetToolTip
1259
1260 #endif // wxUSE_TOOLTIPS
1261
1262 // ---------------------------------------------------------------------------
1263 // moving and resizing
1264 // ---------------------------------------------------------------------------
1265
1266 // Get total size
1267 void wxWindowOS2::DoGetSize(
1268 int* pWidth
1269 , int* pHeight
1270 ) const
1271 {
1272 HWND hWnd;
1273 RECTL vRect;
1274
1275 if (IsKindOf(CLASSINFO(wxFrame)))
1276 {
1277 wxFrame* pFrame = wxDynamicCast(this, wxFrame);
1278 hWnd = pFrame->GetFrame();
1279 }
1280 else
1281 hWnd = GetHwnd();
1282
1283 ::WinQueryWindowRect(hWnd, &vRect);
1284
1285 if (pWidth)
1286 *pWidth = vRect.xRight - vRect.xLeft;
1287 if (pHeight )
1288 // OS/2 PM is backwards from windows
1289 *pHeight = vRect.yTop - vRect.yBottom;
1290 } // end of wxWindowOS2::DoGetSize
1291
1292 void wxWindowOS2::DoGetPosition(
1293 int* pX
1294 , int* pY
1295 ) const
1296 {
1297 HWND hWnd = GetHwnd();
1298 SWP vSwp;
1299 POINTL vPoint;
1300 wxWindow* pParent = GetParent();
1301
1302 //
1303 // It would seem that WinQueryWindowRect would be the correlary to
1304 // the WIN32 WinGetRect, but unlike WinGetRect which returns the window
1305 // origin position in screen coordinates, WinQueryWindowRect returns it
1306 // relative to itself, i.e. (0,0). To get the same under PM we must
1307 // us WinQueryWindowPos. This call, unlike the WIN32 call, however,
1308 // returns a position relative to it's parent, so no parent adujstments
1309 // are needed under OS/2. Also, windows should be created using
1310 // wxWindow coordinates, i.e 0,0 is the TOP left so vSwp will already
1311 // reflect that.
1312 //
1313 ::WinQueryWindowPos(hWnd, &vSwp);
1314
1315 vPoint.x = vSwp.x;
1316 vPoint.y = vSwp.y;
1317
1318 //
1319 // We may be faking the client origin. So a window that's really at (0,
1320 // 30) may appear (to wxWin apps) to be at (0, 0).
1321 //
1322 if (pParent)
1323 {
1324 wxPoint vPt(pParent->GetClientAreaOrigin());
1325
1326 vPoint.x -= vPt.x;
1327 vPoint.y -= vPt.y;
1328 }
1329
1330 if (pX)
1331 *pX = vPoint.x;
1332 if (pY)
1333 *pY = vPoint.y;
1334 } // end of wxWindowOS2::DoGetPosition
1335
1336 void wxWindowOS2::DoScreenToClient(
1337 int* pX
1338 , int* pY
1339 ) const
1340 {
1341 HWND hWnd = GetHwnd();
1342 SWP vSwp;
1343
1344 ::WinQueryWindowPos(hWnd, &vSwp);
1345
1346 if (pX)
1347 *pX += vSwp.x;
1348 if (pY)
1349 *pY += vSwp.y;
1350 } // end of wxWindowOS2::DoScreenToClient
1351
1352 void wxWindowOS2::DoClientToScreen(
1353 int* pX
1354 , int* pY
1355 ) const
1356 {
1357 HWND hWnd = GetHwnd();
1358 SWP vSwp;
1359
1360 ::WinQueryWindowPos(hWnd, &vSwp);
1361
1362 if (pX)
1363 *pX += vSwp.x;
1364 if (pY)
1365 *pY += vSwp.y;
1366 } // end of wxWindowOS2::DoClientToScreen
1367
1368 //
1369 // Get size *available for subwindows* i.e. excluding menu bar etc.
1370 // Must be a frame type window
1371 //
1372 void wxWindowOS2::DoGetClientSize(
1373 int* pWidth
1374 , int* pHeight
1375 ) const
1376 {
1377 HWND hWnd = GetHwnd();
1378 RECTL vRect;
1379
1380 ::WinQueryWindowRect(hWnd, &vRect);
1381 if (IsKindOf(CLASSINFO(wxDialog)))
1382 {
1383 RECTL vTitle;
1384 HWND hWndTitle;
1385 //
1386 // For a Dialog we have to explicitly request the client portion.
1387 // For a Frame the hWnd IS the client window
1388 //
1389 hWndTitle = ::WinWindowFromID(hWnd, FID_TITLEBAR);
1390 if (::WinQueryWindowRect(hWndTitle, &vTitle))
1391 {
1392 if (vTitle.yTop - vTitle.yBottom == 0)
1393 {
1394 //
1395 // Dialog has not been created yet, use a default
1396 //
1397 vTitle.yTop = 20;
1398 }
1399 vRect.yTop -= (vTitle.yTop - vTitle.yBottom);
1400 }
1401
1402 ULONG uStyle = ::WinQueryWindowULong(hWnd, QWL_STYLE);
1403
1404 //
1405 // Deal with borders
1406 //
1407 if (uStyle & FCF_DLGBORDER)
1408 {
1409 vRect.xLeft += 4;
1410 vRect.xRight -= 4;
1411 vRect.yTop -= 4;
1412 vRect.yBottom += 4;
1413 }
1414 else if (uStyle & FCF_SIZEBORDER)
1415 {
1416 vRect.xLeft += 4;
1417 vRect.xRight -= 4;
1418 vRect.yTop -= 4;
1419 vRect.yBottom += 4;
1420 }
1421 else if (uStyle & FCF_BORDER)
1422 {
1423 vRect.xLeft += 2;
1424 vRect.xRight -= 2;
1425 vRect.yTop -= 2;
1426 vRect.yBottom += 2;
1427 }
1428 else // make some kind of adjustment or top sizers ram into the titlebar!
1429 {
1430 vRect.xLeft += 3;
1431 vRect.xRight -= 3;
1432 vRect.yTop -= 3;
1433 vRect.yBottom += 3;
1434 }
1435 }
1436 if (pWidth)
1437 *pWidth = vRect.xRight - vRect.xLeft;
1438 if (pHeight)
1439 *pHeight = vRect.yTop - vRect.yBottom;
1440 } // end of wxWindowOS2::DoGetClientSize
1441
1442 void wxWindowOS2::DoMoveWindow(
1443 int nX
1444 , int nY
1445 , int nWidth
1446 , int nHeight
1447 )
1448 {
1449 RECTL vRect;
1450 wxWindow* pParent = GetParent();
1451
1452 /* Due to OS/2's inverted coordinate system, changing the height
1453 of a window requires repositioning all it's children, e.g. if
1454 you want a child of height 100 to be at the top left corner of
1455 the parent you need to position the lower left corner of the
1456 child at (0, (height of parent - 100)), so, obviously, if the
1457 height of the parent changes, the child needs to be repositioned. */
1458 int nHeightDelta;
1459 GetSize(0, &nHeightDelta);
1460 nHeightDelta = nHeight - nHeightDelta;
1461
1462 if (pParent && !IsKindOf(CLASSINFO(wxDialog)))
1463 {
1464 int nOS2Height = GetOS2ParentHeight(pParent);
1465
1466 nY = nOS2Height - (nY + nHeight);
1467 }
1468 else
1469 {
1470 RECTL vRect;
1471
1472 ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
1473 nY = vRect.yTop - (nY + nHeight);
1474 }
1475
1476 //
1477 // In the case of a frame whose client is sized, the client cannot be
1478 // large than its parent frame minus its borders! This usually happens
1479 // when using an autosizer to size a frame to precisely hold client
1480 // controls as in the notebook sample.
1481 //
1482 // In this case, we may need to resize both a frame and its client so we
1483 // need a quick calc of the frame border size, then if the frame
1484 // (less its borders) is smaller than the client, size the frame to
1485 // encompass the client with the appropriate border size.
1486 //
1487 if (IsKindOf(CLASSINFO(wxFrame)))
1488 {
1489 RECTL vFRect;
1490 HWND hWndFrame;
1491 int nWidthFrameDelta = 0;
1492 int nHeightFrameDelta = 0;
1493 int nHeightFrame = 0;
1494 int nWidthFrame = 0;
1495 wxFrame* pFrame;
1496
1497 pFrame = wxDynamicCast(this, wxFrame);
1498 hWndFrame = pFrame->GetFrame();
1499 ::WinQueryWindowRect(hWndFrame, &vRect);
1500 ::WinMapWindowPoints(hWndFrame, HWND_DESKTOP, (PPOINTL)&vRect, 2);
1501 vFRect = vRect;
1502 ::WinCalcFrameRect(hWndFrame, &vRect, TRUE);
1503 nWidthFrameDelta = ((vRect.xLeft - vFRect.xLeft) + (vFRect.xRight - vRect.xRight));
1504 nHeightFrameDelta = ((vRect.yBottom - vFRect.yBottom) + (vFRect.yTop - vRect.yTop));
1505 nWidthFrame = vFRect.xRight - vFRect.xLeft;
1506 nHeightFrame = vFRect.yTop - vFRect.yBottom;
1507
1508 if (nWidth == vFRect.xRight - vFRect.xLeft &&
1509 nHeight == vFRect.yTop - vFRect.yBottom)
1510 {
1511 //
1512 // In this case the caller is not aware of OS/2's need to size both
1513 // the frame and it's client and is really only moving the window,
1514 // not resizeing it. So move the frame, and back off the sizes
1515 // for a proper client fit.
1516 //
1517 ::WinSetWindowPos( hWndFrame
1518 ,HWND_TOP
1519 ,(LONG)nX - (vRect.xLeft - vFRect.xLeft)
1520 ,(LONG)nY - (vRect.yBottom - vFRect.yBottom)
1521 ,(LONG)0
1522 ,(LONG)0
1523 ,SWP_MOVE
1524 );
1525 nX += (vRect.xLeft - vFRect.xLeft);
1526 nY += (vRect.yBottom - vFRect.yBottom);
1527 nWidth -= nWidthFrameDelta;
1528 nHeight -= nHeightFrameDelta;
1529 }
1530 else
1531 {
1532 if (nWidth > nWidthFrame - nHeightFrameDelta ||
1533 nHeight > nHeightFrame - nHeightFrameDelta)
1534 {
1535 ::WinSetWindowPos( hWndFrame
1536 ,HWND_TOP
1537 ,(LONG)nX - (vRect.xLeft - vFRect.xLeft)
1538 ,(LONG)nY - (vRect.yBottom - vFRect.yBottom)
1539 ,(LONG)nWidth + nWidthFrameDelta
1540 ,(LONG)nHeight + nHeightFrameDelta
1541 ,SWP_MOVE | SWP_SIZE
1542 );
1543 }
1544 }
1545 }
1546
1547 ::WinSetWindowPos( GetHwnd()
1548 ,HWND_TOP
1549 ,(LONG)nX
1550 ,(LONG)nY
1551 ,(LONG)nWidth
1552 ,(LONG)nHeight
1553 ,SWP_SIZE | SWP_MOVE
1554 );
1555 if (m_vWinSwp.cx == 0 && m_vWinSwp.cy == 0 && m_vWinSwp.fl == 0)
1556 //
1557 // Uninitialized
1558 //
1559 ::WinQueryWindowPos(GetHwnd(), &m_vWinSwp);
1560 else
1561 {
1562 int nYDiff = m_vWinSwp.cy - nHeight;
1563
1564 //
1565 // Handle resizing of scrolled windows. The target or window to
1566 // be scrolled is the owner (gets the scroll notificaitons). The
1567 // parent is usually the parent frame of the scrolled panel window.
1568 // In order to show the scrollbars the target window will be shrunk
1569 // by the size of the scroll bar widths (20) and moved in the X and Y
1570 // directon. That value will be computed as part of the diff for
1571 // moving the children. Everytime the window is sized the
1572 // toplevel OnSize is going to resize the panel to fit the client
1573 // or the whole sizer and will need to me resized. This will send
1574 // a WM_SIZE out which will be intercepted by the ScrollHelper
1575 // which will cause the scrollbars to be displayed via the SetScrollbar
1576 // call in CWindow.
1577 //
1578 if (IsKindOf(CLASSINFO(wxScrolledWindow)))
1579 {
1580 int nAdjustWidth = 0;
1581 int nAdjustHeight = 0;
1582 SWP vSwpScroll;
1583
1584 if (GetScrollBarHorz() == NULLHANDLE ||
1585 !WinIsWindowShowing(GetScrollBarHorz()))
1586 nAdjustHeight = 0L;
1587 else
1588 nAdjustHeight = 20L;
1589 if (GetScrollBarVert() == NULLHANDLE ||
1590 !WinIsWindowShowing(GetScrollBarVert()))
1591 nAdjustWidth = 0L;
1592 else
1593 nAdjustWidth = 20L;
1594 ::WinQueryWindowPos(GetHWND(), &vSwpScroll);
1595 ::WinSetWindowPos( GetHWND()
1596 ,HWND_TOP
1597 ,vSwpScroll.x
1598 ,vSwpScroll.y + nAdjustHeight
1599 ,vSwpScroll.cx - nAdjustWidth
1600 ,vSwpScroll.cy - nAdjustHeight
1601 ,SWP_MOVE | SWP_SIZE
1602 );
1603 nYDiff -= nAdjustHeight;
1604 }
1605 MoveChildren(nYDiff);
1606 ::WinQueryWindowPos(GetHwnd(), &m_vWinSwp);
1607 }
1608 #if 0
1609 // FIXME: By my logic, the next line should be needed as it moves child
1610 // windows when resizing the parent (see comment at beginning of
1611 // function). However, this seems to cause lots of problems. At
1612 // least, e.g. the grid sample almost works with this line
1613 // commented out but crashes badly with it.
1614 MoveChildren(nHeightDelta);
1615 #endif
1616 } // end of wxWindowOS2::DoMoveWindow
1617
1618 //
1619 // Set the size of the window: if the dimensions are positive, just use them,
1620 // but if any of them is equal to -1, it means that we must find the value for
1621 // it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in
1622 // which case -1 is a valid value for x and y)
1623 //
1624 // If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate
1625 // the width/height to best suit our contents, otherwise we reuse the current
1626 // width/height
1627 //
1628 void wxWindowOS2::DoSetSize( int nX,
1629 int nY,
1630 int nWidth,
1631 int nHeight,
1632 int nSizeFlags )
1633 {
1634 //
1635 // Get the current size and position...
1636 //
1637 int nCurrentX;
1638 int nCurrentY;
1639 int nCurrentWidth;
1640 int nCurrentHeight;
1641 wxSize vSize = wxDefaultSize;
1642
1643 GetPosition(&nCurrentX, &nCurrentY);
1644 GetSize(&nCurrentWidth, &nCurrentHeight);
1645
1646 //
1647 // ... and don't do anything (avoiding flicker) if it's already ok
1648 //
1649 //
1650 // Must convert Y coords to test for equality under OS/2
1651 //
1652 int nY2 = nY;
1653
1654 if (nX == nCurrentX && nY2 == nCurrentY &&
1655 nWidth == nCurrentWidth && nHeight == nCurrentHeight)
1656 {
1657 return;
1658 }
1659
1660 if (nX == wxDefaultCoord && !(nSizeFlags & wxSIZE_ALLOW_MINUS_ONE))
1661 nX = nCurrentX;
1662 if (nY == wxDefaultCoord && !(nSizeFlags & wxSIZE_ALLOW_MINUS_ONE))
1663 nY = nCurrentY;
1664
1665 AdjustForParentClientOrigin(nX, nY, nSizeFlags);
1666
1667 if (nWidth == wxDefaultCoord)
1668 {
1669 if (nSizeFlags & wxSIZE_AUTO_WIDTH)
1670 {
1671 vSize = DoGetBestSize();
1672 nWidth = vSize.x;
1673 }
1674 else
1675 {
1676 //
1677 // Just take the current one
1678 //
1679 nWidth = nCurrentWidth;
1680 }
1681 }
1682
1683 if (nHeight == wxDefaultCoord)
1684 {
1685 if (nSizeFlags & wxSIZE_AUTO_HEIGHT)
1686 {
1687 if (vSize.x == wxDefaultCoord)
1688 {
1689 vSize = DoGetBestSize();
1690 }
1691 nHeight = vSize.y;
1692 }
1693 else
1694 {
1695 // just take the current one
1696 nHeight = nCurrentHeight;
1697 }
1698 }
1699
1700 DoMoveWindow( nX, nY, nWidth, nHeight );
1701 } // end of wxWindowOS2::DoSetSize
1702
1703 void wxWindowOS2::DoSetClientSize( int nWidth,
1704 int nHeight )
1705 {
1706 POINTL vPoint;
1707 int nActualWidth;
1708 int nActualHeight;
1709 wxWindow* pParent = (wxWindow*)GetParent();
1710 HWND hParentWnd = (HWND)0;
1711
1712 if (pParent)
1713 hParentWnd = (HWND)pParent->GetHWND();
1714
1715 if (IsKindOf(CLASSINFO(wxFrame)))
1716 {
1717 wxFrame* pFrame = wxDynamicCast(this, wxFrame);
1718 HWND hFrame = pFrame->GetFrame();
1719 RECTL vRect;
1720 RECTL vRect2;
1721 RECTL vRect3;
1722
1723 ::WinQueryWindowRect(GetHwnd(), &vRect2);
1724 ::WinQueryWindowRect(hFrame, &vRect);
1725 ::WinQueryWindowRect(hParentWnd, &vRect3);
1726 nActualWidth = vRect2.xRight - vRect2.xLeft - vRect.xRight + nWidth;
1727 nActualHeight = vRect2.yTop - vRect2.yBottom - vRect.yTop + nHeight;
1728
1729 vPoint.x = vRect2.xLeft;
1730 vPoint.y = vRect2.yBottom;
1731 if (pParent)
1732 {
1733 vPoint.x -= vRect3.xLeft;
1734 vPoint.y -= vRect3.yBottom;
1735 }
1736 }
1737 else
1738 {
1739 int nX;
1740 int nY;
1741
1742 GetPosition(&nX, &nY);
1743 nActualWidth = nWidth;
1744 nActualHeight = nHeight;
1745
1746 vPoint.x = nX;
1747 vPoint.y = nY;
1748 }
1749 DoMoveWindow( vPoint.x, vPoint.y, nActualWidth, nActualHeight );
1750
1751 wxSize size( nWidth, nHeight );
1752 wxSizeEvent vEvent( size, m_windowId );
1753 vEvent.SetEventObject(this);
1754 GetEventHandler()->ProcessEvent(vEvent);
1755 } // end of wxWindowOS2::DoSetClientSize
1756
1757 // ---------------------------------------------------------------------------
1758 // text metrics
1759 // ---------------------------------------------------------------------------
1760
1761 int wxWindowOS2::GetCharHeight() const
1762 {
1763 HPS hPs;
1764 FONTMETRICS vFontMetrics;
1765
1766 hPs = ::WinGetPS(GetHwnd());
1767
1768 if(!GpiQueryFontMetrics(hPs, sizeof(FONTMETRICS), &vFontMetrics))
1769 {
1770 ::WinReleasePS(hPs);
1771 return (0);
1772 }
1773 ::WinReleasePS(hPs);
1774 return(vFontMetrics.lMaxAscender + vFontMetrics.lMaxDescender);
1775 } // end of wxWindowOS2::GetCharHeight
1776
1777 int wxWindowOS2::GetCharWidth() const
1778 {
1779 HPS hPs;
1780 FONTMETRICS vFontMetrics;
1781
1782 hPs = ::WinGetPS(GetHwnd());
1783
1784 if(!GpiQueryFontMetrics(hPs, sizeof(FONTMETRICS), &vFontMetrics))
1785 {
1786 ::WinReleasePS(hPs);
1787 return (0);
1788 }
1789 ::WinReleasePS(hPs);
1790 return(vFontMetrics.lAveCharWidth);
1791 } // end of wxWindowOS2::GetCharWidth
1792
1793 void wxWindowOS2::GetTextExtent( const wxString& rString,
1794 int* pX,
1795 int* pY,
1796 int* pDescent,
1797 int* pExternalLeading,
1798 const wxFont* WXUNUSED(pTheFont) ) const
1799 {
1800 POINTL avPoint[TXTBOX_COUNT];
1801 POINTL vPtMin;
1802 POINTL vPtMax;
1803 int i;
1804 int l;
1805 FONTMETRICS vFM; // metrics structure
1806 BOOL bRc = FALSE;
1807 char* pStr;
1808 HPS hPS;
1809
1810 hPS = ::WinGetPS(GetHwnd());
1811
1812 l = rString.Length();
1813 if (l > 0L)
1814 {
1815 pStr = (PCH)rString.c_str();
1816
1817 //
1818 // In world coordinates.
1819 //
1820 bRc = ::GpiQueryTextBox( hPS
1821 ,l
1822 ,pStr
1823 ,TXTBOX_COUNT // return maximum information
1824 ,avPoint // array of coordinates points
1825 );
1826 if (bRc)
1827 {
1828 vPtMin.x = avPoint[0].x;
1829 vPtMax.x = avPoint[0].x;
1830 vPtMin.y = avPoint[0].y;
1831 vPtMax.y = avPoint[0].y;
1832 for (i = 1; i < 4; i++)
1833 {
1834 if(vPtMin.x > avPoint[i].x) vPtMin.x = avPoint[i].x;
1835 if(vPtMin.y > avPoint[i].y) vPtMin.y = avPoint[i].y;
1836 if(vPtMax.x < avPoint[i].x) vPtMax.x = avPoint[i].x;
1837 if(vPtMax.y < avPoint[i].y) vPtMax.y = avPoint[i].y;
1838 }
1839 bRc = ::GpiQueryFontMetrics( hPS
1840 ,sizeof(FONTMETRICS)
1841 ,&vFM
1842 );
1843 if (!bRc)
1844 {
1845 vPtMin.x = 0;
1846 vPtMin.y = 0;
1847 vPtMax.x = 0;
1848 vPtMax.y = 0;
1849 }
1850 }
1851 else
1852 {
1853 vPtMin.x = 0;
1854 vPtMin.y = 0;
1855 vPtMax.x = 0;
1856 vPtMax.y = 0;
1857 }
1858 }
1859 else
1860 {
1861 vPtMin.x = 0;
1862 vPtMin.y = 0;
1863 vPtMax.x = 0;
1864 vPtMax.y = 0;
1865 }
1866 if (pX)
1867 *pX = (vPtMax.x - vPtMin.x + 1);
1868 if (pY)
1869 *pY = (vPtMax.y - vPtMin.y + 1);
1870 if (pDescent)
1871 {
1872 if (bRc)
1873 *pDescent = vFM.lMaxDescender;
1874 else
1875 *pDescent = 0;
1876 }
1877 if (pExternalLeading)
1878 {
1879 if (bRc)
1880 *pExternalLeading = vFM.lExternalLeading;
1881 else
1882 *pExternalLeading = 0;
1883 }
1884 ::WinReleasePS(hPS);
1885 } // end of wxWindow::GetTextExtent
1886
1887 bool wxWindowOS2::IsMouseInWindow() const
1888 {
1889 //
1890 // Get the mouse position
1891 POINTL vPt;
1892
1893 ::WinQueryPointerPos(HWND_DESKTOP, &vPt);
1894
1895 //
1896 // Find the window which currently has the cursor and go up the window
1897 // chain until we find this window - or exhaust it
1898 //
1899 HWND hWnd = ::WinWindowFromPoint(HWND_DESKTOP, &vPt, TRUE);
1900
1901 while (hWnd && (hWnd != GetHwnd()))
1902 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
1903
1904 return hWnd != NULL;
1905 } // end of wxWindowOS2::IsMouseInWindow
1906
1907
1908 // ---------------------------------------------------------------------------
1909 // popup menu
1910 // ---------------------------------------------------------------------------
1911 //
1912 #if wxUSE_MENUS_NATIVE
1913 bool wxWindowOS2::DoPopupMenu( wxMenu* pMenu,
1914 int nX,
1915 int nY )
1916 {
1917 HWND hWndOwner = GetHwnd();
1918 HWND hWndParent = GetHwnd();
1919 HWND hMenu = GetHmenuOf(pMenu);
1920 bool bIsWaiting = true;
1921 int nHeight;
1922
1923 // Protect against recursion
1924 if (wxCurrentPopupMenu)
1925 return false;
1926
1927 pMenu->SetInvokingWindow(this);
1928 pMenu->UpdateUI();
1929
1930 if ( nX == -1 && nY == -1 )
1931 {
1932 wxPoint mouse = wxGetMousePosition();
1933 nX = mouse.x; nY = mouse.y;
1934 }
1935 else
1936 {
1937 DoClientToScreen( &nX
1938 ,&nY
1939 );
1940 DoGetSize(0,&nHeight);
1941 nY = nHeight - nY;
1942 }
1943 wxCurrentPopupMenu = pMenu;
1944
1945 ::WinPopupMenu( hWndParent
1946 ,hWndOwner
1947 ,hMenu
1948 ,nX
1949 ,nY
1950 ,0L
1951 ,PU_HCONSTRAIN | PU_VCONSTRAIN | PU_MOUSEBUTTON1 | PU_KEYBOARD
1952 );
1953
1954 while(bIsWaiting)
1955 {
1956 QMSG vMsg;
1957
1958 ::WinGetMsg(vHabmain,&vMsg, (HWND)0, 0, 0);
1959 if (vMsg.msg == WM_COMMAND)
1960 bIsWaiting = false;
1961 ::WinDispatchMsg(vHabmain, (PQMSG)&vMsg);
1962 }
1963
1964 wxCurrentPopupMenu = NULL;
1965 pMenu->SetInvokingWindow(NULL);
1966 return true;
1967 } // end of wxWindowOS2::DoPopupMenu
1968 #endif // wxUSE_MENUS_NATIVE
1969
1970 // ===========================================================================
1971 // pre/post message processing
1972 // ===========================================================================
1973
1974 MRESULT wxWindowOS2::OS2DefWindowProc( WXUINT uMsg,
1975 WXWPARAM wParam,
1976 WXLPARAM lParam )
1977 {
1978 if (m_fnOldWndProc)
1979 return (MRESULT)m_fnOldWndProc(GetHWND(), uMsg, (MPARAM)wParam, (MPARAM)lParam);
1980 else
1981 return ::WinDefWindowProc(GetHWND(), uMsg, (MPARAM)wParam, (MPARAM)lParam);
1982 } // end of wxWindowOS2::OS2DefWindowProc
1983
1984 bool wxWindowOS2::OS2ProcessMessage( WXMSG* pMsg )
1985 {
1986 // wxUniversal implements tab traversal itself
1987 #ifndef __WXUNIVERSAL__
1988 QMSG* pQMsg = (QMSG*)pMsg;
1989
1990 if (m_hWnd != 0 && (GetWindowStyleFlag() & wxTAB_TRAVERSAL))
1991 {
1992 //
1993 // Intercept dialog navigation keys
1994 //
1995 bool bProcess = true;
1996 USHORT uKeyFlags = SHORT1FROMMP(pQMsg->mp1);
1997
1998 if (uKeyFlags & KC_KEYUP)
1999 bProcess = false;
2000
2001 if (uKeyFlags & KC_ALT)
2002 bProcess = false;
2003
2004 if (!(uKeyFlags & KC_VIRTUALKEY))
2005 bProcess = false;
2006
2007 if (bProcess)
2008 {
2009 bool bCtrlDown = IsCtrlDown();
2010 bool bShiftDown = IsShiftDown();
2011
2012 //
2013 // WM_QUERYDLGCODE: ask the control if it wants the key for itself,
2014 // don't process it if it's the case (except for Ctrl-Tab/Enter
2015 // combinations which are always processed)
2016 //
2017 ULONG ulDlgCode = 0;
2018
2019 if (!bCtrlDown)
2020 {
2021 ulDlgCode = (ULONG)::WinSendMsg(pQMsg->hwnd, WM_QUERYDLGCODE, pQMsg, 0);
2022 }
2023
2024 bool bForward = true;
2025 bool bWindowChange = false;
2026
2027 switch (SHORT2FROMMP(pQMsg->mp2))
2028 {
2029 //
2030 // Going to make certain assumptions about specific types of controls
2031 // here, so we may have to alter some things later if they prove invalid
2032 //
2033 case VK_TAB:
2034 //
2035 // Shift tabl will always be a nav-key but tabs may be wanted
2036 //
2037 if (!bShiftDown)
2038 {
2039 bProcess = false;
2040 }
2041 else
2042 {
2043 //
2044 // Entry Fields want tabs for themselve usually
2045 //
2046 switch (ulDlgCode)
2047 {
2048 case DLGC_ENTRYFIELD:
2049 case DLGC_MLE:
2050 bProcess = true;
2051 break;
2052
2053 default:
2054 bProcess = false;
2055 }
2056
2057 //
2058 // Ctrl-Tab cycles thru notebook pages
2059 //
2060 bWindowChange = bCtrlDown;
2061 bForward = !bShiftDown;
2062 }
2063 break;
2064
2065 case VK_UP:
2066 case VK_LEFT:
2067 if (bCtrlDown)
2068 bProcess = false;
2069 else
2070 bForward = false;
2071 break;
2072
2073 case VK_DOWN:
2074 case VK_RIGHT:
2075 if (bCtrlDown)
2076 bProcess = false;
2077 break;
2078
2079 case VK_ENTER:
2080 {
2081 if (bCtrlDown)
2082 {
2083 //
2084 // ctrl-enter is not processed
2085 //
2086 return false;
2087 }
2088 else if (ulDlgCode & DLGC_BUTTON)
2089 {
2090 //
2091 // buttons want process Enter themselevs
2092 //
2093 bProcess = false;
2094 }
2095 else
2096 {
2097 wxButton* pBtn = wxDynamicCast( GetDefaultItem()
2098 ,wxButton
2099 );
2100
2101 if (pBtn && pBtn->IsEnabled())
2102 {
2103 //
2104 // If we do have a default button, do press it
2105 //
2106 pBtn->OS2Command(BN_CLICKED, 0 /* unused */);
2107 return true;
2108 }
2109 else if (!IsTopLevel())
2110 {
2111 //
2112 // if not a top level window, let parent
2113 // handle it
2114 //
2115 return false;
2116 }
2117 // else: but if it does not it makes sense to make
2118 // it work like a TAB - and that's what we do.
2119 // Note that Ctrl-Enter always works this way.
2120 }
2121 }
2122 break;
2123
2124 default:
2125 bProcess = false;
2126 }
2127
2128 if (bProcess)
2129 {
2130 wxNavigationKeyEvent vEvent;
2131
2132 vEvent.SetDirection(bForward);
2133 vEvent.SetWindowChange(bWindowChange);
2134 vEvent.SetEventObject(this);
2135
2136 if (GetEventHandler()->ProcessEvent(vEvent))
2137 {
2138 wxButton* pBtn = wxDynamicCast(FindFocus(), wxButton);
2139
2140 if (pBtn)
2141 {
2142 //
2143 // The button which has focus should be default
2144 //
2145 pBtn->SetDefault();
2146 }
2147 return true;
2148 }
2149 }
2150 }
2151 //
2152 // Let Dialogs process
2153 //
2154 if (::WinSendMsg(pQMsg->hwnd, WM_QUERYDLGCODE, pQMsg, 0));
2155 return true;
2156 }
2157 #else
2158 pMsg = pMsg; // just shut up the compiler
2159 #endif // __WXUNIVERSAL__
2160
2161 return false;
2162 } // end of wxWindowOS2::OS2ProcessMessage
2163
2164 bool wxWindowOS2::OS2TranslateMessage( WXMSG* pMsg )
2165 {
2166 #if wxUSE_ACCEL && !defined(__WXUNIVERSAL__)
2167 return m_acceleratorTable.Translate(m_hWnd, pMsg);
2168 #else
2169 pMsg = pMsg;
2170 return false;
2171 #endif //wxUSE_ACCEL
2172 } // end of wxWindowOS2::OS2TranslateMessage
2173
2174 bool wxWindowOS2::OS2ShouldPreProcessMessage( WXMSG* WXUNUSED(pMsg) )
2175 {
2176 // preprocess all messages by default
2177 return true;
2178 } // end of wxWindowOS2::OS2ShouldPreProcessMessage
2179
2180 // ---------------------------------------------------------------------------
2181 // message params unpackers
2182 // ---------------------------------------------------------------------------
2183
2184 void wxWindowOS2::UnpackCommand(
2185 WXWPARAM wParam
2186 , WXLPARAM lParam
2187 , WORD* pId
2188 , WXHWND* phWnd
2189 , WORD* pCmd
2190 )
2191 {
2192 *pId = LOWORD(wParam);
2193 *phWnd = NULL; // or may be GetHWND() ?
2194 *pCmd = LOWORD(lParam);
2195 } // end of wxWindowOS2::UnpackCommand
2196
2197 void wxWindowOS2::UnpackActivate(
2198 WXWPARAM wParam
2199 , WXLPARAM lParam
2200 , WXWORD* pState
2201 , WXHWND* phWnd
2202 )
2203 {
2204 *pState = LOWORD(wParam);
2205 *phWnd = (WXHWND)lParam;
2206 } // end of wxWindowOS2::UnpackActivate
2207
2208 void wxWindowOS2::UnpackScroll(
2209 WXWPARAM wParam
2210 , WXLPARAM lParam
2211 , WXWORD* pCode
2212 , WXWORD* pPos
2213 , WXHWND* phWnd
2214 )
2215 {
2216 ULONG ulId;
2217 HWND hWnd;
2218
2219 ulId = (ULONG)LONGFROMMP(wParam);
2220 hWnd = ::WinWindowFromID(GetHwnd(), ulId);
2221 if (hWnd == m_hWndScrollBarHorz || hWnd == m_hWndScrollBarVert)
2222 *phWnd = NULLHANDLE;
2223 else
2224 *phWnd = hWnd;
2225
2226 *pPos = SHORT1FROMMP(lParam);
2227 *pCode = SHORT2FROMMP(lParam);
2228 } // end of wxWindowOS2::UnpackScroll
2229
2230 void wxWindowOS2::UnpackMenuSelect(
2231 WXWPARAM wParam
2232 , WXLPARAM lParam
2233 , WXWORD* pItem
2234 , WXWORD* pFlags
2235 , WXHMENU* phMenu
2236 )
2237 {
2238 *pItem = (WXWORD)LOWORD(wParam);
2239 *pFlags = HIWORD(wParam);
2240 *phMenu = (WXHMENU)lParam;
2241 } // end of wxWindowOS2::UnpackMenuSelect
2242
2243 // ---------------------------------------------------------------------------
2244 // Main wxWidgets window proc and the window proc for wxWindow
2245 // ---------------------------------------------------------------------------
2246
2247 //
2248 // Hook for new window just as it's being created, when the window isn't yet
2249 // associated with the handle
2250 //
2251 wxWindowOS2* wxWndHook = NULL;
2252
2253 //
2254 // Main window proc
2255 //
2256 MRESULT EXPENTRY wxWndProc(
2257 HWND hWnd
2258 , ULONG ulMsg
2259 , MPARAM wParam
2260 , MPARAM lParam
2261 )
2262 {
2263 wxWindowOS2* pWnd = wxFindWinFromHandle((WXHWND)hWnd);
2264
2265 //
2266 // When we get the first message for the HWND we just created, we associate
2267 // it with wxWindow stored in wxWndHook
2268 //
2269 if (!pWnd && wxWndHook)
2270 {
2271 wxAssociateWinWithHandle(hWnd, wxWndHook);
2272 pWnd = wxWndHook;
2273 wxWndHook = NULL;
2274 pWnd->SetHWND((WXHWND)hWnd);
2275 }
2276
2277 MRESULT rc = (MRESULT)0;
2278
2279
2280 //
2281 // Stop right here if we don't have a valid handle in our wxWindow object.
2282 //
2283 if (pWnd && !pWnd->GetHWND())
2284 {
2285 pWnd->SetHWND((WXHWND) hWnd);
2286 rc = pWnd->OS2DefWindowProc(ulMsg, wParam, lParam );
2287 pWnd->SetHWND(0);
2288 }
2289 else
2290 {
2291 if (pWnd)
2292 {
2293 rc = pWnd->OS2WindowProc(ulMsg, wParam, lParam);
2294 if ( (pWnd->GetScrollBarHorz() != NULLHANDLE ||
2295 pWnd->GetScrollBarVert() != NULLHANDLE) &&
2296 ulMsg == WM_PAINT)
2297 {
2298 if (pWnd->GetScrollBarHorz() != NULLHANDLE)
2299 ::WinInvalidateRect(pWnd->GetScrollBarHorz(), NULL, TRUE);
2300 if (pWnd->GetScrollBarVert() != NULLHANDLE)
2301 ::WinInvalidateRect(pWnd->GetScrollBarVert(), NULL, TRUE);
2302 }
2303 }
2304 else
2305 rc = ::WinDefWindowProc(hWnd, ulMsg, wParam, lParam);
2306 }
2307
2308 return rc;
2309 } // end of wxWndProc
2310
2311 //
2312 // We will add (or delete) messages we need to handle at this default
2313 // level as we go
2314 //
2315 MRESULT wxWindowOS2::OS2WindowProc( WXUINT uMsg,
2316 WXWPARAM wParam,
2317 WXLPARAM lParam )
2318 {
2319 //
2320 // Did we process the uMsg?
2321 //
2322 bool bProcessed = false;
2323 MRESULT mResult;
2324
2325 //
2326 // For most messages we should return 0 when we do process the message
2327 //
2328 mResult = (MRESULT)0;
2329
2330 switch (uMsg)
2331 {
2332 case WM_CREATE:
2333 {
2334 bool bMayCreate;
2335
2336 bProcessed = HandleCreate( (WXLPCREATESTRUCT)lParam
2337 ,&bMayCreate
2338 );
2339 if (bProcessed)
2340 {
2341 //
2342 // Return 0 to bAllow window creation
2343 //
2344 mResult = (MRESULT)(bMayCreate ? 0 : -1);
2345 }
2346 }
2347 break;
2348
2349 case WM_DESTROY:
2350 HandleDestroy();
2351 bProcessed = true;
2352 break;
2353
2354 case WM_MOVE:
2355 bProcessed = HandleMove( LOWORD(lParam)
2356 ,HIWORD(lParam)
2357 );
2358 break;
2359
2360 case WM_SIZE:
2361 bProcessed = HandleSize( LOWORD(lParam)
2362 ,HIWORD(lParam)
2363 ,(WXUINT)wParam
2364 );
2365 break;
2366
2367 case WM_WINDOWPOSCHANGED:
2368
2369 //
2370 // Dialogs under OS/2 do not get WM_SIZE events at all.
2371 // Instead they get this, which can function much like WM_SIZE
2372 // PSWP contains the new sizes and positioning, PSWP+1 the old
2373 // We use this because ADJUSTWINDOWPOS comes BEFORE the new
2374 // position is added and our auto layout does a WinQueryWindowRect
2375 // to get the CURRENT client size. That is the size used to position
2376 // child controls, so we need to already be sized
2377 // in order to get the child controls positoned properly.
2378 //
2379 if (IsKindOf(CLASSINFO(wxDialog)) || IsKindOf(CLASSINFO(wxFrame)))
2380 {
2381 PSWP pSwp = (PSWP)PVOIDFROMMP(wParam);
2382 PSWP pSwp2 = pSwp++;
2383
2384 if (!(pSwp->cx == pSwp2->cx &&
2385 pSwp->cy == pSwp2->cy))
2386 bProcessed = HandleSize( pSwp->cx
2387 ,pSwp->cy
2388 ,(WXUINT)lParam
2389 );
2390 if (IsKindOf(CLASSINFO(wxFrame)))
2391 {
2392 wxFrame* pFrame = wxDynamicCast(this, wxFrame);
2393
2394 if (pFrame)
2395 {
2396 if (pFrame->GetStatusBar())
2397 pFrame->PositionStatusBar();
2398 if (pFrame->GetToolBar())
2399 pFrame->PositionToolBar();
2400 }
2401 }
2402 }
2403 break;
2404
2405 case WM_ACTIVATE:
2406 {
2407 WXWORD wState;
2408 WXHWND hWnd;
2409
2410 UnpackActivate( wParam
2411 ,lParam
2412 ,&wState
2413 ,&hWnd
2414 );
2415
2416 bProcessed = HandleActivate( wState
2417 ,(WXHWND)hWnd
2418 );
2419 bProcessed = false;
2420 }
2421 break;
2422
2423 case WM_SETFOCUS:
2424 if (SHORT1FROMMP((MPARAM)lParam) == TRUE)
2425 bProcessed = HandleSetFocus((WXHWND)(HWND)wParam);
2426 else
2427 bProcessed = HandleKillFocus((WXHWND)(HWND)wParam);
2428 break;
2429
2430 case WM_PAINT:
2431 bProcessed = HandlePaint();
2432 break;
2433
2434 case WM_CLOSE:
2435 //
2436 // Don't let the DefWindowProc() destroy our window - we'll do it
2437 // ourselves in ~wxWindow
2438 //
2439 bProcessed = true;
2440 mResult = (MRESULT)TRUE;
2441 break;
2442
2443 case WM_SHOW:
2444 bProcessed = HandleShow(wParam != 0, (int)lParam);
2445 break;
2446
2447 //
2448 // Under OS2 PM Joysticks are treated just like mouse events
2449 // The "Motion" events will be prevelent in joysticks
2450 //
2451 case WM_MOUSEMOVE:
2452 case WM_BUTTON1DOWN:
2453 case WM_BUTTON1UP:
2454 case WM_BUTTON1DBLCLK:
2455 case WM_BUTTON1MOTIONEND:
2456 case WM_BUTTON1MOTIONSTART:
2457 case WM_BUTTON2DOWN:
2458 case WM_BUTTON2UP:
2459 case WM_BUTTON2DBLCLK:
2460 case WM_BUTTON2MOTIONEND:
2461 case WM_BUTTON2MOTIONSTART:
2462 case WM_BUTTON3DOWN:
2463 case WM_BUTTON3UP:
2464 case WM_BUTTON3DBLCLK:
2465 case WM_BUTTON3MOTIONEND:
2466 case WM_BUTTON3MOTIONSTART:
2467 {
2468 if (uMsg == WM_BUTTON1DOWN && AcceptsFocus())
2469 SetFocus();
2470
2471 short nX = LOWORD(wParam);
2472 short nY = HIWORD(wParam);
2473
2474 //
2475 // Redirect the event to a static control if necessary
2476 //
2477 if (this == GetCapture())
2478 {
2479 bProcessed = HandleMouseEvent( uMsg
2480 ,nX
2481 ,nY
2482 ,(WXUINT)SHORT2FROMMP(lParam)
2483 );
2484 }
2485 else
2486 {
2487 wxWindow* pWin = FindWindowForMouseEvent( this
2488 ,&nX
2489 ,&nY
2490 );
2491 if (!pWin->IsOfStandardClass())
2492 {
2493 if (uMsg == WM_BUTTON1DOWN && pWin->AcceptsFocus() )
2494 pWin->SetFocus();
2495 }
2496 bProcessed = pWin->HandleMouseEvent( uMsg
2497 ,nX
2498 ,nY
2499 ,(WXUINT)SHORT2FROMMP(lParam)
2500 );
2501 }
2502 }
2503 break;
2504
2505 case WM_SYSCOMMAND:
2506 bProcessed = HandleSysCommand(wParam, lParam);
2507 break;
2508
2509 case WM_COMMAND:
2510 {
2511 WORD id, cmd;
2512 WXHWND hwnd;
2513 UnpackCommand(wParam, lParam, &id, &hwnd, &cmd);
2514
2515 bProcessed = HandleCommand(id, cmd, hwnd);
2516 }
2517 break;
2518
2519 //
2520 // For these messages we must return TRUE if process the message
2521 //
2522 case WM_DRAWITEM:
2523 case WM_MEASUREITEM:
2524 {
2525 int nIdCtrl = (UINT)wParam;
2526
2527 if ( uMsg == WM_DRAWITEM )
2528 {
2529 bProcessed = OS2OnDrawItem(nIdCtrl,
2530 (WXDRAWITEMSTRUCT *)lParam);
2531 }
2532 else
2533 {
2534 return MRFROMLONG(OS2OnMeasureItem( nIdCtrl
2535 ,(WXMEASUREITEMSTRUCT *)lParam
2536 ));
2537 }
2538
2539 if ( bProcessed )
2540 mResult = (MRESULT)TRUE;
2541 }
2542 break;
2543
2544 case WM_QUERYDLGCODE:
2545 if (!IsOfStandardClass())
2546 {
2547 if ( m_lDlgCode )
2548 {
2549 mResult = (MRESULT)m_lDlgCode;
2550 bProcessed = true;
2551 }
2552 }
2553 //
2554 //else: get the dlg code from the DefWindowProc()
2555 //
2556 break;
2557
2558 //
2559 // In OS/2 PM all keyboard events are of the WM_CHAR type. Virtual key and key-up
2560 // and key-down events are obtained from the WM_CHAR params.
2561 //
2562 case WM_CHAR:
2563 {
2564 USHORT uKeyFlags = SHORT1FROMMP((MPARAM)wParam);
2565
2566 if (uKeyFlags & KC_KEYUP)
2567 {
2568 //TODO: check if the cast to WXWORD isn't causing trouble
2569 bProcessed = HandleKeyUp(wParam, lParam);
2570 break;
2571 }
2572 else // keydown event
2573 {
2574 m_bLastKeydownProcessed = false;
2575 //
2576 // If this has been processed by an event handler,
2577 // return 0 now (we've handled it). DON't RETURN
2578 // we still need to process further
2579 //
2580 m_bLastKeydownProcessed = HandleKeyDown(wParam, lParam);
2581 if (uKeyFlags & KC_VIRTUALKEY)
2582 {
2583 USHORT uVk = SHORT2FROMMP((MPARAM)lParam);
2584
2585 //
2586 // We consider these message "not interesting" to OnChar
2587 //
2588 switch(uVk)
2589 {
2590 case VK_SHIFT:
2591 case VK_CTRL:
2592 case VK_MENU:
2593 case VK_CAPSLOCK:
2594 case VK_NUMLOCK:
2595 case VK_SCRLLOCK:
2596 bProcessed = true;
2597 break;
2598
2599 // Avoid duplicate messages to OnChar for these ASCII keys: they
2600 // will be translated by TranslateMessage() and received in WM_CHAR
2601 case VK_ESC:
2602 case VK_ENTER:
2603 case VK_BACKSPACE:
2604 case VK_TAB:
2605 // But set processed to false, not true to still pass them to
2606 // the control's default window proc - otherwise built-in
2607 // keyboard handling won't work
2608 bProcessed = false;
2609 break;
2610
2611 default:
2612 bProcessed = HandleChar(wParam, lParam);
2613 }
2614 break;
2615 }
2616 else // WM_CHAR -- Always an ASCII character
2617 {
2618 if (m_bLastKeydownProcessed)
2619 {
2620 //
2621 // The key was handled in the EVT_KEY_DOWN and handling
2622 // a key in an EVT_KEY_DOWN handler is meant, by
2623 // design, to prevent EVT_CHARs from happening
2624 //
2625 m_bLastKeydownProcessed = false;
2626 bProcessed = true;
2627 }
2628 else // do generate a CHAR event
2629 {
2630 bProcessed = HandleChar(wParam, lParam, true);
2631 break;
2632 }
2633 }
2634 }
2635 }
2636
2637 case WM_HSCROLL:
2638 case WM_VSCROLL:
2639 {
2640 WXWORD wCode;
2641 WXWORD wPos;
2642 WXHWND hWnd;
2643 UnpackScroll( wParam
2644 ,lParam
2645 ,&wCode
2646 ,&wPos
2647 ,&hWnd
2648 );
2649
2650 bProcessed = OS2OnScroll( uMsg == WM_HSCROLL ? wxHORIZONTAL
2651 : wxVERTICAL
2652 ,wCode
2653 ,wPos
2654 ,hWnd
2655 );
2656 }
2657 break;
2658
2659 case WM_CONTROL:
2660 switch(SHORT2FROMMP(wParam))
2661 {
2662 case BN_PAINT:
2663 {
2664 HWND hWnd = ::WinWindowFromID((HWND)GetHwnd(), SHORT1FROMMP(wParam));
2665 wxWindowOS2* pWin = wxFindWinFromHandle(hWnd);
2666
2667 if (!pWin)
2668 {
2669 bProcessed = false;
2670 break;
2671 }
2672 if (pWin->IsKindOf(CLASSINFO(wxBitmapButton)))
2673 {
2674 wxBitmapButton* pBitmapButton = wxDynamicCast(pWin, wxBitmapButton);
2675
2676 pBitmapButton->OS2OnDraw((WXDRAWITEMSTRUCT *)lParam);
2677 }
2678 return 0;
2679 }
2680 // break;
2681
2682 case BKN_PAGESELECTEDPENDING:
2683 {
2684 PPAGESELECTNOTIFY pPage = (PPAGESELECTNOTIFY)lParam;
2685
2686 if ((pPage->ulPageIdNew != pPage->ulPageIdCur) &&
2687 (pPage->ulPageIdNew > 0L && pPage->ulPageIdCur > 0L))
2688 {
2689 wxWindowOS2* pWin = wxFindWinFromHandle(pPage->hwndBook);
2690 wxNotebookEvent vEvent( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
2691 ,(int)SHORT1FROMMP(wParam)
2692 ,(int)pPage->ulPageIdNew
2693 ,(int)pPage->ulPageIdCur
2694 );
2695 if (!pWin)
2696 {
2697 bProcessed = false;
2698 break;
2699 }
2700 if (pWin->IsKindOf(CLASSINFO(wxNotebook)))
2701 {
2702 wxNotebook* pNotebook = wxDynamicCast(pWin, wxNotebook);
2703
2704 vEvent.SetEventObject(pWin);
2705 pNotebook->OnSelChange(vEvent);
2706 bProcessed = true;
2707 }
2708 else
2709 bProcessed = false;
2710 }
2711 else
2712 bProcessed = false;
2713 }
2714 break;
2715
2716 case BN_CLICKED: // Dups as LN_SELECT and CBN_LBSELECT
2717 {
2718 HWND hWnd = ::WinWindowFromID((HWND)GetHwnd(), SHORT1FROMMP(wParam));
2719 wxWindowOS2* pWin = wxFindWinFromHandle(hWnd);
2720
2721 if (!pWin)
2722 {
2723 bProcessed = false;
2724 break;
2725 }
2726 //
2727 // Simulate a WM_COMMAND here, as wxWidgets expects all control
2728 // button clicks to generate WM_COMMAND msgs, not WM_CONTROL
2729 //
2730 if (pWin->IsKindOf(CLASSINFO(wxRadioBox)))
2731 {
2732 wxRadioBox* pRadioBox = wxDynamicCast(pWin, wxRadioBox);
2733
2734 pRadioBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
2735 ,(WXWORD)SHORT1FROMMP(wParam)
2736 );
2737 }
2738 if (pWin->IsKindOf(CLASSINFO(wxRadioButton)))
2739 {
2740 wxRadioButton* pRadioButton = wxDynamicCast(pWin, wxRadioButton);
2741
2742 pRadioButton->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
2743 ,(WXWORD)SHORT1FROMMP(wParam)
2744 );
2745 }
2746 if (pWin->IsKindOf(CLASSINFO(wxCheckBox)))
2747 {
2748 wxCheckBox* pCheckBox = wxDynamicCast(pWin, wxCheckBox);
2749
2750 pCheckBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
2751 ,(WXWORD)SHORT1FROMMP(wParam)
2752 );
2753 }
2754 if (pWin->IsKindOf(CLASSINFO(wxListBox)))
2755 {
2756 wxListBox* pListBox = wxDynamicCast(pWin, wxListBox);
2757
2758 pListBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
2759 ,(WXWORD)SHORT1FROMMP(wParam)
2760 );
2761 if (pListBox->GetWindowStyle() & wxLB_OWNERDRAW)
2762 Refresh();
2763 }
2764 if (pWin->IsKindOf(CLASSINFO(wxComboBox)))
2765 {
2766 wxComboBox* pComboBox = wxDynamicCast(pWin, wxComboBox);
2767
2768 pComboBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
2769 ,(WXWORD)SHORT1FROMMP(wParam)
2770 );
2771 }
2772 return 0;
2773 }
2774 // break;
2775
2776 case LN_ENTER: /* dups as CBN_EFCHANGE */
2777 {
2778 HWND hWnd = HWNDFROMMP(lParam);
2779 wxWindowOS2* pWin = wxFindWinFromHandle(hWnd);
2780
2781 if (!pWin)
2782 {
2783 bProcessed = false;
2784 break;
2785 }
2786 //
2787 // Simulate a WM_COMMAND here, as wxWidgets expects all control
2788 // button clicks to generate WM_COMMAND msgs, not WM_CONTROL
2789 //
2790 if (pWin->IsKindOf(CLASSINFO(wxListBox)))
2791 {
2792 wxListBox* pListBox = wxDynamicCast(pWin, wxListBox);
2793
2794 pListBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
2795 ,(WXWORD)SHORT1FROMMP(wParam)
2796 );
2797 if (pListBox->GetWindowStyle() & wxLB_OWNERDRAW)
2798 Refresh();
2799
2800 }
2801 if (pWin->IsKindOf(CLASSINFO(wxComboBox)))
2802 {
2803 wxComboBox* pComboBox = wxDynamicCast(pWin, wxComboBox);
2804
2805 pComboBox->OS2Command( (WXUINT)SHORT2FROMMP(wParam)
2806 ,(WXWORD)SHORT1FROMMP(wParam)
2807 );
2808 }
2809 return 0;
2810 }
2811 // break;
2812
2813 case SPBN_UPARROW:
2814 case SPBN_DOWNARROW:
2815 case SPBN_CHANGE:
2816 {
2817 char zVal[10];
2818 long lVal;
2819
2820 ::WinSendMsg( HWNDFROMMP(lParam)
2821 ,SPBM_QUERYVALUE
2822 ,&zVal[0]
2823 ,MPFROM2SHORT( (USHORT)10
2824 ,(USHORT)SPBQ_UPDATEIFVALID
2825 )
2826 );
2827 lVal = atol(zVal);
2828 bProcessed = OS2OnScroll( wxVERTICAL
2829 ,(WXWORD)SHORT2FROMMP(wParam)
2830 ,(WXWORD)lVal
2831 ,HWNDFROMMP(lParam)
2832 );
2833 }
2834 break;
2835
2836 case SLN_SLIDERTRACK:
2837 {
2838 HWND hWnd = ::WinWindowFromID(GetHWND(), SHORT1FROMMP(wParam));
2839 wxWindowOS2* pChild = wxFindWinFromHandle(hWnd);
2840
2841 if (!pChild)
2842 {
2843 bProcessed = false;
2844 break;
2845 }
2846 if (pChild->IsKindOf(CLASSINFO(wxSlider)))
2847 bProcessed = OS2OnScroll( wxVERTICAL
2848 ,(WXWORD)SHORT2FROMMP(wParam)
2849 ,(WXWORD)LONGFROMMP(lParam)
2850 ,hWnd
2851 );
2852 }
2853 break;
2854 }
2855 break;
2856
2857 #if defined(__VISAGECPP__) && (__IBMCPP__ >= 400)
2858 case WM_CTLCOLORCHANGE:
2859 {
2860 bProcessed = HandleCtlColor(&hBrush);
2861 }
2862 break;
2863 #endif
2864 case WM_ERASEBACKGROUND:
2865 //
2866 // Returning TRUE to requestw PM to paint the window background
2867 // in SYSCLR_WINDOW. We don't really want that
2868 //
2869 bProcessed = HandleEraseBkgnd((WXHDC)(HPS)wParam);
2870 mResult = (MRESULT)(FALSE);
2871 break;
2872
2873 // the return value for this message is ignored
2874 case WM_SYSCOLORCHANGE:
2875 bProcessed = HandleSysColorChange();
2876 break;
2877
2878 case WM_REALIZEPALETTE:
2879 bProcessed = HandlePaletteChanged();
2880 break;
2881
2882 // move all drag and drops to wxDrg
2883 case WM_ENDDRAG:
2884 bProcessed = HandleEndDrag(wParam);
2885 break;
2886
2887 case WM_INITDLG:
2888 bProcessed = HandleInitDialog((WXHWND)(HWND)wParam);
2889
2890 if ( bProcessed )
2891 {
2892 // we never set focus from here
2893 mResult = (MRESULT)FALSE;
2894 }
2895 break;
2896
2897 // wxFrame specific message
2898 case WM_MINMAXFRAME:
2899 bProcessed = HandleGetMinMaxInfo((PSWP)wParam);
2900 break;
2901
2902 case WM_SYSVALUECHANGED:
2903 // TODO: do something
2904 mResult = (MRESULT)TRUE;
2905 break;
2906
2907 //
2908 // Comparable to WM_SETPOINTER for windows, only for just controls
2909 //
2910 case WM_CONTROLPOINTER:
2911 bProcessed = HandleSetCursor( SHORT1FROMMP(wParam) // Control ID
2912 ,(HWND)lParam // Cursor Handle
2913 );
2914 if (bProcessed )
2915 {
2916 //
2917 // Returning TRUE stops the DefWindowProc() from further
2918 // processing this message - exactly what we need because we've
2919 // just set the cursor.
2920 //
2921 mResult = (MRESULT)TRUE;
2922 }
2923 break;
2924
2925 #if wxUSE_MENUS_NATIVE
2926 case WM_MENUEND:
2927 if (wxCurrentPopupMenu)
2928 {
2929 if (GetHmenuOf(wxCurrentPopupMenu) == (HWND)lParam)
2930 {
2931 // Break out of msg loop in DoPopupMenu
2932 ::WinPostMsg((HWND)lParam,WM_COMMAND,wParam,0);
2933 }
2934 }
2935 break;
2936 #endif // wxUSE_MENUS_NATIVE
2937
2938 }
2939 if (!bProcessed)
2940 {
2941 #ifdef __WXDEBUG__
2942 wxLogTrace(wxTraceMessages, wxT("Forwarding %s to DefWindowProc."),
2943 wxGetMessageName(uMsg));
2944 #endif // __WXDEBUG__
2945 if (IsKindOf(CLASSINFO(wxFrame)))
2946 mResult = ::WinDefWindowProc(m_hWnd, uMsg, wParam, lParam);
2947 else if (IsKindOf(CLASSINFO(wxDialog)))
2948 mResult = ::WinDefDlgProc( m_hWnd, uMsg, wParam, lParam);
2949 else
2950 mResult = OS2DefWindowProc(uMsg, wParam, lParam);
2951 }
2952 return mResult;
2953 } // end of wxWindowOS2::OS2WindowProc
2954
2955 // ----------------------------------------------------------------------------
2956 // wxWindow <-> HWND map
2957 // ----------------------------------------------------------------------------
2958
2959 wxWinHashTable *wxWinHandleHash = NULL;
2960
2961 wxWindow* wxFindWinFromHandle(
2962 WXHWND hWnd
2963 )
2964 {
2965 return (wxWindow *)wxWinHandleHash->Get((long)hWnd);
2966 } // end of wxFindWinFromHandle
2967
2968 void wxAssociateWinWithHandle(
2969 HWND hWnd
2970 , wxWindowOS2* pWin
2971 )
2972 {
2973 //
2974 // Adding NULL hWnd is (first) surely a result of an error and
2975 // (secondly) breaks menu command processing
2976 //
2977 wxCHECK_RET( hWnd != (HWND)NULL,
2978 wxT("attempt to add a NULL hWnd to window list ignored") );
2979
2980
2981 wxWindow* pOldWin = wxFindWinFromHandle((WXHWND) hWnd);
2982
2983 if (pOldWin && (pOldWin != pWin))
2984 {
2985 wxString str(pWin->GetClassInfo()->GetClassName());
2986
2987 wxLogError( _T("Bug! Found existing HWND %X for new window of class %s")
2988 ,(int)hWnd
2989 ,str.c_str()
2990 );
2991 }
2992 else if (!pOldWin)
2993 {
2994 wxWinHandleHash->Put( (long)hWnd
2995 ,(wxWindow *)pWin
2996 );
2997 }
2998 } // end of wxAssociateWinWithHandle
2999
3000 void wxRemoveHandleAssociation( wxWindowOS2* pWin )
3001 {
3002 wxWinHandleHash->Delete((long)pWin->GetHWND());
3003 } // end of wxRemoveHandleAssociation
3004
3005 //
3006 // Default destroyer - override if you destroy it in some other way
3007 // (e.g. with MDI child windows)
3008 //
3009 void wxWindowOS2::OS2DestroyWindow()
3010 {
3011 }
3012
3013 bool wxWindowOS2::OS2GetCreateWindowCoords( const wxPoint& rPos,
3014 const wxSize& rSize,
3015 int& rnX,
3016 int& rnY,
3017 int& rnWidth,
3018 int& rnHeight ) const
3019 {
3020 bool bNonDefault = false;
3021 static const int DEFAULT_Y = 200;
3022 static const int DEFAULT_H = 250;
3023
3024 if (rPos.x == wxDefaultCoord)
3025 {
3026 rnX = rnY = CW_USEDEFAULT;
3027 }
3028 else
3029 {
3030 rnX = rPos.x;
3031 rnY = rPos.y == wxDefaultCoord ? DEFAULT_Y : rPos.y;
3032 bNonDefault = true;
3033 }
3034 if (rSize.x == wxDefaultCoord)
3035 {
3036 rnWidth = rnHeight = CW_USEDEFAULT;
3037 }
3038 else
3039 {
3040 rnWidth = rSize.x;
3041 rnHeight = rSize.y == wxDefaultCoord ? DEFAULT_H : rSize.y;
3042 bNonDefault = true;
3043 }
3044 return bNonDefault;
3045 } // end of wxWindowOS2::OS2GetCreateWindowCoords
3046
3047 WXHWND wxWindowOS2::OS2GetParent() const
3048 {
3049 return m_parent ? m_parent->GetHWND() : NULL;
3050 }
3051
3052 bool wxWindowOS2::OS2Create( PSZ zClass,
3053 const wxChar* zTitle,
3054 WXDWORD dwStyle,
3055 const wxPoint& rPos,
3056 const wxSize& rSize,
3057 void* pCtlData,
3058 WXDWORD WXUNUSED(dwExStyle),
3059 bool bIsChild )
3060 {
3061 ERRORID vError;
3062 wxString sError;
3063 int nX = 0L;
3064 int nY = 0L;
3065 int nWidth = 0L;
3066 int nHeight = 0L;
3067 long lControlId = 0L;
3068 wxWindowCreationHook vHook(this);
3069 wxString sClassName((wxChar*)zClass);
3070
3071 OS2GetCreateWindowCoords( rPos
3072 ,rSize
3073 ,nX
3074 ,nY
3075 ,nWidth
3076 ,nHeight
3077 );
3078
3079 if (bIsChild)
3080 {
3081 lControlId = GetId();
3082 if (GetWindowStyleFlag() & wxCLIP_SIBLINGS)
3083 {
3084 dwStyle |= WS_CLIPSIBLINGS;
3085 }
3086 }
3087 //
3088 // For each class "Foo" we have we also have "FooNR" ("no repaint") class
3089 // which is the same but without CS_[HV]REDRAW class styles so using it
3090 // ensures that the window is not fully repainted on each resize
3091 //
3092 if (!HasFlag(wxFULL_REPAINT_ON_RESIZE))
3093 {
3094 sClassName += wxT("NR");
3095 }
3096 m_hWnd = (WXHWND)::WinCreateWindow( (HWND)OS2GetParent()
3097 ,(PSZ)sClassName.c_str()
3098 ,(PSZ)(zTitle ? zTitle : wxEmptyString)
3099 ,(ULONG)dwStyle
3100 ,(LONG)0L
3101 ,(LONG)0L
3102 ,(LONG)0L
3103 ,(LONG)0L
3104 ,NULLHANDLE
3105 ,HWND_TOP
3106 ,(ULONG)lControlId
3107 ,pCtlData
3108 ,NULL
3109 );
3110 if (!m_hWnd)
3111 {
3112 vError = ::WinGetLastError(wxGetInstance());
3113 sError = wxPMErrorToStr(vError);
3114 return false;
3115 }
3116 SubclassWin(m_hWnd);
3117 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
3118
3119 m_backgroundColour.Set(wxString(wxT("GREY")));
3120
3121 LONG lColor = (LONG)m_backgroundColour.GetPixel();
3122
3123 if (!::WinSetPresParam( m_hWnd
3124 ,PP_BACKGROUNDCOLOR
3125 ,sizeof(LONG)
3126 ,(PVOID)&lColor
3127 ))
3128 {
3129 vError = ::WinGetLastError(vHabmain);
3130 sError = wxPMErrorToStr(vError);
3131 wxLogError(_T("Error creating frame. Error: %s\n"), sError.c_str());
3132 return false;
3133 }
3134 SetSize( nX
3135 ,nY
3136 ,nWidth
3137 ,nHeight
3138 );
3139 return true;
3140 } // end of WinGuiBase_Window::OS2Create
3141
3142 // ===========================================================================
3143 // OS2 PM message handlers
3144 // ===========================================================================
3145
3146 // ---------------------------------------------------------------------------
3147 // window creation/destruction
3148 // ---------------------------------------------------------------------------
3149
3150 bool wxWindowOS2::HandleCreate( WXLPCREATESTRUCT WXUNUSED(vCs),
3151 bool* pbMayCreate )
3152 {
3153 wxWindowCreateEvent vEvent((wxWindow*)this);
3154
3155 (void)GetEventHandler()->ProcessEvent(vEvent);
3156 *pbMayCreate = true;
3157 return true;
3158 } // end of wxWindowOS2::HandleCreate
3159
3160 bool wxWindowOS2::HandleDestroy()
3161 {
3162 wxWindowDestroyEvent vEvent((wxWindow*)this);
3163 vEvent.SetId(GetId());
3164 (void)GetEventHandler()->ProcessEvent(vEvent);
3165
3166 //
3167 // Delete our drop target if we've got one
3168 //
3169 #if wxUSE_DRAG_AND_DROP
3170 if (m_dropTarget != NULL)
3171 {
3172 delete m_dropTarget;
3173 m_dropTarget = NULL;
3174 }
3175 #endif // wxUSE_DRAG_AND_DROP
3176
3177 //
3178 // WM_DESTROY handled
3179 //
3180 return true;
3181 } // end of wxWindowOS2::HandleDestroy
3182
3183 // ---------------------------------------------------------------------------
3184 // activation/focus
3185 // ---------------------------------------------------------------------------
3186 void wxWindowOS2::OnSetFocus(
3187 wxFocusEvent& rEvent
3188 )
3189 {
3190 rEvent.Skip();
3191 } // end of wxWindowOS2::OnSetFocus
3192
3193 bool wxWindowOS2::HandleActivate(
3194 int nState
3195 , WXHWND WXUNUSED(hActivate)
3196 )
3197 {
3198 wxActivateEvent vEvent( wxEVT_ACTIVATE
3199 ,(bool)nState
3200 ,m_windowId
3201 );
3202 vEvent.SetEventObject(this);
3203 return GetEventHandler()->ProcessEvent(vEvent);
3204 } // end of wxWindowOS2::HandleActivate
3205
3206 bool wxWindowOS2::HandleSetFocus( WXHWND WXUNUSED(hWnd) )
3207 {
3208 //
3209 // Notify the parent keeping track of focus for the kbd navigation
3210 // purposes that we got it
3211 //
3212 wxChildFocusEvent vEventFocus((wxWindow *)this);
3213 (void)GetEventHandler()->ProcessEvent(vEventFocus);
3214
3215 #if wxUSE_CARET
3216 //
3217 // Deal with caret
3218 //
3219 if (m_caret)
3220 {
3221 m_caret->OnSetFocus();
3222 }
3223 #endif // wxUSE_CARET
3224
3225 #if wxUSE_TEXTCTRL
3226 // If it's a wxTextCtrl don't send the event as it will be done
3227 // after the control gets to process it from EN_FOCUS handler
3228 if ( wxDynamicCastThis(wxTextCtrl) )
3229 {
3230 return false;
3231 }
3232 #endif // wxUSE_TEXTCTRL
3233
3234 wxFocusEvent vEvent(wxEVT_SET_FOCUS, m_windowId);
3235
3236 vEvent.SetEventObject(this);
3237 return GetEventHandler()->ProcessEvent(vEvent);
3238 } // end of wxWindowOS2::HandleSetFocus
3239
3240 bool wxWindowOS2::HandleKillFocus( WXHWND hWnd )
3241 {
3242 #if wxUSE_CARET
3243 //
3244 // Deal with caret
3245 //
3246 if (m_caret)
3247 {
3248 m_caret->OnKillFocus();
3249 }
3250 #endif // wxUSE_CARET
3251
3252 #if wxUSE_TEXTCTRL
3253 //
3254 // If it's a wxTextCtrl don't send the event as it will be done
3255 // after the control gets to process it.
3256 //
3257 wxTextCtrl* pCtrl = wxDynamicCastThis(wxTextCtrl);
3258
3259 if (pCtrl)
3260 {
3261 return false;
3262 }
3263 #endif
3264
3265 //
3266 // Don't send the event when in the process of being deleted. This can
3267 // only cause problems if the event handler tries to access the object.
3268 //
3269 if ( m_isBeingDeleted )
3270 {
3271 return false;
3272 }
3273
3274 wxFocusEvent vEvent( wxEVT_KILL_FOCUS
3275 ,m_windowId
3276 );
3277
3278 vEvent.SetEventObject(this);
3279
3280 //
3281 // wxFindWinFromHandle() may return NULL, it is ok
3282 //
3283 vEvent.SetWindow(wxFindWinFromHandle(hWnd));
3284 return GetEventHandler()->ProcessEvent(vEvent);
3285 } // end of wxWindowOS2::HandleKillFocus
3286
3287 // ---------------------------------------------------------------------------
3288 // miscellaneous
3289 // ---------------------------------------------------------------------------
3290
3291 bool wxWindowOS2::HandleShow(
3292 bool bShow
3293 , int WXUNUSED(nStatus)
3294 )
3295 {
3296 wxShowEvent vEvent(GetId(), bShow);
3297
3298 vEvent.SetEventObject(this);
3299 return GetEventHandler()->ProcessEvent(vEvent);
3300 } // end of wxWindowOS2::HandleShow
3301
3302 bool wxWindowOS2::HandleInitDialog( WXHWND WXUNUSED(hWndFocus) )
3303 {
3304 wxInitDialogEvent vEvent(GetId());
3305
3306 vEvent.SetEventObject(this);
3307 return GetEventHandler()->ProcessEvent(vEvent);
3308 } // end of wxWindowOS2::HandleInitDialog
3309
3310 bool wxWindowOS2::HandleEndDrag(WXWPARAM WXUNUSED(wParam))
3311 {
3312 // TODO: We'll handle drag and drop later
3313 return false;
3314 }
3315
3316 bool wxWindowOS2::HandleSetCursor( USHORT WXUNUSED(vId),
3317 WXHWND hPointer )
3318 {
3319 //
3320 // Under OS/2 PM this allows the pointer to be changed
3321 // as it passes over a control
3322 //
3323 ::WinSetPointer(HWND_DESKTOP, (HPOINTER)hPointer);
3324 return true;
3325 } // end of wxWindowOS2::HandleSetCursor
3326
3327 // ---------------------------------------------------------------------------
3328 // owner drawn stuff
3329 // ---------------------------------------------------------------------------
3330 bool wxWindowOS2::OS2OnDrawItem( int vId,
3331 WXDRAWITEMSTRUCT* pItemStruct )
3332 {
3333 #if wxUSE_OWNER_DRAWN
3334 wxDC vDc;
3335
3336 #if wxUSE_MENUS_NATIVE
3337 //
3338 // Is it a menu item?
3339 //
3340 if (vId == 0)
3341 {
3342 ERRORID vError;
3343 wxString sError;
3344 POWNERITEM pMeasureStruct = (POWNERITEM)pItemStruct;
3345 wxFrame* pFrame = (wxFrame*)this;
3346 wxMenuItem* pMenuItem = pFrame->GetMenuBar()->FindItem(pMeasureStruct->idItem, pMeasureStruct->hItem);
3347 HDC hDC = ::GpiQueryDevice(pMeasureStruct->hps);
3348 wxRect vRect( pMeasureStruct->rclItem.xLeft
3349 ,pMeasureStruct->rclItem.yBottom
3350 ,pMeasureStruct->rclItem.xRight - pMeasureStruct->rclItem.xLeft
3351 ,pMeasureStruct->rclItem.yTop - pMeasureStruct->rclItem.yBottom
3352 );
3353 vDc.SetHDC( hDC, false );
3354 vDc.SetHPS( pMeasureStruct->hps );
3355 //
3356 // Load the wxWidgets Pallete and set to RGB mode
3357 //
3358 if (!::GpiCreateLogColorTable( pMeasureStruct->hps
3359 ,0L
3360 ,LCOLF_CONSECRGB
3361 ,0L
3362 ,(LONG)wxTheColourDatabase->m_nSize
3363 ,(PLONG)wxTheColourDatabase->m_palTable
3364 ))
3365 {
3366 vError = ::WinGetLastError(vHabmain);
3367 sError = wxPMErrorToStr(vError);
3368 wxLogError(_T("Unable to set current color table. Error: %s\n"), sError.c_str());
3369 }
3370 //
3371 // Set the color table to RGB mode
3372 //
3373 if (!::GpiCreateLogColorTable( pMeasureStruct->hps
3374 ,0L
3375 ,LCOLF_RGB
3376 ,0L
3377 ,0L
3378 ,NULL
3379 ))
3380 {
3381 vError = ::WinGetLastError(vHabmain);
3382 sError = wxPMErrorToStr(vError);
3383 wxLogError(_T("Unable to set current color table. Error: %s\n"), sError.c_str());
3384 }
3385
3386 wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
3387
3388 int eAction = 0;
3389 int eStatus = 0;
3390
3391 if (pMeasureStruct->fsAttribute == pMeasureStruct->fsAttributeOld)
3392 {
3393 //
3394 // Entire Item needs to be redrawn (either it has reappeared from
3395 // behind another window or is being displayed for the first time
3396 //
3397 eAction = wxOwnerDrawn::wxODDrawAll;
3398
3399 if (pMeasureStruct->fsAttribute & MIA_HILITED)
3400 {
3401 //
3402 // If it is currently selected we let the system handle it
3403 //
3404 eStatus |= wxOwnerDrawn::wxODSelected;
3405 }
3406 if (pMeasureStruct->fsAttribute & MIA_CHECKED)
3407 {
3408 //
3409 // If it is currently checked we draw our own
3410 //
3411 eStatus |= wxOwnerDrawn::wxODChecked;
3412 pMeasureStruct->fsAttributeOld = pMeasureStruct->fsAttribute &= ~MIA_CHECKED;
3413 }
3414 if (pMeasureStruct->fsAttribute & MIA_DISABLED)
3415 {
3416 //
3417 // If it is currently disabled we let the system handle it
3418 //
3419 eStatus |= wxOwnerDrawn::wxODDisabled;
3420 }
3421 //
3422 // Don't really care about framed (indicationg focus) or NoDismiss
3423 //
3424 }
3425 else
3426 {
3427 if (pMeasureStruct->fsAttribute & MIA_HILITED)
3428 {
3429 eAction = wxOwnerDrawn::wxODDrawAll;
3430 eStatus |= wxOwnerDrawn::wxODSelected;
3431 //
3432 // Keep the system from trying to highlight with its bogus colors
3433 //
3434 pMeasureStruct->fsAttributeOld = pMeasureStruct->fsAttribute &= ~MIA_HILITED;
3435 }
3436 else if (!(pMeasureStruct->fsAttribute & MIA_HILITED))
3437 {
3438 eAction = wxOwnerDrawn::wxODDrawAll;
3439 eStatus = 0;
3440 //
3441 // Keep the system from trying to highlight with its bogus colors
3442 //
3443 pMeasureStruct->fsAttribute = pMeasureStruct->fsAttributeOld &= ~MIA_HILITED;
3444 }
3445 else
3446 {
3447 //
3448 // For now we don't care about anything else
3449 // just ignore the entire message!
3450 //
3451 return true;
3452 }
3453 }
3454 //
3455 // Now redraw the item
3456 //
3457 return(pMenuItem->OnDrawItem( vDc
3458 ,vRect
3459 ,(wxOwnerDrawn::wxODAction)eAction
3460 ,(wxOwnerDrawn::wxODStatus)eStatus
3461 ));
3462 //
3463 // leave the fsAttribute and fsOldAttribute unchanged. If different,
3464 // the system will do the highlight or fraeming or disabling for us,
3465 // otherwise, we'd have to do it ourselves.
3466 //
3467 }
3468 #endif // wxUSE_MENUS_NATIVE
3469
3470 wxWindow* pItem = FindItem(vId);
3471
3472 if (pItem && pItem->IsKindOf(CLASSINFO(wxControl)))
3473 {
3474 return ((wxControl *)pItem)->OS2OnDraw(pItemStruct);
3475 }
3476 #else
3477 vId = vId;
3478 pItemStruct = pItemStruct;
3479 #endif
3480 return false;
3481 } // end of wxWindowOS2::OS2OnDrawItem
3482
3483 long wxWindowOS2::OS2OnMeasureItem( int lId,
3484 WXMEASUREITEMSTRUCT* pItemStruct )
3485 {
3486 #if wxUSE_OWNER_DRAWN
3487 //
3488 // Is it a menu item?
3489 //
3490 if (lId == 65536) // I really don't like this...has to be a better indicator
3491 {
3492 if (IsKindOf(CLASSINFO(wxFrame))) // we'll assume if Frame then a menu
3493 {
3494 size_t nWidth;
3495 size_t nHeight;
3496 POWNERITEM pMeasureStruct = (POWNERITEM)pItemStruct;
3497 wxFrame* pFrame = (wxFrame*)this;
3498 wxMenuItem* pMenuItem = pFrame->GetMenuBar()->FindItem(pMeasureStruct->idItem, pMeasureStruct->hItem);
3499
3500 wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
3501 nWidth = 0L;
3502 nHeight = 0L;
3503 if (pMenuItem->OnMeasureItem( &nWidth
3504 ,&nHeight
3505 ))
3506 {
3507 MRESULT mRc;
3508
3509 pMeasureStruct->rclItem.xRight = nWidth;
3510 pMeasureStruct->rclItem.xLeft = 0L;
3511 pMeasureStruct->rclItem.yTop = nHeight;
3512 pMeasureStruct->rclItem.yBottom = 0L;
3513 mRc = MRFROM2SHORT(nHeight, nWidth);
3514 return LONGFROMMR(mRc);
3515 }
3516 return 0L;
3517 }
3518 }
3519 wxWindow* pItem = FindItem(lId);
3520
3521 if (pItem && pItem->IsKindOf(CLASSINFO(wxControl)))
3522 {
3523 OWNERITEM vItem;
3524
3525 vItem.idItem = (LONG)pItemStruct;
3526 return ((wxControl *)pItem)->OS2OnMeasure((WXMEASUREITEMSTRUCT*)&vItem);
3527 }
3528 #else
3529 lId = lId;
3530 pItemStruct = pItemStruct;
3531 #endif // wxUSE_OWNER_DRAWN
3532 return FALSE;
3533 }
3534
3535 // ---------------------------------------------------------------------------
3536 // colours and palettes
3537 // ---------------------------------------------------------------------------
3538
3539 bool wxWindowOS2::HandleSysColorChange()
3540 {
3541 wxSysColourChangedEvent vEvent;
3542
3543 vEvent.SetEventObject(this);
3544 return GetEventHandler()->ProcessEvent(vEvent);
3545 } // end of wxWindowOS2::HandleSysColorChange
3546
3547 bool wxWindowOS2::HandleCtlColor( WXHBRUSH* WXUNUSED(phBrush) )
3548 {
3549 //
3550 // Not much provided with message. So not sure I can do anything with it
3551 //
3552 return true;
3553 } // end of wxWindowOS2::HandleCtlColor
3554
3555
3556 // Define for each class of dialog and control
3557 WXHBRUSH wxWindowOS2::OnCtlColor(WXHDC WXUNUSED(hDC),
3558 WXHWND WXUNUSED(hWnd),
3559 WXUINT WXUNUSED(nCtlColor),
3560 WXUINT WXUNUSED(message),
3561 WXWPARAM WXUNUSED(wParam),
3562 WXLPARAM WXUNUSED(lParam))
3563 {
3564 return (WXHBRUSH)0;
3565 }
3566
3567 bool wxWindowOS2::HandlePaletteChanged()
3568 {
3569 // need to set this to something first
3570 WXHWND hWndPalChange = NULLHANDLE;
3571
3572 wxPaletteChangedEvent vEvent(GetId());
3573
3574 vEvent.SetEventObject(this);
3575 vEvent.SetChangedWindow(wxFindWinFromHandle(hWndPalChange));
3576
3577 return GetEventHandler()->ProcessEvent(vEvent);
3578 } // end of wxWindowOS2::HandlePaletteChanged
3579
3580 //
3581 // Responds to colour changes: passes event on to children.
3582 //
3583 void wxWindowOS2::OnSysColourChanged(
3584 wxSysColourChangedEvent& rEvent
3585 )
3586 {
3587 wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
3588
3589 while (node)
3590 {
3591 //
3592 // Only propagate to non-top-level windows
3593 //
3594 wxWindow* pWin = (wxWindow *)node->GetData();
3595
3596 if (pWin->GetParent())
3597 {
3598 wxSysColourChangedEvent vEvent;
3599
3600 rEvent.SetEventObject(pWin);
3601 pWin->GetEventHandler()->ProcessEvent(vEvent);
3602 }
3603 node = node->GetNext();
3604 }
3605 } // end of wxWindowOS2::OnSysColourChanged
3606
3607 // ---------------------------------------------------------------------------
3608 // painting
3609 // ---------------------------------------------------------------------------
3610
3611 void wxWindow::OnPaint (
3612 wxPaintEvent& rEvent
3613 )
3614 {
3615 HDC hDC = (HDC)wxPaintDC::FindDCInCache((wxWindow*) rEvent.GetEventObject());
3616
3617 if (hDC != 0)
3618 {
3619 OS2DefWindowProc( (WXUINT)WM_PAINT
3620 ,(WXWPARAM)hDC
3621 ,(WXLPARAM)0
3622 );
3623 }
3624 } // end of wxWindow::OnPaint
3625
3626 bool wxWindowOS2::HandlePaint()
3627 {
3628 HRGN hRgn;
3629 wxPaintEvent vEvent(m_windowId);
3630 HPS hPS;
3631 bool bProcessed;
3632
3633 // Create empty region
3634 // TODO: get HPS somewhere else if possible
3635 hPS = ::WinGetPS(GetHwnd());
3636 hRgn = ::GpiCreateRegion(hPS, 0, NULL);
3637
3638 if (::WinQueryUpdateRegion(GetHwnd(), hRgn) == RGN_ERROR)
3639 {
3640 wxLogLastError(wxT("CreateRectRgn"));
3641 return false;
3642 }
3643
3644 // Get all the rectangles from the region, convert the individual
3645 // rectangles to "the other" coordinate system and reassemble a
3646 // region from the rectangles, to be feed into m_updateRegion.
3647 //
3648 // FIXME: This is a bad hack since OS/2 API specifies that rectangles
3649 // passed into GpiSetRegion must not have Bottom > Top,
3650 // however, at first sight, it _seems_ to work nonetheless.
3651 //
3652 RGNRECT vRgnData;
3653 PRECTL pUpdateRects = NULL;
3654 vRgnData.ulDirection = RECTDIR_LFRT_TOPBOT;
3655 if (::GpiQueryRegionRects( hPS // Pres space
3656 ,hRgn // Handle of region to query
3657 ,NULL // Return all RECTs
3658 ,&vRgnData // Will contain number or RECTs in region
3659 ,NULL // NULL to return number of RECTs
3660 ))
3661 {
3662 pUpdateRects = new RECTL[vRgnData.crcReturned];
3663 vRgnData.crc = vRgnData.crcReturned;
3664 vRgnData.ircStart = 1;
3665 if (::GpiQueryRegionRects( hPS // Pres space of source
3666 ,hRgn // Handle of source region
3667 ,NULL // Return all RECTs
3668 ,&vRgnData // Operations set to return rects
3669 ,pUpdateRects // Will contain the actual RECTS
3670 ))
3671 {
3672 int height;
3673 RECT vRect;
3674 ::WinQueryWindowRect(GetHwnd(), &vRect);
3675 height = vRect.yTop;
3676
3677 for(size_t i = 0; i < vRgnData.crc; i++)
3678 {
3679 int rectHeight;
3680 rectHeight = pUpdateRects[i].yTop - pUpdateRects[i].yBottom;
3681 pUpdateRects[i].yTop = height - pUpdateRects[i].yTop;
3682 pUpdateRects[i].yBottom = pUpdateRects[i].yTop + rectHeight;
3683 }
3684 ::GpiSetRegion(hPS, hRgn, vRgnData.crc, pUpdateRects);
3685 delete [] pUpdateRects;
3686 }
3687 }
3688
3689 m_updateRegion = wxRegion(hRgn, hPS);
3690
3691 vEvent.SetEventObject(this);
3692 bProcessed = GetEventHandler()->ProcessEvent(vEvent);
3693
3694 if (!bProcessed &&
3695 IsKindOf(CLASSINFO(wxPanel)) &&
3696 GetChildren().GetCount() == 0
3697 )
3698 {
3699 //
3700 // OS/2 needs to process this right here, not by the default proc
3701 // Window's default proc correctly paints everything, OS/2 does not.
3702 // For decorative panels that typically have no children, we draw
3703 // borders.
3704 //
3705 HPS hPS;
3706 RECTL vRect;
3707
3708 hPS = ::WinBeginPaint( GetHwnd()
3709 ,NULLHANDLE
3710 ,&vRect
3711 );
3712 if(hPS)
3713 {
3714 ::GpiCreateLogColorTable( hPS
3715 ,0L
3716 ,LCOLF_CONSECRGB
3717 ,0L
3718 ,(LONG)wxTheColourDatabase->m_nSize
3719 ,(PLONG)wxTheColourDatabase->m_palTable
3720 );
3721 ::GpiCreateLogColorTable( hPS
3722 ,0L
3723 ,LCOLF_RGB
3724 ,0L
3725 ,0L
3726 ,NULL
3727 );
3728 if (::WinIsWindowVisible(GetHWND()))
3729 ::WinFillRect(hPS, &vRect, GetBackgroundColour().GetPixel());
3730 if (m_dwExStyle)
3731 {
3732 LINEBUNDLE vLineBundle;
3733
3734 vLineBundle.lColor = 0x00000000; // Black
3735 vLineBundle.usMixMode = FM_OVERPAINT;
3736 vLineBundle.fxWidth = 1;
3737 vLineBundle.lGeomWidth = 1;
3738 vLineBundle.usType = LINETYPE_SOLID;
3739 vLineBundle.usEnd = 0;
3740 vLineBundle.usJoin = 0;
3741 ::GpiSetAttrs( hPS
3742 ,PRIM_LINE
3743 ,LBB_COLOR | LBB_MIX_MODE | LBB_WIDTH | LBB_GEOM_WIDTH | LBB_TYPE
3744 ,0L
3745 ,&vLineBundle
3746 );
3747 ::WinQueryWindowRect(GetHwnd(), &vRect);
3748 wxDrawBorder( hPS
3749 ,vRect
3750 ,m_dwExStyle
3751 );
3752 }
3753 }
3754 ::WinEndPaint(hPS);
3755 bProcessed = true;
3756 }
3757 else if (!bProcessed &&
3758 IsKindOf(CLASSINFO(wxPanel))
3759 )
3760 {
3761 //
3762 // Panel with children, usually fills a frame client so no borders.
3763 //
3764 HPS hPS;
3765 RECTL vRect;
3766
3767 hPS = ::WinBeginPaint( GetHwnd()
3768 ,NULLHANDLE
3769 ,&vRect
3770 );
3771 if(hPS)
3772 {
3773 ::GpiCreateLogColorTable( hPS
3774 ,0L
3775 ,LCOLF_CONSECRGB
3776 ,0L
3777 ,(LONG)wxTheColourDatabase->m_nSize
3778 ,(PLONG)wxTheColourDatabase->m_palTable
3779 );
3780 ::GpiCreateLogColorTable( hPS
3781 ,0L
3782 ,LCOLF_RGB
3783 ,0L
3784 ,0L
3785 ,NULL
3786 );
3787
3788 if (::WinIsWindowVisible(GetHWND()))
3789 ::WinFillRect(hPS, &vRect, GetBackgroundColour().GetPixel());
3790 }
3791 ::WinEndPaint(hPS);
3792 bProcessed = true;
3793 }
3794 return bProcessed;
3795 } // end of wxWindowOS2::HandlePaint
3796
3797 bool wxWindowOS2::HandleEraseBkgnd( WXHDC hDC )
3798 {
3799 SWP vSwp;
3800 bool rc;
3801
3802 ::WinQueryWindowPos(GetHwnd(), &vSwp);
3803 if (vSwp.fl & SWP_MINIMIZE)
3804 return true;
3805
3806 wxDC vDC;
3807
3808 vDC.m_hPS = (HPS)hDC; // this is really a PS
3809 vDC.SetWindow((wxWindow*)this);
3810 vDC.BeginDrawing();
3811
3812 wxEraseEvent vEvent(m_windowId, &vDC);
3813
3814 vEvent.SetEventObject(this);
3815
3816 rc = GetEventHandler()->ProcessEvent(vEvent);
3817
3818 vDC.EndDrawing();
3819 vDC.m_hPS = NULLHANDLE;
3820 return true;
3821 } // end of wxWindowOS2::HandleEraseBkgnd
3822
3823 void wxWindowOS2::OnEraseBackground(wxEraseEvent& rEvent)
3824 {
3825 RECTL vRect;
3826 HPS hPS = rEvent.GetDC()->GetHPS();
3827 APIRET rc;
3828 LONG lColor = m_backgroundColour.GetPixel();
3829
3830 rc = ::WinQueryWindowRect(GetHwnd(), &vRect);
3831 rc = ::WinFillRect(hPS, &vRect, lColor);
3832 } // end of wxWindowOS2::OnEraseBackground
3833
3834 // ---------------------------------------------------------------------------
3835 // moving and resizing
3836 // ---------------------------------------------------------------------------
3837
3838 bool wxWindowOS2::HandleMinimize()
3839 {
3840 wxIconizeEvent vEvent(m_windowId);
3841
3842 vEvent.SetEventObject(this);
3843 return GetEventHandler()->ProcessEvent(vEvent);
3844 } // end of wxWindowOS2::HandleMinimize
3845
3846 bool wxWindowOS2::HandleMaximize()
3847 {
3848 wxMaximizeEvent vEvent(m_windowId);
3849
3850 vEvent.SetEventObject(this);
3851 return GetEventHandler()->ProcessEvent(vEvent);
3852 } // end of wxWindowOS2::HandleMaximize
3853
3854 bool wxWindowOS2::HandleMove( int nX, int nY )
3855 {
3856 wxPoint pt(nX, nY);
3857 wxMoveEvent vEvent(pt, m_windowId);
3858
3859 vEvent.SetEventObject(this);
3860 return GetEventHandler()->ProcessEvent(vEvent);
3861 } // end of wxWindowOS2::HandleMove
3862
3863 bool wxWindowOS2::HandleSize( int nWidth,
3864 int nHeight,
3865 WXUINT WXUNUSED(nFlag) )
3866 {
3867 wxSize sz(nWidth, nHeight);
3868 wxSizeEvent vEvent(sz, m_windowId);
3869
3870 vEvent.SetEventObject(this);
3871 return GetEventHandler()->ProcessEvent(vEvent);
3872 } // end of wxWindowOS2::HandleSize
3873
3874 bool wxWindowOS2::HandleGetMinMaxInfo( PSWP pSwp )
3875 {
3876 POINTL vPoint;
3877
3878 switch(pSwp->fl)
3879 {
3880 case SWP_MAXIMIZE:
3881 #if !(defined(__WATCOMC__) && __WATCOMC__ < 1240 )
3882 // Open Watcom 1.3 had incomplete headers
3883 // that's reported and should be fixed for OW 1.4
3884 ::WinGetMaxPosition(GetHwnd(), pSwp);
3885 m_maxWidth = pSwp->cx;
3886 m_maxHeight = pSwp->cy;
3887 #endif
3888 break;
3889
3890 case SWP_MINIMIZE:
3891 #if !(defined(__WATCOMC__) && __WATCOMC__ < 1240 )
3892 // Open Watcom 1.3 had incomplete headers
3893 // that's reported and should be fixed for OW 1.4
3894 ::WinGetMinPosition(GetHwnd(), pSwp, &vPoint);
3895 m_minWidth = pSwp->cx;
3896 m_minHeight = pSwp->cy;
3897 #else
3898 wxUnusedVar(vPoint);
3899 #endif
3900 break;
3901
3902 default:
3903 return false;
3904 }
3905 return true;
3906 } // end of wxWindowOS2::HandleGetMinMaxInfo
3907
3908 // ---------------------------------------------------------------------------
3909 // command messages
3910 // ---------------------------------------------------------------------------
3911 bool wxWindowOS2::HandleCommand( WXWORD wId,
3912 WXWORD wCmd,
3913 WXHWND hControl )
3914 {
3915 #if wxUSE_MENUS_NATIVE
3916 if (wxCurrentPopupMenu)
3917 {
3918 wxMenu* pPopupMenu = wxCurrentPopupMenu;
3919
3920 wxCurrentPopupMenu = NULL;
3921 return pPopupMenu->OS2Command(wCmd, wId);
3922 }
3923 #endif // wxUSE_MENUS_NATIVE
3924
3925 wxWindow* pWin = FindItem(wId);
3926
3927 if (!pWin)
3928 {
3929 pWin = wxFindWinFromHandle(hControl);
3930 }
3931
3932 if (pWin)
3933 return pWin->OS2Command(wCmd, wId);
3934
3935 return false;
3936 } // end of wxWindowOS2::HandleCommand
3937
3938 bool wxWindowOS2::HandleSysCommand( WXWPARAM wParam,
3939 WXLPARAM WXUNUSED(lParam) )
3940 {
3941 //
3942 // 4 bits are reserved
3943 //
3944 switch (SHORT1FROMMP(wParam))
3945 {
3946 case SC_MAXIMIZE:
3947 return HandleMaximize();
3948
3949 case SC_MINIMIZE:
3950 return HandleMinimize();
3951 }
3952 return false;
3953 } // end of wxWindowOS2::HandleSysCommand
3954
3955 // ---------------------------------------------------------------------------
3956 // mouse events
3957 // ---------------------------------------------------------------------------
3958 //TODO!!! check against MSW
3959 void wxWindowOS2::InitMouseEvent(
3960 wxMouseEvent& rEvent
3961 , int nX
3962 , int nY
3963 , WXUINT uFlags
3964 )
3965 {
3966 int nHeight;
3967 DoGetSize(0, &nHeight);
3968 rEvent.m_x = nX;
3969 // Convert to wxWidgets standard coordinate system!
3970 rEvent.m_y = nHeight - nY;
3971 rEvent.m_shiftDown = ((uFlags & KC_SHIFT) != 0);
3972 rEvent.m_controlDown = ((uFlags & KC_CTRL) != 0);
3973 rEvent.m_altDown = ((uFlags & KC_ALT) != 0);
3974 rEvent.m_leftDown = (::WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) &
3975 0x8000) != 0;
3976 rEvent.m_middleDown = (::WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) &
3977 0x8000) != 0;
3978 rEvent.m_rightDown = (::WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) &
3979 0x8000) != 0;
3980 rEvent.SetTimestamp(s_currentMsg.time);
3981 rEvent.SetEventObject(this);
3982 rEvent.SetId(GetId());
3983
3984 #if wxUSE_MOUSEEVENT_HACK
3985 m_lastMouseX = nX;
3986 m_lastMouseY = nY;
3987 m_lastMouseEvent = rEvent.GetEventType();
3988 #endif // wxUSE_MOUSEEVENT_HACK
3989 } // end of wxWindowOS2::InitMouseEvent
3990
3991 bool wxWindowOS2::HandleMouseEvent( WXUINT uMsg,
3992 int nX,
3993 int nY,
3994 WXUINT uFlags )
3995 {
3996 bool bProcessed = false;
3997
3998 //
3999 // The mouse events take consecutive IDs from WM_MOUSEFIRST to
4000 // WM_MOUSELAST, so it's enough to subtract WM_MOUSEMOVE == WM_MOUSEFIRST
4001 // from the message id and take the value in the table to get wxWin event
4002 // id
4003 //
4004 static const wxEventType eventsMouse[] =
4005 {
4006 wxEVT_MOTION,
4007 wxEVT_LEFT_DOWN,
4008 wxEVT_LEFT_UP,
4009 wxEVT_LEFT_DCLICK,
4010 wxEVT_RIGHT_DOWN,
4011 wxEVT_RIGHT_UP,
4012 wxEVT_RIGHT_DCLICK,
4013 wxEVT_MIDDLE_DOWN,
4014 wxEVT_MIDDLE_UP,
4015 wxEVT_MIDDLE_DCLICK
4016 };
4017
4018 // Bounds check
4019 if ((uMsg >= WM_MOUSEMOVE) && (uMsg <= WM_BUTTON3DBLCLK))
4020 {
4021 wxMouseEvent vEvent(eventsMouse[uMsg - WM_MOUSEMOVE]);
4022
4023 InitMouseEvent( vEvent
4024 ,nX
4025 ,nY
4026 ,uFlags
4027 );
4028
4029 bProcessed = GetEventHandler()->ProcessEvent(vEvent);
4030 if (!bProcessed)
4031 {
4032 HPOINTER hCursor = (HPOINTER)GetCursor().GetHCURSOR();
4033
4034 if (hCursor != NULLHANDLE)
4035 {
4036 ::WinSetPointer(HWND_DESKTOP, hCursor);
4037 bProcessed = true;
4038 }
4039 }
4040 }
4041 return bProcessed;
4042 } // end of wxWindowOS2::HandleMouseEvent
4043
4044 bool wxWindowOS2::HandleMouseMove( int nX,
4045 int nY,
4046 WXUINT uFlags )
4047 {
4048 if (!m_bMouseInWindow)
4049 {
4050 //
4051 // Generate an ENTER event
4052 //
4053 m_bMouseInWindow = true;
4054
4055 wxMouseEvent vEvent(wxEVT_ENTER_WINDOW);
4056
4057 InitMouseEvent( vEvent
4058 ,nX
4059 ,nY
4060 ,uFlags
4061 );
4062
4063 (void)GetEventHandler()->ProcessEvent(vEvent);
4064 }
4065 return HandleMouseEvent( WM_MOUSEMOVE
4066 ,nX
4067 ,nY
4068 ,uFlags
4069 );
4070 } // end of wxWindowOS2::HandleMouseMove
4071
4072 // ---------------------------------------------------------------------------
4073 // keyboard handling
4074 // ---------------------------------------------------------------------------
4075
4076 //
4077 // Create the key event of the given type for the given key - used by
4078 // HandleChar and HandleKeyDown/Up
4079 //
4080 wxKeyEvent wxWindowOS2::CreateKeyEvent(
4081 wxEventType eType
4082 , int nId
4083 , WXLPARAM lParam
4084 , WXWPARAM wParam
4085 ) const
4086 {
4087 wxKeyEvent vEvent(eType);
4088
4089 vEvent.SetId(GetId());
4090 vEvent.m_shiftDown = IsShiftDown();
4091 vEvent.m_controlDown = IsCtrlDown();
4092 vEvent.m_altDown = (HIWORD(lParam) & KC_ALT) == KC_ALT;
4093
4094 vEvent.SetEventObject((wxWindow *)this); // const_cast
4095 vEvent.m_keyCode = nId;
4096 vEvent.m_rawCode = (wxUint32)wParam;
4097 vEvent.m_rawFlags = (wxUint32)lParam;
4098 vEvent.SetTimestamp(s_currentMsg.time);
4099
4100 //
4101 // Translate the position to client coords
4102 //
4103 POINTL vPoint;
4104 RECTL vRect;
4105
4106 ::WinQueryPointerPos(HWND_DESKTOP, &vPoint);
4107 ::WinQueryWindowRect( GetHwnd()
4108 ,&vRect
4109 );
4110
4111 vPoint.x -= vRect.xLeft;
4112 vPoint.y -= vRect.yBottom;
4113
4114 vEvent.m_x = vPoint.x;
4115 vEvent.m_y = vPoint.y;
4116
4117 return vEvent;
4118 } // end of wxWindowOS2::CreateKeyEvent
4119
4120 //
4121 // isASCII is true only when we're called from WM_CHAR handler and not from
4122 // WM_KEYDOWN one
4123 //
4124 bool wxWindowOS2::HandleChar( WXWPARAM WXUNUSED(wParam),
4125 WXLPARAM lParam,
4126 bool isASCII )
4127 {
4128 bool bCtrlDown = false;
4129 int vId;
4130
4131 if (m_bLastKeydownProcessed)
4132 {
4133 //
4134 // The key was handled in the EVT_KEY_DOWN. Handling a key in an
4135 // EVT_KEY_DOWN handler is meant, by design, to prevent EVT_CHARs
4136 // from happening, so just bail out at this point.
4137 //
4138 m_bLastKeydownProcessed = false;
4139 return true;
4140 }
4141 if (isASCII)
4142 {
4143 //
4144 // If 1 -> 26, translate to either special keycode or just set
4145 // ctrlDown. IOW, Ctrl-C should result in keycode == 3 and
4146 // ControlDown() == true.
4147 //
4148 vId = SHORT1FROMMP(lParam);
4149 if ((vId > 0) && (vId < 27))
4150 {
4151 switch (vId)
4152 {
4153 case 13:
4154 vId = WXK_RETURN;
4155 break;
4156
4157 case 8:
4158 vId = WXK_BACK;
4159 break;
4160
4161 case 9:
4162 vId = WXK_TAB;
4163 break;
4164
4165 default:
4166 bCtrlDown = true;
4167 break;
4168 }
4169 }
4170 }
4171 else // we're called from WM_KEYDOWN
4172 {
4173 vId = wxCharCodeOS2ToWX((int)SHORT2FROMMP(lParam));
4174 if (vId == 0)
4175 return false;
4176 }
4177
4178 wxKeyEvent vEvent(CreateKeyEvent( wxEVT_CHAR, vId, lParam ));
4179
4180 if (bCtrlDown)
4181 {
4182 vEvent.m_controlDown = true;
4183 }
4184
4185 return (GetEventHandler()->ProcessEvent(vEvent));
4186 }
4187
4188 bool wxWindowOS2::HandleKeyDown( WXWPARAM wParam,
4189 WXLPARAM lParam )
4190 {
4191 int nId = wxCharCodeOS2ToWX((int)SHORT2FROMMP(lParam));
4192
4193 if (!nId)
4194 {
4195 //
4196 // Normal ASCII char
4197 //
4198 nId = SHORT1FROMMP(lParam);
4199 }
4200
4201 if (nId != -1)
4202 {
4203 wxKeyEvent vEvent(CreateKeyEvent( wxEVT_KEY_DOWN
4204 ,nId
4205 ,(MPARAM)lParam
4206 ,(MPARAM)wParam
4207 ));
4208
4209 if (GetEventHandler()->ProcessEvent(vEvent))
4210 {
4211 return true;
4212 }
4213 }
4214 return false;
4215 } // end of wxWindowOS2::HandleKeyDown
4216
4217 bool wxWindowOS2::HandleKeyUp( WXWPARAM wParam,
4218 WXLPARAM lParam )
4219 {
4220 int nId = wxCharCodeOS2ToWX((int)SHORT2FROMMP(lParam));
4221
4222 if (!nId)
4223 {
4224 //
4225 // Normal ASCII char
4226 //
4227 nId = CHAR1FROMMP(lParam);
4228 }
4229
4230 if (nId != -1)
4231 {
4232 wxKeyEvent vEvent(CreateKeyEvent( wxEVT_KEY_UP
4233 ,nId
4234 ,(MPARAM)lParam
4235 ,(MPARAM)wParam
4236 ));
4237
4238 if (GetEventHandler()->ProcessEvent(vEvent))
4239 return true;
4240 }
4241 return false;
4242 } // end of wxWindowOS2::HandleKeyUp
4243
4244 // ---------------------------------------------------------------------------
4245 // joystick
4246 // ---------------------------------------------------------------------------
4247
4248 // ---------------------------------------------------------------------------
4249 // scrolling
4250 // ---------------------------------------------------------------------------
4251
4252 bool wxWindowOS2::OS2OnScroll( int nOrientation,
4253 WXWORD wParam,
4254 WXWORD wPos,
4255 WXHWND hControl )
4256 {
4257 if (hControl)
4258 {
4259 wxWindow* pChild = wxFindWinFromHandle(hControl);
4260
4261 if (pChild )
4262 return pChild->OS2OnScroll( nOrientation
4263 ,wParam
4264 ,wPos
4265 ,hControl
4266 );
4267 }
4268
4269 wxScrollWinEvent vEvent;
4270
4271 vEvent.SetPosition(wPos);
4272 vEvent.SetOrientation(nOrientation);
4273 vEvent.SetEventObject(this);
4274
4275 switch (wParam)
4276 {
4277 case SB_LINEUP:
4278 vEvent.SetEventType(wxEVT_SCROLLWIN_LINEUP);
4279 break;
4280
4281 case SB_LINEDOWN:
4282 vEvent.SetEventType(wxEVT_SCROLLWIN_LINEDOWN);
4283 break;
4284
4285 case SB_PAGEUP:
4286 vEvent.SetEventType(wxEVT_SCROLLWIN_PAGEUP);
4287 break;
4288
4289 case SB_PAGEDOWN:
4290 vEvent.SetEventType(wxEVT_SCROLLWIN_PAGEDOWN);
4291 break;
4292
4293 case SB_SLIDERPOSITION:
4294 vEvent.SetEventType(wxEVT_SCROLLWIN_THUMBRELEASE);
4295 break;
4296
4297 case SB_SLIDERTRACK:
4298 vEvent.SetEventType(wxEVT_SCROLLWIN_THUMBTRACK);
4299 break;
4300
4301 default:
4302 return false;
4303 }
4304 return GetEventHandler()->ProcessEvent(vEvent);
4305 } // end of wxWindowOS2::OS2OnScroll
4306
4307 void wxWindowOS2::MoveChildren(
4308 int nDiff
4309 )
4310 {
4311 //
4312 // We want to handle top levels ourself, manually
4313 //
4314 if (!IsTopLevel() && GetAutoLayout())
4315 {
4316 Layout();
4317 }
4318 else
4319 {
4320 SWP vSwp;
4321
4322 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
4323 node;
4324 node = node->GetNext())
4325 {
4326 wxWindow* pWin = node->GetData();
4327
4328 ::WinQueryWindowPos( GetHwndOf(pWin)
4329 ,&vSwp
4330 );
4331 // Actually, only move children that already are placed on the
4332 // frame, not ones which are still at wxDefaultCoord.
4333 if (vSwp.y == wxDefaultCoord)
4334 continue;
4335 if (pWin->IsKindOf(CLASSINFO(wxControl)))
4336 {
4337 wxControl* pCtrl;
4338
4339 //
4340 // Must deal with controls that have margins like ENTRYFIELD. The SWP
4341 // struct of such a control will have and origin offset from its intended
4342 // position by the width of the margins.
4343 //
4344 pCtrl = wxDynamicCast(pWin, wxControl);
4345 vSwp.y -= pCtrl->GetYComp();
4346 vSwp.x -= pCtrl->GetXComp();
4347 }
4348 ::WinSetWindowPos( GetHwndOf(pWin)
4349 ,HWND_TOP
4350 ,vSwp.x
4351 ,vSwp.y - nDiff
4352 ,vSwp.cx
4353 ,vSwp.cy
4354 ,SWP_MOVE
4355 );
4356 ::WinQueryWindowPos(GetHwndOf(pWin), pWin->GetSwp());
4357 if (pWin->IsKindOf(CLASSINFO(wxRadioBox)))
4358 {
4359 wxRadioBox* pRadioBox;
4360
4361 pRadioBox = wxDynamicCast(pWin, wxRadioBox);
4362 pRadioBox->AdjustButtons( (int)vSwp.x
4363 ,(int)vSwp.y - nDiff
4364 ,(int)vSwp.cx
4365 ,(int)vSwp.cy
4366 ,pRadioBox->GetSizeFlags()
4367 );
4368 }
4369 if (pWin->IsKindOf(CLASSINFO(wxSlider)))
4370 {
4371 wxSlider* pSlider;
4372
4373 pSlider = wxDynamicCast(pWin, wxSlider);
4374 pSlider->AdjustSubControls( (int)vSwp.x
4375 ,(int)vSwp.y - nDiff
4376 ,(int)vSwp.cx
4377 ,(int)vSwp.cy
4378 ,(int)pSlider->GetSizeFlags()
4379 );
4380 }
4381 }
4382 }
4383 Refresh();
4384 } // end of wxWindowOS2::MoveChildren
4385
4386 //
4387 // Getting the Y position for a window, like a control, is a real
4388 // pain. There are three sitatuions we must deal with in determining
4389 // the OS2 to wxWidgets Y coordinate.
4390 //
4391 // 1) The controls are created in a dialog.
4392 // This is the easiest since a dialog is created with its original
4393 // size so the standard: Y = ParentHeight - (Y + ControlHeight);
4394 //
4395 // 2) The controls are direct children of a frame
4396 // In this instance the controls are actually children of the Frame's
4397 // client. During creation the frame's client resizes several times
4398 // during creation of the status bar and toolbars. The CFrame class
4399 // will take care of this using its AlterChildPos proc.
4400 //
4401 // 3) The controls are children of a panel, which in turn is a child of
4402 // a frame.
4403 // The panel may be one of many, in which case the same treatment
4404 // as 1 applies. It may be the only child, though.
4405 // This is the nastiest case. A panel is created as the only child of
4406 // the frame and as such, when a frame has only one child, the child is
4407 // expanded to fit the entire client area of the frame. Because the
4408 // controls are created BEFORE this occurs their positions are totally
4409 // whacked and any call to WinQueryWindowPos will return invalid
4410 // coordinates. So for this situation we have to compare the size of
4411 // the panel at control creation time with that of the frame client. If
4412 // they are the same we can use the standard Y position equation. If
4413 // not, then we must use the Frame Client's dimensions to position them
4414 // as that will be the eventual size of the panel after the frame resizes
4415 // it!
4416 //
4417 int wxWindowOS2::GetOS2ParentHeight( wxWindowOS2* pParent )
4418 {
4419 //
4420 // Case 1
4421 //
4422 if (pParent->IsKindOf(CLASSINFO(wxDialog)))
4423 return(pParent->GetClientSize().y);
4424
4425 //
4426 // Case 2 -- if we are one of the separately built standard Frame
4427 // children, like a statusbar, menubar, or toolbar we want to
4428 // use the frame, itself, for positioning. Otherwise we are
4429 // child window and want to use the Frame's client.
4430 //
4431 else if (pParent->IsKindOf(CLASSINFO(wxFrame)))
4432 {
4433 if (IsKindOf(CLASSINFO(wxStatusBar)) ||
4434 IsKindOf(CLASSINFO(wxMenuBar)) ||
4435 IsKindOf(CLASSINFO(wxToolBar))
4436 )
4437 {
4438 if (IsKindOf(CLASSINFO(wxToolBar)))
4439 {
4440 wxFrame* pFrame = wxDynamicCast(GetParent(), wxFrame);
4441
4442 if (pFrame->GetToolBar() == this)
4443 return(pParent->GetSize().y);
4444 else
4445 return(pParent->GetClientSize().y);
4446 }
4447 else
4448 return(pParent->GetSize().y);
4449 }
4450 else
4451 return(pParent->GetClientSize().y);
4452 }
4453 //
4454 // Case -- this is for any window that is the sole child of a Frame.
4455 // The grandparent must exist and it must be of type CFrame
4456 // and it's height must be different. Otherwise the standard
4457 // applies.
4458 //
4459 // else
4460 // {
4461
4462 return(pParent->GetClientSize().y);
4463
4464 // }
4465 } // end of wxWindowOS2::GetOS2ParentHeight
4466
4467 //
4468 // OS/2 needs a lot extra manipulation to deal with layouts
4469 // for canvas windows, particularly scrolled ones.
4470 //
4471 wxWindowCreationHook::wxWindowCreationHook(
4472 wxWindow* pWinBeingCreated
4473 )
4474 {
4475 gpWinBeingCreated = pWinBeingCreated;
4476 } // end of wxWindowCreationHook::wxWindowCreationHook
4477
4478 wxWindowCreationHook::~wxWindowCreationHook()
4479 {
4480 gpWinBeingCreated = NULL;
4481 } // end of wxWindowCreationHook::~wxWindowCreationHook
4482
4483 // ===========================================================================
4484 // global functions
4485 // ===========================================================================
4486
4487 void wxGetCharSize(
4488 WXHWND hWnd
4489 , int* pX
4490 , int* pY
4491 ,wxFont* WXUNUSED(pTheFont)
4492 )
4493 {
4494 FONTMETRICS vFM;
4495 HPS hPS;
4496 BOOL rc;
4497
4498 hPS =::WinGetPS(hWnd);
4499
4500 rc = ::GpiQueryFontMetrics(hPS, sizeof(FONTMETRICS), &vFM);
4501 if (rc)
4502 {
4503 if (pX)
4504 *pX = vFM.lAveCharWidth;
4505 if (pY)
4506 *pY = vFM.lEmHeight + vFM.lExternalLeading;
4507 }
4508 else
4509 {
4510 if (pX)
4511 *pX = 10;
4512 if (pY)
4513 *pY = 15;
4514 }
4515 ::WinReleasePS(hPS);
4516 } // end of wxGetCharSize
4517
4518 //
4519 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
4520 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
4521 //
4522 int wxCharCodeOS2ToWX(
4523 int nKeySym
4524 )
4525 {
4526 int nId = 0;
4527
4528 switch (nKeySym)
4529 {
4530 case VK_BACKTAB: nId = WXK_BACK; break;
4531 case VK_TAB: nId = WXK_TAB; break;
4532 case VK_CLEAR: nId = WXK_CLEAR; break;
4533 case VK_ENTER: nId = WXK_RETURN; break;
4534 case VK_SHIFT: nId = WXK_SHIFT; break;
4535 case VK_CTRL: nId = WXK_CONTROL; break;
4536 case VK_PAUSE: nId = WXK_PAUSE; break;
4537 case VK_SPACE: nId = WXK_SPACE; break;
4538 case VK_PAGEUP: nId = WXK_PRIOR; break;
4539 case VK_PAGEDOWN: nId = WXK_NEXT; break;
4540 case VK_ESC: nId = WXK_ESCAPE; break;
4541 case VK_END: nId = WXK_END; break;
4542 case VK_HOME : nId = WXK_HOME; break;
4543 case VK_LEFT : nId = WXK_LEFT; break;
4544 case VK_UP: nId = WXK_UP; break;
4545 case VK_RIGHT: nId = WXK_RIGHT; break;
4546 case VK_DOWN : nId = WXK_DOWN; break;
4547 case VK_PRINTSCRN: nId = WXK_PRINT; break;
4548 case VK_INSERT: nId = WXK_INSERT; break;
4549 case VK_DELETE: nId = WXK_DELETE; break;
4550 case VK_CAPSLOCK: nId = WXK_CAPITAL; break;
4551 case VK_F1: nId = WXK_F1; break;
4552 case VK_F2: nId = WXK_F2; break;
4553 case VK_F3: nId = WXK_F3; break;
4554 case VK_F4: nId = WXK_F4; break;
4555 case VK_F5: nId = WXK_F5; break;
4556 case VK_F6: nId = WXK_F6; break;
4557 case VK_F7: nId = WXK_F7; break;
4558 case VK_F8: nId = WXK_F8; break;
4559 case VK_F9: nId = WXK_F9; break;
4560 case VK_F10: nId = WXK_F10; break;
4561 case VK_F11: nId = WXK_F11; break;
4562 case VK_F12: nId = WXK_F12; break;
4563 case VK_F13: nId = WXK_F13; break;
4564 case VK_F14: nId = WXK_F14; break;
4565 case VK_F15: nId = WXK_F15; break;
4566 case VK_F16: nId = WXK_F16; break;
4567 case VK_F17: nId = WXK_F17; break;
4568 case VK_F18: nId = WXK_F18; break;
4569 case VK_F19: nId = WXK_F19; break;
4570 case VK_F20: nId = WXK_F20; break;
4571 case VK_F21: nId = WXK_F21; break;
4572 case VK_F22: nId = WXK_F22; break;
4573 case VK_F23: nId = WXK_F23; break;
4574 case VK_F24: nId = WXK_F24; break;
4575 case VK_OEM_1: nId = ';'; break;
4576 case VK_OEM_PLUS: nId = '+'; break;
4577 case VK_OEM_COMMA: nId = ','; break;
4578 case VK_OEM_MINUS: nId = '-'; break;
4579 case VK_OEM_PERIOD: nId = '.'; break;
4580 case VK_OEM_2: nId = '/'; break;
4581 case VK_OEM_3: nId = '~'; break;
4582 case VK_OEM_4: nId = '['; break;
4583 case VK_OEM_5: nId = '\\'; break;
4584 case VK_OEM_6: nId = ']'; break;
4585 case VK_OEM_7: nId = '\''; break;
4586 case VK_NUMLOCK: nId = WXK_NUMLOCK; break;
4587 case VK_SCRLLOCK: nId = WXK_SCROLL; break;
4588 default:
4589 {
4590 return 0;
4591 }
4592 }
4593 return nId;
4594 } // end of wxCharCodeOS2ToWX
4595
4596 int wxCharCodeWXToOS2( int nId,
4597 bool* bIsVirtual)
4598 {
4599 int nKeySym = 0;
4600
4601 *bIsVirtual = true;
4602 switch (nId)
4603 {
4604 case WXK_CLEAR: nKeySym = VK_CLEAR; break;
4605 case WXK_SHIFT: nKeySym = VK_SHIFT; break;
4606 case WXK_CONTROL: nKeySym = VK_CTRL; break;
4607 case WXK_PAUSE: nKeySym = VK_PAUSE; break;
4608 case WXK_PRIOR: nKeySym = VK_PAGEUP; break;
4609 case WXK_NEXT : nKeySym = VK_PAGEDOWN; break;
4610 case WXK_END: nKeySym = VK_END; break;
4611 case WXK_HOME : nKeySym = VK_HOME; break;
4612 case WXK_LEFT : nKeySym = VK_LEFT; break;
4613 case WXK_UP: nKeySym = VK_UP; break;
4614 case WXK_RIGHT: nKeySym = VK_RIGHT; break;
4615 case WXK_DOWN : nKeySym = VK_DOWN; break;
4616 case WXK_PRINT: nKeySym = VK_PRINTSCRN; break;
4617 case WXK_INSERT: nKeySym = VK_INSERT; break;
4618 case WXK_DELETE: nKeySym = VK_DELETE; break;
4619 case WXK_F1: nKeySym = VK_F1; break;
4620 case WXK_F2: nKeySym = VK_F2; break;
4621 case WXK_F3: nKeySym = VK_F3; break;
4622 case WXK_F4: nKeySym = VK_F4; break;
4623 case WXK_F5: nKeySym = VK_F5; break;
4624 case WXK_F6: nKeySym = VK_F6; break;
4625 case WXK_F7: nKeySym = VK_F7; break;
4626 case WXK_F8: nKeySym = VK_F8; break;
4627 case WXK_F9: nKeySym = VK_F9; break;
4628 case WXK_F10: nKeySym = VK_F10; break;
4629 case WXK_F11: nKeySym = VK_F11; break;
4630 case WXK_F12: nKeySym = VK_F12; break;
4631 case WXK_F13: nKeySym = VK_F13; break;
4632 case WXK_F14: nKeySym = VK_F14; break;
4633 case WXK_F15: nKeySym = VK_F15; break;
4634 case WXK_F16: nKeySym = VK_F16; break;
4635 case WXK_F17: nKeySym = VK_F17; break;
4636 case WXK_F18: nKeySym = VK_F18; break;
4637 case WXK_F19: nKeySym = VK_F19; break;
4638 case WXK_F20: nKeySym = VK_F20; break;
4639 case WXK_F21: nKeySym = VK_F21; break;
4640 case WXK_F22: nKeySym = VK_F22; break;
4641 case WXK_F23: nKeySym = VK_F23; break;
4642 case WXK_F24: nKeySym = VK_F24; break;
4643 case WXK_NUMLOCK: nKeySym = VK_NUMLOCK; break;
4644 case WXK_SCROLL: nKeySym = VK_SCRLLOCK; break;
4645 default:
4646 {
4647 *bIsVirtual = false;
4648 nKeySym = nId;
4649 break;
4650 }
4651 }
4652 return nKeySym;
4653 } // end of wxCharCodeWXToOS2
4654
4655 wxWindow* wxGetActiveWindow()
4656 {
4657 HWND hWnd = ::WinQueryActiveWindow(HWND_DESKTOP);
4658
4659 if (hWnd != 0)
4660 {
4661 return wxFindWinFromHandle((WXHWND)hWnd);
4662 }
4663 return NULL;
4664 } // end of wxGetActiveWindow
4665
4666 #ifdef __WXDEBUG__
4667 const wxChar* wxGetMessageName( int nMessage )
4668 {
4669 switch (nMessage)
4670 {
4671 case 0x0000: return wxT("WM_NULL");
4672 case 0x0001: return wxT("WM_CREATE");
4673 case 0x0002: return wxT("WM_DESTROY");
4674 case 0x0004: return wxT("WM_ENABLE");
4675 case 0x0005: return wxT("WM_SHOW");
4676 case 0x0006: return wxT("WM_MOVE");
4677 case 0x0007: return wxT("WM_SIZE");
4678 case 0x0008: return wxT("WM_ADJUSTWINDOWPOS");
4679 case 0x0009: return wxT("WM_CALCVALIDRECTS");
4680 case 0x000A: return wxT("WM_SETWINDOWPARAMS");
4681 case 0x000B: return wxT("WM_QUERYWINDOWPARAMS");
4682 case 0x000C: return wxT("WM_HITTEST");
4683 case 0x000D: return wxT("WM_ACTIVATE");
4684 case 0x000F: return wxT("WM_SETFOCUS");
4685 case 0x0010: return wxT("WM_SETSELECTION");
4686 case 0x0011: return wxT("WM_PPAINT");
4687 case 0x0012: return wxT("WM_PSETFOCUS");
4688 case 0x0013: return wxT("WM_PSYSCOLORCHANGE");
4689 case 0x0014: return wxT("WM_PSIZE");
4690 case 0x0015: return wxT("WM_PACTIVATE");
4691 case 0x0016: return wxT("WM_PCONTROL");
4692 case 0x0020: return wxT("WM_COMMAND");
4693 case 0x0021: return wxT("WM_SYSCOMMAND");
4694 case 0x0022: return wxT("WM_HELP");
4695 case 0x0023: return wxT("WM_PAINT");
4696 case 0x0024: return wxT("WM_TIMER");
4697 case 0x0025: return wxT("WM_SEM1");
4698 case 0x0026: return wxT("WM_SEM2");
4699 case 0x0027: return wxT("WM_SEM3");
4700 case 0x0028: return wxT("WM_SEM4");
4701 case 0x0029: return wxT("WM_CLOSE");
4702 case 0x002A: return wxT("WM_QUIT");
4703 case 0x002B: return wxT("WM_SYSCOLORCHANGE");
4704 case 0x002D: return wxT("WM_SYSVALUECHANGE");
4705 case 0x002E: return wxT("WM_APPTERMINATENOTIFY");
4706 case 0x002F: return wxT("WM_PRESPARAMCHANGED");
4707 // Control notification messages
4708 case 0x0030: return wxT("WM_CONTROL");
4709 case 0x0031: return wxT("WM_VSCROLL");
4710 case 0x0032: return wxT("WM_HSCROLL");
4711 case 0x0033: return wxT("WM_INITMENU");
4712 case 0x0034: return wxT("WM_MENUSELECT");
4713 case 0x0035: return wxT("WM_MENUSEND");
4714 case 0x0036: return wxT("WM_DRAWITEM");
4715 case 0x0037: return wxT("WM_MEASUREITEM");
4716 case 0x0038: return wxT("WM_CONTROLPOINTER");
4717 case 0x003A: return wxT("WM_QUERYDLGCODE");
4718 case 0x003B: return wxT("WM_INITDLG");
4719 case 0x003C: return wxT("WM_SUBSTITUTESTRING");
4720 case 0x003D: return wxT("WM_MATCHMNEMONIC");
4721 case 0x003E: return wxT("WM_SAVEAPPLICATION");
4722 case 0x0129: return wxT("WM_CTLCOLORCHANGE");
4723 case 0x0130: return wxT("WM_QUERYCTLTYPE");
4724 // Frame messages
4725 case 0x0040: return wxT("WM_FLASHWINDOW");
4726 case 0x0041: return wxT("WM_FORMATFRAME");
4727 case 0x0042: return wxT("WM_UPDATEFRAME");
4728 case 0x0043: return wxT("WM_FOCUSCHANGE");
4729 case 0x0044: return wxT("WM_SETBORDERSIZE");
4730 case 0x0045: return wxT("WM_TRACKFRAME");
4731 case 0x0046: return wxT("WM_MINMAXFRAME");
4732 case 0x0047: return wxT("WM_SETICON");
4733 case 0x0048: return wxT("WM_QUERYICON");
4734 case 0x0049: return wxT("WM_SETACCELTABLE");
4735 case 0x004A: return wxT("WM_QUERYACCELTABLE");
4736 case 0x004B: return wxT("WM_TRANSLATEACCEL");
4737 case 0x004C: return wxT("WM_QUERYTRACKINFO");
4738 case 0x004D: return wxT("WM_QUERYBORDERSIZE");
4739 case 0x004E: return wxT("WM_NEXTMENU");
4740 case 0x004F: return wxT("WM_ERASEBACKGROUND");
4741 case 0x0050: return wxT("WM_QUERYFRAMEINFO");
4742 case 0x0051: return wxT("WM_QUERYFOCUSCHAIN");
4743 case 0x0052: return wxT("WM_OWNERPOSCHANGE");
4744 case 0x0053: return wxT("WM_CACLFRAMERECT");
4745 case 0x0055: return wxT("WM_WINDOWPOSCHANGED");
4746 case 0x0056: return wxT("WM_ADJUSTFRAMEPOS");
4747 case 0x0059: return wxT("WM_QUERYFRAMECTLCOUNT");
4748 case 0x005B: return wxT("WM_QUERYHELPINFO");
4749 case 0x005C: return wxT("WM_SETHELPINFO");
4750 case 0x005D: return wxT("WM_ERROR");
4751 case 0x005E: return wxT("WM_REALIZEPALETTE");
4752 // Clipboard messages
4753 case 0x0060: return wxT("WM_RENDERFMT");
4754 case 0x0061: return wxT("WM_RENDERALLFMTS");
4755 case 0x0062: return wxT("WM_DESTROYCLIPBOARD");
4756 case 0x0063: return wxT("WM_PAINTCLIPBOARD");
4757 case 0x0064: return wxT("WM_SIZECLIPBOARD");
4758 case 0x0065: return wxT("WM_HSCROLLCLIPBOARD");
4759 case 0x0066: return wxT("WM_VSCROLLCLIPBOARD");
4760 case 0x0067: return wxT("WM_DRAWCLIPBOARD");
4761 // mouse messages
4762 case 0x0070: return wxT("WM_MOUSEMOVE");
4763 case 0x0071: return wxT("WM_BUTTON1DOWN");
4764 case 0x0072: return wxT("WM_BUTTON1UP");
4765 case 0x0073: return wxT("WM_BUTTON1DBLCLK");
4766 case 0x0074: return wxT("WM_BUTTON2DOWN");
4767 case 0x0075: return wxT("WM_BUTTON2UP");
4768 case 0x0076: return wxT("WM_BUTTON2DBLCLK");
4769 case 0x0077: return wxT("WM_BUTTON3DOWN");
4770 case 0x0078: return wxT("WM_BUTTON3UP");
4771 case 0x0079: return wxT("WM_BUTTON3DBLCLK");
4772 case 0x007D: return wxT("WM_MOUSEMAP");
4773 case 0x007E: return wxT("WM_VRNDISABLED");
4774 case 0x007F: return wxT("WM_VRNENABLED");
4775 case 0x0410: return wxT("WM_CHORD");
4776 case 0x0411: return wxT("WM_BUTTON1MOTIONSTART");
4777 case 0x0412: return wxT("WM_BUTTON1MOTIONEND");
4778 case 0x0413: return wxT("WM_BUTTON1CLICK");
4779 case 0x0414: return wxT("WM_BUTTON2MOTIONSTART");
4780 case 0x0415: return wxT("WM_BUTTON2MOTIONEND");
4781 case 0x0416: return wxT("WM_BUTTON2CLICK");
4782 case 0x0417: return wxT("WM_BUTTON3MOTIONSTART");
4783 case 0x0418: return wxT("WM_BUTTON3MOTIONEND");
4784 case 0x0419: return wxT("WM_BUTTON3CLICK");
4785 case 0x0420: return wxT("WM_BEGINDRAG");
4786 case 0x0421: return wxT("WM_ENDDRAG");
4787 case 0x0422: return wxT("WM_SINGLESELECT");
4788 case 0x0423: return wxT("WM_OPEN");
4789 case 0x0424: return wxT("WM_CONTEXTMENU");
4790 case 0x0425: return wxT("WM_CONTEXTHELP");
4791 case 0x0426: return wxT("WM_TEXTEDIT");
4792 case 0x0427: return wxT("WM_BEGINSELECT");
4793 case 0x0228: return wxT("WM_ENDSELECT");
4794 case 0x0429: return wxT("WM_PICKUP");
4795 case 0x04C0: return wxT("WM_PENFIRST");
4796 case 0x04FF: return wxT("WM_PENLAST");
4797 case 0x0500: return wxT("WM_MMPMFIRST");
4798 case 0x05FF: return wxT("WM_MMPMLAST");
4799 case 0x0600: return wxT("WM_STDDLGFIRST");
4800 case 0x06FF: return wxT("WM_STDDLGLAST");
4801 case 0x0BD0: return wxT("WM_BIDI_FIRST");
4802 case 0x0BFF: return wxT("WM_BIDI_LAST");
4803 // keyboard input
4804 case 0x007A: return wxT("WM_CHAR");
4805 case 0x007B: return wxT("WM_VIOCHAR");
4806 // DDE messages
4807 case 0x00A0: return wxT("WM_DDE_INITIATE");
4808 case 0x00A1: return wxT("WM_DDE_REQUEST");
4809 case 0x00A2: return wxT("WM_DDE_ACK");
4810 case 0x00A3: return wxT("WM_DDE_DATA");
4811 case 0x00A4: return wxT("WM_DDE_ADVISE");
4812 case 0x00A5: return wxT("WM_DDE_UNADVISE");
4813 case 0x00A6: return wxT("WM_DDE_POKE");
4814 case 0x00A7: return wxT("WM_DDE_EXECUTE");
4815 case 0x00A8: return wxT("WM_DDE_TERMINATE");
4816 case 0x00A9: return wxT("WM_DDE_INITIATEACK");
4817 case 0x00AF: return wxT("WM_DDE_LAST");
4818 // Buttons
4819 case 0x0120: return wxT("BM_CLICK");
4820 case 0x0121: return wxT("BM_QUERYCHECKINDEX");
4821 case 0x0122: return wxT("BM_QUERYHILITE");
4822 case 0x0123: return wxT("BM_SETHILITE");
4823 case 0x0124: return wxT("BM_QUERYCHECK");
4824 case 0x0125: return wxT("BM_SETCHECK");
4825 case 0x0126: return wxT("BM_SETDEFAULT");
4826 case 0x0128: return wxT("BM_AUTOSIZE");
4827 // Combo boxes
4828 case 0x029A: return wxT("CBID_LIST");
4829 case 0x029B: return wxT("CBID_EDIT");
4830 case 0x0170: return wxT("CBM_SHOWLIST");
4831 case 0x0171: return wxT("CBM_HILITE");
4832 case 0x0172: return wxT("CBM_ISLISTSHOWING");
4833 // Edit fields
4834 case 0x0140: return wxT("EM_QUERYCHANGED");
4835 case 0x0141: return wxT("EM_QUERYSEL");
4836 case 0x0142: return wxT("EM_SETSEL");
4837 case 0x0143: return wxT("EM_SETTEXTLIMIT");
4838 case 0x0144: return wxT("EM_CUT");
4839 case 0x0145: return wxT("EM_COPY");
4840 case 0x0146: return wxT("EM_CLEAR");
4841 case 0x0147: return wxT("EM_PASTE");
4842 case 0x0148: return wxT("EM_QUERYFIRSTCHAR");
4843 case 0x0149: return wxT("EM_SETFIRSTCHAR");
4844 case 0x014A: return wxT("EM_QUERYREADONLY");
4845 case 0x014B: return wxT("EM_SETREADONLY");
4846 case 0x014C: return wxT("EM_SETINSERTMODE");
4847 // Listboxes
4848 case 0x0160: return wxT("LM_QUERYITEMCOUNT");
4849 case 0x0161: return wxT("LM_INSERTITEM");
4850 case 0x0162: return wxT("LM_SETOPENINDEX");
4851 case 0x0163: return wxT("LM_DELETEITEM");
4852 case 0x0164: return wxT("LM_SELECTITEM");
4853 case 0x0165: return wxT("LM_QUERYSELECTION");
4854 case 0x0166: return wxT("LM_SETITEMTEXT");
4855 case 0x0167: return wxT("LM_QUERYITEMTEXTLENGTH");
4856 case 0x0168: return wxT("LM_QUERYITEMTEXT");
4857 case 0x0169: return wxT("LM_SETITEMHANDLE");
4858 case 0x016A: return wxT("LM_QUERYITEMHANDLE");
4859 case 0x016B: return wxT("LM_SEARCHSTRING");
4860 case 0x016C: return wxT("LM_SETITEMHEIGHT");
4861 case 0x016D: return wxT("LM_QUERYTOPINDEX");
4862 case 0x016E: return wxT("LM_DELETEALL");
4863 case 0x016F: return wxT("LM_INSERTMULITEMS");
4864 case 0x0660: return wxT("LM_SETITEMWIDTH");
4865 // Menus
4866 case 0x0180: return wxT("MM_INSERTITEM");
4867 case 0x0181: return wxT("MM_DELETEITEM");
4868 case 0x0182: return wxT("MM_QUERYITEM");
4869 case 0x0183: return wxT("MM_SETITEM");
4870 case 0x0184: return wxT("MM_QUERYITEMCOUNT");
4871 case 0x0185: return wxT("MM_STARTMENUMODE");
4872 case 0x0186: return wxT("MM_ENDMENUMODE");
4873 case 0x0188: return wxT("MM_REMOVEITEM");
4874 case 0x0189: return wxT("MM_SELECTITEM");
4875 case 0x018A: return wxT("MM_QUERYSELITEMID");
4876 case 0x018B: return wxT("MM_QUERYITEMTEXT");
4877 case 0x018C: return wxT("MM_QUERYITEMTEXTLENGTH");
4878 case 0x018D: return wxT("MM_SETITEMHANDLE");
4879 case 0x018E: return wxT("MM_SETITEMTEXT");
4880 case 0x018F: return wxT("MM_ITEMPOSITIONFROMID");
4881 case 0x0190: return wxT("MM_ITEMIDFROMPOSITION");
4882 case 0x0191: return wxT("MM_QUERYITEMATTR");
4883 case 0x0192: return wxT("MM_SETITEMATTR");
4884 case 0x0193: return wxT("MM_ISITEMVALID");
4885 case 0x0194: return wxT("MM_QUERYITEMRECT");
4886 case 0x0431: return wxT("MM_QUERYDEFAULTITEMID");
4887 case 0x0432: return wxT("MM_SETDEFAULTITEMID");
4888 // Scrollbars
4889 case 0x01A0: return wxT("SBM_SETSCROLLBAR");
4890 case 0x01A1: return wxT("SBM_SETPOS");
4891 case 0x01A2: return wxT("SBM_QUERYPOS");
4892 case 0x01A3: return wxT("SBM_QUERYRANGE");
4893 case 0x01A6: return wxT("SBM_SETTHUMBSIZE");
4894
4895 // Help messages
4896 case 0x0F00: return wxT("WM_HELPBASE");
4897 case 0x0FFF: return wxT("WM_HELPTOP");
4898 // Beginning of user defined messages
4899 case 0x1000: return wxT("WM_USER");
4900
4901 // wxWidgets user defined types
4902
4903 // listview
4904 // case 0x1000 + 0: return wxT("LVM_GETBKCOLOR");
4905 case 0x1000 + 1: return wxT("LVM_SETBKCOLOR");
4906 case 0x1000 + 2: return wxT("LVM_GETIMAGELIST");
4907 case 0x1000 + 3: return wxT("LVM_SETIMAGELIST");
4908 case 0x1000 + 4: return wxT("LVM_GETITEMCOUNT");
4909 case 0x1000 + 5: return wxT("LVM_GETITEMA");
4910 case 0x1000 + 75: return wxT("LVM_GETITEMW");
4911 case 0x1000 + 6: return wxT("LVM_SETITEMA");
4912 case 0x1000 + 76: return wxT("LVM_SETITEMW");
4913 case 0x1000 + 7: return wxT("LVM_INSERTITEMA");
4914 case 0x1000 + 77: return wxT("LVM_INSERTITEMW");
4915 case 0x1000 + 8: return wxT("LVM_DELETEITEM");
4916 case 0x1000 + 9: return wxT("LVM_DELETEALLITEMS");
4917 case 0x1000 + 10: return wxT("LVM_GETCALLBACKMASK");
4918 case 0x1000 + 11: return wxT("LVM_SETCALLBACKMASK");
4919 case 0x1000 + 12: return wxT("LVM_GETNEXTITEM");
4920 case 0x1000 + 13: return wxT("LVM_FINDITEMA");
4921 case 0x1000 + 83: return wxT("LVM_FINDITEMW");
4922 case 0x1000 + 14: return wxT("LVM_GETITEMRECT");
4923 case 0x1000 + 15: return wxT("LVM_SETITEMPOSITION");
4924 case 0x1000 + 16: return wxT("LVM_GETITEMPOSITION");
4925 case 0x1000 + 17: return wxT("LVM_GETSTRINGWIDTHA");
4926 case 0x1000 + 87: return wxT("LVM_GETSTRINGWIDTHW");
4927 case 0x1000 + 18: return wxT("LVM_HITTEST");
4928 case 0x1000 + 19: return wxT("LVM_ENSUREVISIBLE");
4929 case 0x1000 + 20: return wxT("LVM_SCROLL");
4930 case 0x1000 + 21: return wxT("LVM_REDRAWITEMS");
4931 case 0x1000 + 22: return wxT("LVM_ARRANGE");
4932 case 0x1000 + 23: return wxT("LVM_EDITLABELA");
4933 case 0x1000 + 118: return wxT("LVM_EDITLABELW");
4934 case 0x1000 + 24: return wxT("LVM_GETEDITCONTROL");
4935 case 0x1000 + 25: return wxT("LVM_GETCOLUMNA");
4936 case 0x1000 + 95: return wxT("LVM_GETCOLUMNW");
4937 case 0x1000 + 26: return wxT("LVM_SETCOLUMNA");
4938 case 0x1000 + 96: return wxT("LVM_SETCOLUMNW");
4939 case 0x1000 + 27: return wxT("LVM_INSERTCOLUMNA");
4940 case 0x1000 + 97: return wxT("LVM_INSERTCOLUMNW");
4941 case 0x1000 + 28: return wxT("LVM_DELETECOLUMN");
4942 case 0x1000 + 29: return wxT("LVM_GETCOLUMNWIDTH");
4943 case 0x1000 + 30: return wxT("LVM_SETCOLUMNWIDTH");
4944 case 0x1000 + 31: return wxT("LVM_GETHEADER");
4945 case 0x1000 + 33: return wxT("LVM_CREATEDRAGIMAGE");
4946 case 0x1000 + 34: return wxT("LVM_GETVIEWRECT");
4947 case 0x1000 + 35: return wxT("LVM_GETTEXTCOLOR");
4948 case 0x1000 + 36: return wxT("LVM_SETTEXTCOLOR");
4949 case 0x1000 + 37: return wxT("LVM_GETTEXTBKCOLOR");
4950 case 0x1000 + 38: return wxT("LVM_SETTEXTBKCOLOR");
4951 case 0x1000 + 39: return wxT("LVM_GETTOPINDEX");
4952 case 0x1000 + 40: return wxT("LVM_GETCOUNTPERPAGE");
4953 case 0x1000 + 41: return wxT("LVM_GETORIGIN");
4954 case 0x1000 + 42: return wxT("LVM_UPDATE");
4955 case 0x1000 + 43: return wxT("LVM_SETITEMSTATE");
4956 case 0x1000 + 44: return wxT("LVM_GETITEMSTATE");
4957 case 0x1000 + 45: return wxT("LVM_GETITEMTEXTA");
4958 case 0x1000 + 115: return wxT("LVM_GETITEMTEXTW");
4959 case 0x1000 + 46: return wxT("LVM_SETITEMTEXTA");
4960 case 0x1000 + 116: return wxT("LVM_SETITEMTEXTW");
4961 case 0x1000 + 47: return wxT("LVM_SETITEMCOUNT");
4962 case 0x1000 + 48: return wxT("LVM_SORTITEMS");
4963 case 0x1000 + 49: return wxT("LVM_SETITEMPOSITION32");
4964 case 0x1000 + 50: return wxT("LVM_GETSELECTEDCOUNT");
4965 case 0x1000 + 51: return wxT("LVM_GETITEMSPACING");
4966 case 0x1000 + 52: return wxT("LVM_GETISEARCHSTRINGA");
4967 case 0x1000 + 117: return wxT("LVM_GETISEARCHSTRINGW");
4968 case 0x1000 + 53: return wxT("LVM_SETICONSPACING");
4969 case 0x1000 + 54: return wxT("LVM_SETEXTENDEDLISTVIEWSTYLE");
4970 case 0x1000 + 55: return wxT("LVM_GETEXTENDEDLISTVIEWSTYLE");
4971 case 0x1000 + 56: return wxT("LVM_GETSUBITEMRECT");
4972 case 0x1000 + 57: return wxT("LVM_SUBITEMHITTEST");
4973 case 0x1000 + 58: return wxT("LVM_SETCOLUMNORDERARRAY");
4974 case 0x1000 + 59: return wxT("LVM_GETCOLUMNORDERARRAY");
4975 case 0x1000 + 60: return wxT("LVM_SETHOTITEM");
4976 case 0x1000 + 61: return wxT("LVM_GETHOTITEM");
4977 case 0x1000 + 62: return wxT("LVM_SETHOTCURSOR");
4978 case 0x1000 + 63: return wxT("LVM_GETHOTCURSOR");
4979 case 0x1000 + 64: return wxT("LVM_APPROXIMATEVIEWRECT");
4980 case 0x1000 + 65: return wxT("LVM_SETWORKAREA");
4981
4982 // tree view
4983 case 0x1100 + 0: return wxT("TVM_INSERTITEMA");
4984 case 0x1100 + 50: return wxT("TVM_INSERTITEMW");
4985 case 0x1100 + 1: return wxT("TVM_DELETEITEM");
4986 case 0x1100 + 2: return wxT("TVM_EXPAND");
4987 case 0x1100 + 4: return wxT("TVM_GETITEMRECT");
4988 case 0x1100 + 5: return wxT("TVM_GETCOUNT");
4989 case 0x1100 + 6: return wxT("TVM_GETINDENT");
4990 case 0x1100 + 7: return wxT("TVM_SETINDENT");
4991 case 0x1100 + 8: return wxT("TVM_GETIMAGELIST");
4992 case 0x1100 + 9: return wxT("TVM_SETIMAGELIST");
4993 case 0x1100 + 10: return wxT("TVM_GETNEXTITEM");
4994 case 0x1100 + 11: return wxT("TVM_SELECTITEM");
4995 case 0x1100 + 12: return wxT("TVM_GETITEMA");
4996 case 0x1100 + 62: return wxT("TVM_GETITEMW");
4997 case 0x1100 + 13: return wxT("TVM_SETITEMA");
4998 case 0x1100 + 63: return wxT("TVM_SETITEMW");
4999 case 0x1100 + 14: return wxT("TVM_EDITLABELA");
5000 case 0x1100 + 65: return wxT("TVM_EDITLABELW");
5001 case 0x1100 + 15: return wxT("TVM_GETEDITCONTROL");
5002 case 0x1100 + 16: return wxT("TVM_GETVISIBLECOUNT");
5003 case 0x1100 + 17: return wxT("TVM_HITTEST");
5004 case 0x1100 + 18: return wxT("TVM_CREATEDRAGIMAGE");
5005 case 0x1100 + 19: return wxT("TVM_SORTCHILDREN");
5006 case 0x1100 + 20: return wxT("TVM_ENSUREVISIBLE");
5007 case 0x1100 + 21: return wxT("TVM_SORTCHILDRENCB");
5008 case 0x1100 + 22: return wxT("TVM_ENDEDITLABELNOW");
5009 case 0x1100 + 23: return wxT("TVM_GETISEARCHSTRINGA");
5010 case 0x1100 + 64: return wxT("TVM_GETISEARCHSTRINGW");
5011 case 0x1100 + 24: return wxT("TVM_SETTOOLTIPS");
5012 case 0x1100 + 25: return wxT("TVM_GETTOOLTIPS");
5013
5014 // header
5015 case 0x1200 + 0: return wxT("HDM_GETITEMCOUNT");
5016 case 0x1200 + 1: return wxT("HDM_INSERTITEMA");
5017 case 0x1200 + 10: return wxT("HDM_INSERTITEMW");
5018 case 0x1200 + 2: return wxT("HDM_DELETEITEM");
5019 case 0x1200 + 3: return wxT("HDM_GETITEMA");
5020 case 0x1200 + 11: return wxT("HDM_GETITEMW");
5021 case 0x1200 + 4: return wxT("HDM_SETITEMA");
5022 case 0x1200 + 12: return wxT("HDM_SETITEMW");
5023 case 0x1200 + 5: return wxT("HDM_LAYOUT");
5024 case 0x1200 + 6: return wxT("HDM_HITTEST");
5025 case 0x1200 + 7: return wxT("HDM_GETITEMRECT");
5026 case 0x1200 + 8: return wxT("HDM_SETIMAGELIST");
5027 case 0x1200 + 9: return wxT("HDM_GETIMAGELIST");
5028 case 0x1200 + 15: return wxT("HDM_ORDERTOINDEX");
5029 case 0x1200 + 16: return wxT("HDM_CREATEDRAGIMAGE");
5030 case 0x1200 + 17: return wxT("HDM_GETORDERARRAY");
5031 case 0x1200 + 18: return wxT("HDM_SETORDERARRAY");
5032 case 0x1200 + 19: return wxT("HDM_SETHOTDIVIDER");
5033
5034 // tab control
5035 case 0x1300 + 2: return wxT("TCM_GETIMAGELIST");
5036 case 0x1300 + 3: return wxT("TCM_SETIMAGELIST");
5037 case 0x1300 + 4: return wxT("TCM_GETITEMCOUNT");
5038 case 0x1300 + 5: return wxT("TCM_GETITEMA");
5039 case 0x1300 + 60: return wxT("TCM_GETITEMW");
5040 case 0x1300 + 6: return wxT("TCM_SETITEMA");
5041 case 0x1300 + 61: return wxT("TCM_SETITEMW");
5042 case 0x1300 + 7: return wxT("TCM_INSERTITEMA");
5043 case 0x1300 + 62: return wxT("TCM_INSERTITEMW");
5044 case 0x1300 + 8: return wxT("TCM_DELETEITEM");
5045 case 0x1300 + 9: return wxT("TCM_DELETEALLITEMS");
5046 case 0x1300 + 10: return wxT("TCM_GETITEMRECT");
5047 case 0x1300 + 11: return wxT("TCM_GETCURSEL");
5048 case 0x1300 + 12: return wxT("TCM_SETCURSEL");
5049 case 0x1300 + 13: return wxT("TCM_HITTEST");
5050 case 0x1300 + 14: return wxT("TCM_SETITEMEXTRA");
5051 case 0x1300 + 40: return wxT("TCM_ADJUSTRECT");
5052 case 0x1300 + 41: return wxT("TCM_SETITEMSIZE");
5053 case 0x1300 + 42: return wxT("TCM_REMOVEIMAGE");
5054 case 0x1300 + 43: return wxT("TCM_SETPADDING");
5055 case 0x1300 + 44: return wxT("TCM_GETROWCOUNT");
5056 case 0x1300 + 45: return wxT("TCM_GETTOOLTIPS");
5057 case 0x1300 + 46: return wxT("TCM_SETTOOLTIPS");
5058 case 0x1300 + 47: return wxT("TCM_GETCURFOCUS");
5059 case 0x1300 + 48: return wxT("TCM_SETCURFOCUS");
5060 case 0x1300 + 49: return wxT("TCM_SETMINTABWIDTH");
5061 case 0x1300 + 50: return wxT("TCM_DESELECTALL");
5062
5063 // toolbar
5064 case WM_USER+1000+1: return wxT("TB_ENABLEBUTTON");
5065 case WM_USER+1000+2: return wxT("TB_CHECKBUTTON");
5066 case WM_USER+1000+3: return wxT("TB_PRESSBUTTON");
5067 case WM_USER+1000+4: return wxT("TB_HIDEBUTTON");
5068 case WM_USER+1000+5: return wxT("TB_INDETERMINATE");
5069 case WM_USER+1000+9: return wxT("TB_ISBUTTONENABLED");
5070 case WM_USER+1000+10: return wxT("TB_ISBUTTONCHECKED");
5071 case WM_USER+1000+11: return wxT("TB_ISBUTTONPRESSED");
5072 case WM_USER+1000+12: return wxT("TB_ISBUTTONHIDDEN");
5073 case WM_USER+1000+13: return wxT("TB_ISBUTTONINDETERMINATE");
5074 case WM_USER+1000+17: return wxT("TB_SETSTATE");
5075 case WM_USER+1000+18: return wxT("TB_GETSTATE");
5076 case WM_USER+1000+19: return wxT("TB_ADDBITMAP");
5077 case WM_USER+1000+20: return wxT("TB_ADDBUTTONS");
5078 case WM_USER+1000+21: return wxT("TB_INSERTBUTTON");
5079 case WM_USER+1000+22: return wxT("TB_DELETEBUTTON");
5080 case WM_USER+1000+23: return wxT("TB_GETBUTTON");
5081 case WM_USER+1000+24: return wxT("TB_BUTTONCOUNT");
5082 case WM_USER+1000+25: return wxT("TB_COMMANDTOINDEX");
5083 case WM_USER+1000+26: return wxT("TB_SAVERESTOREA");
5084 case WM_USER+1000+76: return wxT("TB_SAVERESTOREW");
5085 case WM_USER+1000+27: return wxT("TB_CUSTOMIZE");
5086 case WM_USER+1000+28: return wxT("TB_ADDSTRINGA");
5087 case WM_USER+1000+77: return wxT("TB_ADDSTRINGW");
5088 case WM_USER+1000+29: return wxT("TB_GETITEMRECT");
5089 case WM_USER+1000+30: return wxT("TB_BUTTONSTRUCTSIZE");
5090 case WM_USER+1000+31: return wxT("TB_SETBUTTONSIZE");
5091 case WM_USER+1000+32: return wxT("TB_SETBITMAPSIZE");
5092 case WM_USER+1000+33: return wxT("TB_AUTOSIZE");
5093 case WM_USER+1000+35: return wxT("TB_GETTOOLTIPS");
5094 case WM_USER+1000+36: return wxT("TB_SETTOOLTIPS");
5095 case WM_USER+1000+37: return wxT("TB_SETPARENT");
5096 case WM_USER+1000+39: return wxT("TB_SETROWS");
5097 case WM_USER+1000+40: return wxT("TB_GETROWS");
5098 case WM_USER+1000+42: return wxT("TB_SETCMDID");
5099 case WM_USER+1000+43: return wxT("TB_CHANGEBITMAP");
5100 case WM_USER+1000+44: return wxT("TB_GETBITMAP");
5101 case WM_USER+1000+45: return wxT("TB_GETBUTTONTEXTA");
5102 case WM_USER+1000+75: return wxT("TB_GETBUTTONTEXTW");
5103 case WM_USER+1000+46: return wxT("TB_REPLACEBITMAP");
5104 case WM_USER+1000+47: return wxT("TB_SETINDENT");
5105 case WM_USER+1000+48: return wxT("TB_SETIMAGELIST");
5106 case WM_USER+1000+49: return wxT("TB_GETIMAGELIST");
5107 case WM_USER+1000+50: return wxT("TB_LOADIMAGES");
5108 case WM_USER+1000+51: return wxT("TB_GETRECT");
5109 case WM_USER+1000+52: return wxT("TB_SETHOTIMAGELIST");
5110 case WM_USER+1000+53: return wxT("TB_GETHOTIMAGELIST");
5111 case WM_USER+1000+54: return wxT("TB_SETDISABLEDIMAGELIST");
5112 case WM_USER+1000+55: return wxT("TB_GETDISABLEDIMAGELIST");
5113 case WM_USER+1000+56: return wxT("TB_SETSTYLE");
5114 case WM_USER+1000+57: return wxT("TB_GETSTYLE");
5115 case WM_USER+1000+58: return wxT("TB_GETBUTTONSIZE");
5116 case WM_USER+1000+59: return wxT("TB_SETBUTTONWIDTH");
5117 case WM_USER+1000+60: return wxT("TB_SETMAXTEXTROWS");
5118 case WM_USER+1000+61: return wxT("TB_GETTEXTROWS");
5119 case WM_USER+1000+41: return wxT("TB_GETBITMAPFLAGS");
5120 }
5121
5122 static wxString s_szBuf;
5123 s_szBuf.Printf(wxT("<unknown message = %d>"), nMessage);
5124 return s_szBuf.c_str();
5125
5126 } // end of wxGetMessageName
5127
5128 #endif // __WXDEBUG__
5129
5130 // Unused?
5131 #if 0
5132 static void TranslateKbdEventToMouse(
5133 wxWindow* pWin
5134 , int* pX
5135 , int* pY
5136 , ULONG* pFlags
5137 )
5138 {
5139 //
5140 // Construct the key mask
5141 ULONG& fwKeys = *pFlags;
5142
5143 fwKeys = VK_BUTTON2;
5144 if ((::WinGetKeyState(HWND_DESKTOP, VK_CTRL) & 0x100) != 0)
5145 fwKeys |= VK_CTRL;
5146 if ((::WinGetKeyState(HWND_DESKTOP, VK_SHIFT) & 0x100) != 0)
5147 fwKeys |= VK_SHIFT;
5148
5149 //
5150 // Simulate right mouse button click
5151 //
5152 POINTL vPoint;
5153
5154 ::WinQueryMsgPos(vHabmain, &vPoint);
5155 *pX = vPoint.x;
5156 *pY = vPoint.y;
5157
5158 pWin->ScreenToClient(pX, pY);
5159 } // end of TranslateKbdEventToMouse
5160 #endif
5161
5162 // Find the wxWindow at the current mouse position, returning the mouse
5163 // position.
5164 wxWindow* wxFindWindowAtPointer(wxPoint& WXUNUSED(rPt))
5165 {
5166 return wxFindWindowAtPoint(wxGetMousePosition());
5167 }
5168
5169 wxWindow* wxFindWindowAtPoint(const wxPoint& rPt)
5170 {
5171 POINTL vPt2;
5172
5173 vPt2.x = rPt.x;
5174 vPt2.y = rPt.y;
5175
5176 HWND hWndHit = ::WinWindowFromPoint(HWND_DESKTOP, &vPt2, FALSE);
5177 wxWindow* pWin = wxFindWinFromHandle((WXHWND)hWndHit) ;
5178 HWND hWnd = hWndHit;
5179
5180 //
5181 // Try to find a window with a wxWindow associated with it
5182 //
5183 while (!pWin && (hWnd != 0))
5184 {
5185 hWnd = ::WinQueryWindow(hWnd, QW_PARENT);
5186 pWin = wxFindWinFromHandle((WXHWND)hWnd) ;
5187 }
5188 return pWin;
5189 }
5190
5191 // Get the current mouse position.
5192 wxPoint wxGetMousePosition()
5193 {
5194 POINTL vPt;
5195
5196 ::WinQueryPointerPos(HWND_DESKTOP, &vPt);
5197 return wxPoint(vPt.x, vPt.y);
5198 }
5199
5200 wxWindowOS2* FindWindowForMouseEvent( wxWindow* pWin,
5201 short* WXUNUSED(pnX),
5202 short* WXUNUSED(pnY) )
5203 {
5204 HWND hWnd = GetHwndOf(pWin);
5205 HWND hWndUnderMouse;
5206 POINTL vPoint;
5207 BOOL rcEnabled = FALSE;
5208 BOOL rcVisible = FALSE;
5209
5210 ::WinQueryPointerPos(HWND_DESKTOP, &vPoint);
5211 hWndUnderMouse = ::WinWindowFromPoint(HWND_DESKTOP, &vPoint, TRUE);
5212 if (hWndUnderMouse != HWND_DESKTOP)
5213 {
5214 wxWindow* pWinUnderMouse = wxFindWinFromHandle((WXHWND)hWndUnderMouse);
5215
5216 if (pWinUnderMouse)
5217 {
5218 wxWindowList::compatibility_iterator current = pWinUnderMouse->GetChildren().GetFirst();
5219 wxWindow* pGrandChild = NULL;
5220 RECTL vRect;
5221 POINTL vPoint2;
5222
5223 ::WinMapWindowPoints(HWND_DESKTOP, hWndUnderMouse, &vPoint, 1);
5224 //
5225 // Find a child window mouse might be under
5226 //
5227 while (current)
5228 {
5229 wxWindow* pChild = current->GetData();
5230
5231 vPoint2.x = vPoint.x;
5232 vPoint2.y = vPoint.y;
5233 ::WinMapWindowPoints(hWndUnderMouse, pChild->GetHWND(), &vPoint2, 1);
5234 ::WinQueryWindowRect(pChild->GetHWND(), &vRect);
5235 if (::WinPtInRect(vHabmain, &vRect, &vPoint2))
5236 {
5237 if (pChild->IsTopLevel())
5238 {
5239 POINTL vPoint3;
5240 wxWindowList::compatibility_iterator current2 =pChild->GetChildren().GetFirst();
5241
5242 while (current2)
5243 {
5244 wxWindow* pGrandChild = current2->GetData();
5245
5246 vPoint3.x = vPoint2.x;
5247 vPoint3.y = vPoint2.y;
5248 ::WinMapWindowPoints( pChild->GetHWND()
5249 ,pGrandChild->GetHWND()
5250 ,&vPoint3
5251 ,1
5252 );
5253 ::WinQueryWindowRect(pGrandChild->GetHWND(), &vRect);
5254 if (::WinPtInRect(vHabmain, &vRect, &vPoint3))
5255 {
5256 hWndUnderMouse = GetHwndOf(pGrandChild);
5257 pWinUnderMouse = pGrandChild;
5258 break;
5259 }
5260 current2 = current2->GetNext();
5261 }
5262 if (pGrandChild)
5263 break;
5264 }
5265 hWndUnderMouse = GetHwndOf(pChild);
5266 pWinUnderMouse = pChild;
5267 rcVisible = ::WinIsWindowVisible(hWndUnderMouse);
5268 rcEnabled = ::WinIsWindowEnabled(hWndUnderMouse);
5269 if (rcVisible && rcEnabled)
5270 break;
5271 }
5272 current = current->GetNext();
5273 }
5274 }
5275 }
5276 rcVisible = ::WinIsWindowVisible(hWndUnderMouse);
5277 rcEnabled = ::WinIsWindowEnabled(hWndUnderMouse);
5278
5279
5280 //
5281 // Check that we have a child window which is susceptible to receive mouse
5282 // events: for this it must be shown and enabled
5283 //
5284 if ( hWndUnderMouse &&
5285 hWndUnderMouse != hWnd &&
5286 rcVisible && rcEnabled)
5287 {
5288 wxWindow* pWinUnderMouse = wxFindWinFromHandle((WXHWND)hWndUnderMouse);
5289
5290 if (pWinUnderMouse)
5291 {
5292 //
5293 // Translate the mouse coords to the other window coords
5294 //
5295 pWin = pWinUnderMouse;
5296 }
5297 }
5298 return pWin;
5299 } // end of FindWindowForMouseEvent