⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atl under the hood - part 5.mht

📁 大家知道wtl是window UI库
💻 MHT
📖 第 1 页 / 共 5 页
字号:
        <SPAN class=3Dcpp-keyword>case</SPAN> WM_CREATE:
            pThis-&gt;OnCreate(wParam, lParam);
            <SPAN class=3Dcpp-keyword>break</SPAN>;

        <SPAN class=3Dcpp-keyword>case</SPAN> WM_PAINT:
            pThis-&gt;OnPaint(wParam, lParam);
            <SPAN class=3Dcpp-keyword>break</SPAN>;

        <SPAN class=3Dcpp-keyword>case</SPAN> WM_LBUTTONDOWN:
            pThis-&gt;OnLButtonDown(wParam, lParam);
            <SPAN class=3Dcpp-keyword>break</SPAN>;

        <SPAN class=3Dcpp-keyword>case</SPAN> WM_KEYDOWN:
            pThis-&gt;OnKeyDown(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> ZDriveWindow1 : <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(&amp;ps);
        GetClientRect(&amp;rect);
        ::SetBkMode(hDC, TRANSPARENT);
        ::DrawText(hDC, <SPAN class=3Dcpp-string>"ZDriveWindow1"</SPAN>, =
-<SPAN class=3Dcpp-literal>1</SPAN>, &amp;rect,=20
                   DT_CENTER | DT_VCENTER | DT_SINGLELINE);
        EndPaint(&amp;ps);

        <SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
    }

    LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam)
    {
        ::MessageBox(NULL, <SPAN =
class=3Dcpp-string>"ZDriveWindow1::OnLButtonDown"</SPAN>, <SPAN =
class=3Dcpp-string>"Msg"</SPAN>, MB_OK);
        <SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
    }

};

<SPAN class=3Dcpp-keyword>class</SPAN> ZDriveWindow2 : <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(&amp;ps);
        GetClientRect(&amp;rect);
        ::SetBkMode(hDC, TRANSPARENT);
        ::Rectangle(hDC, rect.left, rect.top, rect.right, rect.bottom);
        ::DrawText(hDC, <SPAN class=3Dcpp-string>"ZDriveWindow2"</SPAN>, =
-<SPAN class=3Dcpp-literal>1</SPAN>, &amp;rect,
                   DT_CENTER | DT_VCENTER | DT_SINGLELINE);
        EndPaint(&amp;ps);

        <SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
    }

    LRESULT OnLButtonDown(WPARAM wParam, LPARAM lParam)
    {
        ::MessageBox(NULL, <SPAN =
class=3Dcpp-string>"ZDriveWindow2::OnLButtonDown"</SPAN>, <SPAN =
class=3Dcpp-string>"Msg"</SPAN>, MB_OK);
        <SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
    }

};

