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