2013-03-20 58 views
4

我正在尝试执行以下操作之一 1.打开所需的程序并以编程方式按下一个键 2.找到打开的程序窗口,然后按a键编程 (或罚款)发送键盘到c#中的应用程序(sendkeys,postmessage,sendmessage都不工作)

我已经尝试了SendKeys.SendWait(),PostMessage()和SendMessage()的许多实现失败。下面是我的代码片段窗口

//included all these for attempts 
    [DllImport("User32.dll")] 
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 

    [DllImport("User32.dll")] 
    static extern int SetForegroundWindow(IntPtr hWnd); 

    [DllImport("User32.Dll", EntryPoint = "PostMessageA")] 
    static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam); 

    [DllImport("user32.dll")] 
    static extern byte VkKeyScan(char ch); 

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

获取手柄,通过SendMessage函数/ PostMessage的使用变量/的SendKeys

IntPtr ptrOBS = proc.Handle;//this works properly, proc is instantiated properly 
//IntPtr ptrOBS = FindWindow(null, "Open Broadcaster Software v0.472b"); 
SetForegroundWindow(ptrOBS); 
const UInt32 WM_CHAR = 0x0102; 
const uint WM_KEYDOWN = 0x100; 
const int VK_R = 0x52; // taken from http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx 
const int VK_S = 0x53; 

SendMessage函数尝试:

SendMessage(ptrOBS, WM_KEYDOWN, (IntPtr)VK_R, (IntPtr)1);//tried both WM_CHAR and WM_KEYDOWN 

PostMessage的尝试:

string message = "rs"; 
bool sent = PostMessage(ptrOBS, WM_KEYDOWN, VkKeyScan(message[0]), 0); 

的SendKeys尝试:

SendKeys.SendWait("{r}"); 

试图SetFocus的父窗口(应用程序)和子窗口(按钮由按键即时试图发送触发)上:

static void SetFocus(IntPtr hwndTarget, string childClassName) 
    { 
     // hwndTarget is the other app's main window 
     // ... 
     IntPtr targetThreadID = GetWindowThreadProcessId(hwndTarget, IntPtr.Zero); //target thread id 
     IntPtr myThreadID = GetCurrentThread(); // calling thread id, our thread id 
     try 
     { 
      bool lRet = AttachThreadInput(myThreadID, targetThreadID, -1); // attach current thread id to target window 

      // if it's not already in the foreground... 
      lRet = BringWindowToTop(hwndTarget); 
      SetForegroundWindow(hwndTarget); 

      // if you know the child win class name do something like this (enumerate windows using Win API again)... 
      IntPtr hwndChild = (IntPtr)1183492;//(IntPtr)EnumAllWindows(hwndTarget, childClassName).FirstOrDefault(); 

      if (hwndChild == IntPtr.Zero) 
      { 
       // or use keyboard etc. to focus, i.e. send keys/input... 
       // SendInput (...); 
       return; 
      } 

      // you can use also the edit control's hwnd or some child window (of target) here 
      SetFocus(hwndChild); // hwndTarget); 
      SendKeys.SendWait("{r}"); 
     } 
     finally 
     { 
      SendKeys.SendWait("{r}"); 
      bool lRet = AttachThreadInput(myThreadID, targetThreadID, 0); //detach from foreground window 
      SendKeys.SendWait("{r}"); 
     } 
    } 

对于NSGaga:

string windowName = "Open Broadcaster Software v0.472b"; 
IntPtr outerPtr = FindWindow(null, windowName); 
IntPtr ptrOBS = (IntPtr)527814;//button that im trying to trigger keypress on 
SetForegroundWindow(outerPtr); 
SetForegroundWindow(ptrOBS); 
SetFocus(outerPtr, "OBSWindowClass");//SetFocus(ptrOBS, "Button"); 
const UInt32 WM_CHAR = 0x0102; 
const int VK_R = 0x52; // taken from http://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx 
const int VK_S = 0x53; 

//SetForegroundWindow(ptrOBS); 
System.Threading.Thread.Sleep(3000); 
SendKeys.SendWait("{r}"); 
SendMessage(outerPtr, WM_KEYDOWN, (IntPtr)VK_R, (IntPtr)1); 
PostMessage(outerPtr, WM_KEYDOWN, VkKeyScan('r'), 0); 
+0

