// This is a part of the Active Template Library. // Copyright (C) 1996-1997 Microsoft Corporation // All rights reserved. // // This source code is only intended as a supplement to the // Active Template Library Reference and related // electronic documentation provided with the library. // See these sources for detailed information regarding the // Active Template Library product. #ifndef __ATLWIN_H__ #define __ATLWIN_H__ #ifndef __cplusplus #error ATL requires C++ compilation (use a .cpp suffix) #endif #ifndef __ATLBASE_H__ #error atlwin.h requires atlbase.h to be included first #endif #ifndef WS_EX_NOINHERITLAYOUT #define WS_EX_NOINHERITLAYOUT 0x00100000L // Disable inheritence of mirroring by children #endif #ifndef WS_EX_LAYOUTRTL #define WS_EX_LAYOUTRTL 0x00400000L // Right to left mirroring #endif #ifndef NOMIRRORBITMAP #define NOMIRRORBITMAP (DWORD)0x80000000 // Do not Mirror the bitmap in this call #endif #ifndef LAYOUT_RTL #define LAYOUT_RTL 0x00000001 // Right to left #endif #ifndef LAYOUT_BTT #define LAYOUT_BTT 0x00000002 // Bottom to top #endif #ifndef LAYOUT_VBH #define LAYOUT_VBH 0x00000004 // Vertical before horizontal #endif #ifndef LAYOUT_ORIENTATIONMASK #define LAYOUT_ORIENTATIONMASK LAYOUT_RTL | LAYOUT_BTT | LAYOUT_VBH #endif #ifndef LAYOUT_BITMAPORIENTATIONPRESERVED #define LAYOUT_BITMAPORIENTATIONPRESERVED 0x00000008 #endif #ifdef SubclassWindow #pragma push_macro( "SubclassWindow" ) #define _ATL_REDEF_SUBCLASSWINDOW #undef SubclassWindow #endif #ifndef ATL_NO_NAMESPACE namespace ATL { #endif ///////////////////////////////////////////////////////////////////////////// // Forward declarations class CWindow; class CMessageMap; class CDynamicChain; class CWndClassInfo; template class CWindowImpl; template class CDialogImpl; class CContainedWindow; ///////////////////////////////////////////////////////////////////////////// // CWindow - client side for a Windows window class CWindow { public: HWND m_hWnd; CWindow(HWND hWnd = NULL) { m_hWnd = hWnd; } CWindow& operator=(HWND hWnd) { m_hWnd = hWnd; return *this; } void Attach(HWND hWndNew) { _ASSERTE(::IsWindow(hWndNew)); m_hWnd = hWndNew; } HWND Detach() { HWND hWnd = m_hWnd; m_hWnd = NULL; return hWnd; } BOOL DestroyWindow() { _ASSERTE(::IsWindow(m_hWnd)); if(!::DestroyWindow(m_hWnd)) return FALSE; m_hWnd = NULL; return TRUE; } // Attributes operator HWND() const { return m_hWnd; } DWORD GetStyle() const { _ASSERTE(::IsWindow(m_hWnd)); return (DWORD)::GetWindowLong(m_hWnd, GWL_STYLE); } DWORD GetExStyle() const { _ASSERTE(::IsWindow(m_hWnd)); return (DWORD)::GetWindowLong(m_hWnd, GWL_EXSTYLE); } BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0); BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0); LONG GetWindowLong(int nIndex) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetWindowLong(m_hWnd, nIndex); } LONG SetWindowLong(int nIndex, LONG dwNewLong) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetWindowLong(m_hWnd, nIndex, dwNewLong); } WORD GetWindowWord(int nIndex) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetWindowWord(m_hWnd, nIndex); } WORD SetWindowWord(int nIndex, WORD wNewWord) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetWindowWord(m_hWnd, nIndex, wNewWord); } // Message Functions LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { _ASSERTE(::IsWindow(m_hWnd)); return ::SendMessage(m_hWnd,message,wParam,lParam); } BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { _ASSERTE(::IsWindow(m_hWnd)); return ::PostMessage(m_hWnd,message,wParam,lParam); } BOOL SendNotifyMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { _ASSERTE(::IsWindow(m_hWnd)); return ::SendNotifyMessage(m_hWnd, message, wParam, lParam); } // Window Text Functions BOOL SetWindowText(LPCTSTR lpszString) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetWindowText(m_hWnd, lpszString); } int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount); } int GetWindowTextLength() const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetWindowTextLength(m_hWnd); } BOOL GetWindowText(BSTR& bstrText); // Font Functions void SetFont(HFONT hFont, BOOL bRedraw = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0)); } HFONT GetFont() const { _ASSERTE(::IsWindow(m_hWnd)); return (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0); } // Menu Functions (non-child windows only) #if defined(_WINUSER_) && !defined(NOMENUS) HMENU GetMenu() const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetMenu(m_hWnd); } BOOL SetMenu(HMENU hMenu) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetMenu(m_hWnd, hMenu); } BOOL DrawMenuBar() { _ASSERTE(::IsWindow(m_hWnd)); return ::DrawMenuBar(m_hWnd); } HMENU GetSystemMenu(BOOL bRevert) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetSystemMenu(m_hWnd, bRevert); } BOOL HiliteMenuItem(HMENU hMenu, UINT uItemHilite, UINT uHilite) { _ASSERTE(::IsWindow(m_hWnd)); return ::HiliteMenuItem(m_hWnd, hMenu, uItemHilite, uHilite); } #endif // Window Size and Position Functions BOOL IsIconic() const { _ASSERTE(::IsWindow(m_hWnd)); return ::IsIconic(m_hWnd); } BOOL IsZoomed() const { _ASSERTE(::IsWindow(m_hWnd)); return ::IsZoomed(m_hWnd); } BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint); } BOOL MoveWindow(LPCRECT lpRect, BOOL bRepaint = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::MoveWindow(m_hWnd, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, bRepaint); } BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags); } BOOL SetWindowPos(HWND hWndInsertAfter, LPCRECT lpRect, UINT nFlags) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetWindowPos(m_hWnd, hWndInsertAfter, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, nFlags); } #if defined(_WINUSER_) && !defined(NOMDI) UINT ArrangeIconicWindows() { _ASSERTE(::IsWindow(m_hWnd)); return ::ArrangeIconicWindows(m_hWnd); } #endif BOOL BringWindowToTop() { _ASSERTE(::IsWindow(m_hWnd)); return ::BringWindowToTop(m_hWnd); } BOOL GetWindowRect(LPRECT lpRect) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetWindowRect(m_hWnd, lpRect); } BOOL GetClientRect(LPRECT lpRect) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetClientRect(m_hWnd, lpRect); } BOOL GetWindowPlacement(WINDOWPLACEMENT FAR* lpwndpl) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetWindowPlacement(m_hWnd, lpwndpl); } BOOL SetWindowPlacement(const WINDOWPLACEMENT FAR* lpwndpl) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetWindowPlacement(m_hWnd, lpwndpl); } // Coordinate Mapping Functions BOOL ClientToScreen(LPPOINT lpPoint) const { _ASSERTE(::IsWindow(m_hWnd)); return ::ClientToScreen(m_hWnd, lpPoint); } BOOL ClientToScreen(LPRECT lpRect) const { _ASSERTE(::IsWindow(m_hWnd)); if(!::ClientToScreen(m_hWnd, (LPPOINT)lpRect)) return FALSE; if(!::ClientToScreen(m_hWnd, ((LPPOINT)lpRect)+1)) return FALSE; if (GetExStyle() & WS_EX_LAYOUTRTL) { // Swap left and right LONG temp = lpRect->left; lpRect->left = lpRect->right; lpRect->right = temp; } return TRUE; } BOOL ScreenToClient(LPPOINT lpPoint) const { _ASSERTE(::IsWindow(m_hWnd)); return ::ScreenToClient(m_hWnd, lpPoint); } BOOL ScreenToClient(LPRECT lpRect) const { _ASSERTE(::IsWindow(m_hWnd)); if(!::ScreenToClient(m_hWnd, (LPPOINT)lpRect)) return FALSE; if(!::ScreenToClient(m_hWnd, ((LPPOINT)lpRect)+1)) return FALSE; if (GetExStyle() & WS_EX_LAYOUTRTL) { // Swap left and right LONG temp = lpRect->left; lpRect->left = lpRect->right; lpRect->right = temp; } return TRUE; } int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const { _ASSERTE(::IsWindow(m_hWnd)); return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount); } int MapWindowPoints(HWND hWndTo, LPRECT lpRect) const { _ASSERTE(::IsWindow(m_hWnd)); return ::MapWindowPoints(m_hWnd, hWndTo, (LPPOINT)lpRect, 2); } // Update and Painting Functions HDC BeginPaint(LPPAINTSTRUCT lpPaint) { _ASSERTE(::IsWindow(m_hWnd)); return ::BeginPaint(m_hWnd, lpPaint); } void EndPaint(LPPAINTSTRUCT lpPaint) { _ASSERTE(::IsWindow(m_hWnd)); ::EndPaint(m_hWnd, lpPaint); } HDC GetDC() { _ASSERTE(::IsWindow(m_hWnd)); return ::GetDC(m_hWnd); } HDC GetWindowDC() { _ASSERTE(::IsWindow(m_hWnd)); return ::GetWindowDC(m_hWnd); } int ReleaseDC(HDC hDC) { _ASSERTE(::IsWindow(m_hWnd)); return ::ReleaseDC(m_hWnd, hDC); } void Print(HDC hDC, DWORD dwFlags) const { _ASSERTE(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_PRINT, (WPARAM)hDC, dwFlags); } void PrintClient(HDC hDC, DWORD dwFlags) const { _ASSERTE(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_PRINTCLIENT, (WPARAM)hDC, dwFlags); } BOOL UpdateWindow() { _ASSERTE(::IsWindow(m_hWnd)); return ::UpdateWindow(m_hWnd); } void SetRedraw(BOOL bRedraw = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0); } BOOL GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE) { _ASSERTE(::IsWindow(m_hWnd)); return ::GetUpdateRect(m_hWnd, lpRect, bErase); } int GetUpdateRgn(HRGN hRgn, BOOL bErase = FALSE) { _ASSERTE(::IsWindow(m_hWnd)); return ::GetUpdateRgn(m_hWnd, hRgn, bErase); } BOOL Invalidate(BOOL bErase = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::InvalidateRect(m_hWnd, NULL, bErase); } BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::InvalidateRect(m_hWnd, lpRect, bErase); } void InvalidateRgn(HRGN hRgn, BOOL bErase = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); ::InvalidateRgn(m_hWnd, hRgn, bErase); } BOOL ValidateRect(LPCRECT lpRect) { _ASSERTE(::IsWindow(m_hWnd)); return ::ValidateRect(m_hWnd, lpRect); } BOOL ValidateRgn(HRGN hRgn) { _ASSERTE(::IsWindow(m_hWnd)); return ::ValidateRgn(m_hWnd, hRgn); } BOOL ShowWindow(int nCmdShow) { _ASSERTE(::IsWindow(m_hWnd)); return ::ShowWindow(m_hWnd, nCmdShow); } BOOL IsWindowVisible() const { _ASSERTE(::IsWindow(m_hWnd)); return ::IsWindowVisible(m_hWnd); } BOOL ShowOwnedPopups(BOOL bShow = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::ShowOwnedPopups(m_hWnd, bShow); } HDC GetDCEx(HRGN hRgnClip, DWORD flags) { _ASSERTE(::IsWindow(m_hWnd)); return ::GetDCEx(m_hWnd, hRgnClip, flags); } BOOL LockWindowUpdate(BOOL bLock = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::LockWindowUpdate(bLock ? m_hWnd : NULL); } BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, HRGN hRgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE) { _ASSERTE(::IsWindow(m_hWnd)); return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgnUpdate, flags); } // Timer Functions UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD)) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetTimer(m_hWnd, nIDEvent, nElapse, (TIMERPROC)lpfnTimer); } BOOL KillTimer(UINT_PTR nIDEvent) { _ASSERTE(::IsWindow(m_hWnd)); return ::KillTimer(m_hWnd, nIDEvent); } // Window State Functions BOOL IsWindowEnabled() const { _ASSERTE(::IsWindow(m_hWnd)); return ::IsWindowEnabled(m_hWnd); } BOOL EnableWindow(BOOL bEnable = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::EnableWindow(m_hWnd, bEnable); } HWND SetActiveWindow() { _ASSERTE(::IsWindow(m_hWnd)); return ::SetActiveWindow(m_hWnd); } HWND SetCapture() { _ASSERTE(::IsWindow(m_hWnd)); return ::SetCapture(m_hWnd); } HWND SetFocus() { _ASSERTE(::IsWindow(m_hWnd)); return ::SetFocus(m_hWnd); } // Dialog-Box Item Functions BOOL CheckDlgButton(int nIDButton, UINT nCheck) { _ASSERTE(::IsWindow(m_hWnd)); return ::CheckDlgButton(m_hWnd, nIDButton, nCheck); } BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) { _ASSERTE(::IsWindow(m_hWnd)); return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton); } int DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT nFileType) { _ASSERTE(::IsWindow(m_hWnd)); return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, nFileType); } int DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT nFileType) { _ASSERTE(::IsWindow(m_hWnd)); return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, nFileType); } BOOL DlgDirSelect(LPTSTR lpString, int nCount, int nIDListBox) { _ASSERTE(::IsWindow(m_hWnd)); return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox); } BOOL DlgDirSelectComboBox(LPTSTR lpString, int nCount, int nIDComboBox) { _ASSERTE(::IsWindow(m_hWnd)); return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox); } UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetDlgItemInt(m_hWnd, nID, lpTrans, bSigned); } UINT GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetDlgItemText(m_hWnd, nID, lpStr, nMaxCount); } BOOL GetDlgItemText(int nID, BSTR& bstrText) const { _ASSERTE(::IsWindow(m_hWnd)); HWND hWndCtl = GetDlgItem(nID); if(hWndCtl == NULL) return FALSE; return CWindow(hWndCtl).GetWindowText(bstrText); } HWND GetNextDlgGroupItem(HWND hWndCtl, BOOL bPrevious = FALSE) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetNextDlgGroupItem(m_hWnd, hWndCtl, bPrevious); } HWND GetNextDlgTabItem(HWND hWndCtl, BOOL bPrevious = FALSE) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetNextDlgTabItem(m_hWnd, hWndCtl, bPrevious); } UINT IsDlgButtonChecked(int nIDButton) const { _ASSERTE(::IsWindow(m_hWnd)); return ::IsDlgButtonChecked(m_hWnd, nIDButton); } LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { _ASSERTE(::IsWindow(m_hWnd)); return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam); } BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned); } BOOL SetDlgItemText(int nID, LPCTSTR lpszString) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetDlgItemText(m_hWnd, nID, lpszString); } // Scrolling Functions int GetScrollPos(int nBar) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetScrollPos(m_hWnd, nBar); } BOOL GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos); } BOOL ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL) { _ASSERTE(::IsWindow(m_hWnd)); return ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect); } int ScrollWindowEx(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate, UINT flags) { _ASSERTE(::IsWindow(m_hWnd)); return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, flags); } int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw); } BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw); } BOOL ShowScrollBar(UINT nBar, BOOL bShow = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return ::ShowScrollBar(m_hWnd, nBar, bShow); } BOOL EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH) { _ASSERTE(::IsWindow(m_hWnd)); return ::EnableScrollBar(m_hWnd, uSBFlags, uArrowFlags); } // Window Access Functions HWND ChildWindowFromPoint(POINT point) const { _ASSERTE(::IsWindow(m_hWnd)); return ::ChildWindowFromPoint(m_hWnd, point); } HWND ChildWindowFromPointEx(POINT point, UINT uFlags) const { _ASSERTE(::IsWindow(m_hWnd)); return ::ChildWindowFromPointEx(m_hWnd, point, uFlags); } HWND GetTopWindow() const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetTopWindow(m_hWnd); } HWND GetWindow(UINT nCmd) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetWindow(m_hWnd, nCmd); } HWND GetLastActivePopup() const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetLastActivePopup(m_hWnd); } BOOL IsChild(HWND hWnd) const { _ASSERTE(::IsWindow(m_hWnd)); return ::IsChild(m_hWnd, hWnd); } HWND GetParent() const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetParent(m_hWnd); } HWND SetParent(HWND hWndNewParent) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetParent(m_hWnd, hWndNewParent); } // Window Tree Access int GetDlgCtrlID() const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetDlgCtrlID(m_hWnd); } int SetDlgCtrlID(int nID) { _ASSERTE(::IsWindow(m_hWnd)); return (int)::SetWindowLong(m_hWnd, GWL_ID, nID); } HWND GetDlgItem(int nID) const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetDlgItem(m_hWnd, nID); } HWND GetDescendantWindow(int nID) const; void SendMessageToDescendants(UINT message, WPARAM wParam = 0, LPARAM lParam = 0, BOOL bDeep = TRUE); // Alert Functions BOOL FlashWindow(BOOL bInvert) { _ASSERTE(::IsWindow(m_hWnd)); return ::FlashWindow(m_hWnd, bInvert); } int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK) { _ASSERTE(::IsWindow(m_hWnd)); return ::MessageBox(m_hWnd, lpszText, lpszCaption, nType); } // Clipboard Functions BOOL ChangeClipboardChain(HWND hWndNewNext) { _ASSERTE(::IsWindow(m_hWnd)); return ::ChangeClipboardChain(m_hWnd, hWndNewNext); } HWND SetClipboardViewer() { _ASSERTE(::IsWindow(m_hWnd)); return ::SetClipboardViewer(m_hWnd); } BOOL OpenClipboard() { _ASSERTE(::IsWindow(m_hWnd)); return ::OpenClipboard(m_hWnd); } // Caret Functions BOOL CreateCaret(HBITMAP hBitmap) { _ASSERTE(::IsWindow(m_hWnd)); return ::CreateCaret(m_hWnd, hBitmap, 0, 0); } BOOL CreateSolidCaret(int nWidth, int nHeight) { _ASSERTE(::IsWindow(m_hWnd)); return ::CreateCaret(m_hWnd, (HBITMAP)0, nWidth, nHeight); } BOOL CreateGrayCaret(int nWidth, int nHeight) { _ASSERTE(::IsWindow(m_hWnd)); return ::CreateCaret(m_hWnd, (HBITMAP)1, nWidth, nHeight); } BOOL HideCaret() { _ASSERTE(::IsWindow(m_hWnd)); return ::HideCaret(m_hWnd); } BOOL ShowCaret() { _ASSERTE(::IsWindow(m_hWnd)); return ::ShowCaret(m_hWnd); } // Drag-Drop Functions #ifdef _INC_SHELLAPI void DragAcceptFiles(BOOL bAccept = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); ::DragAcceptFiles(m_hWnd, bAccept); } #endif // Icon Functions HICON SetIcon(HICON hIcon, BOOL bBigIcon = TRUE) { _ASSERTE(::IsWindow(m_hWnd)); return (HICON)::SendMessage(m_hWnd, WM_SETICON, bBigIcon, (LPARAM)hIcon); } HICON GetIcon(BOOL bBigIcon = TRUE) const { _ASSERTE(::IsWindow(m_hWnd)); return (HICON)::SendMessage(m_hWnd, WM_GETICON, bBigIcon, 0); } // Help Functions #if defined(_WINUSER_) && !defined(NOHELP) BOOL WinHelp(LPCTSTR lpszHelp, UINT nCmd = HELP_CONTEXT, DWORD_PTR dwData = 0) { _ASSERTE(::IsWindow(m_hWnd)); return ::WinHelp(m_hWnd, lpszHelp, nCmd, dwData); } BOOL SetWindowContextHelpId(DWORD dwContextHelpId) { _ASSERTE(::IsWindow(m_hWnd)); return ::SetWindowContextHelpId(m_hWnd, dwContextHelpId); } DWORD GetWindowContextHelpId() const { _ASSERTE(::IsWindow(m_hWnd)); return ::GetWindowContextHelpId(m_hWnd); } #endif // Hot Key Functions int SetHotKey(WORD wVirtualKeyCode, WORD wModifiers) { _ASSERTE(::IsWindow(m_hWnd)); return (int)::SendMessage(m_hWnd, WM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0); } DWORD GetHotKey(WORD& /* wVirtualKeyCode */, WORD& /* wModifiers */) const { _ASSERTE(::IsWindow(m_hWnd)); return (DWORD)::SendMessage(m_hWnd, WM_GETHOTKEY, 0, 0); } // Misc. Operations BOOL CenterWindow(HWND hWndCenter = NULL); HWND GetTopLevelParent() const; HWND GetTopLevelWindow() const; }; ///////////////////////////////////////////////////////////////////////////// // Thunks for __stdcall member functions #if defined(_M_IX86) #pragma pack(push,1) struct _stdcallthunk { DWORD m_mov; // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd) DWORD m_this; // BYTE m_jmp; // jmp WndProc DWORD m_relproc; // relative jmp void Init(DWORD_PTR proc, void* pThis) { m_mov = 0x042444C7; //C7 44 24 0C m_this = PtrToUlong(pThis); m_jmp = 0xe9; m_relproc = DWORD((INT_PTR)proc - ((INT_PTR)this+sizeof(_stdcallthunk))); // write block from data cache and // flush from instruction cache FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); } }; #pragma pack(pop) #elif defined (_M_AMD64) #pragma pack(push,2) struct _stdcallthunk { USHORT RcxMov; // mov rcx, pThis ULONG64 RcxImm; // USHORT RaxMov; // mov rax, target ULONG64 RaxImm; // USHORT RaxJmp; // jmp target void Init(DWORD_PTR proc, void *pThis) { RcxMov = 0xb948; // mov rcx, pThis RcxImm = (ULONG64)pThis; // RaxMov = 0xb848; // mov rax, target RaxImm = (ULONG64)proc; // RaxJmp = 0xe0ff; // jmp rax FlushInstructionCache(GetCurrentProcess(), this, sizeof(_stdcallthunk)); } }; #pragma pack(pop) #elif defined(_M_IA64) #pragma pack(push,8) extern "C" LRESULT CALLBACK _WndProcThunkProc( HWND, UINT, WPARAM, LPARAM ); struct _FuncDesc { void* pfn; void* gp; }; struct _stdcallthunk { _FuncDesc m_funcdesc; void* m_pFunc; void* m_pThis; void Init(DWORD_PTR proc, void* pThis) { const _FuncDesc* pThunkProc; pThunkProc = reinterpret_cast< const _FuncDesc* >( _WndProcThunkProc ); m_funcdesc.pfn = pThunkProc->pfn; m_funcdesc.gp = &m_pFunc; m_pFunc = reinterpret_cast< void* >( proc ); m_pThis = pThis; ::FlushInstructionCache( GetCurrentProcess(), this, sizeof( _stdcallthunk ) ); } }; #pragma pack(pop) #else #error Only AMD64, IA64, and X86 supported #endif class CDynamicStdCallThunk { public: _stdcallthunk *pThunk; CDynamicStdCallThunk() { pThunk = NULL; } ~CDynamicStdCallThunk() { if (pThunk) HeapFree(GetProcessHeap(), 0, pThunk); } void Init(DWORD_PTR proc, void *pThis) { if (!pThunk) { pThunk = static_cast<_stdcallthunk *>(HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, sizeof(_stdcallthunk))); } ATLASSERT(pThunk); pThunk->Init(proc, pThis); } }; typedef CDynamicStdCallThunk CStdCallThunk; ///////////////////////////////////////////////////////////////////////////// // WindowProc thunks class CWndProcThunk { public: _AtlCreateWndData cd; CStdCallThunk thunk; void Init(WNDPROC proc, void* pThis) { thunk.Init((DWORD_PTR)proc, pThis); } }; ///////////////////////////////////////////////////////////////////////////// // CMessageMap - abstract class that provides an interface for message maps class ATL_NO_VTABLE CMessageMap { public: virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID) = 0; }; ///////////////////////////////////////////////////////////////////////////// // Message map #define BEGIN_MSG_MAP(theClass) \ public: \ BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \ { \ BOOL bHandled = TRUE; \ hWnd; \ switch(dwMsgMapID) \ { \ case 0: #define ALT_MSG_MAP(msgMapID) \ break; \ case msgMapID: #define MESSAGE_HANDLER(msg, func) \ if(uMsg == msg) \ { \ bHandled = TRUE; \ lResult = func(uMsg, wParam, lParam, bHandled); \ if(bHandled) \ return TRUE; \ } #define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \ if(uMsg >= msgFirst && uMsg <= msgLast) \ { \ bHandled = TRUE; \ lResult = func(uMsg, wParam, lParam, bHandled); \ if(bHandled) \ return TRUE; \ } #define COMMAND_HANDLER(id, code, func) \ if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \ { \ bHandled = TRUE; \ lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ if(bHandled) \ return TRUE; \ } #define COMMAND_ID_HANDLER(id, func) \ if(uMsg == WM_COMMAND && id == LOWORD(wParam)) \ { \ bHandled = TRUE; \ lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ if(bHandled) \ return TRUE; \ } #define COMMAND_CODE_HANDLER(code, func) \ if(uMsg == WM_COMMAND && code == HIWORD(wParam)) \ { \ bHandled = TRUE; \ lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ if(bHandled) \ return TRUE; \ } #define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \ if(uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ { \ bHandled = TRUE; \ lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ if(bHandled) \ return TRUE; \ } #define NOTIFY_HANDLER(id, cd, func) \ if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \ { \ bHandled = TRUE; \ lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ if(bHandled) \ return TRUE; \ } #define NOTIFY_ID_HANDLER(id, func) \ if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom) \ { \ bHandled = TRUE; \ lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ if(bHandled) \ return TRUE; \ } #define NOTIFY_CODE_HANDLER(cd, func) \ if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ { \ bHandled = TRUE; \ lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ if(bHandled) \ return TRUE; \ } #define NOTIFY_RANGE_HANDLER(idFirst, idLast, func) \ if(uMsg == WM_NOTIFY && ((LPNMHDR)lParam)->idFrom >= idFirst && ((LPNMHDR)lParam)->idFrom <= idLast) \ { \ bHandled = TRUE; \ lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ if(bHandled) \ return TRUE; \ } #define CHAIN_MSG_MAP(theChainClass) \ { \ if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \ return TRUE; \ } #define CHAIN_MSG_MAP_MEMBER(theChainMember) \ { \ if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \ return TRUE; \ } #define CHAIN_MSG_MAP_ALT(theChainClass, msgMapID) \ { \ if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \ return TRUE; \ } #define CHAIN_MSG_MAP_ALT_MEMBER(theChainMember, msgMapID) \ { \ if(theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \ return TRUE; \ } #define CHAIN_MSG_MAP_DYNAMIC(dynaChainID) \ { \ if(CDynamicChain::CallChain(dynaChainID, hWnd, uMsg, wParam, lParam, lResult)) \ return TRUE; \ } #define CHAIN_MSG_MAP_ALT_DYNAMIC(dynaChainID, msgMapID) \ { \ if(CDynamicChain::CallChain(dynaChainID, hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \ return TRUE; \ } #define END_MSG_MAP() \ break; \ default: \ ATLTRACE(_T("Invalid message map ID (%i)\n"), dwMsgMapID); \ _ASSERTE(FALSE); \ break; \ } \ return FALSE; \ } // Handler prototypes: // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); ///////////////////////////////////////////////////////////////////////////// // CDynamicChain - provides support for dynamic chaining class CDynamicChain { public: struct ATL_CHAIN_ENTRY { DWORD m_dwChainID; CMessageMap* m_pObject; DWORD m_dwMsgMapID; }; int m_nEntries; ATL_CHAIN_ENTRY** m_pChainEntry; CDynamicChain() : m_nEntries(0), m_pChainEntry(NULL) { } ~CDynamicChain(); BOOL SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID = 0); BOOL RemoveChainEntry(DWORD dwChainID); BOOL CallChain(DWORD dwChainID, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult); }; ///////////////////////////////////////////////////////////////////////////// // CWndClassInfo - Manages Windows class information class CWndClassInfo { public: WNDCLASSEX m_wc; LPCTSTR m_lpszOrigName; WNDPROC pWndProc; LPCTSTR m_lpszCursorID; BOOL m_bSystemCursor; ATOM m_atom; TCHAR m_szAutoName[sizeof("ATL:") + (sizeof(PVOID)*2)+1]; ATOM Register(WNDPROC*); }; #define DECLARE_WND_CLASS(WndClassName) \ static CWndClassInfo& GetWndClassInfo() \ { \ static CWndClassInfo wc = \ { \ { sizeof(WNDCLASSEX), CS_HREDRAW|CS_VREDRAW, StartWindowProc, \ 0, 0, 0, 0, 0, (HBRUSH)(COLOR_WINDOW+1), 0, WndClassName, 0 }, \ NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \ }; \ return wc; \ } #define DECLARE_WND_SUPERCLASS(WndClassName, OrigWndClassName) \ static CWndClassInfo& GetWndClassInfo() \ { \ static CWndClassInfo wc = \ { \ { sizeof(WNDCLASSEX), NULL, StartWindowProc, \ 0, 0, 0, 0, 0, NULL, 0, WndClassName, 0 }, \ OrigWndClassName, NULL, NULL, TRUE, 0, _T("") \ }; \ return wc; \ } ///////////////////////////////////////////////////////////////////////////// // CWindowImpl - Implements a window class ATL_NO_VTABLE CWindowImplBase : public CWindow, public CMessageMap { public: CWndProcThunk m_thunk; WNDPROC m_pfnSuperWindowProc; CWindowImplBase() : m_pfnSuperWindowProc(::DefWindowProc) {} static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, UINT_PTR nID, ATOM atom); BOOL SubclassWindow(HWND hWnd); HWND UnsubclassWindow(); LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { #ifdef STRICT return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); #else return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); #endif } }; template class ATL_NO_VTABLE CWindowImpl : public CWindowImplBase { public: DECLARE_WND_CLASS(NULL) HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL, DWORD dwStyle = WS_CHILD | WS_VISIBLE, DWORD dwExStyle = 0, UINT_PTR nID = 0) { ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc); return CWindowImplBase::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, atom); } }; ///////////////////////////////////////////////////////////////////////////// // CDialog - Implements a dialog box class ATL_NO_VTABLE CDialogImplBase : public CWindow, public CMessageMap { public: CWndProcThunk m_thunk; static INT_PTR CALLBACK StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL EndDialog(int nRetCode); }; template class ATL_NO_VTABLE CDialogImpl : public CDialogImplBase { public: INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) { _ASSERTE(m_hWnd == NULL); _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBase*)this); INT_PTR nRet = ::DialogBoxParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD), hWndParent, T::StartDialogProc, NULL); m_hWnd = NULL; return nRet; } HWND Create(HWND hWndParent) { _ASSERTE(m_hWnd == NULL); _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBase*)this); HWND hWnd = ::CreateDialogParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD), hWndParent, T::StartDialogProc, NULL); _ASSERTE(m_hWnd == hWnd); return hWnd; } }; ///////////////////////////////////////////////////////////////////////////// // CContainedWindow - Implements a contained window class CContainedWindow : public CWindow { public: CWndProcThunk m_thunk; LPTSTR m_lpszClassName; WNDPROC m_pfnSuperWindowProc; CMessageMap* m_pObject; DWORD m_dwMsgMapID; CContainedWindow(LPTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID = 0) : m_lpszClassName(lpszClassName), m_pfnSuperWindowProc(::DefWindowProc), m_pObject(pObject), m_dwMsgMapID(dwMsgMapID) { } void SwitchMessageMap(DWORD dwMsgMapID) { m_dwMsgMapID = dwMsgMapID; } static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); ATOM RegisterWndSuperclass(); HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL, DWORD dwStyle = WS_CHILD | WS_VISIBLE, DWORD dwExStyle = 0, UINT nID = 0); BOOL SubclassWindow(HWND hWnd); HWND UnsubclassWindow(); LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) { #ifdef STRICT return ::CallWindowProc(m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); #else return ::CallWindowProc((FARPROC)m_pfnSuperWindowProc, m_hWnd, uMsg, wParam, lParam); #endif } }; #ifndef ATL_NO_NAMESPACE }; //namespace ATL #endif #ifdef _ATL_REDEF_SUBCLASSWINDOW #pragma pop_macro( "SubclassWindow" ) #undef _ATL_REDEF_SUBCLASSWINDOW #endif #endif // __ATLWIN_H__