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