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