cfbce1db79f9bbe79810fed5cb3fcadc284e38e4
[reactos.git] / base / shell / explorer / utility / window.cpp
1 /*
2 * Copyright 2003, 2004, 2005 Martin Fuchs
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19
20 //
21 // Explorer clone
22 //
23 // window.cpp
24 //
25 // Martin Fuchs, 23.07.2003
26 //
27
28
29 #include <precomp.h>
30
31 #include "../resource.h" // for ID_GO_BACK, ...
32
33
34 WindowClass::WindowClass(LPCTSTR classname, UINT style_, WNDPROC wndproc)
35 {
36 memset(this, 0, sizeof(WNDCLASSEX));
37
38 cbSize = sizeof(WNDCLASSEX);
39 style = style_;
40 hInstance = g_Globals._hInstance;
41 hCursor = LoadCursor(0, IDC_ARROW);
42
43 lpszClassName = classname;
44 lpfnWndProc = wndproc;
45
46 _atomClass = 0;
47 }
48
49
50 IconWindowClass::IconWindowClass(LPCTSTR classname, UINT nid, UINT style, WNDPROC wndproc)
51 : WindowClass(classname, style, wndproc)
52 {
53 hIcon = ResIcon(nid);
54 hIconSm = SmallIcon(nid);
55 }
56
57
58 Window::WindowMap Window::s_wnd_map;
59
60 Window::CREATORFUNC Window::s_window_creator = NULL;
61 const void* Window::s_new_info = NULL;
62
63 HHOOK Window::s_hcbtHook = 0;
64
65
66 Window::StaticWindowData& Window::GetStaticWindowData()
67 {
68 static StaticWindowData s_initialized_data;
69
70 return s_initialized_data;
71 }
72
73
74 Window::Window(HWND hwnd)
75 : WindowHandle(hwnd)
76 {
77 Lock lock(GetStaticWindowData()._map_crit_sect); // protect access to s_wnd_map
78
79 s_wnd_map[_hwnd] = this;
80 }
81
82 Window::~Window()
83 {
84 Lock lock(GetStaticWindowData()._map_crit_sect); // protect access to s_wnd_map
85
86 s_wnd_map.erase(_hwnd);
87 }
88
89
90 HWND Window::Create(CREATORFUNC creator, DWORD dwExStyle,
91 LPCTSTR lpClassName, LPCTSTR lpWindowName,
92 DWORD dwStyle, int x, int y, int w, int h,
93 HWND hwndParent, HMENU hMenu/*, LPVOID lpParam*/)
94 {
95 Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
96
97 s_window_creator = creator;
98 s_new_info = NULL;
99
100 return CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle,
101 x, y, w, h,
102 hwndParent, hMenu, g_Globals._hInstance, 0/*lpParam*/);
103 }
104
105 HWND Window::Create(CREATORFUNC_INFO creator, const void* info, DWORD dwExStyle,
106 LPCTSTR lpClassName, LPCTSTR lpWindowName,
107 DWORD dwStyle, int x, int y, int w, int h,
108 HWND hwndParent, HMENU hMenu/*, LPVOID lpParam*/)
109 {
110 Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
111
112 s_window_creator = (CREATORFUNC) creator;
113 s_new_info = info;
114
115 return CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle,
116 x, y, w, h,
117 hwndParent, hMenu, g_Globals._hInstance, 0/*lpParam*/);
118 }
119
120
121 Window* Window::create_mdi_child(const ChildWndInfo& info, const MDICREATESTRUCT& mcs, CREATORFUNC_INFO creator)
122 {
123 Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
124
125 s_window_creator = (CREATORFUNC) creator;
126 s_new_info = &info;
127
128 s_hcbtHook = SetWindowsHookEx(WH_CBT, MDICBTHookProc, 0, GetCurrentThreadId());
129
130 HWND hwnd = (HWND) SendMessage(info._hmdiclient, WM_MDICREATE, 0, (LPARAM)&mcs);
131
132 // end hook in case it's not already done
133 if (s_hcbtHook)
134 UnhookWindowsHookEx(s_hcbtHook);
135
136 Window* child = get_window(hwnd);
137 s_new_info = NULL;
138
139 if (child && (!hwnd || !child->_hwnd))
140 child = NULL;
141
142 return child;
143 }
144
145 LRESULT CALLBACK Window::MDICBTHookProc(int code, WPARAM wparam, LPARAM lparam)
146 {
147 if (code == HCBT_CREATEWND) {
148 UnhookWindowsHookEx(s_hcbtHook); // use the hook only for the first created window
149 s_hcbtHook = 0;
150
151 HWND hwnd = (HWND)wparam;
152
153 // create Window controller and associate it with the window handle
154 Window* child = get_window(hwnd);
155
156 if (!child)
157 child = create_controller(hwnd);
158 }
159
160 return CallNextHookEx(s_hcbtHook, code, wparam, lparam);
161 }
162
163
164 /*
165 Window* Window::create_property_sheet(PropertySheetDialog* ppsd, CREATORFUNC creator, const void* info)
166 {
167 Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
168
169 s_window_creator = creator;
170 s_new_info = info;
171
172 s_hcbtHook = SetWindowsHookEx(WH_CBT, PropSheetCBTHookProc, 0, GetCurrentThreadId());
173
174 HWND hwnd = (HWND) PropertySheet(ppsd);
175
176 UnhookWindowsHookEx(s_hcbtHook);
177
178 Window* child = get_window(hwnd);
179 s_new_info = NULL;
180
181 if (child && (!hwnd || !child->_hwnd))
182 child = NULL;
183
184 return child;
185 }
186 */
187
188 LRESULT CALLBACK Window::PropSheetCBTHookProc(int code, WPARAM wparam, LPARAM lparam)
189 {
190 if (code == HCBT_CREATEWND) {
191 HWND hwnd = (HWND)wparam;
192
193 // create Window controller and associate it with the window handle
194 Window* child = get_window(hwnd);
195
196 if (!child)
197 child = create_controller(hwnd);
198 }
199
200 return CallNextHookEx(s_hcbtHook, code, wparam, lparam);
201 }
202
203
204 /// get window controller from window handle
205
206 Window* Window::get_window(HWND hwnd)
207 {
208 {
209 Lock lock(GetStaticWindowData()._map_crit_sect); // protect access to s_wnd_map
210
211 WindowMap::const_iterator found = s_wnd_map.find(hwnd);
212
213 if (found!=s_wnd_map.end())
214 return found->second;
215 }
216
217 return NULL;
218 }
219
220
221 /// create controller for a new window
222
223 Window* Window::create_controller(HWND hwnd)
224 {
225 if (s_window_creator) { // protect for recursion and create the window object only for the first window
226 Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
227
228 const void* info = s_new_info;
229 s_new_info = NULL;
230
231 CREATORFUNC window_creator = s_window_creator;
232 s_window_creator = NULL;
233
234 if (info)
235 return CREATORFUNC_INFO(window_creator)(hwnd, info);
236 else
237 return CREATORFUNC(window_creator)(hwnd);
238 }
239
240 return NULL;
241 }
242
243
244 LRESULT Window::Init(LPCREATESTRUCT pcs)
245 {
246 return 0;
247 }
248
249
250 LRESULT CALLBACK Window::WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
251 {
252 Window* pThis = get_window(hwnd);
253
254 if (!pThis)
255 pThis = create_controller(hwnd);
256
257 if (pThis) {
258 switch(nmsg) {
259 case WM_COMMAND:
260 return pThis->Command(LOWORD(wparam), HIWORD(wparam));
261
262 case WM_NOTIFY:
263 return pThis->Notify(wparam, (NMHDR*)lparam);
264
265 case WM_NOTIFYFORMAT:
266 return NFR_CURRENT;
267
268 case WM_CREATE:
269 return pThis->Init((LPCREATESTRUCT)lparam);
270
271 case WM_NCDESTROY:
272 delete pThis;
273 return 0;
274
275 default:
276 return pThis->WndProc(nmsg, wparam, lparam);
277 }
278 }
279 else
280 return DefWindowProc(hwnd, nmsg, wparam, lparam);
281 }
282
283 LRESULT Window::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
284 {
285 return DefWindowProc(_hwnd, nmsg, wparam, lparam);
286 }
287
288 int Window::Command(int id, int code)
289 {
290 return 1; // no command handler found
291 }
292
293 int Window::Notify(int id, NMHDR* pnmh)
294 {
295 return 0;
296 }
297
298 void Window::CancelModes()
299 {
300 PostMessage(HWND_BROADCAST, WM_CANCELMODE, 0, 0);
301 }
302
303
304 SubclassedWindow::SubclassedWindow(HWND hwnd)
305 : super(hwnd)
306 {
307 _orgWndProc = SubclassWindow(_hwnd, SubclassedWndProc);
308
309 if (!_orgWndProc)
310 delete this;
311 }
312
313 LRESULT CALLBACK SubclassedWindow::SubclassedWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
314 {
315 SubclassedWindow* pThis = GET_WINDOW(SubclassedWindow, hwnd);
316 assert(pThis);
317
318 if (pThis) {
319 switch(nmsg) {
320 case WM_COMMAND:
321 if (!pThis->Command(LOWORD(wparam), HIWORD(wparam)))
322 return 0;
323 break;
324
325 case WM_NOTIFY:
326 return pThis->Notify(wparam, (NMHDR*)lparam);
327
328 case WM_NOTIFYFORMAT:
329 return NFR_CURRENT;
330
331 case WM_CREATE:
332 return pThis->Init((LPCREATESTRUCT)lparam);
333
334 case WM_NCDESTROY:
335 delete pThis;
336 return 0;
337
338 default:
339 return pThis->WndProc(nmsg, wparam, lparam);
340 }
341 }
342
343 return CallWindowProc(pThis->_orgWndProc, hwnd, nmsg, wparam, lparam);
344 }
345
346 LRESULT SubclassedWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
347 {
348 return CallWindowProc(_orgWndProc, _hwnd, nmsg, wparam, lparam);
349 }
350
351 int SubclassedWindow::Command(int id, int code)
352 {
353 return 1; // no command handler found
354 }
355
356 int SubclassedWindow::Notify(int id, NMHDR* pnmh)
357 {
358 return CallWindowProc(_orgWndProc, _hwnd, WM_NOTIFY, id, (LPARAM)pnmh);
359 }
360
361
362 ChildWindow::ChildWindow(HWND hwnd, const ChildWndInfo& info)
363 : super(hwnd),
364 _hwndFrame(GetParent(info._hmdiclient))
365 {
366 _focus_pane = 0;
367 _split_pos = DEFAULT_SPLIT_POS;
368 _last_split = DEFAULT_SPLIT_POS;
369 }
370
371
372 ChildWindow* ChildWindow::create(const ChildWndInfo& info, const RECT& rect, CREATORFUNC_INFO creator,
373 LPCTSTR classname, LPCTSTR title, DWORD style)
374 {
375 MDICREATESTRUCT mcs;
376
377 mcs.szClass = classname;
378 mcs.szTitle = title;
379 mcs.hOwner = g_Globals._hInstance;
380 mcs.x = rect.left,
381 mcs.y = rect.top;
382 mcs.cx = rect.right - rect.left;
383 mcs.cy = rect.bottom - rect.top;
384 mcs.style = style;
385 mcs.lParam = 0;
386
387 return static_cast<ChildWindow*>(create_mdi_child(info, mcs, creator));
388 }
389
390
391 LRESULT ChildWindow::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
392 {
393 switch(nmsg) {
394 case WM_PAINT: {
395 RECT rc;
396 PaintCanvas canvas(_hwnd);
397 ClientRect rt(_hwnd);
398 rt.left = _split_pos-SPLIT_WIDTH/2;
399 rt.right = _split_pos+SPLIT_WIDTH/2+1;
400 HBRUSH lastBrush = SelectBrush(canvas, GetStockBrush(COLOR_SPLITBAR));
401 Rectangle(canvas, rt.left, rt.top-1, rt.right, rt.bottom+1);
402 SetRect(&rc, rt.left, rt.top-1, rt.right, rt.bottom+1);
403 DrawEdge(canvas, &rc, EDGE_RAISED, BF_RECT);
404 SelectObject(canvas, lastBrush);
405 break;}
406
407 case WM_SETCURSOR:
408 if (LOWORD(lparam) == HTCLIENT) {
409 POINT pt;
410 GetCursorPos(&pt);
411 ScreenToClient(_hwnd, &pt);
412
413 if (pt.x>=_split_pos-SPLIT_WIDTH/2 && pt.x<_split_pos+SPLIT_WIDTH/2+1) {
414 SetCursor(LoadCursor(0, IDC_SIZEWE));
415 return TRUE;
416 }
417 }
418 goto def;
419
420 case WM_SIZE:
421 if (wparam != SIZE_MINIMIZED)
422 resize_children(LOWORD(lparam), HIWORD(lparam));
423 goto def;
424
425 case WM_GETMINMAXINFO:
426 DefMDIChildProc(_hwnd, nmsg, wparam, lparam);
427
428 {LPMINMAXINFO lpmmi = (LPMINMAXINFO)lparam;
429
430 lpmmi->ptMaxTrackSize.x <<= 1; // 2*GetSystemMetrics(SM_CXSCREEN) / SM_CXVIRTUALSCREEN
431 lpmmi->ptMaxTrackSize.y <<= 1; // 2*GetSystemMetrics(SM_CYSCREEN) / SM_CYVIRTUALSCREEN
432 break;}
433
434 case WM_LBUTTONDOWN: {
435 int x = GET_X_LPARAM(lparam);
436
437 ClientRect rt(_hwnd);
438
439 if (x>=_split_pos-SPLIT_WIDTH/2 && x<_split_pos+SPLIT_WIDTH/2+1) {
440 _last_split = _split_pos;
441 SetCapture(_hwnd);
442 }
443
444 break;}
445
446 case WM_LBUTTONUP:
447 if (GetCapture() == _hwnd)
448 ReleaseCapture();
449 break;
450
451 case WM_KEYDOWN:
452 if (wparam == VK_ESCAPE)
453 if (GetCapture() == _hwnd) {
454 _split_pos = _last_split;
455 ClientRect rt(_hwnd);
456 resize_children(rt.right, rt.bottom);
457 _last_split = -1;
458 ReleaseCapture();
459 SetCursor(LoadCursor(0, IDC_ARROW));
460 }
461 break;
462
463 case WM_MOUSEMOVE:
464 if (GetCapture() == _hwnd) {
465 int x = GET_X_LPARAM(lparam);
466
467 ClientRect rt(_hwnd);
468
469 if (x>=0 && x<rt.right) {
470 _split_pos = x;
471 resize_children(rt.right, rt.bottom);
472 rt.left = x-SPLIT_WIDTH/2;
473 rt.right = x+SPLIT_WIDTH/2+1;
474 InvalidateRect(_hwnd, &rt, FALSE);
475 UpdateWindow(_left_hwnd);
476 UpdateWindow(_hwnd);
477 UpdateWindow(_right_hwnd);
478 }
479 }
480 break;
481
482 case PM_DISPATCH_COMMAND:
483 switch(LOWORD(wparam)) {
484 case ID_GO_BACK:
485 if (!_url_history.empty()) {
486 const String& url = jump_to_int(_url_history.top());
487
488 if (jump_to_int(url))
489 set_url(url);
490
491 _url_history.pop();
492 }
493 break;
494
495 case ID_GO_FORWARD:
496 //@@
497 break;
498
499 case ID_GO_UP:
500 ///@todo
501 break;
502
503 case ID_GO_HOME:
504 //@@
505 break;
506
507 default:
508 return FALSE;
509 }
510 return TRUE;
511
512 case WM_MDIACTIVATE:
513 if ((HWND)lparam == _hwnd) {
514 SendMessage(_hwndFrame, PM_SETSTATUSTEXT, 0, (LPARAM)_statusText.c_str());
515 SendMessage(_hwndFrame, PM_URL_CHANGED, 0, (LPARAM)_url.c_str());
516 }
517 break;
518
519 case PM_JUMP_TO_URL:
520 return go_to((LPCTSTR)lparam)? TRUE: FALSE;
521
522 default: def:
523 return DefMDIChildProc(_hwnd, nmsg, wparam, lparam);
524 }
525
526 return 0;
527 }
528
529
530 void ChildWindow::resize_children(int cx, int cy)
531 {
532 HDWP hdwp = BeginDeferWindowPos(2);
533 RECT rt;
534
535 rt.left = 0;
536 rt.top = 0;
537 rt.right = cx;
538 rt.bottom = cy;
539
540 if (_left_hwnd) {
541 cx = _split_pos + SPLIT_WIDTH/2;
542
543 hdwp = DeferWindowPos(hdwp, _left_hwnd, 0, rt.left, rt.top, _split_pos-SPLIT_WIDTH/2-rt.left, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
544 } else {
545 _split_pos = 0;
546 cx = 0;
547 }
548
549 if (_right_hwnd)
550 hdwp = DeferWindowPos(hdwp, _right_hwnd, 0, rt.left+cx+1, rt.top, rt.right-cx, rt.bottom-rt.top, SWP_NOZORDER|SWP_NOACTIVATE);
551
552 EndDeferWindowPos(hdwp);
553 }
554
555
556 bool ChildWindow::go_to(LPCTSTR url)
557 {
558 const String& url_str = jump_to_int(url);
559
560 if (!url_str.empty()) {
561 set_url(url_str);
562
563 _url_history.push(url_str);
564
565 return true;
566 } else
567 return false;
568 }
569
570 void ChildWindow::set_url(LPCTSTR url)
571 {
572 if (_url != url) {
573 _url = url;
574
575 SendMessage(_hwndFrame, PM_URL_CHANGED, 0, (LPARAM)url);
576 }
577 }
578
579
580 WindowSet Window::s_pretranslate_windows;
581
582 void Window::register_pretranslate(HWND hwnd)
583 {
584 s_pretranslate_windows.insert(hwnd);
585 }
586
587 void Window::unregister_pretranslate(HWND hwnd)
588 {
589 s_pretranslate_windows.erase(hwnd);
590 }
591
592 BOOL Window::pretranslate_msg(LPMSG pmsg)
593 {
594 for(WindowSet::const_iterator it=Window::s_pretranslate_windows.begin(); it!=s_pretranslate_windows.end(); ++it)
595 if (SendMessage(*it, PM_TRANSLATE_MSG, 0, (LPARAM)pmsg))
596 return TRUE;
597
598 return FALSE;
599 }
600
601
602 WindowSet Window::s_dialogs;
603
604 void Window::register_dialog(HWND hwnd)
605 {
606 s_dialogs.insert(hwnd);
607 }
608
609 void Window::unregister_dialog(HWND hwnd)
610 {
611 s_dialogs.erase(hwnd);
612 }
613
614 BOOL Window::dispatch_dialog_msg(MSG* pmsg)
615 {
616 for(WindowSet::const_iterator it=Window::s_dialogs.begin(); it!=s_dialogs.end(); ++it)
617 if (IsDialogMessage(*it, pmsg))
618 return TRUE;
619
620 return FALSE;
621 }
622
623
624 int Window::MessageLoop()
625 {
626 MSG msg;
627
628 while(GetMessage(&msg, 0, 0, 0)) {
629 try {
630 if (pretranslate_msg(&msg))
631 continue;
632
633 if (dispatch_dialog_msg(&msg))
634 continue;
635
636 TranslateMessage(&msg);
637
638 try {
639 DispatchMessage(&msg);
640 } catch(COMException& e) {
641 HandleException(e, 0);
642 }
643 } catch(COMException& e) {
644 HandleException(e, 0);
645 }
646 }
647
648 return msg.wParam;
649 }
650
651
652 LRESULT Window::SendParent(UINT nmsg, WPARAM wparam, LPARAM lparam)
653 {
654 HWND parent = GetParent(_hwnd);
655
656 if (!parent)
657 return 0;
658
659 return SendMessage(parent, nmsg, wparam, lparam);
660 }
661
662 LRESULT Window::PostParent(UINT nmsg, WPARAM wparam, LPARAM lparam)
663 {
664 HWND parent = GetParent(_hwnd);
665
666 if (!parent)
667 return 0;
668
669 return PostMessage(parent, nmsg, wparam, lparam);
670 }
671
672
673 PreTranslateWindow::PreTranslateWindow(HWND hwnd)
674 : super(hwnd)
675 {
676 register_pretranslate(hwnd);
677 }
678
679 PreTranslateWindow::~PreTranslateWindow()
680 {
681 unregister_pretranslate(_hwnd);
682 }
683
684
685 Dialog::Dialog(HWND hwnd)
686 : super(hwnd)
687 {
688 register_dialog(hwnd);
689 }
690
691 Dialog::~Dialog()
692 {
693 unregister_dialog(_hwnd);
694 }
695
696 int Dialog::DoModal(UINT nid, CREATORFUNC creator, HWND hwndParent)
697 {
698 Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
699
700 s_window_creator = creator;
701 s_new_info = NULL;
702
703 ///@todo call Window::pretranslate_msg()
704
705 return DialogBoxParam(g_Globals._hInstance, MAKEINTRESOURCE(nid), hwndParent, DialogProc, 0/*lpParam*/);
706 }
707
708 int Dialog::DoModal(UINT nid, CREATORFUNC_INFO creator, const void* info, HWND hwndParent)
709 {
710 Lock lock(GetStaticWindowData()._create_crit_sect); // protect access to s_window_creator and s_new_info
711
712 s_window_creator = (CREATORFUNC) creator;
713 s_new_info = NULL;
714
715 ///@todo call Window::pretranslate_msg()
716
717 return DialogBoxParam(g_Globals._hInstance, MAKEINTRESOURCE(nid), hwndParent, DialogProc, 0/*lpParam*/);
718 }
719
720 INT_PTR CALLBACK Window::DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
721 {
722 Window* pThis = get_window(hwnd);
723
724 if (pThis) {
725 switch(nmsg) {
726 case WM_COMMAND:
727 pThis->Command(LOWORD(wparam), HIWORD(wparam));
728 return TRUE; // message has been processed
729
730 case WM_NOTIFY:
731 pThis->Notify(wparam, (NMHDR*)lparam);
732 return TRUE; // message has been processed
733
734 case WM_NOTIFYFORMAT:
735 SetWindowLongPtr(hwnd, DWLP_MSGRESULT, NFR_CURRENT); // set return value NFR_CURRENT
736 return TRUE; // message has been processed
737
738 case WM_NCDESTROY:
739 delete pThis;
740 return TRUE; // message has been processed
741
742 default:
743 return pThis->WndProc(nmsg, wparam, lparam);
744 }
745 } else if (nmsg == WM_INITDIALOG) {
746 pThis = create_controller(hwnd);
747
748 if (pThis)
749 return pThis->Init(NULL);
750 }
751
752 return FALSE; // message has not been processed
753 }
754
755 LRESULT Dialog::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
756 {
757 return FALSE; // message has not been processed
758 }
759
760 int Dialog::Command(int id, int code)
761 {
762 if (code == BN_CLICKED) {
763 EndDialog(_hwnd, id);
764 return 0; // message has been processed
765 }
766
767 return 1;
768 }
769
770
771 ResizeManager::ResizeManager(HWND hwnd)
772 : _hwnd(hwnd)
773 {
774 ClientRect clnt(hwnd);
775 _last_size.cx = clnt.right;
776 _last_size.cy = clnt.bottom;
777
778 WindowRect rect(hwnd);
779 _min_wnd_size.cx = rect.right - rect.left;
780 _min_wnd_size.cy = rect.bottom - rect.top;
781 }
782
783 void ResizeManager::HandleSize(int cx, int cy)
784 {
785 ClientRect clnt_rect(_hwnd);
786 SIZE new_size = {cx, cy};
787
788 int dx = new_size.cx - _last_size.cx;
789 int dy = new_size.cy - _last_size.cy;
790
791 if (!dx && !dy)
792 return;
793
794 _last_size = new_size;
795
796 HDWP hDWP = BeginDeferWindowPos(size());
797
798 for(ResizeManager::const_iterator it=begin(); it!=end(); ++it) {
799 const ResizeEntry& e = *it;
800 RECT move = {0};
801
802 if (e._flags & MOVE_LEFT)
803 move.left += dx;
804
805 if (e._flags & MOVE_RIGHT)
806 move.right += dx;
807
808 if (e._flags & MOVE_TOP)
809 move.top += dy;
810
811 if (e._flags & MOVE_BOTTOM)
812 move.bottom += dy;
813
814 UINT flags = 0;
815
816 if (!move.left && !move.top)
817 flags = SWP_NOMOVE;
818
819 if (move.right==move.left && move.bottom==move.top)
820 flags |= SWP_NOSIZE;
821
822 if (flags != (SWP_NOMOVE|SWP_NOSIZE)) {
823 HWND hwnd = GetDlgItem(_hwnd, e._id);
824
825 if (hwnd) {
826 WindowRect rect(hwnd);
827 ScreenToClient(_hwnd, rect);
828
829 rect.left += move.left;
830 rect.right += move.right;
831 rect.top += move.top;
832 rect.bottom += move.bottom;
833
834 hDWP = DeferWindowPos(hDWP, hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, flags|SWP_NOACTIVATE|SWP_NOZORDER);
835 }
836 }
837 }
838
839 EndDeferWindowPos(hDWP);
840 }
841
842 void ResizeManager::Resize(int dx, int dy)
843 {
844 ::SetWindowPos(_hwnd, 0, 0, 0, _min_wnd_size.cx+dx, _min_wnd_size.cy+dy, SWP_NOMOVE|SWP_NOACTIVATE);
845 MoveVisible(_hwnd);
846
847 ClientRect clnt_rect(_hwnd);
848 HandleSize(clnt_rect.right, clnt_rect.bottom);
849 }
850
851
852 Button::Button(HWND parent, LPCTSTR title, int left, int top, int width, int height,
853 int id, DWORD flags, DWORD exStyle)
854 : WindowHandle(CreateWindowEx(exStyle, TEXT("BUTTON"), title, flags, left, top, width, height,
855 parent, (HMENU)id, g_Globals._hInstance, 0))
856 {
857 }
858
859
860 LRESULT OwnerdrawnButton::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
861 {
862 if (nmsg == PM_DISPATCH_DRAWITEM) {
863 DrawItem((LPDRAWITEMSTRUCT)lparam);
864 return TRUE;
865 } else
866 return super::WndProc(nmsg, wparam, lparam);
867 }
868
869
870 Static::Static(HWND parent, LPCTSTR title, int left, int top, int width, int height,
871 int id, DWORD flags, DWORD exStyle)
872 : WindowHandle(CreateWindowEx(exStyle, TEXT("STATIC"), title, flags, left, top, width, height,
873 parent, (HMENU)id, g_Globals._hInstance, 0))
874 {
875 }
876
877
878 static RECT s_MyDrawText_Rect = {0, 0, 0, 0};
879
880 static BOOL CALLBACK MyDrawText(HDC hdc, LPARAM data, int cnt)
881 {
882 ::DrawText(hdc, (LPCTSTR)data, cnt, &s_MyDrawText_Rect, DT_SINGLELINE);
883 return TRUE;
884 }
885
886 void DrawGrayText(HDC hdc, LPRECT pRect, LPCTSTR title, int dt_flags)
887 {
888 COLORREF gray = GetSysColor(COLOR_GRAYTEXT);
889
890 if (gray) {
891 TextColor lcColor(hdc, GetSysColor(COLOR_BTNHIGHLIGHT));
892 RECT shadowRect = {pRect->left+1, pRect->top+1, pRect->right+1, pRect->bottom+1};
893 DrawText(hdc, title, -1, &shadowRect, dt_flags);
894
895 SetTextColor(hdc, gray);
896 DrawText(hdc, title, -1, pRect, dt_flags);
897 } else {
898 int old_r = pRect->right;
899 int old_b = pRect->bottom;
900
901 DrawText(hdc, title, -1, pRect, dt_flags|DT_CALCRECT);
902
903 int x = pRect->left + (old_r-pRect->right)/2;
904 int y = pRect->top + (old_b-pRect->bottom)/2;
905 int w = pRect->right-pRect->left;
906 int h = pRect->bottom-pRect->top;
907 s_MyDrawText_Rect.right = w;
908 s_MyDrawText_Rect.bottom = h;
909
910 GrayString(hdc, GetSysColorBrush(COLOR_GRAYTEXT), MyDrawText, (LPARAM)title, -1, x, y, w, h);
911 }
912 }
913
914
915 /* not yet used
916 void ColorButton::DrawItem(LPDRAWITEMSTRUCT dis)
917 {
918 UINT state = DFCS_BUTTONPUSH;
919
920 if (dis->itemState & ODS_DISABLED)
921 state |= DFCS_INACTIVE;
922
923 RECT textRect = {dis->rcItem.left+2, dis->rcItem.top+2, dis->rcItem.right-4, dis->rcItem.bottom-4};
924
925 if (dis->itemState & ODS_SELECTED) {
926 state |= DFCS_PUSHED;
927 ++textRect.left; ++textRect.top;
928 ++textRect.right; ++textRect.bottom;
929 }
930
931 DrawFrameControl(dis->hDC, &dis->rcItem, DFC_BUTTON, state);
932
933 TCHAR title[BUFFER_LEN];
934 GetWindowText(_hwnd, title, BUFFER_LEN);
935
936 BkMode bk_mode(dis->hDC, TRANSPARENT);
937
938 if (dis->itemState & (ODS_DISABLED|ODS_GRAYED))
939 DrawGrayText(dis, &textRect, title, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
940 else {
941 TextColor lcColor(dis->hDC, _textColor);
942 DrawText(dis->hDC, title, -1, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
943 }
944
945 if (dis->itemState & ODS_FOCUS) {
946 RECT rect = {
947 dis->rcItem.left+3, dis->rcItem.top+3,
948 dis->rcItem.right-dis->rcItem.left-4, dis->rcItem.bottom-dis->rcItem.top-4
949 };
950 if (dis->itemState & ODS_SELECTED) {
951 ++rect.left; ++rect.top;
952 ++rect.right; ++rect.bottom;
953 }
954 DrawFocusRect(dis->hDC, &rect);
955 }
956 }
957 */
958
959
960 void PictureButton::DrawItem(LPDRAWITEMSTRUCT dis)
961 {
962 UINT state = DFCS_BUTTONPUSH;
963 int style = GetWindowStyle(_hwnd);
964
965 if (dis->itemState & ODS_DISABLED)
966 state |= DFCS_INACTIVE;
967
968 POINT imagePos;
969 RECT textRect;
970 int dt_flags;
971
972 if (style & BS_BOTTOM) {
973 // align horizontal centered, vertical floating
974 imagePos.x = (dis->rcItem.left + dis->rcItem.right - _cx) / 2;
975 imagePos.y = dis->rcItem.top + 3;
976
977 textRect.left = dis->rcItem.left + 2;
978 textRect.top = dis->rcItem.top + _cy + 4;
979 textRect.right = dis->rcItem.right - 4;
980 textRect.bottom = dis->rcItem.bottom - 4;
981
982 dt_flags = DT_SINGLELINE|DT_CENTER|DT_VCENTER;
983 } else {
984 // horizontal floating, vertical centered
985 imagePos.x = dis->rcItem.left + 3;
986 imagePos.y = (dis->rcItem.top + dis->rcItem.bottom - _cy)/2;
987
988 textRect.left = dis->rcItem.left + _cx + 4;
989 textRect.top = dis->rcItem.top + 2;
990 textRect.right = dis->rcItem.right - 4;
991 textRect.bottom = dis->rcItem.bottom - 4;
992
993 dt_flags = DT_SINGLELINE|DT_VCENTER/*|DT_CENTER*/;
994 }
995
996 if (dis->itemState & ODS_SELECTED) {
997 state |= DFCS_PUSHED;
998 ++imagePos.x; ++imagePos.y;
999 ++textRect.left; ++textRect.top;
1000 ++textRect.right; ++textRect.bottom;
1001 }
1002
1003 if (_flat) {
1004 FillRect(dis->hDC, &dis->rcItem, _hBrush);
1005
1006 if (style & BS_FLAT) // Only with BS_FLAT set, there will be drawn a frame without highlight.
1007 DrawEdge(dis->hDC, &dis->rcItem, EDGE_RAISED, BF_RECT|BF_FLAT);
1008 } else
1009 DrawFrameControl(dis->hDC, &dis->rcItem, DFC_BUTTON, state);
1010
1011 if (_hIcon)
1012 DrawIconEx(dis->hDC, imagePos.x, imagePos.y, _hIcon, _cx, _cy, 0, _hBrush, DI_NORMAL);
1013 else {
1014 MemCanvas mem_dc;
1015 BitmapSelection sel(mem_dc, _hBmp);
1016 BitBlt(dis->hDC, imagePos.x, imagePos.y, _cx, _cy, mem_dc, 0, 0, SRCCOPY);
1017 }
1018
1019 TCHAR title[BUFFER_LEN];
1020 GetWindowText(_hwnd, title, BUFFER_LEN);
1021
1022 BkMode bk_mode(dis->hDC, TRANSPARENT);
1023
1024 if (dis->itemState & (ODS_DISABLED|ODS_GRAYED))
1025 DrawGrayText(dis->hDC, &textRect, title, dt_flags);
1026 else {
1027 TextColor lcColor(dis->hDC, GetSysColor(COLOR_BTNTEXT));
1028 DrawText(dis->hDC, title, -1, &textRect, dt_flags);
1029 }
1030
1031 if (dis->itemState & ODS_FOCUS) {
1032 RECT rect = {
1033 dis->rcItem.left+3, dis->rcItem.top+3,
1034 dis->rcItem.right-dis->rcItem.left-4, dis->rcItem.bottom-dis->rcItem.top-4
1035 };
1036 if (dis->itemState & ODS_SELECTED) {
1037 ++rect.left; ++rect.top;
1038 ++rect.right; ++rect.bottom;
1039 }
1040 DrawFocusRect(dis->hDC, &rect);
1041 }
1042 }
1043
1044
1045 void FlatButton::DrawItem(LPDRAWITEMSTRUCT dis)
1046 {
1047 UINT style = DFCS_BUTTONPUSH;
1048
1049 if (dis->itemState & ODS_DISABLED)
1050 style |= DFCS_INACTIVE;
1051
1052 RECT textRect = {dis->rcItem.left+2, dis->rcItem.top+2, dis->rcItem.right-4, dis->rcItem.bottom-4};
1053
1054 if (dis->itemState & ODS_SELECTED) {
1055 style |= DFCS_PUSHED;
1056 ++textRect.left; ++textRect.top;
1057 ++textRect.right; ++textRect.bottom;
1058 }
1059
1060 FillRect(dis->hDC, &dis->rcItem, GetSysColorBrush(COLOR_BTNFACE));
1061
1062 // highlight the button?
1063 if (_active)
1064 DrawEdge(dis->hDC, &dis->rcItem, EDGE_ETCHED, BF_RECT);
1065 else if (GetWindowStyle(_hwnd) & BS_FLAT) // Only with BS_FLAT there will be drawn a frame to show highlighting.
1066 DrawEdge(dis->hDC, &dis->rcItem, EDGE_RAISED, BF_RECT|BF_FLAT);
1067
1068 TCHAR txt[BUFFER_LEN];
1069 int txt_len = GetWindowText(_hwnd, txt, BUFFER_LEN);
1070
1071 if (dis->itemState & (ODS_DISABLED|ODS_GRAYED)) {
1072 COLORREF gray = GetSysColor(COLOR_GRAYTEXT);
1073
1074 if (gray) {
1075 {
1076 TextColor lcColor(dis->hDC, GetSysColor(COLOR_BTNHIGHLIGHT));
1077 RECT shadowRect = {textRect.left+1, textRect.top+1, textRect.right+1, textRect.bottom+1};
1078 DrawText(dis->hDC, txt, txt_len, &shadowRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
1079 }
1080
1081 BkMode mode(dis->hDC, TRANSPARENT);
1082 TextColor lcColor(dis->hDC, gray);
1083 DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
1084 } else {
1085 int old_r = textRect.right;
1086 int old_b = textRect.bottom;
1087 DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER|DT_CALCRECT);
1088 int x = textRect.left + (old_r-textRect.right)/2;
1089 int y = textRect.top + (old_b-textRect.bottom)/2;
1090 int w = textRect.right-textRect.left;
1091 int h = textRect.bottom-textRect.top;
1092 s_MyDrawText_Rect.right = w;
1093 s_MyDrawText_Rect.bottom = h;
1094 GrayString(dis->hDC, GetSysColorBrush(COLOR_GRAYTEXT), MyDrawText, (LPARAM)txt, txt_len, x, y, w, h);
1095 }
1096 } else {
1097 TextColor lcColor(dis->hDC, _active? _activeColor: _textColor);
1098 DrawText(dis->hDC, txt, txt_len, &textRect, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
1099 }
1100
1101 if (dis->itemState & ODS_FOCUS) {
1102 RECT rect = {
1103 dis->rcItem.left+3, dis->rcItem.top+3,
1104 dis->rcItem.right-dis->rcItem.left-4, dis->rcItem.bottom-dis->rcItem.top-4
1105 };
1106 if (dis->itemState & ODS_SELECTED) {
1107 ++rect.left; ++rect.top;
1108 ++rect.right; ++rect.bottom;
1109 }
1110 DrawFocusRect(dis->hDC, &rect);
1111 }
1112 }
1113
1114 LRESULT FlatButton::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
1115 {
1116 switch(nmsg) {
1117 case WM_MOUSEMOVE: {
1118 bool active = false;
1119
1120 if (IsWindowEnabled(_hwnd)) {
1121 DWORD pid_foreground;
1122 HWND hwnd_foreground = GetForegroundWindow(); //@@ may be better look for WM_ACTIVATEAPP ?
1123 GetWindowThreadProcessId(hwnd_foreground, &pid_foreground);
1124
1125 if (GetCurrentProcessId() == pid_foreground) {
1126 POINT pt = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
1127 ClientRect clntRect(_hwnd);
1128
1129 // highlight the button?
1130 if (pt.x>=clntRect.left && pt.x<clntRect.right && pt.y>=clntRect.top && pt.y<clntRect.bottom)
1131 active = true;
1132 }
1133 }
1134
1135 if (active != _active) {
1136 _active = active;
1137
1138 if (active) {
1139 TRACKMOUSEEVENT tme = {sizeof(tme), /*TME_HOVER|*/TME_LEAVE, _hwnd/*, HOVER_DEFAULT*/};
1140 _TrackMouseEvent(&tme);
1141 }
1142
1143 InvalidateRect(_hwnd, NULL, TRUE);
1144 }
1145
1146 return 0;}
1147
1148 case WM_LBUTTONUP: {
1149 POINT pt = {GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam)};
1150 ClientRect clntRect(_hwnd);
1151
1152 // no more in the active rectangle?
1153 if (pt.x<clntRect.left || pt.x>=clntRect.right || pt.y<clntRect.top || pt.y>=clntRect.bottom)
1154 goto cancel_press;
1155
1156 goto def;}
1157
1158 case WM_CANCELMODE:
1159 cancel_press: {
1160 TRACKMOUSEEVENT tme = {sizeof(tme), /*TME_HOVER|*/TME_LEAVE|TME_CANCEL, _hwnd/*, HOVER_DEFAULT*/};
1161 _TrackMouseEvent(&tme);
1162 _active = false;
1163 ReleaseCapture();}
1164 // fall through
1165
1166 case WM_MOUSELEAVE:
1167 if (_active) {
1168 _active = false;
1169
1170 InvalidateRect(_hwnd, NULL, TRUE);
1171 }
1172
1173 return 0;
1174
1175 default: def:
1176 return super::WndProc(nmsg, wparam, lparam);
1177 }
1178 }
1179
1180
1181 HyperlinkCtrl::HyperlinkCtrl(HWND hwnd, COLORREF colorLink, COLORREF colorVisited)
1182 : super(hwnd),
1183 _cmd(ResString(GetDlgCtrlID(hwnd))),
1184 _textColor(colorLink),
1185 _colorVisited(colorVisited),
1186 _hfont(0),
1187 _crsr_link(0)
1188 {
1189 init();
1190 }
1191
1192 HyperlinkCtrl::HyperlinkCtrl(HWND owner, int id, COLORREF colorLink, COLORREF colorVisited)
1193 : super(GetDlgItem(owner, id)),
1194 _cmd(ResString(id)),
1195 _textColor(colorLink),
1196 _colorVisited(colorVisited),
1197 _hfont(0),
1198 _crsr_link(0)
1199 {
1200 init();
1201 }
1202
1203 void HyperlinkCtrl::init()
1204 {
1205 if (_cmd.empty()) {
1206 TCHAR txt[BUFFER_LEN];
1207 _cmd.assign(txt, GetWindowText(_hwnd, txt, BUFFER_LEN));
1208 }
1209 }
1210
1211 HyperlinkCtrl::~HyperlinkCtrl()
1212 {
1213 if (_hfont)
1214 DeleteObject(_hfont);
1215 }
1216
1217 LRESULT HyperlinkCtrl::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
1218 {
1219 switch(nmsg) {
1220 case PM_DISPATCH_CTLCOLOR: {
1221 if (!_hfont) {
1222 HFONT hfont = (HFONT) SendMessage(_hwnd, WM_GETFONT, 0, 0);
1223 LOGFONT lf; GetObject(hfont, sizeof(lf), &lf);
1224 lf.lfUnderline = TRUE;
1225 _hfont = CreateFontIndirect(&lf);
1226 }
1227
1228 HDC hdc = (HDC) wparam;
1229 SetTextColor(hdc, _textColor); //@@
1230 SelectFont(hdc, _hfont);
1231 SetBkMode(hdc, TRANSPARENT);
1232 return (LRESULT)GetStockObject(HOLLOW_BRUSH);
1233 }
1234
1235 case WM_SETCURSOR:
1236 if (!_crsr_link)
1237 _crsr_link = LoadCursor(0, IDC_HAND);
1238
1239 if (_crsr_link)
1240 SetCursor(_crsr_link);
1241 return 0;
1242
1243 case WM_NCHITTEST:
1244 return HTCLIENT; // Aktivierung von Maus-Botschaften
1245
1246 case WM_LBUTTONDOWN:
1247 if (LaunchLink()) {
1248 _textColor = _colorVisited;
1249 InvalidateRect(_hwnd, NULL, FALSE);
1250 } else
1251 MessageBeep(0);
1252 return 0;
1253
1254 default:
1255 return super::WndProc(nmsg, wparam, lparam);
1256 }
1257 }
1258
1259
1260 ToolTip::ToolTip(HWND owner)
1261 : super(CreateWindowEx(WS_EX_TOPMOST|WS_EX_NOPARENTNOTIFY, TOOLTIPS_CLASS, 0,
1262 WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
1263 owner, 0, g_Globals._hInstance, 0))
1264 {
1265 activate();
1266 }
1267
1268
1269 ListSort::ListSort(HWND hwndListview, PFNLVCOMPARE compare_fct)
1270 : WindowHandle(hwndListview),
1271 _compare_fct(compare_fct)
1272 {
1273 _sort_crit = 0;
1274 _direction = false;
1275 }
1276
1277 void ListSort::toggle_sort(int idx)
1278 {
1279 if (_sort_crit == idx)
1280 _direction = !_direction;
1281 else {
1282 _sort_crit = idx;
1283 _direction = false;
1284 }
1285 }
1286
1287 void ListSort::sort()
1288 {
1289 int idx = ListView_GetSelectionMark(_hwnd);
1290 LPARAM param = ListView_GetItemData(_hwnd, idx);
1291
1292 ListView_SortItems(_hwnd, _compare_fct, (LPARAM)this);
1293
1294 if (idx >= 0) {
1295 idx = ListView_FindItemPara(_hwnd, param);
1296 ListView_EnsureVisible(_hwnd, idx, FALSE);
1297 }
1298 }
1299
1300
1301 PropSheetPage::PropSheetPage(UINT nid, Window::CREATORFUNC dlg_creator)
1302 : _dlg_creator(dlg_creator)
1303 {
1304 PROPSHEETPAGE::dwSize = sizeof(PROPSHEETPAGE);
1305 PROPSHEETPAGE::dwFlags = 0;
1306 PROPSHEETPAGE::hInstance = g_Globals._hInstance;
1307 PROPSHEETPAGE::pszTemplate = MAKEINTRESOURCE(nid);
1308 PROPSHEETPAGE::pfnDlgProc = PropSheetPageDlg::DialogProc;
1309 PROPSHEETPAGE::lParam = (LPARAM) this;
1310 }
1311
1312
1313 #ifndef PSM_GETRESULT // currently (as of 18.01.2004) missing in MinGW headers
1314 #define PSM_GETRESULT (WM_USER + 135)
1315 #define PropSheet_GetResult(hDlg) SNDMSG(hDlg, PSM_GETRESULT, 0, 0)
1316 #endif
1317
1318
1319 PropertySheetDialog::PropertySheetDialog(HWND owner)
1320 : _hwnd(0)
1321 {
1322 PROPSHEETHEADER::dwSize = sizeof(PROPSHEETHEADER);
1323 PROPSHEETHEADER::dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS;
1324 PROPSHEETHEADER::hwndParent = owner;
1325 PROPSHEETHEADER::hInstance = g_Globals._hInstance;
1326 }
1327
1328 void PropertySheetDialog::add(PropSheetPage& psp)
1329 {
1330 _pages.push_back(psp);
1331 }
1332
1333 int PropertySheetDialog::DoModal(int start_page)
1334 {
1335 PROPSHEETHEADER::ppsp = (LPCPROPSHEETPAGE) &_pages[0];
1336 PROPSHEETHEADER::nPages = _pages.size();
1337 PROPSHEETHEADER::nStartPage = start_page;
1338 /*
1339 Window* pwnd = Window::create_property_sheet(this, WINDOW_CREATOR(PropertySheetDlg), NULL);
1340 if (!pwnd)
1341 return -1;
1342
1343 HWND hwndPropSheet = *pwnd;
1344 */
1345 int ret = PropertySheet(this);
1346 if (ret == -1)
1347 return -1;
1348
1349 HWND hwndPropSheet = (HWND) ret;
1350 HWND hwndparent = GetParent(hwndPropSheet);
1351
1352 if (hwndparent)
1353 EnableWindow(hwndparent, FALSE);
1354
1355 ret = 0;
1356 MSG msg;
1357
1358 while(GetMessage(&msg, 0, 0, 0)) {
1359 try {
1360 if (Window::pretranslate_msg(&msg))
1361 continue;
1362
1363 if (PropSheet_IsDialogMessage(hwndPropSheet, &msg))
1364 continue;
1365
1366 if (Window::dispatch_dialog_msg(&msg))
1367 continue;
1368
1369 TranslateMessage(&msg);
1370
1371 try {
1372 DispatchMessage(&msg);
1373 } catch(COMException& e) {
1374 HandleException(e, 0);
1375 }
1376
1377 if (!PropSheet_GetCurrentPageHwnd(hwndPropSheet)) {
1378 ret = PropSheet_GetResult(hwndPropSheet);
1379 break;
1380 }
1381 } catch(COMException& e) {
1382 HandleException(e, 0);
1383 }
1384 }
1385
1386 if (hwndparent)
1387 EnableWindow(hwndparent, TRUE);
1388
1389 DestroyWindow(hwndPropSheet);
1390
1391 return ret;
1392 }
1393
1394 HWND PropertySheetDialog::GetCurrentPage()
1395 {
1396 HWND hdlg = PropSheet_GetCurrentPageHwnd(_hwnd);
1397 return hdlg;
1398 }
1399
1400
1401 PropSheetPageDlg::PropSheetPageDlg(HWND hwnd)
1402 : super(hwnd)
1403 {
1404 }
1405
1406 INT_PTR CALLBACK PropSheetPageDlg::DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam)
1407 {
1408 PropSheetPageDlg* pThis = GET_WINDOW(PropSheetPageDlg, hwnd);
1409
1410 if (pThis) {
1411 switch(nmsg) {
1412 case WM_COMMAND:
1413 pThis->Command(LOWORD(wparam), HIWORD(wparam));
1414 return TRUE; // message has been processed
1415
1416 case WM_NOTIFY:
1417 pThis->Notify(wparam, (NMHDR*)lparam);
1418 return TRUE; // message has been processed
1419
1420 case WM_NOTIFYFORMAT:
1421 SetWindowLongPtr(hwnd, DWLP_MSGRESULT, NFR_CURRENT); // set return value NFR_CURRENT
1422 return TRUE; // message has been processed
1423
1424 case WM_NCDESTROY:
1425 delete pThis;
1426 return TRUE; // message has been processed
1427
1428 default:
1429 return pThis->WndProc(nmsg, wparam, lparam);
1430 }
1431 } else if (nmsg == WM_INITDIALOG) {
1432 PROPSHEETPAGE* psp = (PROPSHEETPAGE*) lparam;
1433 PropSheetPage* ppsp = (PropSheetPage*) psp->lParam;
1434
1435 if (ppsp->_dlg_creator) {
1436 pThis = static_cast<PropSheetPageDlg*>(ppsp->_dlg_creator(hwnd));
1437
1438 if (pThis)
1439 return pThis->Init(NULL);
1440 }
1441 }
1442
1443 return FALSE; // message has not been processed
1444 }
1445
1446 int PropSheetPageDlg::Command(int id, int code)
1447 {
1448 // override call to EndDialog in Dialog::Command();
1449
1450 return FALSE;
1451 }