如何获取TStatusPanel(StatusBar-Delphi)的索引?

如何获取TStatusPanel(StatusBar-Delphi)的索引?,delphi,statusbar,Delphi,Statusbar,例如,我试图在ondblick事件中获取TStatusPanel(一个TStatusBar面板)的索引,以便将其与ShowMessage()一起使用,但我不知道如何获取索引 我知道像OnDrawPanel这样的事件有一个Panel:TStatusPanel参数,但我在OnDblClick中需要相同的东西,但只有一个参数,发送方:TObject 例如,如果StatusBar.Panel=1,则没有类似于的命令。我可以使用StatusBar.Panels[0]但是我不知道如何比较单击的索引来显示我的

例如,我试图在
ondblick
事件中获取
TStatusPanel
(一个
TStatusBar
面板)的索引,以便将其与
ShowMessage()
一起使用,但我不知道如何获取索引

我知道像
OnDrawPanel
这样的事件有一个
Panel:TStatusPanel
参数,但我在
OnDblClick
中需要相同的东西,但只有一个参数,
发送方:TObject

例如,如果StatusBar.Panel=1,则没有类似于
的命令。我可以使用
StatusBar.Panels[0]
但是我不知道如何比较单击的索引来显示我的消息

好吧,这就是我需要的简单方法:

if StatusBar.Panel = 0 then
  showmessage('0')
else if StatusBar.Panel = 1 then
  showmessage('1');
我知道上面的代码不起作用,它只是一个例子。应该是这样的:

if StatusBar.Panels[0].'SOMETHING' = 0 then
  showmessage('0')
else if StatusBar.Panels[0].'SOMETHING' = 1 then
  showmessage('1');

您可以在
OnDblClick
事件处理程序中使用
GetMessagePos
,在检索触发双击处理程序并转换为客户端坐标的
WM_lbuttondblck
消息时获取鼠标位置。然后,您可以在状态栏的面板上迭代,以找到鼠标所在的部分。例如:

procedure TForm1.StatusBar1DblClick(Sender: TObject);
var
  Pt: TPoint;
  i, w: Integer;
begin
  Pt := SmallPointToPoint(TSmallPoint(DWORD(GetMessagePos)));
  MapWindowPoints(HWND_DESKTOP, StatusBar1.Handle, Pt, 1);
  w := 0;
  for i := 0 to StatusBar1.Panels.Count - 1 do begin
    w := w + StatusBar1.Panels[i].Width;
    if Pt.X < w then begin
      ShowMessage(IntToStr(i));
      Break;
    end;
  end;
end;

几乎相同的逻辑,但它从状态栏获取实际的面板边界。换句话说,如果单击面板之间的分隔符,它将返回-1

uses 
  Winapi.CommCtrl;

procedure TForm1.StatusBar1DblClick(Sender: TObject);
var
  LClickPos: TPoint;
  LIndex: Integer;

  function GetPanelIndex: Integer;
  var
    I: Integer;
    LRect: TRect;
  begin
    for I := 0 to StatusBar1.Panels.Count - 1 do
    begin
      if SendMessage(StatusBar1.Handle, SB_GETRECT, I, LPARAM(@LRect)) <> 0 then
      begin
        if PtInRect(LRect, LClickPos) then
          Exit(I);
      end;
    end;

    Result := -1;
  end;

begin
  LClickPos := SmallPointToPoint(TSmallPoint(GetMessagePos()));
  LClickPos := StatusBar1.ScreenToClient(LClickPos);
  LIndex := GetPanelIndex;

  Application.MessageBox(PChar(Format('Panel %d', [LIndex])), 'Test');
