1

我有以下代码,将项目添加到系统菜单。我的问题是 DeleteMenu(SysMenu, cLANGMENU, MF_BYCOMMAND) 没有删除添加到系统菜单的弹出菜单。我无法理解的是为什么为添加的项目(扫描组件)工作,而不是为“程序语言”工作

procedure TForm1.Button1Click(Sender: TObject);
const aBaseItem : string = 'Programm-Sprache';
      cSepSYSTEM_MENU = wm_user + 100;
      cScanCompSystemMenu = wm_user + 101;
      cLANGMENU = wm_user + 102;
      SC_ITEM = $FF00;
var
  MenuItemInfo: TMenuItemInfo;
  PopupMenu: HMENU;
  Result: Boolean;
  SysMenu: HMenu;
  iPos, NumItems : Integer;
  wTemp1, wtemp2 : string;
  Buffer: array[0..79] of Char;
begin
  {Create the popup menu}
  PopupMenu := CreatePopupMenu;
  {Insert an item into it}
  for iPos := 5 downto 0 do
  begin
    FillChar(MenuItemInfo, SizeOf(MenuItemInfo), iPos);
      with MenuItemInfo do
      begin
        cbSize := SizeOf(MenuItemInfo);
        fMask := MIIM_TYPE or MIIM_ID;
        fType := MFT_STRING;
        wID := SC_ITEM + iPos;
        dwTypeData := PChar(inttostr(iPos));
        cch := Length(dwTypeData) * 2 + 2; //4; {'Item' is 4 chars}
      end;
    Result := InsertMenuItem(PopupMenu, 0, True, MenuItemInfo);
    Assert(Result, 'InsertMenuItem failed');
  end;

  SysMenu := GetSystemMenu(Handle, False);
  //why this isn't working???
  if not DeleteMenu(SysMenu, cLANGMENU, MF_BYCOMMAND) then
   begin
     ShowMessage('System Error Message: '+ SysErrorMessage(GetLastError)) ;
     //error message is - operation completed succesfully
   end;

  {Insert the popup into the system menu}
  FillChar(MenuItemInfo, SizeOf(MenuItemInfo), 0);
  with MenuItemInfo do
  begin
    cbSize := SizeOf(MenuItemInfo);
    fMask := MIIM_SUBMENU or MIIM_TYPE or MIIM_ID;
    fType := MFT_STRING;
    hSubMenu := PopupMenu;
    wId := cLANGMENU;
    dwTypeData :=  PChar('Test');//Before editing the question it was Program Language
    cch := Length(dwTypeData) * 2 + 2; //7; {'SubMenu' is 7 chars}
  end;

  Assert(SysMenu <> 0);
  Result := InsertMenuItem(SysMenu, GetMenuItemCount(SysMenu), True, MenuItemInfo);
  Assert(Result, 'InsertMenuItem failed');


      SysMenu := GetSystemMenu(Handle, False);
  //delete menu if exists - this is working
  DeleteMenu(SysMenu,cSepSYSTEM_MENU,MF_SEPARATOR);
  DeleteMenu(SysMenu,cScanCompSystemMenu,MFT_STRING);
  //add new ones
  InsertMenu(SysMenu, Word(-1), MF_SEPARATOR, cSepSYSTEM_MENU, '');
  FillChar(MenuItemInfo, SizeOf(TMenuItemInfo), #0);
  with MenuItemInfo do
   begin
   cbSize := SizeOf(TMenuItemInfo);
    fMask := MIIM_TYPE or MIIM_ID or MIIM_STATE;
    fType := MFT_STRING;
    wId := cScanCompSystemMenu;
    dwTypeData := PChar('Scan components');
    cch := Length('Scan components');
   end;
  Result := InsertMenuItem(SysMenu, GetMenuItemCount(SysMenu), True, MenuItemInfo);
  Assert(Result, 'InsertMenuItem failed');
end;

LE:这段代码运行了好几次,所以我需要删除每次添加的项目。LE2:即使这段代码是用Delphi(Object Pascal)编写的,它也从Windows 调用WinApi 函数。也许有人在这方面进行了大量工作并且是 C/C++ 程序员可以提供帮助。

4

3 回答 3

4

该文档表明您需要设置miim_ID标志以使用wID. 没有它,操作系统会忽略该字段,因此您创建的菜单项不会获得您指定的 ID 值。因此,您进一步尝试通过该 ID 引用该项目失败。

您在添加“扫描组件”项时设置了该标志,但为“测试”项省略了它。

您可以致电GetSystemMenu(Handle, True). 这将在您每次调用它时重置菜单,因此您不必撤消任何先前的自定义。

于 2012-07-30T14:32:42.457 回答
1

Program LanguageDelphi XE2 -每次单击按钮都会添加一个系统菜单项,Scan components尽管您说它已为您删除,但没有任何影响。

我建议这是因为它Scan components是一个没有子菜单的顶级菜单项,而“程序语言”有子菜单项 0 -> 5。我怀疑如果你先删除这些,你应该可以删除父菜单(嗯,它不应该清理它自己的孩子吗?)。

很抱歉,但我没有时间编码/验证这一点,因为我要赶飞机,而且我们似乎对不同的 Delphi 版本有不同的行为——但这就是两者之间的区别,你应该看看.

我希望我能提供更多帮助。

于 2012-07-30T10:46:22.590 回答
1

根据 Rob Kennedy 和 David Heffernan 的回答,我解决了这个问题。解决方法不是删除菜单项,而是重新获取系统菜单的句柄。代码如下:

procedure TForm1.Button1Click(Sender: TObject);
const 
      cSepSYSTEM_MENU = wm_user + 100;
      cScanCompSystemMenu = wm_user + 101;
      cLANGMENU = 65444;
      SC_ITEM = $FF00;
var
  MenuItemInfo: TMenuItemInfo;
  PopupMenu: HMENU;
  Result: Boolean;
  SysMenu: HMenu;
  iPos, NumItems : Integer;
  wTemp1, wtemp2 : string;
  Buffer: array[0..79] of Char;
  subMenu : HMENU;
begin

  SysMenu := GetSystemMenu(Handle, True);
  SysMenu := GetSystemMenu(Handle, False);

  //add new ones
  InsertMenu(SysMenu, Word(-1), MF_SEPARATOR, cSepSYSTEM_MENU, '');
  FillChar(MenuItemInfo, SizeOf(TMenuItemInfo), #0);
  with MenuItemInfo do
   begin
   cbSize := SizeOf(TMenuItemInfo);
    fMask := MIIM_TYPE or MIIM_ID or MIIM_STATE;
    fType := MFT_STRING;
    wId := cScanCompSystemMenu;
    dwTypeData := PChar('Scan components');
    cch := Length('Scan components');
   end;
  Result := InsertMenuItem(SysMenu, GetMenuItemCount(SysMenu), True, MenuItemInfo);
  Assert(Result, 'InsertMenuItem failed');

  {Create the popup menu}
  PopupMenu := CreatePopupMenu;
  {Insert an item into it}
  for iPos := Random(10) downto 0 do
  begin
    FillChar(MenuItemInfo, SizeOf(MenuItemInfo), 0);
      with MenuItemInfo do
      begin
        cbSize := SizeOf(MenuItemInfo);
        fMask := MIIM_TYPE or MIIM_ID;
        fType := MFT_STRING;
        wID := SC_ITEM + iPos;
        dwTypeData := PChar(inttostr(iPos));
        cch := Length(dwTypeData) * 2 + 2; //4; {'Item' is 4 chars}
      end;
    Result := InsertMenuItem(PopupMenu, 0, True, MenuItemInfo);
    Assert(Result, 'InsertMenuItem failed');
  end;

  FillChar(MenuItemInfo, SizeOf(MenuItemInfo), 0);
  with MenuItemInfo do

  begin
    cbSize := SizeOf(MenuItemInfo);
    fMask := MIIM_SUBMENU or MIIM_TYPE;
    fType := MFT_STRING;
    hSubMenu := PopupMenu;
    wId := cLANGMENU;
    dwTypeData :=  PChar('Programm-Language');
    cch := Length(dwTypeData) * 2 + 2; //7; {'SubMenu' is 7 chars}
  end;

  Assert(SysMenu <> 0);
  Result := InsertMenuItem(SysMenu, GetMenuItemCount(SysMenu), True, MenuItemInfo);
  Assert(Result, 'InsertMenuItem failed');
end;
于 2012-07-31T07:26:47.157 回答