SendMessage() is the simplest function you can use to send messages to Windows or to other applications. One of the best ways to test this function is to work with the system commands. You'll find a complete test program for the system commands in the \Chapter 04\C#\SysCommand and \Chapter 04\VB\SysCommand folders of the CD. This example shows the full set of SC commands in action (at least those that are documented). Figure 4.4 shows the dialog for this example, which includes a list of the SC commands, along with one long string for testing the vertical scroll command (SC_VSCROLL).
Note Some commands in the list will only work if you trigger the Test button with the Enter key, instead of clicking Test with the mouse. The reason is that the action takes place immediately—the mouse cursor changes to the double-pointed or other arrow type. Unfortunately, because the mouse is already in use, the command fails. The only way to get around this problem for testing is to use the keyboard in place of the mouse.
igure 4.4: The SysCommand example shows how the various system commands work.
Some of the system commands require special handling. For example, the SC_MONITORPOWER command requires input in the lParam argument. The standard value of 0 doesn't accomplish anything. If you input 1, then the display will go to a low power state, while a value of 2 turns the display off. The example uses a value of 2 to ensure that most systems will see at least a momentary power down of the screen. In some cases, you might have to modify the display settings to get this system command to work properly. Here's the modified code.
DoSysCommand = (Int3 2)SystemCommand.SC_MONITORPOWER; SendMessage(this.Handle, WM_SYSCOMMAND, DoSysCommand, 2); return;
Notice that we're still using the handle for the main window. Figure 4.5 shows another view from Spy++. Notice that each of the major controls in the application is also a window. The window-like quality of the controls enables you to access them by sending them messages. Of course, the control has to have some means of responding to the messages—there's no magic involved.
Warning Figure 4.5 also shows two hidden windows—those with a grayed outline. The first is for .NET
broadcasts, while the second is for GDI+, as opposed to the plain GDI used by standard Windows applications. In most cases, you won't want to modify these windows or send messages to them—you might see unpredictable results. To send a message to a control, you need to provide both a handle for the control's window and an event handler to listen for the message. In some cases, such as moving a window, the .NET Framework provides a default handler. You can also add your own handler that CLR will call when the .NET portion of the call completes. The following code shows how to obtain the handle for lbCommandSel and use it to move the list box around.
IntPtr Temp = IntPtr.Zero; // A temporary handle.
// Load the proper system command. DoSysCommand = (Int3 2)SystemCommand.SC_MOVE;
// Obtain the handle to the list box. Temp = lbCommandSel.Handle;
// Move the list box instead of the main window. SendMessage(Temp, WM_SYSCOMMAND, DoSysCommand, 0); return;
You must highlight the SC_MOVE(List Box) entry in the list, tab twice to highlight the Test button, and then press Enter. Clicking Test will cause the code to fail because the mouse is already engaged in clicking. You'll see the mouse cursor change to a quad-ended move cursor. Moving the mouse will move the list box. Press Enter again and you'll see the ending message found in the lbCommandSel_Move() method. Normally, you'd place any code required to end the move command in this method, but the example uses a simple message box.
Was this article helpful?