end;
使用
Winapi.CommCtrl;
程序TForm1.StatusBar1DblClick(发送方:ToObject);
变量
立法会十题:TPoint ;;
LIndex:整数;
函数GetPanelIndex:整数;
变量
I:整数;
LRect:TRect;
开始
对于I:=0到StatusBar1.Panels.Count-1 do
开始
如果SendMessage(StatusBar1.Handle、SB_GETRECT、I、LPARAM(@LRect))为0,则
开始
如果PtInRect(LRect,LClickPos),则
出口(I);
结束;
结束;
结果:=-1;
结束;
开始
LClickPos:=SmallPointToPoint(TSmallPoint(GetMessagePos());
LClickPos:=StatusBar1.ScreenToClient(LClickPos);
LIndex:=GetPanelIndex;
Application.MessageBox(PChar(格式('Panel%d',[LIndex]),'Test');
结束;
我建议使用而不是。这样,您就减少了向
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;
使用
…,Winapi.CommCtrl;
函数GetStatusPanelAt(StatusBar:TStatusBar;X,Y:Integer):TStatusPanel;超载;
函数GetStatusPanelAt(StatusBar:TStatusBar;const P:TPoint):TStatusPanel;超载;
...
函数GetStatusPanelAt(StatusBar:TStatusBar;X,Y:Integer):TStatusPanel;
开始
结果:=GetStatusPanelAt(状态栏,点(X,Y));
结束;
函数GetStatusPanelAt(StatusBar:TStatusBar;const P:TPoint):TStatusPanel;
变量
索引:整数;
arr:整数数组;
小组:TStatusPanel;
开始
结果:=无;
如果不是PtInRect(StatusBar.ClientRect,P),则
出口
SetLength(arr,SendMessage(StatusBar.Handle,SB_GETPARTS,0,0));
SendMessage(StatusBar.Handle、SB_GETPARTS、Length(arr)、lpram(PInteger(arr));
指数:=0;
而索引如果(P.X

我使用这个解决方案,它对我有效。简单明了

首先,为状态栏的OnMouseDown事件编写一个处理程序

procedure TfrmMain.StatusBarMouseDown(Sender: TObject; Button: TMouseButton; Shift:
  TShiftState; X, Y: Integer);
begin
  TComponent(Sender).Tag := X;
end;
procedure TfrmMain.StatusBarDblClick(Sender: TObject);
var
  AccumelatedWidth, i : Integer;
begin
  AccumelatedWidth := 0;
  for i := 0 to StatusBar.Panels.Count - 1 do
    begin
      AccumelatedWidth := AccumelatedWidth + StatusBar.Panels[i].Width;
      if StatusBar.Tag < AccumelatedWidth then
        begin
          ShowMessage ('You clicked panel ' + i.ToString);
          Break;
        end;
    end;
end;
然后为状态栏的OnDoublClick事件编写一个处理程序

procedure TfrmMain.StatusBarMouseDown(Sender: TObject; Button: TMouseButton; Shift:
  TShiftState; X, Y: Integer);
begin
  TComponent(Sender).Tag := X;
end;
procedure TfrmMain.StatusBarDblClick(Sender: TObject);
var
  AccumelatedWidth, i : Integer;
begin
  AccumelatedWidth := 0;
  for i := 0 to StatusBar.Panels.Count - 1 do
    begin
      AccumelatedWidth := AccumelatedWidth + StatusBar.Panels[i].Width;
      if StatusBar.Tag < AccumelatedWidth then
        begin
          ShowMessage ('You clicked panel ' + i.ToString);
          Break;
        end;
    end;
end;
过程TfrmMain.StatusBarDblClick(发送方:ToObject);
变量
累计宽度,i:整数;
开始
累计宽度:=0;
对于i:=0到StatusBar.Panels.Count-1 do
开始
AccumelatedWidth:=AccumelatedWidth+状态栏。面板[i]。宽度;
如果StatusBar.Tag
给GetMessagePos打电话,找出点击了哪个面板。谢谢你的回答,但状态栏是可调整大小的,GetMessagePos返回不同的位置。你对某人更准确,但后来放弃了对GetCursorPos的准确性。使用GetMessagePosThanks非常重要,它固定在GetMessagePosUsed上并且在我的“小故障”桌面终端上工作得很好…谢谢!
procedure TfrmMain.StatusBarMouseDown(Sender: TObject; Button: TMouseButton; Shift:
  TShiftState; X, Y: Integer);
begin
  TComponent(Sender).Tag := X;
end;
procedure TfrmMain.StatusBarDblClick(Sender: TObject);
var
  AccumelatedWidth, i : Integer;
begin
  AccumelatedWidth := 0;
  for i := 0 to StatusBar.Panels.Count - 1 do
    begin
      AccumelatedWidth := AccumelatedWidth + StatusBar.Panels[i].Width;
      if StatusBar.Tag < AccumelatedWidth then
        begin
          ShowMessage ('You clicked panel ' + i.ToString);
          Break;
        end;
    end;
end;