2012-07-30 46 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