SubClassWndProc
This example shows how to use the WndProc method and the WindowProc property to subclass a custom control's window procedure. This example subclasses the window procedure of a TListBox descendant to respond to a user-defined message called WM_STYLEMESSAGE
. The subclassed window procedure can be turned on or off by pressing an option button.
class TMyListBoxDescendant : public TListBox { __published: IDE-managed Components void __fastcall SubClassWndProc(Messages::TMessage &Message); void __fastcall ToggleSubClass(bool On); void __fastcall OnDrawItemProc( TWinControl *Control, int Index, const TRect &Rect, TOwnerDrawState State); private: // User declarations public: // User declarations __fastcall TMyListBoxDescendant(TComponent* Owner); }; TForm1 *Form1; TMyListBoxDescendant *MyListBoxDescendant1; Graphics::TBitmap *bitmap0; const WM_STYLEMESSAGE = WM_USER + 2000; __fastcall TMyListBoxDescendant::TMyListBoxDescendant(TComponent* Owner) : TListBox(Owner) { } void __fastcall TForm1::Button1Click(TObject *Sender) { PostMessage( MyListBoxDescendant1->Handle, WM_STYLEMESSAGE, Integer(lbOwnerDrawFixed), 0); } void __fastcall TForm1::Button2Click(TObject *Sender) { PostMessage( MyListBoxDescendant1->Handle, WM_STYLEMESSAGE, Integer(lbStandard), 0); } void __fastcall TForm1::SubClassRadioGroup1Click(TObject *Sender) { MyListBoxDescendant1->ToggleSubClass(SubClassRadioGroup1->ItemIndex == 0); } void __fastcall TMyListBoxDescendant::SubClassWndProc(Messages::TMessage &Message) { if (Message.Msg == WM_STYLEMESSAGE) Style = (TListBoxStyle)Message.WParam; else WndProc(Message); } void __fastcall TMyListBoxDescendant::ToggleSubClass(bool On) { if (On) WindowProc = SubClassWndProc; else WindowProc = WndProc; } #include <memory> //For STL auto_ptr class void __fastcall TMyListBoxDescendant::OnDrawItemProc(TWinControl *Control, int Index, const TRect &Rect, TOwnerDrawState State) { Graphics::TBitmap *bitmap; // Temporary variable for the item's bitmap int Offset = 2; // Default text offset width // Note that you draw on the list box's canvas, not on the form TCanvas *canvas = dynamic_cast<TListBox *>(Control)->Canvas; canvas->FillRect(Rect); // Clear the rectangle. bitmap = dynamic_cast<Graphics::TBitmap *>((dynamic_cast<TListBox *>(Control))->Items->Objects[Index]); if (bitmap) { canvas->BrushCopy( Bounds(Rect.Left + Offset, Rect.Top, bitmap->Width, bitmap->Height), bitmap, Bounds(0, 0, bitmap->Width, bitmap->Height), clRed); // Render bitmap. Offset += bitmap->Width + 4; // Add four pixels between bitmap and text. } // Display the text canvas->TextOut(Rect.Left + Offset, Rect.Top, dynamic_cast<TListBox *>(Control)->Items->Strings[Index]); } __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { MyListBoxDescendant1 = new TMyListBoxDescendant(Form1); // The owner cleans this up. MyListBoxDescendant1->Visible = True; MyListBoxDescendant1->Parent = Form1; MyListBoxDescendant1->Visible = True; MyListBoxDescendant1->Left = SubClassRadioGroup1->Left + SubClassRadioGroup1->Width + 30;; MyListBoxDescendant1->Top = SubClassRadioGroup1->Top; MyListBoxDescendant1->Height = SubClassRadioGroup1->Height; MyListBoxDescendant1->OnDrawItem = MyListBoxDescendant1->OnDrawItemProc; static std::auto_ptr<Graphics::TBitmap> _bitmap0Cleaner(bitmap0 = new Graphics::TBitmap); ImageList1->GetBitmap(0, bitmap0); MyListBoxDescendant1->Items->AddObject("Butterfly", bitmap0); SubClassRadioGroup1->Items->Add("SubClassWndProc"); SubClassRadioGroup1->Items->Add("WndProc"); SubClassRadioGroup1->ItemIndex = 2; }
动态转换:
dynamic_cast
TForm2 * p=dynamic_cast<TForm2*>(Form2);
dynamic_cast<TListBox *>