2012-02-22 7 views
4

Media Subtitler라는 프로그램 내에서 메뉴 항목을 클릭하려고합니다.C# WinAPI 메뉴 항목 클릭

먼저 GetMenu 함수를 사용하려고했지만 IntPtr.Zero가 반환되었습니다. 그런 다음 Alt 키 + 내 메뉴의 첫 글자를 사용하여 시도했지만 (F는 파일을 나타냄) 아무 것도하지 않았습니다. 그런 다음 간단한 MOUSEDOWN 및 MOUSEUP 메시지를 사용했지만 다시 시도했지만 아무 것도하지 않았습니다 (해당 범위의 모든 것을 클릭하는 루프를 만들려고했으나 해당 영역에 클릭이 없었습니다).

제가 분명히 알고있는 것은 올바른 창에서 작업하고 있다는 것입니다.

내가 뭘 잘못하고 있니?

누군가 그것을 테스트하고 싶다면 무료로 Media Subtitler를 다운로드 할 수 있으며 그다지 큰 부담은 아닙니다.

또한, 여기에 내가 테스트했던 코드는 다음과 같습니다 어떤 도움

Process p = Process.Start(@"C:\Program Files\DivXLand\Media Subtitler\MediaSub.exe"); 
     p.WaitForInputIdle(1500); 
     Thread.Sleep(3000); 

     SetForegroundWindow(p.MainWindowHandle); 
     ShowWindow(p.MainWindowHandle, SW_MAXIMIZE); 

     IntPtr handle = p.MainWindowHandle; 

     SendMessage(handle, WM_NCHITTEST, 0, MakeLParam(18, 29)); 

     //for (int i = 0; i < 200; i++) 
     //{ 
     // for (int x = 0; x < 200; x++) 
     // { 
     //  SendMessage(p.MainWindowHandle, WM_LBUTTONDOWN, 0, MakeLParam(i, x)); 
     //  SendMessage(p.MainWindowHandle, WM_LBUTTONUP, 0, MakeLParam(i, x)); 
     // } 
     //} 
     //IntPtr menuItems = GetMenu(p.MainWindowHandle); 
     return; 
     //SendMessage(p.MainWindowHandle, WM_COMMAND, 6, 0); 
     SendMessage(p.MainWindowHandle, WM_KEYDOWN, VK_MENU, 0); 
     SendMessage(p.MainWindowHandle, WM_KEYUP, VK_MENU, 0); 
     SendMessage(p.MainWindowHandle, WM_KEYDOWN, VK_F, 0); 
     SendMessage(p.MainWindowHandle, WM_KEYUP, VK_F, 0); 

감사합니다!

답변

6

응용 프로그램의 기본 창으로 보낸 메시지를 모니터링하여 메뉴 항목의 메뉴 식별자를 추출했습니다.

[DllImport("user32.dll")] 
public static extern IntPtr PostMessage(IntPtr hWnd, Message msg, int wParam, int lParam); 

PostMessage(handle, WM_COMMAND, 2, 0); // File->New subtitle 

PostMessage(handle, WM_COMMAND, 3, 0); // File->New from clipboard 

PostMessage(handle, WM_COMMAND, 5, 0); // File->Open text or subtitle 

PostMessage(handle, WM_COMMAND, 6, 0); // File->Open video 

... 

내가 미디어 Subtitler와 코드를 테스트했습니다, 그리고 그것은 마법처럼 작동합니다 : 당신은 wParam로 메뉴 항목의 ID로, 윈도우에 WM_COMMAND 메시지를 게시 할 수 있습니다! 이것이 작동하지 않는 유일한 상황은 Windows Vista 또는 Seven에서 대상 프로그램이 관리자로 실행 중이고 C# 프로그램이 아닌 경우입니다. 그 사실을 알고 있어야합니다!

메뉴 ID는 WM_COMMAND 메시지 (Spy ++ 사용)를 모니터링하여 쉽게 검사 할 수 있습니다.
PostMessage 대신 SendMessage을 사용할 수도 있지만 사용자가 메뉴 작업으로 열린 창을 닫을 때까지 프로그램이 정지됩니다.

동일한 방법을 사용하여 다른 명령을 응용 프로그램의 다른 창으로 보낼 수 있습니다. 예를 들어, '비디오 열기'창에서 '열기'버튼을 클릭하십시오.

+0

답장을 보내 주셔서 감사합니다. spy ++로 프로그램을 보았을 때 메뉴 처리기를 볼 수 없었습니다. 어떻게 찾았습니까? 메뉴 핸들러를 가져 오는 코드를 작성할 수 있습니까? 감사. –

+1

메뉴 처리기를 가져올 필요가 없습니다 (spy ++의 창 속성에서 사용할 수 있음). 방금 창에 대한 메시지를 모니터링했습니다. spy ++에서 창 목록을 새로 고치고 '창 찾기'도구를 클릭하고 십자선을 창으로 드래그하십시오. 찾았 으면 그것을 마우스 오른쪽 버튼으로 클릭하고'Messages'를 선택하십시오. 이 창에서 spy ++는 모든 메시지가 전송되어 창에 게시됨을 나타냅니다. 'Messages' 메뉴 (Ctrl + O)에서'Logging options'을 선택하여 메시지를 필터링 할 수 있습니다. –

+0

고마워요! 그것은 작동합니다! –

0

Visual Studio에는 개체 핸들을 볼 수있는 도구 Spy ++가 있습니다. 당신이 그것을 볼 경우 , 당신은, 당신이 바로 핸들을 얻는 경우에 (핸들이 다른 매번 될 것입니다 당신이 당신의 응용 프로그램을 실행) 그들에게 얻을 USER32.DLL 기능

[DllImport("user32.dll", SetLastError = true)] 
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string className, string lpszWindow); 

를 사용하여 얻을 수있을 것입니다 SendMessage를 사용하여 Enter를 보내거나를 클릭 할 수 있어야합니다.

는 하나의 응용 프로그램에서이 작업을 시도하고, 나는 늘 당신은 또한 System.Windows.Automation 네임 스페이스를 사용하여이 모든 작업을 수행 할 수 있습니다

+2

또 다른 유용한 도구는 [Windows SDK] (http://www.microsoft.com/download/en/details.aspx?id=8279)에서 Insptect Objects (또는 이전 버전에서 호출 된 UISpy)를 사용하는 경우입니다 버전)을 사용하여 창 사이의 관계를 확인합니다. 자동화 코드를 작성할 때 매우 유용합니다. –

4

를 작업하는 경우에만 미안 읽고 텍스트를 작성하는 데 사용 : http://msdn.microsoft.com/en-us/library/ms590934.aspx

이 네임 스페이스를 사용하면 Win32 API와의 interop을 수행 할 필요가 없습니다. 당신이 AutomationElement를 개체로 창을 설정 한 후

public static AutomationElement GetWindowByName(string name) 
{ 
    AutomationElement root = AutomationElement.RootElement; 
    foreach (AutomationElement window in root.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window))) 
    { 
     if (window.Current.Name.Contains(name) && window.Current.IsKeyboardFocusable) 
     { 
      return window; 
     } 
    } 
    return null; 
} 

, 당신은 컨트롤을 검색 등 이러한 컨트롤에 작업을 수행 할 수 있습니다 : 여기에 이름이 포함 된 문자열을 검색하여 창을 얻는 방법의 예 .

희망이 도움이됩니다!

+0

좋은 점은 알지만이 네임 스페이스는 _WPF_Windows에만 해당합니다 – itsho