我有一个包含可变数量项目的高列表框。它并不总是满满的。我知道当用户没有通过此代码选择项目时:
if ( lstbox.ItemIndex = -1 ) then
ShowMessage('here');
但是当我选择一个Item然后点击列表框的'whitespace'时,这不起作用。我该如何发现这种情况?
答案 0 :(得分:7)
您可以通过多种方式完成此操作。一个是在 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 事件的消息)。但是,如果直接调用单击处理程序,则 GetMessagePos()返回的鼠标位置可能与处理程序中的处理几乎没有关系。如果任何此类直接调用可能合理地利用当前鼠标位置,则可以使用 GetCursorPos()获得。
GetCursorPos()也可以直接使用,因为它可以直接获取 TPoint 值中的鼠标位置,从而无需转换 TSmallPoint < /强>:
GetCursorPos(mousePos);
无论哪种方式,您的处理程序以任何方式依赖于鼠标位置的事实使得直接调用此事件处理程序成为问题,因此如果这是一个考虑因素,那么您可能希望将事件处理程序中的任何位置无关响应隔离到一个方法中可以在需要时显式调用,而与鼠标与控件的交互无关。