controlsc++builderc++builder-2006

Why my Control does not catch MouseWheel messages?


Using C++Builder 2006.

I'm trying to modify a TCustomControl derived class, and i need that class to catch mouse wheel events (or messages). I've tried to use the answer for this Delphi question but i don't get the event.

This is my relevant code:

TMouseWheelHandler.h

class PACKAGE TMouseWheelHandler : public TCustomControl
{
private:
  typedef TCustomControl inherited;

protected:
  virtual void __fastcall Paint();

  void __fastcall WMSize            (TWMSize &Message);
  void __fastcall CMMouseEnter  (TMessage &Message);
  void __fastcall CMMouseLeave  (TMessage &Message);
  void __fastcall WMMouseMove       (TMessage &Message);
  BEGIN_MESSAGE_MAP
    VCL_MESSAGE_HANDLER(WM_SIZE, TWMSize, WMSize)
    VCL_MESSAGE_HANDLER(CM_MOUSEENTER   , TMessage, CMMouseEnter)
    VCL_MESSAGE_HANDLER(CM_MOUSELEAVE   , TMessage, CMMouseLeave)
    VCL_MESSAGE_HANDLER(WM_MOUSEMOVE    , TMessage, WMMouseMove)
  END_MESSAGE_MAP(TCustomControl)

  virtual bool DoMouseWheel     (TShiftState Shift, int WheelDelta, TPoint & MousePos);
  virtual bool DoMouseWheelDown (TShiftState Shift,                 TPoint & MousePos);
  virtual bool DoMouseWheelUp       (TShiftState Shift,                 TPoint & MousePos);
  void MouseWheelHandler    (const TMessage &Message);

public:
  __fastcall TMouseWheelHandler(TComponent* Owner);

__published:
  __property OnMouseWheelUp;
  __property OnMouseWheelDown;
  __property OnMouseWheel;
  __property OnClick;
};

TMouseWheelHandler.cpp

//===========================================================================
//===========================================================================
//===========================================================================
bool TMouseWheelHandler::DoMouseWheel   (TShiftState Shift, int WheelDelta, TPoint & MousePos)
{
  OutputDebugString(__FUNC__);
  return inherited::DoMouseWheel(Shift,WheelDelta,MousePos);
}
//===========================================================================
bool TMouseWheelHandler::DoMouseWheelDown (TShiftState Shift,         TPoint & MousePos)
{
  OutputDebugString(__FUNC__);
  return inherited::DoMouseWheelDown(Shift, MousePos);
}
//===========================================================================
bool TMouseWheelHandler::DoMouseWheelUp   (TShiftState Shift,         TPoint & MousePos)
{
  OutputDebugString(__FUNC__);
  return inherited::DoMouseWheelUp(Shift, MousePos);
}
//===========================================================================
// MOUSE MANAGEMENT TAKEN FROM STACKOVERFLOW DELPHI SOLUTION
//===========================================================================
void __fastcall TMouseWheelHandler::CMMouseEnter  (TMessage &Message)
{
  OutputDebugString(__FUNC__);
  SetFocus();
  MouseCapture = true;
  Refresh();
}
//===========================================================================
void __fastcall TMouseWheelHandler::CMMouseLeave  (TMessage &Message)
{
  OutputDebugString(__FUNC__);
  MouseCapture = false;
  Refresh();
}
//===========================================================================
void __fastcall TMouseWheelHandler::WMMouseMove (TMessage &Message)
{
  if (MouseCapture) {
    TPoint pt;
    POINTSTOPOINT(pt , MAKEPOINTS(Message.LParam) );

    if (PtInRect(ClientRect, pt) ) {
      OutputDebugString("MOUSE IN");
    }else{
      OutputDebugString("MOUSE OUT");
      MouseCapture = false;
      Refresh();
    }
  }else{
    OutputDebugString("NO_CAPTURE");
  }
}
//===========================================================================
void TMouseWheelHandler::MouseWheelHandler  (const TMessage &Message)
{
  OutputDebugString(__FUNC__);
  TMessage MyMessage = Message; // In the DELPHI sample Message was'nt a const
  MyMessage.Result = Perform(CM_MOUSEWHEEL, MyMessage.WParam, MyMessage.LParam);
  if (MyMessage.Result == 0) {
    inherited::MouseWheelHandler(MyMessage);
  }
}
//===========================================================================
//===========================================================================
//===========================================================================

And this is how i use the Control in my Form:

WH = new TMouseWheelHandler(this);
WH->Parent = Panel1;
WH->Align  = alTop;
WH->Height = Panel1->Height/2;
WH->OnMouseWheel        = GGMouseWheel;
WH->OnMouseWheelDown    = GGMouseWheelDown;
WH->OnMouseWheelUp      = GGMouseWheelUp;

void __fastcall TTestForm::GGMouseWheel(TObject *Sender, TShiftState Shift, int WheelDelta, const TPoint &MousePos, bool &Handled)
{
  OutputDebugString(__FUNC__);
}
//---------------------------------------------------------------------------

void __fastcall TTestForm::GGMouseWheelDown(TObject *Sender, TShiftState Shift, const TPoint &MousePos, bool &Handled)
{
  OutputDebugString(__FUNC__);
}
//---------------------------------------------------------------------------

void __fastcall TTestForm::GGMouseWheelUp(TObject *Sender, TShiftState Shift, const TPoint &MousePos, bool &Handled)
{
  OutputDebugString(__FUNC__);
}
//---------------------------------------------------------------------------

What i see from the debug prints are that none of the DoMouse* functions and also the MouseWheelHandler function are never called, while the Form GGMouseWheel* functions are.

All i'd need is to manage some variables in the DoMouse* functions.

What am i doing wrong?


Solution

  • Your MESSAGE_MAP should be declared public not protected, since it overrides the virtual Dispatch() method which is public. Personally, I prefer to override the virtual WndProc() method instead of using MESSAGE_MAPs.

    That being said, there is no need to handle the mouse wheel messages directly, simply override the virtual DoMouseWheel...() methods. Note that your DoMouseWheel...() and MouseWheelHandler() methods are all declared incorrectly, so they are NOT overriding the virtual methods of the same names.

    Try these declarations instead (you could have looked in Controls.hpp to get these, or read the documentation):

    DYNAMIC bool __fastcall DoMouseWheel(TShiftState Shift, int WheelDelta, const TPoint &MousePos);
    DYNAMIC bool __fastcall DoMouseWheelDown(TShiftState Shift, const TPoint &MousePos);
    DYNAMIC bool __fastcall DoMouseWheelUp(TShiftState Shift, const TPoint &MousePos);
    DYNAMIC void __fastcall MouseWheelHandler(TMessage &Message);