2012-07-30 3 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 cLANGMENU가있는 메뉴가 나타날 것이라고 기대하십니까? 왜 cLANGMENU는 WM_USER와 관련이 있습니까? 메시지 ID가 아닙니다. –

+0

@David Heffernan - 실제로 처음으로 존재하지 않는 메뉴를 삭제하려고합니다. 메시지가 클릭 이벤트에서 catch되면 WM_USER와 관련됩니다 (예 : 다른 ID $ FF00으로 변경할 수 있음). 문제는 시스템 메뉴에서이 하위 메뉴를 삭제할 수 없다는 것입니다. 이 코드는 여러 번 실행해야하므로이 하위 메뉴를 삭제하고 다른 값으로 다시 삽입해야합니다. – RBA

+1

'GetSystemMenu'의 두 번째 매개 변수로'True'를 전달하면, 메뉴 항목 삭제에 신경 쓸 필요가 없습니다. OS는 신선한 메뉴에 대한 핸들을 제공하고, 원하지 않는 항목을 삭제하려고하는 대신 원하는 항목을 추가 * 할 수 있습니다. –

답변

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

델파이 XE2 - 버튼을 클릭하면 매번 Program Language 시스템 메뉴 항목이 추가되고 Scan components에는 영향을 미치지 않지만 제거됩니다.

Scan components은 하위 메뉴가없는 최상위 메뉴 항목이며 '프로그램 언어'에는 하위 메뉴 항목 0 -> 5가 있기 때문에 제안하는 바입니다. 먼저 해당 항목을 삭제하면 그런 다음 부모 메뉴를 삭제할 수 있어야합니다 (흠, 자신의 자녀를 정리해서는 안됩니까?).

죄송하지만, 나는 잡을 비행기가있어 코드를 작성하고 검증 할 시간이 없으며 다른 델파이 버전과는 다른 행동을하는 것처럼 보입니다.하지만 그 차이점은 무엇입니까? 보고 있어야합니다.

나는 더 많은 도움이되기를 바랍니다.

+0

시험해 주셔서 감사합니다. +1, 그리고 이것에 대한 추가 조사를 할 것입니다. – RBA

+0

아무 것도 발견하지 못하면 질문을 업데이트하십시오. – Mawg

4

The documentationmiim_ID 플래그를 wID으로 설정해야한다는 것을 나타냅니다. 이를 사용하지 않으면 OS가 해당 필드를 무시하므로 사용자가 만든 메뉴 항목에 지정한 ID 값이 표시되지 않습니다. 따라서 해당 ID로 해당 항목을 참조하려는 추가 시도가 실패합니다.

"구성 요소 검색"항목을 추가 할 때 해당 플래그를 설정하지만 "테스트"항목에서는 생략합니다.

GetSystemMenu(Handle, True)으로 전화하면 더 쉽게 할 수 있습니다. 이렇게하면 호출 할 때마다 메뉴가 재설정되므로 이전 사용자 정의를 실행 취소 할 필요가 없습니다.

+0

이 코드를 SysMenu로 Chaging하는 것을 계속 돕겠습니다 : = GetSystemMenu (Handle, True); 빈 핸들을 제공하므로 아이템을 추가 할 수 없습니다. "프로그램 언어"의 경우, 저는 영어 원어민이 아니며, 제가 가진 문제에 초점을 맞춘이 예를하고있었습니다. 나는 그 질문을 편집 할 것이다. – RBA

+2

@RBA GetSystemMenu에 대한 설명서를 읽으십시오. 되돌리기 위해 TRUE를 전달하면 실제로 NULL이 반환됩니다. 리셋 된 수정 가능한 메뉴를 얻으려면 FALSE를 전달하는 호출을 따라야합니다. –

+0

이 답변과 의견을 바탕으로 완전히 기능적인 예를 만들었습니다. +1 – RBA

관련 문제