Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect "whitespace" click in a listbox

Tags:

delphi

I have a tall listbox with a variable number of items. It won't always be full. I know when a user doesn't select an item by this code:

if ( lstbox.ItemIndex = -1 ) then
  ShowMessage('here');

But this does not work when I an Item is selected and then I click in the 'whitespace' of the listbox. How do I detect that sort of situation?

like image 368
Paul Avatar asked Oct 29 '25 16:10

Paul


1 Answers

You can do this in a number of ways. One would be in the OnMouseDown event using the X and Y parameters to that event, which are the client co-ordinates in the listbox at which the user clicked:

procedure TMyForm.ListBox1MouseDown(Sender: TObject;
                                    Button: TMouseButton;
                                    Shift: TShiftState;
                                    X,  Y: Integer);
begin
  if TListbox(Sender).ItemAtPos(Point(X, Y), TRUE) <> -1 then
    // item was clicked
  else
    // 'whitespace' was clicked
end;

But this won't affect the behaviour in any OnClick event. If you need to perform this test in OnClick then you need to obtain the mouse position and convert it to the listbox client co-ordinates before doing the same test:

procedure TMyForm.ListBox1Click(Sender: TObject);
var
  msgMousePos: TSmallPoint;
  mousePos: TPoint;
begin
  // Obtain screen co-ords of mouse at time of originating message
  //
  // Note that GetMessagePos returns a TSmallPoint which we need to convert to a TPoint
  //  in order to make further use of it

  msgMousePos := TSmallPoint(GetMessagePos);  

  mousePos := SmallPointToPoint(msgMousePos);
  mousePos := TListbox(Sender).ScreenToClient(mousePos);

  if TListbox(Sender).ItemAtPos(mousePos, TRUE) <> -1 then
    // item clicked
  else
    // 'whitespace' clicked
end;

NOTE: GetMessagePos() obtains the mouse position at the time of the most recently observed mouse message (which should in this case be the message that originated the Click event). However, if your Click handler is invoked directly then the mouse position returned by GetMessagePos() is likely to have little or no relevance to the processing in the handler. If any such direct invocation might sensibly utilise the current mouse position, then this may be obtained using GetCursorPos().

GetCursorPos() is also much more straightforward to use as it obtains the mouse position in a TPoint value directly, avoiding the need to convert from TSmallPoint:

GetCursorPos(mousePos);

Either way, the fact that your handler is dependent upon mouse position in any way makes directly invoking this event handler problematic so if this is a consideration then you might wish to isolate any position independent response in the event handler into a method that can be explicitly invoked if/when required, independently of the mouse interaction with the control.

like image 173
Deltics Avatar answered Oct 31 '25 07:10

Deltics



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!