Why my controls don't offer the onMouseWheel event to be handled ?

I need to handle MouseWheel movements over Labels and other controls but the onMouseWheel event is only shown for the Form and not for the controls in my Delphi 7 IDE.
Do I need to handle them in the Form and figure out over witch controls the mouse is each time ?
If the onMouseWheel (and onMouseWheelUp/onMouseWheelDown) event is shown in the hierarchy for the Controls, why is it not shown in their event tabs ?
Thank's for the help !
dadosutterAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

BTechoCommented:
Hello.

Very simply , yes you can use only the Forms OnMouseWheel events.

To know over which component the mouse is currently hovering above you can use this , but it will not work with TLabels only with TWinControls

Place a TApplicationEvents component on the Form, on the OnMessage events use this snippet:


  if Msg.message:=WM_MOUSEWHEEL then begin

//Just for test you can see how easy is it to then access
//the controls properties by just knowing the component
//handle.

 Edit1.Text := FindControl(Msg.hwnd).Name;
   end;


For Labels and other non TWinControls descandents you have to use this on each of the OnMouseEnter events

MouseOverControl: TControl; //Global Variable

Then assign this code to the components OnMouseEnter events:
MouseOverControl := TControl(Sender);

Then on the Form's OnMouseWheel event:
Edit1.Text := MouseOverControl.Name;

I havent tested the code but it should all work :-)

Also of couse you could've created a descadant for each of the control you needed and each have its own MouseWheel events but the above method seems to be less of a hassle.




0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
dadosutterAuthor Commented:
Thank's BEcho,
   I had figured out these options by the time I got your msg and they work just fine.
   My problem is a bit harder though :(
   The thing is that I have some FRAMES, with several (numeric) labels in each of them. These frames are like independend developed mini-aplications and are integrated in the Main Form in diferent tabs of a Page Control.
   What I'm trying to do is to implement a MouseWheel setting of the label values and I want it to be sufficient just take the mouse cursor over a label and then use the wheel.
   Playing with your suggestions, I found out that a frame will only handle the onMouseWheel events if the focus is in one of it's controls and labels are NOT controls. Even if I use a dummy/hidden control (or other trick to keep the focus there), when the label caption is being altered, the focus is lost again and the onMouseWheel event will only be handled by the Main Form handle (if there's one....).
   I also thought about using a global var to save the label we're over and handle the onMouseWheel in the Main Form but I would loose all the Frame independency and encapsulation.
   I just don't understand why the onMouseWheel event is not available for all the controls (and labels are in the StdControls unit, even if they don't "control" anything) just like any other mouse event (onEnter, onClick, etc..)
   What I need then is a way to handle the onMouseWheel INSIDE A FRAME, treating the problem of the focus getting out of the frame when we update a label's caption.
   Yes, I'm setting a "lMouseCurrentlyOver" on the onEnter event of each label and setting it to nil on the onLeave but when I try to update the label's caption, the focus goes away from the frame and my onMouseWheel handler stops receiving wheelDeltas...

Thank's again you all !
Dado
0
dadosutterAuthor Commented:
Hello there,
   Following BTecho sugestions, I ended up in a simple and not very ugly (like handling frame onMouseWheel events on it's host Form) solution and I'm pasting it downhere for those who can be interested in.
   Please be free to ask for the source & dfm code if it'll be of any help for you.
   I'll still work on a "Spinnable Control" class that implements the behavior already achieved here. Thank's BTecho for the help and inspiration :)
   The example shows two 4 digit numbers that can have each digit set just moving the mouse cursor over it and spinning the mouse wheel. Please note that it's NOT necessary to click over any label and this function is still free for any other behavior (ex: reseting the digit to zero).
   I still did NOT understand why the onMouseWheel event was not allowed to be treated directly in each control, just like any other mouse event (onClick, on Enter, etc...).

Good programming out there ! :)
Dado

////////////////////////////////////////////////////////////////////////////////
//
// Simple test of the spinnable digits.
// The funcionality of a mouse wheel is used to "spin" the value of digit labels
//
////////////////////////////////////////////////////////////////////////////////
unit TestingOrbitLabels;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Math;

type
  TOrbitLabels = class(TFrame)
    lbv1d1: TLabel;
    lbv1d4: TLabel;
    lbv1d3: TLabel;
    lbv1d2: TLabel;
    lbv2d1: TLabel;
    lbv2d4: TLabel;
    lbv2d3: TLabel;
    lbv2d2: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    Label1: TLabel;
    Label2: TLabel;
    lbResult: TLabel;
    procedure MouseEnteraDigit(Sender: TObject);
    procedure MouseLeaveaDigit(Sender: TObject);
    procedure FrameMouseWheel(Sender: TObject; Shift: TShiftState;
      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);

  private
    { Private declarations }
    lbMouseCurrentlyOver: TLabel;
    procedure RecalcAll;

  public
    { Public declarations }
  end;

implementation


{$R *.dfm}


////////////////////////////////////////////////////////////////////////////////
//
// onMouseEnter event Handler for ALL single digit labels to be WheelSpinned.
//
////////////////////////////////////////////////////////////////////////////////
procedure TOrbitLabels.MouseEnteraDigit(Sender: TObject);
begin
  lbMouseCurrentlyOver := (Sender as TLabel);
  Self.SetFocus;                        // Keep MouseWheel events in the Frame !
end;

////////////////////////////////////////////////////////////////////////////////
//
// onMouseLeave event Handler for ALL single digit labels to be WheelSpinned.
//
////////////////////////////////////////////////////////////////////////////////
procedure TOrbitLabels.MouseLeaveaDigit(Sender: TObject);
begin
  lbMouseCurrentlyOver := nil;
