【问题标题】:NativeWindowHandle Returns 0, but Spy displays handleNativeWindowHandle 返回 0,但 Spy 显示句柄
【发布时间】:2013-09-10 19:23:48
【问题描述】:

我正在尝试自动化应用程序中的流程。当我手动执行此过程时,此过程的 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 ...

目标是选择一个区域并将该区域复制到剪贴板。我可以使用 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);
        }
    }

控制台显示:

得到面板:...,3083016(在 Spy++ 中显示的句柄:002F0B08

Got Main: ... , 0(在 Spy++ 中显示的句柄:007406BC

按回车键开始

试过

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 消息没有发送到执行复制功能的窗口。

编辑:我设法通过使用以下方法从 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

关于为什么这不起作用的任何想法?

【问题讨论】:

    标签: ui-automation postmessage window-handles


    【解决方案1】:

    这里有几个问题。

    1. 如果有问题的控件是无窗口的,NativeWindowHandle 通常可以为 0。由于所有无窗口控件都必须托管在 some 窗口中(即使它是顶级窗口),Spy++ 将始终显示消息将转到的(主机)窗口。如果您确实需要 NativeWindowHandle,您可以沿着自动化父链向上走,直到找到不为 NULL 的 NativeWindowHandle
    2. 您应该使用 UI 自动化方法(例如 SetFocus),或者至少使用 SendInput 发送鼠标/键盘事件,而不是发布鼠标/键盘消息。有很多事情发生在“幕后”,而发布消息根本无法做到。 (例如,激活、键盘状态管理等)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-01
      相关资源
      最近更新 更多