00001 /* 00002 * Copyright 2003, 2004, 2005 Martin Fuchs 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 */ 00018 00019 00020 // 00021 // Explorer clone 00022 // 00023 // window.h 00024 // 00025 // Martin Fuchs, 23.07.2003 00026 // 00027 00028 00029 typedef set<HWND> WindowSet; 00030 00031 00032 /* 00033 Classes are declared using "struct", not "class" because the default 00034 access mode is "public". This way we can list the member functions in a 00035 natural order without explicitly specifying any access mode at the begin 00036 of the definition. 00037 First are public constructors and destructor, then public member functions. 00038 After that we list protected member varibables and functions. If needed, 00039 private implemenation varibales and functions are positioned at the end. 00040 */ 00041 00042 00043 /// information structure for creation of a MDI child window 00044 struct ChildWndInfo 00045 { 00046 ChildWndInfo(HWND hmdiclient) 00047 : _hmdiclient(hmdiclient) {} 00048 00049 HWND _hmdiclient; 00050 }; 00051 00052 00053 /** 00054 Class Window is the base class for several C++ window wrapper classes. 00055 Window objects are allocated from the heap. They are automatically freed 00056 when the window gets destroyed. 00057 */ 00058 struct Window : public WindowHandle 00059 { 00060 Window(HWND hwnd); 00061 virtual ~Window(); 00062 00063 00064 typedef map<HWND,Window*> WindowMap; 00065 00066 typedef Window* (*CREATORFUNC)(HWND); 00067 typedef Window* (*CREATORFUNC_INFO)(HWND, const void*); 00068 00069 static HWND Create(CREATORFUNC creator, 00070 DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, 00071 DWORD dwStyle, int x, int y, int w, int h, 00072 HWND hwndParent=0, HMENU hMenu=0/*, LPVOID lpParam=0*/); 00073 00074 static HWND Create(CREATORFUNC_INFO creator, const void* info, 00075 DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, 00076 DWORD dwStyle, int x, int y, int w, int h, 00077 HWND hwndParent=0, HMENU hMenu=0/*, LPVOID lpParam=0*/); 00078 00079 static Window* create_mdi_child(const ChildWndInfo& info, const MDICREATESTRUCT& mcs, CREATORFUNC_INFO creator); 00080 // static Window* create_property_sheet(struct PropertySheetDialog* ppsd, CREATORFUNC creator, const void* info); 00081 00082 static LRESULT CALLBACK WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam); 00083 static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam); 00084 00085 static Window* get_window(HWND hwnd); 00086 #ifndef _MSC_VER 00087 template<typename CLASS> static CLASS* get_window(HWND hwnd) {return static_cast<CLASS*>(get_window(hwnd));} 00088 #define GET_WINDOW(CLASS, hwnd) Window::get_window<CLASS>(hwnd) 00089 #endif 00090 00091 static void register_pretranslate(HWND hwnd); 00092 static void unregister_pretranslate(HWND hwnd); 00093 static BOOL pretranslate_msg(LPMSG pmsg); 00094 00095 static void register_dialog(HWND hwnd); 00096 static void unregister_dialog(HWND hwnd); 00097 static BOOL dispatch_dialog_msg(LPMSG pmsg); 00098 00099 static int MessageLoop(); 00100 00101 00102 LRESULT SendParent(UINT nmsg, WPARAM wparam=0, LPARAM lparam=0); 00103 LRESULT PostParent(UINT nmsg, WPARAM wparam=0, LPARAM lparam=0); 00104 00105 static void CancelModes(); 00106 00107 00108 protected: 00109 virtual LRESULT Init(LPCREATESTRUCT pcs); // WM_CREATE processing 00110 virtual LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); 00111 virtual int Command(int id, int code); // WM_COMMAND processing 00112 virtual int Notify(int id, NMHDR* pnmh); // WM_NOTIFY processing 00113 00114 static Window* create_controller(HWND hwnd); 00115 00116 00117 static WindowMap s_wnd_map; 00118 00119 static const void* s_new_info; 00120 static CREATORFUNC s_window_creator; 00121 00122 00123 /// structure for managing critical sections as static class information in struct Window 00124 struct StaticWindowData { 00125 CritSect _map_crit_sect; 00126 CritSect _create_crit_sect; 00127 }; 00128 00129 static StaticWindowData& GetStaticWindowData(); 00130 00131 00132 // MDI child creation 00133 static HHOOK s_hcbtHook; 00134 static LRESULT CALLBACK MDICBTHookProc(int code, WPARAM wparam, LPARAM lparam); 00135 static LRESULT CALLBACK PropSheetCBTHookProc(int code, WPARAM wparam, LPARAM lparam); 00136 00137 static WindowSet s_pretranslate_windows; 00138 static WindowSet s_dialogs; 00139 }; 00140 00141 #ifdef UNICODE 00142 #define NFR_CURRENT NFR_UNICODE 00143 #else 00144 #define NFR_CURRENT NFR_ANSI 00145 #endif 00146 00147 00148 #ifdef _MSC_VER 00149 template<typename CLASS> struct GetWindowHelper 00150 { 00151 static CLASS* get_window(HWND hwnd) { 00152 return static_cast<CLASS*>(Window::get_window(hwnd)); 00153 } 00154 }; 00155 #define GET_WINDOW(CLASS, hwnd) GetWindowHelper<CLASS>::get_window(hwnd) 00156 #endif 00157 00158 00159 /// dynamic casting of Window pointers 00160 template<typename CLASS> struct TypeCheck 00161 { 00162 static CLASS* dyn_cast(Window* wnd) 00163 {return dynamic_cast<CLASS*>(wnd);} 00164 }; 00165 00166 #define WINDOW_DYNAMIC_CAST(CLASS, hwnd) \ 00167 TypeCheck<CLASS>::dyn_cast(Window::get_window(hwnd)) 00168 00169 00170 /** 00171 SubclassedWindow is used to wrap already existing window handles 00172 into C++ Window objects. To construct a object, use the "new" operator 00173 to put it in the heap. It is automatically freed, when the window 00174 gets destroyed. 00175 */ 00176 struct SubclassedWindow : public Window 00177 { 00178 typedef Window super; 00179 00180 SubclassedWindow(HWND); 00181 00182 protected: 00183 WNDPROC _orgWndProc; 00184 00185 static LRESULT CALLBACK SubclassedWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam); 00186 00187 virtual LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); 00188 virtual int Command(int id, int code); 00189 virtual int Notify(int id, NMHDR* pnmh); 00190 }; 00191 00192 00193 /// template class used in macro WINDOW_CREATOR to define the creater functions for Window objects 00194 template<typename WND_CLASS> struct WindowCreator 00195 { 00196 static WND_CLASS* window_creator(HWND hwnd) 00197 { 00198 return new WND_CLASS(hwnd); 00199 } 00200 }; 00201 00202 #define WINDOW_CREATOR(WND_CLASS) \ 00203 ((Window::CREATORFUNC) WindowCreator<WND_CLASS>::window_creator) 00204 00205 00206 /// template class used in macro WINDOW_CREATOR_INFO to the define creater functions for Window objects with additional creation information 00207 template<typename WND_CLASS, typename INFO_CLASS> struct WindowCreatorInfo 00208 { 00209 static WND_CLASS* window_creator(HWND hwnd, const void* info) 00210 { 00211 return new WND_CLASS(hwnd, *static_cast<const INFO_CLASS*>(info)); 00212 } 00213 }; 00214 00215 #define WINDOW_CREATOR_INFO(WND_CLASS, INFO_CLASS) \ 00216 ((Window::CREATORFUNC_INFO) WindowCreatorInfo<WND_CLASS, INFO_CLASS>::window_creator) 00217 00218 00219 /** 00220 WindowClass is a neat wrapper for RegisterClassEx(). 00221 Just construct a WindowClass object, override the attributes you want 00222 to change, then call Register() or simply request the ATOM value to 00223 register the window class. You don't have to worry calling Register() 00224 more than once. It checks if, the class has already been registered. 00225 */ 00226 struct WindowClass : public WNDCLASSEX 00227 { 00228 WindowClass(LPCTSTR classname, UINT style=0, WNDPROC wndproc=Window::WindowWndProc); 00229 00230 ATOM Register() 00231 { 00232 if (!_atomClass) 00233 _atomClass = RegisterClassEx(this); 00234 00235 return _atomClass; 00236 } 00237 00238 operator ATOM() {return Register();} 00239 00240 // return LPCTSTR for the CreateWindowEx() parameter 00241 operator LPCTSTR() {return (LPCTSTR)(int)Register();} 00242 00243 protected: 00244 ATOM _atomClass; 00245 }; 00246 00247 /// window class with gray background color 00248 struct BtnWindowClass : public WindowClass 00249 { 00250 BtnWindowClass(LPCTSTR classname, UINT style=0, WNDPROC wndproc=Window::WindowWndProc) 00251 : WindowClass(classname, style, wndproc) 00252 { 00253 hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); 00254 } 00255 }; 00256 00257 /// window class with specified icon from resources 00258 struct IconWindowClass : public WindowClass 00259 { 00260 IconWindowClass(LPCTSTR classname, UINT nid, UINT style=0, WNDPROC wndproc=Window::WindowWndProc); 00261 }; 00262 00263 00264 // private message constants 00265 #define PM_DISPATCH_COMMAND (WM_APP+0x00) 00266 #define PM_TRANSLATE_MSG (WM_APP+0x01) 00267 00268 00269 #define SPLIT_WIDTH 5 00270 #define DEFAULT_SPLIT_POS 300 00271 #define COLOR_SPLITBAR LTGRAY_BRUSH 00272 00273 00274 /// menu info structure 00275 struct MenuInfo 00276 { 00277 HMENU _hMenuView; 00278 }; 00279 00280 #define PM_FRM_GET_MENUINFO (WM_APP+0x02) 00281 00282 #define Frame_GetMenuInfo(hwnd) ((MenuInfo*)SNDMSG(hwnd, PM_FRM_GET_MENUINFO, 0, 0)) 00283 00284 00285 /** 00286 Class ChildWindow represents MDI child windows. 00287 It is used with class MainFrame. 00288 */ 00289 struct ChildWindow : public Window 00290 { 00291 typedef Window super; 00292 00293 ChildWindow(HWND hwnd, const ChildWndInfo& info); 00294 00295 static ChildWindow* create(const ChildWndInfo& info, const RECT& rect, CREATORFUNC_INFO creator, 00296 LPCTSTR classname, LPCTSTR title=NULL, DWORD style=0); 00297 00298 bool go_to(LPCTSTR url); 00299 00300 protected: 00301 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); 00302 00303 virtual void resize_children(int cx, int cy); 00304 virtual String jump_to_int(LPCTSTR url) = 0; 00305 00306 protected: 00307 MenuInfo*_menu_info; 00308 00309 WindowHandle _left_hwnd; 00310 WindowHandle _right_hwnd; 00311 int _focus_pane; // 0: left 1: right 00312 00313 int _split_pos; 00314 int _last_split; 00315 00316 HWND _hwndFrame; 00317 String _statusText; 00318 String _url; 00319 00320 stack<String> _url_history; 00321 00322 void set_url(LPCTSTR url); 00323 }; 00324 00325 #define PM_SETSTATUSTEXT (WM_APP+0x1E) 00326 00327 00328 /** 00329 PreTranslateWindow is used to register windows to be called by Window::pretranslate_msg(). 00330 This way you get PM_TRANSLATE_MSG messages before the message loop dispatches messages. 00331 You can then for example use TranslateAccelerator() to implement key shortcuts. 00332 */ 00333 struct PreTranslateWindow : public Window 00334 { 00335 typedef Window super; 00336 00337 PreTranslateWindow(HWND); 00338 ~PreTranslateWindow(); 00339 }; 00340 00341 00342 /** 00343 The class DialogWindow implements modeless dialogs, which are managed by 00344 Window::dispatch_dialog_msg() in Window::MessageLoop(). 00345 A DialogWindow object should be constructed by calling Window::Create() 00346 and specifying the class using the WINDOW_CREATOR() macro. 00347 */ 00348 struct DialogWindow : public Window 00349 { 00350 typedef Window super; 00351 00352 DialogWindow(HWND hwnd) 00353 : super(hwnd) 00354 { 00355 register_dialog(hwnd); 00356 } 00357 00358 ~DialogWindow() 00359 { 00360 unregister_dialog(_hwnd); 00361 } 00362 }; 00363 00364 00365 /** 00366 The class Dialog implements modal dialogs. 00367 A Dialog object should be constructed by calling Dialog::DoModal() 00368 and specifying the class using the WINDOW_CREATOR() macro. 00369 */ 00370 struct Dialog : public Window 00371 { 00372 typedef Window super; 00373 00374 Dialog(HWND); 00375 ~Dialog(); 00376 00377 static int DoModal(UINT nid, CREATORFUNC creator, HWND hwndParent=0); 00378 static int DoModal(UINT nid, CREATORFUNC_INFO creator, const void* info, HWND hwndParent=0); 00379 00380 protected: 00381 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); 00382 int Command(int id, int code); 00383 }; 00384 00385 00386 #define PM_FRM_CALC_CLIENT (WM_APP+0x03) 00387 #define Frame_CalcFrameClient(hwnd, prt) ((BOOL)SNDMSG(hwnd, PM_FRM_CALC_CLIENT, 0, (LPARAM)(PRECT)prt)) 00388 00389 #define PM_JUMP_TO_URL (WM_APP+0x25) 00390 #define PM_URL_CHANGED (WM_APP+0x26) 00391 00392 00393 struct PropSheetPage : public PROPSHEETPAGE 00394 { 00395 PropSheetPage(UINT nid, Window::CREATORFUNC dlg_creator); 00396 00397 void init(struct PropertySheetDialog*); 00398 00399 protected: 00400 friend struct PropSheetPageDlg; 00401 00402 Window::CREATORFUNC _dlg_creator; 00403 }; 00404 00405 00406 /// Property Sheet dialog 00407 struct PropertySheetDialog : public PROPSHEETHEADER 00408 { 00409 PropertySheetDialog(HWND owner); 00410 00411 void add(PropSheetPage& psp); 00412 int DoModal(int start_page=0); 00413 00414 HWND GetCurrentPage(); 00415 00416 protected: 00417 typedef vector<PROPSHEETPAGE> Vector; 00418 Vector _pages; 00419 HWND _hwnd; 00420 }; 00421 00422 00423 /// Property Sheet Page (inner dialog) 00424 struct PropSheetPageDlg : public Dialog 00425 { 00426 typedef Dialog super; 00427 00428 PropSheetPageDlg(HWND); 00429 00430 protected: 00431 friend struct PropertySheetDialog; 00432 friend struct PropSheetPage; 00433 00434 static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPARAM lparam); 00435 00436 int Command(int id, int code); 00437 }; 00438 00439 00440 /* 00441 /// Property Sheet Dialog (outer dialog) 00442 struct PropertySheetDlg : public SubclassedWindow 00443 { 00444 typedef SubclassedWindow super; 00445 00446 PropertySheetDlg(HWND hwnd) : super(hwnd) {} 00447 }; 00448 */ 00449 00450 00451 // Layouting of resizable windows 00452 00453 /// Flags to specify how to move and resize controls when resizing their parent window 00454 enum RESIZE_FLAGS { 00455 MOVE_LEFT = 0x1, 00456 MOVE_RIGHT = 0x2, 00457 MOVE_TOP = 0x4, 00458 MOVE_BOTTOM = 0x8, 00459 00460 MOVE_X = MOVE_LEFT | MOVE_RIGHT, 00461 MOVE_Y = MOVE_TOP | MOVE_BOTTOM, 00462 RESIZE_X= MOVE_RIGHT, 00463 RESIZE_Y= MOVE_BOTTOM, 00464 00465 MOVE = MOVE_X | MOVE_Y, 00466 RESIZE = RESIZE_X | RESIZE_Y 00467 }; 00468 00469 /// structure to assign RESIZE_FLAGS to dialogs control 00470 struct ResizeEntry 00471 { 00472 ResizeEntry(UINT id, int flags) 00473 : _id(id), _flags(flags) {} 00474 00475 ResizeEntry(HWND hwnd, int flags) 00476 : _id(GetDlgCtrlID(hwnd)), _flags(flags) {} 00477 00478 UINT _id; 00479 int _flags; 00480 }; 00481 00482 00483 /// Management of controls in resizable dialogs 00484 struct ResizeManager : public std::list<ResizeEntry> 00485 { 00486 typedef std::list<ResizeEntry> super; 00487 00488 ResizeManager(HWND hwnd); 00489 00490 void Add(UINT id, int flags) 00491 {push_back(ResizeEntry(id, flags));} 00492 00493 void Add(HWND hwnd, int flags) 00494 {push_back(ResizeEntry(hwnd, flags));} 00495 00496 void HandleSize(int cx, int cy); 00497 void Resize(int dx, int dy); 00498 00499 void SetMinMaxInfo(LPMINMAXINFO lpmmi) 00500 { 00501 lpmmi->ptMinTrackSize.x = _min_wnd_size.cx; 00502 lpmmi->ptMinTrackSize.y = _min_wnd_size.cy; 00503 } 00504 00505 SIZE _min_wnd_size; 00506 00507 protected: 00508 HWND _hwnd; 00509 SIZE _last_size; 00510 }; 00511 00512 00513 /// Controller base template class for resizable dialogs 00514 template<typename BASE> struct ResizeController : public BASE 00515 { 00516 typedef BASE super; 00517 00518 ResizeController(HWND hwnd) 00519 : super(hwnd), 00520 _resize_mgr(hwnd) 00521 { 00522 } 00523 00524 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 00525 { 00526 switch(nmsg) { 00527 case PM_FRM_CALC_CLIENT: 00528 GetClientSpace((PRECT)lparam); 00529 return TRUE; 00530 00531 case WM_SIZE: 00532 if (wparam != SIZE_MINIMIZED) 00533 _resize_mgr.HandleSize(LOWORD(lparam), HIWORD(lparam)); 00534 goto def; 00535 00536 case WM_GETMINMAXINFO: 00537 _resize_mgr.SetMinMaxInfo((LPMINMAXINFO)lparam); 00538 goto def; 00539 00540 default: def: 00541 return super::WndProc(nmsg, wparam, lparam); 00542 } 00543 } 00544 00545 virtual void GetClientSpace(PRECT prect) 00546 { 00547 if (!IsIconic(this->_hwnd)) { 00548 GetClientRect(this->_hwnd, prect); 00549 } else { 00550 WINDOWPLACEMENT wp; 00551 GetWindowPlacement(this->_hwnd, &wp); 00552 prect->left = prect->top = 0; 00553 prect->right = wp.rcNormalPosition.right-wp.rcNormalPosition.left- 00554 2*(GetSystemMetrics(SM_CXSIZEFRAME)+GetSystemMetrics(SM_CXEDGE)); 00555 prect->bottom = wp.rcNormalPosition.bottom-wp.rcNormalPosition.top- 00556 2*(GetSystemMetrics(SM_CYSIZEFRAME)+GetSystemMetrics(SM_CYEDGE))- 00557 GetSystemMetrics(SM_CYCAPTION)-GetSystemMetrics(SM_CYMENUSIZE); 00558 } 00559 } 00560 00561 protected: 00562 ResizeManager _resize_mgr; 00563 }; 00564 00565 00566 /** 00567 This class constructs button controls. 00568 The button will remain existent when the C++ Button object is destroyed. 00569 There is no conjunction between C++ object and windows control life time. 00570 */ 00571 struct Button : public WindowHandle 00572 { 00573 Button(HWND parent, LPCTSTR text, int left, int top, int width, int height, 00574 int id, DWORD flags=WS_VISIBLE|WS_CHILD|BS_PUSHBUTTON, DWORD exStyle=0); 00575 }; 00576 00577 00578 /** 00579 This class constructs static controls. 00580 The control will remain existent when the C++ object is destroyed. 00581 There is no conjunction between C++ object and windows control life time. 00582 */ 00583 struct Static : public WindowHandle 00584 { 00585 Static(HWND parent, LPCTSTR text, int left, int top, int width, int height, 00586 int id, DWORD flags=WS_VISIBLE|WS_CHILD|SS_SIMPLE, DWORD ex_flags=0); 00587 }; 00588 00589 00590 // control color message routing for ColorStatic and HyperlinkCtrl 00591 00592 #define PM_DISPATCH_CTLCOLOR (WM_APP+0x08) 00593 00594 template<typename BASE> struct CtlColorParent : public BASE 00595 { 00596 typedef BASE super; 00597 00598 CtlColorParent(HWND hwnd) 00599 : super(hwnd) {} 00600 00601 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 00602 { 00603 switch(nmsg) { 00604 case WM_CTLCOLOR: 00605 case WM_CTLCOLORBTN: 00606 case WM_CTLCOLORDLG: 00607 case WM_CTLCOLORSCROLLBAR: 00608 case WM_CTLCOLORSTATIC: { 00609 HWND hctl = (HWND) lparam; 00610 return SendMessage(hctl, PM_DISPATCH_CTLCOLOR, wparam, nmsg); 00611 } 00612 00613 default: 00614 return super::WndProc(nmsg, wparam, lparam); 00615 } 00616 } 00617 }; 00618 00619 00620 #define PM_DISPATCH_DRAWITEM (WM_APP+0x09) 00621 00622 /// draw message routing for ColorButton and PictureButton 00623 template<typename BASE> struct OwnerDrawParent : public BASE 00624 { 00625 typedef BASE super; 00626 00627 OwnerDrawParent(HWND hwnd) 00628 : super(hwnd) {} 00629 00630 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 00631 { 00632 switch(nmsg) { 00633 case WM_DRAWITEM: 00634 if (wparam) { // should there be drawn a control? 00635 HWND hctl = GetDlgItem(this->_hwnd, wparam); 00636 00637 if (hctl) 00638 return SendMessage(hctl, PM_DISPATCH_DRAWITEM, wparam, lparam); 00639 } /*else // or is it a menu entry? 00640 ; */ 00641 00642 return 0; 00643 00644 default: 00645 return super::WndProc(nmsg, wparam, lparam); 00646 } 00647 } 00648 }; 00649 00650 00651 /** 00652 Subclass button controls to draw them by using PM_DISPATCH_DRAWITEM 00653 The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons. 00654 */ 00655 struct OwnerdrawnButton : public SubclassedWindow 00656 { 00657 typedef SubclassedWindow super; 00658 00659 OwnerdrawnButton(HWND hwnd) 00660 : super(hwnd) {} 00661 00662 protected: 00663 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); 00664 00665 virtual void DrawItem(LPDRAWITEMSTRUCT dis) = 0; 00666 }; 00667 00668 extern void DrawGrayText(HDC hdc, LPRECT pRect, LPCTSTR text, int dt_flags); 00669 00670 00671 /** 00672 Subclass button controls to paint colored text labels. 00673 The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons. 00674 */ 00675 /* not yet used 00676 struct ColorButton : public OwnerdrawnButton 00677 { 00678 typedef OwnerdrawnButton super; 00679 00680 ColorButton(HWND hwnd, COLORREF textColor) 00681 : super(hwnd), _textColor(textColor) {} 00682 00683 protected: 00684 virtual void DrawItem(LPDRAWITEMSTRUCT dis); 00685 00686 COLORREF _textColor; 00687 }; 00688 */ 00689 00690 00691 struct FlatButton : public OwnerdrawnButton 00692 { 00693 typedef OwnerdrawnButton super; 00694 00695 FlatButton(HWND hwnd) 00696 : super(hwnd), _active(false) {} 00697 00698 FlatButton(HWND owner, int id) 00699 : super(GetDlgItem(owner, IDOK)), _active(false) {} 00700 00701 protected: 00702 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); 00703 virtual void DrawItem(LPDRAWITEMSTRUCT dis); 00704 00705 COLORREF _textColor; 00706 COLORREF _activeColor; 00707 bool _active; 00708 }; 00709 00710 00711 /** 00712 Subclass button controls to paint pictures left to the labels. 00713 The buttons should have set the style bit BS_OWNERDRAW. 00714 The owning window should use the OwnerDrawParent template to route owner draw messages to the buttons. 00715 */ 00716 struct PictureButton : public OwnerdrawnButton 00717 { 00718 typedef OwnerdrawnButton super; 00719 00720 PictureButton(HWND hwnd, HICON hIcon, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false) 00721 : super(hwnd), _hIcon(hIcon), _hBmp(0), _hBrush(hbrush), _flat(flat) 00722 { 00723 _cx = 16; 00724 _cy = 16; 00725 } 00726 00727 PictureButton(HWND hparent, int id, HICON hIcon, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false) 00728 : super(GetDlgItem(hparent, id)), _hIcon(hIcon), _hBmp(0), _hBrush(hbrush), _flat(flat) 00729 { 00730 _cx = 16; 00731 _cy = 16; 00732 } 00733 00734 PictureButton(HWND hwnd, HBITMAP hBmp, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false) 00735 : super(hwnd), _hIcon(0), _hBmp(hBmp), _hBrush(hbrush), _flat(flat) 00736 { 00737 BITMAP bmp; 00738 GetObject(hBmp, sizeof(bmp), &bmp); 00739 _cx = bmp.bmWidth; 00740 _cy = bmp.bmHeight; 00741 } 00742 00743 PictureButton(HWND hparent, int id, HBITMAP hBmp, HBRUSH hbrush=GetSysColorBrush(COLOR_BTNFACE), bool flat=false) 00744 : super(GetDlgItem(hparent, id)), _hIcon(0), _hBmp(hBmp), _hBrush(hbrush), _flat(flat) 00745 { 00746 BITMAP bmp; 00747 GetObject(hBmp, sizeof(bmp), &bmp); 00748 _cx = bmp.bmWidth; 00749 _cy = bmp.bmHeight; 00750 } 00751 00752 protected: 00753 virtual void DrawItem(LPDRAWITEMSTRUCT dis); 00754 00755 HICON _hIcon; 00756 HBITMAP _hBmp; 00757 HBRUSH _hBrush; 00758 00759 int _cx; 00760 int _cy; 00761 00762 bool _flat; 00763 }; 00764 00765 00766 struct ColorStatic : public SubclassedWindow 00767 { 00768 typedef SubclassedWindow super; 00769 00770 ColorStatic(HWND hwnd, COLORREF textColor=RGB(255,0,0), HBRUSH hbrush_bkgnd=0, HFONT hfont=0) 00771 : super(hwnd), 00772 _textColor(textColor), 00773 _hbrush_bkgnd(hbrush_bkgnd), 00774 _hfont(hfont) 00775 { 00776 } 00777 00778 ColorStatic(HWND owner, int id, COLORREF textColor=RGB(255,0,0), HBRUSH hbrush_bkgnd=0, HFONT hfont=0) 00779 : super(GetDlgItem(owner, id)), 00780 _textColor(textColor), 00781 _hbrush_bkgnd(hbrush_bkgnd), 00782 _hfont(hfont) 00783 { 00784 } 00785 00786 protected: 00787 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 00788 { 00789 if (nmsg == PM_DISPATCH_CTLCOLOR) { 00790 HDC hdc = (HDC) wparam; 00791 00792 SetTextColor(hdc, _textColor); 00793 00794 if (_hfont) 00795 SelectFont(hdc, _hfont); 00796 00797 if (_hbrush_bkgnd) 00798 return (LRESULT)_hbrush_bkgnd; 00799 else { 00800 SetBkMode(hdc, TRANSPARENT); 00801 return (LRESULT)GetStockBrush(HOLLOW_BRUSH); 00802 } 00803 } else 00804 return super::WndProc(nmsg, wparam, lparam); 00805 } 00806 00807 COLORREF _textColor; 00808 HBRUSH _hbrush_bkgnd; 00809 HFONT _hfont; 00810 }; 00811 00812 00813 /// Hyperlink Controls 00814 00815 struct HyperlinkCtrl : public SubclassedWindow 00816 { 00817 typedef SubclassedWindow super; 00818 00819 HyperlinkCtrl(HWND hwnd, COLORREF colorLink=RGB(0,0,255), COLORREF colorVisited=RGB(128,0,128)); 00820 HyperlinkCtrl(HWND owner, int id, COLORREF colorLink=RGB(0,0,255), COLORREF colorVisited=RGB(128,0,128)); 00821 00822 ~HyperlinkCtrl(); 00823 00824 String _cmd; 00825 00826 protected: 00827 COLORREF _textColor; 00828 COLORREF _colorVisited; 00829 HFONT _hfont; 00830 HCURSOR _crsr_link; 00831 00832 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam); 00833 00834 void init(); 00835 00836 bool LaunchLink() 00837 { 00838 if (!_cmd.empty()) { 00839 HINSTANCE hinst = ShellExecute(GetParent(_hwnd), _T("open"), _cmd, 0, 0, SW_SHOWNORMAL); 00840 return (int)hinst > HINSTANCE_ERROR; 00841 } 00842 00843 return true; 00844 } 00845 }; 00846 00847 00848 /// encapsulation of tool tip controls 00849 struct ToolTip : public WindowHandle 00850 { 00851 typedef WindowHandle super; 00852 00853 ToolTip(HWND owner); 00854 00855 void activate(BOOL active=TRUE) 00856 { 00857 SendMessage(_hwnd, TTM_ACTIVATE, active, 0); 00858 } 00859 00860 void add(HWND hparent, HWND htool, LPCTSTR txt=LPSTR_TEXTCALLBACK, LPARAM lparam=0) 00861 { 00862 TOOLINFO ti = { 00863 sizeof(TOOLINFO), TTF_SUBCLASS|TTF_IDISHWND|TTF_TRANSPARENT, hparent, (UINT)htool, 00864 {0,0,0,0}, 0, (LPTSTR)txt, lparam 00865 }; 00866 00867 #ifdef UNICODE ///@todo Why is it neccesary to try both TTM_ADDTOOLW and TTM_ADDTOOLW ?! 00868 if (!SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti)) 00869 SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti); 00870 #else 00871 if (!SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti)) 00872 SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti); 00873 #endif 00874 } 00875 00876 void add(HWND hparent, UINT id, const RECT& rect, LPCTSTR txt=LPSTR_TEXTCALLBACK, LPARAM lparam=0) 00877 { 00878 TOOLINFO ti = { 00879 sizeof(TOOLINFO), TTF_SUBCLASS|TTF_TRANSPARENT, hparent, id, 00880 {rect.left,rect.top,rect.right,rect.bottom}, 0, (LPTSTR)txt, lparam 00881 }; 00882 00883 #ifdef UNICODE 00884 if (!SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti)) 00885 SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti); 00886 #else 00887 if (!SendMessage(_hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti)) 00888 SendMessage(_hwnd, TTM_ADDTOOLW, 0, (LPARAM)&ti); 00889 #endif 00890 } 00891 00892 void remove(HWND hparent, HWND htool) 00893 { 00894 TOOLINFO ti = { 00895 sizeof(TOOLINFO), TTF_IDISHWND, hparent, (UINT)htool, 00896 {0,0,0,0}, 0, 0, 0 00897 }; 00898 00899 SendMessage(_hwnd, TTM_DELTOOL, 0, (LPARAM)&ti); 00900 } 00901 00902 void remove(HWND hparent, UINT id) 00903 { 00904 TOOLINFO ti = { 00905 sizeof(TOOLINFO), 0, hparent, id, 00906 {0,0,0,0}, 0, 0, 0 00907 }; 00908 00909 SendMessage(_hwnd, TTM_DELTOOL, 0, (LPARAM)&ti); 00910 } 00911 }; 00912 00913 00914 inline int ListView_GetItemData(HWND list_ctrl, int idx) 00915 { 00916 LV_ITEM item; 00917 00918 item.mask = LVIF_PARAM; 00919 item.iItem = idx; 00920 00921 if (!ListView_GetItem(list_ctrl, &item)) 00922 return 0; 00923 00924 return item.lParam; 00925 } 00926 00927 inline int ListView_FindItemPara(HWND list_ctrl, LPARAM param) 00928 { 00929 LVFINDINFO fi; 00930 00931 fi.flags = LVFI_PARAM; 00932 fi.lParam = param; 00933 00934 return ListView_FindItem(list_ctrl, (unsigned)-1, &fi); 00935 } 00936 00937 inline int ListView_GetFocusedItem(HWND list_ctrl) 00938 { 00939 int idx = ListView_GetItemCount(list_ctrl); 00940 00941 while(--idx >= 0) 00942 if (ListView_GetItemState(list_ctrl, idx, LVIS_FOCUSED)) 00943 break; 00944 00945 return idx; 00946 } 00947 00948 00949 /// sorting of list controls 00950 struct ListSort : public WindowHandle 00951 { 00952 ListSort(HWND hwndListview, PFNLVCOMPARE compare_fct); 00953 00954 void toggle_sort(int idx); 00955 void sort(); 00956 00957 int _sort_crit; 00958 bool _direction; 00959 00960 protected: 00961 PFNLVCOMPARE _compare_fct; 00962 00963 static int CALLBACK CompareFunc(LPARAM lparam1, LPARAM lparam2, LPARAM lparamSort); 00964 }; 00965 00966 00967 inline LPARAM TreeView_GetItemData(HWND hwndTreeView, HTREEITEM hItem) 00968 { 00969 TVITEM tvItem; 00970 00971 tvItem.mask = TVIF_PARAM; 00972 tvItem.hItem = hItem; 00973 00974 if (!TreeView_GetItem(hwndTreeView, &tvItem)) 00975 return 0; 00976 00977 return tvItem.lParam; 00978 } 00979 00980 00981 enum {TRAYBUTTON_LEFT=0, TRAYBUTTON_RIGHT, TRAYBUTTON_MIDDLE}; 00982 00983 #define PM_TRAYICON (WM_APP+0x20) 00984 00985 #define WINMSG_TASKBARCREATED TEXT("TaskbarCreated") 00986 00987 #define WINMSG_SHELLHOOK TEXT("SHELLHOOK") 00988 00989 00990 struct TrayIcon 00991 { 00992 TrayIcon(HWND hparent, UINT id) 00993 : _hparent(hparent), _id(id) {} 00994 00995 ~TrayIcon() 00996 {Remove();} 00997 00998 void Add(HICON hIcon, LPCTSTR tooltip=NULL) 00999 {Set(NIM_ADD, _id, hIcon, tooltip);} 01000 01001 void Modify(HICON hIcon, LPCTSTR tooltip=NULL) 01002 {Set(NIM_MODIFY, _id, hIcon, tooltip);} 01003 01004 void Remove() 01005 { 01006 NOTIFYICONDATA nid = { 01007 sizeof(NOTIFYICONDATA), // cbSize 01008 _hparent, // hWnd 01009 _id, // uID 01010 }; 01011 01012 Shell_NotifyIcon(NIM_DELETE, &nid); 01013 } 01014 01015 protected: 01016 HWND _hparent; 01017 UINT _id; 01018 01019 void Set(DWORD dwMessage, UINT id, HICON hIcon, LPCTSTR tooltip=NULL) 01020 { 01021 NOTIFYICONDATA nid = { 01022 sizeof(NOTIFYICONDATA), // cbSize 01023 _hparent, // hWnd 01024 id, // uID 01025 NIF_MESSAGE|NIF_ICON, // uFlags 01026 PM_TRAYICON, // uCallbackMessage 01027 hIcon // hIcon 01028 }; 01029 01030 if (tooltip) 01031 lstrcpyn(nid.szTip, tooltip, COUNTOF(nid.szTip)); 01032 01033 if (nid.szTip[0]) 01034 nid.uFlags |= NIF_TIP; 01035 01036 Shell_NotifyIcon(dwMessage, &nid); 01037 } 01038 }; 01039 01040 01041 template<typename BASE> struct TrayIconControllerTemplate : public BASE 01042 { 01043 typedef BASE super; 01044 01045 TrayIconControllerTemplate(HWND hwnd) : BASE(hwnd), 01046 WM_TASKBARCREATED(RegisterWindowMessage(WINMSG_TASKBARCREATED)) 01047 { 01048 } 01049 01050 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 01051 { 01052 if (nmsg == PM_TRAYICON) { 01053 switch(lparam) { 01054 case WM_MOUSEMOVE: 01055 TrayMouseOver(wparam); 01056 break; 01057 01058 case WM_LBUTTONDOWN: 01059 TrayClick(wparam, TRAYBUTTON_LEFT); 01060 break; 01061 01062 case WM_LBUTTONDBLCLK: 01063 TrayDblClick(wparam, TRAYBUTTON_LEFT); 01064 break; 01065 01066 case WM_RBUTTONDOWN: 01067 TrayClick(wparam, TRAYBUTTON_RIGHT); 01068 break; 01069 01070 case WM_RBUTTONDBLCLK: 01071 TrayDblClick(wparam, TRAYBUTTON_RIGHT); 01072 break; 01073 01074 case WM_MBUTTONDOWN: 01075 TrayClick(wparam, TRAYBUTTON_MIDDLE); 01076 break; 01077 01078 case WM_MBUTTONDBLCLK: 01079 TrayDblClick(wparam, TRAYBUTTON_MIDDLE); 01080 break; 01081 } 01082 01083 return 0; 01084 } else if (nmsg == WM_TASKBARCREATED) { 01085 AddTrayIcons(); 01086 return 0; 01087 } else 01088 return super::WndProc(nmsg, wparam, lparam); 01089 } 01090 01091 virtual void AddTrayIcons() = 0; 01092 virtual void TrayMouseOver(UINT id) {} 01093 virtual void TrayClick(UINT id, int btn) {} 01094 virtual void TrayDblClick(UINT id, int btn) {} 01095 01096 protected: 01097 const UINT WM_TASKBARCREATED; 01098 }; 01099 01100 01101 struct EditController : public SubclassedWindow 01102 { 01103 typedef SubclassedWindow super; 01104 01105 EditController(HWND hwnd) 01106 : super(hwnd) 01107 { 01108 } 01109 01110 protected: 01111 LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam) 01112 { 01113 if (nmsg==WM_KEYDOWN && wparam==VK_RETURN) { 01114 SendParent(WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(_hwnd),1), (LPARAM)_hwnd); 01115 return 0; 01116 } else 01117 return super::WndProc(nmsg, wparam, lparam); 01118 } 01119 };
ROS Explorer Source Code Documentation
generated on 02.01.2013 by ![]() |