3

Well, I've tried my best to look at code examples and posts all over the web on how to do this, but I haven't been able to make any headway in a few months using windows API to interact with another program that's already running. I'm not the greatest programmer and some of this stuff is beyond me.

The most I've been able to do is find the Calculator process and its handle, and use that with SetWindowText to change the title. What I'd really like to learn how to do is make my program use the windows user32 (I think this must be the correct library) to enter some numbers by actually pressing the number key buttons on the software calculator to do a simple calculation.

I don't really have a use for this program, it's just a goal I'm trying to reach to learn how to use the windows API past my very beginner level SPECIFICALLY in C#. If no one has the code for this, or even if you do, I'd most appreciate some suggestions for books or resources on the web I should be reading to learn how to do this.

Bret Lien
  • 153
  • 2
  • 8
  • 2
    Once you have the window handle you can send it messages (via `SendMessage` or `PostMessage`). To get it to do things you could try sending it keyboard messages (`WM_KEYDOWN` / `WM_KEYUP`) or button messages (`WM_COMMAND`). The best thing to do is to use a tool like Spy++ to see what messages Calculator itself sees when you press its buttons, and then replicate those. – Jonathan Potter Jan 01 '13 at 07:37
  • As a side resource you might look at AutoIT if you haven't already it has a compiled C# API that hooks into windows for you. You just pass in titles of windows so on so forth. I have some code I can share with you tomorrow on doing exactly what your trying to do with pinvoke. I used to make c# bots which is why I got started with pinvoke. – Steven Combs Jan 01 '13 at 07:54
  • possible duplicate of [Are there any automation test example source code using .NET](http://stackoverflow.com/questions/4294097/are-there-any-automation-test-example-source-code-using-net). The `System.Windows.Automation` namespace is designed exactly for what you are trying to do. – Raymond Chen Jan 01 '13 at 14:06
  • +1 for "If no one has the code for this, or even if you do, I'd most appreciate some suggestions for books or resources on the web I should be reading to learn how to do this." – Greg D Jan 04 '13 at 15:01

2 Answers2

8

Since you say you're using C# you should be using the System.Windows.Automation namespace, whose entire purpose in life is to allow you to control other programs via automation.

You didn't give details as to what you wanted, but here's a program that pushes "7" in the calculator.

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();
 }
}
Raymond Chen
  • 44,448
  • 11
  • 96
  • 135
2

You are entering the fun world of platform invoking (P/Invoke). Your best friend in this world is www.pinvoke.net, which contains c# (and vb.net) signatures for a great number of winapi functions.

For example, SendMessage:

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

and this list of message codes.

You'll notice that all p/invoke methods use the DllImport attribute, found in the System.Runtime.InteropServices namespace.

They also have an extern modifier in the method signature. This means that the code is found outside of the current assembly.

You can then use SendMessage to send messages to the handle of the calculator.

As Jonathan mentioned in his comment, you should use Spy++ to detect which messages are being sent that result in the actions you want to replicate.

For good measure, here is an article with more introductory information on P/Invoke.

Rotem
  • 21,452
  • 6
  • 62
  • 109
  • 1
    Since the OP is writing code in C#, you may as well use `System.Windows.Automation` which does all this heavy lifting for you. – Raymond Chen Jan 01 '13 at 14:07