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

📄 faq76.htm

📁 C++builder学习资料C++builder
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<b>class</b> TForm1 <b>:</b> <b>public</b> TForm

<b>{</b>

<b>...</b>

<b>private</b><b>:</b>

    <b>static</b> LRESULT CALLBACK ListViewProc<b>(</b>HWND hWnd<b>,</b>

                                         UINT uMsg<b>,</b>

                                         WPARAM wParam<b>,</b>

                                         LPARAM lParam<b>)</b><b>;</b>

<b>}</b><b>;</b>



</pre>

<P>

When you use a static member function as your callback procedure, you cannot attempt to call non-static member functions

and you can't dereference non-static member variables of the class. This presents a problem in this example, because we

store the original window procedure in a private variable. We would not be able to dereference this variable from a

static callback function (unless we made the variable static too). The next section describes a VCL technique that

allows you to subclass using a non-static member function of a class.

</P>





<P>

<B>Note 3:</B> The original window proc for the listview is stored in a variable called <TT>FOriginalProc</TT>. This

variable serves two purposes. First, it allows us to pass on window messages when we don't want to alter the default

behavior of the control. Secondly, when the form's destructor executes, we set the window proc of the listview back

to the original handler. This is very important. The lifetime of the listview exceeds the lifetime of the form.

Actually, to be more precise, it exceeds the lifetime of the <TT>TForm1</TT> part of the form.</P>

<P>

The listview is deleted by the base classes of the form. When the listview gets destroyed, certain messages are sent.

Windows will send those messages to the <TT>ControlWndProc</TT> function if we don't restore the original handler.

The problem is that <TT>ControlWndProc</TT> calls a method of <TT>TForm1</TT>.

This is a bad scenario if the <TT>TForm1</TT> destructor has already executed. To prevent this from occuring, the code

restores the original window procedure of the listview in the destructor of the form.

</P>



<BR>



<H4>

Subclassing with the VCL MakeObjectInstance function

</H4>

<P>

The VCL provides a utility function called <TT>MakeObjectInstance</TT> that allows you to sublcass a window using

a member function of a class. When you subclass using <TT>MakeObjectInstance</TT>, the actual window proc is a method

inside the VCL called <TT>StdWndProc</TT>. <TT>StdWndProc</TT> dispatches windows messages to the method of your

class. <TT>StdWndProc</TT> handles the task of determining which object should get

the message. Put another way, <TT>StdWndProc</TT> knows the value of the hidden <TT>this</TT> pointer that must be

passed when your member function is called.

</P>

<P>

The code snippets below demonstrate how to sublcass the listview using <TT>MakeObjectInstance</TT>. Notice that the

stand alone function <TT>ControlWndProc</TT> is no longer needed.

</P>

<pre>

<font color="navy">//-------------------------------------------------------</font>

<font color="navy">// header file</font>

<b>class</b> TForm1 <b>:</b> <b>public</b> TForm

<b>{</b>

<b>__published</b><b>:</b>	<font color="navy">// IDE-managed Components</font>

    TListView <b>*</b>ListView1<b>;</b>

    TImageList <b>*</b>ImageList1<b>;</b>

    <b>void</b> <b>__fastcall</b> FormResize<b>(</b>TObject <b>*</b>Sender<b>)</b><b>;</b>

<b>private</b><b>:</b>	<font color="navy">// User declarations</font>

    WNDPROC FOriginalProc<b>;</b>

    <b>void</b> <b>*</b>  FObjectInstance<b>;</b>

    <b>void</b> <b>__fastcall</b> PaintListView<b>(</b>HDC <b>&</b>dc<b>)</b><b>;</b>

    <b>void</b> <b>__fastcall</b> ListViewProc<b>(</b>TMessage <b>&</b>msg<b>)</b><b>;</b>



<b>public</b><b>:</b>		<font color="navy">// User declarations</font>

    <b>__fastcall</b> TForm1<b>(</b>TComponent<b>*</b> Owner<b>)</b><b>;</b>

    <b>__fastcall</b> <b>~</b>TForm1<b>(</b><b>)</b><b>;</b>

<b>}</b><b>;</b>





<font color="navy">//-------------------------------------------------------</font>

<font color="navy">// source file</font>

<font color="navy">//-------------------------------------------------------</font>



<font color="navy">//-------------------------------------------------------</font>

<b>__fastcall</b> TForm1<b>:</b><b>:</b>TForm1<b>(</b>TComponent<b>*</b> Owner<b>)</b>

    <b>:</b> TForm<b>(</b>Owner<b>)</b>

<b>{</b>

    <font color="navy">// Call GetWindowLong to retrieve the original window proc</font>

    FOriginalProc <b>=</b> <b>(</b>WNDPROC<b>)</b> GetWindowLong<b>(</b>ListView1<b>-></b>Handle<b>,</b> GWL_WNDPROC<b>)</b><b>;</b>



    <font color="navy">// Call MakeObjectInstance to setup a wndproc for the member function</font>

    FObjectInstance <b>=</b> MakeObjectInstance<b>(</b>ListViewProc<b>)</b><b>;</b>



    <font color="navy">// Pass the result of MakeObjectInstance to SetWindowLong</font>

    <font color="navy">// to assign the new window proc for the listview</font>

    SetWindowLong<b>(</b>ListView1<b>-></b>Handle<b>,</b> GWL_WNDPROC<b>,</b> <b>(</b>LONG<b>)</b>FObjectInstance<b>)</b><b>;</b>

<b>}</b>

<font color="navy">//-------------------------------------------------------</font>

<b>__fastcall</b> TForm1<b>:</b><b>:</b><b>~</b>TForm1<b>(</b><b>)</b>

<b>{</b>

    <font color="navy">// Set the window proc back to the original function</font>

    SetWindowLong<b>(</b>ListView1<b>-></b>Handle<b>,</b> GWL_WNDPROC<b>,</b> <b>(</b>LONG<b>)</b> FOriginalProc<b>)</b><b>;</b>



    <font color="navy">// Call FreeObjectInstance to release memory consumed by MakeObjectInstance</font>

    FreeObjectInstance<b>(</b>FObjectInstance<b>)</b><b>;</b>

<b>}</b>

<font color="navy">//-------------------------------------------------------</font>

<b>void</b> <b>__fastcall</b> TForm1<b>:</b><b>:</b>ListViewProc<b>(</b>TMessage <b>&</b>msg<b>)</b>

<b>{</b>

    msg<b>.</b>Result <b>=</b> <font color="blue">0</font><b>;</b>

    <b>switch</b><b>(</b>msg<b>.</b>Msg<b>)</b>

    <b>{</b>

        <b>case</b> WM_ERASEBKGND<b>:</b>

            PaintListView<b>(</b><b>(</b>HDC<b>)</b>msg<b>.</b>WParam<b>)</b><b>;</b>

            msg<b>.</b>Result <b>=</b> <font color="blue">0</font><b>;</b>

            <b>break</b><b>;</b>

        <b>case</b> WM_HSCROLL<b>:</b>

        <b>case</b> WM_VSCROLL<b>:</b>

            LockWindowUpdate<b>(</b>ListView1<b>-></b>Handle<b>)</b><b>;</b>

            msg<b>.</b>Result <b>=</b> CallWindowProc <b>(</b><b>(</b>FARPROC<b>)</b>FOriginalProc<b>,</b>

                                         ListView1<b>-></b>Handle<b>,</b>

                                         msg<b>.</b>Msg<b>,</b>

                                         msg<b>.</b>WParam<b>,</b>

                                         msg<b>.</b>LParam<b>)</b><b>;</b>

            InvalidateRect <b>(</b>ListView1<b>-></b>Handle<b>,</b> <font color="blue">0</font><b>,</b> <b>true</b><b>)</b><b>;</b>

            LockWindowUpdate<b>(</b>NULL<b>)</b><b>;</b>

            <b>break</b><b>;</b>

        <b>default</b><b>:</b>

            msg<b>.</b>Result <b>=</b> CallWindowProc <b>(</b><b>(</b>FARPROC<b>)</b>FOriginalProc<b>,</b>

                                         ListView1<b>-></b>Handle<b>,</b>

                                         msg<b>.</b>Msg<b>,</b>

                                         msg<b>.</b>WParam<b>,</b>

                                         msg<b>.</b>LParam<b>)</b><b>;</b>

            <b>break</b><b>;</b>

    <b>}</b>

<b>}</b>

