Jump to content
RaelB

Detect when user clicks down on scrollbar button?

Recommended Posts

Hi,

In a control with scrollbar, is it possible to detect when the user clicks down and then up on the middle scrollbar button (i.e. draggable part of the scrollbar)?

Thanks

Edited by RaelB
add info

Share this post


Link to post
3 hours ago, RaelB said:

Hi,

In a control with scrollbar, is it possible to detect when the user clicks down and then up on the middle scrollbar button (i.e. draggable part of the scrollbar)?

Thanks

Yes, in a VCL control, at least. The control wll receive WM_VSCROLL messages when the user manipulates the scrollbar. The message parameters tell you what has happened.

Share this post


Link to post

Thanks. So if a TForm is holding such a component, e.g. TVirtualStringTree, how can I write a method on the form, such that it will be receiving those scrolling messages from the VST?

Share this post


Link to post
17 hours ago, Lajos Juhász said:

You can handle OnMessage for the Applicaton or simple use the OnScroll event of the component.

OnMessage only triggers for posted messages (PostMessage), but WM_VSCROLL is send (SendMessage). Using an OnSCroll event, if the control offers one, is the preferred way, though.

Share this post


Link to post
20 hours ago, RaelB said:

Thanks. So if a TForm is holding such a component, e.g. TVirtualStringTree, how can I write a method on the form, such that it will be receiving those scrolling messages from the VST?

If the OnScroll event of the control is not sufficient for your need you have to subclass the control using its WindowProc property. Here is a short example using a TListbox filled with enough items to show a scrollbar as victim. The form also needs a TMemo to show the message traced.

Note a few things regarding VCL subclassing:

  • You need to find a place where the control you want to subclass has been created and that will only execute once during form creation. I used an overloaded Loaded method.
  • The subclassing should be undone before the form is destroyed. A good place for that is an overloaded BeforeDestruction method.
  • The replacement windowproc must pass all unhandeled messages to the original or the control will stop working. Usually one also passes the message one wants to handle to the original proc, perhaps with modified message parameters.
type
  TMainform = class(Tform)
    ListBox1: TListBox;
    Memo1: TMemo;
  private
    FListWndProc: TWndMethod;
    procedure NewListboxProc(var Message: TMessage);
  protected
    procedure Loaded; override;
  public
    procedure BeforeDestruction; override;
  end;
  
  ....
  
  function GetScrollCodeAsText(aScrollcode: Smallint): string;
begin
  case aScrollcode of
    SB_LINEUP: Result := 'SB_LINEUP';
    SB_LINEDOWN: Result := 'SB_LINEDOWN';
    SB_BOTTOM: Result := 'SB_BOTTOM';
    SB_ENDSCROLL: Result := 'SB_ENDSCROLL';
    SB_PAGEUP: Result := 'SB_PAGEUP';
    SB_PAGEDOWN: Result := 'SB_PAGEDOWN';
    SB_THUMBPOSITION: Result := 'SB_THUMBPOSITION';
    SB_THUMBTRACK: Result := 'SB_THUMBTRACK';
    SB_TOP: Result := 'SB_TOP';
  else
    Result := 'unknown';
  end;
end;


procedure TMainform.BeforeDestruction;
begin
  if Assigned(FListWndProc) and Assigned(ListBox1) then
    Listbox1.WindowProc := FListWndProc;
  inherited;
end;

procedure TMainform.Loaded;
begin
  inherited;
  if Assigned(ListBox1) then begin
    FListWndProc := Listbox1.WindowProc;
    Listbox1.WindowProc := NewListboxProc;
  end;
end;

procedure TMainform.NewListboxProc(var Message: TMessage);
begin
  try
    if Message.Msg = WM_VSCROLL then begin
      memo1.Lines.Add(
        Format('Scroll code: %d (%s), position: %d',
          [TWMVScroll(Message).ScrollCode,
           GetScrollCodeAsText(TWMVScroll(Message).ScrollCode),
           TWMVScroll(Message).Pos
           ]));
    end;

  finally
    FListWndProc(Message);
  end;
end;

A click on the scrollbar thump (still in the top position) results in three messages:

 

Scroll code: 5 (SB_THUMBTRACK), position: 0
Scroll code: 4 (SB_THUMBPOSITION), position: 0
Scroll code: 8 (SB_ENDSCROLL), position: 0

 

Edited by PeterBelow

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×