Saturday, November 3, 2012

Update text in C++ from AutoIt using SendMessage

Last week me and another programmer worked on one-way communication between an AutoIt application with a C++ application.

The C++ application, let's call it Launcher, launched the AutoIt (let's call it Worker) and waited for it to finish while the AutoIt performed various tasks which are quicker to write in script than in C++. In the end the Worker would return a value indicating success or failure and the Launcher continue accordingly displaying a message to the user.

We used this solution for a couple of customers in the past (each time just replacing the Worker to perform a different task), and since the Worker's tasks could have taken a while to complete we added GUI for it as well.
This caused us to have multiple windows for what was supposed to be a simple don't-make-me-think Launcher.

After trying a few methods for displaying both windows (all of which looked bad) we decided that the Worker would notify the Launcher on it's progress and the Launcher would show it, and since the Worker is different every time we needed it quite flexible.

Since AutoIt doesn't really have callback functions and we didn't want to bring COM into the equation we decided that the Launcher would pass to the Worker a handle to a window, and the Worker would update the text in that window using WinAPI's SendMessage.

Now, even though AutoIt has a wrapper for SendMessage ("_SendMessage") it didn't work when passing strings (or unicode strings), which is what we needed. Even the DllCall, while appearing to work and returning a success value didn't pass the string correctly, it would always arrive as 0.

After many trial and errors, this is the solution that worked.
const $WM_SETTEXT = 0xC

$Edithwnd = $cmdline[1]
$sText = "status update"

DllCall("user32.dll", "int", "SendMessageW", "hwnd", $Edithwnd, "UINT", $WM_SETTEXT, "WPARAM", 0, "wstr", $sText)

  • user32.dll is the dll that contains the function.
  • SendMessageW is the name of the function, if you don't use Unicode and need the ANSI version just call SendMessage.
  • $Edithwnd is the window handle to update in the Launcher.
  • $WM_SETTEXT marks the message type. In our case a const in windows programming, 0XC, which says WM_SETTEXT.
  • The 0 is a additional parameters which needs to be 0 in our case.
  • and $sText is the text we want to pass to the Launcher. Again, if you are using ANSI make sure this is "str" type and not "wstr".

I know that after figuring out the parameter types that worked I could have still used the _SendMessage function with working types, but I just didn't see the point as it just calls the sendMessageW function anyway.

No comments:

Post a Comment