2013-09-10 3 views
0

Я пытаюсь автоматизировать процесс в приложении. Spy ++ представление этого процесса, когда я делаю это вручную выглядит следующим образом:NativeWindowHandle Возвращает 0, но Spy отображает дескриптор

WINDOW 002F0B08 
002F0B08 P WM_LBUTTONDOWN fwKeys:MK_LBUTTON xPOS:# ypos:# (Start Pos) 
002F0B08 P WM_MOUSEMOVE fwKeys:MK_LBUTTON xPOS:# ypos:# 
... 
002F0B08 P WM_LBUTTONUP fwKeys:MK_LBUTTON xPOS:# ypos:# (Final Pos) 

WINDOW 007406BC 
007406BC P WM_KEYDOWN fwKeys:VK_CONTROL ... 
007406BC P WM_KEYDOWN fwKeys:VK_C ... 
007406BC P WM_KEYUP fwKeys:VK_CONTROL ... 
007406BC P WM_KEYUP fwKeys:VK_C ... 

Цель состоит в том, чтобы выбрать область и скопировать область в clipbard. Я в состоянии выполнить первую часть с помощью PostMessage:

PostMessage(PanelHandle, WM_LBUTTONDOWN, (int)MK_LBUTTON, new IntPtr(lParam)); //send left mouse button down 

, и это отражено в Spy ++ окно сообщения, но по какой-то причине он не работает в окне, которое отражает сочетание клавиш CTRL + C, когда я делаю это вручную.

Весь код:

class MouseControl 
    { 
     [DllImport("user32.dll")] 
     static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, IntPtr lParam); 

     [DllImport("user32.dll")] 
     public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 


     [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)] 
     static extern void mouse_event(MouseEventFlags flags, uint dx, uint dy, uint delta, IntPtr extraInfo); 

     public static void Select(AutomationElement window) 
     { 
      AutomationElement main = null; 
      AutomationElement panel = window.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "2")); 
      main = window.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Session A - [24 x 80]")); 
      Console.WriteLine("Got Panel: {0} , {1}", panel.ToString(), (new IntPtr(panel.Current.NativeWindowHandle)).ToString()); 
      Console.WriteLine("Got Main: {0} , {1}", main.ToString(), (new IntPtr(main.Current.NativeWindowHandle)).ToString()); 

      if (main == null) 
       Console.WriteLine("Could not find main"); 

      // GET REF POINT IN WINDOW 
      System.Windows.Point p = panel.GetClickablePoint(); 

      // LeftMouseDown(); 
      // LeftMouseUp(); 

      double new_X = p.X-400; 
      double new_Y = p.Y-800; 

      const uint WM_LBUTTONDOWN = 0x0201; 
      const uint WM_LBUTTONUP = 0x0202; 
      const uint MK_LBUTTON = 0x1; 
      const uint WM_MOUSEMOVE = 0x0200; 
      const uint WM_KEYDOWN = 0x100; 
      const uint WM_KEYUP = 0x101; 
      const uint VK_C = 0x043; 
      const uint VK_CONTROL = 0x011; 


      IntPtr PanelHandle = new IntPtr(panel.Current.NativeWindowHandle); 
      IntPtr WindowHandle = new IntPtr(main.Current.NativeWindowHandle); 

      Console.WriteLine("Press Return To Start"); 
      Console.ReadLine(); 

      //LeftMouseDown(); 
      int lParam = (((int)new_Y << 16) | ((int)new_X & 0xffff)); 
      PostMessage(PanelHandle, WM_LBUTTONDOWN, (int)MK_LBUTTON, new IntPtr(lParam));//send left mouse button down 
      Console.WriteLine("Tried"); 
      while (new_X < p.X + 100) 
      { 

       lParam = (((int)new_X << 16) | ((int)new_Y & 0xffff)); 
       PostMessage(PanelHandle, WM_MOUSEMOVE, (int)MK_LBUTTON, new IntPtr(lParam));//send left mouse button down 

       new_X += 1; 
       new_Y += 1; 
      } 

      PostMessage(PanelHandle, WM_LBUTTONUP, (int)MK_LBUTTON, new IntPtr(lParam));//send left mouse button down 
      Console.WriteLine("WM_LBUTTONUP, MK_LBUTTON, {1} was sent to {0}", PanelHandle, lParam); 

      PostMessage(WindowHandle, WM_KEYDOWN, (int)VK_CONTROL, IntPtr.Zero); 
      Console.WriteLine("WM_KEYDOWN, VK_CONTROL was sent to {0}", WindowHandle); 

      PostMessage(WindowHandle, WM_KEYDOWN, (int)VK_C, IntPtr.Zero); 
      Console.WriteLine("WM_KEYDOWN, VK_C was sent to {0}", WindowHandle); 

      PostMessage(WindowHandle, WM_KEYUP, (int)VK_CONTROL, IntPtr.Zero); 
      Console.WriteLine("WM_KEYUP, VK_CONTROL was sent to {0}", WindowHandle); 

      PostMessage(WindowHandle, WM_KEYUP, (int)VK_C, IntPtr.Zero); 
      Console.WriteLine("WM_KEYUP, VK_C was sent to {0}", WindowHandle); 
     } 
    } 

