【问题标题】:send mouse click发送鼠标点击
【发布时间】:2016-01-08 13:22:02
【问题描述】:

我正在尝试通过 sendmessage 在不使用鼠标的情况下模拟鼠标点击 不知何故它不起作用,但没有错误显示。 这是我的新代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Diagnostics;


namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private const int BM_CLICK = 0x00F5;

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

        [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);

    public Form1()
    {
        InitializeComponent();
    }



        private void button1_Click(object sender, EventArgs e)
        {
            IntPtr hwndChild = IntPtr.Zero;
            IntPtr hwnd = IntPtr.Zero;
            hwnd = FindWindow(null, "MSPaintApp");
            hwndChild = FindWindowEx(hwnd, IntPtr.Zero, "Afx:00007FF765740000:8", null);
            SendMessage(hwndChild, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
        }
    }
}

你能告诉我如何放置 X Y 坐标,它会点击一个子窗口。我看到很多帖子教如何做到这一点,但我不知道理解它,系统说不要问其他人的问题:(

【问题讨论】:

    标签: c#


    【解决方案1】:

    对我来说,问题是应该使用 FindWindow("MSPaintApp", null) 搜索 MSPaintApp 窗口,因为 MSPaintApp 是类名,而不是窗口标题。

    那么,Afx:00007FF765740000:8 不是MSPaintApp 的孩子,而是MSPaintView 的孩子,即MSPaintApp 的孩子。

    此外,您不必“模拟”BM_CLICK,但必须先模拟 WM_LBUTTONDOWN,然后再模拟 WM_LBUTTONUP

    请考虑这个似乎可以工作的示例(在 Windows 7 上)

    class Program
    {
        private const uint WM_LBUTTONDOWN = 0x201;
        private const uint WM_LBUTTONUP = 0x202;
        private const uint MK_LBUTTON = 0x0001;
    
        public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr parameter);
    
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
    
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
    
        [DllImport("user32.dll", SetLastError = true)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
    
        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
    
        static IntPtr childWindow;
    
        static void Main(string[] args)
        {                     
            IntPtr hwndMain = FindWindow("MSPaintApp", null);
            IntPtr hwndView = FindWindowEx(hwndMain, IntPtr.Zero, "MSPaintView", null);
            // Getting the child windows of MSPaintView because it seems that the class name of the child isn't constant
            EnumChildWindows(hwndView, new EnumWindowsProc(EnumWindow), IntPtr.Zero);
            // Simulate press of left mouse button on coordinates 10, 10
            SendMessage(childWindow, WM_LBUTTONDOWN, new IntPtr(MK_LBUTTON), CreateLParam(10, 10));
            // Simulate release of left mouse button on coordinates 100, 100
            SendMessage(childWindow, WM_LBUTTONUP, new IntPtr(MK_LBUTTON), CreateLParam(100, 100)); 
        }
    
        static bool EnumWindow(IntPtr handle, IntPtr pointer)
        {
            // Get the first child because it seems that MSPaintView has only this child
            childWindow = handle;
            // Stop enumerating the windows
            return false;
        }
    
        private static IntPtr CreateLParam(int LoWord, int HiWord)
        {
            return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
        }
    }
    

    【讨论】:

    • 非常感谢 codroipo。你是我的英雄!!!我试了一下,它似乎就像我希望的那样工作。但这确实给我留下了一个大问题。你怎么知道paint的hwndmain是MsPaintApp。和 hwndView = MSPaintView?我的意思是也许我可能会在差异程序上编写下一个代码。如何正确获取程序的 hwndmain 和 hwndview?
    • @EakzilaKung 我们知道 hwndMainMSPaintApp 多亏了 Spy++。 hwndView 也是如此。如果你想编写一个模拟点击其他程序窗口的通用方法,我认为你不能,因为程序使用了很多Windows。在 Paint 中,我们知道要绘制我们必须单击 MSPaintView 的第一个子 window,其他程序肯定使用另一种 Windows 架构(具有不同的类名)。例如在 Paint 中,如果我们想点击 Paste 按钮,我们需要找到合适的窗口来发送合适的消息
    • 这对我来说真的很复杂。在我阅读了您上面的信息之后。我尝试使用其他程序,它确实有很多孩子。而且看起来更复杂的是,我需要处理的孩子是孩子中的孩子。和 this//// IntPtr hwndView = FindWindowEx(hwndMain, IntPtr.Zero, "MSPaintView", null);为什么后面的孩子是 IntPtr.Zero 而字符串类名是 MSPaintView。我认为 MSPaintView 是 MsPaintApp 之后的孩子。对不起......我真的不知道,我觉得我问了一些愚蠢的问题。我试图自己寻找答案,但完全不明白
    • @EakzilaKung 将 childAfter 指定为 FindWindowEx 的意思是“ehy,FindWindowEx,枚举 parent 之后的所有子窗口 childAfter”(有关参数的更多信息,请查看 MSDN)。 MSPaintViewMsPaintApp 的孩子,Afx:000somethingMSPaintView 的孩子。所以顺序是MsPaintApp->MSPaintView->Afx:000something
    【解决方案2】:

    我要回到这里很多年了,但我很确定在最小化应用程序时不会传递鼠标事件窗口消息。我确定最小化的窗口无论如何都会受到不同的对待。

    除此之外,当窗口没有被最小化时,这段代码是否有效?您可能想使用 Spy++ 多看一下窗口的结构,因为我认为您需要获取您尝试单击的任何内容的 hWnd 并在那里发送消息。很大程度上取决于应用程序本身的编写方式以及 UI 的绘制方式。

    【讨论】:

    • 它根本不动。油漆是否最小化无关紧要。我还将看看 Spy++ 和 hWnd。谢谢
    • 我快速浏览了一下,似乎有更好的方法来模拟鼠标输入(大概是因为您不知道目标中正在订阅和使用哪些鼠标事件应用)。看看这里:stackoverflow.com/questions/8021954/…
    猜你喜欢
    • 1970-01-01
    • 2012-11-05
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    相关资源
    最近更新 更多