【问题标题】:manipulating the simple windows Calculator using win32 API in c#?在 c# 中使用 win32 API 操作简单的 windows 计算器?
【发布时间】:2012-12-16 00:49:52
【问题描述】:

好吧,我已经尽力查看代码示例并在网上发布了有关如何执行此操作的帖子,但几个月内我无法使用 Windows API 与其他 API 交互取得任何进展已经运行的程序。我不是最伟大的程序员,其中一些东西超出了我的范围。

我能做的最多就是找到 Calculator 进程及其句柄,并将其与 SetWindowText 一起使用来更改标题。我真正想学习的方法是让我的程序使用windows user32(我认为这一定是正确的库)通过实际按下软件计算器上的数字键按钮进行简单计算来输入一些数字。

我对这个程序并没有真正的用处,它只是我试图达到的一个目标,即在 C# 中学习如何在我的初级水平之后使用 Windows API。如果没有人有这方面的代码,或者即使你有,我非常感谢一些关于我应该阅读以了解如何做到这一点的网络书籍或资源的建议。

【问题讨论】:

  • 获得窗口句柄后,您可以向其发送消息(通过SendMessagePostMessage)。要让它做一些事情,你可以尝试向它发送键盘消息 (WM_KEYDOWN / WM_KEYUP) 或按钮消息 (WM_COMMAND)。最好的办法是使用像 Spy++ 这样的工具来查看当您按下它的按钮时计算器本身会看到什么消息,然后复制这些消息。
  • 作为辅助资源,如果您还没有 AutoIT,它有一个已编译的 C# API,可以为您连接到 Windows。您只需传入窗口的标题等等。我有一些代码可以在明天与您分享,具体说明您正在尝试使用 pinvoke 做什么。我曾经制作 c# 机器人,这就是我开始使用 pinvoke 的原因。
  • Are there any automation test example source code using .NET 的可能副本。 System.Windows.Automation 命名空间正是为您想要做的事情而设计的。
  • +1 表示“如果没有人有这方面的代码,或者即使你有,我也会非常感谢一些关于我应该阅读的网络书籍或资源的建议,以了解如何做这个。”

标签: c# windows api winapi


【解决方案1】:

您正在进入平台调用 (P/Invoke) 的有趣世界。你在这个世界上最好的朋友是www.pinvoke.net,它包含大量winapi函数的c#(和vb.net)签名。

例如SendMessage:

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

还有这个list of message codes

您会注意到所有 p/invoke 方法都使用 DllImport 属性,该属性位于 System.Runtime.InteropServices 命名空间中。

它们在方法签名中还有一个extern 修饰符。这意味着代码是在当前程序集之外找到的。

然后您可以使用SendMessage 向计算器的句柄发送消息。

正如 Jonathan 在他的评论中提到的,您应该使用 Spy++ 来检测正在发送的哪些消息会导致您想要复制的操作。

为了更好地衡量,here 是一篇包含更多关于 P/Invoke 的介绍性信息的文章。

【讨论】:

  • 由于 OP 使用 C# 编写代码,您不妨使用System.Windows.Automation,它为您完成所有这些繁重的工作。
【解决方案2】:

既然你说你在使用 C#,你应该使用 System.Windows.Automation 命名空间,它的全部目的是让你通过自动化控制其他程序。

你没有详细说明你想要什么,但这是一个在计算器中按下“7”的程序。

using System.Windows.Automation;

class Program
{
 public static void Main()
 {
  var calcWindow = AutomationElement.RootElement.FindFirst(
   TreeScope.Children,
   new PropertyCondition(AutomationElement.NameProperty, "Calculator"));
  if (calcWindow == null) return;

  var sevenButton = calcWindow.FindFirst(TreeScope.Descendants,
   new PropertyCondition(AutomationElement.NameProperty, "7"));

  var invokePattern = sevenButton.GetCurrentPattern(InvokePattern.Pattern)
                     as InvokePattern;
  invokePattern.Invoke();
 }
}

【讨论】:

  • 我可以在 Winform 应用程序中使用它吗?
  • @Jack 编写一个测试应用程序并找出答案。
  • 哇。你是来自blogs.msdn.com/b/oldnewthing 的雷蒙德。我是你的忠实粉丝。 :)
  • 来自未来的问候。这似乎不适用于 Windows 10。sevenButtonnull
猜你喜欢
  • 2014-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 1970-01-01
相关资源
最近更新 更多