📄 atl under the hood - part 5.mht
字号:
<SPAN class=3Dcpp-keyword>return</SPAN> ::DefWindowProc(hWnd, =
uMsg, wParam, lParam);
}
};
<SPAN class=3Dcpp-keyword>int</SPAN> WINAPI WinMain(HINSTANCE hInstance, =
HINSTANCE hPrevInstance,=20
LPSTR lpCmdLine, <SPAN =
class=3Dcpp-keyword>int</SPAN> nCmdShow)
{
<SPAN class=3Dcpp-keyword>char</SPAN> szAppName[] =3D <SPAN =
class=3Dcpp-string>"Hello world"</SPAN>;
MSG msg;
WNDCLASS wnd;
ZWindow zwnd;
=20
wnd.cbClsExtra =3D NULL;
wnd.cbWndExtra =3D NULL;
wnd.hbrBackground =3D (HBRUSH)GetStockObject(WHITE_BRUSH);
wnd.hCursor =3D LoadCursor(NULL, IDC_ARROW);
wnd.hIcon =3D LoadIcon(NULL, IDI_APPLICATION);
wnd.hInstance =3D hInstance;
wnd.lpfnWndProc =3D zwnd.WndProc;
wnd.lpszClassName =3D szAppName;
wnd.lpszMenuName =3D NULL;
wnd.style =3D CS_HREDRAW | CS_VREDRAW;
=20
<SPAN class=3Dcpp-keyword>if</SPAN> (!RegisterClass(&wnd))
{
MessageBox(NULL, <SPAN class=3Dcpp-string>"Can not register =
window class"</SPAN>, <SPAN class=3Dcpp-string>"Error"</SPAN>,=20
MB_OK | MB_ICONINFORMATION);
<SPAN class=3Dcpp-keyword>return</SPAN> -<SPAN =
class=3Dcpp-literal>1</SPAN>;
}
g_pWnd =3D &zwnd;
zwnd.Create(szAppName, <SPAN class=3Dcpp-string>"Hell world"</SPAN>, =
hInstance);
zwnd.ShowWindow(nCmdShow);
zwnd.UpdateWindow();
<SPAN class=3Dcpp-keyword>while</SPAN> (GetMessage(&msg, NULL, =
<SPAN class=3Dcpp-literal>0</SPAN>, <SPAN class=3Dcpp-literal>0</SPAN>))
{
DispatchMessage(&msg);
}
=20
<SPAN class=3Dcpp-keyword>return</SPAN> msg.wParam;
}
</PRE>
<P>So we finally we have working program. Now let's take the =
advantage of=20
Object Oriented programming. If we call function on each message =
and made=20
that function virtual then we can call those functions when we =
inherit=20
class from ZWindow. So we can customize the default behavior of =
ZWindow.=20
Now the <CODE>WndProc</CODE> is something like this </P><PRE><SPAN =
class=3Dcpp-keyword>static</SPAN> LRESULT CALLBACK WndProc(HWND hWnd, =
UINT uMsg, WPARAM wParam,=20
LPARAM lParam)
{
ZWindow* pThis =3D g_pWnd;
<SPAN class=3Dcpp-keyword>switch</SPAN> (uMsg)
{
<SPAN class=3Dcpp-keyword>case</SPAN> WM_CREATE:
pThis->OnCreate(wParam, lParam);
<SPAN class=3Dcpp-keyword>break</SPAN>;
<SPAN class=3Dcpp-keyword>case</SPAN> WM_PAINT:
pThis->OnPaint(wParam, lParam);
<SPAN class=3Dcpp-keyword>break</SPAN>;
<SPAN class=3Dcpp-keyword>case</SPAN> WM_DESTROY:
::PostQuitMessage(<SPAN class=3Dcpp-literal>0</SPAN>);
<SPAN class=3Dcpp-keyword>break</SPAN>;
}
<SPAN class=3Dcpp-keyword>return</SPAN> ::DefWindowProc(hWnd, uMsg, =
wParam, lParam);
}
</PRE>
<P>Here <CODE>OnCreate</CODE> and <CODE>OnPaint</CODE> are virtual =
function. And when we inherit the class from ZWindow then we can =
override=20
all those function which we want to customize. Here is a complete =
program=20
which shows the usage of <CODE>WM_PAINT</CODE> message in the =
drive class.=20
</P><B>Program 70</B> <PRE><SPAN class=3Dcpp-preprocessor>#include =
<windows.h></SPAN>
<SPAN class=3Dcpp-keyword>class</SPAN> ZWindow;
ZWindow* g_pWnd =3D NULL;
<SPAN class=3Dcpp-keyword>class</SPAN> ZWindow
{
<SPAN class=3Dcpp-keyword>public</SPAN>:
HWND m_hWnd;
ZWindow(HWND hWnd =3D <SPAN class=3Dcpp-literal>0</SPAN>) : =
m_hWnd(hWnd) { }
<SPAN class=3Dcpp-keyword>inline</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> Attach(HWND hWnd)
{ m_hWnd =3D hWnd; }
<SPAN class=3Dcpp-keyword>inline</SPAN> BOOL ShowWindow(<SPAN =
class=3Dcpp-keyword>int</SPAN> nCmdShow)
{ <SPAN class=3Dcpp-keyword>return</SPAN> ::ShowWindow(m_hWnd, =
nCmdShow); }
<SPAN class=3Dcpp-keyword>inline</SPAN> BOOL UpdateWindow()
{ <SPAN class=3Dcpp-keyword>return</SPAN> ::UpdateWindow(m_hWnd); }
<SPAN class=3Dcpp-keyword>inline</SPAN> HDC BeginPaint(LPPAINTSTRUCT =
ps)
{ <SPAN class=3Dcpp-keyword>return</SPAN> ::BeginPaint(m_hWnd, ps); =
}
<SPAN class=3Dcpp-keyword>inline</SPAN> BOOL EndPaint(LPPAINTSTRUCT =
ps)
{ <SPAN class=3Dcpp-keyword>return</SPAN> ::EndPaint(m_hWnd, ps); }
<SPAN class=3Dcpp-keyword>inline</SPAN> BOOL GetClientRect(LPRECT =
rect)
{ <SPAN class=3Dcpp-keyword>return</SPAN> ::GetClientRect(m_hWnd, =
rect); }
BOOL Create(LPCTSTR szClassName, LPCTSTR szTitle, HINSTANCE =
hInstance,=20
HWND hWndParent =3D <SPAN class=3Dcpp-literal>0</SPAN>, =
DWORD dwStyle =3D WS_OVERLAPPEDWINDOW,=20
DWORD dwExStyle =3D <SPAN class=3Dcpp-literal>0</SPAN>, =
HMENU hMenu =3D <SPAN class=3Dcpp-literal>0</SPAN>)
{
m_hWnd =3D ::CreateWindowEx(dwExStyle, szClassName, szTitle, =
dwStyle,=20
CW_USEDEFAULT,CW_USEDEFAULT, =
CW_USEDEFAULT,=20
CW_USEDEFAULT, hWndParent, hMenu, =
hInstance, NULL);
<SPAN class=3Dcpp-keyword>return</SPAN> m_hWnd !=3D NULL;
}
<SPAN class=3Dcpp-keyword>virtual</SPAN> LRESULT OnPaint(WPARAM =
wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
hDC =3D BeginPaint(&ps);
GetClientRect(&rect);
::DrawText(hDC, <SPAN class=3Dcpp-string>"Hello world"</SPAN>, =
-<SPAN class=3Dcpp-literal>1</SPAN>, &rect,=20
DT_CENTER | DT_VCENTER | DT_SINGLELINE);
EndPaint(&ps);
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
<SPAN class=3Dcpp-keyword>virtual</SPAN> LRESULT OnCreate(WPARAM =
wParam, LPARAM lParam)
{
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
<SPAN class=3Dcpp-keyword>static</SPAN> LRESULT CALLBACK =
WndProc(HWND hWnd, UINT uMsg, WPARAM wParam,=20
LPARAM lParam)
{
ZWindow* pThis =3D g_pWnd;
<SPAN class=3Dcpp-keyword>switch</SPAN> (uMsg)
{
<SPAN class=3Dcpp-keyword>case</SPAN> WM_CREATE:
pThis->OnCreate(wParam, lParam);
<SPAN class=3Dcpp-keyword>break</SPAN>;
<SPAN class=3Dcpp-keyword>case</SPAN> WM_PAINT:
pThis->OnPaint(wParam, lParam);
<SPAN class=3Dcpp-keyword>break</SPAN>;
<SPAN class=3Dcpp-keyword>case</SPAN> WM_DESTROY:
::PostQuitMessage(<SPAN class=3Dcpp-literal>0</SPAN>);
<SPAN class=3Dcpp-keyword>break</SPAN>;
}
<SPAN class=3Dcpp-keyword>return</SPAN> ::DefWindowProc(hWnd, =
uMsg, wParam, lParam);
}
};
<SPAN class=3Dcpp-keyword>class</SPAN> ZDriveWindow : <SPAN =
class=3Dcpp-keyword>public</SPAN> ZWindow
{
<SPAN class=3Dcpp-keyword>public</SPAN>:
LRESULT OnPaint(WPARAM wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
hDC =3D BeginPaint(&ps);
GetClientRect(&rect);
SetBkMode(hDC, TRANSPARENT);
DrawText(hDC, <SPAN class=3Dcpp-string>"Hello world From =
Drive"</SPAN>, -<SPAN class=3Dcpp-literal>1</SPAN>, &rect,=20
DT_CENTER | DT_VCENTER | DT_SINGLELINE);
EndPaint(&ps);
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
};
</PRE>
<P>The output of this program is a message "Hello world from =
Drive" in a=20
window. Everything works fine until we work on one drive class. =
The=20
problem started when we drive more than one class from ZWindow. =
Then all=20
the message goes to the last drive class of ZWindow. Let's take a =
look at=20
the following program. </P><B>Program 71</B> <PRE><SPAN =
class=3Dcpp-preprocessor>#include <windows.h></SPAN>
<SPAN class=3Dcpp-keyword>class</SPAN> ZWindow;
ZWindow* g_pWnd =3D NULL;
<SPAN class=3Dcpp-keyword>class</SPAN> ZWindow
{
<SPAN class=3Dcpp-keyword>public</SPAN>:
HWND m_hWnd;
ZWindow(HWND hWnd =3D <SPAN class=3Dcpp-literal>0</SPAN>) : =
m_hWnd(hWnd) { }
<SPAN class=3Dcpp-keyword>inline</SPAN> <SPAN =
class=3Dcpp-keyword>void</SPAN> Attach(HWND hWnd)
{ m_hWnd =3D hWnd; }
<SPAN class=3Dcpp-keyword>inline</SPAN> BOOL ShowWindow(<SPAN =
class=3Dcpp-keyword>int</SPAN> nCmdShow)
{ <SPAN class=3Dcpp-keyword>return</SPAN> ::ShowWindow(m_hWnd, =
nCmdShow); }
<SPAN class=3Dcpp-keyword>inline</SPAN> BOOL UpdateWindow()
{ <SPAN class=3Dcpp-keyword>return</SPAN> ::UpdateWindow(m_hWnd); }
<SPAN class=3Dcpp-keyword>inline</SPAN> HDC BeginPaint(LPPAINTSTRUCT =
ps)
{ <SPAN class=3Dcpp-keyword>return</SPAN> ::BeginPaint(m_hWnd, ps); =
}
<SPAN class=3Dcpp-keyword>inline</SPAN> BOOL EndPaint(LPPAINTSTRUCT =
ps)
{ <SPAN class=3Dcpp-keyword>return</SPAN> ::EndPaint(m_hWnd, ps); }
<SPAN class=3Dcpp-keyword>inline</SPAN> BOOL GetClientRect(LPRECT =
rect)
{ <SPAN class=3Dcpp-keyword>return</SPAN> ::GetClientRect(m_hWnd, =
rect); }
BOOL Create(LPCTSTR szClassName, LPCTSTR szTitle, HINSTANCE =
hInstance,=20
HWND hWndParent =3D <SPAN class=3Dcpp-literal>0</SPAN>, =
DWORD dwStyle =3D WS_OVERLAPPEDWINDOW,=20
DWORD dwExStyle =3D <SPAN class=3Dcpp-literal>0</SPAN>, =
HMENU hMenu =3D <SPAN class=3Dcpp-literal>0</SPAN>, <SPAN =
class=3Dcpp-keyword>int</SPAN> x =3D CW_USEDEFAULT,=20
<SPAN class=3Dcpp-keyword>int</SPAN> y =3D =
CW_USEDEFAULT, <SPAN class=3Dcpp-keyword>int</SPAN> nWidth =3D =
CW_USEDEFAULT,=20
<SPAN class=3Dcpp-keyword>int</SPAN> nHeight =3D =
CW_USEDEFAULT)
{
m_hWnd =3D ::CreateWindowEx(dwExStyle, szClassName, szTitle, =
dwStyle,=20
x, y, nWidth, nHeight, hWndParent, =
hMenu,=20
hInstance, NULL);
<SPAN class=3Dcpp-keyword>return</SPAN> m_hWnd !=3D NULL;
}
<SPAN class=3Dcpp-keyword>virtual</SPAN> LRESULT OnPaint(WPARAM =
wParam, LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
RECT rect;
hDC =3D BeginPaint(&ps);
GetClientRect(&rect);
::DrawText(hDC, <SPAN class=3Dcpp-string>"Hello world"</SPAN>, =
-<SPAN class=3Dcpp-literal>1</SPAN>, &rect,=20
DT_CENTER | DT_VCENTER | DT_SINGLELINE);
EndPaint(&ps);
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
<SPAN class=3Dcpp-keyword>virtual</SPAN> LRESULT =
OnLButtonDown(WPARAM wParam, LPARAM lParam)
{
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
<SPAN class=3Dcpp-keyword>virtual</SPAN> LRESULT OnCreate(WPARAM =
wParam, LPARAM lParam)
{
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
<SPAN class=3Dcpp-keyword>virtual</SPAN> LRESULT OnKeyDown(WPARAM =
wParam, LPARAM lParam)
{
<SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
<SPAN class=3Dcpp-keyword>static</SPAN> LRESULT CALLBACK =
StartWndProc(HWND hWnd, UINT uMsg,=20
WPARAM wParam, LPARAM lParam)
{
ZWindow* pThis =3D g_pWnd;
<SPAN class=3Dcpp-keyword>if</SPAN> (uMsg =3D=3D WM_NCDESTROY)
::PostQuitMessage(<SPAN class=3Dcpp-literal>0</SPAN>);
<SPAN class=3Dcpp-keyword>switch</SPAN> (uMsg)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -