#ifndef __VWINDOW_HPP #define __VWINDOW_HPP #ifndef VWCL_WRAP_WINDOWS_ONLY #include "vApplication.hpp" #endif #include "vRTTI.hpp" #include class VWindow; typedef struct tagVWCL_ENUM_PARAM { UINT nMessageOrID; LPVOID lpInData; // Normally input pointer LPVOID lpOutData; // Normally output pointer } VWCL_ENUM_PARAM; // VDOC> class VWindow : public VRTTI { #ifndef VWCL_WRAP_WINDOWS_ONLY friend class VApplication; #endif public: VWindow(UINT nRTTI = VWCL_RTTI_WINDOW) : VRTTI(nRTTI) { m_hWindow = NULL; #ifndef VWCL_WRAP_WINDOWS_ONLY m_lpfnOldWndProc = NULL; #endif } virtual ~VWindow() { #ifndef VWCL_WRAP_WINDOWS_ONLY DestroyWindow(); #endif } // Returns HWND operator HWND () { return GetSafeWindow(); } #ifndef VWCL_WRAP_WINDOWS_ONLY // Attach an existing Windows window to a VWindow object, subclassing it routing messages through the object BOOL Attach(HWND hWnd); #else // Simply assign hWnd to this object, but do not subclass it HWND Attach(HWND hWnd) { assert(hWnd && ::IsWindow(hWnd)); m_hWindow = hWnd; return m_hWindow; } #endif // Center a window on screen void CenterWindow() { assert(GetSafeWindow()); // Center a window on screen RECT r; GetWindowRect(&r); SetWindowPos( m_hWindow, HWND_TOP, ((GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left)) / 2), ((GetSystemMetrics(SM_CYSCREEN) - (r.bottom - r.top)) / 2), 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); } void CheckDlgButton(int nID, UINT nCheck = BST_CHECKED) { assert(GetSafeWindow()); ::CheckDlgButton(m_hWindow, nID, nCheck); } BOOL ClientToScreen(LPPOINT lpPoint) { assert(GetSafeWindow() && lpPoint); return ::ClientToScreen(m_hWindow, lpPoint); } #ifndef VWCL_WRAP_WINDOWS_ONLY // Lowest common denominator of window creation functions BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, LPRECT lpRect, HWND hWndParent, UINT nIDorMenu, BOOL bDontCallPostCreateWindow = FALSE); #endif virtual BOOL DestroyWindow() { if ( GetSafeWindow() ) return ::DestroyWindow(m_hWindow); return FALSE; } #ifndef VWCL_WRAP_WINDOWS_ONLY // Detach an existing Windows window with an associated VWindow object, removing any subclassing, and restore to previous state void Detach(); #else // Simply remove the window handle from object void Detach() { m_hWindow = NULL; } #endif BOOL EnableWindow(BOOL bEnable = TRUE) { assert(GetSafeWindow()); return ::EnableWindow(m_hWindow, bEnable); } #ifndef VWCL_WRAP_WINDOWS_ONLY // Enter a message loop WPARAM EnterMessageLoop(HACCEL hAccel) { MSG msg; // Enter message loop while ( GetMessage(&msg, NULL, 0, 0) != 0 ) { if ( hAccel == NULL || hAccel && TranslateAccelerator(m_hWindow, hAccel, &msg) == 0 ) HandleMessage(&msg); } return msg.wParam; } #endif // Find a child window when the class is known HWND FindChildWindowByClass(LPCTSTR lpszClass) { assert(lpszClass && lstrlen(lpszClass)); // Iterate child windows VWCL_ENUM_PARAM EnumParam = {ENUM_FIND_CHILD_BY_CLASS, (LPVOID)lpszClass, NULL}; EnumChildWindows(m_hWindow, (WNDENUMPROC)EnumChildWndProc, (LPARAM)&EnumParam); // EnumParam.lpOutData will be non-NULL if a handle was found if ( EnumParam.lpOutData ) return (HWND)EnumParam.lpOutData; return NULL; } HWND GetDlgItem(int nID) { assert(GetSafeWindow()); return ::GetDlgItem(m_hWindow, nID); } UINT GetDlgItemInt(int nID, LPBOOL lpTranslated = NULL, BOOL bSigned = FALSE) { assert(GetSafeWindow()); return ::GetDlgItemInt(m_hWindow, nID, lpTranslated, bSigned); } int GetDlgItemText(int nID, LPTSTR lpszBuffer, int nSizeOfBuffer) { assert(GetSafeWindow()); return ::GetDlgItemText(m_hWindow, nID, lpszBuffer, nSizeOfBuffer); } HFONT GetFont() { assert(GetSafeWindow()); return (HFONT)::SendMessage(m_hWindow, WM_GETFONT, 0, 0); } HMENU GetMenu() { assert(GetSafeWindow()); return ::GetMenu(m_hWindow); } HWND GetParent() { assert(GetSafeWindow()); return ::GetParent(m_hWindow); } HWND GetSafeWindow() { return (IsWindow()) ? m_hWindow : NULL; } LONG GetStyle() { return GetWindowLong(GWL_STYLE); } LONG GetWindowLong(int nIndex) { assert(GetSafeWindow()); return ::GetWindowLong(m_hWindow, nIndex); } #ifdef WIN32 BOOL GetClientRect(LPRECT lpRect) { assert(lpRect && GetSafeWindow()); return ::GetClientRect(m_hWindow, lpRect); } BOOL GetWindowRect(LPRECT lpRect) { assert(lpRect && GetSafeWindow()); return ::GetWindowRect(m_hWindow, lpRect); } #else void GetClientRect(LPRECT lpRect) { assert(lpRect && GetSafeWindow()); ::GetClientRect(m_hWindow, lpRect); } void GetWindowRect(LPRECT lpRect) { assert(lpRect && GetSafeWindow()); ::GetWindowRect(m_hWindow, lpRect); } #endif #ifndef VWCL_WRAP_WINDOWS_ONLY // Called from a VWindow class that implements a message loop virtual void HandleMessage(LPMSG lpMsg) { assert(lpMsg); // Called from a VWindow derived class that implements a message loop if ( !PreTranslateMessage(lpMsg) ) { TranslateMessage(lpMsg); DispatchMessage(lpMsg); } } #endif void InvalidateRect(LPRECT lpRect = NULL, BOOL bErase = TRUE) { assert(GetSafeWindow()); ::InvalidateRect(m_hWindow, lpRect, bErase); } // Return TRUE if the object is a VDialog type (That is, a VDialogXXX class, not all VDialog derivitives) BOOL IsVDialogType() { switch ( RTTI() ) { // Top level window is a dialog case VWindow::VWCL_RTTI_DIALOG: case VWindow::VWCL_RTTI_MAIN_DIALOG: case VWindow::VWCL_RTTI_SPLIT_MAIN_DIALOG: case VWindow::VWCL_RTTI_SPLIT_DIALOG: return TRUE; } return FALSE; } UINT IsDlgButtonChecked(int nID) { assert(GetSafeWindow()); return ::IsDlgButtonChecked(m_hWindow, nID); } BOOL IsIconic() { assert(GetSafeWindow()); return ::IsIconic(m_hWindow); } BOOL IsWindow() { return (m_hWindow) ? ::IsWindow(m_hWindow) : FALSE; } BOOL IsWindowEnabled() { assert(GetSafeWindow()); return ::IsWindowEnabled(m_hWindow); } BOOL IsWindowVisible() { assert(GetSafeWindow()); return ::IsWindowVisible(m_hWindow); } int MessageBox(LPCTSTR lpcszText, LPCTSTR lpcszCaption, UINT nType = MB_OK) { int nResult; HWND hWndFocus = GetFocus(); nResult = ::MessageBox(m_hWindow, lpcszText, lpcszCaption, nType); if ( hWndFocus ) ::SetFocus(hWndFocus); return nResult; } int MessageBox(LPCTSTR lpcszText, UINT nType = MB_OK) { return MessageBox(lpcszText, VGetAppTitle(), nType); } // If VString.hpp is included, implement these functions #ifdef __VSTRING_HPP int MessageBox(UINT nStringID, UINT nType = MB_OK, HINSTANCE hResource = NULL) { return MessageBox(VString(nStringID, hResource), nType); } int MessageBox(UINT nStringID, LPCTSTR lpcszCaption, UINT nType = MB_OK, HINSTANCE hResource = NULL) { return MessageBox(VString(nStringID, hResource), lpcszCaption, nType); } int MessageBox(UINT nStringID, UINT nCaptionID, UINT nType, HINSTANCE hResource = NULL) { return MessageBox(VString(nStringID, hResource), VString(nCaptionID, hResource), nType); } #endif BOOL MoveWindow(int x, int y, int cx, int cy, BOOL bRedraw = TRUE) { assert(GetSafeWindow()); return ::MoveWindow(m_hWindow, x, y, cx, cy, bRedraw); } BOOL MoveWindow(LPRECT lpRect, BOOL bRedraw = TRUE) { assert(lpRect); assert(GetSafeWindow()); return ::MoveWindow(m_hWindow, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, bRedraw); } BOOL PostMessage(UINT nMessage, WPARAM wParam, LPARAM lParam) { assert(GetSafeWindow()); return ::PostMessage(m_hWindow, nMessage, wParam, lParam); } // Override to allow user to call IsDialogMessage() or perform other // processing before message is dispatched. Return TRUE if message was processed virtual BOOL PreTranslateMessage(LPMSG lpMsg) { return FALSE; } BOOL ReleaseCapture() { assert(GetSafeWindow()); return ::ReleaseCapture(); } BOOL ScreenToClient(LPPOINT lpPoint) { assert(GetSafeWindow() && lpPoint); return ::ScreenToClient(m_hWindow, lpPoint); } LRESULT SendDlgItemMessage(UINT nID, UINT nMessage, WPARAM wParam, LPARAM lParam) { assert(GetSafeWindow()); return ::SendDlgItemMessage(m_hWindow, nID, nMessage, wParam, lParam); } LRESULT SendMessage(UINT nMessage, WPARAM wParam, LPARAM lParam) { assert(GetSafeWindow()); return ::SendMessage(m_hWindow, nMessage, wParam, lParam); } HWND SetCapture() { assert(GetSafeWindow()); return ::SetCapture(m_hWindow); } BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = FALSE) { assert(GetSafeWindow()); return ::SetDlgItemInt(m_hWindow, nID, nValue, bSigned); } #ifdef WIN32 BOOL SetDlgItemText(int nID, LPCTSTR lpszText) { assert(GetSafeWindow()); return ::SetDlgItemText(m_hWindow, nID, lpszText); } #else void SetDlgItemText(int nID, LPCTSTR lpszText) { assert(GetSafeWindow()); ::SetDlgItemText(m_hWindow, nID, lpszText); } #endif HWND SetFocus() { assert(GetSafeWindow()); return ::SetFocus(m_hWindow); } BOOL SetMenu(HMENU hMenu) { assert(GetSafeWindow()); return ::SetMenu(m_hWindow, hMenu); } LONG SetStyle(DWORD dwStyle) { return SetWindowLong(GWL_STYLE, dwStyle); } LONG SetWindowLong(int nIndex, LONG nNewLong) { assert(GetSafeWindow()); return ::SetWindowLong(m_hWindow, nIndex, nNewLong); } #if defined(_WIN64) LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR nNewLongPtr) { assert(GetSafeWindow()); return ::SetWindowLongPtr(m_hWindow, nIndex, nNewLongPtr); } #endif #ifdef WIN32 BOOL SetWindowText(LPCTSTR lpszText) { assert(GetSafeWindow()); return ::SetWindowText(m_hWindow, lpszText); } #else void SetWindowText(LPCTSTR lpszText) { assert(GetSafeWindow()); ::SetWindowText(m_hWindow, lpszText); } #endif BOOL ShowWindow(int nCmdShow = SW_SHOWNORMAL) { assert(GetSafeWindow()); return ::ShowWindow(m_hWindow, nCmdShow); } #ifdef WIN32 BOOL UpdateWindow() { assert(GetSafeWindow()); return ::UpdateWindow(m_hWindow); } #else void UpdateWindow() { assert(GetSafeWindow()); ::UpdateWindow(m_hWindow); } #endif #ifndef VWCL_WRAP_WINDOWS_ONLY // Window procedure virtual LRESULT WindowProc(HWND hWnd, UINT nMessage, WPARAM wParam, LPARAM lParam); #endif // Fast Runtime Type Information supported on ALL compilers // Implemented int VRTTI base class for VWindow and derived classes enum { VWCL_RTTI_UNKNOWN, VWCL_RTTI_BUTTON, VWCL_RTTI_CHECKBOX, VWCL_RTTI_COMBOBOX, VWCL_RTTI_DIALOG, VWCL_RTTI_EDIT, VWCL_RTTI_GROUPBOX, VWCL_RTTI_LISTBOX, VWCL_RTTI_LISTVIEW_CTRL, VWCL_RTTI_MAIN_DIALOG, VWCL_RTTI_MAIN_WINDOW, VWCL_RTTI_PAGE_SETUP_DIALOG, VWCL_RTTI_PRINT_DIALOG, VWCL_RTTI_PRINT_SETUP_DIALOG, VWCL_RTTI_RADIO_BUTTON, VWCL_RTTI_SCROLLBAR, VWCL_RTTI_SPLASH_WINDOW, VWCL_RTTI_SPLIT_MAIN_DIALOG, VWCL_RTTI_SPLIT_MAIN_WINDOW, VWCL_RTTI_SPLIT_WINDOW, VWCL_RTTI_SS_TREE_CTRL, VWCL_RTTI_STATIC, VWCL_RTTI_STATUSBAR_CTRL, VWCL_RTTI_TAB_CTRL, VWCL_RTTI_TAB_CTRL_WINDOW, VWCL_RTTI_TOOLBAR_CTRL, VWCL_RTTI_TREE_CTRL, VWCL_RTTI_WINDOW, VWCL_RTTI_SPLIT_DIALOG, VWCL_RTTI_SHELL_TAB_WINDOW, VWCL_RTTI_MINI_WINDOW, VWCL_RTTI_DIRECTORY_TREE_CTRL, VWCL_RTTI_XTREE_CTRL, VWCL_RTTI_XEDIT, VWCL_RTTI_SS_INDEXED_TREE_CTRL, VWCL_RTTI_PROPERTY_SHEET, VWCL_RTTI_PROPERTY_PAGE, VWCL_RTTI_PROGRESS_CTRL, }; // Handle this object encapsulates HWND m_hWindow; #ifndef VWCL_WRAP_WINDOWS_ONLY // For subclased windows, the old Window Procedure WNDPROC m_lpfnOldWndProc; #endif // Enumeration is VWLC_ENUM_PARAM::nMessageOrID in EnumChildWndProc() call enum { ENUM_FIND_CHILD_BY_CLASS = WM_USER + 4096, }; protected: // Enumerate child windows (for various reasons). LPARAM is a pointer to a VWLC_ENUM_PARAM struct static BOOL CALLBACK EnumChildWndProc(HWND hWnd, LPARAM lParam) { VWCL_ENUM_PARAM* pEnumParam = (VWCL_ENUM_PARAM*)lParam; assert(pEnumParam); // Determine what we need to do switch ( pEnumParam->nMessageOrID ) { case WM_DESTROY: ::DestroyWindow(hWnd); break; case ENUM_FIND_CHILD_BY_CLASS: { // pEnumParam->lpInData is a string LPCTSTR lpszFind = (LPCTSTR)pEnumParam->lpInData; assert(lpszFind && lstrlen(lpszFind)); // Get the class of this window TCHAR szClass[50]; ::GetClassName(hWnd, szClass, sizeof(szClass)/sizeof(TCHAR)); // Did we find a hit? if ( lstrcmpi(szClass, lpszFind) == 0 ) { // Set the hWnd into the pEnumParam->lpOutData field and quit pEnumParam->lpOutData = hWnd; return FALSE; } break; } } return TRUE; } #ifndef VWCL_WRAP_WINDOWS_ONLY // Handler for WM_CLOSE. Default implementation calls DestroyWindow() virtual void OnClose() { DestroyWindow(); } // Handler for WM_COMMAND. Return 0 if message was handled virtual int OnCommand(WORD wNotifyCode, WORD wID, HWND hWndControl) { return 1; } // Handler for WM_CREATE. Return 0 if message was handled, -1 to stop window creation virtual int OnCreate(LPCREATESTRUCT lpCreateStruct) { return 1; } // Handler for WM_DESTROY. Return 0 if message was handled virtual int OnDestroy() { return 1; } // Handler for WM_PAINT. Return 0 if message was handled virtual int OnPaint() { return 1; } // Handler for WM_SIZE. Return 0 if message was handled virtual int OnSize(WPARAM wFlags, int cx, int cy) { return 1; } // Handler for WM_NOTIFY. Return 0 if message was handled virtual LRESULT OnNotify(int nIDControl, LPNMHDR lpNMHDR) { return 1; } // Support for reflected WM_NOTIFY messages. Derived class must // return 0 is message was handled, -1 if handled and parent should // NOT be notified, or 1 if message was not handled and parent should // be notified. If -1 if returned, derived classes must also set // the lCommonControlResult to the return value expected by the common control virtual int OnReflectedNotify(LPNMHDR lpNMHDR, LPARAM& lCommonControlResult) { return 1; } // Called after Attach() returns successfully virtual void PostAttachWindow() {;} // Called after Create() returns successfully. Returning FALSE from // this override will cause the window to be destroyed virtual BOOL PostCreateWindow() { return TRUE;} // Called after WM_DESTROY completes. Safe to do a delete this on VWindow object virtual void PostNcDestroy() {;} // Custom virtual functions for common overrides and default returns virtual BOOL PreCreateWindow(LPCREATESTRUCT lpCreateStruct) { return TRUE; } #endif }; #endif // __VWINDOW_HPP