<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;
    ZDriveWindow1 zwnd1;
    ZDriveWindow2 zwnd2;
   =20
    wnd.cbClsExtra        =3D NULL;
    wnd.cbWndExtra        =3D NULL;
    wnd.hbrBackground        =3D (HBRUSH)GetStockObject(GRAY_BRUSH);
    wnd.hCursor        =3D LoadCursor(NULL, IDC_ARROW);
    wnd.hIcon            =3D LoadIcon(NULL, IDI_APPLICATION);
    wnd.hInstance        =3D hInstance;
    wnd.lpfnWndProc        =3D ZWindow::StartWndProc;
    wnd.lpszClassName        =3D szAppName;
    wnd.lpszMenuName        =3D NULL;
    wnd.style            =3D CS_HREDRAW | CS_VREDRAW;
   =20
    <SPAN class=3Dcpp-keyword>if</SPAN> (!RegisterClass(&amp;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 &amp;zwnd1;
    zwnd1.Create(szAppName, <SPAN class=3Dcpp-string>"Hell =
world"</SPAN>, hInstance);

    zwnd1.ShowWindow(nCmdShow);
    zwnd1.UpdateWindow();

    g_pWnd =3D &amp;zwnd2;

    zwnd2.Create(szAppName, <SPAN class=3Dcpp-string>"Hello =
world"</SPAN>, hInstance, zwnd1.m_hWnd,=20
        WS_VISIBLE | WS_CHILD | ES_MULTILINE, NULL, NULL, <SPAN =
class=3Dcpp-literal>0</SPAN>, <SPAN class=3Dcpp-literal>0</SPAN>, <SPAN =
class=3Dcpp-literal>150</SPAN>, <SPAN class=3Dcpp-literal>150</SPAN>);

    <SPAN class=3Dcpp-keyword>while</SPAN> (GetMessage(&amp;msg, NULL, =
<SPAN class=3Dcpp-literal>0</SPAN>, <SPAN class=3Dcpp-literal>0</SPAN>))
    {
        DispatchMessage(&amp;msg);
    }
   =20
    <SPAN class=3Dcpp-keyword>return</SPAN> msg.wParam;
}
</PRE>
      <P>The output of this program shows the same message box no matter =
on=20
      which window you click. </P>
      <CENTER><IMG=20
      =
src=3D"http://www.codeproject.com/atl/atl_underthehood_5/Thunk1.jpg"></IM=
G></CENTER>
      <P>You get the same message box no matter you click on any window. =
This=20
      means message is not properly propagate to appropriate window. In =
fact=20
      each window has their own window procedure, which handles all the =
messages=20
      of that window. But here we use the call back function of second =
drive=20
      class with the first window, so we can't executer the message =
handler of=20
      first window. </P>
      <P>Here our main problem is to associate the callback function of =
window=20
      with appropriate window. Means <CODE>HWND</CODE> should be =
associated with=20
      appropriate Drive class. So message should be go to right window. =
There=20
      can be more than one solution of this problem, let's take a look =
at each=20
      solution one by one. </P>
      <P>The first obvious solution come in mind, which can be easily=20
      implemented is to make a global structure, which stores the=20
      <CODE>HWND</CODE> with appropriate Drive class address. But there =
are two=20
      main problems with this approach. Fist the structure becomes =
larger and=20
      larger when more and more window will be added in the program. And =
second=20
      problem is that there is of course searching time involve in that =
global=20
      structure and it is time consuming to search it when that =
structure=20
      becomes very large. </P>
      <P>The main purpose of ATL is to make as small as possible and as =
fast as=20
      possible. And this technique fails on both criteria. This method =
is not=20
      only slow but also consumes lots of memory when there are lots of =
window=20
      involves in the program. </P>
      <P>The other possible solution is to use <CODE>cbWndExtra</CODE> =
field of=20
      <CODE>WNDCLASS</CODE> or <CODE>WNDCLASSEX</CODE> structure. There =
is still=20
      one question why not use <CODE>cbClsExtra</CODE> instead of=20
      <CODE>cbWndExtra</CODE>? The answer is simple =
<CODE>cbClsExtra</CODE>=20
      store the extra bytes for each class and <CODE>cbWndExtra</CODE> =
store=20
      extra byes for each window from the class. And you can create more =
than=20
      one window from the same class so if you use =
<CODE>cbClsExtra</CODE> then=20
      you can't distinguish the different window call back function from =

      <CODE>cbClsExtra</CODE> because it is same of all those window =
which are=20
      create by the same class. And store the address of appropriate =
drive class=20
      in this field. </P>
      <P>It seems good solution at lest seems better then the first one. =
But=20
      there are still two problems in this solution. The first one is =
that if=20
      user wants to use <CODE>cbWndExtra</CODE> then he/she might =
overwrite the=20
      data which is written by using this technique. So client of this =
class has=20
      to be careful not to lose that information when using=20
      <CODE>cbWndExtra</CODE>. Ok fine, you have decided and documented =
that not=20
      use cbWndExtra when using your library, but there is still one =
more=20
      problem. This method is not very much fast, again against the rule =
of ATL,=20
      that ATL should be as small and as fast as possible. </P>
      <P>ATL neither use first method nor second. The method which ATL =
used is=20
      called Thunk. Thunk is a small set of code to do some work and =
this term=20
      is used in different context. It may be possible that you have =
listen two=20
      type of Thunking </P><B>Universal Thunking</B>=20
      <P>Universal Thunking enables to call 32-bit function from 16-bit =
code.=20
      Available on both Win 9x and Win NT/2000/XP. This is also known as =
Generic=20
      Thunking. </P><B>General Thunking</B>=20
      <P>Generic Thunking enables to call 16-bit function from 32-bit =
code. It=20
      is available only on Win 9x because Win NT/2000/XP are true 32 bit =

      operating system so there is no logical reason to call 16 bit =
function=20
      from 32 bit code. This is also known as Flat Thunking. </P>
      <P>ATL doesn't use any of this, because you are not going to mix =
16-bit=20
      and 32-bit code in ATL. In fact ATL insert a small code to call =
the=20
      correct Window procedure. </P>
      <P>Lets star some basic concepts before the study of thunking of =
ATL. Take=20
      a look at the following simple program. </P><B>Program 72</B> =
<PRE><SPAN class=3Dcpp-preprocessor>#include &lt;iostream&gt;</SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;

<SPAN class=3Dcpp-keyword>struct</SPAN> S
{
    <SPAN class=3Dcpp-keyword>char</SPAN> ch;
    <SPAN class=3Dcpp-keyword>int</SPAN> i;
};

<SPAN class=3Dcpp-keyword>int</SPAN> main()
{
    cout &lt;&lt; <SPAN class=3Dcpp-string>"Size of character =3D =
"</SPAN> &lt;&lt; <SPAN class=3Dcpp-keyword>sizeof</SPAN>(<SPAN =
class=3Dcpp-keyword>char</SPAN>) &lt;&lt; endl;
    cout &lt;&lt; <SPAN class=3Dcpp-string>"Size of integer =3D "</SPAN> =
&lt;&lt; <SPAN class=3Dcpp-keyword>sizeof</SPAN>(<SPAN =
class=3Dcpp-keyword>int</SPAN>) &lt;&lt; endl;
    cout &lt;&lt; <SPAN class=3Dcpp-string>"Size of structure =3D =
"</SPAN> &lt;&lt; <SPAN class=3Dcpp-keyword>sizeof</SPAN>(S) &lt;&lt; =
endl;
    <SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of this program is </P><PRE>Size of character =3D =
<SPAN class=3Dcpp-literal>1</SPAN>
Size of integer =3D <SPAN class=3Dcpp-literal>4</SPAN>
Size of structure =3D <SPAN class=3Dcpp-literal>8</SPAN>
</PRE>
      <P>The sum of the sizes of integer and character should be 5 not =
8. Ok=20
      lets change a program little bit and add one more member variable =
into the=20
      program to see what's going on. </P><B>Program 73</B> <PRE><SPAN =
class=3Dcpp-preprocessor>#include &lt;iostream&gt;</SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;

<SPAN class=3Dcpp-keyword>struct</SPAN> S
{
    <SPAN class=3Dcpp-keyword>char</SPAN> ch1;
    <SPAN class=3Dcpp-keyword>char</SPAN> ch2;
    <SPAN class=3Dcpp-keyword>int</SPAN> i;
};

<SPAN class=3Dcpp-keyword>int</SPAN> main()
{
    cout &lt;&lt; <SPAN class=3Dcpp-string>"Size of character =3D =
"</SPAN> &lt;&lt; <SPAN class=3Dcpp-keyword>sizeof</SPAN>(<SPAN =
class=3Dcpp-keyword>char</SPAN>) &lt;&lt; endl;
    cout &lt;&lt; <SPAN class=3Dcpp-string>"Size of integer =3D "</SPAN> =
&lt;&lt; <SPAN class=3Dcpp-keyword>sizeof</SPAN>(<SPAN =
class=3Dcpp-keyword>int</SPAN>) &lt;&lt; endl;
    cout &lt;&lt; <SPAN class=3Dcpp-string>"Size of structure =3D =
"</SPAN> &lt;&lt; <SPAN class=3Dcpp-keyword>sizeof</SPAN>(S) &lt;&lt; =
endl;
    <SPAN class=3Dcpp-keyword>return</SPAN> <SPAN =
class=3Dcpp-literal>0</SPAN>;
}
</PRE>
      <P>The output of this program is same as previous one. So what is =
going on=20
      here? Change a program little bit more to see what is going on =
Under the=20
      Hood. </P><B>Program 74</B> <PRE><SPAN =
class=3Dcpp-preprocessor>#include &lt;iostream&gt;</SPAN>
using <SPAN class=3Dcpp-keyword>namespace</SPAN> std;

<SPAN class=3Dcpp-keyword>struct</SPAN> S
{
    <SPAN class=3Dcpp-keyword>char</SPAN> ch1;
    <SPAN class=3Dcpp-keyword>char</SPAN> ch2;
    <SPAN class=3Dcpp-keyword>int</SPAN> i;
}s;

<SPAN class=3Dcpp-keyword>int</SPAN> main()
{
    cout &lt;&lt; <SPAN class=3Dcpp-string>"Address of ch1 =3D "</SPAN> =
&lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>)&amp;s.ch1 &lt;&lt; endl;
    cout &lt;&lt; <SPAN class=3Dcpp-string>"Address of ch2 =3D "</SPAN> =
&lt;&lt; (<SPAN class=3Dcpp-keyword>int</SPAN>)&amp;s.ch2 &lt;&lt; endl;
    cout &lt;&lt; <SPAN class=3Dcpp-string>"Address of

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -