別のアプリケーションでメニュー コマンドにアクセスするための送信 API はありますか? たとえば、メモ帳の [表示] メニューにアクセスしようとしています。どうすればいいですか?GetSystemMenu を使用して既にメニューを取得しましたが、アクセスできません。これにはすでにAPIがあると思いますが、わかりません。
2 に答える
次の Python のコードは、View / Status Bar メニュー項目を有効にします。とにかく疑似コードのように見えるので、問題なく Delphi に変換できます。横の 4 番目のメニュー項目 (「表示」) と下の 1 番目の項目 (「ステータス バー」) を選択します。必要に応じて、項目をウォークスルーして を使用して、目的の項目をテキストで検索するように変更できますGetMenuString
。詳細については、MSDN を参照してください。
エラーチェックは行わないことに注意してください。また、メモ帳のタイトルが「無題 - メモ帳」であることを想定していることにも注意してください。(これを に変更して、何でも検索できます。それは DelphiNone
にあると思います。)nil
from win32gui import *
from win32con import *
hwnd = FindWindow('Notepad', 'Untitled - Notepad') # use Winspector Spy to find window class name and title
hmenu = GetMenu(hwnd)
hviewmenu = GetSubMenu(hmenu, 3) # 3rd menu item across, starting from 0
id = GetMenuItemID(hviewmenu, 0) # 0th menu item down ("Status Bar")
PostMessage(hwnd, WM_COMMAND, id, 0)
ここにいくつかの Delphi コードがあります。
真のメニューがない場合、これは機能しないことに注意してください。
ヘルプから: 「GetMenu はフローティング メニュー バーでは機能しません。フローティング メニュー バーは、標準メニューを模倣したカスタム コントロールであり、メニューではありません。フローティング メニュー バーのハンドルを取得するには、Active Accessibility API を使用してください。」
たとえば、Delphi 自体では動作しません...
// Grab sub menu for a Window (by handle), given by (0 based) indices in menu hierarchy
function GetASubmenu(const hW: HWND; const MenuInts: array of Integer): HMENU;
var
hSubMenu: HMENU;
I: Integer;
begin
Result := 0;
if Length(MenuInts) = 0 then
Exit;
hSubMenu := GetMenu(hW);
if not IsMenu(hSubMenu) then
Exit;
for I in MenuInts do
begin
Assert(I < GetMenuItemCount(hSubMenu), format('GetASubmenu: tried %d out of %d items',[I, GetMenuItemCount(hSubMenu)]));
hSubMenu := GetSubMenu(hSubMenu, I);
if not IsMenu(hSubMenu) then
Exit;
end;
Result := hSubMenu;
end;
// Get the caption for MenuItem ID
function GetMenuItemCaption(const hSubMenu: HMENU; const Id: Integer): string;
var
MenuItemInfo: TMenuItemInfo;
begin
MenuItemInfo.cbSize := 44; // Required for Windows 95. not sizeof(AMenuInfo)
MenuItemInfo.fMask := MIIM_STRING;
// to get the menu caption, 1023 first chars should be enough
SetLength(Result, 1023 + 1);
MenuItemInfo.dwTypeData := PChar(Result);
MenuItemInfo.cch := Length(Result)-1;
if not GetMenuItemInfo(hSubMenu, Id, False, MenuItemInfo) then
RaiseLastOSError;
// real caption's size. Should call GetMenuItemInfo again if was too short
SetLength(Result, MenuItemInfo.cch);
{$WARN SYMBOL_PLATFORM OFF}
if DebugHook > 0 then
OutputDebugString(MenuItemInfo.dwTypeData);
end;
procedure Test;
var
hwnd, hSubMenu: Cardinal;
id : Integer;
begin
// hwnd := FindWindow('Afx:00400000:8:00010013:00000000:03F61829', nil); // UltraEdit
// hSubMenu := GetASubmenu(hwnd, [5,0]);
hwnd := FindWindow('Notepad', nil); // get the 1st instance of Notepad...
hSubMenu := GetASubmenu(hwnd, [3]); // 4th submenu Menu aka &View
if hSubMenu > 0 then
begin
id := GetMenuItemID(hSubMenu, 0); // 1st Item in that sub menu (must not be a submenu itself)
if id > -1 then
begin
PostMessage(hwnd, WM_COMMAND, id, 0);
ShowMessage('Done: ' + GetMenuItemCaption(hSubMenu, id));
end
else
RaiseLastOSError;
end
else
RaiseLastOSError;
end;