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