我建议使用SB_GETPARTS
代替SB_GETRECT
。这样,您发送给TStatusBar
的消息会更少:
uses
..., Winapi.CommCtrl;
function GetStatusPanelAt(StatusBar: TStatusBar; X, Y: Integer): TStatusPanel; overload;
function GetStatusPanelAt(StatusBar: TStatusBar; const P: TPoint): TStatusPanel; overload;
...
function GetStatusPanelAt(StatusBar: TStatusBar; X, Y: Integer): TStatusPanel;
begin
Result := GetStatusPanelAt(StatusBar, Point(X, Y));
end;
function GetStatusPanelAt(StatusBar: TStatusBar; const P: TPoint): TStatusPanel;
var
index: Integer;
arr: array of Integer;
Panel: TStatusPanel;
begin
Result := nil;
if not PtInRect(StatusBar.ClientRect, P) then
Exit;
SetLength(arr, SendMessage(StatusBar.Handle, SB_GETPARTS, 0, 0));
SendMessage(StatusBar.Handle, SB_GETPARTS, Length(arr), LPARAM(PInteger(arr)));
index := 0;
while index < Length(arr) do
begin
if (P.X <= arr[index]) or (arr[index] = -1) then
begin
Result := StatusBar.Panels[index];
Exit;
end;
Inc(index);
end;
end;
然后,您可以这样做:
uses
..., System.Types, Winapi.Windows;
procedure TForm5.StatusBar1DblClick(Sender: TObject);
var
Pt: TPoint;
Panel: TStatusPanel;
begin
Pt := SmallPointToPoint(TSmallPoint(GetMessagePos()));
Pt := StatusBar1.ScreenToClient(Pt);
Panel := GetStatusPanelAt(StatusBar1, Pt);
if Panel <> nil then
ShowMessage('Click on Panel ' + IntToStr(Panel.Index))
else
ShowMessage('No click on a Panel');
end;
或者,如果您使用的是D2006或更高版本,则可以将逻辑封装到类助手中:
uses
..., Winapi.CommCtrl;
type
TStatusBarHelper = class helper for TStatusBar
public
function GetPanelAt(X, Y: Integer): TStatusPanel; overload;
function GetPanelAt(const P: TPoint): TStatusPanel; overload;
end;
...
function TStatusBarHelper.GetPanelAt(X, Y: Integer): TStatusPanel;
begin
Result := GetPanelAt(Point(X, Y));
end;
function TStatusBarHelper.GetPanelAt(const P: TPoint): TStatusPanel;
var
index: Integer;
arr: array of Integer;
Panel: TStatusPanel;
begin
Result := nil;
if not PtInRect(Self.ClientRect, P) then
Exit;
SetLength(arr, SendMessage(Self.Handle, SB_GETPARTS, 0, 0));
SendMessage(Self.Handle, SB_GETPARTS, Length(arr), LPARAM(PInteger(arr)));
index := 0;
while index < Length(arr) do
begin
if (P.X <= arr[index]) or (arr[index] = -1) then
begin
Result := Self.Panels[index];
Exit;
end;
Inc(index);
end;
end;
uses
..., System.Types, Winapi.Windows;
procedure TForm5.StatusBar1DblClick(Sender: TObject);
var
Pt: TPoint;
Panel: TStatusPanel;
begin
Pt := SmallPointToPoint(TSmallPoint(GetMessagePos()));
Pt := StatusBar1.ScreenToClient(Pt);
Panel := StatusBar1.GetPanelAt(Pt);
if Panel <> nil then
ShowMessage('Click on Panel ' + IntToStr(Panel.Index))
else
ShowMessage('No click on a Panel');
end;