30

マウスをその場所に移動せずに、ウィンドウが上になくても、プログラムで別のウィンドウの場所をクリックすることは可能ですか?ある場所でのマウスクリックをシミュレートするために、ある種のメッセージを別のウィンドウに送信したいと思います。

私はPostMessageでこれを達成しようとしました:

PostMessage(WindowHandle, 0x201, IntPtr.Zero, CreateLParam(300,300));
PostMessage(WindowHandle, 0x202, IntPtr.Zero, CreateLParam(300,300));

CreateLParam関数を次のように作成しました。

private static IntPtr CreateLParam(int LoWord, int HiWord)
{
     return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
}

問題は、ウィンドウが彼の場所でロックされることです。私のアプリケーションは(1,1)座標をクリックすると思います。誰かがこの問題で私を助けることができますか?

編集:これはPostMessageです:

[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
public static extern bool PostMessage(IntPtr WindowHandle, int Msg, IntPtr wParam, IntPtr lParam);

また、0x201と0x202は、それぞれWM_LBUTTONDOWNとWM_LBUTTONUPです。

4

3 に答える 3

33

メッセージを送信してそれを行うことはできません。代わりに、SendInputWindowsAPIを使用してください。

メソッドClickOnPointを呼び出します。これは、フォームクリックイベントの例です。this.handleフォームハンドルも同様です。これらはウィンドウウィッチハンドルのクライアント座標であることに注意してください。これを簡単に変更して画面座標を送信できます。この場合、必要ありません。以下のハンドルまたはClientToScreen呼び出し。

ClickOnPoint(this.Handle, new Point(375, 340));

更新:今すぐSendInputを使用して、tnxTom。

ところで。私はこのサンプルに必要な宣言のみを使用しました。それ以上のものには素晴らしいライブラリがあります:Windows入力シミュレーター(C#SendInputラッパー-キーボードとマウスのシミュレーション)

  public class ClickOnPointTool
  {

    [DllImport("user32.dll")]
    static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint);

    [DllImport("user32.dll")]
    internal static extern uint SendInput(uint nInputs, [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs,  int cbSize);

#pragma warning disable 649
    internal struct INPUT
    {
      public UInt32 Type;
      public MOUSEKEYBDHARDWAREINPUT Data;
    }

    [StructLayout(LayoutKind.Explicit)]
    internal struct MOUSEKEYBDHARDWAREINPUT
    {
      [FieldOffset(0)]
      public MOUSEINPUT Mouse;
    }

    internal struct MOUSEINPUT
    {
      public Int32 X;
      public Int32 Y;
      public UInt32 MouseData;
      public UInt32 Flags;
      public UInt32 Time;
      public IntPtr ExtraInfo;
    }

#pragma warning restore 649


    public static void ClickOnPoint(IntPtr wndHandle , Point clientPoint)
    {
      var oldPos = Cursor.Position;

      /// get screen coordinates
      ClientToScreen(wndHandle, ref clientPoint);

      /// set cursor on coords, and press mouse
      Cursor.Position = new Point(clientPoint.X, clientPoint.Y);

      var inputMouseDown = new INPUT();
      inputMouseDown.Type = 0; /// input type mouse
      inputMouseDown.Data.Mouse.Flags = 0x0002; /// left button down

      var inputMouseUp = new INPUT();
      inputMouseUp.Type = 0; /// input type mouse
      inputMouseUp.Data.Mouse.Flags = 0x0004; /// left button up

      var inputs = new INPUT[] { inputMouseDown, inputMouseUp };
      SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(INPUT)));

      /// return mouse 
      Cursor.Position = oldPos;
    }

  }
于 2012-04-27T18:26:22.847 に答える
20

過去に、 Windows Media Playerにメッセージを送信する方法を見つけた ので、それを使用して、必要なアプリケーションのクリックをシミュレートしました。

