如何实现从TPaintBox创建的新组件的OnClick,OnMouseDown,OnMouseUp事件?

时间:2017-04-18 09:00:21

标签: c++ vcl c++builder-xe5

我正在尝试从TPaintBox创建一个新组件。新组件大小为Rect(0,0,160,248)。我在新组件上绘制了两个矩形,我想对上面的每个矩形实现事件。

获取矩形位于Rect(102,43,157,63),我想为此矩形区域实现OnGetClick,OnGetMouseDown,OnGetMouseUp等事件。

设置矩形位于Rect(102,69,157,89),我想为此矩形区域实现OnSetClick,OnSetMouseDown,OnSetMouseUp等事件。

新组件区域的其余部分将显示与VGauge相关的显示值,并且我不包含在下面的代码中。

class PACKAGE TVGauge : public TPaintBox
{
   public:
     virtual void __fastcall Paint(void) ;
};
void __fastcall TVGauge::Paint(void)
{
  int ind1, ind2 ;
  TRect tempR ;
  String str;
  Canvas->Font->Size  = 8 ;

  //whole rect
  Canvas->Pen->Color        = clSilver ;
  Canvas->Brush->Color      = clBtnFace ;
  Canvas->Rectangle(ClientRect) ; //Rect(0,0,160,248)

  //----------
  Canvas->Pen->Color    = clMedGray ;
  Canvas->Font->Color   = clWindowText ;
  Canvas->Brush->Color  = clWhite ;

  //Get Button ; draw a rectangle and it should act like a button
  Canvas->Rectangle(102 , 43  , 157 , 63 ) ;
  Canvas->TextOut(112,  48 ,L"Get");

  //Set Button ; draw a rectangle and it should act like a button
   Canvas->Rectangle(102 , 69  , 157 , 89 ) ;
   Canvas->TextOut(112,  74 ,L"Set");

  //display values related to the VGauge 
  //..
  //..

   if(OnPaint != NULL)  OnPaint(this) ;
}

我不知道如何为新组件实现上述事件。所以,我希望得到实施这个组件的建议。

1 个答案:

答案 0 :(得分:1)

覆盖虚拟MouseDown()MouseUp()方法,例如:

enum TVGaugeButton { tvgGetBtn, tvgSetBtn };

typedef void __fastcall (__closure *TVGaugeMouseEvent)(TObject *Sender, TVGaugeButton GaugeButton, TMouseButton MouseButton, TShiftState Shift, int X, int Y);
typedef void __fastcall (__closure *TVGaugeClickEvent)(TObject *Sender, TVGaugeButton GaugeButton);

class PACKAGE TVGauge : public TPaintBox
{
    typedef TPaintBox inherited;

private:
    bool FMouseDown[2];

    TVGaugeMouseEvent FOnGaugeButtonMouseDown;
    TVGaugeMouseEvent FOnGaugeButtonMouseUp;
    TVGaugeClickEvent FOnGaugeButtonClick;

    TRect __fastcall GetButtonRect(TVGaugeButton WhichButton);

protected:
    DYNAMIC void __fastcall MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y);
    DYNAMIC void __fastcall MouseUp(TMouseButton Button, TShiftState Shift, int X, int Y);
    virtual void __fastcall Paint();

public:
    __fastcall TVGauge(TComponent *Owner);

    virtual void __fastcall SetBounds(int ALeft, int ATop, int AWidth, int AHeight);

__published:
    __property TVGaugeClickEvent OnGaugeButtonClick = {read=FOnGaugeButtonClick, write=FOnGaugeButtonClick};
    __property TVGaugeMouseEvent OnGaugeButtonMouseDown ={read=FOnGaugeButtonMouseDown, write=FOnGaugeButtonMouseDown};
    __property TVGaugeMouseEvent OnGaugeButtonMouseUp = {read=FOnGaugeButtonMouseUp, write=FOnGaugeButtonMouseUp};
};

__fastcall TVGauge::TVGauge(TComponent *Owner)
    : TPaintBox(Owner)
{
}

void __fastcall TVGauge::SetBounds(int ALeft, int ATop, int AWidth, int AHeight)
{
    inherited::SetBounds(ALeft, ATop, 160, 248);
}

TRect __fastcall TVGauge::GetButtonRect(TVGaugeButton WhichButton)
{
    switch (WhichButton)
    {
        case tvgGetBtn:
            return Rect(102, 43, 157, 63);

        case tvgSetBtn:
            return Rect(102, 69, 157, 89);
    }

    return Rect(0, 0, 0, 0);
}

void __fastcall TVGauge::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
{
    inherited::MouseDown(Button, Shift, X, Y);

    for (int i = tvgGetBtn; i <= tvgSetBtn; ++i)
    {
        TVGaugeButton myBtn = (TVGaugeButton) i;

        TRect r = GetButtonRect(myBtn);
        if (PtInRect(&r, Point(X, Y)))
        {
            if (Button == mbLeft)
                FMouseDown[i] = true;

            if (FOnGaugeButtonMouseDown)
                FOnGaugeButtonMouseDown(this, myBtn, Button, Shift, X-r.Left, Y-r.Top);

            break;
        }
    }
}

void __fastcall TVGauge::MouseUp(TMouseButton Button, TShiftState Shift, int X, int Y)
{
    inherited::MouseDown(Button, Shift, X, Y);

    for (int i = tvgGetBtn; i <= tvgSetBtn; ++i)
    {
        TVGaugeButton myBtn = (TVGaugeButton) i;

        TRect r = GetButtonRect(myBtn);
        if (PtInRect(&r, Point(X, Y)))
        {
            bool bClicked = false;

            if (Button == mbLeft)
            {
                FMouseDown[i] = false;
                bClicked = true;
            }

            if (FOnGaugeButtonMouseUp)
                FOnGaugeButtonMouseUp(this, myBtn, Button, Shift, X-r.Left, Y-r.Top);

            if ((bClicked) && (FOnGaugeButtonClick))
                FOnGaugeButtonClick(this, myBtn);

            break;
        }
    }
}

void __fastcall TVGauge::Paint()
{
    TRect tempR;

    Canvas->Font->Size = 8;

    //whole rect
    Canvas->Pen->Color = clSilver;
    Canvas->Brush->Color = clBtnFace;
    Canvas->Rectangle(ClientRect);

    //----------
    Canvas->Pen->Color = clMedGray;
    Canvas->Font->Color = clWindowText;
    Canvas->Brush->Color = clWhite;

    //Get Button ; draw a rectangle and it should act like a button
    tempR = GetButtonRect(tvgGetBtn);
    Canvas->Rectangle(tempR);
    Canvas->TextRect(tempR, tempR.Left + 10, tempR.Top + 5, _D("Get"));

    //Set Button ; draw a rectangle and it should act like a button
    tempR = GetButtonRect(tvgSetBtn);
    Canvas->Rectangle(tempR);
    Canvas->TextRect(tempR, tempR.Left + 10, tempR.Top + 5, _D("Set"));

    //display values related to the VGauge 
    //..
    //..

    if (OnPaint)
        OnPaint(this);
}

另外,您应该直接从TGraphicControl而不是TPaintBox派生您的组件。 TPaintBoxTGraphicControl之间的区别在于TPaintBox公开OnPaint事件,其中它覆盖Paint()以触发{{} 1}}。您根本不需要组件中的OnPaint事件,因为您正在进行所有自己的绘画(除非您真的希望用户在绘画的顶部绘图)。