<font color="navy">//-------------------------------------------------------</font>

<b>void</b> <b>__fastcall</b> TForm1<b>:</b><b>:</b>PaintListView<b>(</b>HDC <b>&</b>dc<b>)</b>

<b>{</b>

    <font color="navy">//Same painting code as before</font>

    <b>...</b>

<b>}</b>

<font color="navy">//-------------------------------------------------------</font>

<b>void</b> <b>__fastcall</b><b>/</b> TForm1<b>:</b><b>:</b>FormResize<b>(</b>TObject <b>*</b>Sender<b>)</b>

<b>{</b>

    ListView1<b>-></b>Repaint<b>(</b><b>)</b><b>;</b>

<b>}</b>

<font color="navy">//-------------------------------------------------------</font>

</pre>



<P>

<B>Note 1:</B> <TT>MakeObjectInstance</TT> returns a <TT>void</TT> pointer. This <TT>void</TT> pointer should

be passed to the <TT>SetWindowLong</TT> API function. Do not pass the name of your member function to

<TT>SetWindowLong</TT>.

</P>

<P>

<B>Note 2:</B> Every call to <TT>MakeObjectInstance</TT> should have a corresponding call to

<TT>FreeObjectInstance</TT>. <TT>MakeObjectInstance</TT> allocates memory that is not freed until you call

<TT>FreeObjectInstance</TT>. Failing to free up this memory causes memory leaks.

</P>





<BR>



<H4>

Subclassing with the WindowProc property of a control</H4>

<P>

The <TT>TControl</TT> class from the VCL provides a public property that allows you to subclass a control without much

effort. The property is called <TT>WindowProc</TT>. You can intercept messages sent to a control by assigning a new

function to the <TT>WindowProc</TT> property of a control. The next code listing demonstrates how to subclass the

listview control through its <TT>WindowProc</TT> property.

</P>

<pre>

<font color="navy">//-------------------------------------------------------</font>

<font color="navy">// header file</font>

<b>class</b> TForm1 <b>:</b> <b>public</b> TForm

<b>{</b>

<b>__published</b><b>:</b>	<font color="navy">// IDE-managed Components</font>

    TListView <b>*</b>ListView1<b>;</b>

    TImageList <b>*</b>ImageList1<b>;</b>

    <b>void</b> <b>__fastcall</b> FormResize<b>(</b>TObject <b>*</b>Sender<b>)</b><b>;</b>

<b>private</b><b>:</b>	<font color="navy">// User declarations</font>

    TWndMethod FOriginalProc<b>;</b>



    <b>void</b> <b>__fastcall</b> ListViewProc<b>(</b>TMessage <b>&</b>msg<b>)</b><b>;</b>

    <b>void</b> <b>__fastcall</b> PaintListView<b>(</b>HDC <b>&</b>dc<b>)</b><b>;</b>



<b>public</b><b>:</b>		<font color="navy">// User declarations</font>

    <b>__fastcall</b> TForm1<b>(</b>TComponent<b>*</b> Owner<b>)</b><b>;</b>

    <b>__fastcall</b> <b>~</b>TForm1<b>(</b><b>)</b><b>;</b>

<b>}</b><b>;</b>





<font color="navy">//-------------------------------------------------------</font>

<font color="navy">// source file</font>

<font color="navy">//-------------------------------------------------------</font>



<b>__fastcall</b> TForm1<b>:</b><b>:</b>TForm1<b>(</b>TComponent<b>*</b> Owner<b>)</b>

    <b>:</b> TForm<b>(</b>Owner<b>)</b>

<b>{</b>

    <font color="navy">// Store the original valud of WindowProc in the member variable</font>

⌨️ 快捷键说明

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