]> git.saurik.com Git - wxWidgets.git/blob - src/msw/window.cpp
Added wxExpr parser/lexer files which had somehow got lost;
[wxWidgets.git] / src / msw / window.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: windows.cpp
3 // Purpose: wxWindow
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "window.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include <stdio.h>
25 #include "wx/setup.h"
26 #include "wx/menu.h"
27 #include "wx/dc.h"
28 #include "wx/dcclient.h"
29 #include "wx/utils.h"
30 #include "wx/app.h"
31 #include "wx/panel.h"
32 #include "wx/layout.h"
33 #include "wx/dialog.h"
34 #include "wx/listbox.h"
35 #include "wx/button.h"
36 #include "wx/settings.h"
37 #include "wx/msgdlg.h"
38 #endif
39
40 #if USE_OWNER_DRAWN
41 #include "wx/ownerdrw.h"
42 #endif
43
44 #if USE_DRAG_AND_DROP
45 #include "wx/msw/ole/droptgt.h"
46 #endif
47
48 #include "wx/menuitem.h"
49 #include "wx/msw/private.h"
50
51 #include <string.h>
52
53 #ifndef __GNUWIN32__
54 #include <shellapi.h>
55 #include <mmsystem.h>
56 #endif
57
58 #ifdef __WIN32__
59 #include <windowsx.h>
60 #endif
61
62 #ifdef __GNUWIN32__
63 #include <wx/msw/gnuwin32/extra.h>
64 #endif
65
66 #ifdef GetCharWidth
67 #undef GetCharWidth
68 #endif
69
70 #ifdef FindWindow
71 #undef FindWindow
72 #endif
73
74 #ifdef GetClassName
75 #undef GetClassName
76 #endif
77
78 #ifdef GetClassInfo
79 #undef GetClassInfo
80 #endif
81
82 #define WINDOW_MARGIN 3 // This defines sensitivity of Leave events
83
84 wxMenu *wxCurrentPopupMenu = NULL;
85 extern wxList wxPendingDelete;
86
87 void wxRemoveHandleAssociation(wxWindow *win);
88 void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win);
89 wxWindow *wxFindWinFromHandle(WXHWND hWnd);
90
91 #if !USE_SHARED_LIBRARY
92 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxEvtHandler)
93
94 BEGIN_EVENT_TABLE(wxWindow, wxEvtHandler)
95 EVT_CHAR(wxWindow::OnChar)
96 EVT_SIZE(wxWindow::OnSize)
97 EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
98 EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
99 EVT_INIT_DIALOG(wxWindow::OnInitDialog)
100 EVT_IDLE(wxWindow::OnIdle)
101 END_EVENT_TABLE()
102
103 #endif
104
105 // Find an item given the MS Windows id
106 wxWindow *wxWindow::FindItem(const int id) const
107 {
108 if (!GetChildren())
109 return NULL;
110 wxNode *current = GetChildren()->First();
111 while (current)
112 {
113 wxWindow *childWin = (wxWindow *)current->Data();
114
115 wxWindow *wnd = childWin->FindItem(id) ;
116 if (wnd)
117 return wnd ;
118
119 if (childWin->IsKindOf(CLASSINFO(wxControl)))
120 {
121 wxControl *item = (wxControl *)childWin;
122 if (item->m_windowId == id)
123 return item;
124 else
125 {
126 // In case it's a 'virtual' control (e.g. radiobox)
127 if (item->GetSubcontrols().Member((wxObject *)id))
128 return item;
129 }
130 }
131 current = current->Next();
132 }
133 return NULL;
134 }
135
136 // Find an item given the MS Windows handle
137 wxWindow *wxWindow::FindItemByHWND(const WXHWND hWnd, bool controlOnly) const
138 {
139 if (!GetChildren())
140 return NULL;
141 wxNode *current = GetChildren()->First();
142 while (current)
143 {
144 wxObject *obj = (wxObject *)current->Data() ;
145 // Do a recursive search.
146 wxWindow *parent = (wxWindow *)obj ;
147 wxWindow *wnd = parent->FindItemByHWND(hWnd) ;
148 if (wnd)
149 return wnd ;
150
151 if ((!controlOnly) || obj->IsKindOf(CLASSINFO(wxControl)))
152 {
153 wxWindow *item = (wxWindow *)current->Data();
154 if ((HWND)(item->GetHWND()) == (HWND) hWnd)
155 return item;
156 else
157 {
158 if ( item->ContainsHWND(hWnd) )
159 return item;
160 }
161 }
162 current = current->Next();
163 }
164 return NULL;
165 }
166
167 // Default command handler
168 bool wxWindow::MSWCommand(const WXUINT WXUNUSED(param), const WXWORD WXUNUSED(id))
169 {
170 return FALSE;
171 }
172
173 bool wxWindow::MSWNotify(const WXWPARAM WXUNUSED(wParam), const WXLPARAM WXUNUSED(lParam))
174 {
175 return FALSE;
176 }
177
178 void wxWindow::PreDelete(const WXHDC WXUNUSED(dc))
179 {
180 }
181
182 WXHWND wxWindow::GetHWND(void) const
183 {
184 return (WXHWND) m_hWnd;
185 }
186
187 void wxWindow::SetHWND(WXHWND hWnd)
188 {
189 m_hWnd = hWnd;
190 }
191
192 // Constructor
193 wxWindow::wxWindow(void)
194 {
195 // Generic
196 m_windowId = 0;
197 m_isShown = TRUE;
198 m_windowStyle = 0;
199 m_windowParent = NULL;
200 m_windowEventHandler = this;
201 m_windowName = "";
202 m_windowCursor = *wxSTANDARD_CURSOR;
203 m_children = new wxList;
204 m_doubleClickAllowed = 0 ;
205 m_winCaptured = FALSE;
206 m_constraints = NULL;
207 m_constraintsInvolvedIn = NULL;
208 m_windowSizer = NULL;
209 m_sizerParent = NULL;
210 m_autoLayout = FALSE;
211 m_windowValidator = NULL;
212
213 // MSW-specific
214 m_hWnd = 0;
215 m_winEnabled = TRUE;
216 m_caretWidth = 0; m_caretHeight = 0;
217 m_caretEnabled = FALSE;
218 m_caretShown = FALSE;
219 m_inOnSize = FALSE;
220 m_minSizeX = -1;
221 m_minSizeY = -1;
222 m_maxSizeX = -1;
223 m_maxSizeY = -1;
224 // m_paintHDC = 0;
225 // m_tempHDC = 0;
226 m_isBeingDeleted = FALSE;
227 m_oldWndProc = 0;
228 #ifndef __WIN32__
229 m_globalHandle = 0;
230 #endif
231 m_useCtl3D = FALSE;
232
233 m_defaultItem = NULL;
234
235 wxSystemSettings settings;
236
237 m_backgroundColour = settings.GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
238 m_foregroundColour = *wxBLACK;
239 m_defaultForegroundColour = *wxBLACK ;
240 m_defaultBackgroundColour = settings.GetSystemColour(wxSYS_COLOUR_3DFACE) ;
241
242 /*
243 wxColour(GetRValue(GetSysColor(COLOR_WINDOW)),
244 GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE)));
245 */
246
247 // wxWnd
248 m_lastMsg = 0;
249 m_lastWParam = 0;
250 m_lastLParam = 0;
251 m_acceleratorTable = 0;
252 m_hMenu = 0;
253
254 m_xThumbSize = 0;
255 m_yThumbSize = 0;
256 m_backgroundTransparent = FALSE;
257
258 m_lastXPos = (float)-1.0;
259 m_lastYPos = (float)-1.0;
260 m_lastEvent = -1;
261 m_returnCode = 0;
262
263 #if USE_DRAG_AND_DROP
264 m_pDropTarget = NULL;
265 #endif
266 }
267
268 // Destructor
269 wxWindow::~wxWindow(void)
270 {
271 m_isBeingDeleted = TRUE;
272
273 // JACS - if behaviour is odd, restore this
274 // to the start of ~wxWindow. Vadim has changed
275 // it to nearer the end. Unsure of side-effects
276 // e.g. when deleting associated global data.
277 // Restore old Window proc, if required
278 // UnsubclassWin();
279
280 // Have to delete constraints/sizer FIRST otherwise
281 // sizers may try to look at deleted windows as they
282 // delete themselves.
283 #if USE_CONSTRAINTS
284 DeleteRelatedConstraints();
285 if (m_constraints)
286 {
287 // This removes any dangling pointers to this window
288 // in other windows' constraintsInvolvedIn lists.
289 UnsetConstraints(m_constraints);
290 delete m_constraints;
291 m_constraints = NULL;
292 }
293 if (m_windowSizer)
294 {
295 delete m_windowSizer;
296 m_windowSizer = NULL;
297 }
298 // If this is a child of a sizer, remove self from parent
299 if (m_sizerParent)
300 m_sizerParent->RemoveChild((wxWindow *)this);
301 #endif
302
303 // wxWnd
304 MSWDetachWindowMenu();
305
306 // TODO for backward compatibility
307 #if 0
308 // WX_CANVAS
309 if (m_windowDC)
310 {
311 HWND hWnd = (HWND) GetHWND();
312 HDC dc = ::GetDC(hWnd);
313 m_windowDC->SelectOldObjects (dc);
314 ReleaseDC(hWnd, dc);
315 delete m_windowDC;
316 }
317 #endif
318
319 if (m_windowParent)
320 m_windowParent->RemoveChild(this);
321
322 DestroyChildren();
323
324 if (m_hWnd)
325 ::DestroyWindow((HWND)m_hWnd);
326
327 wxRemoveHandleAssociation(this);
328 m_hWnd = 0;
329 #ifndef __WIN32__
330 if (m_globalHandle)
331 {
332 GlobalFree((HGLOBAL) m_globalHandle);
333 m_globalHandle = 0;
334 }
335 #endif
336
337 delete m_children;
338 m_children = NULL;
339
340 // Just in case the window has been Closed, but
341 // we're then deleting immediately: don't leave
342 // dangling pointers.
343 wxPendingDelete.DeleteObject(this);
344
345 // Just in case we've loaded a top-level window via
346 // wxWindow::LoadNativeDialog but we weren't a dialog
347 // class
348 wxTopLevelWindows.DeleteObject(this);
349
350 // if (GetFont() && GetFont()->Ok())
351 // GetFont()->ReleaseResource();
352
353 if ( m_windowValidator )
354 delete m_windowValidator;
355
356 // Restore old Window proc, if required
357 // and remove hWnd <-> wxWindow association
358 UnsubclassWin();
359 }
360
361 // Destroy the window (delayed, if a managed window)
362 bool wxWindow::Destroy(void)
363 {
364 delete this;
365 return TRUE;
366 }
367
368 extern char wxCanvasClassName[];
369
370 // Constructor
371 bool wxWindow::Create(wxWindow *parent, const wxWindowID id,
372 const wxPoint& pos,
373 const wxSize& size,
374 const long style,
375 const wxString& name)
376 {
377 // Generic
378 m_isBeingDeleted = FALSE;
379 m_windowId = 0;
380 m_isShown = TRUE;
381 m_windowStyle = 0;
382 m_windowParent = NULL;
383 m_windowEventHandler = this;
384 // m_windowFont = NULL;
385 // We don't wish internal (potentially transient) fonts to be found
386 // by FindOrCreate
387 // wxTheFontList->RemoveFont(& m_windowFont);
388 m_windowName = "";
389 m_windowCursor = *wxSTANDARD_CURSOR;
390 m_doubleClickAllowed = 0 ;
391 m_winCaptured = FALSE;
392 m_constraints = NULL;
393 m_constraintsInvolvedIn = NULL;
394 m_windowSizer = NULL;
395 m_sizerParent = NULL;
396 m_autoLayout = FALSE;
397 m_windowValidator = NULL;
398 #if USE_DRAG_AND_DROP
399 m_pDropTarget = NULL;
400 #endif
401
402 // MSW-specific
403 m_hWnd = 0;
404 m_winEnabled = TRUE;
405 m_caretWidth = 0; m_caretHeight = 0;
406 m_caretEnabled = FALSE;
407 m_caretShown = FALSE;
408 m_inOnSize = FALSE;
409 m_minSizeX = -1;
410 m_minSizeY = -1;
411 m_maxSizeX = -1;
412 m_maxSizeY = -1;
413 // m_paintHDC = 0;
414 // m_tempHDC = 0;
415 m_oldWndProc = 0;
416 #ifndef __WIN32__
417 m_globalHandle = 0;
418 #endif
419 m_useCtl3D = FALSE;
420 m_defaultItem = NULL;
421 m_windowParent = NULL;
422 // m_windowDC = NULL;
423 m_mouseInWindow = FALSE;
424 if (!parent)
425 return FALSE;
426
427 if (parent) parent->AddChild(this);
428
429 // wxWnd
430 m_lastMsg = 0;
431 m_lastWParam = 0;
432 m_lastLParam = 0;
433 m_acceleratorTable = 0;
434 m_hMenu = 0;
435
436 m_xThumbSize = 0;
437 m_yThumbSize = 0;
438 m_backgroundTransparent = FALSE;
439
440 m_lastXPos = (float)-1.0;
441 m_lastYPos = (float)-1.0;
442 m_lastEvent = -1;
443 m_returnCode = 0;
444
445 SetName(name);
446
447 if ( id == -1 )
448 m_windowId = (int)NewControlId();
449 else
450 m_windowId = id;
451
452 int x = pos.x;
453 int y = pos.y;
454 int width = size.x;
455 int height = size.y;
456
457 wxSystemSettings settings;
458
459 m_backgroundColour = settings.GetSystemColour(wxSYS_COLOUR_WINDOW) ; ;
460 m_foregroundColour = *wxBLACK;
461 m_defaultForegroundColour = *wxBLACK ;
462 m_defaultBackgroundColour = settings.GetSystemColour(wxSYS_COLOUR_3DFACE) ;
463 /*
464 m_defaultBackgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)),
465 GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE)));
466 */
467
468 m_windowStyle = style;
469
470 DWORD msflags = 0;
471 if (style & wxBORDER)
472 msflags |= WS_BORDER;
473 if (style & wxTHICK_FRAME)
474 msflags |= WS_THICKFRAME;
475
476 msflags |= WS_CHILD | WS_VISIBLE;
477 if (style & wxCLIP_CHILDREN)
478 msflags |= WS_CLIPCHILDREN;
479
480 bool want3D;
481 WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
482
483 // Even with extended styles, need to combine with WS_BORDER
484 // for them to look right.
485 if (want3D || (m_windowStyle & wxSIMPLE_BORDER) || (m_windowStyle & wxRAISED_BORDER) ||
486 (m_windowStyle & wxSUNKEN_BORDER) || (m_windowStyle & wxDOUBLE_BORDER))
487 msflags |= WS_BORDER;
488
489 m_mouseInWindow = FALSE ;
490
491 if ( id == -1 )
492 m_windowId = (int)NewControlId();
493 else
494 m_windowId = id;
495
496 MSWCreate(m_windowId, (wxWindow *)parent, wxCanvasClassName, this, NULL, x, y, width, height, msflags,
497 NULL, exStyle);
498
499 return TRUE;
500 }
501
502 void wxWindow::SetFocus(void)
503 {
504 HWND hWnd = (HWND) GetHWND();
505 if (hWnd)
506 ::SetFocus(hWnd);
507 }
508
509 void wxWindow::Enable(const bool enable)
510 {
511 m_winEnabled = enable;
512 HWND hWnd = (HWND) GetHWND();
513 if (hWnd)
514 ::EnableWindow(hWnd, (BOOL)enable);
515 }
516
517 void wxWindow::CaptureMouse(void)
518 {
519 HWND hWnd = (HWND) GetHWND();
520 if (hWnd && !m_winCaptured)
521 {
522 SetCapture(hWnd);
523 m_winCaptured = TRUE;
524 }
525 }
526
527 void wxWindow::ReleaseMouse(void)
528 {
529 if (m_winCaptured)
530 {
531 ReleaseCapture();
532 m_winCaptured = FALSE;
533 }
534 }
535
536 // Push/pop event handler (i.e. allow a chain of event handlers
537 // be searched)
538 void wxWindow::PushEventHandler(wxEvtHandler *handler)
539 {
540 handler->SetNextHandler(GetEventHandler());
541 SetEventHandler(handler);
542 }
543
544 wxEvtHandler *wxWindow::PopEventHandler(bool deleteHandler)
545 {
546 if ( GetEventHandler() )
547 {
548 wxEvtHandler *handlerA = GetEventHandler();
549 wxEvtHandler *handlerB = handlerA->GetNextHandler();
550 handlerA->SetNextHandler(NULL);
551 SetEventHandler(handlerB);
552 if ( deleteHandler )
553 {
554 delete handlerA;
555 return NULL;
556 }
557 else
558 return handlerA;
559 }
560 else
561 return NULL;
562 }
563
564 #if USE_DRAG_AND_DROP
565
566 void wxWindow::SetDropTarget(wxDropTarget *pDropTarget)
567 {
568 if ( m_pDropTarget != 0 ) {
569 m_pDropTarget->Revoke(m_hWnd);
570 delete m_pDropTarget;
571 }
572
573 m_pDropTarget = pDropTarget;
574 if ( m_pDropTarget != 0 )
575 m_pDropTarget->Register(m_hWnd);
576 }
577
578 #endif
579
580 //old style file-manager drag&drop support
581 // I think we should retain the old-style
582 // DragAcceptFiles in parallel with SetDropTarget.
583 // JACS
584 void wxWindow::DragAcceptFiles(const bool accept)
585 {
586 HWND hWnd = (HWND) GetHWND();
587 if (hWnd)
588 ::DragAcceptFiles(hWnd, (BOOL)accept);
589 }
590
591 // Get total size
592 void wxWindow::GetSize(int *x, int *y) const
593 {
594 HWND hWnd = (HWND) GetHWND();
595 RECT rect;
596 GetWindowRect(hWnd, &rect);
597 *x = rect.right - rect.left;
598 *y = rect.bottom - rect.top;
599 }
600
601 void wxWindow::GetPosition(int *x, int *y) const
602 {
603 HWND hWnd = (HWND) GetHWND();
604 HWND hParentWnd = 0;
605 if (GetParent())
606 hParentWnd = (HWND) GetParent()->GetHWND();
607
608 RECT rect;
609 GetWindowRect(hWnd, &rect);
610
611 // Since we now have the absolute screen coords,
612 // if there's a parent we must subtract its top left corner
613 POINT point;
614 point.x = rect.left;
615 point.y = rect.top;
616 if (hParentWnd)
617 {
618 ::ScreenToClient(hParentWnd, &point);
619 }
620 *x = point.x;
621 *y = point.y;
622 }
623
624 void wxWindow::ScreenToClient(int *x, int *y) const
625 {
626 HWND hWnd = (HWND) GetHWND();
627 POINT pt;
628 pt.x = *x;
629 pt.y = *y;
630 ::ScreenToClient(hWnd, &pt);
631
632 *x = pt.x;
633 *y = pt.y;
634 }
635
636 void wxWindow::ClientToScreen(int *x, int *y) const
637 {
638 HWND hWnd = (HWND) GetHWND();
639 POINT pt;
640 pt.x = *x;
641 pt.y = *y;
642 ::ClientToScreen(hWnd, &pt);
643
644 *x = pt.x;
645 *y = pt.y;
646 }
647
648 void wxWindow::SetCursor(const wxCursor& cursor)
649 {
650 m_windowCursor = cursor;
651 if (m_windowCursor.Ok())
652 {
653 HWND hWnd = (HWND) GetHWND();
654
655 // Change the cursor NOW if we're within the correct window
656 POINT point;
657 ::GetCursorPos(&point);
658
659 RECT rect;
660 ::GetWindowRect(hWnd, &rect);
661
662 if (::PtInRect(&rect, point) && !wxIsBusy())
663 ::SetCursor((HCURSOR) m_windowCursor.GetHCURSOR());
664 }
665
666 // This will cause big reentrancy problems if wxFlushEvents is implemented.
667 // wxFlushEvents();
668 // return old_cursor;
669 }
670
671
672 // Get size *available for subwindows* i.e. excluding menu bar etc.
673 // For XView, this is the same as GetSize
674 void wxWindow::GetClientSize(int *x, int *y) const
675 {
676 HWND hWnd = (HWND) GetHWND();
677 RECT rect;
678 GetClientRect(hWnd, &rect);
679 *x = rect.right;
680 *y = rect.bottom;
681 }
682
683 void wxWindow::SetSize(const int x, const int y, const int width, const int height, const int sizeFlags)
684 {
685 int currentX, currentY;
686 GetPosition(&currentX, &currentY);
687 int actualWidth = width;
688 int actualHeight = height;
689 int actualX = x;
690 int actualY = y;
691 if (x == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
692 actualX = currentX;
693 if (y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
694 actualY = currentY;
695
696 int currentW,currentH;
697 GetSize(&currentW, &currentH);
698 if (width == -1)
699 actualWidth = currentW ;
700 if (height == -1)
701 actualHeight = currentH ;
702
703 HWND hWnd = (HWND) GetHWND();
704 if (hWnd)
705 MoveWindow(hWnd, actualX, actualY, actualWidth, actualHeight, (BOOL)TRUE);
706
707 /* Not needed? should be called anyway via MoveWindow
708 if (!(width == -1) && (height == -1))
709 {
710 #if WXWIN_COMPATIBILITY
711 GetEventHandler()->OldOnSize(width, height);
712 #else
713 wxSizeEvent event(wxSize(width, height), m_windowId);
714 event.eventObject = this;
715 GetEventHandler()->ProcessEvent(event);
716 #endif
717 }
718 */
719 }
720
721 void wxWindow::SetClientSize(const int width, const int height)
722 {
723 wxWindow *parent = GetParent();
724 HWND hWnd = (HWND) GetHWND();
725 HWND hParentWnd = (HWND) (HWND) parent->GetHWND();
726
727 RECT rect;
728 GetClientRect(hWnd, &rect);
729
730 RECT rect2;
731 GetWindowRect(hWnd, &rect2);
732
733 // Find the difference between the entire window (title bar and all)
734 // and the client area; add this to the new client size to move the
735 // window
736 int actual_width = rect2.right - rect2.left - rect.right + width;
737 int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
738
739 // If there's a parent, must subtract the parent's top left corner
740 // since MoveWindow moves relative to the parent
741
742 POINT point;
743 point.x = rect2.left;
744 point.y = rect2.top;
745 if (parent)
746 {
747 ::ScreenToClient(hParentWnd, &point);
748 }
749
750 MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE);
751 #if WXWIN_COMPATIBILITY
752 GetEventHandler()->OldOnSize(width, height);
753 #else
754 wxSizeEvent event(wxSize(width, height), m_windowId);
755 event.m_eventObject = this;
756 GetEventHandler()->ProcessEvent(event);
757 #endif
758 }
759
760 bool wxWindow::Show(const bool show)
761 {
762 HWND hWnd = (HWND) GetHWND();
763 int cshow;
764 if (show)
765 cshow = SW_SHOW;
766 else
767 cshow = SW_HIDE;
768 ShowWindow(hWnd, (BOOL)cshow);
769 if (show)
770 {
771 BringWindowToTop(hWnd);
772 // Next line causes a crash on NT, apparently.
773 // UpdateWindow(hWnd); // Should this be here or will it cause inefficiency?
774 }
775 return TRUE;
776 }
777
778 bool wxWindow::IsShown(void) const
779 {
780 return (::IsWindowVisible((HWND) GetHWND()) != 0);
781 }
782
783 int wxWindow::GetCharHeight(void) const
784 {
785 TEXTMETRIC lpTextMetric;
786 HWND hWnd = (HWND) GetHWND();
787 HDC dc = ::GetDC(hWnd);
788
789 GetTextMetrics(dc, &lpTextMetric);
790 ::ReleaseDC(hWnd, dc);
791
792 return lpTextMetric.tmHeight;
793 }
794
795 int wxWindow::GetCharWidth(void) const
796 {
797 TEXTMETRIC lpTextMetric;
798 HWND hWnd = (HWND) GetHWND();
799 HDC dc = ::GetDC(hWnd);
800
801 GetTextMetrics(dc, &lpTextMetric);
802 ::ReleaseDC(hWnd, dc);
803
804 return lpTextMetric.tmAveCharWidth;
805 }
806
807 void wxWindow::GetTextExtent(const wxString& string, int *x, int *y,
808 int *descent, int *externalLeading, const wxFont *theFont, const bool) const
809 {
810 wxFont *fontToUse = (wxFont *)theFont;
811 if (!fontToUse)
812 fontToUse = (wxFont *) & m_windowFont;
813
814 HWND hWnd = (HWND) GetHWND();
815 HDC dc = ::GetDC(hWnd);
816
817 HFONT fnt = 0;
818 HFONT was = 0;
819 if (fontToUse && fontToUse->Ok())
820 {
821 if ((fnt=(HFONT) fontToUse->GetResourceHandle()))
822 was = SelectObject(dc,fnt) ;
823 }
824
825 SIZE sizeRect;
826 TEXTMETRIC tm;
827 GetTextExtentPoint(dc, (const char *)string, (int)string.Length(), &sizeRect);
828 GetTextMetrics(dc, &tm);
829
830 if (fontToUse && fnt && was)
831 SelectObject(dc,was) ;
832
833 ReleaseDC(hWnd, dc);
834
835 *x = sizeRect.cx;
836 *y = sizeRect.cy;
837 if (descent) *descent = tm.tmDescent;
838 if (externalLeading) *externalLeading = tm.tmExternalLeading;
839
840 // if (fontToUse)
841 // fontToUse->ReleaseResource();
842 }
843
844 #if WXWIN_COMPATIBILITY
845 void wxWindow::GetTextExtent(const wxString& string, float *x, float *y,
846 float *descent,
847 float *externalLeading,
848 const wxFont *theFont, const bool use16) const
849 {
850 int x1, y1, descent1, externalLeading1;
851 GetTextExtent(string, &x1, &y1, &descent1, &externalLeading1, theFont, use16);
852 *x = x1; *y = y1;
853 if ( descent )
854 *descent = descent1;
855 if ( externalLeading )
856 *externalLeading = externalLeading1;
857 }
858 #endif
859
860 void wxWindow::Refresh(const bool eraseBack, const wxRectangle *rect)
861 {
862 HWND hWnd = (HWND) GetHWND();
863 if (hWnd)
864 {
865 if (rect)
866 {
867 RECT mswRect;
868 mswRect.left = rect->x;
869 mswRect.top = rect->y;
870 mswRect.right = rect->x + rect->width;
871 mswRect.bottom = rect->y + rect->height;
872
873 ::InvalidateRect(hWnd, &mswRect, eraseBack);
874 }
875 else
876 ::InvalidateRect(hWnd, NULL, eraseBack);
877 }
878 }
879
880 // Hook for new window just as it's being created,
881 // when the window isn't yet associated with the handle
882 wxWindow *wxWndHook = NULL;
883
884 // Main window proc
885 LRESULT APIENTRY _EXPORT wxWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
886 {
887 wxWindow *wnd = wxFindWinFromHandle((WXHWND) hWnd);
888
889 if (!wnd && wxWndHook)
890 {
891 wxAssociateWinWithHandle(hWnd, wxWndHook);
892 wnd = wxWndHook;
893 wxWndHook = NULL;
894 wnd->m_hWnd = (WXHWND) hWnd;
895 }
896 #if (DEBUG > 1)
897 wxDebugMsg("hWnd = %d, m_hWnd = %d, msg = %d\n", hWnd, m_hWnd, message);
898 #endif
899 // Stop right here if we don't have a valid handle
900 // in our wxWnd object.
901 if (wnd && !wnd->m_hWnd) {
902 // wxDebugMsg("Warning: could not find a valid handle, wx_win.cc/wxWndProc.\n");
903 wnd->m_hWnd = (WXHWND) hWnd;
904 long res = wnd->MSWDefWindowProc(message, wParam, lParam );
905 wnd->m_hWnd = 0;
906 return res;
907 }
908
909 if (wnd) {
910 wnd->m_lastMsg = message;
911 wnd->m_lastWParam = wParam;
912 wnd->m_lastLParam = lParam;
913 }
914 if (wnd)
915 return wnd->MSWWindowProc(message, wParam, lParam);
916 else
917 return DefWindowProc( hWnd, message, wParam, lParam );
918 }
919
920 // Should probably have a test for 'genuine' NT
921 #if defined(__WIN32__)
922 #define DIMENSION_TYPE short
923 #else
924 #define DIMENSION_TYPE int
925 #endif
926
927 // Main Windows 3 window proc
928 long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
929 {
930 #if 0
931 switch (message)
932 {
933 case WM_INITDIALOG:
934 case WM_ACTIVATE:
935 case WM_SETFOCUS:
936 case WM_KILLFOCUS:
937 case WM_CREATE:
938 case WM_PAINT:
939 case WM_QUERYDRAGICON:
940 case WM_SIZE:
941 case WM_RBUTTONDOWN:
942 case WM_RBUTTONUP:
943 case WM_RBUTTONDBLCLK:
944 case WM_MBUTTONDOWN:
945 case WM_MBUTTONUP:
946 case WM_MBUTTONDBLCLK:
947 case WM_LBUTTONDOWN:
948 case WM_LBUTTONUP:
949 case WM_LBUTTONDBLCLK:
950 case WM_MOUSEMOVE:
951 // case WM_DESTROY:
952 case WM_COMMAND:
953 case WM_NOTIFY:
954 case WM_MENUSELECT:
955 case WM_INITMENUPOPUP:
956 case WM_DRAWITEM:
957 case WM_MEASUREITEM:
958 case WM_KEYDOWN:
959 case WM_KEYUP:
960 case WM_CHAR: // Always an ASCII character
961 case WM_HSCROLL:
962 case WM_VSCROLL:
963 case WM_CTLCOLORBTN:
964 case WM_CTLCOLORDLG:
965 case WM_CTLCOLORLISTBOX:
966 case WM_CTLCOLORMSGBOX:
967 case WM_CTLCOLORSCROLLBAR:
968 case WM_CTLCOLORSTATIC:
969 case WM_CTLCOLOREDIT:
970 case WM_SYSCOLORCHANGE:
971 case WM_ERASEBKGND:
972 case WM_MDIACTIVATE:
973 case WM_DROPFILES:
974 case WM_QUERYENDSESSION:
975 // case WM_CLOSE:
976 case WM_GETMINMAXINFO:
977 return MSWDefWindowProc(message, wParam, lParam );
978 }
979 #endif
980
981
982 HWND hWnd = (HWND)m_hWnd;
983
984 switch (message)
985 {
986 case WM_ACTIVATE:
987 {
988 #ifdef __WIN32__
989 WORD state = LOWORD(wParam);
990 WORD minimized = HIWORD(wParam);
991 HWND hwnd = (HWND)lParam;
992 #else
993 WORD state = (WORD)wParam;
994 WORD minimized = LOWORD(lParam);
995 HWND hwnd = (HWND)HIWORD(lParam);
996 #endif
997 MSWOnActivate(state, (minimized != 0), (WXHWND) hwnd);
998 return 0;
999 break;
1000 }
1001 case WM_SETFOCUS:
1002 {
1003 HWND hwnd = (HWND)wParam;
1004 // return OnSetFocus(hwnd);
1005
1006 if (MSWOnSetFocus((WXHWND) hwnd))
1007 return 0;
1008 else return MSWDefWindowProc(message, wParam, lParam );
1009 break;
1010 }
1011 case WM_KILLFOCUS:
1012 {
1013 HWND hwnd = (HWND)lParam;
1014 // return OnKillFocus(hwnd);
1015 if (MSWOnKillFocus((WXHWND) hwnd))
1016 return 0;
1017 else
1018 return MSWDefWindowProc(message, wParam, lParam );
1019 break;
1020 }
1021 case WM_CREATE:
1022 {
1023 MSWOnCreate((WXLPCREATESTRUCT) (LPCREATESTRUCT)lParam);
1024 return 0;
1025 break;
1026 }
1027 case WM_SHOWWINDOW:
1028 {
1029 MSWOnShow((wParam != 0), (int) lParam);
1030 break;
1031 }
1032 case WM_PAINT:
1033 {
1034 if (MSWOnPaint())
1035 return 0;
1036 else return MSWDefWindowProc(message, wParam, lParam );
1037 break;
1038 }
1039 case WM_QUERYDRAGICON:
1040 {
1041 HICON hIcon = 0;
1042 if ((hIcon = (HICON) MSWOnQueryDragIcon()))
1043 return (long)hIcon;
1044 else return MSWDefWindowProc(message, wParam, lParam );
1045 break;
1046 }
1047
1048 case WM_SIZE:
1049 {
1050 int width = LOWORD(lParam);
1051 int height = HIWORD(lParam);
1052 MSWOnSize(width, height, wParam);
1053 break;
1054 }
1055
1056 case WM_WINDOWPOSCHANGING:
1057 {
1058 WINDOWPOS *pos = (WINDOWPOS *)lParam;
1059 MSWOnWindowPosChanging((void *)pos);
1060 break;
1061 }
1062
1063 case WM_RBUTTONDOWN:
1064 {
1065 int x = (DIMENSION_TYPE) LOWORD(lParam);
1066 int y = (DIMENSION_TYPE) HIWORD(lParam);
1067 MSWOnRButtonDown(x, y, wParam);
1068 break;
1069 }
1070 case WM_RBUTTONUP:
1071 {
1072 int x = (DIMENSION_TYPE) LOWORD(lParam);
1073 int y = (DIMENSION_TYPE) HIWORD(lParam);
1074 MSWOnRButtonUp(x, y, wParam);
1075 break;
1076 }
1077 case WM_RBUTTONDBLCLK:
1078 {
1079 int x = (DIMENSION_TYPE) LOWORD(lParam);
1080 int y = (DIMENSION_TYPE) HIWORD(lParam);
1081 MSWOnRButtonDClick(x, y, wParam);
1082 break;
1083 }
1084 case WM_MBUTTONDOWN:
1085 {
1086 int x = (DIMENSION_TYPE) LOWORD(lParam);
1087 int y = (DIMENSION_TYPE) HIWORD(lParam);
1088 MSWOnMButtonDown(x, y, wParam);
1089 break;
1090 }
1091 case WM_MBUTTONUP:
1092 {
1093 int x = (DIMENSION_TYPE) LOWORD(lParam);
1094 int y = (DIMENSION_TYPE) HIWORD(lParam);
1095 MSWOnMButtonUp(x, y, wParam);
1096 break;
1097 }
1098 case WM_MBUTTONDBLCLK:
1099 {
1100 int x = (DIMENSION_TYPE) LOWORD(lParam);
1101 int y = (DIMENSION_TYPE) HIWORD(lParam);
1102 MSWOnMButtonDClick(x, y, wParam);
1103 break;
1104 }
1105 case WM_LBUTTONDOWN:
1106 {
1107 int x = (DIMENSION_TYPE) LOWORD(lParam);
1108 int y = (DIMENSION_TYPE) HIWORD(lParam);
1109 MSWOnLButtonDown(x, y, wParam);
1110 break;
1111 }
1112 case WM_LBUTTONUP:
1113 {
1114 int x = (DIMENSION_TYPE) LOWORD(lParam);
1115 int y = (DIMENSION_TYPE) HIWORD(lParam);
1116 MSWOnLButtonUp(x, y, wParam);
1117 break;
1118 }
1119 case WM_LBUTTONDBLCLK:
1120 {
1121 int x = (DIMENSION_TYPE) LOWORD(lParam);
1122 int y = (DIMENSION_TYPE) HIWORD(lParam);
1123 MSWOnLButtonDClick(x, y, wParam);
1124 break;
1125 }
1126 case WM_MOUSEMOVE:
1127 {
1128 int x = (DIMENSION_TYPE) LOWORD(lParam);
1129 int y = (DIMENSION_TYPE) HIWORD(lParam);
1130 MSWOnMouseMove(x, y, wParam);
1131 break;
1132 }
1133 case MM_JOY1BUTTONDOWN:
1134 {
1135 int x = LOWORD(lParam);
1136 int y = HIWORD(lParam);
1137 MSWOnJoyDown(wxJOYSTICK1, x, y, wParam);
1138 break;
1139 }
1140 case MM_JOY2BUTTONDOWN:
1141 {
1142 int x = LOWORD(lParam);
1143 int y = HIWORD(lParam);
1144 MSWOnJoyDown(wxJOYSTICK2, x, y, wParam);
1145 break;
1146 }
1147 case MM_JOY1BUTTONUP:
1148 {
1149 int x = LOWORD(lParam);
1150 int y = HIWORD(lParam);
1151 MSWOnJoyUp(wxJOYSTICK1, x, y, wParam);
1152 break;
1153 }
1154 case MM_JOY2BUTTONUP:
1155 {
1156 int x = LOWORD(lParam);
1157 int y = HIWORD(lParam);
1158 MSWOnJoyUp(wxJOYSTICK2, x, y, wParam);
1159 break;
1160 }
1161 case MM_JOY1MOVE:
1162 {
1163 int x = LOWORD(lParam);
1164 int y = HIWORD(lParam);
1165 MSWOnJoyMove(wxJOYSTICK1, x, y, wParam);
1166 break;
1167 }
1168 case MM_JOY2MOVE:
1169 {
1170 int x = LOWORD(lParam);
1171 int y = HIWORD(lParam);
1172 MSWOnJoyMove(wxJOYSTICK2, x, y, wParam);
1173 break;
1174 }
1175 case MM_JOY1ZMOVE:
1176 {
1177 int z = LOWORD(lParam);
1178 MSWOnJoyZMove(wxJOYSTICK1, z, wParam);
1179 break;
1180 }
1181 case MM_JOY2ZMOVE:
1182 {
1183 int z = LOWORD(lParam);
1184 MSWOnJoyZMove(wxJOYSTICK2, z, wParam);
1185 break;
1186 }
1187 case WM_DESTROY:
1188 {
1189 if (MSWOnDestroy())
1190 return 0;
1191 else return MSWDefWindowProc(message, wParam, lParam );
1192 break;
1193 }
1194 case WM_SYSCOMMAND:
1195 {
1196 return MSWOnSysCommand(wParam, lParam);
1197 break;
1198 }
1199 case WM_COMMAND:
1200 {
1201 #ifdef __WIN32__
1202 WORD id = LOWORD(wParam);
1203 HWND hwnd = (HWND)lParam;
1204 WORD cmd = HIWORD(wParam);
1205 #else
1206 WORD id = (WORD)wParam;
1207 HWND hwnd = (HWND)LOWORD(lParam) ;
1208 WORD cmd = HIWORD(lParam);
1209 #endif
1210 if (!MSWOnCommand(id, cmd, (WXHWND) hwnd))
1211 return MSWDefWindowProc(message, wParam, lParam );
1212 break;
1213 }
1214 #if defined(__WIN95__)
1215 case WM_NOTIFY:
1216 {
1217 if (!MSWOnNotify(wParam, lParam))
1218 return MSWDefWindowProc(message, wParam, lParam );
1219 break;
1220 }
1221 #endif
1222 case WM_MENUSELECT:
1223 {
1224 #ifdef __WIN32__
1225 WORD flags = HIWORD(wParam);
1226 HMENU sysmenu = (HMENU)lParam;
1227 #else
1228 WORD flags = LOWORD(lParam);
1229 HMENU sysmenu = (HMENU)HIWORD(lParam);
1230 #endif
1231 MSWOnMenuHighlight((WORD)wParam, flags, (WXHMENU) sysmenu);
1232 break;
1233 }
1234 case WM_INITMENUPOPUP:
1235 {
1236 MSWOnInitMenuPopup((WXHMENU) (HMENU)wParam, (int)LOWORD(lParam), (HIWORD(lParam) != 0));
1237 break;
1238 }
1239 case WM_DRAWITEM:
1240 {
1241 return MSWOnDrawItem((int)wParam, (WXDRAWITEMSTRUCT *)lParam);
1242 break;
1243 }
1244 case WM_MEASUREITEM:
1245 {
1246 return MSWOnMeasureItem((int)wParam, (WXMEASUREITEMSTRUCT *)lParam);
1247 break;
1248 }
1249
1250 case WM_KEYDOWN:
1251 {
1252 if (wParam == VK_SHIFT)
1253 return Default();
1254
1255 else if (wParam == VK_CONTROL)
1256 return Default();
1257
1258 // Avoid duplicate messages to OnChar
1259 else if ((wParam != VK_ESCAPE) && (wParam != VK_SPACE) && (wParam != VK_RETURN) && (wParam != VK_BACK) && (wParam != VK_TAB))
1260 {
1261 MSWOnChar((WORD)wParam, lParam);
1262 if (::GetKeyState(VK_CONTROL)&0x100?TRUE:FALSE)
1263 return Default();
1264 }
1265 else
1266 return Default();
1267 }
1268 case WM_KEYUP:
1269 {
1270 break;
1271 }
1272 // VZ: WM_KEYUP not processed
1273 case WM_CHAR: // Always an ASCII character
1274 {
1275 MSWOnChar((WORD)wParam, lParam, TRUE);
1276 break;
1277 }
1278
1279 case WM_HSCROLL:
1280 {
1281 #ifdef __WIN32__
1282 WORD code = LOWORD(wParam);
1283 WORD pos = HIWORD(wParam);
1284 HWND control = (HWND)lParam;
1285 #else
1286 WORD code = (WORD)wParam;
1287 WORD pos = LOWORD(lParam);
1288 HWND control = (HWND)HIWORD(lParam);
1289 #endif
1290 MSWOnHScroll(code, pos, (WXHWND) control);
1291 break;
1292 }
1293 case WM_VSCROLL:
1294 {
1295 #ifdef __WIN32__
1296 WORD code = LOWORD(wParam);
1297 WORD pos = HIWORD(wParam);
1298 HWND control = (HWND)lParam;
1299 #else
1300 WORD code = (WORD)wParam;
1301 WORD pos = LOWORD(lParam);
1302 HWND control = (HWND)HIWORD(lParam);
1303 #endif
1304 MSWOnVScroll(code, pos, (WXHWND) control);
1305 break;
1306 }
1307 #ifdef __WIN32__
1308 case WM_CTLCOLORBTN:
1309 {
1310 int nCtlColor = CTLCOLOR_BTN;
1311 HWND control = (HWND)lParam;
1312 HDC pDC = (HDC)wParam;
1313 return (DWORD)MSWOnCtlColor((WXHDC) pDC, (WXHWND) control, nCtlColor,
1314 message, wParam, lParam);
1315 break;
1316 }
1317 case WM_CTLCOLORDLG:
1318 {
1319 int nCtlColor = CTLCOLOR_DLG;
1320 HWND control = (HWND)lParam;
1321 HDC pDC = (HDC)wParam;
1322 return (DWORD)MSWOnCtlColor((WXHDC) pDC, (WXHWND) control, nCtlColor,
1323 message, wParam, lParam);\
1324 break;
1325 }
1326 case WM_CTLCOLORLISTBOX:
1327 {
1328 int nCtlColor = CTLCOLOR_LISTBOX;
1329 HWND control = (HWND)lParam;
1330 HDC pDC = (HDC)wParam;
1331 return (DWORD)MSWOnCtlColor((WXHDC) pDC, (WXHWND) control, nCtlColor,
1332 message, wParam, lParam);
1333 break;
1334 }
1335 case WM_CTLCOLORMSGBOX:
1336 {
1337 int nCtlColor = CTLCOLOR_MSGBOX;
1338 HWND control = (HWND)lParam;
1339 HDC pDC = (HDC)wParam;
1340 return (DWORD)MSWOnCtlColor((WXHDC) pDC, (WXHWND) control, nCtlColor,
1341 message, wParam, lParam);
1342 break;
1343 }
1344 case WM_CTLCOLORSCROLLBAR:
1345 {
1346 int nCtlColor = CTLCOLOR_SCROLLBAR;
1347 HWND control = (HWND)lParam;
1348 HDC pDC = (HDC)wParam;
1349 return (DWORD)MSWOnCtlColor((WXHDC) pDC, (WXHWND) control, nCtlColor,
1350 message, wParam, lParam);
1351 break;
1352 }
1353 case WM_CTLCOLORSTATIC:
1354 {
1355 int nCtlColor = CTLCOLOR_STATIC;
1356 HWND control = (HWND)lParam;
1357 HDC pDC = (HDC)wParam;
1358 return (DWORD)MSWOnCtlColor((WXHDC) pDC, (WXHWND) control, nCtlColor,
1359 message, wParam, lParam);
1360 break;
1361 }
1362 case WM_CTLCOLOREDIT:
1363 {
1364 int nCtlColor = CTLCOLOR_EDIT;
1365 HWND control = (HWND)lParam;
1366 HDC pDC = (HDC)wParam;
1367 return (DWORD)MSWOnCtlColor((WXHDC) pDC, (WXHWND) control, nCtlColor,
1368 message, wParam, lParam);
1369 break;
1370 }
1371 #else
1372 case WM_CTLCOLOR:
1373 {
1374 HWND control = (HWND)LOWORD(lParam);
1375 int nCtlColor = (int)HIWORD(lParam);
1376 HDC pDC = (HDC)wParam;
1377 return (DWORD)MSWOnCtlColor((WXHDC) pDC, (WXHWND) control, nCtlColor,
1378 message, wParam, lParam);
1379 break;
1380 }
1381 #endif
1382 case WM_SYSCOLORCHANGE:
1383 {
1384 // Return value of 0 means, we processed it.
1385 if (MSWOnColorChange((WXHWND) hWnd, message, wParam, lParam) == 0)
1386 return 0;
1387 else
1388 return MSWDefWindowProc(message, wParam, lParam );
1389 break;
1390 }
1391 case WM_ERASEBKGND:
1392 {
1393 // Prevents flicker when dragging
1394 if (IsIconic(hWnd)) return 1;
1395
1396 // EXPERIMENTAL
1397 // return 1;
1398 if (!MSWOnEraseBkgnd((WXHDC) (HDC)wParam))
1399 return 0; // Default(); MSWDefWindowProc(message, wParam, lParam );
1400 else return 1;
1401 break;
1402 }
1403 case WM_MDIACTIVATE:
1404 {
1405 #ifdef __WIN32__
1406 HWND hWndActivate = GET_WM_MDIACTIVATE_HWNDACTIVATE(wParam,lParam);
1407 HWND hWndDeactivate = GET_WM_MDIACTIVATE_HWNDDEACT(wParam,lParam);
1408 BOOL activate = GET_WM_MDIACTIVATE_FACTIVATE(hWnd,wParam,lParam);
1409 return MSWOnMDIActivate((long) activate, (WXHWND) hWndActivate, (WXHWND) hWndDeactivate);
1410 #else
1411 return MSWOnMDIActivate((BOOL)wParam, (HWND)LOWORD(lParam),
1412 (HWND)HIWORD(lParam));
1413 #endif
1414 }
1415 case WM_DROPFILES:
1416 {
1417 MSWOnDropFiles(wParam);
1418 break;
1419 }
1420 case WM_INITDIALOG:
1421 {
1422 return 0; // MSWOnInitDialog((WXHWND)(HWND)wParam);
1423 break;
1424 }
1425 case WM_QUERYENDSESSION:
1426 {
1427 // Same as WM_CLOSE, but inverted results. Thx Microsoft :-)
1428 return MSWOnClose();
1429 break;
1430 }
1431 case WM_CLOSE:
1432 {
1433 if (MSWOnClose())
1434 return 0L;
1435 else
1436 return 1L;
1437 break;
1438 }
1439
1440 case WM_GETMINMAXINFO:
1441 {
1442 MINMAXINFO *info = (MINMAXINFO *)lParam;
1443 if (m_minSizeX != -1)
1444 info->ptMinTrackSize.x = (int)m_minSizeX;
1445 if (m_minSizeY != -1)
1446 info->ptMinTrackSize.y = (int)m_minSizeY;
1447 if (m_maxSizeX != -1)
1448 info->ptMaxTrackSize.x = (int)m_maxSizeX;
1449 if (m_maxSizeY != -1)
1450 info->ptMaxTrackSize.y = (int)m_maxSizeY;
1451 return MSWDefWindowProc(message, wParam, lParam );
1452 break;
1453 }
1454
1455 /*
1456 #if HAVE_SOCKET
1457 case WM_TIMER:
1458 {
1459 __ddeUnblock(hWnd, wParam);
1460 break;
1461 }
1462
1463 case ASYNC_SELECT_MESSAGE:
1464 return ddeWindowProc(hWnd,message,wParam,lParam);
1465 #endif
1466 */
1467
1468 default:
1469 return MSWDefWindowProc(message, wParam, lParam );
1470 }
1471 return 0; // Success: we processed this command.
1472 }
1473
1474 // Dialog window proc
1475 LONG APIENTRY _EXPORT
1476 wxDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
1477 {
1478 return 0;
1479 }
1480
1481 wxList *wxWinHandleList = NULL;
1482 wxWindow *wxFindWinFromHandle(WXHWND hWnd)
1483 {
1484 wxNode *node = wxWinHandleList->Find((long)hWnd);
1485 if (!node)
1486 return NULL;
1487 return (wxWindow *)node->Data();
1488 }
1489
1490 void wxAssociateWinWithHandle(HWND hWnd, wxWindow *win)
1491 {
1492 // adding NULL hWnd is (first) surely a result of an error and
1493 // (secondly) breaks menu command processing
1494 wxCHECK_RET( hWnd != NULL, "attempt to add a NULL hWnd to window list" );
1495
1496 if ( !wxWinHandleList->Find((long)hWnd) )
1497 wxWinHandleList->Append((long)hWnd, win);
1498 }
1499
1500 void wxRemoveHandleAssociation(wxWindow *win)
1501 {
1502 wxWinHandleList->DeleteObject(win);
1503 }
1504
1505 // Default destroyer - override if you destroy it in some other way
1506 // (e.g. with MDI child windows)
1507 void wxWindow::MSWDestroyWindow(void)
1508 {
1509 #if 0
1510
1511 #if DEBUG > 1
1512 wxDebugMsg("wxWindow::MSWDestroyWindow %d\n", handle);
1513 #endif
1514 MSWDetachWindowMenu();
1515 // SetWindowLong(handle, 0, (long)0);
1516 HWND oldHandle = handle;
1517 handle = NULL;
1518
1519 ::DestroyWindow(oldHandle);
1520
1521 // Menu is destroyed explicitly by wxMDIChild::DestroyWindow,
1522 // or when Windows HWND is deleted if MDI parent or
1523 // SDI frame.
1524 /*
1525 if (m_hMenu)
1526 {
1527 ::DestroyMenu(m_hMenu);
1528 m_hMenu = 0;
1529 }
1530 */
1531 #endif
1532 }
1533
1534 void wxWindow::MSWCreate(const int id, wxWindow *parent, const char *wclass, wxWindow *wx_win, const char *title,
1535 const int x, const int y, const int width, const int height,
1536 const WXDWORD style, const char *dialog_template, const WXDWORD extendedStyle)
1537 {
1538 bool is_dialog = (dialog_template != NULL);
1539 int x1 = CW_USEDEFAULT;
1540 int y1 = 0;
1541 int width1 = CW_USEDEFAULT;
1542 int height1 = 100;
1543
1544 // Find parent's size, if it exists, to set up a possible default
1545 // panel size the size of the parent window
1546 RECT parent_rect;
1547 if (parent)
1548 {
1549 // Was GetWindowRect: JACS 5/5/95
1550 ::GetClientRect((HWND) parent->GetHWND(), &parent_rect);
1551
1552 width1 = parent_rect.right - parent_rect.left;
1553 height1 = parent_rect.bottom - parent_rect.top;
1554 }
1555
1556 if (x > -1) x1 = x;
1557 if (y > -1) y1 = y;
1558 if (width > -1) width1 = width;
1559 if (height > -1) height1 = height;
1560
1561 HWND hParent = NULL;
1562 if (parent)
1563 hParent = (HWND) parent->GetHWND();
1564
1565 wxWndHook = this;
1566
1567 if (is_dialog)
1568 {
1569 // MakeProcInstance doesn't seem to be needed in C7. Is it needed for
1570 // other compilers???
1571 // VZ: it's always needed for Win16 and never for Win32
1572 #ifdef __WIN32__
1573 m_hWnd = (WXHWND) ::CreateDialog(wxGetInstance(), dialog_template, hParent,
1574 (DLGPROC)wxDlgProc);
1575 #else
1576 DLGPROC dlgproc = (DLGPROC)MakeProcInstance((DLGPROC)wxWndProc, wxGetInstance());
1577
1578 m_hWnd = (WXHWND) ::CreateDialog(wxGetInstance(), dialog_template, hParent,
1579 (DLGPROC)dlgproc);
1580 #endif
1581
1582 if (m_hWnd == 0)
1583 MessageBox(NULL, "Can't find dummy dialog template!\nCheck resource include path for finding wx.rc.",
1584 "wxWindows Error", MB_ICONEXCLAMATION | MB_OK);
1585 else MoveWindow((HWND) m_hWnd, x1, y1, width1, height1, FALSE);
1586 }
1587 else
1588 {
1589 int controlId = 0;
1590 if (style & WS_CHILD)
1591 controlId = id;
1592 if (!title)
1593 title = "";
1594
1595 m_hWnd = (WXHWND) CreateWindowEx(extendedStyle, wclass,
1596 title,
1597 style,
1598 x1, y1,
1599 width1, height1,
1600 // hParent, NULL, wxGetInstance(),
1601 hParent, (HMENU)controlId, wxGetInstance(),
1602 NULL);
1603
1604 if (m_hWnd == 0)
1605 {
1606 char buf[300];
1607 sprintf(buf, "Can't create window of class %s! Weird.\nPossible Windows 3.x compatibility problem?",
1608 wclass);
1609 wxFatalError(buf,
1610 "Fatal wxWindows Error");
1611 }
1612 }
1613 wxWndHook = NULL;
1614 wxWinHandleList->Append((long)m_hWnd, this);
1615
1616 #if DEBUG > 1
1617 wxDebugMsg("wxWindow::MSWCreate %d\n", m_hWnd);
1618 #endif
1619 }
1620
1621 void wxWindow::MSWOnCreate(WXLPCREATESTRUCT WXUNUSED(cs))
1622 {
1623 }
1624
1625 bool wxWindow::MSWOnClose(void)
1626 {
1627 #if DEBUG > 1
1628 wxDebugMsg("wxWindow::MSWOnClose %d\n", handle);
1629 #endif
1630 return FALSE;
1631 }
1632
1633 bool wxWindow::MSWOnDestroy(void)
1634 {
1635 #if DEBUG > 1
1636 wxDebugMsg("wxWindow::MSWOnDestroy %d\n", handle);
1637 #endif
1638 // delete our drop target if we've got one
1639 #if USE_DRAG_AND_DROP
1640 if ( m_pDropTarget != NULL ) {
1641 m_pDropTarget->Revoke(m_hWnd);
1642
1643 delete m_pDropTarget;
1644 m_pDropTarget = NULL;
1645 }
1646 #endif
1647
1648 return TRUE;
1649 }
1650
1651 // Deal with child commands from buttons etc.
1652
1653 bool wxWindow::MSWOnNotify(const WXWPARAM wParam, const WXLPARAM lParam)
1654 {
1655 #if defined(__WIN95__)
1656 // Find a child window to send the notification to, e.g. a toolbar.
1657 // There's a problem here. NMHDR::hwndFrom doesn't give us the
1658 // handle of the toolbar; it's probably the handle of the tooltip
1659 // window (anyway, it's parent is also the toolbar's parent).
1660 // So, since we don't know which hWnd or wxWindow originated the
1661 // WM_NOTIFY, we'll need to go through all the children of this window
1662 // trying out MSWNotify.
1663 // This won't work now, though, because any number of controls
1664 // could respond to the same generic messages :-(
1665
1666 /* This doesn't work for toolbars, but try for other controls first.
1667 */
1668 NMHDR *hdr = (NMHDR *)lParam;
1669 HWND hWnd = (HWND)hdr->hwndFrom;
1670 wxWindow *win = wxFindWinFromHandle((WXHWND) hWnd);
1671
1672 if ( win )
1673 return win->MSWNotify(wParam, lParam);
1674 else
1675 {
1676 // Rely on MSWNotify to check whether the message
1677 // belongs to the window or not
1678 wxNode *node = GetChildren()->First();
1679 while (node)
1680 {
1681 wxWindow *child = (wxWindow *)node->Data();
1682 if ( child->MSWNotify(wParam, lParam) )
1683 return TRUE;
1684 node = node->Next();
1685 }
1686 }
1687
1688 return FALSE;
1689
1690 #endif
1691 return FALSE;
1692 }
1693
1694 void wxWindow::MSWOnMenuHighlight(const WXWORD WXUNUSED(item), const WXWORD WXUNUSED(flags), const WXHMENU WXUNUSED(sysmenu))
1695 {
1696 #if DEBUG > 1
1697 wxDebugMsg("wxWindow::MSWOnMenuHighlight %d\n", handle);
1698 #endif
1699 }
1700
1701 void wxWindow::MSWOnInitMenuPopup(const WXHMENU menu, const int pos, const bool isSystem)
1702 {
1703 if (!isSystem)
1704 OldOnInitMenuPopup(pos);
1705 }
1706
1707 bool wxWindow::MSWOnActivate(const int state, const bool WXUNUSED(minimized), const WXHWND WXUNUSED(activate))
1708 {
1709 #if DEBUG > 1
1710 wxDebugMsg("wxWindow::MSWOnActivate %d\n", handle);
1711 #endif
1712
1713 #if WXWIN_COMPATIBILITY
1714 GetEventHandler()->OldOnActivate(((state == WA_ACTIVE) || (state == WA_CLICKACTIVE)));
1715 #else
1716 wxActivateEvent event(wxEVT_ACTIVATE, ((state == WA_ACTIVE) || (state == WA_CLICKACTIVE)),
1717 m_windowId);
1718 event.m_eventObject = this;
1719 GetEventHandler()->ProcessEvent(event);
1720 #endif
1721 return 0;
1722 }
1723
1724 bool wxWindow::MSWOnSetFocus(const WXHWND WXUNUSED(hwnd))
1725 {
1726 #if DEBUG > 1
1727 wxDebugMsg("wxWindow::MSWOnSetFocus %d\n", m_hWnd);
1728 #endif
1729 // Deal with caret
1730 if (m_caretEnabled && (m_caretWidth > 0) && (m_caretHeight > 0))
1731 {
1732 ::CreateCaret((HWND) GetHWND(), NULL, m_caretWidth, m_caretHeight);
1733 if (m_caretShown)
1734 ::ShowCaret((HWND) GetHWND());
1735 }
1736
1737 #if WXWIN_COMPATIBILITY
1738 GetEventHandler()->OldOnSetFocus();
1739 #else
1740 wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
1741 event.m_eventObject = this;
1742 GetEventHandler()->ProcessEvent(event);
1743 #endif
1744 return TRUE;
1745 }
1746
1747 bool wxWindow::MSWOnKillFocus(const WXHWND WXUNUSED(hwnd))
1748 {
1749 #if DEBUG > 1
1750 wxDebugMsg("wxWindow::MSWOnKillFocus %d\n", m_hWnd);
1751 #endif
1752 // Deal with caret
1753 if (m_caretEnabled)
1754 {
1755 ::DestroyCaret();
1756 }
1757
1758 #if WXWIN_COMPATIBILITY
1759 GetEventHandler()->OldOnKillFocus();
1760 #else
1761 wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId);
1762 event.m_eventObject = this;
1763 GetEventHandler()->ProcessEvent(event);
1764 #endif
1765 return TRUE;
1766 }
1767
1768 void wxWindow::MSWOnDropFiles(const WXWPARAM wParam)
1769 {
1770 #if DEBUG > 1
1771 wxDebugMsg("wxWindow::MSWOnDropFiles %d\n", m_hWnd);
1772 #endif
1773
1774 HANDLE hFilesInfo = (HANDLE)wParam;
1775 POINT dropPoint;
1776 DragQueryPoint(hFilesInfo, (LPPOINT) &dropPoint);
1777
1778 // Get the total number of files dropped
1779 WORD gwFilesDropped = (WORD)DragQueryFile ((HDROP)hFilesInfo,
1780 (UINT)-1,
1781 (LPSTR)0,
1782 (UINT)0);
1783
1784 wxString *files = new wxString[gwFilesDropped];
1785 int wIndex;
1786 for (wIndex=0; wIndex < (int)gwFilesDropped; wIndex++)
1787 {
1788 DragQueryFile (hFilesInfo, wIndex, (LPSTR) wxBuffer, 1000);
1789 files[wIndex] = wxBuffer;
1790 }
1791 DragFinish (hFilesInfo);
1792
1793 wxDropFilesEvent event(wxEVT_DROP_FILES, gwFilesDropped, files);
1794 event.m_eventObject = this;
1795 event.m_pos.x = dropPoint.x; event.m_pos.x = dropPoint.y;
1796
1797 GetEventHandler()->ProcessEvent(event);
1798
1799 delete[] files;
1800 }
1801
1802 bool wxWindow::MSWOnDrawItem(const int id, WXDRAWITEMSTRUCT *itemStruct)
1803 {
1804 #if USE_OWNER_DRAWN
1805 if ( id == 0 ) { // is it a menu item?
1806 DRAWITEMSTRUCT *pDrawStruct = (DRAWITEMSTRUCT *)itemStruct;
1807 wxMenuItem *pMenuItem = (wxMenuItem *)(pDrawStruct->itemData);
1808 wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
1809
1810 // prepare to call OnDrawItem()
1811 wxDC dc;
1812 dc.SetHDC((WXHDC)pDrawStruct->hDC, FALSE);
1813 wxRect rect(pDrawStruct->rcItem.left, pDrawStruct->rcItem.top,
1814 pDrawStruct->rcItem.right - pDrawStruct->rcItem.left,
1815 pDrawStruct->rcItem.bottom - pDrawStruct->rcItem.top);
1816 return pMenuItem->OnDrawItem(
1817 dc, rect,
1818 (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction,
1819 (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
1820 );
1821 }
1822 #endif // owner-drawn menus
1823
1824 wxWindow *item = FindItem(id);
1825 #if USE_DYNAMIC_CLASSES
1826 if (item && item->IsKindOf(CLASSINFO(wxControl)))
1827 {
1828 return ((wxControl *)item)->MSWOnDraw(itemStruct);
1829 }
1830 else
1831 #endif
1832 return FALSE;
1833 }
1834
1835 bool wxWindow::MSWOnMeasureItem(const int id, WXMEASUREITEMSTRUCT *itemStruct)
1836 {
1837 #if USE_OWNER_DRAWN
1838 if ( id == 0 ) { // is it a menu item?
1839 MEASUREITEMSTRUCT *pMeasureStruct = (MEASUREITEMSTRUCT *)itemStruct;
1840 wxMenuItem *pMenuItem = (wxMenuItem *)(pMeasureStruct->itemData);
1841 wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
1842
1843 return pMenuItem->OnMeasureItem(&pMeasureStruct->itemWidth,
1844 &pMeasureStruct->itemHeight);
1845 }
1846 #endif // owner-drawn menus
1847
1848 wxWindow *item = FindItem(id);
1849 #if USE_DYNAMIC_CLASSES
1850 if (item && item->IsKindOf(CLASSINFO(wxControl)))
1851 {
1852 return ((wxControl *)item)->MSWOnMeasure(itemStruct);
1853 }
1854 else
1855 #endif
1856 return FALSE;
1857 }
1858
1859 WXHBRUSH wxWindow::MSWOnCtlColor(const WXHDC pDC, const WXHWND pWnd, const WXUINT nCtlColor,
1860 const WXUINT message, const WXWPARAM wParam, const WXLPARAM lParam)
1861 {
1862 #if DEBUG > 1
1863 wxDebugMsg("wxWindow::MSWOnCtlColour %d\n", m_hWnd);
1864 #endif
1865 if (nCtlColor == CTLCOLOR_DLG)
1866 {
1867 return OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
1868 }
1869
1870 wxControl *item = (wxControl *)FindItemByHWND(pWnd, TRUE);
1871
1872 WXHBRUSH hBrush = 0;
1873
1874 if ( item )
1875 hBrush = item->OnCtlColor(pDC, pWnd, nCtlColor, message, wParam, lParam);
1876
1877 // I think that even for dialogs, we may need to call DefWindowProc (?)
1878 // Or maybe just rely on the usual default behaviour.
1879 if ( !hBrush )
1880 hBrush = (WXHBRUSH) MSWDefWindowProc(message, wParam, lParam);
1881
1882 return hBrush ;
1883 }
1884
1885 // Define for each class of dialog and control
1886 WXHBRUSH wxWindow::OnCtlColor(const WXHDC pDC, const WXHWND pWnd, const WXUINT nCtlColor,
1887 WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
1888 {
1889 return (WXHBRUSH) MSWDefWindowProc(message, wParam, lParam);
1890 }
1891
1892 bool wxWindow::MSWOnColorChange(const WXHWND hWnd, const WXUINT message, const WXWPARAM wParam, const WXLPARAM lParam)
1893 {
1894 wxSysColourChangedEvent event;
1895 event.m_eventObject = this;
1896
1897 // Check if app handles this.
1898 if (GetEventHandler()->ProcessEvent(event))
1899 return 0;
1900
1901 #if WXWIN_COMPATIBILITY
1902 if (GetEventHandler()->OldOnSysColourChange())
1903 return 0;
1904 #endif
1905
1906 // We didn't process it
1907 return 1;
1908 }
1909
1910 // Responds to colour changes: passes event on to children.
1911 void wxWindow::OnSysColourChanged(wxSysColourChangedEvent& event)
1912 {
1913 wxNode *node = GetChildren()->First();
1914 while ( node )
1915 {
1916 // Only propagate to non-top-level windows
1917 wxWindow *win = (wxWindow *)node->Data();
1918 if ( win->GetParent() )
1919 {
1920 wxSysColourChangedEvent event2;
1921 event.m_eventObject = win;
1922 win->GetEventHandler()->ProcessEvent(event2);
1923 }
1924
1925 node = node->Next();
1926 }
1927 }
1928
1929 long wxWindow::MSWDefWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
1930 {
1931 if ( m_oldWndProc )
1932 return ::CallWindowProc(CASTWNDPROC (FARPROC) m_oldWndProc, (HWND) GetHWND(), (UINT) nMsg, (WPARAM) wParam, (LPARAM) lParam);
1933 else
1934 return ::DefWindowProc((HWND) GetHWND(), nMsg, wParam, lParam);
1935 }
1936
1937 long wxWindow::Default()
1938 {
1939 // Ignore 'fake' events (perhaps generated as a result of a separate real event)
1940 if (m_lastMsg == 0)
1941 return 0;
1942
1943 return this->MSWDefWindowProc(m_lastMsg, m_lastWParam, m_lastLParam);
1944 }
1945
1946 bool wxWindow::MSWProcessMessage(WXMSG* pMsg)
1947 {
1948 if (!m_hWnd)
1949 return FALSE;
1950 else
1951 {
1952 // Suggestion by Andrew Davison to allow
1953 // a panel to accept character input in user edit mode
1954
1955 // OK, what we probably want to do here for wxWin 2.0
1956 // is have a window style to indicate whether the window
1957 // should process dialog-style input, since we can't
1958 // otherwise tell whether it's supposed to do tab traversal
1959 // or not.
1960 if (GetWindowStyleFlag() & wxTAB_TRAVERSAL)
1961 return (::IsDialogMessage((HWND) m_hWnd, (MSG *)pMsg) != 0);
1962 else
1963 return FALSE;
1964 }
1965 }
1966
1967 long wxWindow::MSWOnMDIActivate(const long WXUNUSED(flag), const WXHWND WXUNUSED(activate), const WXHWND WXUNUSED(deactivate))
1968 {
1969 #if DEBUG > 1
1970 wxDebugMsg("wxWindow::MSWOnMDIActivate %d\n", m_hWnd);
1971 #endif
1972 return 1;
1973 }
1974
1975 void wxWindow::MSWDetachWindowMenu(void)
1976 {
1977 if (m_hMenu)
1978 {
1979 int N = GetMenuItemCount((HMENU) m_hMenu);
1980 int i;
1981 for (i = 0; i < N; i++)
1982 {
1983 char buf[100];
1984 int chars = GetMenuString((HMENU) m_hMenu, i, buf, 100, MF_BYPOSITION);
1985 if ((chars > 0) && (strcmp(buf, "&Window") == 0))
1986 {
1987 RemoveMenu((HMENU) m_hMenu, i, MF_BYPOSITION);
1988 break;
1989 }
1990 }
1991 }
1992 }
1993
1994 bool wxWindow::MSWOnPaint(void)
1995 {
1996 #if WXWIN_COMPATIBILITY
1997 GetEventHandler()->OldOnPaint();
1998 #else
1999 wxPaintEvent event(m_windowId);
2000 event.m_eventObject = this;
2001 GetEventHandler()->ProcessEvent(event);
2002 #endif
2003 return TRUE;
2004 }
2005
2006 void wxWindow::MSWOnSize(const int w, const int h, const WXUINT WXUNUSED(flag))
2007 {
2008 if (m_inOnSize)
2009 return;
2010
2011 #if DEBUG > 1
2012 wxDebugMsg("wxWindow::MSWOnSize %d\n", m_hWnd);
2013 #endif
2014 if (!m_hWnd)
2015 return;
2016
2017 m_inOnSize = TRUE;
2018
2019 #if WXWIN_COMPATIBILITY
2020 GetEventHandler()->OldOnSize(w, h);
2021 #else
2022 wxSizeEvent event(wxSize(w, h), m_windowId);
2023 event.m_eventObject = this;
2024 GetEventHandler()->ProcessEvent(event);
2025 #endif
2026
2027 m_inOnSize = FALSE;
2028 }
2029
2030 void wxWindow::MSWOnWindowPosChanging(void *WXUNUSED(lpPos))
2031 {
2032 Default();
2033 }
2034
2035 // Deal with child commands from buttons etc.
2036 bool wxWindow::MSWOnCommand(const WXWORD id, const WXWORD cmd, const WXHWND WXUNUSED(control))
2037 {
2038 #if DEBUG > 1
2039 wxDebugMsg("wxWindow::MSWOnCommand\n");
2040 #endif
2041 if (wxCurrentPopupMenu)
2042 {
2043 wxMenu *popupMenu = wxCurrentPopupMenu;
2044 wxCurrentPopupMenu = NULL;
2045 bool succ = popupMenu->MSWCommand(cmd, id);
2046 return succ;
2047 }
2048 #if DEBUG > 1
2049 char buf[80];
2050 sprintf(buf, "Looking for item %d...\n", id);
2051 wxDebugMsg(buf);
2052 #endif
2053
2054 wxWindow *item = FindItem(id);
2055 if (item)
2056 {
2057 bool value = item->MSWCommand(cmd, id);
2058 #if DEBUG > 1
2059 if (value)
2060 wxDebugMsg("MSWCommand succeeded\n");
2061 else
2062 wxDebugMsg("MSWCommand failed\n");
2063 #endif
2064 return value;
2065 }
2066 else
2067 {
2068 #if DEBUG > 1
2069 wxDebugMsg("Could not find item!\n");
2070 char buf[100];
2071 wxDebugMsg("Item ids for this panel:\n");
2072
2073 wxNode *current = GetChildren()->First();
2074 while (current)
2075 {
2076 wxObject *obj = (wxObject *)current->Data() ;
2077 if (obj->IsKindOf(CLASSINFO(wxControl)))
2078 {
2079 wxControl *item = (wxControl *)current->Data();
2080 sprintf(buf, " %d\n", (int)item->m_windowId);
2081 wxDebugMsg(buf);
2082 }
2083 current = current->Next();
2084 }
2085 wxYield();
2086 #endif
2087 return FALSE;
2088 }
2089 }
2090
2091 long wxWindow::MSWOnSysCommand(WXWPARAM wParam, WXLPARAM lParam)
2092 {
2093 switch (wParam)
2094 {
2095 case SC_MAXIMIZE:
2096 {
2097 wxMaximizeEvent event(m_windowId);
2098 event.SetEventObject(this);
2099 if (!GetEventHandler()->ProcessEvent(event))
2100 return Default();
2101 else
2102 return 0;
2103 break;
2104 }
2105 case SC_MINIMIZE:
2106 {
2107 wxIconizeEvent event(m_windowId);
2108 event.SetEventObject(this);
2109 if (!GetEventHandler()->ProcessEvent(event))
2110 return Default();
2111 else
2112 return 0;
2113 break;
2114 }
2115 default:
2116 return Default();
2117 }
2118 return 0;
2119 }
2120
2121 void wxWindow::MSWOnLButtonDown(const int x, const int y, const WXUINT flags)
2122 {
2123 #if 0 // defined(__WIN32__) && !defined(WIN95)
2124 // DClick not clean supported on Win3.1, except if someone know
2125 // how to emulate Sleep()...
2126 // This means that your app will receive Down-Up-Dclick sequences
2127 // rather than Dclick
2128 if (m_doubleClickAllowed)
2129 {
2130 UINT time = GetDoubleClickTime() ;
2131 Sleep(time) ;
2132 MSG dummy ;
2133 if (PeekMessage(&dummy,m_hWnd,
2134 WM_LBUTTONDBLCLK,WM_LBUTTONDBLCLK,
2135 PM_NOREMOVE)
2136 )
2137 {
2138 PeekMessage(&dummy,m_hWnd,WM_LBUTTONUP,WM_LBUTTONUP,PM_REMOVE);
2139 return;
2140 }
2141 }
2142 #endif
2143
2144 wxMouseEvent event(wxEVT_LEFT_DOWN);
2145
2146 event.m_x = x; event.m_y = y;
2147 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2148 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2149 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2150 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2151 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2152 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2153 event.m_eventObject = this;
2154
2155 m_lastXPos = event.m_x; m_lastYPos = event.m_y; m_lastEvent = wxEVENT_TYPE_LEFT_DOWN;
2156 GetEventHandler()->OldOnMouseEvent(event);
2157 }
2158
2159 void wxWindow::MSWOnLButtonUp(const int x, const int y, const WXUINT flags)
2160 {
2161 wxMouseEvent event(wxEVT_LEFT_UP);
2162
2163 event.m_x = x; event.m_y = y;
2164 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2165 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2166 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2167 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2168 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2169 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2170 event.m_eventObject = this;
2171
2172 m_lastXPos = event.m_x; m_lastYPos = event.m_y; m_lastEvent = wxEVT_LEFT_UP;
2173
2174 GetEventHandler()->OldOnMouseEvent(event);
2175 }
2176
2177 void wxWindow::MSWOnLButtonDClick(const int x, const int y, const WXUINT flags)
2178 {
2179 wxMouseEvent event(wxEVT_LEFT_DCLICK);
2180
2181 event.m_x = x; event.m_y = y;
2182 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2183 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2184 event.m_leftDown = ((flags & MK_LBUTTON != 0));
2185 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2186 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2187 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2188 event.m_eventObject = this;
2189
2190 m_lastXPos = event.m_x; m_lastYPos = event.m_y; m_lastEvent = wxEVT_LEFT_DCLICK;
2191
2192 // if (m_doubleClickAllowed)
2193 GetEventHandler()->OldOnMouseEvent(event);
2194 }
2195
2196 void wxWindow::MSWOnMButtonDown(const int x, const int y, const WXUINT flags)
2197 {
2198 #if 0 // defined(__WIN32__) && !defined(__WIN95__)
2199 // DClick not clean supported on Win3.1, except if someone know
2200 // how to emulate Sleep()...
2201 // This means that your app will receive Down-Up-Dclick sequences
2202 // rather than Dclick
2203 if (m_doubleClickAllowed)
2204 {
2205 UINT time = GetDoubleClickTime() ;
2206 Sleep(time) ;
2207 MSG dummy ;
2208 if (PeekMessage(&dummy,m_hWnd,
2209 WM_MBUTTONDBLCLK,WM_MBUTTONDBLCLK,
2210 PM_NOREMOVE)
2211 )
2212 {
2213 PeekMessage(&dummy,m_hWnd,WM_MBUTTONUP,WM_MBUTTONUP,PM_REMOVE);
2214 return;
2215 }
2216 }
2217 #endif
2218
2219 wxMouseEvent event(wxEVT_MIDDLE_DOWN);
2220
2221 event.m_x = x; event.m_y = y;
2222 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2223 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2224 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2225 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2226 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2227 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2228 event.m_eventObject = this;
2229
2230 m_lastXPos = event.m_x; m_lastYPos = event.m_y; m_lastEvent = wxEVT_MIDDLE_DOWN;
2231 GetEventHandler()->OldOnMouseEvent(event);
2232 }
2233
2234 void wxWindow::MSWOnMButtonUp(const int x, const int y, const WXUINT flags)
2235 {
2236 //wxDebugMsg("MButtonUp\n") ;
2237 wxMouseEvent event(wxEVT_MIDDLE_UP);
2238
2239 event.m_x = x; event.m_y = y;
2240 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2241 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2242 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2243 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2244 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2245 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2246 event.m_eventObject = this;
2247
2248 m_lastXPos = event.m_x; m_lastYPos = event.m_y; m_lastEvent = wxEVT_MIDDLE_UP;
2249 GetEventHandler()->OldOnMouseEvent(event);
2250 }
2251
2252 void wxWindow::MSWOnMButtonDClick(const int x, const int y, const WXUINT flags)
2253 {
2254 wxMouseEvent event(wxEVT_MIDDLE_DCLICK);
2255
2256 event.m_x = x; event.m_y = y;
2257 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2258 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2259 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2260 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2261 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2262 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2263 event.m_eventObject = this;
2264
2265 m_lastXPos = event.m_x; m_lastYPos = event.m_y; m_lastEvent = wxEVT_MIDDLE_DCLICK;
2266 // if (m_doubleClickAllowed)
2267 GetEventHandler()->OldOnMouseEvent(event);
2268 }
2269
2270 void wxWindow::MSWOnRButtonDown(const int x, const int y, const WXUINT flags)
2271 {
2272 #if 0 // defined(__WIN32__) && !defined(__WIN95__)
2273 // DClick not clean supported on Win3.1, except if someone know
2274 // how to emulate Sleep()...
2275 // This means that your app will receive Down-Up-Dclick sequences
2276 // rather than Dclick
2277 if (m_doubleClickAllowed)
2278 {
2279 UINT time = GetDoubleClickTime() ;
2280 Sleep(time) ;
2281 MSG dummy ;
2282 if (PeekMessage(&dummy,m_hWnd,
2283 WM_RBUTTONDBLCLK,WM_RBUTTONDBLCLK,
2284 PM_NOREMOVE)
2285 )
2286 {
2287 PeekMessage(&dummy,m_hWnd,WM_RBUTTONUP,WM_RBUTTONUP,PM_REMOVE);
2288 return;
2289 }
2290 }
2291 #endif
2292
2293 wxMouseEvent event(wxEVT_RIGHT_DOWN);
2294
2295 event.m_x = x; event.m_y = y;
2296 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2297 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2298 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2299 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2300 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2301 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2302 event.m_eventObject = this;
2303
2304 m_lastXPos = event.m_x; m_lastYPos = event.m_y; m_lastEvent = wxEVT_RIGHT_DOWN;
2305 GetEventHandler()->OldOnMouseEvent(event);
2306 }
2307
2308 void wxWindow::MSWOnRButtonUp(const int x, const int y, const WXUINT flags)
2309 {
2310 wxMouseEvent event(wxEVT_RIGHT_UP);
2311
2312 event.m_x = x; event.m_y = y;
2313 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2314 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2315 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2316 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2317 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2318 event.m_eventObject = this;
2319 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2320
2321 m_lastXPos = event.m_x; m_lastYPos = event.m_y; m_lastEvent = wxEVT_RIGHT_UP;
2322 GetEventHandler()->OldOnMouseEvent(event);
2323 }
2324
2325 void wxWindow::MSWOnRButtonDClick(const int x, const int y, const WXUINT flags)
2326 {
2327 wxMouseEvent event(wxEVT_RIGHT_DCLICK);
2328
2329 event.m_x = x; event.m_y = y;
2330 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2331 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2332 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2333 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2334 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2335 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2336 event.m_eventObject = this;
2337
2338 m_lastXPos = event.m_x; m_lastYPos = event.m_y; m_lastEvent = wxEVT_RIGHT_DCLICK;
2339 // if (m_doubleClickAllowed)
2340 GetEventHandler()->OldOnMouseEvent(event);
2341 }
2342
2343 void wxWindow::MSWOnMouseMove(const int x, const int y, const WXUINT flags)
2344 {
2345 // 'normal' move event...
2346 // Set cursor, but only if we're not in 'busy' mode
2347
2348 // Trouble with this is that it sets the cursor for controls too :-(
2349 if (m_windowCursor.Ok() && !wxIsBusy())
2350 ::SetCursor((HCURSOR) m_windowCursor.GetHCURSOR());
2351
2352 if (!m_mouseInWindow)
2353 {
2354 // Generate an ENTER event
2355 m_mouseInWindow = TRUE;
2356 MSWOnMouseEnter(x, y, flags);
2357 }
2358
2359 wxMouseEvent event(wxEVT_MOTION);
2360
2361 event.m_x = x; event.m_y = y;
2362 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2363 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2364 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2365 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2366 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2367 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2368 event.m_eventObject = this;
2369
2370 // Window gets a click down message followed by a mouse move
2371 // message even if position isn't changed! We want to discard
2372 // the trailing move event if x and y are the same.
2373 if ((m_lastEvent == wxEVT_RIGHT_DOWN || m_lastEvent == wxEVT_LEFT_DOWN ||
2374 m_lastEvent == wxEVT_MIDDLE_DOWN) &&
2375 (m_lastXPos == event.m_x && m_lastYPos == event.m_y))
2376 {
2377 m_lastXPos = event.m_x; m_lastYPos = event.m_y;
2378 m_lastEvent = wxEVT_MOTION;
2379 return;
2380 }
2381
2382 m_lastEvent = wxEVT_MOTION;
2383 m_lastXPos = event.m_x; m_lastYPos = event.m_y;
2384 GetEventHandler()->OldOnMouseEvent(event);
2385 }
2386
2387 void wxWindow::MSWOnMouseEnter(const int x, const int y, const WXUINT flags)
2388 {
2389 wxMouseEvent event(wxEVT_ENTER_WINDOW);
2390
2391 event.m_x = x; event.m_y = y;
2392 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2393 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2394 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2395 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2396 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2397 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2398 event.m_eventObject = this;
2399
2400 m_lastEvent = wxEVT_ENTER_WINDOW;
2401 m_lastXPos = event.m_x; m_lastYPos = event.m_y;
2402 // No message - ensure we don't try to call the default behaviour accidentally.
2403 m_lastMsg = 0;
2404 GetEventHandler()->ProcessEvent(event);
2405 }
2406
2407 void wxWindow::MSWOnMouseLeave(const int x, const int y, const WXUINT flags)
2408 {
2409 wxMouseEvent event(wxEVT_LEAVE_WINDOW);
2410
2411 event.m_x = x; event.m_y = y;
2412 event.m_shiftDown = ((flags & MK_SHIFT) != 0);
2413 event.m_controlDown = ((flags & MK_CONTROL) != 0);
2414 event.m_leftDown = ((flags & MK_LBUTTON) != 0);
2415 event.m_middleDown = ((flags & MK_MBUTTON) != 0);
2416 event.m_rightDown = ((flags & MK_RBUTTON) != 0);
2417 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2418 event.m_eventObject = this;
2419
2420 m_lastEvent = wxEVT_LEAVE_WINDOW;
2421 m_lastXPos = event.m_x; m_lastYPos = event.m_y;
2422 // No message - ensure we don't try to call the default behaviour accidentally.
2423 m_lastMsg = 0;
2424 GetEventHandler()->ProcessEvent(event);
2425 }
2426
2427 void wxWindow::MSWOnChar(const WXWORD wParam, const WXLPARAM lParam, const bool isASCII)
2428 {
2429 int id;
2430 bool tempControlDown = FALSE;
2431 if (isASCII)
2432 {
2433 // If 1 -> 26, translate to CTRL plus a letter.
2434 id = wParam;
2435 if ((id > 0) && (id < 27))
2436 {
2437 switch (id)
2438 {
2439 case 13:
2440 {
2441 id = WXK_RETURN;
2442 break;
2443 }
2444 case 8:
2445 {
2446 id = WXK_BACK;
2447 break;
2448 }
2449 case 9:
2450 {
2451 id = WXK_TAB;
2452 break;
2453 }
2454 default:
2455 {
2456 tempControlDown = TRUE;
2457 id = id + 96;
2458 }
2459 }
2460 }
2461 }
2462 else if ((id = wxCharCodeMSWToWX(wParam)) == 0) {
2463 // it's ASCII and will be processed here only when called from
2464 // WM_CHAR (i.e. when isASCII = TRUE)
2465 id = -1;
2466 }
2467
2468 if (id != -1)
2469 {
2470 wxKeyEvent event(wxEVT_CHAR);
2471 event.m_shiftDown = (::GetKeyState(VK_SHIFT)&0x100?TRUE:FALSE);
2472 event.m_controlDown = (::GetKeyState(VK_CONTROL)&0x100?TRUE:FALSE);
2473 if ((HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN)
2474 event.m_altDown = TRUE;
2475
2476 event.m_eventObject = this;
2477 event.m_keyCode = id;
2478 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
2479
2480 POINT pt ;
2481 GetCursorPos(&pt) ;
2482 RECT rect ;
2483 GetWindowRect((HWND) GetHWND(),&rect) ;
2484 pt.x -= rect.left ;
2485 pt.y -= rect.top ;
2486
2487 event.m_x = pt.x; event.m_y = pt.y;
2488
2489 #if WXWIN_COMPATIBILITY
2490 GetEventHandler()->OldOnChar(event);
2491 #else
2492 if (!GetEventHandler()->ProcessEvent(event))
2493 Default();
2494 #endif
2495 }
2496 }
2497
2498 void wxWindow::MSWOnJoyDown(const int joystick, const int x, const int y, const WXUINT flags)
2499 {
2500 int buttons = 0;
2501 int change = 0;
2502 if (flags & JOY_BUTTON1CHG)
2503 change = wxJOY_BUTTON1;
2504 if (flags & JOY_BUTTON2CHG)
2505 change = wxJOY_BUTTON2;
2506 if (flags & JOY_BUTTON3CHG)
2507 change = wxJOY_BUTTON3;
2508 if (flags & JOY_BUTTON4CHG)
2509 change = wxJOY_BUTTON4;
2510
2511 if (flags & JOY_BUTTON1)
2512 buttons |= wxJOY_BUTTON1;
2513 if (flags & JOY_BUTTON2)
2514 buttons |= wxJOY_BUTTON2;
2515 if (flags & JOY_BUTTON3)
2516 buttons |= wxJOY_BUTTON3;
2517 if (flags & JOY_BUTTON4)
2518 buttons |= wxJOY_BUTTON4;
2519
2520 wxJoystickEvent event(wxEVT_JOY_BUTTON_DOWN, buttons, joystick, change);
2521 event.SetPosition(wxPoint(x, y));
2522 event.SetEventObject(this);
2523
2524 GetEventHandler()->ProcessEvent(event);
2525 }
2526
2527 void wxWindow::MSWOnJoyUp(const int joystick, const int x, const int y, const WXUINT flags)
2528 {
2529 int buttons = 0;
2530 int change = 0;
2531 if (flags & JOY_BUTTON1CHG)
2532 change = wxJOY_BUTTON1;
2533 if (flags & JOY_BUTTON2CHG)
2534 change = wxJOY_BUTTON2;
2535 if (flags & JOY_BUTTON3CHG)
2536 change = wxJOY_BUTTON3;
2537 if (flags & JOY_BUTTON4CHG)
2538 change = wxJOY_BUTTON4;
2539
2540 if (flags & JOY_BUTTON1)
2541 buttons |= wxJOY_BUTTON1;
2542 if (flags & JOY_BUTTON2)
2543 buttons |= wxJOY_BUTTON2;
2544 if (flags & JOY_BUTTON3)
2545 buttons |= wxJOY_BUTTON3;
2546 if (flags & JOY_BUTTON4)
2547 buttons |= wxJOY_BUTTON4;
2548
2549 wxJoystickEvent event(wxEVT_JOY_BUTTON_UP, buttons, joystick, change);
2550 event.SetPosition(wxPoint(x, y));
2551 event.SetEventObject(this);
2552
2553 GetEventHandler()->ProcessEvent(event);
2554 }
2555
2556 void wxWindow::MSWOnJoyMove(const int joystick, const int x, const int y, const WXUINT flags)
2557 {
2558 int buttons = 0;
2559 if (flags & JOY_BUTTON1)
2560 buttons |= wxJOY_BUTTON1;
2561 if (flags & JOY_BUTTON2)
2562 buttons |= wxJOY_BUTTON2;
2563 if (flags & JOY_BUTTON3)
2564 buttons |= wxJOY_BUTTON3;
2565 if (flags & JOY_BUTTON4)
2566 buttons |= wxJOY_BUTTON4;
2567
2568 wxJoystickEvent event(wxEVT_JOY_MOVE, buttons, joystick, 0);
2569 event.SetPosition(wxPoint(x, y));
2570 event.SetEventObject(this);
2571
2572 GetEventHandler()->ProcessEvent(event);
2573 }
2574
2575 void wxWindow::MSWOnJoyZMove(const int joystick, const int z, const WXUINT flags)
2576 {
2577 int buttons = 0;
2578 if (flags & JOY_BUTTON1)
2579 buttons |= wxJOY_BUTTON1;
2580 if (flags & JOY_BUTTON2)
2581 buttons |= wxJOY_BUTTON2;
2582 if (flags & JOY_BUTTON3)
2583 buttons |= wxJOY_BUTTON3;
2584 if (flags & JOY_BUTTON4)
2585 buttons |= wxJOY_BUTTON4;
2586
2587 wxJoystickEvent event(wxEVT_JOY_ZMOVE, buttons, joystick, 0);
2588 event.SetZPosition(z);
2589 event.SetEventObject(this);
2590
2591 GetEventHandler()->ProcessEvent(event);
2592 }
2593
2594 void wxWindow::MSWOnVScroll(const WXWORD wParam, const WXWORD pos, const WXHWND control)
2595 {
2596 if (control)
2597 {
2598 wxWindow *child = wxFindWinFromHandle(control);
2599 if ( child )
2600 child->MSWOnVScroll(wParam, pos, control);
2601 return;
2602 }
2603
2604 wxScrollEvent event;
2605 event.SetPosition(pos);
2606 event.SetOrientation(wxVERTICAL);
2607 event.m_eventObject = this;
2608
2609 switch ( wParam )
2610 {
2611 case SB_TOP:
2612 event.m_eventType = wxEVT_SCROLL_TOP;
2613 break;
2614
2615 case SB_BOTTOM:
2616 event.m_eventType = wxEVT_SCROLL_BOTTOM;
2617 break;
2618
2619 case SB_LINEUP:
2620 event.m_eventType = wxEVT_SCROLL_LINEUP;
2621 break;
2622
2623 case SB_LINEDOWN:
2624 event.m_eventType = wxEVT_SCROLL_LINEDOWN;
2625 break;
2626
2627 case SB_PAGEUP:
2628 event.m_eventType = wxEVT_SCROLL_PAGEUP;
2629 break;
2630
2631 case SB_PAGEDOWN:
2632 event.m_eventType = wxEVT_SCROLL_PAGEDOWN;
2633 break;
2634
2635 case SB_THUMBTRACK:
2636 case SB_THUMBPOSITION:
2637 event.m_eventType = wxEVT_SCROLL_THUMBTRACK;
2638 break;
2639
2640 default:
2641 return;
2642 break;
2643 }
2644
2645 if (!GetEventHandler()->ProcessEvent(event))
2646 #if WXWIN_COMPATIBILITY
2647 GetEventHandler()->OldOnScroll(event);
2648 #else
2649 Default();
2650 #endif
2651 }
2652
2653 void wxWindow::MSWOnHScroll( const WXWORD wParam, const WXWORD pos, const WXHWND control)
2654 {
2655 if (control)
2656 {
2657 wxWindow *child = wxFindWinFromHandle(control);
2658 if ( child )
2659 child->MSWOnHScroll(wParam, pos, control);
2660 return;
2661 }
2662
2663 wxScrollEvent event;
2664 event.SetPosition(pos);
2665 event.SetOrientation(wxHORIZONTAL);
2666 event.m_eventObject = this;
2667
2668 switch ( wParam )
2669 {
2670 case SB_TOP:
2671 event.m_eventType = wxEVT_SCROLL_TOP;
2672 break;
2673
2674 case SB_BOTTOM:
2675 event.m_eventType = wxEVT_SCROLL_BOTTOM;
2676 break;
2677
2678 case SB_LINEUP:
2679 event.m_eventType = wxEVT_SCROLL_LINEUP;
2680 break;
2681
2682 case SB_LINEDOWN:
2683 event.m_eventType = wxEVT_SCROLL_LINEDOWN;
2684 break;
2685
2686 case SB_PAGEUP:
2687 event.m_eventType = wxEVT_SCROLL_PAGEUP;
2688 break;
2689
2690 case SB_PAGEDOWN:
2691 event.m_eventType = wxEVT_SCROLL_PAGEDOWN;
2692 break;
2693
2694 case SB_THUMBTRACK:
2695 case SB_THUMBPOSITION:
2696 event.m_eventType = wxEVT_SCROLL_THUMBTRACK;
2697 break;
2698
2699 default:
2700 return;
2701 break;
2702 }
2703 if (!GetEventHandler()->ProcessEvent(event))
2704 #if WXWIN_COMPATIBILITY
2705 GetEventHandler()->OldOnScroll(event);
2706 #else
2707 Default();
2708 #endif
2709 }
2710
2711 void wxWindow::MSWOnShow(bool show, int status)
2712 {
2713 wxShowEvent event(GetId(), show);
2714 event.m_eventObject = this;
2715 GetEventHandler()->ProcessEvent(event);
2716 }
2717
2718 bool wxWindow::MSWOnInitDialog(WXHWND WXUNUSED(hWndFocus))
2719 {
2720 wxInitDialogEvent event(GetId());
2721 event.m_eventObject = this;
2722 GetEventHandler()->ProcessEvent(event);
2723 return TRUE;
2724 }
2725
2726 void wxWindow::InitDialog(void)
2727 {
2728 wxInitDialogEvent event(GetId());
2729 event.SetEventObject( this );
2730 GetEventHandler()->ProcessEvent(event);
2731 }
2732
2733 // Default init dialog behaviour is to transfer data to window
2734 void wxWindow::OnInitDialog(wxInitDialogEvent& event)
2735 {
2736 TransferDataToWindow();
2737 }
2738
2739 void wxGetCharSize(WXHWND wnd, int *x, int *y,wxFont *the_font)
2740 {
2741 TEXTMETRIC tm;
2742 HDC dc = ::GetDC((HWND) wnd);
2743 HFONT fnt =0;
2744 HFONT was = 0;
2745 if (the_font)
2746 {
2747 #if DEBUG > 1
2748 wxDebugMsg("wxGetCharSize: Selecting HFONT %X\n", fnt);
2749 #endif
2750 // the_font->UseResource();
2751 // the_font->RealizeResource();
2752 if ((fnt=(HFONT) the_font->GetResourceHandle()))
2753 was = SelectObject(dc,fnt) ;
2754 }
2755 GetTextMetrics(dc, &tm);
2756 if (the_font && fnt && was)
2757 {
2758 #if DEBUG > 1
2759 wxDebugMsg("wxGetCharSize: Selecting old HFONT %X\n", was);
2760 #endif
2761 SelectObject(dc,was) ;
2762 }
2763 ReleaseDC((HWND)wnd, dc);
2764 *x = tm.tmAveCharWidth;
2765 *y = tm.tmHeight + tm.tmExternalLeading;
2766
2767 // if (the_font)
2768 // the_font->ReleaseResource();
2769 }
2770
2771 // Returns 0 if was a normal ASCII value, not a special key. This indicates that
2772 // the key should be ignored by WM_KEYDOWN and processed by WM_CHAR instead.
2773 int wxCharCodeMSWToWX(int keySym)
2774 {
2775 int id = 0;
2776 switch (keySym)
2777 {
2778 case VK_CANCEL: id = WXK_CANCEL; break;
2779 case VK_BACK: id = WXK_BACK; break;
2780 case VK_TAB: id = WXK_TAB; break;
2781 case VK_CLEAR: id = WXK_CLEAR; break;
2782 case VK_RETURN: id = WXK_RETURN; break;
2783 case VK_SHIFT: id = WXK_SHIFT; break;
2784 case VK_CONTROL: id = WXK_CONTROL; break;
2785 case VK_MENU : id = WXK_MENU; break;
2786 case VK_PAUSE: id = WXK_PAUSE; break;
2787 case VK_SPACE: id = WXK_SPACE; break;
2788 case VK_ESCAPE: id = WXK_ESCAPE; break;
2789 case VK_PRIOR: id = WXK_PRIOR; break;
2790 case VK_NEXT : id = WXK_NEXT; break;
2791 case VK_END: id = WXK_END; break;
2792 case VK_HOME : id = WXK_HOME; break;
2793 case VK_LEFT : id = WXK_LEFT; break;
2794 case VK_UP: id = WXK_UP; break;
2795 case VK_RIGHT: id = WXK_RIGHT; break;
2796 case VK_DOWN : id = WXK_DOWN; break;
2797 case VK_SELECT: id = WXK_SELECT; break;
2798 case VK_PRINT: id = WXK_PRINT; break;
2799 case VK_EXECUTE: id = WXK_EXECUTE; break;
2800 case VK_INSERT: id = WXK_INSERT; break;
2801 case VK_DELETE: id = WXK_DELETE; break;
2802 case VK_HELP : id = WXK_HELP; break;
2803 case VK_NUMPAD0: id = WXK_NUMPAD0; break;
2804 case VK_NUMPAD1: id = WXK_NUMPAD1; break;
2805 case VK_NUMPAD2: id = WXK_NUMPAD2; break;
2806 case VK_NUMPAD3: id = WXK_NUMPAD3; break;
2807 case VK_NUMPAD4: id = WXK_NUMPAD4; break;
2808 case VK_NUMPAD5: id = WXK_NUMPAD5; break;
2809 case VK_NUMPAD6: id = WXK_NUMPAD6; break;
2810 case VK_NUMPAD7: id = WXK_NUMPAD7; break;
2811 case VK_NUMPAD8: id = WXK_NUMPAD8; break;
2812 case VK_NUMPAD9: id = WXK_NUMPAD9; break;
2813 case VK_MULTIPLY: id = WXK_MULTIPLY; break;
2814 case VK_ADD: id = WXK_ADD; break;
2815 case VK_SUBTRACT: id = WXK_SUBTRACT; break;
2816 case VK_DECIMAL: id = WXK_DECIMAL; break;
2817 case VK_DIVIDE: id = WXK_DIVIDE; break;
2818 case VK_F1: id = WXK_F1; break;
2819 case VK_F2: id = WXK_F2; break;
2820 case VK_F3: id = WXK_F3; break;
2821 case VK_F4: id = WXK_F4; break;
2822 case VK_F5: id = WXK_F5; break;
2823 case VK_F6: id = WXK_F6; break;
2824 case VK_F7: id = WXK_F7; break;
2825 case VK_F8: id = WXK_F8; break;
2826 case VK_F9: id = WXK_F9; break;
2827 case VK_F10: id = WXK_F10; break;
2828 case VK_F11: id = WXK_F11; break;
2829 case VK_F12: id = WXK_F12; break;
2830 case VK_F13: id = WXK_F13; break;
2831 case VK_F14: id = WXK_F14; break;
2832 case VK_F15: id = WXK_F15; break;
2833 case VK_F16: id = WXK_F16; break;
2834 case VK_F17: id = WXK_F17; break;
2835 case VK_F18: id = WXK_F18; break;
2836 case VK_F19: id = WXK_F19; break;
2837 case VK_F20: id = WXK_F20; break;
2838 case VK_F21: id = WXK_F21; break;
2839 case VK_F22: id = WXK_F22; break;
2840 case VK_F23: id = WXK_F23; break;
2841 case VK_F24: id = WXK_F24; break;
2842 case VK_NUMLOCK: id = WXK_NUMLOCK; break;
2843 case VK_SCROLL: id = WXK_SCROLL; break;
2844 default:
2845 {
2846 return 0;
2847 }
2848 }
2849 return id;
2850 }
2851
2852 int wxCharCodeWXToMSW(int id, bool *isVirtual)
2853 {
2854 *isVirtual = TRUE;
2855 int keySym = 0;
2856 switch (id)
2857 {
2858 case WXK_CANCEL: keySym = VK_CANCEL; break;
2859 case WXK_CLEAR: keySym = VK_CLEAR; break;
2860 case WXK_SHIFT: keySym = VK_SHIFT; break;
2861 case WXK_CONTROL: keySym = VK_CONTROL; break;
2862 case WXK_MENU : keySym = VK_MENU; break;
2863 case WXK_PAUSE: keySym = VK_PAUSE; break;
2864 case WXK_PRIOR: keySym = VK_PRIOR; break;
2865 case WXK_NEXT : keySym = VK_NEXT; break;
2866 case WXK_END: keySym = VK_END; break;
2867 case WXK_HOME : keySym = VK_HOME; break;
2868 case WXK_LEFT : keySym = VK_LEFT; break;
2869 case WXK_UP: keySym = VK_UP; break;
2870 case WXK_RIGHT: keySym = VK_RIGHT; break;
2871 case WXK_DOWN : keySym = VK_DOWN; break;
2872 case WXK_SELECT: keySym = VK_SELECT; break;
2873 case WXK_PRINT: keySym = VK_PRINT; break;
2874 case WXK_EXECUTE: keySym = VK_EXECUTE; break;
2875 case WXK_INSERT: keySym = VK_INSERT; break;
2876 case WXK_DELETE: keySym = VK_DELETE; break;
2877 case WXK_HELP : keySym = VK_HELP; break;
2878 case WXK_NUMPAD0: keySym = VK_NUMPAD0; break;
2879 case WXK_NUMPAD1: keySym = VK_NUMPAD1; break;
2880 case WXK_NUMPAD2: keySym = VK_NUMPAD2; break;
2881 case WXK_NUMPAD3: keySym = VK_NUMPAD3; break;
2882 case WXK_NUMPAD4: keySym = VK_NUMPAD4; break;
2883 case WXK_NUMPAD5: keySym = VK_NUMPAD5; break;
2884 case WXK_NUMPAD6: keySym = VK_NUMPAD6; break;
2885 case WXK_NUMPAD7: keySym = VK_NUMPAD7; break;
2886 case WXK_NUMPAD8: keySym = VK_NUMPAD8; break;
2887 case WXK_NUMPAD9: keySym = VK_NUMPAD9; break;
2888 case WXK_MULTIPLY: keySym = VK_MULTIPLY; break;
2889 case WXK_ADD: keySym = VK_ADD; break;
2890 case WXK_SUBTRACT: keySym = VK_SUBTRACT; break;
2891 case WXK_DECIMAL: keySym = VK_DECIMAL; break;
2892 case WXK_DIVIDE: keySym = VK_DIVIDE; break;
2893 case WXK_F1: keySym = VK_F1; break;
2894 case WXK_F2: keySym = VK_F2; break;
2895 case WXK_F3: keySym = VK_F3; break;
2896 case WXK_F4: keySym = VK_F4; break;
2897 case WXK_F5: keySym = VK_F5; break;
2898 case WXK_F6: keySym = VK_F6; break;
2899 case WXK_F7: keySym = VK_F7; break;
2900 case WXK_F8: keySym = VK_F8; break;
2901 case WXK_F9: keySym = VK_F9; break;
2902 case WXK_F10: keySym = VK_F10; break;
2903 case WXK_F11: keySym = VK_F11; break;
2904 case WXK_F12: keySym = VK_F12; break;
2905 case WXK_F13: keySym = VK_F13; break;
2906 case WXK_F14: keySym = VK_F14; break;
2907 case WXK_F15: keySym = VK_F15; break;
2908 case WXK_F16: keySym = VK_F16; break;
2909 case WXK_F17: keySym = VK_F17; break;
2910 case WXK_F18: keySym = VK_F18; break;
2911 case WXK_F19: keySym = VK_F19; break;
2912 case WXK_F20: keySym = VK_F20; break;
2913 case WXK_F21: keySym = VK_F21; break;
2914 case WXK_F22: keySym = VK_F22; break;
2915 case WXK_F23: keySym = VK_F23; break;
2916 case WXK_F24: keySym = VK_F24; break;
2917 case WXK_NUMLOCK: keySym = VK_NUMLOCK; break;
2918 case WXK_SCROLL: keySym = VK_SCROLL; break;
2919 default:
2920 {
2921 *isVirtual = FALSE;
2922 keySym = id;
2923 break;
2924 }
2925 }
2926 return keySym;
2927 }
2928
2929 // Caret manipulation
2930 void wxWindow::CreateCaret(const int w, const int h)
2931 {
2932 m_caretWidth = w;
2933 m_caretHeight = h;
2934 m_caretEnabled = TRUE;
2935 }
2936
2937 void wxWindow::CreateCaret(const wxBitmap *WXUNUSED(bitmap))
2938 {
2939 // Not implemented
2940 }
2941
2942 void wxWindow::ShowCaret(const bool show)
2943 {
2944 if (m_caretEnabled)
2945 {
2946 if (show)
2947 ::ShowCaret((HWND) GetHWND());
2948 else
2949 ::HideCaret((HWND) GetHWND());
2950 m_caretShown = show;
2951 }
2952 }
2953
2954 void wxWindow::DestroyCaret(void)
2955 {
2956 m_caretEnabled = FALSE;
2957 }
2958
2959 void wxWindow::SetCaretPos(const int x, const int y)
2960 {
2961 ::SetCaretPos(x, y);
2962 }
2963
2964 void wxWindow::GetCaretPos(int *x, int *y) const
2965 {
2966 POINT point;
2967 ::GetCaretPos(&point);
2968 *x = point.x;
2969 *y = point.y;
2970 }
2971
2972 /*
2973 * Update iterator. Use from within OnPaint.
2974 */
2975
2976 static RECT gs_UpdateRect;
2977
2978 wxUpdateIterator::wxUpdateIterator(wxWindow* wnd)
2979 {
2980 current = 0; //start somewhere...
2981 #if defined(__WIN32__) && !defined(__win32s__)
2982 rlist = NULL; //make sure I don't free randomly
2983 int len = GetRegionData((HRGN) wnd->m_updateRgn,0,NULL); //Get buffer size
2984 if (len)
2985 {
2986 rlist = (WXRGNDATA *) (RGNDATA *)new char[len];
2987 GetRegionData((HRGN) wnd->m_updateRgn,len, (RGNDATA *)rlist);
2988 rp = (void *)(RECT*) ((RGNDATA *)rlist)->Buffer;
2989 rects = ((RGNDATA *)rlist)->rdh.nCount;
2990 }
2991 else
2992 #endif
2993 {
2994 gs_UpdateRect.left = wnd->m_updateRect.x;
2995 gs_UpdateRect.top = wnd->m_updateRect.y;
2996 gs_UpdateRect.right = wnd->m_updateRect.x + wnd->m_updateRect.width;
2997 gs_UpdateRect.bottom = wnd->m_updateRect.y + wnd->m_updateRect.height;
2998 rects = 1;
2999 rp = (void *)&gs_UpdateRect; //Only one available in Win16,32s
3000 }
3001 }
3002
3003 wxUpdateIterator::~wxUpdateIterator(void)
3004 {
3005 #ifdef __WIN32__
3006 #ifndef __win32s__
3007 if (rlist) delete (RGNDATA *) rlist;
3008 #endif
3009 #endif
3010 }
3011
3012 wxUpdateIterator::operator int (void)
3013 {
3014 if (current < rects)
3015 {
3016 return TRUE;
3017 }
3018 else
3019 {
3020 return FALSE;
3021 }
3022 }
3023
3024 wxUpdateIterator* wxUpdateIterator::operator ++(int)
3025 {
3026 current++;
3027 return this;
3028 }
3029
3030 void wxUpdateIterator::GetRect(wxRect *rect)
3031 {
3032 RECT *mswRect = ((RECT *)rp)+current; //ought to error check this...
3033 rect->x = mswRect->left;
3034 rect->y = mswRect->top;
3035 rect->width = mswRect->right - mswRect->left;
3036 rect->height = mswRect->bottom - mswRect->top;
3037 }
3038
3039 int wxUpdateIterator::GetX()
3040 {
3041 return ((RECT*)rp)[current].left;
3042 }
3043
3044 int wxUpdateIterator::GetY()
3045 {
3046 return ((RECT *)rp)[current].top;
3047 }
3048
3049 int wxUpdateIterator::GetW()
3050 {
3051 return ((RECT *)rp)[current].right-GetX();
3052 }
3053
3054 int wxUpdateIterator::GetH()
3055 {
3056 return ((RECT *)rp)[current].bottom-GetY();
3057 }
3058
3059 wxWindow *wxGetActiveWindow(void)
3060 {
3061 HWND hWnd = GetActiveWindow();
3062 if (hWnd != 0)
3063 {
3064 return wxFindWinFromHandle((WXHWND) hWnd);
3065 }
3066 return NULL;
3067 }
3068
3069 // Windows keyboard hook. Allows interception of e.g. F1, ESCAPE
3070 // in active frames and dialogs, regardless of where the focus is.
3071 static HHOOK wxTheKeyboardHook = 0;
3072 static FARPROC wxTheKeyboardHookProc = 0;
3073 int APIENTRY _EXPORT
3074 wxKeyboardHook(int nCode, WORD wParam, DWORD lParam);
3075
3076 void wxSetKeyboardHook(bool doIt)
3077 {
3078 if (doIt)
3079 {
3080 wxTheKeyboardHookProc = MakeProcInstance((FARPROC) wxKeyboardHook, wxGetInstance());
3081 wxTheKeyboardHook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) wxTheKeyboardHookProc, wxGetInstance(),
3082 #ifdef __WIN32__
3083 GetCurrentThreadId());
3084 // (DWORD)GetCurrentProcess()); // This is another possibility. Which is right?
3085 #else
3086 GetCurrentTask());
3087 #endif
3088 }
3089 else
3090 {
3091 UnhookWindowsHookEx(wxTheKeyboardHook);
3092 FreeProcInstance(wxTheKeyboardHookProc);
3093 }
3094 }
3095
3096 int APIENTRY _EXPORT
3097 wxKeyboardHook(int nCode, WORD wParam, DWORD lParam)
3098 {
3099 DWORD hiWord = HIWORD(lParam);
3100 if (nCode != HC_NOREMOVE && ((hiWord & KF_UP) == 0))
3101 {
3102 int id;
3103 if ((id = wxCharCodeMSWToWX(wParam)) != 0)
3104 {
3105 wxKeyEvent event(wxEVT_CHAR_HOOK);
3106 if ((HIWORD(lParam) & KF_ALTDOWN) == KF_ALTDOWN)
3107 event.m_altDown = TRUE;
3108
3109 event.m_eventObject = NULL;
3110 event.m_keyCode = id;
3111 /* begin Albert's fix for control and shift key 26.5 */
3112 event.m_shiftDown = (::GetKeyState(VK_SHIFT)&0x100?TRUE:FALSE);
3113 event.m_controlDown = (::GetKeyState(VK_CONTROL)&0x100?TRUE:FALSE);
3114 /* end Albert's fix for control and shift key 26.5 */
3115 event.SetTimestamp(wxApp::sm_lastMessageTime); /* MATTHEW: timeStamp */
3116
3117 #if WXWIN_COMPATIBILITY
3118 if ( wxTheApp && wxTheApp->OldOnCharHook(event) )
3119 return 1;
3120 #endif
3121 wxWindow *win = wxGetActiveWindow();
3122 if (win)
3123 {
3124 if (win->GetEventHandler()->ProcessEvent(event))
3125 return 1;
3126 }
3127 else
3128 {
3129 if ( wxTheApp && wxTheApp->ProcessEvent(event) )
3130 return 1;
3131 }
3132 }
3133 }
3134 return (int)CallNextHookEx(wxTheKeyboardHook, nCode, wParam, lParam);
3135 }
3136
3137 void wxWindow::SetSizeHints(const int minW, const int minH, const int maxW, const int maxH, const int WXUNUSED(incW), const int WXUNUSED(incH))
3138 {
3139 m_minSizeX = minW;
3140 m_minSizeY = minH;
3141 m_maxSizeX = maxW;
3142 m_maxSizeY = maxH;
3143 }
3144
3145 void wxWindow::Centre(const int direction)
3146 {
3147 int x, y, width, height, panel_width, panel_height, new_x, new_y;
3148
3149 wxWindow *father = (wxWindow *)GetParent();
3150 if (!father)
3151 return;
3152
3153 father->GetClientSize(&panel_width, &panel_height);
3154 GetSize(&width, &height);
3155 GetPosition(&x, &y);
3156
3157 new_x = -1;
3158 new_y = -1;
3159
3160 if (direction & wxHORIZONTAL)
3161 new_x = (int)((panel_width - width)/2);
3162
3163 if (direction & wxVERTICAL)
3164 new_y = (int)((panel_height - height)/2);
3165
3166 SetSize(new_x, new_y, -1, -1);
3167
3168 }
3169
3170 /* TODO (maybe)
3171 void wxWindow::OnPaint(void)
3172 {
3173 PaintSelectionHandles();
3174 }
3175 */
3176
3177 void wxWindow::WarpPointer (const int x_pos, const int y_pos)
3178 {
3179 // Move the pointer to (x_pos,y_pos) coordinates. They are expressed in
3180 // pixel coordinates, relatives to the canvas -- So, we first need to
3181 // substract origin of the window, then convert to screen position
3182
3183 int x = x_pos; int y = y_pos;
3184 /* Leave this to the app to decide (and/or wxScrolledWindow)
3185 x -= m_xScrollPosition * m_xScrollPixelsPerLine;
3186 y -= m_yScrollPosition * m_yScrollPixelsPerLine;
3187 */
3188 RECT rect;
3189 GetWindowRect ((HWND) GetHWND(), &rect);
3190
3191 x += rect.left;
3192 y += rect.top;
3193
3194 SetCursorPos (x, y);
3195 }
3196
3197 void wxWindow::MSWDeviceToLogical (float *x, float *y) const
3198 {
3199 // TODO
3200 // Do we have a SetUserScale in wxWindow too, so we can
3201 // get mouse events scaled?
3202 /*
3203 if (m_windowDC)
3204 {
3205 *x = m_windowDC->DeviceToLogicalX ((int) *x);
3206 *y = m_windowDC->DeviceToLogicalY ((int) *y);
3207 }
3208 */
3209 }
3210
3211 bool wxWindow::MSWOnEraseBkgnd (const WXHDC pDC)
3212 {
3213 wxDC dc ;
3214
3215 dc.SetHDC(pDC);
3216 dc.SetWindow(this);
3217 dc.BeginDrawing();
3218
3219 wxEraseEvent event(m_windowId, &dc);
3220 event.m_eventObject = this;
3221 if (!GetEventHandler()->ProcessEvent(event))
3222 {
3223 dc.EndDrawing();
3224 dc.SelectOldObjects(pDC);
3225 return FALSE;
3226 }
3227 else
3228 {
3229 dc.EndDrawing();
3230 dc.SelectOldObjects(pDC);
3231 }
3232
3233 dc.SetHDC((WXHDC) NULL);
3234 return TRUE;
3235 }
3236
3237 void wxWindow::OnEraseBackground(wxEraseEvent& event)
3238 {
3239 RECT rect;
3240 ::GetClientRect((HWND) GetHWND(), &rect);
3241
3242 HBRUSH hBrush = ::CreateSolidBrush(PALETTERGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue()));
3243 int mode = ::SetMapMode((HDC) event.GetDC()->GetHDC(), MM_TEXT);
3244
3245 // ::GetClipBox((HDC) event.GetDC()->GetHDC(), &rect);
3246 ::FillRect ((HDC) event.GetDC()->GetHDC(), &rect, hBrush);
3247 ::DeleteObject(hBrush);
3248 ::SetMapMode((HDC) event.GetDC()->GetHDC(), mode);
3249 /*
3250 // Less efficient version (and doesn't account for scrolling)
3251 int w, h;
3252 GetClientSize(& w, & h);
3253 wxBrush *brush = wxTheBrushList->FindOrCreateBrush(& GetBackgroundColour(), wxSOLID);
3254 event.GetDC()->SetBrush(brush);
3255 event.GetDC()->SetPen(wxTRANSPARENT_PEN);
3256
3257 event.GetDC()->DrawRectangle(0, 0, w+1, h+1);
3258 */
3259 }
3260
3261 #if WXWIN_COMPATIBILITY
3262 void wxWindow::SetScrollRange(const int orient, const int range, const bool refresh)
3263 {
3264 #if defined(__WIN95__)
3265
3266 int range1 = range;
3267
3268 // Try to adjust the range to cope with page size > 1
3269 // - a Windows API quirk
3270 int pageSize = GetScrollPage(orient);
3271 if ( pageSize > 1 && range > 0)
3272 {
3273 range1 += (pageSize - 1);
3274 }
3275
3276 SCROLLINFO info;
3277 int dir;
3278
3279 if (orient == wxHORIZONTAL) {
3280 dir = SB_HORZ;
3281 } else {
3282 dir = SB_VERT;
3283 }
3284
3285 info.cbSize = sizeof(SCROLLINFO);
3286 info.nPage = pageSize; // Have to set this, or scrollbar goes awry
3287 info.nMin = 0;
3288 info.nMax = range1;
3289 info.nPos = 0;
3290 info.fMask = SIF_RANGE | SIF_PAGE;
3291
3292 HWND hWnd = (HWND) GetHWND();
3293 if (hWnd)
3294 ::SetScrollInfo(hWnd, dir, &info, refresh);
3295 #else
3296 int wOrient ;
3297 if (orient == wxHORIZONTAL)
3298 wOrient = SB_HORZ;
3299 else
3300 wOrient = SB_VERT;
3301
3302 HWND hWnd = (HWND) GetHWND();
3303 if (hWnd)
3304 ::SetScrollRange(hWnd, wOrient, 0, range, refresh);
3305 #endif
3306 }
3307
3308 void wxWindow::SetScrollPage(const int orient, const int page, const bool refresh)
3309 {
3310 #if defined(__WIN95__)
3311 SCROLLINFO info;
3312 int dir;
3313
3314 if (orient == wxHORIZONTAL) {
3315 dir = SB_HORZ;
3316 m_xThumbSize = page;
3317 } else {
3318 dir = SB_VERT;
3319 m_yThumbSize = page;
3320 }
3321
3322 info.cbSize = sizeof(SCROLLINFO);
3323 info.nPage = page;
3324 info.nMin = 0;
3325 info.fMask = SIF_PAGE ;
3326
3327 HWND hWnd = (HWND) GetHWND();
3328 if (hWnd)
3329 ::SetScrollInfo(hWnd, dir, &info, refresh);
3330 #else
3331 if (orient == wxHORIZONTAL)
3332 m_xThumbSize = page;
3333 else
3334 m_yThumbSize = page;
3335 #endif
3336 }
3337
3338 int wxWindow::OldGetScrollRange(const int orient) const
3339 {
3340 int wOrient ;
3341 if (orient == wxHORIZONTAL)
3342 wOrient = SB_HORZ;
3343 else
3344 wOrient = SB_VERT;
3345
3346 #if __WATCOMC__ && defined(__WINDOWS_386__)
3347 short minPos, maxPos;
3348 #else
3349 int minPos, maxPos;
3350 #endif
3351 HWND hWnd = (HWND) GetHWND();
3352 if (hWnd)
3353 {
3354 ::GetScrollRange(hWnd, wOrient, &minPos, &maxPos);
3355 #if defined(__WIN95__)
3356 // Try to adjust the range to cope with page size > 1
3357 // - a Windows API quirk
3358 int pageSize = GetScrollPage(orient);
3359 if ( pageSize > 1 )
3360 {
3361 maxPos -= (pageSize - 1);
3362 }
3363 #endif
3364 return maxPos;
3365 }
3366 else
3367 return 0;
3368 }
3369
3370 int wxWindow::GetScrollPage(const int orient) const
3371 {
3372 if (orient == wxHORIZONTAL)
3373 return m_xThumbSize;
3374 else
3375 return m_yThumbSize;
3376 }
3377 #endif
3378
3379 int wxWindow::GetScrollPos(const int orient) const
3380 {
3381 int wOrient ;
3382 if (orient == wxHORIZONTAL)
3383 wOrient = SB_HORZ;
3384 else
3385 wOrient = SB_VERT;
3386 HWND hWnd = (HWND) GetHWND();
3387 if (hWnd)
3388 {
3389 return ::GetScrollPos(hWnd, wOrient);
3390 }
3391 else
3392 return 0;
3393 }
3394
3395 // This now returns the whole range, not just the number
3396 // of positions that we can scroll.
3397 int wxWindow::GetScrollRange(const int orient) const
3398 {
3399 int wOrient ;
3400 if (orient == wxHORIZONTAL)
3401 wOrient = SB_HORZ;
3402 else
3403 wOrient = SB_VERT;
3404
3405 #if __WATCOMC__ && defined(__WINDOWS_386__)
3406 short minPos, maxPos;
3407 #else
3408 int minPos, maxPos;
3409 #endif
3410 HWND hWnd = (HWND) GetHWND();
3411 if (hWnd)
3412 {
3413 ::GetScrollRange(hWnd, wOrient, &minPos, &maxPos);
3414 #if defined(__WIN95__)
3415 // Try to adjust the range to cope with page size > 1
3416 // - a Windows API quirk
3417 int pageSize = GetScrollPage(orient);
3418 if ( pageSize > 1 )
3419 {
3420 maxPos -= (pageSize - 1);
3421 }
3422 // October 10th: new range concept.
3423 maxPos += pageSize;
3424 #endif
3425
3426 return maxPos;
3427 }
3428 else
3429 return 0;
3430 }
3431
3432 int wxWindow::GetScrollThumb(const int orient) const
3433 {
3434 if (orient == wxHORIZONTAL)
3435 return m_xThumbSize;
3436 else
3437 return m_yThumbSize;
3438 }
3439
3440 void wxWindow::SetScrollPos(const int orient, const int pos, const bool refresh)
3441 {
3442 #if defined(__WIN95__)
3443 SCROLLINFO info;
3444 int dir;
3445
3446 if (orient == wxHORIZONTAL) {
3447 dir = SB_HORZ;
3448 } else {
3449 dir = SB_VERT;
3450 }
3451
3452 info.cbSize = sizeof(SCROLLINFO);
3453 info.nPage = 0;
3454 info.nMin = 0;
3455 info.nPos = pos;
3456 info.fMask = SIF_POS ;
3457
3458 HWND hWnd = (HWND) GetHWND();
3459 if (hWnd)
3460 ::SetScrollInfo(hWnd, dir, &info, refresh);
3461 #else
3462 int wOrient ;
3463 if (orient == wxHORIZONTAL)
3464 wOrient = SB_HORZ;
3465 else
3466 wOrient = SB_VERT;
3467
3468 HWND hWnd = (HWND) GetHWND();
3469 if (hWnd)
3470 ::SetScrollPos(hWnd, wOrient, pos, refresh);
3471 #endif
3472 }
3473
3474 // New function that will replace some of the above.
3475 void wxWindow::SetScrollbar(const int orient, const int pos, const int thumbVisible,
3476 const int range, const bool refresh)
3477 {
3478 /*
3479 SetScrollPage(orient, thumbVisible, FALSE);
3480
3481 int oldRange = range - thumbVisible ;
3482 SetScrollRange(orient, oldRange, FALSE);
3483
3484 SetScrollPos(orient, pos, refresh);
3485 */
3486 #if defined(__WIN95__)
3487 int oldRange = range - thumbVisible ;
3488
3489 int range1 = oldRange;
3490
3491 // Try to adjust the range to cope with page size > 1
3492 // - a Windows API quirk
3493 int pageSize = thumbVisible;
3494 if ( pageSize > 1 && range > 0)
3495 {
3496 range1 += (pageSize - 1);
3497 }
3498
3499 SCROLLINFO info;
3500 int dir;
3501
3502 if (orient == wxHORIZONTAL) {
3503 dir = SB_HORZ;
3504 } else {
3505 dir = SB_VERT;
3506 }
3507
3508 info.cbSize = sizeof(SCROLLINFO);
3509 info.nPage = pageSize; // Have to set this, or scrollbar goes awry
3510 info.nMin = 0;
3511 info.nMax = range1;
3512 info.nPos = pos;
3513 info.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
3514
3515 HWND hWnd = (HWND) GetHWND();
3516 if (hWnd)
3517 ::SetScrollInfo(hWnd, dir, &info, refresh);
3518 #else
3519 int wOrient ;
3520 if (orient == wxHORIZONTAL)
3521 wOrient = SB_HORZ;
3522 else
3523 wOrient = SB_VERT;
3524
3525 HWND hWnd = (HWND) GetHWND();
3526 if (hWnd)
3527 {
3528 ::SetScrollRange(hWnd, wOrient, 0, range, FALSE);
3529 ::SetScrollPos(hWnd, wOrient, pos, refresh);
3530 }
3531 #endif
3532 if (orient == wxHORIZONTAL) {
3533 m_xThumbSize = thumbVisible;
3534 } else {
3535 m_yThumbSize = thumbVisible;
3536 }
3537 }
3538
3539 void wxWindow::ScrollWindow(const int dx, const int dy, const wxRectangle *rect)
3540 {
3541 RECT rect2;
3542 if ( rect )
3543 {
3544 rect2.left = rect->x;
3545 rect2.top = rect->y;
3546 rect2.right = rect->x + rect->width;
3547 rect2.bottom = rect->y + rect->height;
3548 }
3549
3550 if ( rect )
3551 ::ScrollWindow((HWND) GetHWND(), dx, dy, &rect2, NULL);
3552 else
3553 ::ScrollWindow((HWND) GetHWND(), dx, dy, NULL, NULL);
3554 }
3555
3556 void wxWindow::OnSize(wxSizeEvent& event)
3557 {
3558 Default();
3559 #if USE_CONSTRAINTS
3560 if (GetAutoLayout())
3561 Layout();
3562 #endif
3563 }
3564
3565 /*
3566 void wxWindow::CalcScrolledPosition(const int x, const int y, int *xx, int *yy) const
3567 {
3568 *xx = x;
3569 *yy = y;
3570 }
3571
3572 void wxWindow::CalcUnscrolledPosition(const int x, const int y, float *xx, float *yy) const
3573 {
3574 *xx = x;
3575 *yy = y;
3576 }
3577 */
3578
3579 void wxWindow::SetFont(const wxFont& font)
3580 {
3581 // Decrement the usage count of the old label font
3582 // (we may be able to free it up)
3583 // if (GetFont()->Ok())
3584 // GetFont()->ReleaseResource();
3585
3586 m_windowFont = font;
3587
3588 if (!m_windowFont.Ok())
3589 return;
3590
3591 // m_windowFont.UseResource();
3592
3593 HWND hWnd = (HWND) GetHWND();
3594 if (hWnd != 0)
3595 {
3596 // m_windowFont.RealizeResource();
3597
3598 if (m_windowFont.GetResourceHandle())
3599 SendMessage(hWnd, WM_SETFONT,
3600 (WPARAM)m_windowFont.GetResourceHandle(),TRUE);
3601 }
3602 }
3603
3604 void wxWindow::SubclassWin(WXHWND hWnd)
3605 {
3606 wxAssociateWinWithHandle((HWND)hWnd, this);
3607
3608 m_oldWndProc = (WXFARPROC) GetWindowLong((HWND) hWnd, GWL_WNDPROC);
3609 SetWindowLong((HWND) hWnd, GWL_WNDPROC, (LONG) wxWndProc);
3610 }
3611
3612 void wxWindow::UnsubclassWin(void)
3613 {
3614 wxRemoveHandleAssociation(this);
3615
3616 // Restore old Window proc
3617 if ((HWND) GetHWND())
3618 {
3619 FARPROC farProc = (FARPROC) GetWindowLong((HWND) GetHWND(), GWL_WNDPROC);
3620 if ((m_oldWndProc != 0) && (farProc != (FARPROC) m_oldWndProc))
3621 {
3622 SetWindowLong((HWND) GetHWND(), GWL_WNDPROC, (LONG) m_oldWndProc);
3623 m_oldWndProc = 0;
3624 }
3625 }
3626 }
3627
3628 // Make a Windows extended style from the given wxWindows window style
3629 WXDWORD wxWindow::MakeExtendedStyle(long style, bool eliminateBorders)
3630 {
3631 WXDWORD exStyle = 0;
3632 if ( style & wxTRANSPARENT_WINDOW )
3633 exStyle |= WS_EX_TRANSPARENT ;
3634
3635 if ( !eliminateBorders )
3636 {
3637 if ( style & wxSUNKEN_BORDER )
3638 exStyle |= WS_EX_CLIENTEDGE ;
3639 if ( style & wxDOUBLE_BORDER )
3640 exStyle |= WS_EX_DLGMODALFRAME ;
3641 #if defined(__WIN95__)
3642 if ( style & wxRAISED_BORDER )
3643 exStyle |= WS_EX_WINDOWEDGE ;
3644 if ( style & wxSTATIC_BORDER )
3645 exStyle |= WS_EX_STATICEDGE ;
3646 #endif
3647 }
3648 return exStyle;
3649 }
3650
3651 // Determines whether native 3D effects or CTL3D should be used,
3652 // applying a default border style if required, and returning an extended
3653 // style to pass to CreateWindowEx.
3654 WXDWORD wxWindow::Determine3DEffects(WXDWORD defaultBorderStyle, bool *want3D)
3655 {
3656 // If matches certain criteria, then assume no 3D effects
3657 // unless specifically requested (dealt with in MakeExtendedStyle)
3658 if ( !GetParent() || !IsKindOf(CLASSINFO(wxControl)) || (m_windowStyle & wxNO_BORDER) )
3659 {
3660 *want3D = FALSE;
3661 return MakeExtendedStyle(m_windowStyle, FALSE);
3662 }
3663
3664 // Determine whether we should be using 3D effects or not.
3665 bool nativeBorder = FALSE; // by default, we don't want a Win95 effect
3666
3667 // 1) App can specify global 3D effects
3668 *want3D = wxTheApp->GetAuto3D();
3669
3670 // 2) If the parent is being drawn with user colours, or simple border specified,
3671 // switch effects off. TODO: replace wxUSER_COLOURS with wxNO_3D
3672 if (GetParent() && (GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS) || (m_windowStyle & wxSIMPLE_BORDER))
3673 *want3D = FALSE;
3674
3675 // 3) Control can override this global setting by defining
3676 // a border style, e.g. wxSUNKEN_BORDER
3677 if (m_windowStyle & wxSUNKEN_BORDER )
3678 *want3D = TRUE;
3679
3680 // 4) If it's a special border, CTL3D can't cope so we want a native border
3681 if ( (m_windowStyle & wxDOUBLE_BORDER) || (m_windowStyle & wxRAISED_BORDER) ||
3682 (m_windowStyle & wxSTATIC_BORDER) )
3683 {
3684 *want3D = TRUE;
3685 nativeBorder = TRUE;
3686 }
3687
3688 // 5) If this isn't a Win95 app, and we are using CTL3D, remove border
3689 // effects from extended style
3690 #if CTL3D
3691 if ( *want3D )
3692 nativeBorder = FALSE;
3693 #endif
3694
3695 DWORD exStyle = MakeExtendedStyle(m_windowStyle, !nativeBorder);
3696
3697 // If we want 3D, but haven't specified a border here,
3698 // apply the default border style specified.
3699 // TODO what about non-Win95 WIN32? Does it have borders?
3700 #if defined(__WIN95__) && !CTL3D
3701 if (defaultBorderStyle && (*want3D) && ! ((m_windowStyle & wxDOUBLE_BORDER) || (m_windowStyle & wxRAISED_BORDER) ||
3702 (m_windowStyle & wxSTATIC_BORDER) || (m_windowStyle & wxSIMPLE_BORDER) ))
3703 exStyle |= defaultBorderStyle; // WS_EX_CLIENTEDGE ;
3704 #endif
3705
3706 return exStyle;
3707 }
3708
3709 #if WXWIN_COMPATIBILITY
3710 void wxWindow::OldOnPaint(void)
3711 {
3712 wxPaintEvent event(m_windowId);
3713 event.m_eventObject = this;
3714 if (!GetEventHandler()->ProcessEvent(event))
3715 Default();
3716 };
3717
3718 void wxWindow::OldOnSize(int w, int h)
3719 {
3720 wxSizeEvent event(wxSize(w, h), m_windowId);
3721 event.m_eventObject = this;
3722 if (!GetEventHandler()->ProcessEvent(event))
3723 Default();
3724 };
3725
3726 void wxWindow::OldOnMouseEvent(wxMouseEvent& event)
3727 {
3728 if (!GetEventHandler()->ProcessEvent(event))
3729 Default();
3730 };
3731
3732 void wxWindow::OldOnChar(wxKeyEvent& event)
3733 {
3734 if (!GetEventHandler()->ProcessEvent(event))
3735 Default();
3736 };
3737
3738 void wxWindow::OldOnSetFocus(void)
3739 {
3740 wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
3741 event.m_eventObject = this;
3742 if (!GetEventHandler()->ProcessEvent(event))
3743 Default();
3744 };
3745
3746 void wxWindow::OldOnKillFocus(void)
3747 {
3748 wxFocusEvent event(wxEVT_KILL_FOCUS, m_windowId);
3749 event.m_eventObject = this;
3750 if (!GetEventHandler()->ProcessEvent(event))
3751 Default();
3752 };
3753 #endif
3754
3755 void wxWindow::OnChar(wxKeyEvent& event)
3756 {
3757 bool isVirtual;
3758 int id = wxCharCodeWXToMSW((int)event.KeyCode(), &isVirtual);
3759
3760 if ( id == -1 )
3761 id= m_lastWParam;
3762
3763 if ( !event.ControlDown() )
3764 (void) MSWDefWindowProc(m_lastMsg, (WPARAM) id, m_lastLParam);
3765 }
3766
3767 void wxWindow::OnPaint(wxPaintEvent& event)
3768 {
3769 Default();
3770 }
3771
3772 bool wxWindow::IsEnabled(void) const
3773 {
3774 return (::IsWindowEnabled((HWND) GetHWND()) != 0);
3775 }
3776
3777 // Dialog support: override these and call
3778 // base class members to add functionality
3779 // that can't be done using validators.
3780 // NOTE: these functions assume that controls
3781 // are direct children of this window, not grandchildren
3782 // or other levels of descendant.
3783
3784 // Transfer values to controls. If returns FALSE,
3785 // it's an application error (pops up a dialog)
3786 bool wxWindow::TransferDataToWindow(void)
3787 {
3788 wxNode *node = GetChildren()->First();
3789 while ( node )
3790 {
3791 wxWindow *child = (wxWindow *)node->Data();
3792 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */
3793 !child->GetValidator()->TransferToWindow() )
3794 {
3795 wxMessageBox("Application Error", "Could not transfer data to window", wxOK|wxICON_EXCLAMATION);
3796 return FALSE;
3797 }
3798
3799 node = node->Next();
3800 }
3801 return TRUE;
3802 }
3803
3804 // Transfer values from controls. If returns FALSE,
3805 // validation failed: don't quit
3806 bool wxWindow::TransferDataFromWindow(void)
3807 {
3808 wxNode *node = GetChildren()->First();
3809 while ( node )
3810 {
3811 wxWindow *child = (wxWindow *)node->Data();
3812 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->TransferFromWindow() )
3813 {
3814 return FALSE;
3815 }
3816
3817 node = node->Next();
3818 }
3819 return TRUE;
3820 }
3821
3822 bool wxWindow::Validate(void)
3823 {
3824 wxNode *node = GetChildren()->First();
3825 while ( node )
3826 {
3827 wxWindow *child = (wxWindow *)node->Data();
3828 if ( child->GetValidator() && /* child->GetValidator()->Ok() && */ !child->GetValidator()->Validate(this) )
3829 {
3830 return FALSE;
3831 }
3832
3833 node = node->Next();
3834 }
3835 return TRUE;
3836 }
3837
3838 // Get the window with the focus
3839 wxWindow *wxWindow::FindFocus(void)
3840 {
3841 HWND hWnd = ::GetFocus();
3842 if ( hWnd )
3843 {
3844 return wxFindWinFromHandle((WXHWND) hWnd);
3845 }
3846 return NULL;
3847 }
3848
3849 void wxWindow::AddChild(wxWindow *child)
3850 {
3851 GetChildren()->Append(child);
3852 child->m_windowParent = this;
3853 }
3854
3855 void wxWindow::RemoveChild(wxWindow *child)
3856 {
3857 if (GetChildren())
3858 GetChildren()->DeleteObject(child);
3859 child->m_windowParent = NULL;
3860 }
3861
3862 void wxWindow::DestroyChildren(void)
3863 {
3864 if (GetChildren()) {
3865 wxNode *node;
3866 while ((node = GetChildren()->First()) != (wxNode *)NULL) {
3867 wxWindow *child;
3868 if ((child = (wxWindow *)node->Data()) != (wxWindow *)NULL) {
3869 delete child;
3870 if ( GetChildren()->Member(child) )
3871 delete node;
3872 }
3873 } /* while */
3874 }
3875 }
3876
3877 void wxWindow::MakeModal(const bool modal)
3878 {
3879 // Disable all other windows
3880 if (this->IsKindOf(CLASSINFO(wxDialog)) || this->IsKindOf(CLASSINFO(wxFrame)))
3881 {
3882 wxNode *node = wxTopLevelWindows.First();
3883 while (node)
3884 {
3885 wxWindow *win = (wxWindow *)node->Data();
3886 if (win != this)
3887 win->Enable(!modal);
3888
3889 node = node->Next();
3890 }
3891 }
3892 }
3893
3894 // If nothing defined for this, try the parent.
3895 // E.g. we may be a button loaded from a resource, with no callback function
3896 // defined.
3897 void wxWindow::OnCommand(wxWindow& win, wxCommandEvent& event)
3898 {
3899 if (GetEventHandler()->ProcessEvent(event) )
3900 return;
3901 if (m_windowParent)
3902 m_windowParent->GetEventHandler()->OnCommand(win, event);
3903 }
3904
3905 void wxWindow::SetConstraints(wxLayoutConstraints *c)
3906 {
3907 if (m_constraints)
3908 {
3909 UnsetConstraints(m_constraints);
3910 delete m_constraints;
3911 }
3912 m_constraints = c;
3913 if (m_constraints)
3914 {
3915 // Make sure other windows know they're part of a 'meaningful relationship'
3916 if (m_constraints->left.GetOtherWindow() && (m_constraints->left.GetOtherWindow() != this))
3917 m_constraints->left.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3918 if (m_constraints->top.GetOtherWindow() && (m_constraints->top.GetOtherWindow() != this))
3919 m_constraints->top.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3920 if (m_constraints->right.GetOtherWindow() && (m_constraints->right.GetOtherWindow() != this))
3921 m_constraints->right.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3922 if (m_constraints->bottom.GetOtherWindow() && (m_constraints->bottom.GetOtherWindow() != this))
3923 m_constraints->bottom.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3924 if (m_constraints->width.GetOtherWindow() && (m_constraints->width.GetOtherWindow() != this))
3925 m_constraints->width.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3926 if (m_constraints->height.GetOtherWindow() && (m_constraints->height.GetOtherWindow() != this))
3927 m_constraints->height.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3928 if (m_constraints->centreX.GetOtherWindow() && (m_constraints->centreX.GetOtherWindow() != this))
3929 m_constraints->centreX.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3930 if (m_constraints->centreY.GetOtherWindow() && (m_constraints->centreY.GetOtherWindow() != this))
3931 m_constraints->centreY.GetOtherWindow()->AddConstraintReference((wxWindow *)this);
3932 }
3933 }
3934
3935 // This removes any dangling pointers to this window
3936 // in other windows' constraintsInvolvedIn lists.
3937 void wxWindow::UnsetConstraints(wxLayoutConstraints *c)
3938 {
3939 if (c)
3940 {
3941 if (c->left.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3942 c->left.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3943 if (c->top.GetOtherWindow() && (c->top.GetOtherWindow() != this))
3944 c->top.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3945 if (c->right.GetOtherWindow() && (c->right.GetOtherWindow() != this))
3946 c->right.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3947 if (c->bottom.GetOtherWindow() && (c->bottom.GetOtherWindow() != this))
3948 c->bottom.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3949 if (c->width.GetOtherWindow() && (c->width.GetOtherWindow() != this))
3950 c->width.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3951 if (c->height.GetOtherWindow() && (c->height.GetOtherWindow() != this))
3952 c->height.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3953 if (c->centreX.GetOtherWindow() && (c->centreX.GetOtherWindow() != this))
3954 c->centreX.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3955 if (c->centreY.GetOtherWindow() && (c->centreY.GetOtherWindow() != this))
3956 c->centreY.GetOtherWindow()->RemoveConstraintReference((wxWindow *)this);
3957 }
3958 }
3959
3960 // Back-pointer to other windows we're involved with, so if we delete
3961 // this window, we must delete any constraints we're involved with.
3962 void wxWindow::AddConstraintReference(wxWindow *otherWin)
3963 {
3964 if (!m_constraintsInvolvedIn)
3965 m_constraintsInvolvedIn = new wxList;
3966 if (!m_constraintsInvolvedIn->Member(otherWin))
3967 m_constraintsInvolvedIn->Append(otherWin);
3968 }
3969
3970 // REMOVE back-pointer to other windows we're involved with.
3971 void wxWindow::RemoveConstraintReference(wxWindow *otherWin)
3972 {
3973 if (m_constraintsInvolvedIn)
3974 m_constraintsInvolvedIn->DeleteObject(otherWin);
3975 }
3976
3977 // Reset any constraints that mention this window
3978 void wxWindow::DeleteRelatedConstraints(void)
3979 {
3980 if (m_constraintsInvolvedIn)
3981 {
3982 wxNode *node = m_constraintsInvolvedIn->First();
3983 while (node)
3984 {
3985 wxWindow *win = (wxWindow *)node->Data();
3986 wxNode *next = node->Next();
3987 wxLayoutConstraints *constr = win->GetConstraints();
3988
3989 // Reset any constraints involving this window
3990 if (constr)
3991 {
3992 constr->left.ResetIfWin((wxWindow *)this);
3993 constr->top.ResetIfWin((wxWindow *)this);
3994 constr->right.ResetIfWin((wxWindow *)this);
3995 constr->bottom.ResetIfWin((wxWindow *)this);
3996 constr->width.ResetIfWin((wxWindow *)this);
3997 constr->height.ResetIfWin((wxWindow *)this);
3998 constr->centreX.ResetIfWin((wxWindow *)this);
3999 constr->centreY.ResetIfWin((wxWindow *)this);
4000 }
4001 delete node;
4002 node = next;
4003 }
4004 delete m_constraintsInvolvedIn;
4005 m_constraintsInvolvedIn = NULL;
4006 }
4007 }
4008
4009 void wxWindow::SetSizer(wxSizer *sizer)
4010 {
4011 m_windowSizer = sizer;
4012 if (sizer)
4013 sizer->SetSizerParent((wxWindow *)this);
4014 }
4015
4016 /*
4017 * New version
4018 */
4019
4020 bool wxWindow::Layout(void)
4021 {
4022 if (GetConstraints())
4023 {
4024 int w, h;
4025 GetClientSize(&w, &h);
4026 GetConstraints()->width.SetValue(w);
4027 GetConstraints()->height.SetValue(h);
4028 }
4029
4030 // If top level (one sizer), evaluate the sizer's constraints.
4031 if (GetSizer())
4032 {
4033 int noChanges;
4034 GetSizer()->ResetConstraints(); // Mark all constraints as unevaluated
4035 GetSizer()->LayoutPhase1(&noChanges);
4036 GetSizer()->LayoutPhase2(&noChanges);
4037 GetSizer()->SetConstraintSizes(); // Recursively set the real window sizes
4038 return TRUE;
4039 }
4040 else
4041 {
4042 // Otherwise, evaluate child constraints
4043 ResetConstraints(); // Mark all constraints as unevaluated
4044 DoPhase(1); // Just one phase need if no sizers involved
4045 DoPhase(2);
4046 SetConstraintSizes(); // Recursively set the real window sizes
4047 }
4048 return TRUE;
4049 }
4050
4051
4052 // Do a phase of evaluating constraints:
4053 // the default behaviour. wxSizers may do a similar
4054 // thing, but also impose their own 'constraints'
4055 // and order the evaluation differently.
4056 bool wxWindow::LayoutPhase1(int *noChanges)
4057 {
4058 wxLayoutConstraints *constr = GetConstraints();
4059 if (constr)
4060 {
4061 return constr->SatisfyConstraints((wxWindow *)this, noChanges);
4062 }
4063 else
4064 return TRUE;
4065 }
4066
4067 bool wxWindow::LayoutPhase2(int *noChanges)
4068 {
4069 *noChanges = 0;
4070
4071 // Layout children
4072 DoPhase(1);
4073 DoPhase(2);
4074 return TRUE;
4075 }
4076
4077 // Do a phase of evaluating child constraints
4078 bool wxWindow::DoPhase(const int phase)
4079 {
4080 int noIterations = 0;
4081 int maxIterations = 500;
4082 int noChanges = 1;
4083 int noFailures = 0;
4084 wxList succeeded;
4085 while ((noChanges > 0) && (noIterations < maxIterations))
4086 {
4087 noChanges = 0;
4088 noFailures = 0;
4089 wxNode *node = GetChildren()->First();
4090 while (node)
4091 {
4092 wxWindow *child = (wxWindow *)node->Data();
4093 if (!child->IsKindOf(CLASSINFO(wxFrame)) && !child->IsKindOf(CLASSINFO(wxDialog)))
4094 {
4095 wxLayoutConstraints *constr = child->GetConstraints();
4096 if (constr)
4097 {
4098 if (succeeded.Member(child))
4099 {
4100 }
4101 else
4102 {
4103 int tempNoChanges = 0;
4104 bool success = ( (phase == 1) ? child->LayoutPhase1(&tempNoChanges) : child->LayoutPhase2(&tempNoChanges) ) ;
4105 noChanges += tempNoChanges;
4106 if (success)
4107 {
4108 succeeded.Append(child);
4109 }
4110 }
4111 }
4112 }
4113 node = node->Next();
4114 }
4115 noIterations ++;
4116 }
4117 return TRUE;
4118 }
4119
4120 void wxWindow::ResetConstraints(void)
4121 {
4122 wxLayoutConstraints *constr = GetConstraints();
4123 if (constr)
4124 {
4125 constr->left.SetDone(FALSE);
4126 constr->top.SetDone(FALSE);
4127 constr->right.SetDone(FALSE);
4128 constr->bottom.SetDone(FALSE);
4129 constr->width.SetDone(FALSE);
4130 constr->height.SetDone(FALSE);
4131 constr->centreX.SetDone(FALSE);
4132 constr->centreY.SetDone(FALSE);
4133 }
4134 wxNode *node = GetChildren()->First();
4135 while (node)
4136 {
4137 wxWindow *win = (wxWindow *)node->Data();
4138 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
4139 win->ResetConstraints();
4140 node = node->Next();
4141 }
4142 }
4143
4144 // Need to distinguish between setting the 'fake' size for
4145 // windows and sizers, and setting the real values.
4146 void wxWindow::SetConstraintSizes(const bool recurse)
4147 {
4148 wxLayoutConstraints *constr = GetConstraints();
4149 if (constr && constr->left.GetDone() && constr->right.GetDone() &&
4150 constr->width.GetDone() && constr->height.GetDone())
4151 {
4152 int x = constr->left.GetValue();
4153 int y = constr->top.GetValue();
4154 int w = constr->width.GetValue();
4155 int h = constr->height.GetValue();
4156
4157 // If we don't want to resize this window, just move it...
4158 if ((constr->width.GetRelationship() != wxAsIs) ||
4159 (constr->height.GetRelationship() != wxAsIs))
4160 {
4161 // Calls Layout() recursively. AAAGH. How can we stop that.
4162 // Simply take Layout() out of non-top level OnSizes.
4163 SizerSetSize(x, y, w, h);
4164 }
4165 else
4166 {
4167 SizerMove(x, y);
4168 }
4169 }
4170 else if (constr)
4171 {
4172 char *windowClass = this->GetClassInfo()->GetClassName();
4173
4174 wxString winName;
4175 if (GetName() == "")
4176 winName = "unnamed";
4177 else
4178 winName = GetName();
4179 wxDebugMsg("Constraint(s) not satisfied for window of type %s, name %s:\n", (const char *)windowClass, (const char *)winName);
4180 if (!constr->left.GetDone())
4181 wxDebugMsg(" unsatisfied 'left' constraint.\n");
4182 if (!constr->right.GetDone())
4183 wxDebugMsg(" unsatisfied 'right' constraint.\n");
4184 if (!constr->width.GetDone())
4185 wxDebugMsg(" unsatisfied 'width' constraint.\n");
4186 if (!constr->height.GetDone())
4187 wxDebugMsg(" unsatisfied 'height' constraint.\n");
4188 wxDebugMsg("Please check constraints: try adding AsIs() constraints.\n");
4189 }
4190
4191 if (recurse)
4192 {
4193 wxNode *node = GetChildren()->First();
4194 while (node)
4195 {
4196 wxWindow *win = (wxWindow *)node->Data();
4197 if (!win->IsKindOf(CLASSINFO(wxFrame)) && !win->IsKindOf(CLASSINFO(wxDialog)))
4198 win->SetConstraintSizes();
4199 node = node->Next();
4200 }
4201 }
4202 }
4203
4204 // This assumes that all sizers are 'on' the same
4205 // window, i.e. the parent of this window.
4206 void wxWindow::TransformSizerToActual(int *x, int *y) const
4207 {
4208 if (!m_sizerParent || m_sizerParent->IsKindOf(CLASSINFO(wxDialog)) ||
4209 m_sizerParent->IsKindOf(CLASSINFO(wxFrame)) )
4210 return;
4211
4212 int xp, yp;
4213 m_sizerParent->GetPosition(&xp, &yp);
4214 m_sizerParent->TransformSizerToActual(&xp, &yp);
4215 *x += xp;
4216 *y += yp;
4217 }
4218
4219 void wxWindow::SizerSetSize(const int x, const int y, const int w, const int h)
4220 {
4221 int xx = x;
4222 int yy = y;
4223 TransformSizerToActual(&xx, &yy);
4224 SetSize(xx, yy, w, h);
4225 }
4226
4227 void wxWindow::SizerMove(const int x, const int y)
4228 {
4229 int xx = x;
4230 int yy = y;
4231 TransformSizerToActual(&xx, &yy);
4232 Move(xx, yy);
4233 }
4234
4235 // Only set the size/position of the constraint (if any)
4236 void wxWindow::SetSizeConstraint(const int x, const int y, const int w, const int h)
4237 {
4238 wxLayoutConstraints *constr = GetConstraints();
4239 if (constr)
4240 {
4241 if (x != -1)
4242 {
4243 constr->left.SetValue(x);
4244 constr->left.SetDone(TRUE);
4245 }
4246 if (y != -1)
4247 {
4248 constr->top.SetValue(y);
4249 constr->top.SetDone(TRUE);
4250 }
4251 if (w != -1)
4252 {
4253 constr->width.SetValue(w);
4254 constr->width.SetDone(TRUE);
4255 }
4256 if (h != -1)
4257 {
4258 constr->height.SetValue(h);
4259 constr->height.SetDone(TRUE);
4260 }
4261 }
4262 }
4263
4264 void wxWindow::MoveConstraint(const int x, const int y)
4265 {
4266 wxLayoutConstraints *constr = GetConstraints();
4267 if (constr)
4268 {
4269 if (x != -1)
4270 {
4271 constr->left.SetValue(x);
4272 constr->left.SetDone(TRUE);
4273 }
4274 if (y != -1)
4275 {
4276 constr->top.SetValue(y);
4277 constr->top.SetDone(TRUE);
4278 }
4279 }
4280 }
4281
4282 void wxWindow::GetSizeConstraint(int *w, int *h) const
4283 {
4284 wxLayoutConstraints *constr = GetConstraints();
4285 if (constr)
4286 {
4287 *w = constr->width.GetValue();
4288 *h = constr->height.GetValue();
4289 }
4290 else
4291 GetSize(w, h);
4292 }
4293
4294 void wxWindow::GetClientSizeConstraint(int *w, int *h) const
4295 {
4296 wxLayoutConstraints *constr = GetConstraints();
4297 if (constr)
4298 {
4299 *w = constr->width.GetValue();
4300 *h = constr->height.GetValue();
4301 }
4302 else
4303 GetClientSize(w, h);
4304 }
4305
4306 void wxWindow::GetPositionConstraint(int *x, int *y) const
4307 {
4308 wxLayoutConstraints *constr = GetConstraints();
4309 if (constr)
4310 {
4311 *x = constr->left.GetValue();
4312 *y = constr->top.GetValue();
4313 }
4314 else
4315 GetPosition(x, y);
4316 }
4317
4318 bool wxWindow::Close(const bool force)
4319 {
4320 // Let's generalise it to work the same for any window.
4321 /*
4322 if (!IsKindOf(CLASSINFO(wxDialog)) && !IsKindOf(CLASSINFO(wxFrame)))
4323 {
4324 this->Destroy();
4325 return TRUE;
4326 }
4327 */
4328
4329 wxCloseEvent event(wxEVT_CLOSE_WINDOW, m_windowId);
4330 event.SetEventObject(this);
4331 event.SetForce(force);
4332
4333 return GetEventHandler()->ProcessEvent(event);
4334
4335 /*
4336 if ( !force && event.GetVeto() )
4337 return FALSE;
4338
4339 Show(FALSE);
4340
4341 if (!wxPendingDelete.Member(this))
4342 wxPendingDelete.Append(this);
4343
4344 return TRUE;
4345 */
4346 }
4347
4348 wxObject* wxWindow::GetChild(const int number) const
4349 {
4350 // Return a pointer to the Nth object in the Panel
4351 if (!GetChildren())
4352 return(NULL) ;
4353 wxNode *node = GetChildren()->First();
4354 int n = number;
4355 while (node && n--)
4356 node = node->Next() ;
4357 if (node)
4358 {
4359 wxObject *obj = (wxObject *)node->Data();
4360 return(obj) ;
4361 }
4362 else
4363 return NULL ;
4364 }
4365
4366 void wxWindow::OnDefaultAction(wxControl *initiatingItem)
4367 {
4368 if (initiatingItem->IsKindOf(CLASSINFO(wxListBox)) && initiatingItem->GetCallback())
4369 {
4370 wxListBox *lbox = (wxListBox *)initiatingItem;
4371 wxCommandEvent event(wxEVT_COMMAND_LEFT_DCLICK);
4372 event.m_commandInt = -1;
4373 if ((lbox->GetWindowStyleFlag() & wxLB_MULTIPLE) == 0)
4374 {
4375 event.m_commandString = copystring(lbox->GetStringSelection());
4376 event.m_commandInt = lbox->GetSelection();
4377 event.m_clientData = lbox->wxListBox::GetClientData(event.m_commandInt);
4378 }
4379 event.m_eventObject = lbox;
4380
4381 lbox->ProcessCommand(event);
4382
4383 if (event.m_commandString)
4384 delete[] event.m_commandString;
4385 return;
4386 }
4387
4388 wxButton *but = GetDefaultItem();
4389 if (but)
4390 {
4391 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED);
4392 but->Command(event);
4393 }
4394 }
4395
4396 void wxWindow::Clear(void)
4397 {
4398 wxClientDC dc(this);
4399 wxBrush brush(GetBackgroundColour(), wxSOLID);
4400 dc.SetBackground(brush);
4401 dc.Clear();
4402 }
4403
4404 // Fits the panel around the items
4405 void wxWindow::Fit(void)
4406 {
4407 int maxX = 0;
4408 int maxY = 0;
4409 wxNode *node = GetChildren()->First();
4410 while ( node )
4411 {
4412 wxWindow *win = (wxWindow *)node->Data();
4413 int wx, wy, ww, wh;
4414 win->GetPosition(&wx, &wy);
4415 win->GetSize(&ww, &wh);
4416 if ( wx + ww > maxX )
4417 maxX = wx + ww;
4418 if ( wy + wh > maxY )
4419 maxY = wy + wh;
4420
4421 node = node->Next();
4422 }
4423 SetClientSize(maxX + 5, maxY + 5);
4424 }
4425
4426 void wxWindow::SetValidator(const wxValidator& validator)
4427 {
4428 if ( m_windowValidator )
4429 delete m_windowValidator;
4430 m_windowValidator = validator.Clone();
4431
4432 if ( m_windowValidator )
4433 m_windowValidator->SetWindow(this) ;
4434 }
4435
4436 // Find a window by id or name
4437 wxWindow *wxWindow::FindWindow(const long id)
4438 {
4439 if ( GetId() == id)
4440 return this;
4441
4442 wxNode *node = GetChildren()->First();
4443 while ( node )
4444 {
4445 wxWindow *child = (wxWindow *)node->Data();
4446 wxWindow *found = child->FindWindow(id);
4447 if ( found )
4448 return found;
4449 node = node->Next();
4450 }
4451 return NULL;
4452 }
4453
4454 wxWindow *wxWindow::FindWindow(const wxString& name)
4455 {
4456 if ( GetName() == name)
4457 return this;
4458
4459 wxNode *node = GetChildren()->First();
4460 while ( node )
4461 {
4462 wxWindow *child = (wxWindow *)node->Data();
4463 wxWindow *found = child->FindWindow(name);
4464 if ( found )
4465 return found;
4466 node = node->Next();
4467 }
4468 return NULL;
4469 }
4470
4471 /* TODO
4472 // Default input behaviour for a scrolling canvas should be to scroll
4473 // according to the cursor keys pressed
4474 void wxWindow::OnChar(wxKeyEvent& event)
4475 {
4476 int x_page = 0;
4477 int y_page = 0;
4478 int start_x = 0;
4479 int start_y = 0;
4480 // Bugfix Begin
4481 int v_width = 0;
4482 int v_height = 0;
4483 int y_pages = 0;
4484 // Bugfix End
4485
4486 GetScrollUnitsPerPage(&x_page, &y_page);
4487 // Bugfix Begin
4488 GetVirtualSize(&v_width,&v_height);
4489 // Bugfix End
4490 ViewStart(&start_x, &start_y);
4491 // Bugfix begin
4492 if (vert_units)
4493 y_pages = (int)(v_height/vert_units) - y_page;
4494
4495 #ifdef __WINDOWS__
4496 int y = 0;
4497 #else
4498 int y = y_page-1;
4499 #endif
4500 // Bugfix End
4501 switch (event.keyCode)
4502 {
4503 case WXK_PRIOR:
4504 {
4505 // BugFix Begin
4506 if (y_page > 0)
4507 {
4508 if (start_y - y_page > 0)
4509 Scroll(start_x, start_y - y_page);
4510 else
4511 Scroll(start_x, 0);
4512 }
4513 // Bugfix End
4514 break;
4515 }
4516 case WXK_NEXT:
4517 {
4518 // Bugfix Begin
4519 if ((y_page > 0) && (start_y <= y_pages-y-1))
4520 {
4521 if (y_pages + y < start_y + y_page)
4522 Scroll(start_x, y_pages + y);
4523 else
4524 Scroll(start_x, start_y + y_page);
4525 }
4526 // Bugfix End
4527 break;
4528 }
4529 case WXK_UP:
4530 {
4531 if ((y_page > 0) && (start_y >= 1))
4532 Scroll(start_x, start_y - 1);
4533 break;
4534 }
4535 case WXK_DOWN:
4536 {
4537 // Bugfix Begin
4538 if ((y_page > 0) && (start_y <= y_pages-y-1))
4539 // Bugfix End
4540 {
4541 Scroll(start_x, start_y + 1);
4542 }
4543 break;
4544 }
4545 case WXK_LEFT:
4546 {
4547 if ((x_page > 0) && (start_x >= 1))
4548 Scroll(start_x - 1, start_y);
4549 break;
4550 }
4551 case WXK_RIGHT:
4552 {
4553 if (x_page > 0)
4554 Scroll(start_x + 1, start_y);
4555 break;
4556 }
4557 case WXK_HOME:
4558 {
4559 Scroll(0, 0);
4560 break;
4561 }
4562 // This is new
4563 case WXK_END:
4564 {
4565 Scroll(start_x, y_pages+y);
4566 break;
4567 }
4568 // end
4569 }
4570 }
4571 */
4572
4573 // Setup background and foreground colours correctly
4574 void wxWindow::SetupColours(void)
4575 {
4576 if (GetParent())
4577 SetBackgroundColour(GetParent()->GetBackgroundColour());
4578 }
4579
4580 // Do Update UI processing for child controls
4581
4582 // TODO: should this be implemented for the child window rather
4583 // than the parent? Then you can override it e.g. for wxCheckBox
4584 // to do the Right Thing rather than having to assume a fixed number
4585 // of control classes.
4586
4587 void wxWindow::UpdateWindowUI(void)
4588 {
4589 wxWindowID id = GetId();
4590 if (id > 0)
4591 {
4592 wxUpdateUIEvent event(id);
4593 event.m_eventObject = this;
4594
4595 if (this->GetEventHandler()->ProcessEvent(event))
4596 {
4597 if (event.GetSetEnabled())
4598 this->Enable(event.GetEnabled());
4599
4600 if (event.GetSetText() && this->IsKindOf(CLASSINFO(wxControl)))
4601 ((wxControl*)this)->SetLabel(event.GetText());
4602
4603 if (this->IsKindOf(CLASSINFO(wxCheckBox)))
4604 {
4605 if (event.GetSetChecked())
4606 ((wxCheckBox *) this)->SetValue(event.GetChecked());
4607 }
4608 else if (this->IsKindOf(CLASSINFO(wxRadioButton)))
4609 {
4610 if (event.GetSetChecked())
4611 ((wxRadioButton *) this)->SetValue(event.GetChecked());
4612 }
4613 }
4614 }
4615
4616 }
4617
4618 void wxWindow::OnIdle(wxIdleEvent& event)
4619 {
4620 // Check if we need to send a LEAVE event
4621 if (m_mouseInWindow)
4622 {
4623 POINT pt;
4624 ::GetCursorPos(&pt);
4625 if (::WindowFromPoint(pt) != (HWND) GetHWND())
4626 {
4627 // Generate a LEAVE event
4628 m_mouseInWindow = FALSE;
4629 MSWOnMouseLeave(pt.x, pt.y, 0);
4630 }
4631 }
4632 UpdateWindowUI();
4633 }
4634
4635 // Raise the window to the top of the Z order
4636 void wxWindow::Raise(void)
4637 {
4638 ::BringWindowToTop((HWND) GetHWND());
4639 }
4640
4641 // Lower the window to the bottom of the Z order
4642 void wxWindow::Lower(void)
4643 {
4644 ::SetWindowPos((HWND) GetHWND(), HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
4645 }
4646