您可以通过多种方式做到这一点。一种是在 OnMouseDown 事件中使用该事件的 X 和 Y 参数,它们是列表框中的客户端坐标用户点击:
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;
但这不会影响任何 OnClick 事件中的行为。如果您需要在 OnClick 中执行此测试,那么您需要在执行相同测试之前获取鼠标位置并将其转换为列表框客户端坐标:
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;
注意:GetMessagePos() 获取最近观察到的鼠标消息(在这种情况下应该是发起 Click 事件的消息)时的鼠标位置)。但是,如果直接调用 Click 处理程序,则 GetMessagePos() 返回的鼠标位置可能与处理程序中的处理几乎没有相关性或没有相关性。如果任何此类直接调用可能会明智地利用当前鼠标位置,则可以使用 GetCursorPos() 获得。
GetCursorPos() 使用起来也更加直接,因为它直接在 TPoint 值中获取鼠标位置,避免了从 TSmallPoint:
GetCursorPos(mousePos);
无论哪种方式,您的处理程序以任何方式依赖于鼠标位置这一事实使得直接调用此事件处理程序存在问题,因此如果这是一个考虑因素,那么您可能希望将事件处理程序中的任何与位置无关的响应隔离到一个方法中可以在需要时显式调用,与鼠标与控件的交互无关。