дисплеев консоли:

Got Panel: ..., 3083016 (ручка отображается в Spy ++: 002F0B08

Got Главная: ..., 0 (ручка отображается в Spy ++: 007406BC

Нажмите Enter, чтобы начать

T Ried

WM_LBUTTONUP, MK_LBUTTON, 61538539 был отправлен 3213992

WM_KEYDOWN, VK_CONTROL был отправлен в 0

WM_KEYDOWN, VK_C был отправлен в 0

WM_KEYUP, VK_CONTROL был отправлен в 0

WM_KEYUP, VK_C был отправлен пользователю 0

Он успешно выбирает область, но не может скопировать область. Сообщение CTRL + C не отправляет в окно, которое выполняет функцию копирования.

EDIT: мне удалось заставить его работать (не по желанию, но хорошо сейчас), вручную извлекая ручку с Spy ++ с помощью:

var hwnd = new IntPtr(Convert.ToInt32(Console.ReadLine(), 16)); 
IntPtr WindowHandle = hwnd; 

Однако он не выполняет копию. Это руководство копия Spy ++:

<00271> 00390640 P WM_KEYDOWN nVirtKey:VK_CONTROL cRepeat:1 ScanCode:1D fExtended:0 fAltDown:0 fRepeat:0 fUp:0 
<00368> 00390640 P WM_KEYDOWN nVirtKey:'C' cRepeat:1 ScanCode:2E fExtended:0 fAltDown:0 fRepeat:0 fUp:0 
<00375> 00390640 P WM_KEYUP nVirtKey:'C' cRepeat:1 ScanCode:2E fExtended:0 fAltDown:0 fRepeat:1 fUp:1 
<00376> 00390640 P WM_KEYUP nVirtKey:VK_CONTROL cRepeat:1 ScanCode:1D fExtended:0 fAltDown:0 fRepeat:1 fUp:1 

И это то, что моя программа:

<00013> 00390640 P WM_KEYDOWN nVirtKey:VK_CONTROL cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0 
<00014> 00390640 P WM_KEYDOWN nVirtKey:'C' cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0 
<00015> 00390640 P WM_KEYUP nVirtKey:VK_CONTROL cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0 
<00016> 00390640 P WM_KEYUP nVirtKey:'C' cRepeat:0 ScanCode:00 fExtended:0 fAltDown:0 fRepeat:0 fUp:0 

Любые идеи о том, почему это не работает?

ответ

1

Пара вещей здесь неправильно.

  1. NativeWindowHandle часто может быть 0, если данный элемент управления не имеет окон. Поскольку все элементы управления без окон должны быть размещены в окном (даже если это окно верхнего уровня), Spy ++ всегда будет показывать окно (хост), на которое будет отправлено сообщение. Если вам действительно нужен NativeWindowHandle, вы можете подобрать родительскую цепочку автоматизации, пока не найдете NativeWindowHandle, который не является NULL.
  2. Вместо отправки сообщений мыши/клавиатуры вам следует использовать методы автоматизации пользовательского интерфейса (например, SetFocus) или по адресу наименее, используя SendInput для отправки событий мыши/клавиатуры. Там есть лот вещей, которые происходят «под обложками», что сообщения сообщений просто не делают. (Например, активация, управление состоянием клавиатуры и т. Д.)
Смежные вопросы