MessageReceiverWindow

Introduction

MessageReceiverWindow is a graphical tool that receives and displays Windows messages. The tool can either be used with the put_utility feature or with an arbitrary client (e.g. a Python program) that sends messages to a previously spawned instance of MessageReceiverWindow.exe.

Usage

An instance of MessageReceiverWindow.exe can be started as follows:

MessageReceiverWindow <title>

The optional argument title specifies the title of the MessageReceiverWindow instance. If the argument is omitted, the instance gets the default title Form1. Windows messages of type WM_COPYDATA that are send to the spawned instance, appear in its message log. The Copy To Clipboard button allows to copy the content of the message log to the clipboard. The Save As ... button can be used to save the content to a file.

MessageReceiverWindow during the execution of Test Library model MRW01.

Special Commands

While arbitrary text messages are diplayed in the message log, there are special commands for controlling special behavior of an instance of MessageReceiverWindow:

Message Action
@CopyToClipboard Copies the content of the message log to the clipboard
@SaveAs [file] Writes the content of the message log to [file]
@Terminate Terminates the MessageReceiverWindow executable

Usage With put_utility

The put_utility feature offers a convenient integration of MessageReceiverWindow. The example MRW01 shows how this works. First of all, an instance of MessagereceiverWindow needs to be spawned from within GAMS:

$set title Form1
Execute.Async "MessageReceiverWindow.exe %title%";

As soon as the window is ready, text messages or special commands can be sent by using put_utility with the command winMsg:

file f;
put_utility f 'WinMsg' / '%title%' / 'This is some Windows Message from GAMS';

By sending @Terminate, the instance can be terminated:

put_utility f 'WinMsg' / '%title%' / '@Terminate';

Usage With Python

The example MRW02 from the GAMS Test Library demonstrates the use of MessageReceiverWindow from within Python. While it uses the Python programming language from within an Embedded Code section, other programming languages can be used as long as they provide access to Windows messages.

First of all, a ctypes.Structure derived class is defined which is used for sending Windows message to a MessageReceiverWindow instance:

class _CopyDataStruct(ctypes.Structure):
_fields_ = [('dwData', ctypes.c_char_p),
('cbData', ctypes.c_ulong),
('lpData', ctypes.c_char_p)]

The function sendMessage() sends a message to the window with the title windowName. It makes use of functions FindWindowA and SendMessageA from ctypes.windll.user32:

def sendMessage(windowName, message):
cs = _CopyDataStruct()
receiver = ctypes.windll.user32.FindWindowA(None, bytes(windowName, 'utf-8'))
cmd = bytes(message, 'utf-8')
cs.dwData = 1
cs.cbData = len(cmd)+1
cs.lpData = cmd
WM_COPYDATA = 0x4A
ctypes.windll.user32.SendMessageA(receiver, WM_COPYDATA, 0, ctypes.byref(cs))

Popen from the subprocess module is used in order to start an instance of MessageReceiverWindow. The system_directory property of a GamsWorkspace instance from the GAMS Python API is used for finding a GAMS system directory:

windowName = 'MRW Python'
p = Popen([os.path.join(GamsWorkspace().system_directory, 'MessageReceiverWindow.exe'), windowName])

As soon as the window is ready, text messages or special commands can be sent by using the previously defined sendMessage function:

sendMessage(windowName, "This is some Windows Message from Python")

Sending @Terminate will terminate the running MessageReceiverWindow instance:

sendMessage(windowName, "@Terminate")