📄 faq76.htm
字号:
<font color="navy">// and then assign our method to the WindowProc property</font>
FOriginalProc <b>=</b> ListView1<b>-></b>WindowProc<b>;</b>
ListView1<b>-></b>WindowProc <b>=</b> ListViewProc<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>
ListView1<b>-></b>WindowProc <b>=</b> FOriginalProc<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>
FOriginalProc<b>(</b>msg<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>
FOriginalProc<b>(</b>msg<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:</B> Notice that value returned by the <TT>WindowProc</TT> property is of the type <TT>TWndMethod</TT> and
not <TT>WNDPROC</TT>. This has an important consequence. <TT>TWndMethod</TT> functions already know how to deal with
the VCL's <TT>TMessage</TT> structure. This means that you can call the original <TT>WindowProc</TT> function without
bothering with the API <TT>CallWindowProc</TT> function. You simply call the original <TT>WindowProc</TT> and pass it
the <TT>TMessage</TT> structure.
</P>
<BR>
<H4>
Subclassing by deriving a new control</H4>
<P>
It turns out all VCL classes that inherit from <TT>TWinControl</TT> already subclass the window handle of the control.
The subclassing is done so that the VCL class can respond to messages sent to the control. Without subclassing, none
of the internal message maps or <TT>WndProc</TT> functions would ever get called. In fact, the base class uses
<TT>MakeObjectInstance</TT> to perform the subclassing, and the subclassed proc executes the function stored
by the <TT>WindowProc</TT> property to handle the message (see <TT>TWinControl.MainWndProc</TT> in CONTROLS.PAS).
</P>
<P>
Because VCL classes already subclass the window handle, you can intercept messages by deriving a new class from a
VCL base class. When you utilize this technique, you subclass a window handle by subclassing, or inheriting from, a
existing base class. The code below shows how to derive a class from <TT>TListView</TT> that paints the custom
background.
</P>
<pre>
<font color="navy">//-------------------------------------------------------</font>
<font color="navy">// header file</font>
<b>class</b> PACKAGE TXListView <b>:</b> <b>public</b> TListView
<b>{</b>
<b>private</b><b>:</b>
<b>protected</b><b>:</b>
<b>void</b> <b>__fastcall</b> WndProc<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>
<b>__fastcall</b> TXListView<b>(</b>TComponent<b>*</b> Owner<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> TXListView<b>:</b><b>:</b>TXListView<b>(</b>TComponent<b>*</b> Owner<b>)</b>
<b>:</b> TListView<b>(</b>Owner<b>)</b>
<b>{</b>
<b>}</b>
<font color="navy">//-------------------------------------------------------</font>
<b>void</b> <b>__fastcall</b> TXListView<b>:</b><b>:</b>WndProc<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>Handle<b>)</b><b>;</b>
TListView<b>:</b><b>:</b>WndProc<b>(</b>msg<b>)</b><b>;</b>
InvalidateRect <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>
TListView<b>:</b><b>:</b>WndProc<b>(</b>msg<b>)</b><b>;</b>
<b>break</b><b>;</b>
<b>}</b>
<b>}</b>
<font color="navy">//-------------------------------------------------------</font>
<b>void</b> <b>__fastcall</b> TXListView<b>:</b><b>:</b>PaintListView<b>(</b>HDC <b>&</b>dc<b>)</b>
<b>{</b>
TRect rect <b>=</b> BoundsRect<b>;</b>
Graphics<b>:</b><b>:</b>TBitmap <b>*</b>MemBitmap <b>=</b> <b>new</b> Graphics<b>:</b><b>:</b>TBitmap<b>;</b>
MemBitmap<b>-></b>Width <b>=</b> rect<b>.</b>Right <b>-</b> rect<b>.</b>Left<b>;</b>
MemBitmap<b>-></b>Height<b>=</b> rect<b>.</b>Bottom<b>-</b> rect<b>.</b>Top<b>;</b>
MemBitmap<b>-></b>Canvas<b>-></b>Brush<b>-></b>Style <b>=</b> bsSolid<b>;</b>
MemBitmap<b>-></b>Canvas<b>-></b>Brush<b>-></b>Color <b>=</b> clAqua<b>;</b>
MemBitmap<b>-></b>Canvas<b>-></b>FillRect<b>(</b>Rect<b>(</b><font color="blue">0</font><b>,</b><font color="blue">0</font><b>,</b>
MemBitmap<b>-></b>Width<b>,</b>
MemBitmap<b>-></b>Height<b>)</b><b>)</b><b>;</b>
MemBitmap<b>-></b>Canvas<b>-></b>Pen<b>-></b>Color <b>=</b> clNavy<b>;</b>
MemBitmap<b>-></b>Canvas<b>-></b>Pen<b>-></b>Width <b>=</b> <font color="blue">20</font><b>;</b>
MemBitmap<b>-></b>Canvas<b>-></b>MoveTo<b>(</b><font color="blue">0</font><b>,</b><font color="blue">0</font><b>)</b><b>;</b>
MemBitmap<b>-></b>Canvas<b>-></b>LineTo<b>(</b>MemBitmap<b>-></b>Width<b>,</b> MemBitmap<b>-></b>Height<b>)</b><b>;</b>
<b>:</b><b>:</b>BitBlt<b>(</b>dc<b>,</b><font color="blue">0</font><b>,</b><font color="blue">0</font><b>,</b>MemBitmap<b>-></b>Width<b>,</b> MemBitmap<b>-></b>Height<b>,</b>
MemBitmap<b>-></b>Canvas<b>-></b>Handle<b>,</b><font color="blue">0</font><b>,</b><font color="blue">0</font><b>,</b>SRCCOPY<b>)</b><b>;</b>
<b>delete</b> MemBitmap<b>;</b>
<b>}</b>
<font color="navy">//-------------------------------------------------------</font>
<font color="navy">// using the component from a form</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>
TXListView <b>*</b>ListView1 <b>=</b> <b>new</b> TXListView<b>(</b><b>this</b><b>)</b><b>;</b>
ListView1<b>-></b>Align <b>=</b> alClient<b>;</b>
ListView1<b>-></b>Parent <b>=</b> <b>this</b><b>;</b>
ListView1<b>-></b>LargeImages <b>=</b> ImageList1<b>;</b>
ListView1<b>-></b>IconOptions <b>-></b>Arrangement <b>=</b> iaLeft<b>;</b>
<b>int</b> nCount <b>=</b> ImageList1<b>-></b>Count<b>;</b>
<b>for</b><b>(</b><b>int</b> j<b>=</b><font color="blue">0</font><b>;</b> jItems<b>-></b>Add<b>(</b><b>)</b><b>;</b>
item<b>-></b>Caption <b>=</b> <font color="blue">"item "</font> <b>+</b> IntToStr<b>(</b>j<b>)</b><b>;</b>
item<b>-></b>ImageIndex <b>=</b> j<b>;</b>
<b>}</b>
<b>}</b>
<font color="navy">//-------------------------------------------------------</font>
</pre>
<P>
<B>Note:</B> Of all the subclassing techniques described in this article, the technique of inheriting a new class is
probably the best strategy from an object oriented standpoint. It is a bad design practice to litter a form class with
a bunch of code that subclasses and paints the background of a listview control. It is wiser to derive a new class and
encapsulate the custom behavior while maintaining the default behavior of the base class.
</P>
<P>
Notice that you don't have
to write code that subclasses the window handle when you derive a new class from <TT>TListView</TT>. The base class
already does that, and deriving a new class leverages that code in the base classes. Also, you don't have to worry
about listview messages being sent to a form that is in the middle of being destroyed. Not only is deriving a new
class cleaner from an object oriented point of view, it is probably more robust and less prone to failure.
</P>
<BR>
<TABLE BORDER=1 CELLPADDING=10 CELLSPACING=0 WIDTH="100%">
<TR> <TD colspan = 2><B>Downloads for this FAQ</B> </TD> </TR>
<TR> <TD><TT><A HREF="download/subclass1.zip" >subclass1.zip </A></TT></TD> <TD>BCB3 project that demonstrates <TT>SetWindowLong</TT> to subclass a listview.</TD> </TR>
<TR> <TD><TT><A HREF="download/subclass1x.zip">subclass1x.zip</A></TT></TD> <TD>Same as subclass1.zip. Includes an EXE. Zip is 170k.</TD> </TR>
<TR> <TD><TT><A HREF="download/subclass2.zip" >subclass2.zip </A></TT></TD> <TD>BCB3 project that uses <TT>MakeObjectInstance</TT> to subclass a listview.</TD> </TR>
<TR> <TD><TT><A HREF="download/subclass2x.zip">subclass2x.zip</A></TT></TD> <TD>Same as subclass2.zip. Includes an EXE. Zip is 170k.</TD> </TR>
<TR> <TD><TT><A HREF="download/subclass3.zip" >subclass3.zip </A></TT></TD> <TD>BCB3 project that subclasses a listview through its <TT>WindowProc</TT> property.</TD> </TR>
<TR> <TD><TT><A HREF="download/subclass3x.zip">subclass3x.zip</A></TT></TD> <TD>Same as subclass3.zip. Includes an EXE. Zip is 170k.</TD> </TR>
<TR> <TD><TT><A HREF="download/subclass4.zip" >subclass4.zip </A></TT></TD> <TD>BCB3 project that shows how to subclass a listview by deriving a new class.</TD> </TR>
<TR> <TD><TT><A HREF="download/subclass4x.zip">subclass4x.zip</A></TT></TD> <TD>Same as subclass4.zip. Includes an EXE. Zip is 170k.</TD> </TR>
</TABLE>
</TD> </TR>
</TABLE>
</CENTER>
</BODY>
</HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -