向delphi ide添加toolbutton时的奇怪行为

向delphi ide添加toolbutton时的奇怪行为,delphi,delphi-10.2-tokyo,delphi-ide,timagelist,Delphi,Delphi 10.2 Tokyo,Delphi Ide,Timagelist,我尝试了一些东西,想做一个DelphiIDE扩展。 我的基本想法是扩展当前IDE中的待办事项列表功能 第一步是向IDE添加一个toolbutton,它将打开一个显示todo项的表单 但我注意到一些奇怪的事情,我希望自己造成的,因为这将意味着它可以很容易地修复 我正在将我的toolbutton添加到CustomToolbar,这是一个带有蓝色问号的工具栏(请参见稍后的屏幕截图) 发生的事情是:我安装了我的软件包,按钮被添加了正确的图像,就在现有按钮的旁边。 现在,我用安装的软件包关闭模式表单,然后

我尝试了一些东西,想做一个DelphiIDE扩展。 我的基本想法是扩展当前IDE中的待办事项列表功能

第一步是向IDE添加一个toolbutton,它将打开一个显示todo项的表单

但我注意到一些奇怪的事情,我希望自己造成的,因为这将意味着它可以很容易地修复

我正在将我的toolbutton添加到CustomToolbar,这是一个带有蓝色问号的工具栏(请参见稍后的屏幕截图)

发生的事情是:我安装了我的软件包,按钮被添加了正确的图像,就在现有按钮的旁边。 现在,我用安装的软件包关闭模式表单,然后蓝色问号改变

不要介意我使用的图标,我最终会使用一个不同的图标,但可以。
因此,基本上现有的项目更改为我自己的图标,但由于某种原因禁用。我不明白为什么会这样

正如我在网上找到的指南中所建议的,我使用了TDatamodule来实现我的代码

我的代码:

procedure TDatamoduleToDoList.Initialize;
var
  LResource, LhInst: Cardinal;
begin
  LhInst := FindClassHInstance(Self.ClassType);
  if LhInst > 0 then
  begin
    LResource := FindResource(LhInst, 'icon', RT_Bitmap);
    if LResource > 0 then
    begin
      FBMP := Vcl.Graphics.TBitmap.Create;
      FBMP.LoadFromResourceName(LhInst, 'icon');
    end
    else
      DoRaise('Resource not found');
  end
  else
    DoRaise('HInstance Couldn''t be found');
  FToDoAction := TTodoAction.Create(Self);
  FToDoAction.Category := actionCat;
  FToDoAction.ImageIndex := FIntaServices.ImageList.Add(FBMP, nil);
  FToDoAction.Name := 'my_very_own_action_man';
end;

procedure TDatamoduleToDoList.DataModuleCreate(Sender: TObject);
begin
  //Create extension
  if Supports(BorlandIDEServices, INTAServices, FIntaServices) then
  begin
    Initialize;
    if FToDoAction <> nil then
      FCustBut := TSpeedButton(FIntaServices.AddToolButton(sCustomToolBar, 'CstmToDoList', FToDoAction))
    else
      DoRaise('Initialize failed');
  end
  else
    DoRaise('Something went wrong');
end;
过程TDatamoduleToDoList.Initialize;
变量
LResource,LhInst:红衣主教;
开始
LhInst:=FindClassHInstance(Self.ClassType);
如果LhInst>0,则
开始
LResource:=FindResource(lInst,'图标',RT_位图);
如果LResource>0,则
开始
FBMP:=Vcl.Graphics.TBitmap.Create;
FBMP.LoadFromResourceName(LhInst,“icon”);
结束
其他的
DoRaise(“未找到资源”);
结束
其他的
DoRaise(“找不到HInstance”);
FToDoAction:=TTodoAction.Create(Self);
FToDoAction.Category:=actionCat;
FToDoAction.ImageIndex:=FIntaServices.ImageList.Add(FBMP,nil);
FToDoAction.Name:=“我自己的行为人”;
结束;
过程TDatamoduleToDoList.DataModuleCreate(发送方:ToObject);
开始
//创建扩展名
如果支持(Borlandiservices、INTAServices、FintServices),则
开始
初始化;
如果为零,则
FCustBut:=TSpeedButton(FintServices.AddToolButton(sCustomToolBar,'CstmToDoList',FToDoAction))
其他的
DoRaise(“初始化失败”);
结束
其他的
DoRaise(“出了问题”);
结束;
DoRaise是我自己的过程,它简单地销毁我的所有对象并引发异常,这样做是为了防止ide中的mem泄漏

但是,我认为,我没有做任何奇怪的事情,但这个问题还是发生了。
所以我希望这里的人可能做了一些类似的事情,并且看到了我代码中的错误

提前谢谢

另外,如果你需要更多的信息或者看到该单元的其他部分,请告诉我,我会把整个单元放到github或类似的网站上

编辑: 多亏了@Uwe Raabe,我成功地解决了这个问题。 在INTAServices.AddImages的评论中发现了该问题

AddImages从给定的图像列表中获取所有图像并添加它们 到 主应用程序映像列表。它还从 原始图像索引到主图像列表中的新索引。这 映射由AddActionMenu用于重新映射 将操作对象添加到新的ImageIndex。这应该是第一种方法 将操作和菜单项添加到主应用程序窗口时调用。 返回值是的主应用程序映像列表中的第一个索引 源列表中的第一个图像。使用nil调用此函数 用于清除内部映射数组的图像列表。与来自的AddImages函数不同 在祖先接口中,此版本采用允许相同基本索引的标识 可重复使用。这在IDE实现按需加载时非常有用 个性,这样图像将只注册一次,并且是同一个图像 可以使用索引

最终的解决方案是将我的图像添加到本地imagelist,该imagelist被添加到服务的imagelist中 代码:

过程TDatamoduleToDoList.DataModuleCreate(发送方:TObject);
开始
//创建扩展名
如果支持(Borlandiservices、INTAServices、FintServices),则
开始
初始化;
如果为零,则
开始
FCustBut:=TSpeedButton(fintServices.AddToolButton(sCustomToolBar,'CstmToDoList',FToDoAction));
FToDoAction.ImageIndex:=FintServices.AddImages(FiImages)//这就是解决办法
结束
其他的
DoRaise(“初始化失败”);
结束
其他的
DoRaise(“出了问题”);
结束;

您不应该直接摆弄
INTAServices.ImageList
。改为使用
INTAServices.AddMasked
INTAServices.AddImages
(如果您的数据模块中有本地图像列表)


您可以安全地使用
INTAServices.ImageList连接到控件,但不应直接添加或删除其中的图像。

AddToolButton返回什么类型。您必须强制转换的结果表明它不是您所认为的那样。@DavidHeffernan,AddToolButton返回一个TControl。我同意,硬演员在这里可能会有问题,甚至不应该有任何必要。谢谢你的建议。我用本地图像列表尝试了AddMasked和AddImages,但问题仍然存在。还有其他想法吗?提供一个最小的、完整的例子来说明这个问题。好吧,我更深入地研究了它,并解决了它。答案确实在INTAServices.AddImages中,它在上面的评论中。2.我接受这一点,然后再把问题的答案提出来。。谢谢
procedure TDatamoduleToDoList.DataModuleCreate(Sender: TObject);
begin
  //Create extension
  if Supports(BorlandIDEServices, INTAServices, FIntaServices) then
  begin
    Initialize;
    if FToDoAction <> nil then
    begin
      FCustBut := TSpeedButton(FIntaServices.AddToolButton(sCustomToolBar, 'CstmToDoList', FToDoAction));
      FToDoAction.ImageIndex := FIntaServices.AddImages(FImages);//This is the fix
    end
    else
      DoRaise('Initialize failed');
  end
  else
    DoRaise('Something went wrong');
end;