Delphi 在状态栏中绘制在XE7版本中不工作的图像

Delphi 在状态栏中绘制在XE7版本中不工作的图像,delphi,delphi-xe3,delphi-xe7,Delphi,Delphi Xe3,Delphi Xe7,我的应用程序将在初始化时在状态栏中显示一些信息。 我通过在状态栏上绘制图标(打开和关闭)来显示这一点。 以下代码在Embarcadero XE3中运行良好,但在XE7版本中不再运行。 该代码不会引发任何异常或错误。 我怎样才能解决这个问题 procedure TFormMain.StatusBar1DrawPanel(StatusBar: TStatusBar; Panel: TStatusPanel; const Rect: TRect); var i: Integer; begin

我的应用程序将在初始化时在状态栏中显示一些信息。 我通过在状态栏上绘制图标(打开和关闭)来显示这一点。 以下代码在Embarcadero XE3中运行良好,但在XE7版本中不再运行。 该代码不会引发任何异常或错误。 我怎样才能解决这个问题

procedure TFormMain.StatusBar1DrawPanel(StatusBar: TStatusBar;
  Panel: TStatusPanel; const Rect: TRect);
var
  i: Integer;
begin
  case Panel.Index of
    3:
    begin
      i := ICON_DATABASE_OFF;
      if HasDatabaseConnection() then
        i := ICON_DATABASE;
      ImageList1.Draw(StatusBar.Canvas, Rect.Left, Rect.Top, i);
    end;
    4:
    begin
      i := ICON_GLOBE_OFF;
      if HasInternetConnection() then
        i := ICON_GLOBE;
      ImageList1.Draw(StatusBar.Canvas, Rect.Left, Rect.Top, i);
    end;
  end;
end;
在XE3中:

更新
(见评论)
发生此错误的原因是
FormMain
OnResizeEvent

procedure TFormMain.FormResize(Sender: TObject);
begin
  //StatusBar1.Panels[0].Width := FormMain.Width - 448;
  StatusBar1.Panels[0].Width := ClientWidth - 448;
end;
调试时显示的值在两个版本中都相同:
在XE3中:
FormMain.Width=1400
ClientWidth=1024

在XE7中:
FormMain.Width=1400
ClientWidth=1024

定义的尺寸为754(宽度)和515(高度)。
由于一些未知的原因,XE7中的图标未绘制。
如果在窗体打开后调整其大小,图标将正确显示

我没有使用任何皮肤或改变我的应用风格。我使用的是默认配置

状态栏将有6个图标:
0-显示提示(宽度是灵活的;当窗体宽度改变时会改变)
1-将显示当前选定公司的名称(固定宽度)
2-将显示当前用户的名称(固定宽度)
3-将显示一个图标(固定宽度)
4-将显示一个图标(固定宽度)
5-将显示日期(固定宽度)

由于painel 1~5有固定的尺寸(total=448),我看不出有理由重新计算painel[0]的宽度%

同样,问题只发生在XE7中


您需要将
TPanel.Style
设置为
psOwnerDraw
而不是默认的
psText
。如果不这样做,则不会调用OnDrawPanel

对类似代码的快速测试表明它可以工作(至少在XE8中):

结果是:

根据海报的评论(此答案下方),该问题似乎实际上与表单的
OnResize
事件中的代码有关,此时没有足够的空间放置两个问题面板。问题代码(摘自海报评论):

首先,要突出显示代码中最重要的问题:从不在表单的事件处理程序中使用
Form.Width
!使用
Self.Width
(或者简单地使用
Width
,这意味着
Self
)生成正确的代码

StatusBar1.Panels[0].Width := Self.Width - 448;
(因此最好使用
Self.ClientWidth
,它是删除调整大小(边缘)边框和任何滚动条后表单的内部(客户端)区域,而不是
Width
,顺便说一句。)

我认为面板图纸的问题与面板宽度计算有关。如果调整面板[0]大小后没有足够的空间放置面板,则索引3和4处的面板会变得太小,并且无法看到绘制到矩形中的图像。我可以通过将此事件处理程序添加到我的第一个代码块并再次运行应用程序、调整表单大小来重现此过程:

procedure TForm1.FormResize(Sender: TObject);
begin
  StatusBar1.Panels[1].Width := Self.Width - 448;
end;
请注意下面两幅图像中第二个面板的外观变化-第一个是当窗体最初以800的设计宽度显示时,第二个是在运行时将窗口宽度减少到600像素后

宽度为800像素的表单-注释状态栏面板和日期:

宽度为600像素的表单-注意带日期的状态栏面板缺失

这里的解决方案是首先扣除面板3和4的宽度,然后将剩余空间的百分比分配给面板0。注意,我在这里使用的是表单的
ClientWidth
,而不是
Width

procedure TFormMain.FormResize(Sender: TObject);
var
  Available: Double;
begin
  Available := ClientWidth - StatusBar1.Panels[3].Width -
               StatusBar1.Panels[4].Width;
  // Allocate 80% of remaining width to first panel
  StatusBar1.Panels[0] := Trunc(Available * 0.8);
end;

样式设置为psOwnerDraw,但仍然不起作用。正如我所说的,在XE3中工作正常,但在XE7中则不行。我没有更改代码。它与上面的代码(我在发布之前测试过)完美配合。在
StatusBar1DrawPanel
处理程序(在
case
行上)中放置一个断点并运行。当你单步执行代码时会发生什么?什么都没有。我意识到,在接下来的执行中,OnFormResize被以下代码调用:
过程TFormMain.FormResize(发送方:TObject);begin StatusBar1.Panels[0]。宽度:=FormMain.Width-448;结束如果我对此行进行注释,则图标绘制正确。现在的问题是:为什么改变面板的宽度会在XE3而不是XE7中停止工作并正常工作?@rodrigopandini:我不知道。我可以将相同的代码(根据我的状态栏1进行调整)添加到上面的表单中,并且它可以正确绘制。(我准确地添加了:
StatusBar1.Panels[1]。宽度:=ClientWidth-448;
用于测试。)注意:不要在
FormMain
的内部事件处理程序中使用
FormMain
-使用
Self
。这样,您的代码应该是
StatusBar1.Panels[0]。宽度:=Self.Width-448取而代之。切勿从窗体的事件处理程序中引用窗体的实例变量。@rodrigopandini:我怀疑发生的情况是,在
FormMain.Width-488
OnResize
中的
panels[0]
占用之后,面板没有足够的空间。在扣除面板3和4的宽度后,计算
面板[0]。宽度
作为一个百分比,并查看是否可以解决此问题。是否在项目中使用样式(项目-选项-应用程序-外观)?表单的运行时宽度是多少?如果小于450,如果增加宽度,使
面板[0]
宽度为正,是否会显示图像?请用这些问题的答案编辑您的问题,并将您提到的事实包括在对Ken Whites答案的评论中。令人沮丧的是,寻求帮助的人太过漠不关心,以至于无法用一些简单的细节来回答,这些细节可能会排除或确认他们问题的可能原因。已编辑。请检查它。那么您是否至少尝试重新计算面板[0]的宽度,以查看它是否已更改
procedure TForm1.FormResize(Sender: TObject);
begin
  StatusBar1.Panels[1].Width := Self.Width - 448;
end;
procedure TFormMain.FormResize(Sender: TObject);
var
  Available: Double;
begin
  Available := ClientWidth - StatusBar1.Panels[3].Width -
               StatusBar1.Panels[4].Width;
  // Allocate 80% of remaining width to first panel
  StatusBar1.Panels[0] := Trunc(Available * 0.8);
end;