]>
Commit | Line | Data |
---|---|---|
0e320a79 DW |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: frame.cpp | |
3 | // Purpose: wxFrame | |
f0a56ab0 | 4 | // Author: David Webster |
0e320a79 | 5 | // Modified by: |
29435d81 | 6 | // Created: 10/27/99 |
0e320a79 | 7 | // RCS-ID: $Id$ |
f0a56ab0 | 8 | // Copyright: (c) David Webster |
0e320a79 DW |
9 | // Licence: wxWindows licence |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
21802234 DW |
12 | // For compilers that support precompilation, includes "wx.h". |
13 | #include "wx/wxprec.h" | |
14 | ||
29435d81 DW |
15 | #ifdef __BORLANDC__ |
16 | #pragma hdrstop | |
17 | #endif | |
18 | ||
21802234 DW |
19 | #ifndef WX_PRECOMP |
20 | #include "wx/setup.h" | |
21 | #include "wx/frame.h" | |
22 | #include "wx/menu.h" | |
23 | #include "wx/app.h" | |
24 | #include "wx/utils.h" | |
25 | #include "wx/dialog.h" | |
26 | #include "wx/settings.h" | |
27 | #include "wx/dcclient.h" | |
28 | #endif // WX_PRECOMP | |
29 | ||
30 | #include "wx/os2/private.h" | |
0e320a79 DW |
31 | #include "wx/statusbr.h" |
32 | #include "wx/toolbar.h" | |
33 | #include "wx/menuitem.h" | |
21802234 | 34 | #include "wx/log.h" |
0e320a79 | 35 | |
21802234 DW |
36 | extern wxWindowList wxModelessWindows; |
37 | extern wxList WXDLLEXPORT wxPendingDelete; | |
38 | extern wxChar wxFrameClassName[]; | |
39 | extern wxMenu *wxCurrentPopupMenu; | |
0e320a79 DW |
40 | |
41 | #if !USE_SHARED_LIBRARY | |
42 | BEGIN_EVENT_TABLE(wxFrame, wxWindow) | |
43 | EVT_SIZE(wxFrame::OnSize) | |
44 | EVT_ACTIVATE(wxFrame::OnActivate) | |
45 | EVT_MENU_HIGHLIGHT_ALL(wxFrame::OnMenuHighlight) | |
46 | EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged) | |
47 | EVT_IDLE(wxFrame::OnIdle) | |
48 | EVT_CLOSE(wxFrame::OnCloseWindow) | |
49 | END_EVENT_TABLE() | |
50 | ||
51 | IMPLEMENT_DYNAMIC_CLASS(wxFrame, wxWindow) | |
52 | #endif | |
53 | ||
0e320a79 | 54 | bool wxFrame::m_useNativeStatusBar = FALSE; |
0e320a79 DW |
55 | |
56 | wxFrame::wxFrame() | |
57 | { | |
21802234 | 58 | m_frameToolBar = NULL ; |
0e320a79 DW |
59 | m_frameMenuBar = NULL; |
60 | m_frameStatusBar = NULL; | |
61 | ||
0e320a79 DW |
62 | m_iconized = FALSE; |
63 | } | |
64 | ||
29435d81 DW |
65 | bool wxFrame::Create(wxWindow *parent, |
66 | wxWindowID id, | |
67 | const wxString& title, | |
68 | const wxPoint& pos, | |
69 | const wxSize& size, | |
70 | long style, | |
71 | const wxString& name) | |
0e320a79 | 72 | { |
21802234 DW |
73 | #if wxUSE_TOOLTIPS |
74 | m_hwndToolTip = 0; | |
75 | #endif | |
0e320a79 DW |
76 | |
77 | SetName(name); | |
78 | m_windowStyle = style; | |
79 | m_frameMenuBar = NULL; | |
80 | m_frameToolBar = NULL ; | |
81 | m_frameStatusBar = NULL; | |
82 | ||
83 | SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE)); | |
84 | ||
21802234 | 85 | // m_icon = NULL; |
0e320a79 DW |
86 | if ( id > -1 ) |
87 | m_windowId = id; | |
88 | else | |
89 | m_windowId = (int)NewControlId(); | |
90 | ||
91 | if (parent) parent->AddChild(this); | |
92 | ||
21802234 DW |
93 | int x = pos.x; |
94 | int y = pos.y; | |
95 | int width = size.x; | |
96 | int height = size.y; | |
0e320a79 | 97 | |
21802234 DW |
98 | m_iconized = FALSE; |
99 | ||
29435d81 DW |
100 | // we pass NULL as parent to MSWCreate because frames with parents behave |
101 | // very strangely under Win95 shell | |
102 | // Alteration by JACS: keep normal Windows behaviour (float on top of parent) | |
103 | // with this style. | |
21802234 DW |
104 | if ((m_windowStyle & wxFRAME_FLOAT_ON_PARENT) == 0) |
105 | parent = NULL; | |
0e320a79 | 106 | |
21802234 DW |
107 | if (!parent) |
108 | wxTopLevelWindows.Append(this); | |
109 | ||
110 | OS2Create(m_windowId, parent, wxFrameClassName, this, title, | |
111 | x, y, width, height, style); | |
112 | ||
113 | wxModelessWindows.Append(this); | |
114 | return TRUE; | |
0e320a79 DW |
115 | } |
116 | ||
117 | wxFrame::~wxFrame() | |
118 | { | |
21802234 | 119 | m_isBeingDeleted = TRUE; |
0e320a79 DW |
120 | wxTopLevelWindows.DeleteObject(this); |
121 | ||
122 | if (m_frameStatusBar) | |
123 | delete m_frameStatusBar; | |
124 | if (m_frameMenuBar) | |
125 | delete m_frameMenuBar; | |
126 | ||
29435d81 DW |
127 | /* New behaviour March 1998: check if it's the last top-level window */ |
128 | // if (wxTheApp && (this == wxTheApp->GetTopWindow())) | |
129 | ||
0e320a79 DW |
130 | if (wxTheApp && (wxTopLevelWindows.Number() == 0)) |
131 | { | |
132 | wxTheApp->SetTopWindow(NULL); | |
133 | ||
134 | if (wxTheApp->GetExitOnFrameDelete()) | |
135 | { | |
29435d81 | 136 | // PostQuitMessage(0); |
0e320a79 DW |
137 | } |
138 | } | |
139 | ||
140 | wxModelessWindows.DeleteObject(this); | |
21802234 DW |
141 | |
142 | // For some reason, wxWindows can activate another task altogether | |
143 | // when a frame is destroyed after a modal dialog has been invoked. | |
144 | // Try to bring the parent to the top. | |
145 | // MT:Only do this if this frame is currently the active window, else weird | |
146 | // things start to happen | |
29435d81 DW |
147 | |
148 | // TODO: | |
149 | /* | |
21802234 | 150 | if ( wxGetActiveWindow() == this ) |
29435d81 DW |
151 | if (GetParent() && GetParent()->GetHWND()) |
152 | ::BringWindowToTop((HWND) GetParent()->GetHWND()); | |
153 | */ | |
0e320a79 DW |
154 | } |
155 | ||
156 | // Get size *available for subwindows* i.e. excluding menu bar, toolbar etc. | |
21802234 | 157 | void wxFrame::DoGetClientSize(int *x, int *y) const |
0e320a79 | 158 | { |
29435d81 DW |
159 | // TODO: |
160 | /* | |
21802234 | 161 | RECT rect; |
29435d81 | 162 | ::GetClientRect(GetHwnd(), &rect); |
21802234 DW |
163 | |
164 | if ( GetStatusBar() ) | |
165 | { | |
166 | int statusX, statusY; | |
167 | GetStatusBar()->GetClientSize(&statusX, &statusY); | |
29435d81 | 168 | rect.bottom -= statusY; |
21802234 DW |
169 | } |
170 | ||
171 | wxPoint pt(GetClientAreaOrigin()); | |
21802234 DW |
172 | rect.bottom -= pt.y; |
173 | rect.right -= pt.x; | |
174 | ||
175 | if ( x ) | |
176 | *x = rect.right; | |
177 | if ( y ) | |
178 | *y = rect.bottom; | |
179 | */ | |
0e320a79 DW |
180 | } |
181 | ||
182 | // Set the client size (i.e. leave the calculation of borders etc. | |
183 | // to wxWindows) | |
21802234 | 184 | void wxFrame::DoSetClientSize(int width, int height) |
0e320a79 | 185 | { |
21802234 | 186 | HWND hWnd = GetHwnd(); |
0e320a79 | 187 | |
29435d81 DW |
188 | // TODO: |
189 | /* | |
21802234 | 190 | RECT rect; |
29435d81 | 191 | ::GetClientRect(hWnd, &rect); |
21802234 DW |
192 | |
193 | RECT rect2; | |
29435d81 | 194 | GetWindowRect(hWnd, &rect2); |
21802234 DW |
195 | |
196 | // Find the difference between the entire window (title bar and all) | |
197 | // and the client area; add this to the new client size to move the | |
198 | // window | |
21802234 DW |
199 | int actual_width = rect2.right - rect2.left - rect.right + width; |
200 | int actual_height = rect2.bottom - rect2.top - rect.bottom + height; | |
29435d81 | 201 | |
21802234 DW |
202 | if ( GetStatusBar() ) |
203 | { | |
204 | int statusX, statusY; | |
205 | GetStatusBar()->GetClientSize(&statusX, &statusY); | |
29435d81 | 206 | actual_height += statusY; |
21802234 | 207 | } |
29435d81 | 208 | |
21802234 DW |
209 | wxPoint pt(GetClientAreaOrigin()); |
210 | actual_width += pt.y; | |
211 | actual_height += pt.x; | |
212 | ||
213 | POINT point; | |
21802234 DW |
214 | point.x = rect2.left; |
215 | point.y = rect2.top; | |
216 | ||
217 | MoveWindow(hWnd, point.x, point.y, actual_width, actual_height, (BOOL)TRUE); | |
29435d81 | 218 | |
21802234 DW |
219 | wxSizeEvent event(wxSize(width, height), m_windowId); |
220 | event.SetEventObject( this ); | |
221 | GetEventHandler()->ProcessEvent(event); | |
29435d81 | 222 | */ |
0e320a79 DW |
223 | } |
224 | ||
21802234 | 225 | void wxFrame::DoGetSize(int *width, int *height) const |
0e320a79 | 226 | { |
29435d81 DW |
227 | // TODO: |
228 | /* | |
21802234 | 229 | RECT rect; |
29435d81 DW |
230 | GetWindowRect(GetHwnd(), &rect); |
231 | *width = rect.right - rect.left; | |
232 | *height = rect.bottom - rect.top; | |
233 | */ | |
0e320a79 DW |
234 | } |
235 | ||
21802234 | 236 | void wxFrame::DoGetPosition(int *x, int *y) const |
0e320a79 | 237 | { |
29435d81 DW |
238 | // TODO: |
239 | /* | |
21802234 | 240 | RECT rect; |
29435d81 DW |
241 | GetWindowRect(GetHwnd(), &rect); |
242 | POINT point; | |
243 | point.x = rect.left; | |
244 | point.y = rect.top; | |
21802234 DW |
245 | |
246 | *x = point.x; | |
247 | *y = point.y; | |
29435d81 | 248 | */ |
0e320a79 DW |
249 | } |
250 | ||
251 | bool wxFrame::Show(bool show) | |
252 | { | |
29435d81 | 253 | // TODO: |
21802234 | 254 | /* |
29435d81 | 255 | int cshow; |
21802234 DW |
256 | if (show) |
257 | cshow = SW_SHOW; | |
258 | else | |
259 | cshow = SW_HIDE; | |
29435d81 | 260 | |
21802234 DW |
261 | if (!show) |
262 | { | |
263 | // Try to highlight the correct window (the parent) | |
264 | HWND hWndParent = 0; | |
265 | if (GetParent()) | |
266 | { | |
267 | hWndParent = (HWND) GetParent()->GetHWND(); | |
268 | if (hWndParent) | |
29435d81 | 269 | ::BringWindowToTop(hWndParent); |
21802234 DW |
270 | } |
271 | } | |
272 | ||
29435d81 | 273 | ShowWindow(GetHwnd(), (BOOL)cshow); |
21802234 DW |
274 | if (show) |
275 | { | |
29435d81 | 276 | BringWindowToTop(GetHwnd()); |
21802234 DW |
277 | |
278 | wxActivateEvent event(wxEVT_ACTIVATE, TRUE, m_windowId); | |
279 | event.SetEventObject( this ); | |
280 | GetEventHandler()->ProcessEvent(event); | |
281 | } | |
282 | return TRUE; | |
29435d81 DW |
283 | */ |
284 | return FALSE; | |
0e320a79 DW |
285 | } |
286 | ||
287 | void wxFrame::Iconize(bool iconize) | |
288 | { | |
29435d81 DW |
289 | // TODO: |
290 | /* | |
21802234 DW |
291 | if (!iconize) |
292 | Show(TRUE); | |
293 | ||
294 | int cshow; | |
21802234 DW |
295 | if (iconize) |
296 | cshow = SW_MINIMIZE; | |
297 | else | |
298 | cshow = SW_RESTORE; | |
299 | ShowWindow(GetHwnd(), (BOOL)cshow); | |
21802234 | 300 | m_iconized = iconize; |
29435d81 | 301 | */ |
0e320a79 DW |
302 | } |
303 | ||
304 | // Equivalent to maximize/restore in Windows | |
305 | void wxFrame::Maximize(bool maximize) | |
306 | { | |
29435d81 DW |
307 | // TODO: |
308 | /* | |
21802234 DW |
309 | Show(TRUE); |
310 | int cshow; | |
21802234 DW |
311 | if (maximize) |
312 | cshow = SW_MAXIMIZE; | |
313 | else | |
314 | cshow = SW_RESTORE; | |
315 | ShowWindow(GetHwnd(), cshow); | |
21802234 | 316 | m_iconized = FALSE; |
29435d81 | 317 | */ |
0e320a79 DW |
318 | } |
319 | ||
320 | bool wxFrame::IsIconized() const | |
321 | { | |
29435d81 DW |
322 | // TODO: |
323 | /* | |
324 | ((wxFrame *)this)->m_iconized = (::IsIconic(GetHwnd()) != 0); | |
21802234 | 325 | return m_iconized; |
29435d81 DW |
326 | */ |
327 | return FALSE; | |
0e320a79 DW |
328 | } |
329 | ||
21802234 DW |
330 | // Is it maximized? |
331 | bool wxFrame::IsMaximized() const | |
0e320a79 | 332 | { |
29435d81 DW |
333 | // return (::IsZoomed(GetHwnd()) != 0) ; |
334 | return FALSE; | |
0e320a79 DW |
335 | } |
336 | ||
337 | void wxFrame::SetIcon(const wxIcon& icon) | |
338 | { | |
29435d81 DW |
339 | // TODO: |
340 | /* | |
0e320a79 | 341 | m_icon = icon; |
29435d81 DW |
342 | if ( m_icon.Ok() ) |
343 | SendMessage(GetHwnd(), WM_SETICON, | |
344 | (WPARAM)TRUE, (LPARAM)(HICON) m_icon.GetHICON()); | |
345 | */ | |
0e320a79 DW |
346 | } |
347 | ||
21802234 | 348 | #if wxUSE_STATUSBAR |
0e320a79 DW |
349 | wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id, |
350 | const wxString& name) | |
351 | { | |
352 | wxStatusBar *statusBar = NULL; | |
29435d81 DW |
353 | { |
354 | statusBar = new wxStatusBar(this, id, wxPoint(0, 0), wxSize(100, 20), | |
355 | style, name); | |
0e320a79 | 356 | |
29435d81 DW |
357 | // Set the height according to the font and the border size |
358 | wxClientDC dc(statusBar); | |
359 | dc.SetFont(statusBar->GetFont()); | |
0e320a79 | 360 | |
29435d81 DW |
361 | long x, y; |
362 | dc.GetTextExtent("X", &x, &y); | |
0e320a79 | 363 | |
29435d81 | 364 | int height = (int)( (y * 1.1) + 2* statusBar->GetBorderY()); |
0e320a79 | 365 | |
29435d81 DW |
366 | statusBar->SetSize(-1, -1, 100, height); |
367 | } | |
368 | ||
369 | statusBar->SetFieldsCount(number); | |
370 | return statusBar; | |
0e320a79 DW |
371 | } |
372 | ||
373 | wxStatusBar* wxFrame::CreateStatusBar(int number, long style, wxWindowID id, | |
374 | const wxString& name) | |
375 | { | |
21802234 | 376 | // VZ: calling CreateStatusBar twice is an error - why anyone would do it? |
c3d43472 | 377 | wxCHECK_MSG( m_frameStatusBar == NULL, FALSE, |
223d09f6 | 378 | wxT("recreating status bar in wxFrame") ); |
0e320a79 DW |
379 | |
380 | m_frameStatusBar = OnCreateStatusBar(number, style, id, | |
381 | name); | |
382 | if ( m_frameStatusBar ) | |
383 | { | |
384 | PositionStatusBar(); | |
385 | return m_frameStatusBar; | |
386 | } | |
387 | else | |
388 | return NULL; | |
389 | } | |
390 | ||
391 | void wxFrame::SetStatusText(const wxString& text, int number) | |
392 | { | |
223d09f6 | 393 | wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set text for") ); |
0e320a79 DW |
394 | |
395 | m_frameStatusBar->SetStatusText(text, number); | |
396 | } | |
397 | ||
398 | void wxFrame::SetStatusWidths(int n, const int widths_field[]) | |
399 | { | |
223d09f6 | 400 | wxCHECK_RET( m_frameStatusBar != NULL, wxT("no statusbar to set widths for") ); |
0e320a79 DW |
401 | |
402 | m_frameStatusBar->SetStatusWidths(n, widths_field); | |
403 | PositionStatusBar(); | |
404 | } | |
405 | ||
406 | void wxFrame::PositionStatusBar() | |
407 | { | |
21802234 DW |
408 | // native status bar positions itself |
409 | if (m_frameStatusBar) | |
410 | { | |
411 | int w, h; | |
412 | GetClientSize(&w, &h); | |
413 | int sw, sh; | |
414 | m_frameStatusBar->GetSize(&sw, &sh); | |
415 | ||
416 | // Since we wish the status bar to be directly under the client area, | |
417 | // we use the adjusted sizes without using wxSIZE_NO_ADJUSTMENTS. | |
418 | m_frameStatusBar->SetSize(0, h, w, sh); | |
419 | } | |
0e320a79 | 420 | } |
21802234 | 421 | #endif // wxUSE_STATUSBAR |
0e320a79 | 422 | |
21802234 | 423 | void wxFrame::DetachMenuBar() |
0e320a79 | 424 | { |
21802234 | 425 | if (m_frameMenuBar) |
0e320a79 | 426 | { |
29435d81 | 427 | m_frameMenuBar->Detach(); |
0e320a79 | 428 | m_frameMenuBar = NULL; |
21802234 DW |
429 | } |
430 | } | |
431 | ||
432 | void wxFrame::SetMenuBar(wxMenuBar *menu_bar) | |
433 | { | |
434 | if (!menu_bar) | |
435 | { | |
436 | DetachMenuBar(); | |
0e320a79 DW |
437 | return; |
438 | } | |
c3d43472 | 439 | |
29435d81 | 440 | wxCHECK_RET( !menu_bar->GetFrame(), wxT("this menubar is already attached") ); |
0e320a79 | 441 | |
21802234 DW |
442 | if (m_frameMenuBar) |
443 | delete m_frameMenuBar; | |
444 | ||
29435d81 | 445 | m_hMenu = menu_bar->Create(); |
21802234 DW |
446 | |
447 | if ( !m_hMenu ) | |
448 | return; | |
449 | ||
450 | InternalSetMenuBar(); | |
451 | ||
452 | m_frameMenuBar = menu_bar; | |
29435d81 | 453 | menu_bar->Attach(this); |
0e320a79 DW |
454 | } |
455 | ||
21802234 | 456 | void wxFrame::InternalSetMenuBar() |
0e320a79 | 457 | { |
21802234 | 458 | // TODO: |
29435d81 DW |
459 | /* |
460 | if ( !::SetMenu(GetHwnd(), (HMENU)m_hMenu) ) | |
0e320a79 | 461 | { |
21802234 | 462 | wxLogLastError("SetMenu"); |
0e320a79 | 463 | } |
21802234 | 464 | */ |
0e320a79 DW |
465 | } |
466 | ||
467 | // Responds to colour changes, and passes event on to children. | |
468 | void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event) | |
469 | { | |
470 | SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_APPWORKSPACE)); | |
471 | Refresh(); | |
472 | ||
473 | if ( m_frameStatusBar ) | |
474 | { | |
475 | wxSysColourChangedEvent event2; | |
476 | event2.SetEventObject( m_frameStatusBar ); | |
21802234 | 477 | m_frameStatusBar->GetEventHandler()->ProcessEvent(event2); |
0e320a79 DW |
478 | } |
479 | ||
480 | // Propagate the event to the non-top-level children | |
481 | wxWindow::OnSysColourChanged(event); | |
482 | } | |
483 | ||
21802234 DW |
484 | /* |
485 | * Frame window | |
486 | * | |
487 | */ | |
488 | ||
489 | bool wxFrame::OS2Create(int id, wxWindow *parent, const wxChar *wclass, wxWindow *wx_win, const wxChar *title, | |
490 | int x, int y, int width, int height, long style) | |
491 | ||
492 | { | |
493 | m_defaultIcon = (WXHICON) (wxSTD_FRAME_ICON ? wxSTD_FRAME_ICON : wxDEFAULT_FRAME_ICON); | |
494 | ||
495 | // If child windows aren't properly drawn initially, WS_CLIPCHILDREN | |
496 | // could be the culprit. But without it, you can get a lot of flicker. | |
29435d81 | 497 | |
21802234 DW |
498 | // TODO: |
499 | /* | |
500 | DWORD msflags = 0; | |
501 | if ((style & wxCAPTION) == wxCAPTION) | |
502 | msflags = WS_OVERLAPPED; | |
503 | else | |
504 | msflags = WS_POPUP; | |
505 | ||
506 | if (style & wxMINIMIZE_BOX) | |
507 | msflags |= WS_MINIMIZEBOX; | |
508 | if (style & wxMAXIMIZE_BOX) | |
509 | msflags |= WS_MAXIMIZEBOX; | |
510 | if (style & wxTHICK_FRAME) | |
511 | msflags |= WS_THICKFRAME; | |
512 | if (style & wxSYSTEM_MENU) | |
513 | msflags |= WS_SYSMENU; | |
514 | if ((style & wxMINIMIZE) || (style & wxICONIZE)) | |
515 | msflags |= WS_MINIMIZE; | |
516 | if (style & wxMAXIMIZE) | |
517 | msflags |= WS_MAXIMIZE; | |
518 | if (style & wxCAPTION) | |
519 | msflags |= WS_CAPTION; | |
520 | if (style & wxCLIP_CHILDREN) | |
521 | msflags |= WS_CLIPCHILDREN; | |
522 | ||
523 | // Keep this in wxFrame because it saves recoding this function | |
524 | // in wxTinyFrame | |
525 | #if wxUSE_ITSY_BITSY | |
526 | if (style & wxTINY_CAPTION_VERT) | |
527 | msflags |= IBS_VERTCAPTION; | |
528 | if (style & wxTINY_CAPTION_HORIZ) | |
529 | msflags |= IBS_HORZCAPTION; | |
530 | #else | |
531 | if (style & wxTINY_CAPTION_VERT) | |
532 | msflags |= WS_CAPTION; | |
533 | if (style & wxTINY_CAPTION_HORIZ) | |
534 | msflags |= WS_CAPTION; | |
535 | #endif | |
536 | if ((style & wxTHICK_FRAME) == 0) | |
537 | msflags |= WS_BORDER; | |
538 | ||
539 | WXDWORD extendedStyle = MakeExtendedStyle(style); | |
540 | ||
541 | #if !defined(__WIN16__) && !defined(__SC__) | |
542 | if (style & wxFRAME_TOOL_WINDOW) | |
543 | extendedStyle |= WS_EX_TOOLWINDOW; | |
544 | #endif | |
545 | ||
546 | if (style & wxSTAY_ON_TOP) | |
547 | extendedStyle |= WS_EX_TOPMOST; | |
548 | ||
549 | m_iconized = FALSE; | |
29435d81 | 550 | if ( !wxWindow::MSWCreate(id, parent, wclass, wx_win, title, x, y, width, height, |
21802234 DW |
551 | msflags, NULL, extendedStyle) ) |
552 | return FALSE; | |
553 | ||
554 | // Seems to be necessary if we use WS_POPUP | |
555 | // style instead of WS_OVERLAPPED | |
556 | if (width > -1 && height > -1) | |
557 | ::PostMessage(GetHwnd(), WM_SIZE, SIZE_RESTORED, MAKELPARAM(width, height)); | |
29435d81 | 558 | |
21802234 | 559 | return TRUE; |
29435d81 DW |
560 | */ |
561 | return FALSE; | |
21802234 DW |
562 | } |
563 | ||
564 | // Default resizing behaviour - if only ONE subwindow, resize to client | |
565 | // rectangle size | |
0e320a79 DW |
566 | void wxFrame::OnSize(wxSizeEvent& event) |
567 | { | |
21802234 DW |
568 | // if we're using constraints - do use them |
569 | #if wxUSE_CONSTRAINTS | |
570 | if ( GetAutoLayout() ) | |
571 | { | |
572 | Layout(); | |
573 | return; | |
0e320a79 | 574 | } |
21802234 | 575 | #endif |
0e320a79 | 576 | |
21802234 DW |
577 | // do we have _exactly_ one child? |
578 | wxWindow *child = NULL; | |
579 | for ( wxWindowList::Node *node = GetChildren().GetFirst(); | |
580 | node; | |
581 | node = node->GetNext() ) | |
0e320a79 | 582 | { |
21802234 DW |
583 | wxWindow *win = node->GetData(); |
584 | if ( !win->IsTopLevel() | |
585 | #if wxUSE_STATUSBAR | |
586 | && (win != GetStatusBar()) | |
587 | #endif // wxUSE_STATUSBAR | |
588 | #if wxUSE_TOOLBAR | |
589 | && (win != GetToolBar()) | |
590 | #endif // wxUSE_TOOLBAR | |
591 | ) | |
592 | { | |
593 | if ( child ) | |
594 | return; // it's our second subwindow - nothing to do | |
595 | child = win; | |
596 | } | |
0e320a79 | 597 | } |
0e320a79 | 598 | |
21802234 DW |
599 | if ( child ) { |
600 | // we have exactly one child - set it's size to fill the whole frame | |
601 | int clientW, clientH; | |
602 | GetClientSize(&clientW, &clientH); | |
0e320a79 | 603 | |
21802234 DW |
604 | int x = 0; |
605 | int y = 0; | |
0e320a79 | 606 | |
21802234 DW |
607 | child->SetSize(x, y, clientW, clientH); |
608 | } | |
0e320a79 DW |
609 | } |
610 | ||
611 | // Default activation behaviour - set the focus for the first child | |
612 | // subwindow found. | |
613 | void wxFrame::OnActivate(wxActivateEvent& event) | |
614 | { | |
21802234 DW |
615 | for ( wxWindowList::Node *node = GetChildren().GetFirst(); |
616 | node; | |
617 | node = node->GetNext() ) | |
0e320a79 | 618 | { |
21802234 DW |
619 | // FIXME all this is totally bogus - we need to do the same as wxPanel, |
620 | // but how to do it without duplicating the code? | |
621 | ||
622 | // restore focus | |
623 | wxWindow *child = node->GetData(); | |
624 | ||
625 | if ( !child->IsTopLevel() | |
626 | #if wxUSE_TOOLBAR | |
627 | && !wxDynamicCast(child, wxToolBar) | |
628 | #endif // wxUSE_TOOLBAR | |
629 | #if wxUSE_STATUSBAR | |
630 | && !wxDynamicCast(child, wxStatusBar) | |
631 | #endif // wxUSE_STATUSBAR | |
632 | ) | |
633 | { | |
634 | child->SetFocus(); | |
635 | return; | |
636 | } | |
0e320a79 | 637 | } |
0e320a79 DW |
638 | } |
639 | ||
640 | // The default implementation for the close window event. | |
0e320a79 DW |
641 | void wxFrame::OnCloseWindow(wxCloseEvent& event) |
642 | { | |
21802234 | 643 | Destroy(); |
0e320a79 DW |
644 | } |
645 | ||
646 | // Destroy the window (delayed, if a managed window) | |
647 | bool wxFrame::Destroy() | |
648 | { | |
649 | if (!wxPendingDelete.Member(this)) | |
650 | wxPendingDelete.Append(this); | |
651 | return TRUE; | |
652 | } | |
653 | ||
654 | // Default menu selection behaviour - display a help string | |
655 | void wxFrame::OnMenuHighlight(wxMenuEvent& event) | |
656 | { | |
657 | if (GetStatusBar()) | |
658 | { | |
21802234 DW |
659 | wxString help; |
660 | int menuId = event.GetMenuId(); | |
661 | if ( menuId != -1 ) | |
0e320a79 DW |
662 | { |
663 | wxMenuBar *menuBar = GetMenuBar(); | |
21802234 | 664 | if (menuBar && menuBar->FindItem(menuId)) |
0e320a79 | 665 | { |
21802234 | 666 | help = menuBar->GetHelpString(menuId); |
0e320a79 DW |
667 | } |
668 | } | |
21802234 DW |
669 | |
670 | // set status text even if the string is empty - this will at | |
671 | // least remove the string from the item which was previously | |
672 | // selected | |
673 | SetStatusText(help); | |
0e320a79 DW |
674 | } |
675 | } | |
676 | ||
677 | wxMenuBar *wxFrame::GetMenuBar() const | |
678 | { | |
679 | return m_frameMenuBar; | |
680 | } | |
681 | ||
21802234 | 682 | bool wxFrame::ProcessCommand(int id) |
0e320a79 | 683 | { |
21802234 DW |
684 | wxMenuBar *bar = GetMenuBar() ; |
685 | if ( !bar ) | |
686 | return FALSE; | |
0e320a79 | 687 | |
476607a7 | 688 | wxMenuItem *item = bar->FindItem(id); |
0e320a79 | 689 | |
21802234 DW |
690 | if ( item && item->IsCheckable() ) |
691 | { | |
692 | bar->Check(id, !bar->IsChecked(id)) ; | |
693 | } | |
0e320a79 | 694 | |
21802234 DW |
695 | wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, id); |
696 | commandEvent.SetInt( id ); | |
697 | commandEvent.SetEventObject( this ); | |
0e320a79 | 698 | |
21802234 | 699 | return GetEventHandler()->ProcessEvent(commandEvent); |
0e320a79 DW |
700 | } |
701 | ||
702 | // Checks if there is a toolbar, and returns the first free client position | |
703 | wxPoint wxFrame::GetClientAreaOrigin() const | |
704 | { | |
705 | wxPoint pt(0, 0); | |
706 | if (GetToolBar()) | |
707 | { | |
708 | int w, h; | |
709 | GetToolBar()->GetSize(& w, & h); | |
710 | ||
711 | if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL) | |
712 | { | |
713 | pt.x += w; | |
714 | } | |
715 | else | |
716 | { | |
717 | pt.y += h; | |
718 | } | |
719 | } | |
720 | return pt; | |
721 | } | |
722 | ||
e6ebb514 | 723 | void wxFrame::DoScreenToClient(int *x, int *y) const |
0e320a79 | 724 | { |
29435d81 | 725 | wxWindow::DoScreenToClient(x, y); |
0e320a79 DW |
726 | |
727 | // We may be faking the client origin. | |
728 | // So a window that's really at (0, 30) may appear | |
729 | // (to wxWin apps) to be at (0, 0). | |
730 | wxPoint pt(GetClientAreaOrigin()); | |
731 | *x -= pt.x; | |
732 | *y -= pt.y; | |
733 | } | |
734 | ||
e6ebb514 | 735 | void wxFrame::DoClientToScreen(int *x, int *y) const |
0e320a79 DW |
736 | { |
737 | // We may be faking the client origin. | |
738 | // So a window that's really at (0, 30) may appear | |
739 | // (to wxWin apps) to be at (0, 0). | |
740 | wxPoint pt1(GetClientAreaOrigin()); | |
741 | *x += pt1.x; | |
742 | *y += pt1.y; | |
743 | ||
e6ebb514 | 744 | wxWindow::DoClientToScreen(x, y); |
0e320a79 DW |
745 | } |
746 | ||
21802234 | 747 | #if wxUSE_TOOLBAR |
0e320a79 DW |
748 | wxToolBar* wxFrame::CreateToolBar(long style, wxWindowID id, const wxString& name) |
749 | { | |
750 | wxCHECK_MSG( m_frameToolBar == NULL, FALSE, | |
223d09f6 | 751 | wxT("recreating toolbar in wxFrame") ); |
0e320a79 DW |
752 | |
753 | wxToolBar* toolBar = OnCreateToolBar(style, id, name); | |
754 | if (toolBar) | |
755 | { | |
756 | SetToolBar(toolBar); | |
757 | PositionToolBar(); | |
758 | return toolBar; | |
759 | } | |
760 | else | |
761 | { | |
762 | return NULL; | |
763 | } | |
764 | } | |
765 | ||
766 | wxToolBar* wxFrame::OnCreateToolBar(long style, wxWindowID id, const wxString& name) | |
767 | { | |
768 | return new wxToolBar(this, id, wxDefaultPosition, wxDefaultSize, style, name); | |
769 | } | |
770 | ||
771 | void wxFrame::PositionToolBar() | |
772 | { | |
29435d81 DW |
773 | // TODO: |
774 | /* | |
21802234 | 775 | RECT rect; |
29435d81 | 776 | ::GetClientRect(GetHwnd(), &rect); |
0e320a79 DW |
777 | |
778 | if ( GetStatusBar() ) | |
779 | { | |
780 | int statusX, statusY; | |
781 | GetStatusBar()->GetClientSize(&statusX, &statusY); | |
29435d81 | 782 | rect.bottom -= statusY; |
0e320a79 DW |
783 | } |
784 | ||
785 | if (GetToolBar()) | |
786 | { | |
787 | int tw, th; | |
788 | GetToolBar()->GetSize(& tw, & th); | |
789 | ||
790 | if (GetToolBar()->GetWindowStyleFlag() & wxTB_VERTICAL) | |
791 | { | |
21802234 | 792 | // Use the 'real' MSW position |
29435d81 | 793 | GetToolBar()->SetSize(0, 0, tw, rect.bottom, wxSIZE_NO_ADJUSTMENTS); |
0e320a79 DW |
794 | } |
795 | else | |
796 | { | |
21802234 | 797 | // Use the 'real' MSW position |
29435d81 | 798 | GetToolBar()->SetSize(0, 0, rect.right, th, wxSIZE_NO_ADJUSTMENTS); |
21802234 DW |
799 | } |
800 | } | |
29435d81 | 801 | */ |
21802234 DW |
802 | } |
803 | #endif // wxUSE_TOOLBAR | |
804 | ||
805 | // propagate our state change to all child frames: this allows us to emulate X | |
806 | // Windows behaviour where child frames float independently of the parent one | |
807 | // on the desktop, but are iconized/restored with it | |
808 | void wxFrame::IconizeChildFrames(bool bIconize) | |
809 | { | |
810 | for ( wxWindowList::Node *node = GetChildren().GetFirst(); | |
811 | node; | |
812 | node = node->GetNext() ) | |
813 | { | |
814 | wxWindow *win = node->GetData(); | |
815 | ||
816 | if ( win->IsKindOf(CLASSINFO(wxFrame)) ) | |
817 | { | |
818 | ((wxFrame *)win)->Iconize(bIconize); | |
0e320a79 DW |
819 | } |
820 | } | |
821 | } | |
822 | ||
21802234 DW |
823 | |
824 | // make the window modal (all other windows unresponsive) | |
825 | void wxFrame::MakeModal(bool modal) | |
826 | { | |
827 | if (modal) { | |
828 | wxEnableTopLevelWindows(FALSE); | |
829 | Enable(TRUE); // keep this window enabled | |
830 | } | |
831 | else { | |
832 | wxEnableTopLevelWindows(TRUE); | |
833 | } | |
834 | } | |
835 | ||
836 | ||
837 | // =========================================================================== | |
838 | // message processing | |
839 | // =========================================================================== | |
840 | ||
841 | // --------------------------------------------------------------------------- | |
842 | // preprocessing | |
843 | // --------------------------------------------------------------------------- | |
844 | ||
845 | bool wxFrame::OS2TranslateMessage(WXMSG* pMsg) | |
846 | { | |
29435d81 DW |
847 | if ( wxWindow::OS2TranslateMessage(pMsg) ) |
848 | return TRUE; | |
21802234 DW |
849 | |
850 | // try the menu bar accels | |
851 | wxMenuBar *menuBar = GetMenuBar(); | |
852 | if ( !menuBar ) | |
853 | return FALSE; | |
854 | ||
29435d81 DW |
855 | const wxAcceleratorTable& acceleratorTable = menuBar->GetAccelTable(); |
856 | return acceleratorTable.Translate(this, pMsg); | |
21802234 DW |
857 | } |
858 | ||
859 | // --------------------------------------------------------------------------- | |
860 | // our private (non virtual) message handlers | |
861 | // --------------------------------------------------------------------------- | |
862 | ||
863 | bool wxFrame::HandlePaint() | |
864 | { | |
21802234 | 865 | // TODO: |
29435d81 DW |
866 | /* |
867 | RECT rect; | |
868 | if ( GetUpdateRect(GetHwnd(), &rect, FALSE) ) | |
869 | { | |
870 | if ( m_iconized ) | |
871 | { | |
872 | HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon) | |
873 | : (HICON)m_defaultIcon; | |
874 | ||
21802234 DW |
875 | // Hold a pointer to the dc so long as the OnPaint() message |
876 | // is being processed | |
29435d81 DW |
877 | PAINTSTRUCT ps; |
878 | HDC hdc = ::BeginPaint(GetHwnd(), &ps); | |
879 | ||
880 | // Erase background before painting or we get white background | |
881 | MSWDefWindowProc(WM_ICONERASEBKGND, (WORD)(LONG)ps.hdc, 0L); | |
882 | ||
883 | if ( hIcon ) | |
884 | { | |
885 | RECT rect; | |
886 | ::GetClientRect(GetHwnd(), &rect); | |
21802234 DW |
887 | |
888 | // FIXME: why hardcoded? | |
29435d81 DW |
889 | static const int icon_width = 32; |
890 | static const int icon_height = 32; | |
891 | ||
892 | int icon_x = (int)((rect.right - icon_width)/2); | |
893 | int icon_y = (int)((rect.bottom - icon_height)/2); | |
894 | ||
895 | ::DrawIcon(hdc, icon_x, icon_y, hIcon); | |
896 | } | |
897 | ||
898 | ::EndPaint(GetHwnd(), &ps); | |
899 | ||
900 | return TRUE; | |
901 | } | |
902 | else | |
903 | { | |
904 | return wxWindow::HandlePaint(); | |
905 | } | |
906 | } | |
907 | else | |
908 | { | |
909 | // nothing to paint - processed | |
910 | return TRUE; | |
911 | } | |
912 | */ | |
913 | return FALSE; | |
21802234 DW |
914 | } |
915 | ||
916 | bool wxFrame::HandleSize(int x, int y, WXUINT id) | |
917 | { | |
918 | bool processed = FALSE; | |
919 | ||
29435d81 DW |
920 | // TODO: |
921 | /* | |
922 | switch ( id ) | |
21802234 DW |
923 | { |
924 | case SIZENORMAL: | |
925 | // only do it it if we were iconized before, otherwise resizing the | |
926 | // parent frame has a curious side effect of bringing it under it's | |
927 | // children | |
928 | if ( !m_iconized ) | |
929 | break; | |
930 | ||
931 | // restore all child frames too | |
932 | IconizeChildFrames(FALSE); | |
933 | ||
934 | // fall through | |
935 | ||
936 | case SIZEFULLSCREEN: | |
937 | m_iconized = FALSE; | |
938 | break; | |
939 | ||
940 | case SIZEICONIC: | |
941 | // iconize all child frames too | |
942 | IconizeChildFrames(TRUE); | |
943 | ||
944 | m_iconized = TRUE; | |
945 | break; | |
946 | } | |
947 | */ | |
948 | if ( !m_iconized ) | |
949 | { | |
29435d81 | 950 | // forward WM_SIZE to status bar control |
21802234 DW |
951 | PositionStatusBar(); |
952 | PositionToolBar(); | |
953 | ||
954 | wxSizeEvent event(wxSize(x, y), m_windowId); | |
955 | event.SetEventObject( this ); | |
956 | processed = GetEventHandler()->ProcessEvent(event); | |
957 | } | |
958 | ||
959 | return processed; | |
960 | } | |
961 | ||
962 | bool wxFrame::HandleCommand(WXWORD id, WXWORD cmd, WXHWND control) | |
963 | { | |
964 | if ( control ) | |
965 | { | |
966 | // In case it's e.g. a toolbar. | |
967 | wxWindow *win = wxFindWinFromHandle(control); | |
968 | if ( win ) | |
29435d81 | 969 | return win->OS2Command(cmd, id); |
21802234 DW |
970 | } |
971 | ||
972 | // handle here commands from menus and accelerators | |
973 | if ( cmd == 0 || cmd == 1 ) | |
974 | { | |
975 | if ( wxCurrentPopupMenu ) | |
976 | { | |
977 | wxMenu *popupMenu = wxCurrentPopupMenu; | |
978 | wxCurrentPopupMenu = NULL; | |
979 | ||
29435d81 | 980 | return popupMenu->OS2Command(cmd, id); |
21802234 DW |
981 | } |
982 | ||
983 | if ( ProcessCommand(id) ) | |
984 | { | |
985 | return TRUE; | |
986 | } | |
987 | } | |
988 | ||
989 | return FALSE; | |
990 | } | |
991 | ||
992 | bool wxFrame::HandleMenuSelect(WXWORD nItem, WXWORD flags, WXHMENU hMenu) | |
993 | { | |
994 | int item; | |
995 | if ( flags == 0xFFFF && hMenu == 0 ) | |
996 | { | |
997 | // menu was removed from screen | |
998 | item = -1; | |
999 | } | |
29435d81 | 1000 | // TODO: |
21802234 DW |
1001 | /* |
1002 | else if ( !(flags & MF_POPUP) && !(flags & MF_SEPARATOR) ) | |
1003 | { | |
1004 | item = nItem; | |
1005 | } | |
1006 | */ | |
1007 | else | |
1008 | { | |
1009 | // don't give hints for separators (doesn't make sense) nor for the | |
1010 | // items opening popup menus (they don't have them anyhow) | |
1011 | return FALSE; | |
1012 | } | |
1013 | ||
1014 | wxMenuEvent event(wxEVT_MENU_HIGHLIGHT, item); | |
1015 | event.SetEventObject( this ); | |
1016 | ||
1017 | return GetEventHandler()->ProcessEvent(event); | |
1018 | } | |
1019 | ||
1020 | // --------------------------------------------------------------------------- | |
1021 | // the window proc for wxFrame | |
1022 | // --------------------------------------------------------------------------- | |
1023 | ||
1024 | MRESULT wxFrame::OS2WindowProc(HWND hwnd, WXUINT message, WXWPARAM wParam, WXLPARAM lParam) | |
1025 | { | |
1026 | MRESULT rc = 0; | |
1027 | bool processed = FALSE; | |
1028 | ||
1029 | // TODO: | |
1030 | /* | |
1031 | switch ( message ) | |
1032 | { | |
1033 | case WM_CLOSE: | |
1034 | // if we can't close, tell the system that we processed the | |
1035 | // message - otherwise it would close us | |
1036 | processed = !Close(); | |
1037 | break; | |
1038 | ||
1039 | case WM_COMMAND: | |
1040 | { | |
1041 | WORD id, cmd; | |
1042 | WXHWND hwnd; | |
1043 | UnpackCommand((WXWPARAM)wParam, (WXLPARAM)lParam, | |
1044 | &id, &hwnd, &cmd); | |
1045 | ||
1046 | processed = HandleCommand(id, cmd, (WXHWND)hwnd); | |
1047 | } | |
1048 | break; | |
1049 | ||
1050 | case WM_MENUSELECT: | |
1051 | { | |
1052 | WXWORD item, flags; | |
1053 | WXHMENU hmenu; | |
1054 | UnpackMenuSelect(wParam, lParam, &item, &flags, &hmenu); | |
1055 | ||
1056 | processed = HandleMenuSelect(item, flags, hmenu); | |
1057 | } | |
1058 | break; | |
1059 | ||
1060 | case WM_PAINT: | |
1061 | processed = HandlePaint(); | |
1062 | break; | |
1063 | ||
1064 | case WM_QUERYDRAGICON: | |
1065 | { | |
1066 | HICON hIcon = m_icon.Ok() ? GetHiconOf(m_icon) | |
1067 | : (HICON)(m_defaultIcon); | |
1068 | rc = (long)hIcon; | |
1069 | processed = rc != 0; | |
1070 | } | |
1071 | break; | |
1072 | ||
1073 | case WM_SIZE: | |
1074 | processed = HandleSize(LOWORD(lParam), HIWORD(lParam), wParam); | |
1075 | break; | |
1076 | } | |
1077 | */ | |
1078 | if ( !processed ) | |
1079 | rc = wxWindow::OS2WindowProc(hwnd, message, wParam, lParam); | |
1080 | ||
1081 | return rc; | |
1082 | } | |
1083 |