|
|
// This is a part of the Active Template Library.
// Copyright (C) 1996-1998 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
struct _ATL_WNDCLASSINFOA; struct _ATL_WNDCLASSINFOW;
#ifndef _ATL_DLL_IMPL
namespace ATL { #endif
ATLAPI_(ATOM) AtlModuleRegisterWndClassInfoA(_ATL_MODULE* pM, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc); ATLAPI_(ATOM) AtlModuleRegisterWndClassInfoW(_ATL_MODULE* pM, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc);
#ifdef UNICODE
#define AtlModuleRegisterWndClassInfo AtlModuleRegisterWndClassInfoW
#else
#define AtlModuleRegisterWndClassInfo AtlModuleRegisterWndClassInfoA
#endif
#define HIMETRIC_PER_INCH 2540
#define MAP_PIX_TO_LOGHIM(x,ppli) ( (HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli) )
#define MAP_LOGHIM_TO_PIX(x,ppli) ( ((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH )
ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd); ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix); ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric);
#ifndef _ATL_DLL_IMPL
}; //namespace ATL
#endif
struct _ATL_WNDCLASSINFOA { WNDCLASSEXA m_wc; LPCSTR m_lpszOrigName; WNDPROC pWndProc; LPCSTR m_lpszCursorID; BOOL m_bSystemCursor; ATOM m_atom; CHAR m_szAutoName[sizeof("ATL:") + (sizeof(PVOID)*2)+1]; ATOM Register(WNDPROC* p) { return AtlModuleRegisterWndClassInfoA(&_Module, this, p); } }; struct _ATL_WNDCLASSINFOW { WNDCLASSEXW m_wc; LPCWSTR m_lpszOrigName; WNDPROC pWndProc; LPCWSTR m_lpszCursorID; BOOL m_bSystemCursor; ATOM m_atom; WCHAR m_szAutoName[sizeof("ATL:") + (sizeof(PVOID)*2)+1]; ATOM Register(WNDPROC* p) { return AtlModuleRegisterWndClassInfoW(&_Module, this, p); } };
namespace ATL {
/////////////////////////////////////////////////////////////////////////////
// Forward declarations
class CWindow; #ifndef _ATL_NO_HOSTING
template <class TBase = CWindow> class CAxWindowT; #endif //!_ATL_NO_HOSTING
class CMessageMap; class CDynamicChain; typedef _ATL_WNDCLASSINFOA CWndClassInfoA; typedef _ATL_WNDCLASSINFOW CWndClassInfoW; #ifdef UNICODE
#define CWndClassInfo CWndClassInfoW
#else
#define CWndClassInfo CWndClassInfoA
#endif
template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits> class CWindowImpl; template <class T, class TBase = CWindow> class CDialogImpl; #ifndef _ATL_NO_HOSTING
template <class T, class TBase = CWindow> class CAxDialogImpl; #endif //!_ATL_NO_HOSTING
template <WORD t_wDlgTemplateID, BOOL t_bCenter = TRUE> class CSimpleDialog; template <class TBase = CWindow, class TWinTraits = CControlWinTraits> class CContainedWindowT;
/////////////////////////////////////////////////////////////////////////////
// CWindow - client side for a Windows window
class CWindow { public: static RECT rcDefault; HWND m_hWnd;
CWindow(HWND hWnd = NULL) { m_hWnd = hWnd; }
CWindow& operator=(HWND hWnd) { m_hWnd = hWnd; return *this; }
static LPCTSTR GetWndClassName() { return NULL; }
void Attach(HWND hWndNew) { ATLASSERT(::IsWindow(hWndNew)); m_hWnd = hWndNew; }
HWND Detach() { HWND hWnd = m_hWnd; m_hWnd = NULL; return hWnd; }
HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) { m_hWnd = ::CreateWindowEx(dwExStyle, lpstrWndClass, szWindowName, dwStyle, rcPos.left, rcPos.top, rcPos.right - rcPos.left, rcPos.bottom - rcPos.top, hWndParent, (HMENU)(DWORD_PTR)nID, _Module.GetModuleInstance(), lpCreateParam); return m_hWnd; }
HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, LPRECT lpRect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, HMENU hMenu = NULL, LPVOID lpCreateParam = NULL) { if(lpRect == NULL) lpRect = &rcDefault; m_hWnd = ::CreateWindowEx(dwExStyle, lpstrWndClass, szWindowName, dwStyle, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, hWndParent, hMenu, _Module.GetModuleInstance(), lpCreateParam); return m_hWnd; }
BOOL DestroyWindow() { ATLASSERT(::IsWindow(m_hWnd));
if(!::DestroyWindow(m_hWnd)) return FALSE;
m_hWnd = NULL; return TRUE; }
// Attributes
operator HWND() const { return m_hWnd; }
DWORD GetStyle() const { ATLASSERT(::IsWindow(m_hWnd)); return (DWORD)::GetWindowLong(m_hWnd, GWL_STYLE); }
DWORD GetExStyle() const { ATLASSERT(::IsWindow(m_hWnd)); return (DWORD)::GetWindowLong(m_hWnd, GWL_EXSTYLE); }
LONG GetWindowLong(int nIndex) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindowLong(m_hWnd, nIndex); }
LONG SetWindowLong(int nIndex, LONG dwNewLong) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetWindowLong(m_hWnd, nIndex, dwNewLong); }
WORD GetWindowWord(int nIndex) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindowWord(m_hWnd, nIndex); }
WORD SetWindowWord(int nIndex, WORD wNewWord) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetWindowWord(m_hWnd, nIndex, wNewWord); }
// Message Functions
LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { ATLASSERT(::IsWindow(m_hWnd)); return ::SendMessage(m_hWnd,message,wParam,lParam); }
BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { ATLASSERT(::IsWindow(m_hWnd)); return ::PostMessage(m_hWnd,message,wParam,lParam); }
BOOL SendNotifyMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { ATLASSERT(::IsWindow(m_hWnd)); return ::SendNotifyMessage(m_hWnd, message, wParam, lParam); }
// support for C style macros
static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ATLASSERT(::IsWindow(hWnd)); return ::SendMessage(hWnd, message, wParam, lParam); }
// Window Text Functions
BOOL SetWindowText(LPCTSTR lpszString) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetWindowText(m_hWnd, lpszString); }
int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount); }
int GetWindowTextLength() const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindowTextLength(m_hWnd); }
// Font Functions
void SetFont(HFONT hFont, BOOL bRedraw = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(bRedraw, 0)); }
HFONT GetFont() const { ATLASSERT(::IsWindow(m_hWnd)); return (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0); }
// Menu Functions (non-child windows only)
HMENU GetMenu() const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetMenu(m_hWnd); }
BOOL SetMenu(HMENU hMenu) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetMenu(m_hWnd, hMenu); }
BOOL DrawMenuBar() { ATLASSERT(::IsWindow(m_hWnd)); return ::DrawMenuBar(m_hWnd); }
HMENU GetSystemMenu(BOOL bRevert) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetSystemMenu(m_hWnd, bRevert); }
BOOL HiliteMenuItem(HMENU hMenu, UINT uItemHilite, UINT uHilite) { ATLASSERT(::IsWindow(m_hWnd)); return ::HiliteMenuItem(m_hWnd, hMenu, uItemHilite, uHilite); }
// Window Size and Position Functions
BOOL IsIconic() const { ATLASSERT(::IsWindow(m_hWnd)); return ::IsIconic(m_hWnd); }
BOOL IsZoomed() const { ATLASSERT(::IsWindow(m_hWnd)); return ::IsZoomed(m_hWnd); }
BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint); }
BOOL MoveWindow(LPCRECT lpRect, BOOL bRepaint = TRUE) { ATLASSERT(::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) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags); }
BOOL SetWindowPos(HWND hWndInsertAfter, LPCRECT lpRect, UINT nFlags) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetWindowPos(m_hWnd, hWndInsertAfter, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, nFlags); }
UINT ArrangeIconicWindows() { ATLASSERT(::IsWindow(m_hWnd)); return ::ArrangeIconicWindows(m_hWnd); }
BOOL BringWindowToTop() { ATLASSERT(::IsWindow(m_hWnd)); return ::BringWindowToTop(m_hWnd); }
BOOL GetWindowRect(LPRECT lpRect) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindowRect(m_hWnd, lpRect); }
BOOL GetClientRect(LPRECT lpRect) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetClientRect(m_hWnd, lpRect); }
BOOL GetWindowPlacement(WINDOWPLACEMENT FAR* lpwndpl) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindowPlacement(m_hWnd, lpwndpl); }
BOOL SetWindowPlacement(const WINDOWPLACEMENT FAR* lpwndpl) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetWindowPlacement(m_hWnd, lpwndpl); }
// Coordinate Mapping Functions
BOOL ClientToScreen(LPPOINT lpPoint) const { ATLASSERT(::IsWindow(m_hWnd)); return ::ClientToScreen(m_hWnd, lpPoint); }
BOOL ClientToScreen(LPRECT lpRect) const { ATLASSERT(::IsWindow(m_hWnd)); if(!::ClientToScreen(m_hWnd, (LPPOINT)lpRect)) return FALSE; return ::ClientToScreen(m_hWnd, ((LPPOINT)lpRect)+1); }
BOOL ScreenToClient(LPPOINT lpPoint) const { ATLASSERT(::IsWindow(m_hWnd)); return ::ScreenToClient(m_hWnd, lpPoint); }
BOOL ScreenToClient(LPRECT lpRect) const { ATLASSERT(::IsWindow(m_hWnd)); if(!::ScreenToClient(m_hWnd, (LPPOINT)lpRect)) return FALSE; return ::ScreenToClient(m_hWnd, ((LPPOINT)lpRect)+1); }
int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const { ATLASSERT(::IsWindow(m_hWnd)); return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount); }
int MapWindowPoints(HWND hWndTo, LPRECT lpRect) const { ATLASSERT(::IsWindow(m_hWnd)); return ::MapWindowPoints(m_hWnd, hWndTo, (LPPOINT)lpRect, 2); }
// Update and Painting Functions
HDC BeginPaint(LPPAINTSTRUCT lpPaint) { ATLASSERT(::IsWindow(m_hWnd)); return ::BeginPaint(m_hWnd, lpPaint); }
void EndPaint(LPPAINTSTRUCT lpPaint) { ATLASSERT(::IsWindow(m_hWnd)); ::EndPaint(m_hWnd, lpPaint); }
HDC GetDC() { ATLASSERT(::IsWindow(m_hWnd)); return ::GetDC(m_hWnd); }
HDC GetWindowDC() { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindowDC(m_hWnd); }
int ReleaseDC(HDC hDC) { ATLASSERT(::IsWindow(m_hWnd)); return ::ReleaseDC(m_hWnd, hDC); }
void Print(HDC hDC, DWORD dwFlags) const { ATLASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_PRINT, (WPARAM)hDC, dwFlags); }
void PrintClient(HDC hDC, DWORD dwFlags) const { ATLASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_PRINTCLIENT, (WPARAM)hDC, dwFlags); }
BOOL UpdateWindow() { ATLASSERT(::IsWindow(m_hWnd)); return ::UpdateWindow(m_hWnd); }
void SetRedraw(BOOL bRedraw = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0); }
BOOL GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE) { ATLASSERT(::IsWindow(m_hWnd)); return ::GetUpdateRect(m_hWnd, lpRect, bErase); }
int GetUpdateRgn(HRGN hRgn, BOOL bErase = FALSE) { ATLASSERT(::IsWindow(m_hWnd)); return ::GetUpdateRgn(m_hWnd, hRgn, bErase); }
BOOL Invalidate(BOOL bErase = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return ::InvalidateRect(m_hWnd, NULL, bErase); }
BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return ::InvalidateRect(m_hWnd, lpRect, bErase); }
BOOL ValidateRect(LPCRECT lpRect) { ATLASSERT(::IsWindow(m_hWnd)); return ::ValidateRect(m_hWnd, lpRect); }
void InvalidateRgn(HRGN hRgn, BOOL bErase = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); ::InvalidateRgn(m_hWnd, hRgn, bErase); }
BOOL ValidateRgn(HRGN hRgn) { ATLASSERT(::IsWindow(m_hWnd)); return ::ValidateRgn(m_hWnd, hRgn); }
BOOL ShowWindow(int nCmdShow) { ATLASSERT(::IsWindow(m_hWnd)); return ::ShowWindow(m_hWnd, nCmdShow); }
BOOL IsWindowVisible() const { ATLASSERT(::IsWindow(m_hWnd)); return ::IsWindowVisible(m_hWnd); }
BOOL ShowOwnedPopups(BOOL bShow = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return ::ShowOwnedPopups(m_hWnd, bShow); }
HDC GetDCEx(HRGN hRgnClip, DWORD flags) { ATLASSERT(::IsWindow(m_hWnd)); return ::GetDCEx(m_hWnd, hRgnClip, flags); }
BOOL LockWindowUpdate(BOOL bLock = TRUE) { ATLASSERT(::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) { ATLASSERT(::IsWindow(m_hWnd)); return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgnUpdate, flags); }
// Timer Functions
UINT_PTR SetTimer(UINT nIDEvent, UINT nElapse) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetTimer(m_hWnd, nIDEvent, nElapse, NULL); }
BOOL KillTimer(UINT nIDEvent) { ATLASSERT(::IsWindow(m_hWnd)); return ::KillTimer(m_hWnd, nIDEvent); }
// Window State Functions
BOOL IsWindowEnabled() const { ATLASSERT(::IsWindow(m_hWnd)); return ::IsWindowEnabled(m_hWnd); }
BOOL EnableWindow(BOOL bEnable = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return ::EnableWindow(m_hWnd, bEnable); }
HWND SetActiveWindow() { ATLASSERT(::IsWindow(m_hWnd)); return ::SetActiveWindow(m_hWnd); }
HWND SetCapture() { ATLASSERT(::IsWindow(m_hWnd)); return ::SetCapture(m_hWnd); }
HWND SetFocus() { ATLASSERT(::IsWindow(m_hWnd)); return ::SetFocus(m_hWnd); }
// Dialog-Box Item Functions
BOOL CheckDlgButton(int nIDButton, UINT nCheck) { ATLASSERT(::IsWindow(m_hWnd)); return ::CheckDlgButton(m_hWnd, nIDButton, nCheck); }
BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) { ATLASSERT(::IsWindow(m_hWnd)); return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton); }
int DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT nFileType) { ATLASSERT(::IsWindow(m_hWnd)); return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, nFileType); }
int DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT nFileType) { ATLASSERT(::IsWindow(m_hWnd)); return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, nFileType); }
BOOL DlgDirSelect(LPTSTR lpString, int nCount, int nIDListBox) { ATLASSERT(::IsWindow(m_hWnd)); return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox); }
BOOL DlgDirSelectComboBox(LPTSTR lpString, int nCount, int nIDComboBox) { ATLASSERT(::IsWindow(m_hWnd)); return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox); }
UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetDlgItemInt(m_hWnd, nID, lpTrans, bSigned); }
UINT GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetDlgItemText(m_hWnd, nID, lpStr, nMaxCount); } BOOL GetDlgItemText(int nID, BSTR& bstrText) const { ATLASSERT(::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 { ATLASSERT(::IsWindow(m_hWnd)); return ::GetNextDlgGroupItem(m_hWnd, hWndCtl, bPrevious); }
HWND GetNextDlgTabItem(HWND hWndCtl, BOOL bPrevious = FALSE) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetNextDlgTabItem(m_hWnd, hWndCtl, bPrevious); }
UINT IsDlgButtonChecked(int nIDButton) const { ATLASSERT(::IsWindow(m_hWnd)); return ::IsDlgButtonChecked(m_hWnd, nIDButton); }
LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { ATLASSERT(::IsWindow(m_hWnd)); return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam); }
BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned); }
BOOL SetDlgItemText(int nID, LPCTSTR lpszString) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetDlgItemText(m_hWnd, nID, lpszString); }
#ifndef _ATL_NO_HOSTING
HRESULT GetDlgControl(int nID, REFIID iid, void** ppUnk) { ATLASSERT(::IsWindow(m_hWnd)); ATLASSERT(ppUnk != NULL); HRESULT hr = E_FAIL; HWND hWndCtrl = GetDlgItem(nID); if (hWndCtrl != NULL) { *ppUnk = NULL; CComPtr<IUnknown> spUnk; hr = AtlAxGetControl(hWndCtrl, &spUnk); if (SUCCEEDED(hr)) hr = spUnk->QueryInterface(iid, ppUnk); } return hr; } #endif //!_ATL_NO_HOSTING
// Scrolling Functions
int GetScrollPos(int nBar) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetScrollPos(m_hWnd, nBar); }
BOOL GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos); }
BOOL ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL) { ATLASSERT(::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 uFlags) { ATLASSERT(::IsWindow(m_hWnd)); return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, uFlags); }
int ScrollWindowEx(int dx, int dy, UINT uFlags, LPCRECT lpRectScroll = NULL, LPCRECT lpRectClip = NULL, HRGN hRgnUpdate = NULL, LPRECT lpRectUpdate = NULL) { ATLASSERT(::IsWindow(m_hWnd)); return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, uFlags); }
int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw); }
BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw); }
BOOL ShowScrollBar(UINT nBar, BOOL bShow = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return ::ShowScrollBar(m_hWnd, nBar, bShow); }
BOOL EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH) { ATLASSERT(::IsWindow(m_hWnd)); return ::EnableScrollBar(m_hWnd, uSBFlags, uArrowFlags); }
// Window Access Functions
HWND ChildWindowFromPoint(POINT point) const { ATLASSERT(::IsWindow(m_hWnd)); return ::ChildWindowFromPoint(m_hWnd, point); }
HWND ChildWindowFromPointEx(POINT point, UINT uFlags) const { ATLASSERT(::IsWindow(m_hWnd)); return ::ChildWindowFromPointEx(m_hWnd, point, uFlags); }
HWND GetTopWindow() const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetTopWindow(m_hWnd); }
HWND GetWindow(UINT nCmd) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindow(m_hWnd, nCmd); }
HWND GetLastActivePopup() const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetLastActivePopup(m_hWnd); }
BOOL IsChild(HWND hWnd) const { ATLASSERT(::IsWindow(m_hWnd)); return ::IsChild(m_hWnd, hWnd); }
HWND GetParent() const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetParent(m_hWnd); }
HWND SetParent(HWND hWndNewParent) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetParent(m_hWnd, hWndNewParent); }
// Window Tree Access
int GetDlgCtrlID() const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetDlgCtrlID(m_hWnd); }
int SetDlgCtrlID(int nID) { ATLASSERT(::IsWindow(m_hWnd)); return (int)::SetWindowLong(m_hWnd, GWL_ID, nID); }
HWND GetDlgItem(int nID) const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetDlgItem(m_hWnd, nID); }
// Alert Functions
BOOL FlashWindow(BOOL bInvert) { ATLASSERT(::IsWindow(m_hWnd)); return ::FlashWindow(m_hWnd, bInvert); }
int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption = _T(""), UINT nType = MB_OK) { ATLASSERT(::IsWindow(m_hWnd)); return ::MessageBox(m_hWnd, lpszText, lpszCaption, nType); }
// Clipboard Functions
BOOL ChangeClipboardChain(HWND hWndNewNext) { ATLASSERT(::IsWindow(m_hWnd)); return ::ChangeClipboardChain(m_hWnd, hWndNewNext); }
HWND SetClipboardViewer() { ATLASSERT(::IsWindow(m_hWnd)); return ::SetClipboardViewer(m_hWnd); }
BOOL OpenClipboard() { ATLASSERT(::IsWindow(m_hWnd)); return ::OpenClipboard(m_hWnd); }
// Caret Functions
BOOL CreateCaret(HBITMAP hBitmap) { ATLASSERT(::IsWindow(m_hWnd)); return ::CreateCaret(m_hWnd, hBitmap, 0, 0); }
BOOL CreateSolidCaret(int nWidth, int nHeight) { ATLASSERT(::IsWindow(m_hWnd)); return ::CreateCaret(m_hWnd, (HBITMAP)0, nWidth, nHeight); }
BOOL CreateGrayCaret(int nWidth, int nHeight) { ATLASSERT(::IsWindow(m_hWnd)); return ::CreateCaret(m_hWnd, (HBITMAP)1, nWidth, nHeight); }
BOOL HideCaret() { ATLASSERT(::IsWindow(m_hWnd)); return ::HideCaret(m_hWnd); }
BOOL ShowCaret() { ATLASSERT(::IsWindow(m_hWnd)); return ::ShowCaret(m_hWnd); }
#ifdef _INC_SHELLAPI
// Drag-Drop Functions
void DragAcceptFiles(BOOL bAccept = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); ::DragAcceptFiles(m_hWnd, bAccept); } #endif
// Icon Functions
HICON SetIcon(HICON hIcon, BOOL bBigIcon = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return (HICON)::SendMessage(m_hWnd, WM_SETICON, bBigIcon, (LPARAM)hIcon); }
HICON GetIcon(BOOL bBigIcon = TRUE) const { ATLASSERT(::IsWindow(m_hWnd)); return (HICON)::SendMessage(m_hWnd, WM_GETICON, bBigIcon, 0); }
// Help Functions
BOOL WinHelp(LPCTSTR lpszHelp, UINT nCmd = HELP_CONTEXT, DWORD dwData = 0) { ATLASSERT(::IsWindow(m_hWnd)); return ::WinHelp(m_hWnd, lpszHelp, nCmd, dwData); }
BOOL SetWindowContextHelpId(DWORD dwContextHelpId) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetWindowContextHelpId(m_hWnd, dwContextHelpId); }
DWORD GetWindowContextHelpId() const { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindowContextHelpId(m_hWnd); }
// Hot Key Functions
int SetHotKey(WORD wVirtualKeyCode, WORD wModifiers) { ATLASSERT(::IsWindow(m_hWnd)); return (int)::SendMessage(m_hWnd, WM_SETHOTKEY, MAKEWORD(wVirtualKeyCode, wModifiers), 0); }
DWORD GetHotKey() const { ATLASSERT(::IsWindow(m_hWnd)); return (DWORD)::SendMessage(m_hWnd, WM_GETHOTKEY, 0, 0); }
// Misc. Operations
//N new
BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) { ATLASSERT(::IsWindow(m_hWnd)); return ::GetScrollInfo(m_hWnd, nBar, lpScrollInfo); } BOOL SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw); } BOOL IsDialogMessage(LPMSG lpMsg) { ATLASSERT(::IsWindow(m_hWnd)); return ::IsDialogMessage(m_hWnd, lpMsg); }
void NextDlgCtrl() const { ATLASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0L); } void PrevDlgCtrl() const { ATLASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 1, 0L); } void GotoDlgCtrl(HWND hWndCtrl) const { ATLASSERT(::IsWindow(m_hWnd)); ::SendMessage(m_hWnd, WM_NEXTDLGCTL, (WPARAM)hWndCtrl, 1L); }
BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw = TRUE) { ATLASSERT(::IsWindow(m_hWnd));
RECT rcWnd; if(!GetClientRect(&rcWnd)) return FALSE;
if(nWidth != -1) rcWnd.right = nWidth; if(nHeight != -1) rcWnd.bottom = nHeight;
if(!::AdjustWindowRectEx(&rcWnd, GetStyle(), (!(GetStyle() & WS_CHILD) && (GetMenu() != NULL)), GetExStyle())) return FALSE;
UINT uFlags = SWP_NOZORDER | SWP_NOMOVE; if(!bRedraw) uFlags |= SWP_NOREDRAW;
return SetWindowPos(NULL, 0, 0, rcWnd.right - rcWnd.left, rcWnd.bottom - rcWnd.top, uFlags); }
int GetWindowRgn(HRGN hRgn) { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindowRgn(m_hWnd, hRgn); } int SetWindowRgn(HRGN hRgn, BOOL bRedraw = FALSE) { ATLASSERT(::IsWindow(m_hWnd)); return ::SetWindowRgn(m_hWnd, hRgn, bRedraw); } HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) { ATLASSERT(::IsWindow(m_hWnd)); return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); } DWORD GetWindowThreadID() { ATLASSERT(::IsWindow(m_hWnd)); return ::GetWindowThreadProcessId(m_hWnd, NULL); } DWORD GetWindowProcessID() { ATLASSERT(::IsWindow(m_hWnd)); DWORD dwProcessID; ::GetWindowThreadProcessId(m_hWnd, &dwProcessID); return dwProcessID; } BOOL IsWindow() { return ::IsWindow(m_hWnd); } BOOL IsWindowUnicode() { ATLASSERT(::IsWindow(m_hWnd)); return ::IsWindowUnicode(m_hWnd); } BOOL IsParentDialog() { ATLASSERT(::IsWindow(m_hWnd)); TCHAR szBuf[8]; // "#32770" + NUL character
GetClassName(GetParent(), szBuf, sizeof(szBuf)/sizeof(TCHAR)); return lstrcmp(szBuf, _T("#32770")) == 0; } BOOL ShowWindowAsync(int nCmdShow) { ATLASSERT(::IsWindow(m_hWnd)); return ::ShowWindowAsync(m_hWnd, nCmdShow); }
HWND GetDescendantWindow(int nID) const { ATLASSERT(::IsWindow(m_hWnd));
// GetDlgItem recursive (return first found)
// breadth-first for 1 level, then depth-first for next level
// use GetDlgItem since it is a fast USER function
HWND hWndChild, hWndTmp; CWindow wnd; if((hWndChild = ::GetDlgItem(m_hWnd, nID)) != NULL) { if(::GetTopWindow(hWndChild) != NULL) { // children with the same ID as their parent have priority
wnd.Attach(hWndChild); hWndTmp = wnd.GetDescendantWindow(nID); if(hWndTmp != NULL) return hWndTmp; } return hWndChild; }
// walk each child
for(hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL; hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT)) { wnd.Attach(hWndChild); hWndTmp = wnd.GetDescendantWindow(nID); if(hWndTmp != NULL) return hWndTmp; }
return NULL; // not found
}
void SendMessageToDescendants(UINT message, WPARAM wParam = 0, LPARAM lParam = 0, BOOL bDeep = TRUE) { CWindow wnd; for(HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL; hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT)) { ::SendMessage(hWndChild, message, wParam, lParam);
if(bDeep && ::GetTopWindow(hWndChild) != NULL) { // send to child windows after parent
wnd.Attach(hWndChild); wnd.SendMessageToDescendants(message, wParam, lParam, bDeep); } } }
BOOL CenterWindow(HWND hWndCenter = NULL) { ATLASSERT(::IsWindow(m_hWnd));
// determine owner window to center against
DWORD dwStyle = GetStyle(); if(hWndCenter == NULL) { if(dwStyle & WS_CHILD) hWndCenter = ::GetParent(m_hWnd); else hWndCenter = ::GetWindow(m_hWnd, GW_OWNER); }
// get coordinates of the window relative to its parent
RECT rcDlg; ::GetWindowRect(m_hWnd, &rcDlg); RECT rcArea; RECT rcCenter; HWND hWndParent; if(!(dwStyle & WS_CHILD)) { // don't center against invisible or minimized windows
if(hWndCenter != NULL) { DWORD dwStyle = ::GetWindowLong(hWndCenter, GWL_STYLE); if(!(dwStyle & WS_VISIBLE) || (dwStyle & WS_MINIMIZE)) hWndCenter = NULL; }
// center within screen coordinates
::SystemParametersInfo(SPI_GETWORKAREA, NULL, &rcArea, NULL); if(hWndCenter == NULL) rcCenter = rcArea; else ::GetWindowRect(hWndCenter, &rcCenter); } else { // center within parent client coordinates
hWndParent = ::GetParent(m_hWnd); ATLASSERT(::IsWindow(hWndParent));
::GetClientRect(hWndParent, &rcArea); ATLASSERT(::IsWindow(hWndCenter)); ::GetClientRect(hWndCenter, &rcCenter); ::MapWindowPoints(hWndCenter, hWndParent, (POINT*)&rcCenter, 2); }
int DlgWidth = rcDlg.right - rcDlg.left; int DlgHeight = rcDlg.bottom - rcDlg.top;
// find dialog's upper left based on rcCenter
int xLeft = (rcCenter.left + rcCenter.right) / 2 - DlgWidth / 2; int yTop = (rcCenter.top + rcCenter.bottom) / 2 - DlgHeight / 2;
// if the dialog is outside the screen, move it inside
if(xLeft < rcArea.left) xLeft = rcArea.left; else if(xLeft + DlgWidth > rcArea.right) xLeft = rcArea.right - DlgWidth;
if(yTop < rcArea.top) yTop = rcArea.top; else if(yTop + DlgHeight > rcArea.bottom) yTop = rcArea.bottom - DlgHeight;
// map screen coordinates to child coordinates
return ::SetWindowPos(m_hWnd, NULL, xLeft, yTop, -1, -1, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); }
BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0) { ATLASSERT(::IsWindow(m_hWnd));
DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE); DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd; if(dwStyle == dwNewStyle) return FALSE;
::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle); if(nFlags != 0) { ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags); }
return TRUE; }
BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0) { ATLASSERT(::IsWindow(m_hWnd));
DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE); DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd; if(dwStyle == dwNewStyle) return FALSE;
::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwNewStyle); if(nFlags != 0) { ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags); }
return TRUE; }
BOOL GetWindowText(BSTR* pbstrText) { return GetWindowText(*pbstrText); } BOOL GetWindowText(BSTR& bstrText) { USES_CONVERSION; ATLASSERT(::IsWindow(m_hWnd)); if (bstrText != NULL) { SysFreeString(bstrText); bstrText = NULL; }
int nLen = ::GetWindowTextLength(m_hWnd); if(nLen == 0) { bstrText = ::SysAllocString(OLESTR("")); return (bstrText != NULL) ? TRUE : FALSE; }
LPTSTR lpszText = (LPTSTR)_alloca((nLen+1)*sizeof(TCHAR));
if(!::GetWindowText(m_hWnd, lpszText, nLen+1)) return FALSE;
bstrText = ::SysAllocString(T2OLE(lpszText)); return (bstrText != NULL) ? TRUE : FALSE; } HWND GetTopLevelParent() const { ATLASSERT(::IsWindow(m_hWnd));
HWND hWndParent = m_hWnd; HWND hWndTmp; while((hWndTmp = ::GetParent(hWndParent)) != NULL) hWndParent = hWndTmp;
return hWndParent; }
HWND GetTopLevelWindow() const { ATLASSERT(::IsWindow(m_hWnd));
HWND hWndParent; HWND hWndTmp = m_hWnd;
do { hWndParent = hWndTmp; hWndTmp = (::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD) ? ::GetParent(hWndParent) : ::GetWindow(hWndParent, GW_OWNER); } while(hWndTmp != NULL);
return hWndParent; } };
_declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
/////////////////////////////////////////////////////////////////////////////
// CAxWindow - client side for an ActiveX host window
#ifndef _ATL_NO_HOSTING
template <class TBase = CWindow> class CAxWindowT : public TBase { public: // Constructors
CAxWindowT(HWND hWnd = NULL) : TBase(hWnd) { }
CAxWindowT< TBase >& operator=(HWND hWnd) { m_hWnd = hWnd; return *this; }
// Attributes
static LPCTSTR GetWndClassName() { return _T("AtlAxWin"); }
// Operations
HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) { return CWindow::Create(GetWndClassName(), hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam); } HWND Create(HWND hWndParent, LPRECT lpRect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, HMENU hMenu = NULL, LPVOID lpCreateParam = NULL) { return CWindow::Create(GetWndClassName(), hWndParent, lpRect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam); }
HRESULT CreateControl(LPCOLESTR lpszName, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL) { ATLASSERT(::IsWindow(m_hWnd)); return AtlAxCreateControl(lpszName, m_hWnd, pStream, ppUnkContainer); }
HRESULT CreateControl(DWORD dwResID, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL) { TCHAR szModule[_MAX_PATH]; GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
CComBSTR bstrURL(OLESTR("res://")); bstrURL.Append(szModule); bstrURL.Append(OLESTR("/")); TCHAR szResID[11]; wsprintf(szResID, _T("%0d"), dwResID); bstrURL.Append(szResID);
ATLASSERT(::IsWindow(m_hWnd)); return AtlAxCreateControl(bstrURL, m_hWnd, pStream, ppUnkContainer); }
HRESULT CreateControlEx(LPCOLESTR lpszName, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL, REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL) { ATLASSERT(::IsWindow(m_hWnd)); return AtlAxCreateControlEx(lpszName, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink); }
HRESULT CreateControlEx(DWORD dwResID, IStream* pStream = NULL, IUnknown** ppUnkContainer = NULL, IUnknown** ppUnkControl = NULL, REFIID iidSink = IID_NULL, IUnknown* punkSink = NULL) { TCHAR szModule[_MAX_PATH]; GetModuleFileName(_Module.GetModuleInstance(), szModule, _MAX_PATH);
CComBSTR bstrURL(OLESTR("res://")); bstrURL.Append(szModule); bstrURL.Append(OLESTR("/")); TCHAR szResID[11]; wsprintf(szResID, _T("%0d"), dwResID); bstrURL.Append(szResID);
ATLASSERT(::IsWindow(m_hWnd)); return AtlAxCreateControlEx(bstrURL, m_hWnd, pStream, ppUnkContainer, ppUnkControl, iidSink, punkSink); }
HRESULT AttachControl(IUnknown* pControl, IUnknown** ppUnkContainer) { ATLASSERT(::IsWindow(m_hWnd)); return AtlAxAttachControl(pControl, m_hWnd, ppUnkContainer); } HRESULT QueryHost(REFIID iid, void** ppUnk) { ATLASSERT(ppUnk != NULL); HRESULT hr; *ppUnk = NULL; CComPtr<IUnknown> spUnk; hr = AtlAxGetHost(m_hWnd, &spUnk); if (SUCCEEDED(hr)) hr = spUnk->QueryInterface(iid, ppUnk); return hr; } template <class Q> HRESULT QueryHost(Q** ppUnk) { return QueryHost(__uuidof(Q), (void**)ppUnk); } HRESULT QueryControl(REFIID iid, void** ppUnk) { ATLASSERT(ppUnk != NULL); HRESULT hr; *ppUnk = NULL; CComPtr<IUnknown> spUnk; hr = AtlAxGetControl(m_hWnd, &spUnk); if (SUCCEEDED(hr)) hr = spUnk->QueryInterface(iid, ppUnk); return hr; } template <class Q> HRESULT QueryControl(Q** ppUnk) { return QueryControl(__uuidof(Q), (void**)ppUnk); } HRESULT SetExternalDispatch(IDispatch* pDisp) { HRESULT hr; CComPtr<IAxWinHostWindow> spHost; hr = QueryHost(IID_IAxWinHostWindow, (void**)&spHost); if (SUCCEEDED(hr)) hr = spHost->SetExternalDispatch(pDisp); return hr; } HRESULT SetExternalUIHandler(IDocHostUIHandlerDispatch* pUIHandler) { HRESULT hr; CComPtr<IAxWinHostWindow> spHost; hr = QueryHost(IID_IAxWinHostWindow, (void**)&spHost); if (SUCCEEDED(hr)) hr = spHost->SetExternalUIHandler(pUIHandler); return hr; } };
typedef CAxWindowT<CWindow> CAxWindow;
#endif //_ATL_NO_HOSTING
/////////////////////////////////////////////////////////////////////////////
// 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; \ uMsg; \ wParam; \ lParam; \ lResult; \ bHandled; \ 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 END_MSG_MAP() \
break; \ default: \ ATLTRACE2(atlTraceWindowing, 0, _T("Invalid message map ID (%i)\n"), dwMsgMapID); \ ATLASSERT(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);
// Empty message map macro
#define DECLARE_EMPTY_MSG_MAP() \
public: \ BOOL ProcessWindowMessage(HWND, UINT, WPARAM, LPARAM, LRESULT&, DWORD) \ { \ return FALSE; \ }
// Message reflection macros
#define REFLECT_NOTIFICATIONS() \
{ \ bHandled = TRUE; \ lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled); \ if(bHandled) \ return TRUE; \ }
#define DEFAULT_REFLECTION_HANDLER() \
if(DefaultReflectionHandler(hWnd, uMsg, wParam, lParam, lResult)) \ return TRUE;
/////////////////////////////////////////////////////////////////////////////
// CDynamicChain - provides support for dynamic chaining
class CDynamicChain { public: struct ATL_CHAIN_ENTRY { DWORD m_dwChainID; CMessageMap* m_pObject; DWORD m_dwMsgMapID; };
CSimpleArray<ATL_CHAIN_ENTRY*> m_aChainEntry;
CDynamicChain() { }
~CDynamicChain() { for(int i = 0; i < m_aChainEntry.GetSize(); i++) { if(m_aChainEntry[i] != NULL) delete m_aChainEntry[i]; } }
BOOL SetChainEntry(DWORD dwChainID, CMessageMap* pObject, DWORD dwMsgMapID = 0) { // first search for an existing entry
for(int i = 0; i < m_aChainEntry.GetSize(); i++) { if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID) { m_aChainEntry[i]->m_pObject = pObject; m_aChainEntry[i]->m_dwMsgMapID = dwMsgMapID; return TRUE; } }
// create a new one
ATL_CHAIN_ENTRY* pEntry = NULL; ATLTRY(pEntry = new ATL_CHAIN_ENTRY);
if(pEntry == NULL) return FALSE;
pEntry->m_dwChainID = dwChainID; pEntry->m_pObject = pObject; pEntry->m_dwMsgMapID = dwMsgMapID;
// search for an empty one
for(i = 0; i < m_aChainEntry.GetSize(); i++) { if(m_aChainEntry[i] == NULL) { m_aChainEntry[i] = pEntry; return TRUE; } }
// add a new one
BOOL bRet = m_aChainEntry.Add(pEntry);
if(!bRet) { delete pEntry; return FALSE; }
return TRUE; }
BOOL RemoveChainEntry(DWORD dwChainID) { for(int i = 0; i < m_aChainEntry.GetSize(); i++) { if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID) { delete m_aChainEntry[i]; m_aChainEntry[i] = NULL; return TRUE; } }
return FALSE; }
BOOL CallChain(DWORD dwChainID, HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult) { for(int i = 0; i < m_aChainEntry.GetSize(); i++) { if(m_aChainEntry[i] != NULL && m_aChainEntry[i]->m_dwChainID == dwChainID) return (m_aChainEntry[i]->m_pObject)->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, m_aChainEntry[i]->m_dwMsgMapID); }
return FALSE; } };
/////////////////////////////////////////////////////////////////////////////
// CWndClassInfo - Manages Windows class information
#define DECLARE_WND_CLASS(WndClassName) \
static CWndClassInfo& GetWndClassInfo() \ { \ static CWndClassInfo wc = \ { \ { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, StartWindowProc, \ 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \ NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \ }; \ return wc; \ }
#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \
static CWndClassInfo& GetWndClassInfo() \ { \ static CWndClassInfo wc = \ { \ { sizeof(WNDCLASSEX), style, StartWindowProc, \ 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \ NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \ }; \ return wc; \ }
#define DECLARE_WND_SUPERCLASS(WndClassName, OrigWndClassName) \
static CWndClassInfo& GetWndClassInfo() \ { \ static CWndClassInfo wc = \ { \ { sizeof(WNDCLASSEX), 0, StartWindowProc, \ 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \ OrigWndClassName, NULL, NULL, TRUE, 0, _T("") \ }; \ return wc; \ }
/////////////////////////////////////////////////////////////////////////////
// CWinTraits - Defines various default values for a window
template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0> class CWinTraits { public: static DWORD GetWndStyle(DWORD dwStyle) { return dwStyle == 0 ? t_dwStyle : dwStyle; } static DWORD GetWndExStyle(DWORD dwExStyle) { return dwExStyle == 0 ? t_dwExStyle : dwExStyle; } };
typedef CWinTraits<WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0> CControlWinTraits; typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE> CFrameWinTraits; typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_MDICHILD> CMDIChildWinTraits;
typedef CWinTraits<0, 0> CNullTraits;
template <DWORD t_dwStyle = 0, DWORD t_dwExStyle = 0, class TWinTraits = CControlWinTraits> class CWinTraitsOR { public: static DWORD GetWndStyle(DWORD dwStyle) { return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle); } static DWORD GetWndExStyle(DWORD dwExStyle) { return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle); } };
/////////////////////////////////////////////////////////////////////////////
// CWindowImpl - Implements a window
template <class TBase = CWindow> class ATL_NO_VTABLE CWindowImplRoot : public TBase, public CMessageMap { public: CWndProcThunk m_thunk; const MSG* m_pCurrentMsg;
// Constructor/destructor
CWindowImplRoot() : m_pCurrentMsg(NULL) { }
~CWindowImplRoot() { #ifdef _DEBUG
if(m_hWnd != NULL) // should be cleared in WindowProc
{ ATLTRACE2(atlTraceWindowing, 0, _T("ERROR - Object deleted before window was destroyed\n")); ATLASSERT(FALSE); } #endif //_DEBUG
}
// Current message
const MSG* GetCurrentMessage() const { return m_pCurrentMsg; }
// Message reflection support
LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); static BOOL DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult); };
template <class TBase> LRESULT CWindowImplRoot< TBase >::ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { HWND hWndChild = NULL;
switch(uMsg) { case WM_COMMAND: if(lParam != NULL) // not from a menu
hWndChild = (HWND)lParam; break; case WM_NOTIFY: hWndChild = ((LPNMHDR)lParam)->hwndFrom; break; case WM_PARENTNOTIFY: switch(LOWORD(wParam)) { case WM_CREATE: case WM_DESTROY: hWndChild = (HWND)lParam; break; default: hWndChild = GetDlgItem(HIWORD(wParam)); break; } break; case WM_DRAWITEM: if(wParam) // not from a menu
hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem; break; case WM_MEASUREITEM: if(wParam) // not from a menu
hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID); break; case WM_COMPAREITEM: if(wParam) // not from a menu
hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID); break; case WM_DELETEITEM: if(wParam) // not from a menu
hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID); break; case WM_VKEYTOITEM: case WM_CHARTOITEM: case WM_HSCROLL: case WM_VSCROLL: hWndChild = (HWND)lParam; break; case WM_CTLCOLORBTN: case WM_CTLCOLORDLG: case WM_CTLCOLOREDIT: case WM_CTLCOLORLISTBOX: case WM_CTLCOLORMSGBOX: case WM_CTLCOLORSCROLLBAR: case WM_CTLCOLORSTATIC: hWndChild = (HWND)lParam; break; default: break; }
if(hWndChild == NULL) { bHandled = FALSE; return 1; }
ATLASSERT(::IsWindow(hWndChild)); return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam); }
template <class TBase> BOOL CWindowImplRoot< TBase >::DefaultReflectionHandler(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult) { switch(uMsg) { case OCM_COMMAND: case OCM_NOTIFY: case OCM_PARENTNOTIFY: case OCM_DRAWITEM: case OCM_MEASUREITEM: case OCM_COMPAREITEM: case OCM_DELETEITEM: case OCM_VKEYTOITEM: case OCM_CHARTOITEM: case OCM_HSCROLL: case OCM_VSCROLL: case OCM_CTLCOLORBTN: case OCM_CTLCOLORDLG: case OCM_CTLCOLOREDIT: case OCM_CTLCOLORLISTBOX: case OCM_CTLCOLORMSGBOX: case OCM_CTLCOLORSCROLLBAR: case OCM_CTLCOLORSTATIC: lResult = ::DefWindowProc(hWnd, uMsg - OCM__BASE, wParam, lParam); return TRUE; default: break; } return FALSE; }
template <class TBase = CWindow, class TWinTraits = CControlWinTraits> class ATL_NO_VTABLE CWindowImplBaseT : public CWindowImplRoot< TBase > { public: WNDPROC m_pfnSuperWindowProc;
CWindowImplBaseT() : m_pfnSuperWindowProc(::DefWindowProc) {}
static DWORD GetWndStyle(DWORD dwStyle) { return TWinTraits::GetWndStyle(dwStyle); } static DWORD GetWndExStyle(DWORD dwExStyle) { return TWinTraits::GetWndExStyle(dwExStyle); }
virtual WNDPROC GetWindowProc() { return WindowProc; } 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 nID, ATOM atom, LPVOID lpCreateParam = NULL); BOOL DestroyWindow() { ATLASSERT(::IsWindow(m_hWnd)); return ::DestroyWindow(m_hWnd); } BOOL SubclassWindow(HWND hWnd); HWND UnsubclassWindow(BOOL bForce = FALSE);
LRESULT DefWindowProc() { const MSG* pMsg = m_pCurrentMsg; LRESULT lRes = 0; if (pMsg != NULL) lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam); return lRes; }
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
}
virtual void OnFinalMessage(HWND /*hWnd*/) { // override to do something, if needed
} };
typedef CWindowImplBaseT<CWindow> CWindowImplBase;
template <class TBase, class TWinTraits> LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)_Module.ExtractCreateWndData(); ATLASSERT(pThis != NULL); pThis->m_hWnd = hWnd; pThis->m_thunk.Init(pThis->GetWindowProc(), pThis); WNDPROC pProc = (WNDPROC)(pThis->m_thunk.thunk.pThunk); WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LPARAM)pProc); #ifdef _DEBUG
// check if somebody has subclassed us already since we discard it
if(pOldProc != StartWindowProc) ATLTRACE2(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n")); #else
pOldProc; // avoid unused warning
#endif
return pProc(hWnd, uMsg, wParam, lParam); }
template <class TBase, class TWinTraits> LRESULT CALLBACK CWindowImplBaseT< TBase, TWinTraits >::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CWindowImplBaseT< TBase, TWinTraits >* pThis = (CWindowImplBaseT< TBase, TWinTraits >*)hWnd; // set a ptr to this message and save the old value
MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } }; const MSG* pOldMsg = pThis->m_pCurrentMsg; pThis->m_pCurrentMsg = &msg; // pass to the message map to process
LRESULT lRes; BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0); // restore saved value for the current message
ATLASSERT(pThis->m_pCurrentMsg == &msg); pThis->m_pCurrentMsg = pOldMsg; // do the default processing if message was not handled
if(!bRet) { if(uMsg != WM_NCDESTROY) lRes = pThis->DefWindowProc(uMsg, wParam, lParam); else { // unsubclass, if needed
LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC); lRes = pThis->DefWindowProc(uMsg, wParam, lParam); if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc) ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc); // clear out window handle
HWND hWnd = pThis->m_hWnd; pThis->m_hWnd = NULL; // clean up after window is destroyed
pThis->OnFinalMessage(hWnd); } } return lRes; }
template <class TBase, class TWinTraits> HWND CWindowImplBaseT< TBase, TWinTraits >::Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, UINT nID, ATOM atom, LPVOID lpCreateParam) { ATLASSERT(m_hWnd == NULL);
if(atom == 0) return NULL;
_Module.AddCreateWndData(&m_thunk.cd, this);
if(nID == 0 && (dwStyle & WS_CHILD)) #if _ATL_VER > 0x0300
nID = _Module.GetNextWindowID(); #else
nID = (UINT)this; #endif
HWND hWnd = ::CreateWindowEx(dwExStyle, (LPCTSTR)(LONG_PTR)MAKELONG(atom, 0), szWindowName, dwStyle, rcPos.left, rcPos.top, rcPos.right - rcPos.left, rcPos.bottom - rcPos.top, hWndParent, (HMENU)(DWORD_PTR)nID, _Module.GetModuleInstance(), lpCreateParam);
ATLASSERT(m_hWnd == hWnd);
return hWnd; }
template <class TBase, class TWinTraits> BOOL CWindowImplBaseT< TBase, TWinTraits >::SubclassWindow(HWND hWnd) { ATLASSERT(m_hWnd == NULL); ATLASSERT(::IsWindow(hWnd)); m_thunk.Init(GetWindowProc(), this); WNDPROC pProc = (WNDPROC)(m_thunk.thunk.pThunk); WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LPARAM)pProc); if(pfnWndProc == NULL) return FALSE; m_pfnSuperWindowProc = pfnWndProc; m_hWnd = hWnd; return TRUE; }
// Use only if you want to subclass before window is destroyed,
// WindowProc will automatically subclass when window goes away
template <class TBase, class TWinTraits> HWND CWindowImplBaseT< TBase, TWinTraits >::UnsubclassWindow(BOOL bForce /*= FALSE*/) { ATLASSERT(m_hWnd != NULL);
WNDPROC pOurProc = (WNDPROC)(m_thunk.thunk.pThunk); WNDPROC pActiveProc = (WNDPROC)::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC);
HWND hWnd = NULL; if (bForce || pOurProc == pActiveProc) { if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc)) return NULL;
m_pfnSuperWindowProc = ::DefWindowProc; hWnd = m_hWnd; m_hWnd = NULL; } return hWnd; }
template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits> class ATL_NO_VTABLE CWindowImpl : public CWindowImplBaseT< TBase, TWinTraits > { public: DECLARE_WND_CLASS(NULL)
HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) { if (T::GetWndClassInfo().m_lpszOrigName == NULL) T::GetWndClassInfo().m_lpszOrigName = GetWndClassName(); ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
dwStyle = T::GetWndStyle(dwStyle); dwExStyle = T::GetWndExStyle(dwExStyle);
return CWindowImplBaseT< TBase, TWinTraits >::Create(hWndParent, rcPos, szWindowName, dwStyle, dwExStyle, nID, atom, lpCreateParam); } };
/////////////////////////////////////////////////////////////////////////////
// CDialogImpl - Implements a dialog box
template <class TBase = CWindow> class ATL_NO_VTABLE CDialogImplBaseT : public CWindowImplRoot< TBase > { public: virtual WNDPROC GetDialogProc() { return DialogProc; } static LRESULT CALLBACK StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL MapDialogRect(LPRECT lpRect) { ATLASSERT(::IsWindow(m_hWnd)); return ::MapDialogRect(m_hWnd, lpRect); } virtual void OnFinalMessage(HWND /*hWnd*/) { // override to do something, if needed
} // has no meaning for a dialog, but needed for handlers that use it
LRESULT DefWindowProc() { return 0; } };
template <class TBase> LRESULT CALLBACK CDialogImplBaseT< TBase >::StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)_Module.ExtractCreateWndData(); ATLASSERT(pThis != NULL); pThis->m_hWnd = hWnd; pThis->m_thunk.Init(pThis->GetDialogProc(), pThis); WNDPROC pProc = (WNDPROC)(pThis->m_thunk.thunk.pThunk); WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LPARAM)pProc); #ifdef _DEBUG
// check if somebody has subclassed us already since we discard it
if(pOldProc != StartDialogProc) ATLTRACE2(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n")); #else
pOldProc; // avoid unused warning
#endif
return pProc(hWnd, uMsg, wParam, lParam); }
template <class TBase> LRESULT CALLBACK CDialogImplBaseT< TBase >::DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CDialogImplBaseT< TBase >* pThis = (CDialogImplBaseT< TBase >*)hWnd; // set a ptr to this message and save the old value
MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } }; const MSG* pOldMsg = pThis->m_pCurrentMsg; pThis->m_pCurrentMsg = &msg; // pass to the message map to process
LRESULT lRes; BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0); // restore saved value for the current message
ATLASSERT(pThis->m_pCurrentMsg == &msg); pThis->m_pCurrentMsg = pOldMsg; // set result if message was handled
if(bRet) { switch (uMsg) { case WM_COMPAREITEM: case WM_VKEYTOITEM: case WM_CHARTOITEM: case WM_INITDIALOG: case WM_QUERYDRAGICON: case WM_CTLCOLORMSGBOX: case WM_CTLCOLOREDIT: case WM_CTLCOLORLISTBOX: case WM_CTLCOLORBTN: case WM_CTLCOLORDLG: case WM_CTLCOLORSCROLLBAR: case WM_CTLCOLORSTATIC: return lRes; break; } ::SetWindowLongPtr(pThis->m_hWnd, DWLP_MSGRESULT, lRes); return TRUE; } if(uMsg == WM_NCDESTROY) { // clear out window handle
HWND hWnd = pThis->m_hWnd; pThis->m_hWnd = NULL; // clean up after dialog is destroyed
pThis->OnFinalMessage(hWnd); } return FALSE; }
typedef CDialogImplBaseT<CWindow> CDialogImplBase;
template <class T, class TBase = CWindow> class ATL_NO_VTABLE CDialogImpl : public CDialogImplBaseT< TBase > { public: #ifdef _DEBUG
bool m_bModal; CDialogImpl() : m_bModal(false) { } #endif //_DEBUG
// modal dialogs
INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) { ATLASSERT(m_hWnd == NULL); _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); #ifdef _DEBUG
m_bModal = true; #endif //_DEBUG
return ::DialogBoxParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam); } BOOL EndDialog(INT_PTR nRetCode) { ATLASSERT(::IsWindow(m_hWnd)); ATLASSERT(m_bModal); // must be a modal dialog
return ::EndDialog(m_hWnd, nRetCode); } // modeless dialogs
HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) { ATLASSERT(m_hWnd == NULL); _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); #ifdef _DEBUG
m_bModal = false; #endif //_DEBUG
HWND hWnd = ::CreateDialogParam(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam); ATLASSERT(m_hWnd == hWnd); return hWnd; } // for CComControl
HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL) { return Create(hWndParent, dwInitParam); } BOOL DestroyWindow() { ATLASSERT(::IsWindow(m_hWnd)); ATLASSERT(!m_bModal); // must not be a modal dialog
return ::DestroyWindow(m_hWnd); } };
/////////////////////////////////////////////////////////////////////////////
// CAxDialogImpl - Implements a dialog box that hosts ActiveX controls
#ifndef _ATL_NO_HOSTING
template <class T, class TBase = CWindow> class ATL_NO_VTABLE CAxDialogImpl : public CDialogImplBaseT< TBase > { public: #ifdef _DEBUG
bool m_bModal; CAxDialogImpl() : m_bModal(false) { } #endif //_DEBUG
// modal dialogs
INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) { ATLASSERT(m_hWnd == NULL); _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); #ifdef _DEBUG
m_bModal = true; #endif //_DEBUG
return AtlAxDialogBox(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam); } BOOL EndDialog(int nRetCode) { ATLASSERT(::IsWindow(m_hWnd)); ATLASSERT(m_bModal); // must be a modal dialog
return ::EndDialog(m_hWnd, nRetCode); } // modeless dialogs
HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) { ATLASSERT(m_hWnd == NULL); _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBaseT< TBase >*)this); #ifdef _DEBUG
m_bModal = false; #endif //_DEBUG
HWND hWnd = AtlAxCreateDialog(_Module.GetResourceInstance(), MAKEINTRESOURCE(T::IDD), hWndParent, (DLGPROC)T::StartDialogProc, dwInitParam); ATLASSERT(m_hWnd == hWnd); return hWnd; } // for CComControl
HWND Create(HWND hWndParent, RECT&, LPARAM dwInitParam = NULL) { return Create(hWndParent, dwInitParam); } BOOL DestroyWindow() { ATLASSERT(::IsWindow(m_hWnd)); ATLASSERT(!m_bModal); // must not be a modal dialog
return ::DestroyWindow(m_hWnd); } };
#endif //_ATL_NO_HOSTING
/////////////////////////////////////////////////////////////////////////////
// CSimpleDialog - Prebuilt modal dialog that uses standard buttons
template <WORD t_wDlgTemplateID, BOOL t_bCenter = TRUE> class CSimpleDialog : public CDialogImplBase { public: INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow()) { ATLASSERT(m_hWnd == NULL); _Module.AddCreateWndData(&m_thunk.cd, (CDialogImplBase*)this); INT_PTR nRet = ::DialogBox(_Module.GetResourceInstance(), MAKEINTRESOURCE(t_wDlgTemplateID), hWndParent, (DLGPROC)StartDialogProc); m_hWnd = NULL; return nRet; }
typedef CSimpleDialog<t_wDlgTemplateID, t_bCenter> thisClass; BEGIN_MSG_MAP(thisClass) MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) COMMAND_RANGE_HANDLER(IDOK, IDNO, OnCloseCmd) END_MSG_MAP()
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { if(t_bCenter) CenterWindow(GetParent()); return TRUE; }
LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { ::EndDialog(m_hWnd, wID); return 0; } };
/////////////////////////////////////////////////////////////////////////////
// CContainedWindow - Implements a contained window
template <class TBase = CWindow, class TWinTraits = CControlWinTraits> class CContainedWindowT : public TBase { public: CWndProcThunk m_thunk; LPCTSTR m_lpszClassName; WNDPROC m_pfnSuperWindowProc; CMessageMap* m_pObject; DWORD m_dwMsgMapID; const MSG* m_pCurrentMsg;
// If you use this constructor you must supply
// the Window Class Name, Object* and Message Map ID
// Later to the Create call
CContainedWindowT() : m_pCurrentMsg(NULL) { }
CContainedWindowT(LPTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID = 0) : m_lpszClassName(lpszClassName), m_pfnSuperWindowProc(::DefWindowProc), m_pObject(pObject), m_dwMsgMapID(dwMsgMapID), m_pCurrentMsg(NULL) { }
CContainedWindowT(CMessageMap* pObject, DWORD dwMsgMapID = 0) : m_lpszClassName(TBase::GetWndClassName()), m_pfnSuperWindowProc(::DefWindowProc), m_pObject(pObject), m_dwMsgMapID(dwMsgMapID), m_pCurrentMsg(NULL) { }
void SwitchMessageMap(DWORD dwMsgMapID) { m_dwMsgMapID = dwMsgMapID; }
const MSG* GetCurrentMessage() const { return m_pCurrentMsg; }
LRESULT DefWindowProc() { const MSG* pMsg = m_pCurrentMsg; LRESULT lRes = 0; if (pMsg != NULL) lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam); return lRes; }
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
} static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)_Module.ExtractCreateWndData(); ATLASSERT(pThis != NULL); pThis->m_hWnd = hWnd; pThis->m_thunk.Init(WindowProc, pThis); WNDPROC pProc = (WNDPROC)(pThis->m_thunk.thunk.pThunk); WNDPROC pOldProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc); #ifdef _DEBUG
// check if somebody has subclassed us already since we discard it
if(pOldProc != StartWindowProc) ATLTRACE2(atlTraceWindowing, 0, _T("Subclassing through a hook discarded.\n")); #else
pOldProc; // avoid unused warning
#endif
return pProc(hWnd, uMsg, wParam, lParam); }
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CContainedWindowT< TBase >* pThis = (CContainedWindowT< TBase >*)hWnd; ATLASSERT(pThis->m_hWnd != NULL); ATLASSERT(pThis->m_pObject != NULL); // set a ptr to this message and save the old value
MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } }; const MSG* pOldMsg = pThis->m_pCurrentMsg; pThis->m_pCurrentMsg = &msg; // pass to the message map to process
LRESULT lRes; BOOL bRet = pThis->m_pObject->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, pThis->m_dwMsgMapID); // restore saved value for the current message
ATLASSERT(pThis->m_pCurrentMsg == &msg); pThis->m_pCurrentMsg = pOldMsg; // do the default processing if message was not handled
if(!bRet) { if(uMsg != WM_NCDESTROY) lRes = pThis->DefWindowProc(uMsg, wParam, lParam); else { // unsubclass, if needed
LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC); lRes = pThis->DefWindowProc(uMsg, wParam, lParam); if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc) ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc); // clear out window handle
pThis->m_hWnd = NULL; } } return lRes; }
ATOM RegisterWndSuperclass() { ATOM atom = 0; LPTSTR szBuff = (LPTSTR)_alloca((lstrlen(m_lpszClassName) + 14) * sizeof(TCHAR));
WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX);
// Try global class
if(!::GetClassInfoEx(NULL, m_lpszClassName, &wc)) { // try local class
if(!::GetClassInfoEx(_Module.GetModuleInstance(), m_lpszClassName, &wc)) return atom; }
m_pfnSuperWindowProc = wc.lpfnWndProc; lstrcpy(szBuff, _T("ATL:")); lstrcat(szBuff, m_lpszClassName);
WNDCLASSEX wc1; wc1.cbSize = sizeof(WNDCLASSEX); atom = (ATOM)::GetClassInfoEx(_Module.GetModuleInstance(), szBuff, &wc1);
if(atom == 0) // register class
{ wc.lpszClassName = szBuff; wc.lpfnWndProc = StartWindowProc; wc.hInstance = _Module.GetModuleInstance(); wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
atom = ::RegisterClassEx(&wc); }
return atom; } HWND Create(CMessageMap* pObject, DWORD dwMsgMapID, HWND hWndParent, RECT* prcPos, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) { m_lpszClassName = TBase::GetWndClassName(); m_pfnSuperWindowProc = ::DefWindowProc; m_pObject = pObject; m_dwMsgMapID = dwMsgMapID; return Create(hWndParent, prcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam); }
HWND Create(LPCTSTR lpszClassName, CMessageMap* pObject, DWORD dwMsgMapID, HWND hWndParent, RECT* prcPos, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) { m_lpszClassName = lpszClassName; m_pfnSuperWindowProc = ::DefWindowProc; m_pObject = pObject; m_dwMsgMapID = dwMsgMapID; return Create(hWndParent, prcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam); }
// This function is Deprecated, use the version
// which takes a RECT* instead
HWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) { return Create(hWndParent, &rcPos, szWindowName, dwStyle, dwExStyle, nID, lpCreateParam); }
HWND Create(HWND hWndParent, RECT* prcPos, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL) { ATLASSERT(m_hWnd == NULL);
ATOM atom = RegisterWndSuperclass(); if(atom == 0) return NULL;
_Module.AddCreateWndData(&m_thunk.cd, this);
dwStyle = TWinTraits::GetWndStyle(dwStyle); dwExStyle = TWinTraits::GetWndExStyle(dwExStyle);
HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, dwStyle, prcPos->left, prcPos->top, prcPos->right - prcPos->left, prcPos->bottom - prcPos->top, hWndParent, (nID == 0 && (dwStyle & WS_CHILD)) ? (HMENU)this : (HMENU)(DWORD_PTR)nID, _Module.GetModuleInstance(), lpCreateParam); ATLASSERT(m_hWnd == hWnd); return hWnd; }
BOOL SubclassWindow(HWND hWnd) { ATLASSERT(m_hWnd == NULL); ATLASSERT(::IsWindow(hWnd));
m_thunk.Init(WindowProc, this); WNDPROC pProc = (WNDPROC)m_thunk.thunk.pThunk; WNDPROC pfnWndProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)pProc); if(pfnWndProc == NULL) return FALSE; m_pfnSuperWindowProc = pfnWndProc; m_hWnd = hWnd; return TRUE; }
// Use only if you want to subclass before window is destroyed,
// WindowProc will automatically subclass when window goes away
HWND UnsubclassWindow(BOOL bForce = FALSE) { ATLASSERT(m_hWnd != NULL);
WNDPROC pOurProc = (WNDPROC)(m_thunk.thunk.pThunk); WNDPROC pActiveProc = (WNDPROC)::GetWindowLongPtr(m_hWnd, GWLP_WNDPROC);
HWND hWnd = NULL; if (bForce || pOurProc == pActiveProc) { if(!::SetWindowLongPtr(m_hWnd, GWLP_WNDPROC, (LONG_PTR)m_pfnSuperWindowProc)) return NULL;
m_pfnSuperWindowProc = ::DefWindowProc; hWnd = m_hWnd; m_hWnd = NULL; } return hWnd; } };
typedef CContainedWindowT<CWindow> CContainedWindow;
/////////////////////////////////////////////////////////////////////////////
// _DialogSizeHelper - helpers for calculating the size of a dialog template
class _DialogSizeHelper { public: //local struct used for implementation
#pragma pack(push, 1)
struct _ATL_DLGTEMPLATEEX { WORD dlgVer; WORD signature; DWORD helpID; DWORD exStyle; DWORD style; WORD cDlgItems; short x; short y; short cx; short cy; }; #pragma pack(pop)
static void GetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize) { // If the dialog has a font we use it otherwise we default
// to the system font.
if (HasFont(pTemplate)) { TCHAR szFace[LF_FACESIZE]; WORD wFontSize = 0; GetFont(pTemplate, szFace, &wFontSize); GetSizeInDialogUnits(pTemplate, pSize); ConvertDialogUnitsToPixels(szFace, wFontSize, pSize); } else { GetSizeInDialogUnits(pTemplate, pSize); LONG nDlgBaseUnits = GetDialogBaseUnits(); pSize->cx = MulDiv(pSize->cx, LOWORD(nDlgBaseUnits), 4); pSize->cy = MulDiv(pSize->cy, HIWORD(nDlgBaseUnits), 8); } }
static void ConvertDialogUnitsToPixels(LPCTSTR pszFontFace, WORD wFontSize, SIZE* pSizePixel) { // Attempt to create the font to be used in the dialog box
UINT cxSysChar, cySysChar; LOGFONT lf; HDC hDC = ::GetDC(NULL); int cxDlg = pSizePixel->cx; int cyDlg = pSizePixel->cy;
ZeroMemory(&lf, sizeof(LOGFONT)); lf.lfHeight = -MulDiv(wFontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72); lf.lfWeight = FW_NORMAL; lf.lfCharSet = DEFAULT_CHARSET; lstrcpy(lf.lfFaceName, pszFontFace);
HFONT hNewFont = CreateFontIndirect(&lf); if (hNewFont != NULL) { TEXTMETRIC tm; SIZE size; HFONT hFontOld = (HFONT)SelectObject(hDC, hNewFont); GetTextMetrics(hDC, &tm); cySysChar = tm.tmHeight + tm.tmExternalLeading; ::GetTextExtentPoint(hDC, _T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52, &size); cxSysChar = (size.cx + 26) / 52; SelectObject(hDC, hFontOld); DeleteObject(hNewFont); } else { // Could not create the font so just use the system's values
cxSysChar = LOWORD(GetDialogBaseUnits()); cySysChar = HIWORD(GetDialogBaseUnits()); } ::ReleaseDC(NULL, hDC);
// Translate dialog units to pixels
pSizePixel->cx = MulDiv(cxDlg, cxSysChar, 4); pSizePixel->cy = MulDiv(cyDlg, cySysChar, 8); }
static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate) { return ((_ATL_DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF; }
static BOOL HasFont(const DLGTEMPLATE* pTemplate) { return (DS_SETFONT & (IsDialogEx(pTemplate) ? ((_ATL_DLGTEMPLATEEX*)pTemplate)->style : pTemplate->style)); }
static BYTE* GetFontSizeField(const DLGTEMPLATE* pTemplate) { BOOL bDialogEx = IsDialogEx(pTemplate); WORD* pw;
if (bDialogEx) pw = (WORD*)((_ATL_DLGTEMPLATEEX*)pTemplate + 1); else pw = (WORD*)(pTemplate + 1);
if (*pw == (WORD)-1) // Skip menu name string or ordinal
pw += 2; // WORDs
else while(*pw++);
if (*pw == (WORD)-1) // Skip class name string or ordinal
pw += 2; // WORDs
else while(*pw++);
while (*pw++); // Skip caption string
return (BYTE*)pw; }
static BOOL GetFont(const DLGTEMPLATE* pTemplate, TCHAR* pszFace, WORD* pFontSize) { USES_CONVERSION; if (!HasFont(pTemplate)) return FALSE;
BYTE* pb = GetFontSizeField(pTemplate); *pFontSize = *(WORD*)pb; // Skip over font attributes to get to the font name
pb += sizeof(WORD) * (IsDialogEx(pTemplate) ? 3 : 1);
_tcscpy(pszFace, W2T((WCHAR*)pb)); return TRUE; }
static void GetSizeInDialogUnits(const DLGTEMPLATE* pTemplate, SIZE* pSize) { if (IsDialogEx(pTemplate)) { pSize->cx = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cx; pSize->cy = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cy; } else { pSize->cx = pTemplate->cx; pSize->cy = pTemplate->cy; } } };
inline void AtlGetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize) { _DialogSizeHelper::GetDialogSize(pTemplate, pSize); }
}; //namespace ATL
#ifndef _ATL_DLL_IMPL
#ifndef _ATL_DLL
#define _ATLWIN_IMPL
#endif
#endif
#endif // __ATLWIN_H__
//All exports go here
#ifdef _ATLWIN_IMPL
#ifndef _ATL_DLL_IMPL
namespace ATL { #endif
ATLINLINE ATLAPI_(ATOM) AtlModuleRegisterWndClassInfoA(_ATL_MODULE* pM, _ATL_WNDCLASSINFOA* p, WNDPROC* pProc) { if (p->m_atom == 0) { ::EnterCriticalSection(&pM->m_csWindowCreate); if(p->m_atom == 0) { HINSTANCE hInst = pM->m_hInst; if (p->m_lpszOrigName != NULL) { ATLASSERT(pProc != NULL); LPCSTR lpsz = p->m_wc.lpszClassName; WNDPROC proc = p->m_wc.lpfnWndProc;
WNDCLASSEXA wc; wc.cbSize = sizeof(WNDCLASSEX); // Try global class
if(!::GetClassInfoExA(NULL, p->m_lpszOrigName, &wc)) { // try process local
if(!::GetClassInfoExA(_Module.GetModuleInstance(), p->m_lpszOrigName, &wc)) { ::LeaveCriticalSection(&pM->m_csWindowCreate); return 0; } } memcpy(&p->m_wc, &wc, sizeof(WNDCLASSEX)); p->pWndProc = p->m_wc.lpfnWndProc; p->m_wc.lpszClassName = lpsz; p->m_wc.lpfnWndProc = proc; } else { p->m_wc.hCursor = ::LoadCursorA(p->m_bSystemCursor ? NULL : hInst, p->m_lpszCursorID); }
p->m_wc.hInstance = hInst; p->m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
if (p->m_wc.lpszClassName == NULL) { #ifdef _WIN64 // %p isn't available on Win2k/Win9x
wsprintfA(p->m_szAutoName, "ATL:%p", &p->m_wc); #else
wsprintfA(p->m_szAutoName, "ATL:%8.8X", PtrToUlong(&p->m_wc)); #endif
p->m_wc.lpszClassName = p->m_szAutoName; } WNDCLASSEXA wcTemp; memcpy(&wcTemp, &p->m_wc, sizeof(WNDCLASSEXW)); p->m_atom = (ATOM)::GetClassInfoExA(p->m_wc.hInstance, p->m_wc.lpszClassName, &wcTemp); if (p->m_atom == 0) p->m_atom = ::RegisterClassExA(&p->m_wc); } ::LeaveCriticalSection(&pM->m_csWindowCreate); }
if (p->m_lpszOrigName != NULL) { ATLASSERT(pProc != NULL); ATLASSERT(p->pWndProc != NULL); *pProc = p->pWndProc; } return p->m_atom; }
ATLINLINE ATLAPI_(ATOM) AtlModuleRegisterWndClassInfoW(_ATL_MODULE* pM, _ATL_WNDCLASSINFOW* p, WNDPROC* pProc) { if (p->m_atom == 0) { ::EnterCriticalSection(&pM->m_csWindowCreate); if(p->m_atom == 0) { HINSTANCE hInst = pM->m_hInst; if (p->m_lpszOrigName != NULL) { ATLASSERT(pProc != NULL); LPCWSTR lpsz = p->m_wc.lpszClassName; WNDPROC proc = p->m_wc.lpfnWndProc;
WNDCLASSEXW wc; wc.cbSize = sizeof(WNDCLASSEX); // Try global class
if(!::GetClassInfoExW(NULL, p->m_lpszOrigName, &wc)) { // try process local
if(!::GetClassInfoExW(_Module.GetModuleInstance(), p->m_lpszOrigName, &wc)) { ::LeaveCriticalSection(&pM->m_csWindowCreate); return 0; } } memcpy(&p->m_wc, &wc, sizeof(WNDCLASSEX)); p->pWndProc = p->m_wc.lpfnWndProc; p->m_wc.lpszClassName = lpsz; p->m_wc.lpfnWndProc = proc; } else { p->m_wc.hCursor = ::LoadCursorW(p->m_bSystemCursor ? NULL : hInst, p->m_lpszCursorID); }
p->m_wc.hInstance = hInst; p->m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
if (p->m_wc.lpszClassName == NULL) { #ifdef _WIN64 // %p isn't available on Win2k/Win9x
wsprintfW(p->m_szAutoName, L"ATL:%p", &p->m_wc); #else
wsprintfW(p->m_szAutoName, L"ATL:%8.8X", PtrToUlong(&p->m_wc)); #endif
p->m_wc.lpszClassName = p->m_szAutoName; } WNDCLASSEXW wcTemp; memcpy(&wcTemp, &p->m_wc, sizeof(WNDCLASSEXW)); p->m_atom = (ATOM)::GetClassInfoExW(p->m_wc.hInstance, p->m_wc.lpszClassName, &wcTemp); if (p->m_atom == 0) p->m_atom = ::RegisterClassExW(&p->m_wc); } ::LeaveCriticalSection(&pM->m_csWindowCreate); }
if (p->m_lpszOrigName != NULL) { ATLASSERT(pProc != NULL); ATLASSERT(p->pWndProc != NULL); *pProc = p->pWndProc; } return p->m_atom; }
ATLINLINE ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd) { USES_CONVERSION;
// cases hdc, ptd, hdc is metafile, hic
// NULL, NULL, n/a, Display
// NULL, !NULL, n/a, ptd
// !NULL, NULL, FALSE, hdc
// !NULL, NULL, TRUE, display
// !NULL, !NULL, FALSE, ptd
// !NULL, !NULL, TRUE, ptd
if (ptd != NULL) { LPDEVMODEOLE lpDevMode; LPOLESTR lpszDriverName; LPOLESTR lpszDeviceName; LPOLESTR lpszPortName;
if (ptd->tdExtDevmodeOffset == 0) lpDevMode = NULL; else lpDevMode = (LPDEVMODEOLE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
lpszDriverName = (LPOLESTR)((BYTE*)ptd + ptd->tdDriverNameOffset); lpszDeviceName = (LPOLESTR)((BYTE*)ptd + ptd->tdDeviceNameOffset); lpszPortName = (LPOLESTR)((BYTE*)ptd + ptd->tdPortNameOffset);
return ::CreateDC(OLE2CT(lpszDriverName), OLE2CT(lpszDeviceName), OLE2CT(lpszPortName), DEVMODEOLE2T(lpDevMode)); } else if (hdc == NULL || GetDeviceCaps(hdc, TECHNOLOGY) == DT_METAFILE) return ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL); else return hdc; }
ATLINLINE ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix) { int nPixelsPerInchX; // Pixels per logical inch along width
int nPixelsPerInchY; // Pixels per logical inch along height
HDC hDCScreen = GetDC(NULL); if (hDCScreen) { nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX); nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY); ReleaseDC(NULL, hDCScreen); } else { nPixelsPerInchX = nPixelsPerInchY = 1; }
lpSizeInPix->cx = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cx, nPixelsPerInchX); lpSizeInPix->cy = MAP_LOGHIM_TO_PIX(lpSizeInHiMetric->cy, nPixelsPerInchY); }
ATLINLINE ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric) { int nPixelsPerInchX; // Pixels per logical inch along width
int nPixelsPerInchY; // Pixels per logical inch along height
HDC hDCScreen = GetDC(NULL); if (hDCScreen) { nPixelsPerInchX = GetDeviceCaps(hDCScreen, LOGPIXELSX); nPixelsPerInchY = GetDeviceCaps(hDCScreen, LOGPIXELSY); ReleaseDC(NULL, hDCScreen); } else { nPixelsPerInchX = nPixelsPerInchY = 1; }
lpSizeInHiMetric->cx = MAP_PIX_TO_LOGHIM(lpSizeInPix->cx, nPixelsPerInchX); lpSizeInHiMetric->cy = MAP_PIX_TO_LOGHIM(lpSizeInPix->cy, nPixelsPerInchY); }
#ifndef _ATL_DLL_IMPL
}; //namespace ATL
#endif
//Prevent pulling in second time
#undef _ATLWIN_IMPL
#endif // _ATLWIN_IMPL
|