]> git.saurik.com Git - wxWidgets.git/blame - src/msw/control.cpp
implementation changes to closer follow MSW, crashes fixed
[wxWidgets.git] / src / msw / control.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
1e6feb95 2// Name: msw/control.cpp
2bda0e17
KB
3// Purpose: wxControl class
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
6c9a19aa 8// Copyright: (c) Julian Smart
a23fd0e1 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
14f355c2 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
1e6feb95 13 #pragma implementation "control.h"
2bda0e17
KB
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
1e6feb95 20 #pragma hdrstop
2bda0e17
KB
21#endif
22
1e6feb95
VZ
23#if wxUSE_CONTROLS
24
2bda0e17 25#ifndef WX_PRECOMP
1e6feb95
VZ
26 #include "wx/event.h"
27 #include "wx/app.h"
28 #include "wx/dcclient.h"
29 #include "wx/log.h"
2bda0e17
KB
30#endif
31
2432b92d
JS
32#include "wx/control.h"
33
2bda0e17
KB
34#include "wx/msw/private.h"
35
b39dbf34 36#if defined(__WIN95__) && !(defined(__GNUWIN32_OLD__) && !defined(__CYGWIN10__))
c42404a5 37 #include <commctrl.h>
2bda0e17
KB
38#endif
39
2bda0e17
KB
40IMPLEMENT_ABSTRACT_CLASS(wxControl, wxWindow)
41
42BEGIN_EVENT_TABLE(wxControl, wxWindow)
a23fd0e1 43 EVT_ERASE_BACKGROUND(wxControl::OnEraseBackground)
2bda0e17 44END_EVENT_TABLE()
2bda0e17
KB
45
46// Item members
42e69d6b 47wxControl::wxControl()
2bda0e17 48{
2bda0e17
KB
49}
50
42e69d6b 51wxControl::~wxControl()
2bda0e17 52{
42e69d6b 53 m_isBeingDeleted = TRUE;
2bda0e17
KB
54}
55
8d772832 56
5b2f31eb
VZ
57bool wxControl::Create(wxWindow *parent,
58 wxWindowID id,
8d772832 59 const wxPoint& pos,
5b2f31eb
VZ
60 const wxSize& size,
61 long style,
8d772832 62 const wxValidator& validator,
8d772832
RD
63 const wxString& name)
64{
5b2f31eb
VZ
65 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
66 return FALSE;
67
8d772832 68#if wxUSE_VALIDATORS
5b2f31eb 69 SetValidator(validator);
8d772832 70#endif
5b2f31eb
VZ
71
72 return TRUE;
73}
74
75bool wxControl::MSWCreateControl(const wxChar *classname,
76 const wxString& label,
77 const wxPoint& pos,
6dd16e4f 78 const wxSize& size)
5b2f31eb
VZ
79{
80 WXDWORD exstyle;
6dd16e4f 81 WXDWORD msStyle = MSWGetStyle(GetWindowStyle(), &exstyle);
5b2f31eb 82
2eb4c3aa 83 return MSWCreateControl(classname, msStyle, pos, size, label, exstyle);
8d772832
RD
84}
85
222594ea
VZ
86bool wxControl::MSWCreateControl(const wxChar *classname,
87 WXDWORD style,
88 const wxPoint& pos,
89 const wxSize& size,
90 const wxString& label,
2eb4c3aa 91 WXDWORD exstyle)
8d99be5f 92{
222594ea
VZ
93 // if no extended style given, determine it ourselves
94 if ( exstyle == (WXDWORD)-1 )
95 {
fe3d9123 96 exstyle = 0;
65bc172c 97 (void) MSWGetStyle(GetWindowStyle(), &exstyle);
222594ea
VZ
98 }
99
bdf5c30d
VZ
100 // all controls should have this style
101 style |= WS_CHILD;
102
103 // create the control visible if it's currently shown for wxWindows
104 if ( m_isShown )
105 {
106 style |= WS_VISIBLE;
107 }
3f2711d5 108
a63cbfa3
VZ
109 int x = pos.x == -1 ? 0 : pos.x,
110 y = pos.y == -1 ? 0 : pos.y,
111 w = size.x == -1 ? 0 : size.x,
112 h = size.y == -1 ? 0 : size.y;
113
8d99be5f
VZ
114 m_hWnd = (WXHWND)::CreateWindowEx
115 (
222594ea 116 exstyle, // extended style
8d99be5f 117 classname, // the kind of control to create
222594ea 118 label, // the window name
8d99be5f 119 style, // the window style
a63cbfa3 120 x, y, w, h, // the window position and size
8d99be5f
VZ
121 GetHwndOf(GetParent()), // parent
122 (HMENU)GetId(), // child id
123 wxGetInstance(), // app instance
124 NULL // creation parameters
125 );
126
127 if ( !m_hWnd )
128 {
f6bcfd97
BP
129 wxLogDebug(wxT("Failed to create a control of class '%s'"), classname);
130 wxFAIL_MSG(_T("something is very wrong"));
8d99be5f
VZ
131
132 return FALSE;
133 }
134
3f2711d5
VZ
135#if wxUSE_CTL3D
136 if ( want3D )
137 {
138 Ctl3dSubclassCtl(GetHwnd());
139 m_useCtl3D = TRUE;
140 }
141#endif // wxUSE_CTL3D
142
b225f659 143 // install wxWindows window proc for this window
8d99be5f
VZ
144 SubclassWin(m_hWnd);
145
146 // controls use the same font and colours as their parent dialog by default
147 InheritAttributes();
148
a63cbfa3 149 // set the size now if no initial size specified
d45720c5 150 if ( w <= 0 || h <= 0 )
a63cbfa3
VZ
151 {
152 SetBestSize(size);
153 }
154
8d99be5f
VZ
155 return TRUE;
156}
157
65bc172c
VZ
158wxBorder wxControl::GetDefaultBorder() const
159{
160 // we want to automatically give controls a sunken style (confusingly,
161 // it may not really mean sunken at all as we map it to WS_EX_CLIENTEDGE
162 // which is not sunken at all under Windows XP -- rather, just the default)
163 return wxBORDER_SUNKEN;
164}
165
f68586e5 166wxSize wxControl::DoGetBestSize() const
4438caf4
VZ
167{
168 return wxSize(DEFAULT_ITEM_WIDTH, DEFAULT_ITEM_HEIGHT);
169}
170
42e69d6b 171bool wxControl::ProcessCommand(wxCommandEvent& event)
2bda0e17 172{
42e69d6b 173 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
174}
175
a23fd0e1
VZ
176#ifdef __WIN95__
177bool wxControl::MSWOnNotify(int idCtrl,
178 WXLPARAM lParam,
179 WXLPARAM* result)
2bda0e17 180{
a23fd0e1 181 wxEventType eventType = wxEVT_NULL;
b6e5eaa5
VZ
182
183 NMHDR *hdr = (NMHDR*) lParam;
184 switch ( hdr->code )
a23fd0e1
VZ
185 {
186 case NM_CLICK:
187 eventType = wxEVT_COMMAND_LEFT_CLICK;
188 break;
2bda0e17 189
a23fd0e1
VZ
190 case NM_DBLCLK:
191 eventType = wxEVT_COMMAND_LEFT_DCLICK;
192 break;
2bda0e17 193
a23fd0e1
VZ
194 case NM_RCLICK:
195 eventType = wxEVT_COMMAND_RIGHT_CLICK;
196 break;
2bda0e17 197
a23fd0e1
VZ
198 case NM_RDBLCLK:
199 eventType = wxEVT_COMMAND_RIGHT_DCLICK;
200 break;
2bda0e17 201
a23fd0e1
VZ
202 case NM_SETFOCUS:
203 eventType = wxEVT_COMMAND_SET_FOCUS;
204 break;
debe6624 205
a23fd0e1
VZ
206 case NM_KILLFOCUS:
207 eventType = wxEVT_COMMAND_KILL_FOCUS;
208 break;
2bda0e17 209
a23fd0e1
VZ
210 case NM_RETURN:
211 eventType = wxEVT_COMMAND_ENTER;
212 break;
213
214 default:
215 return wxWindow::MSWOnNotify(idCtrl, lParam, result);
216 }
fd3f686c 217
b6e5eaa5 218 wxCommandEvent event(wxEVT_NULL, m_windowId);
2bda0e17 219 event.SetEventType(eventType);
a23fd0e1 220 event.SetEventObject(this);
2bda0e17 221
a23fd0e1 222 return GetEventHandler()->ProcessEvent(event);
2bda0e17 223}
a23fd0e1 224#endif // Win95
2bda0e17 225
2bda0e17
KB
226void wxControl::OnEraseBackground(wxEraseEvent& event)
227{
5bd3a2da
VZ
228 // notice that this 'dumb' implementation may cause flicker for some of the
229 // controls in which case they should intercept wxEraseEvent and process it
230 // themselves somehow
42e69d6b
VZ
231
232 RECT rect;
3f2711d5 233 ::GetClientRect(GetHwnd(), &rect);
42e69d6b 234
3f2711d5 235 HBRUSH hBrush = ::CreateSolidBrush(wxColourToRGB(GetBackgroundColour()));
42e69d6b 236
3f2711d5 237 HDC hdc = GetHdcOf((*event.GetDC()));
4676948b
JS
238
239#ifndef __WXWINCE__
3f2711d5 240 int mode = ::SetMapMode(hdc, MM_TEXT);
4676948b 241#endif
3f2711d5
VZ
242
243 ::FillRect(hdc, &rect, hBrush);
42e69d6b 244 ::DeleteObject(hBrush);
4676948b
JS
245
246#ifndef __WXWINCE__
3f2711d5 247 ::SetMapMode(hdc, mode);
4676948b 248#endif
2bda0e17
KB
249}
250
33ac7e6f 251WXHBRUSH wxControl::OnCtlColor(WXHDC pDC, WXHWND WXUNUSED(pWnd), WXUINT WXUNUSED(nCtlColor),
788722ac
JS
252#if wxUSE_CTL3D
253 WXUINT message,
254 WXWPARAM wParam,
255 WXLPARAM lParam
256#else
33ac7e6f
KB
257 WXUINT WXUNUSED(message),
258 WXWPARAM WXUNUSED(wParam),
788722ac
JS
259 WXLPARAM WXUNUSED(lParam)
260#endif
261 )
f048e32f
VZ
262{
263#if wxUSE_CTL3D
264 if ( m_useCtl3D )
265 {
266 HBRUSH hbrush = Ctl3dCtlColorEx(message, wParam, lParam);
267 return (WXHBRUSH) hbrush;
268 }
269#endif // wxUSE_CTL3D
270
271 HDC hdc = (HDC)pDC;
f6bcfd97
BP
272 wxColour colBack = GetBackgroundColour();
273
f048e32f
VZ
274 ::SetBkColor(hdc, wxColourToRGB(colBack));
275 ::SetTextColor(hdc, wxColourToRGB(GetForegroundColour()));
276
277 wxBrush *brush = wxTheBrushList->FindOrCreateBrush(colBack, wxSOLID);
278
279 return (WXHBRUSH)brush->GetResourceHandle();
280}
281
5b2f31eb 282WXDWORD wxControl::MSWGetStyle(long style, WXDWORD *exstyle) const
8d99be5f 283{
5b2f31eb 284 long msStyle = wxWindow::MSWGetStyle(style, exstyle);
8d99be5f 285
5b2f31eb
VZ
286 if ( AcceptsFocus() )
287 {
288 msStyle |= WS_TABSTOP;
289 }
8d99be5f 290
5b2f31eb 291 return msStyle;
8d99be5f
VZ
292}
293
42e69d6b
VZ
294// ---------------------------------------------------------------------------
295// global functions
296// ---------------------------------------------------------------------------
2bda0e17 297
42e69d6b
VZ
298// Call this repeatedly for several wnds to find the overall size
299// of the widget.
300// Call it initially with -1 for all values in rect.
301// Keep calling for other widgets, and rect will be modified
302// to calculate largest bounding rectangle.
303void wxFindMaxSize(WXHWND wnd, RECT *rect)
2bda0e17 304{
42e69d6b
VZ
305 int left = rect->left;
306 int right = rect->right;
307 int top = rect->top;
308 int bottom = rect->bottom;
2bda0e17 309
42e69d6b 310 GetWindowRect((HWND) wnd, rect);
2bda0e17 311
42e69d6b
VZ
312 if (left < 0)
313 return;
2bda0e17 314
42e69d6b
VZ
315 if (left < rect->left)
316 rect->left = left;
2bda0e17 317
42e69d6b
VZ
318 if (right > rect->right)
319 rect->right = right;
2bda0e17 320
42e69d6b
VZ
321 if (top < rect->top)
322 rect->top = top;
2bda0e17 323
42e69d6b
VZ
324 if (bottom > rect->bottom)
325 rect->bottom = bottom;
2bda0e17
KB
326}
327
1e6feb95 328#endif // wxUSE_CONTROLS