end;


////////////////////////////////////////////////////////////////////////////////
//
// onMouseWheel event handler
//    This routine handles the mouse wheel spinning over ANY of the "spinnable"
// digits. It doesn't care for the final value of each variable, only for the
// digit value and it's kept between 0 and 9.
//    Once the labels do NOT have an onChange event, a general recalculation
// routine is called at the end to update the variables and the redo the calcs.  
//
////////////////////////////////////////////////////////////////////////////////
procedure TOrbitLabels.FrameMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
  iVal: integer;
begin
  if lbMouseCurrentlyOver <> nil then
    begin                                // Inc & Dec digits between 0 & 9
    iVal := StrToInt(lbMouseCurrentlyOver.Caption);

    iVal := iVal + Sign(WheelDelta);
    if iVal > 9 then
      iVal := 0
    else if iVal < 0
      then iVal := 9;

    lbMouseCurrentlyOver.Caption := IntToStr(iVal);
    RecalcAll;
    Handled := True;
    end;

end;


////////////////////////////////////////////////////////////////////////////////
//
// Called each time a "spinnable" digit change it's value.
//    Here is where the validation (range, sign, etc...) of each variable has to
// be done and where the whole calculations take place.
//    Actual code is just a simple example of 2 vars (v1 & v2) and the
// calculation of it's sum.
//
////////////////////////////////////////////////////////////////////////////////
procedure TOrbitLabels.RecalcAll;
var
  i,
  iV1, iV2: integer;
begin
  iV1 := StrToInt(lbv1d1.Caption);
  iV1 := iV1 + StrToInt(lbv1d2.Caption) * 10;
  iV1 := iV1 + StrToInt(lbv1d3.Caption) * 100;
  iV1 := iV1 + StrToInt(lbv1d4.Caption) * 1000;

  iV2 := StrToInt(lbv2d1.Caption);
  iV2 := iV2 + StrToInt(lbv2d2.Caption) * 10;
  iV2 := iV2 + StrToInt(lbv2d3.Caption) * 100;
  iV2 := iV2 + StrToInt(lbv2d4.Caption) * 1000;

  lbResult.Caption := IntToStr(iV1 + iV2);

end;

end.

---------------------------
.DFM Code follows:
---------------------------

object OrbitLabels: TOrbitLabels
  Left = 0
  Top = 0
  Width = 286
  Height = 240
  TabOrder = 0
  OnMouseWheel = FrameMouseWheel
  object lbv1d1: TLabel
    Left = 240
    Top = 24
    Width = 16
    Height = 37
    Caption = '1'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
    OnMouseEnter = MouseEnteraDigit
    OnMouseLeave = MouseLeaveaDigit
  end
  object lbv1d4: TLabel
    Left = 160
    Top = 24
    Width = 18
    Height = 37
    Caption = '4'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
    OnMouseEnter = MouseEnteraDigit
    OnMouseLeave = MouseLeaveaDigit
  end
  object lbv1d3: TLabel
    Left = 188
    Top = 24
    Width = 18
    Height = 37
    Caption = '3'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
    OnMouseEnter = MouseEnteraDigit
    OnMouseLeave = MouseLeaveaDigit
  end
  object lbv1d2: TLabel
    Left = 216
    Top = 24
    Width = 18
    Height = 37
    Caption = '2'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
    OnMouseEnter = MouseEnteraDigit
    OnMouseLeave = MouseLeaveaDigit
  end
  object lbv2d1: TLabel
    Left = 240
    Top = 69
    Width = 16
    Height = 37
    Caption = '1'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
    OnMouseEnter = MouseEnteraDigit
    OnMouseLeave = MouseLeaveaDigit
  end
  object lbv2d4: TLabel
    Left = 160
    Top = 69
    Width = 18
    Height = 37
    Caption = '4'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
    OnMouseEnter = MouseEnteraDigit
    OnMouseLeave = MouseLeaveaDigit
  end
  object lbv2d3: TLabel
    Left = 188
    Top = 69
    Width = 18
    Height = 37
    Caption = '3'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
    OnMouseEnter = MouseEnteraDigit
    OnMouseLeave = MouseLeaveaDigit
  end
  object lbv2d2: TLabel
    Left = 216
    Top = 69
    Width = 18
    Height = 37
    Caption = '2'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
    OnMouseEnter = MouseEnteraDigit
    OnMouseLeave = MouseLeaveaDigit
  end
  object Label9: TLabel
    Left = 24
    Top = 29
    Width = 26
    Height = 24
    Caption = 'V1'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -19
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
  end
  object Label10: TLabel
    Left = 24
    Top = 74
    Width = 26
    Height = 24
    Caption = 'V2'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -19
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
  end
  object Label11: TLabel
    Left = 109
    Top = 24
    Width = 20
    Height = 37
    Caption = '='
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
  end
  object Label12: TLabel
    Left = 109
    Top = 69
    Width = 20
    Height = 37
    Caption = '='
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
  end
  object Label1: TLabel
    Left = 24
    Top = 152
    Width = 75
    Height = 24
    Caption = 'V1 + V2'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -19
    Font.Name = 'MS Sans Serif'
    Font.Style = [fsBold]
    ParentFont = False
  end
  object Label2: TLabel
    Left = 109
    Top = 144
    Width = 18
    Height = 37
    Caption = '='
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
  end
  object lbResult: TLabel
    Left = 157
    Top = 144
    Width = 72
    Height = 37
    Caption = '8642'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -35
    Font.Name = 'MS Sans Serif'
    Font.Style = []
    ParentFont = False
  end
end
0
dadosutterAuthor Commented:
Thank's for the help !
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.