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