是目标进程升高吗? – dotcomslashnet 2013-03-20 23:53:21

+0

如果是这样的话,我会冲墙,没有什么区别。 – SPillai 2013-03-21 00:26:01

+0

See:http://stackoverflow.com/questions/4944621/create-an-on-screen-keyboard – tenfour 2013-03-21 00:48:09

回答

2

有大量的试验和错误与的,得到它的工作
下面是一些代码我之前发布的,你可能会想给一个尝试(并有一些附加的详细信息)...

Pinvoke SetFocus to a particular control

尝试第一焦点设置(使用所提到的机构) - 然后使用SendKeysSendInput

这里是SendInput一些详细的代码...

How to send a string to other application including Microsoft Word

+0

试过这个,没有骰子(请参阅OP) – SPillai 2013-03-26 18:39:19

+0

你设法在目标窗口中的任何东西SetFocus - 使用我提出的(必须遵循的字母) - 这是第一步。我曾多次工作过。但是,一些应用程序是特定的。如果有帮助,也可以尝试提升您的应用程序(如管理员)。 – NSGaga 2013-03-26 18:48:53

+0

或尝试发布你的最终代码(用这种方法) - 我会复制粘贴并在这里运行(调整),并尝试在时间允许的情况下查看 – NSGaga 2013-03-26 18:49:35

4

You cannot reliably use SendMessage and PostMessage for synthesizing keyboard input。他们只是没有为此而设计。这些消息(WM_CHAR,WM_KEYDOWN等)是通知当键盘输入已被接收,处理并转发到适当的收件人时由较低级子系统产生。自己发送或发布这些消息就像恶作剧 - 打电话给某人。 (与所有其他输入合成器方法一样,包括专门用于合成键盘输入的SendInput函数,并且至少在某些实现中是SendKeys实际在引擎盖下使用的函数)仅在您希望接收窗口的窗口键盘输入有重点。在Windows中,只有重点(活动)窗口才会接收输入事件。

因此SendKeys可能是如果你打算让它起作用(或者是P/Invoking SendInput及其所有关联结构)的方法,但是你需要尊重收件人的警告窗口必须有重点。否则,它不会得到任何东西。

它看起来像你的示例代码,你试图使用SetForegroundWindow函数来满足这个先决条件。不幸的是,你传递了一个无效值,而没有进行任何错误检查,可能会提醒你这个错误。具体而言,该代码是错误的:

IntPtr ptrOBS = proc.Handle;//this works properly, proc is instantiated properly 
SetForegroundWindow(ptrOBS); // WRONG, ptrOBS is not a window handle 

即使我相信你ptrOBS被正确初始化,这使得它有效的句柄过程,这是不是一个有效的处理非常不同的事情到窗口。除了显而易见的名义差异之外,进程可以有多个窗口,只有一个窗口可以有焦点(即“在前台”)。

在调用SetForegroundWindow之前,您需要获取特定窗口的句柄,并且我们知道一个进程可以有多个窗口,这可能会非常棘手。你需要一些可靠的方法来确定你想要的窗口。很多人通过将窗口的名称作为字符串进行硬编码来实现这一点,这很好地工作,直到目标应用程序重新编译并且此实现细节发生变化。我能想到的唯一防弹方法是让用户点击目标窗口和您的代码来检索当前在鼠标指针下的窗口句柄。

当然,所有这些都假设您已经注意到在链接的SDK文档的“备注”部分列举的使用SetForegroundWindow的限制。

+0

IntPtr ptrOBS = FindWindow(null,“Open Broadcaster Software v0.472b”);也不工作,我假设FindWindow确实返回实际的窗口句柄,而不是进程句柄?但是,谢谢你指出我需要看和改变的事情。我现在将继续用真正的窗口句柄来抨击SendKeys方法。 – SPillai 2013-03-21 00:22:14

+0

@AHeinen你是否证实'FindWindow'实际返回一个句柄?正确的句柄?使用Spy ++通过将它与您感兴趣的窗口的实际句柄进行比较来验证。 – 2013-03-21 02:50:18

+0

它确实返回应用程序的实际父窗口。我也尝试硬编码IntPtr十六进制=>十进制值的子窗口住房我想用按键(热键按下的按钮)运行的行动。使用/两个窗口都不起作用。我试着实现SetFocus(将更新OP与我的尝试) – SPillai 2013-03-26 18:36:40

相关问题