window.h

Go to the documentation of this file.
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 doxygen

ROS Explorer Homepage