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);
???}
}
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);
???}
}
當 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);
}
·一直以為有 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;
}
這里在 lpParam 參數將 this 指針傳過去,在 WM_NCCREATE? 消息中再獲取 this 指令,但MSDN 相關解釋卻是在 WM_CREATE? 消息處理……
lpParam[in]? Pointer to a value to be passed to the window through the CREATESTRUCT structure (lpCreateParams member) pointed to by the lParam param of the WM_CREATE message. This message is sent to the created window by this function before it returns.
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);
}
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。