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