このクラス(以下のコード)を使用して、ウィンドウを見つけ、必要なメッセージを送信します。

using System;
using System.Runtime.InteropServices;

namespace Mouse_Click_Simulator
{
    /// <summary>
    /// Summary description for Win32.
    /// </summary>
    public class Win32
    {
        // The WM_COMMAND message is sent when the user selects a command item from 
        // a menu, when a control sends a notification message to its parent window, 
        // or when an accelerator keystroke is translated.
        public const int WM_KEYDOWN = 0x100;
        public const int WM_KEYUP = 0x101;
        public const int WM_COMMAND = 0x111;
        public const int WM_LBUTTONDOWN = 0x201;
        public const int WM_LBUTTONUP = 0x202;
        public const int WM_LBUTTONDBLCLK = 0x203;
        public const int WM_RBUTTONDOWN = 0x204;
        public const int WM_RBUTTONUP = 0x205;
        public const int WM_RBUTTONDBLCLK = 0x206;

        // The FindWindow function retrieves a handle to the top-level window whose
        // class name and window name match the specified strings.
        // This function does not search child windows.
        // This function does not perform a case-sensitive search.
        [DllImport("User32.dll")]
        public static extern int FindWindow(string strClassName, string strWindowName);

        // The FindWindowEx function retrieves a handle to a window whose class name 
        // and window name match the specified strings.
        // The function searches child windows, beginning with the one following the
        // specified child window.
        // This function does not perform a case-sensitive search.
        [DllImport("User32.dll")]
        public static extern int FindWindowEx(
            int hwndParent, 
            int hwndChildAfter, 
            string strClassName, 
            string strWindowName);


        // The SendMessage function sends the specified message to a window or windows. 
        // It calls the window procedure for the specified window and does not return
        // until the window procedure has processed the message. 
        [DllImport("User32.dll")]
        public static extern Int32 SendMessage(
            int hWnd,               // handle to destination window
            int Msg,                // message
            int wParam,             // first message parameter
            [MarshalAs(UnmanagedType.LPStr)] string lParam); // second message parameter

        [DllImport("User32.dll")]
        public static extern Int32 SendMessage(
            int hWnd,               // handle to destination window
            int Msg,                // message
            int wParam,             // first message parameter
            int lParam);            // second message parameter
    }
}

例えば:

 Win32.SendMessage(iHandle, Win32.WM_LBUTTONDOWN, 0x00000001, 0x1E5025B);

これが、特定の間隔で「BlueStacks」アプリケーションを自動クリックするために作成したアプリケーションのソースコードです。

、、、などについてFindWindowwParamlParamお気軽に質問してください。それほど難しくはありません:);)お役に立てば幸いです。:)

于 2014-06-23T02:46:48.290 に答える
3

コメントを追加できません:D

私のために働く:

[DllImport("User32.dll")]
    public static extern Int32 SendMessage(
    int hWnd,               
    int Msg,                
    int wParam,            
    IntPtr lParam);

次のようにlParamで座標を組み合わせます。

private static IntPtr CreateLParam(int LoWord, int HiWord)
    {
        return (IntPtr)((HiWord << 16) | (LoWord & 0xffff));
    }

と使用:

Clicktoapp.SendMessage(0x00040156, Clicktoapp.WM_LBUTTONDOWN, 0x00000001, CreateLParam(150,150));
        Clicktoapp.SendMessage(0x00040156, Clicktoapp.WM_LBUTTONUP, 0x00000000, CreateLParam(150, 150));

0x00040156-ウィンドウハンドル。

spy ++を使用してウィンドウハンドルを探していましたが、新しい場合は毎回、FindWindowを使用することをお勧めします。

PS

ウィンドウが上にない場合でも、アプリケーションウィンドウのスクリーンショット

https://stackoverflow.com/a/911225/12928587

私はこのソリューションを使用します。うまくいきます。

于 2020-02-20T16:29:12.620 に答える