2012-07-30 50 views
1

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

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++程序员可以提供帮助。

+1

在添加之前,您似乎正在删除该项目。为什么在添加之前,您会期望带有ID cANGANGEN的菜单出现?为什么cLANGMENU与WM_USER相关?这不是消息ID。 – 2012-07-30 12:58:35

+0

@David Heffernan - 的确,第一次尝试删除一个不存在的菜单。它与WM_USER相关,当消息被捕捉到click事件时(例如,这可以改变为另一个ID $ FF00)。问题是,我无法从系统菜单中删除此子菜单。此代码必须运行多次,因此我需要删除此子菜单,并使用不同的值再次插入它。 – RBA 2012-07-30 13:02:54

+1

如果您通过'True'作为'GetSystemMenu'的第二个参数,那么您不必费心去删除任何菜单项。操作系统会给你一个新菜单的句柄,然后你可以*添加*你想要的物品,而不是试图删除你不需要的物品。 – 2012-07-30 14:22:43

回答

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; 
1

Delphi XE2 - 点击该按钮每次都会添加一个Program Language系统菜单项,并且对Scan components不起作用,尽管您说它已被删除。

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

我很抱歉,但我没有时间编码/验证这一点,因为我有一个要赶上的航班,我们似乎有不同的行为与不同的德尔福版本 - 但这是两者之间的区别和你应该看着。

我希望我能有更多的帮助。

+0

谢谢你的尝试。 +1,我会对此进行进一步调查。 – RBA 2012-07-30 11:43:36

+0

请在发现任何问题时更新问题,我将继续尝试帮助 – Mawg 2012-07-30 12:25:02

4

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

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

您可以致电GetSystemMenu(Handle, True)让自己更容易。这会在您每次调用菜单时重置菜单,因此您不必撤消任何以前的定制。

+0

将代码更改为SysMenu:= GetSystemMenu(Handle,True);给出一个空的句柄,所以我不能添加我的物品。对于“程序语言”,我不是以英语为母语的人,而我正在以这个例子为重点讨论我所遇到的问题。我将编辑该问题。 – RBA 2012-07-30 14:55:18

+2

@RBA请阅读GetSystemMenu的文档。传递TRUE进行回复的确会导致返回NULL。您需要跟进呼叫传递FALSE才能获得已重置的可修改菜单。 – 2012-07-30 15:06:33

+0

基于这个答案和评论,我做了一个功能完整的例子。 +1 – RBA 2012-07-31 07:27:40