首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

C++ Builder 元件開發深度解析(二):繪圖、虛擬函數與 DYNAMIC 關鍵字

     編輯:VC 教學

前言

元件不僅要有外觀(繪圖),更要能響應使用者輸入。本文講解繪圖機制、滑鼠/鍵盤虛擬函數,並深入剖析 Delphi 特有的 DYNAMIC 關鍵字在 BCB 中的對應寫法。

一、繪圖:重寫 Paint 虛擬函數

  • TCustomControl / TGraphicControl 均提供 virtual void __fastcall Paint()。
  • 在 Paint 中使用 Canvas 繪圖(TCanvas 封裝 HDC)。
  • 設計時期與運行時期同樣觸發 Paint,可用 csDesigning 狀態區分視覺效果。
  • 需重繪時呼叫 Invalidate()(排入訊息佇列)或 Repaint()(立即重繪)。

二、滑鼠與鍵盤虛擬函數

事件虛擬函數原型適用基類
滑鼠按下DYNAMIC void __fastcall MouseDown(TShiftState Shift, int X, int Y)TControl 及衍生類
滑鼠移動DYNAMIC void __fastcall MouseMove(TShiftState Shift, int X, int Y)TControl 及衍生類
滑鼠釋放DYNAMIC void __fastcall MouseUp(TShiftState Shift, int X, int Y)TControl 及衍生類
點擊DYNAMIC void __fastcall Click()TControl 及衍生類
鍵盤按下DYNAMIC void __fastcall KeyDown(Word &Key, TShiftState Shift)需繼承 TCustomControl(擁有焦點)
鍵盤釋放DYNAMIC void __fastcall KeyUp(Word &Key, TShiftState Shift)需繼承 TCustomControl
字元輸入DYNAMIC void __fastcall KeyPress(Char &Key)需繼承 TCustomControl

**關鍵點**:所有函數在 Delphi 中宣告為 dynamic,非 virtual。

三、DYNAMIC 關鍵字深度解析

Delphi 的 virtual vs dynamic

  • virtual:標準虛擬函數表(VMT),每類一份完整 VMT,**呼叫速度最快**,但每衍生類都複製完整表,**程式碼體積大**。
  • dynamic:僅維護一份**動態方法表**(DMT),採用稀疏儲存(只記錄被重寫的方法),**程式碼體積小**,呼叫需查表,**速度稍慢**。
  • VCL 大量使用 dynamic 以控制框架整體體積(數百個控件類)。

BCB 中的對應寫法

C++ 無 dynamic 關鍵字,Borland 擴充提供 DYNAMIC 宏:

// 正確重寫 MouseMove
class TMyControl : public TCustomControl {
protected:
    DYNAMIC void __fastcall MouseMove(TShiftState Shift, int X, int Y);
};

// 實作
DYNAMIC void __fastcall TMyControl::MouseMove(TShiftState Shift, int X, int Y) {
    // 自定義邏輯...
    TCustomControl::MouseMove(Shift, X, Y); // 呼叫父類
}

**切勿**使用 virtual 重寫 dynamic 方法,否則 VMT/DMT 不匹配導致呼叫失敗或崩潰。

四、實戰:編寫簡單的 TShape 元件

// MyShape.h
class TMyShape : public TGraphicControl {
protected:
    DYNAMIC void __fastcall Paint();
    DYNAMIC void __fastcall MouseMove(TShiftState Shift, int X, int Y);
    DYNAMIC void __fastcall MouseDown(TShiftState Shift, int X, int Y);
    DYNAMIC void __fastcall MouseUp(TShiftState Shift, int X, int Y);
private:
    TColor FPenColor, FBrushColor;
    bool   FDragging;
    TPoint FDragStart;
__published:
    __property TColor PenColor = {read=FPenColor, write=FPenColor, default=clBlack};
    __property TColor BrushColor = {read=FBrushColor, write=FBrushColor, default=clWhite};
};

// MyShape.cpp
DYNAMIC void __fastcall TMyShape::Paint() {
    Canvas->Pen->Color = FPenColor;
    Canvas->Brush->Color = FBrushColor;
    Canvas->Rectangle(0, 0, Width, Height);
}

DYNAMIC void __fastcall TMyShape::MouseDown(TShiftState Shift, int X, int Y) {
    if (Shift.Contains(ssLeft)) { FDragging = true; FDragStart = Point(X, Y); }
    TGraphicControl::MouseDown(Shift, X, Y);
}

DYNAMIC void __fastcall TMyShape::MouseMove(TShiftState Shift, int X, int Y) {
    if (FDragging) {
        Left += X - FDragStart.X;
        Top  += Y - FDragStart.Y;
    }
    TGraphicControl::MouseMove(Shift, X, Y);
}

DYNAMIC void __fastcall TMyShape::MouseUp(TShiftState Shift, int X, int Y) {
    FDragging = false;
    TGraphicControl::MouseUp(Shift, X, Y);
}

編譯安裝後,即可在調色盤拖放使用,支援設計時期拖曳移動與屬性編輯。

五、總結

  1. 繪圖重寫 Paint,使用 Canvas,善用 Invalidate/Repaint。
  2. 滑鼠/鍵盤事件重寫對應 DYNAMIC 虛擬函數,**必須加 DYNAMIC 宏**。
  3. TCustomControl 擁有焦點可處理鍵盤;TGraphicControl 僅滑鼠。
  4. 理解 dynamic 機制,避免用 virtual 錯誤重寫。

下一篇將進入 VCL 內部訊息核心:CN_*/CM_* 訊息與自訂事件機制。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved