c++c++buildervclc++builder-10.2-tokyo

Why does mouse down block repainting of a component?


I am trying to create a custom component that captures mouse events, especially MouseMove.

I derive from TWinControl, but I have also tried with TGraphicControl, TCustomControl, TTrackBar, etc.

My problem is when I hold down the mouse on the component, it is not being repainted.

The Paint() method is not called until I release the mouse button, even if I call Invalidate().

A TrackBar is the closest component I want to make. You select the tick, and move it around with the mouse. But you do not have to release the mouse to see the tick move at the same time (the component is drawn again).

If I directly call Paint(), it works, but the background is not erased.

What am I missing?

EDIT : I tried again and i confirm if i held the mouse down, Invalidate(); call are take in account only when i release the mouse. Try your self with my code below, paint is only call on release :

__fastcall TMyCustomComponent::TMyCustomComponent(TComponent* Owner)
    : TCustomTransparentControl(Owner)
{
    mValue = 0;
}

void __fastcall TMyCustomComponent::MouseDown(System::Uitypes::TMouseButton Button, System::Classes::TShiftState Shift, int X, int Y)
{
    if (Button == mbLeft)
        {
        mValueStart = 0;        
        }
}

void __fastcall TMyCustomComponent::MouseMove(System::Classes::TShiftState Shift, int X, int Y)
{       
    Invalidate();       
}

void __fastcall TMyCustomComponent::Paint(void)
{
    TGraphicControl::Paint();   
    Canvas->Font->Name = "Arial";
    Canvas->Font->Size = 8;
    Canvas->Font->Style = TFontStyles() << fsBold;
    Canvas->Font->Color = clInfoText;
    Canvas->Brush->Color = clInfoBk;
    Canvas->FillRect(TRect(0, 0, 104, 21));
    mValue++;
    Canvas->TextOut(0, 2, AnsiString(mValue));
    Canvas->Brush->Color = clBtnShadow; 
}

Solution

  • The following works fine for me:

    __fastcall TMyCustomComponent::TMyCustomComponent(TComponent* Owner)
        : TCustomTransparentControl(Owner)
    {
        mValue = 0;
        InterceptMouse = true; // <-- needed for TCustomTransparentControl to trigger Mouse...() methods!
    }
    
    void __fastcall TMyCustomComponent::MouseDown(System::Uitypes::TMouseButton Button, System::Classes::TShiftState Shift, int X, int Y)
    {
        if (Button == mbLeft)
        {
            mValue = 0;
            Invalidate();
        }
        TCustomTransparentControl::MouseDown(Button, Shift, X, Y);
    }
    
    void __fastcall TMyCustomComponent::MouseMove(System::Classes::TShiftState Shift, int X, int Y)
    {
        ++mValue;
        Invalidate();
        TCustomTransparentControl::MouseMove(Shift, X, Y);
    }
    
    void __fastcall TMyCustomComponent::Paint()
    {
        TCustomTransparentControl::Paint();
        Canvas->Font->Name = "Arial";
        Canvas->Font->Size = 8;
        Canvas->Font->Style = TFontStyles() << fsBold;
        Canvas->Font->Color = clInfoText;
        Canvas->Brush->Color = clInfoBk;
        Canvas->FillRect(TRect(0, 0, ClientWidth, ClientHeight));
        Canvas->TextOut(0, 2, String(mValue));
        Canvas->Brush->Color = clBtnShadow;
    }
    

    Pressing down the left mouse button resets mValue to 0 and paints it. And moving the mouse around the control increments mValue and paints it, whether the mouse button is held down or not.