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