LRESULT CALLBACK CWindowWnd::__ControlProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowWnd * pThis = NULL;
if ( uMsg == WM_NCCREATE )
{
LPCREATESTRUCT lpcs = reinterpret_cast < LPCREATESTRUCT > (lParam);
pThis = static_cast < CWindowWnd *> (lpcs -> lpCreateParams);
pThis -> m_hWnd = hWnd;
::SetProp(hWnd, " WndX " , (HANDLE) pThis);
}
else
{
pThis = reinterpret_cast < CWindowWnd *> (::GetProp(hWnd, " WndX " ));
if ( uMsg == WM_NCDESTROY && pThis != NULL )
{
LRESULT lRes = ::CallWindowProc(pThis -> m_OldWndProc, hWnd, uMsg, wParam, lParam);
::SetProp(hWnd, " WndX " , NULL);
if ( pThis -> m_bSubclassed ) pThis -> Unsubclass();
pThis -> m_hWnd = NULL;
pThis -> OnFinalMessage(hWnd);
return lRes;
}
}
if ( pThis != NULL )
{
return pThis -> HandleMessage(uMsg, wParam, lParam);
}
else
{
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
{
CWindowWnd * pThis = NULL;
if ( uMsg == WM_NCCREATE )
{
LPCREATESTRUCT lpcs = reinterpret_cast < LPCREATESTRUCT > (lParam);
pThis = static_cast < CWindowWnd *> (lpcs -> lpCreateParams);
pThis -> m_hWnd = hWnd;
::SetProp(hWnd, " WndX " , (HANDLE) pThis);
}
else
{
pThis = reinterpret_cast < CWindowWnd *> (::GetProp(hWnd, " WndX " ));
if ( uMsg == WM_NCDESTROY && pThis != NULL )
{
LRESULT lRes = ::CallWindowProc(pThis -> m_OldWndProc, hWnd, uMsg, wParam, lParam);
::SetProp(hWnd, " WndX " , NULL);
if ( pThis -> m_bSubclassed ) pThis -> Unsubclass();
pThis -> m_hWnd = NULL;
pThis -> OnFinalMessage(hWnd);
return lRes;
}
}
if ( pThis != NULL )
{
return pThis -> HandleMessage(uMsg, wParam, lParam);
}
else
{
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
LRESULT CALLBACK CWindowWnd::__WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CWindowWnd * pThis = NULL;
if ( uMsg == WM_NCCREATE )
{
LPCREATESTRUCT lpcs = reinterpret_cast < LPCREATESTRUCT > (lParam);
pThis = static_cast < CWindowWnd *> (lpcs -> lpCreateParams);
pThis -> m_hWnd = hWnd;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast < LPARAM > (pThis));
}
else
{
pThis = reinterpret_cast < CWindowWnd *> (::GetWindowLongPtr(hWnd, GWLP_USERDATA));
if ( uMsg == WM_NCDESTROY && pThis != NULL )
{
LRESULT lRes = ::CallWindowProc(pThis -> m_OldWndProc, hWnd, uMsg, wParam, lParam);
::SetWindowLongPtr(pThis -> m_hWnd, GWLP_USERDATA, 0L );
if ( pThis -> m_bSubclassed ) pThis -> Unsubclass();
pThis -> m_hWnd = NULL;
pThis -> OnFinalMessage(hWnd);
return lRes;
}
}
if ( pThis != NULL )
{
return pThis -> HandleMessage(uMsg, wParam, lParam);
}
else
{
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
{
CWindowWnd * pThis = NULL;
if ( uMsg == WM_NCCREATE )
{
LPCREATESTRUCT lpcs = reinterpret_cast < LPCREATESTRUCT > (lParam);
pThis = static_cast < CWindowWnd *> (lpcs -> lpCreateParams);
pThis -> m_hWnd = hWnd;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast < LPARAM > (pThis));
}
else
{
pThis = reinterpret_cast < CWindowWnd *> (::GetWindowLongPtr(hWnd, GWLP_USERDATA));
if ( uMsg == WM_NCDESTROY && pThis != NULL )
{
LRESULT lRes = ::CallWindowProc(pThis -> m_OldWndProc, hWnd, uMsg, wParam, lParam);
::SetWindowLongPtr(pThis -> m_hWnd, GWLP_USERDATA, 0L );
if ( pThis -> m_bSubclassed ) pThis -> Unsubclass();
pThis -> m_hWnd = NULL;
pThis -> OnFinalMessage(hWnd);
return lRes;
}
}
if ( pThis != NULL )
{
return pThis -> HandleMessage(uMsg, wParam, lParam);
}
else
{
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}
当 CreateWindow 采用已存在的类时,使用的是 __ControlProc, 位于 RegisterSuperclass()
wc.lpfnWndProc = CWindowWnd::__ControlProc;
当 CreateWindow 采用创建的类时,使用的是 __WndProc, 位于 RegisterWindowClass()
wc.lpfnWndProc = CWindowWnd::__WndProc;
这两个函数唯一不同的是,
__ControlProc 使用 SetProp() 的方式来设置 This 指针, 而
__WndProc 使用 SetWindowLogPtr -> GWLP_USERDATA 的方式来设置 This 指针
·使用已存在的类时,或许是怕别人已经设置过 GWLP_USERDATA ,所以这里采用了 SetProp() 的方式
void
CWindowWnd::CenterWindow()
{
ASSERT(::IsWindow(m_hWnd));
ASSERT((GetWindowStyle(m_hWnd) & WS_CHILD) == 0 );
RECT rcDlg = { 0 };
::GetWindowRect(m_hWnd, & rcDlg);
RECT rcArea = { 0 };
RECT rcCenter = { 0 };
HWND hWndParent = ::GetParent(m_hWnd);
HWND hWndCenter = ::GetWindowOwner(m_hWnd);
::SystemParametersInfo(SPI_GETWORKAREA, NULL, & rcArea, NULL);
if ( hWndCenter == NULL ) rcCenter = rcArea; else ::GetWindowRect(hWndCenter, & rcCenter);
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 ;
// 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;
::SetWindowPos(m_hWnd, NULL, xLeft, yTop, - 1 , - 1 , SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
{
ASSERT(::IsWindow(m_hWnd));
ASSERT((GetWindowStyle(m_hWnd) & WS_CHILD) == 0 );
RECT rcDlg = { 0 };
::GetWindowRect(m_hWnd, & rcDlg);
RECT rcArea = { 0 };
RECT rcCenter = { 0 };
HWND hWndParent = ::GetParent(m_hWnd);
HWND hWndCenter = ::GetWindowOwner(m_hWnd);
::SystemParametersInfo(SPI_GETWORKAREA, NULL, & rcArea, NULL);
if ( hWndCenter == NULL ) rcCenter = rcArea; else ::GetWindowRect(hWndCenter, & rcCenter);
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 ;
// 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;
::SetWindowPos(m_hWnd, NULL, xLeft, yTop, - 1 , - 1 , SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
}
·一直以为有 CenterWindow() 这个API……,看来是因为MFC用久的缘故罢
HWND CWindowWnd::Create(HWND hwndParent, LPCTSTR pstrName, DWORD dwStyle, DWORD dwExStyle,
int
x,
int
y,
int
cx,
int
cy, HMENU hMenu)
{
if ( GetSuperClassName() != NULL && ! RegisterSuperclass() )
return NULL;
if ( GetSuperClassName() == NULL && ! RegisterWindowClass() )
return NULL;
m_hWnd = ::CreateWindowEx(dwExStyle, GetWindowClassName(), pstrName, dwStyle, x, y, cx, cy, hwndParent, hMenu, CPaintManagerUI::GetResourceInstance(), this );
ASSERT(m_hWnd != NULL);
return m_hWnd;
}
{
if ( GetSuperClassName() != NULL && ! RegisterSuperclass() )
return NULL;
if ( GetSuperClassName() == NULL && ! RegisterWindowClass() )
return NULL;
m_hWnd = ::CreateWindowEx(dwExStyle, GetWindowClassName(), pstrName, dwStyle, x, y, cx, cy, hwndParent, hMenu, CPaintManagerUI::GetResourceInstance(), this );
ASSERT(m_hWnd != NULL);
return m_hWnd;
}
这里在 lpParam 参数将 this 指针传过去,在 WM_NCCREATE 消息中再获取 this 指令,但MSDN 相关解释却是在 WM_CREATE 消息处理……
lpParam
If an application calls CreateWindow to create a MDI client window, lpParam should point to a CLIENTCREATESTRUCT structure. If an MDI client window calls CreateWindow to create an MDI child window, lpParam should point to a MDICREATESTRUCT structure. lpParam may be NULL if no additional data is needed.
void
CWindowWnd::ResizeClient(
int
cx
/*
= -1
*/
,
int
cy
/*
= -1
*/
)
{
ASSERT(::IsWindow(m_hWnd));
RECT rc = { 0 };;
if ( ! ::GetClientRect(m_hWnd, & rc) )
return ;
if ( cx != - 1 ) rc.right = cx;
if ( cy != - 1 ) rc.bottom = cy;
if ( ! ::AdjustWindowRectEx( & rc, GetWindowStyle(m_hWnd), ( ! (GetWindowStyle(m_hWnd) & WS_CHILD) && (::GetMenu(m_hWnd) != NULL)), GetWindowExStyle(m_hWnd)) )
return ;
UINT uFlags = SWP_NOZORDER | SWP_NOMOVE;
::SetWindowPos(m_hWnd, NULL, 0 , 0 , rc.right - rc.left, rc.bottom - rc.top, uFlags);
}
{
ASSERT(::IsWindow(m_hWnd));
RECT rc = { 0 };;
if ( ! ::GetClientRect(m_hWnd, & rc) )
return ;
if ( cx != - 1 ) rc.right = cx;
if ( cy != - 1 ) rc.bottom = cy;
if ( ! ::AdjustWindowRectEx( & rc, GetWindowStyle(m_hWnd), ( ! (GetWindowStyle(m_hWnd) & WS_CHILD) && (::GetMenu(m_hWnd) != NULL)), GetWindowExStyle(m_hWnd)) )
return ;
UINT uFlags = SWP_NOZORDER | SWP_NOMOVE;
::SetWindowPos(m_hWnd, NULL, 0 , 0 , rc.right - rc.left, rc.bottom - rc.top, uFlags);
}
AdjustWindowRectEx()
函数功能:该函数依据所需客户矩形大小,计算需要的窗口矩形的大小。计算出的窗口矩形随后可以传送给CreateWindowEx函数,用于创建一个客户区所需大小的窗口。
函数原型:BOOL AdjustWindowRectEX(LPRECT lpRect,DWORD dwStyte;BOOL bMenu;DWORD dwExStyle);
参数:
lpRect:指向RECT结构的指针,该结构包含所需客户区域的左上角和右下角的坐标。函数返回时,该结构包含容纳所需客户区域的窗口的左上角和右下角的坐标。
dwStyle:指定将被计算尺寸的窗口的窗口风格。
bMenu:指示窗口是否有菜单。
dwExStyle:指定将被计算尺寸的窗口的扩展窗口风格。
返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。
备注:客户矩形是指完全包含一个客户区域的最小矩形;窗口矩形是指完全包含一个窗口的最小矩形,该窗口包含客户区与非客户区。
当一个菜单条下拉出两行或更多行时,AdjustWindowRect函数不增加额外的空间。
速查:Windows NT:3.1以上版本;Windows:95以上版本;Windows CE:1.0以上版本;头文件:winuser.h;库文件:user32.lib。