/* * Overnet GUI Command Line Client. * version 0.02, 2003-11-21 * Written by: * Norman Rasmussen * * changelog: * 0.02: Norman Rasmussen, 2003-11-21 * Added XML comments * * 0.01: Noramn Rasmussen, 2003-10-31 * Initial version */ using System; using System.Collections; using System.Runtime.InteropServices; using System.Text; namespace overnetguiclc { /// /// Overtnet GUI Command Line Client. ///

This program can be used to send command line commands to a running Overnet client.

///
/// /// Written by: Norman Rasmussen ///

This class inherits the Win32Api class, this is to make calling those methods easier. /// Also by keeping them in a seperate class we keep seperate functions isolated into their function units.

///
class GUICLC : Win32Api { /// /// The Class of the Overnet window. /// private static string sOvernetClass = "Overnet"; /// /// The begining of the Title of the Overnet window. /// private static string sOvernetTitle = "Overnet : "; /// /// The Class used by the hidden window that contains an Overnet client hidden in the system tray area. /// private static string sHiddenClass = "Afx:400000:0"; /// /// The ID of the MDIFrame. /// private static int iMDIFrameID = 0x0000E900; /// /// The ID of the Frame at the bottom of the Overnet window /// private static int iBottomFrameOrViewID = 0x0000E910; /// /// The ID of the Frame inside the bottom frame that contains the entry & output controls /// private static int iDialogID = 0x00001780; /// /// The ID of the Entry TextBox Control /// private static int iEntryID = 0x00001778; /// /// The ID of the Output RichEdit Control /// private static int iOutputID = 0x00001779; /// /// The CallBack Function Pointer for finding the Overnet window /// private static CallBack EnumWindowCallBackFunction; /// /// The ArrayList to store the instance(s) of Overnet windows /// private static ArrayList alOvernet; /// /// The main entry point for the application. /// [STAThread] static void Main(string[] args) { // construct the command we wish to pass to Overnet string cmd = string.Join(" ", args); // set up our callback function EnumWindowCallBackFunction = new CallBack(EnumWindowCallBack); // set up our arraylist alOvernet = new ArrayList(); // go find all the Overnet windows EnumWindows(EnumWindowCallBackFunction, 0); // now for each window we found exec the command foreach (int hWnd in alOvernet) { // find the handles for each control int hWndMDIFrame = GetDlgItem(hWnd, iMDIFrameID); int hWndBottomFrameOrView = GetDlgItem(hWndMDIFrame, iBottomFrameOrViewID); int hWndDialog = GetDlgItem(hWndBottomFrameOrView, iDialogID); int hWndEntry = GetDlgItem(hWndDialog, iEntryID); int hWndOutput = GetDlgItem(hWndDialog, iOutputID); /* // try and get the current text from the output richedit // this is currently broken and for some reason refuses to work // i will try and get around to fixing this later Console.WriteLine("Output: (0x{0:x})", hWndOutput); StringBuilder sbOutput = new StringBuilder(1024); GETTEXTEX gettext = new GETTEXTEX(); gettext.cb = sbOutput.Capacity; gettext.flags = GT_DEFAULT; gettext.codepage = -1; IntPtr ptrgettext = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(GETTEXTEX))); Marshal.StructureToPtr(gettext, ptrgettext, true); int r = SendMessage_GETTEXTEX(hWndOutput, EM_GETTEXTEX, ptrgettext, sbOutput); gettext = (GETTEXTEX)Marshal.PtrToStructure(ptrgettext, typeof(GETTEXTEX)); Marshal.FreeHGlobal(ptrgettext); Console.WriteLine("Output: (0x{0:x})\n{1},{2}", hWndOutput, sbOutput.ToString(), r); */ // set the text of the entry textbox StringBuilder sbEntry = new StringBuilder(cmd); SendMessage_StringBuilder(hWndEntry, WM_SETTEXT, sbEntry.Capacity, sbEntry); // and simulate the Enter key being pressed PostMessage(hWndEntry, WM_KEYDOWN, VK_RETURN, 0); // this is where we would re-read the text from the output section, and display the differences to the consol } } /// /// This finction checks to see if the handle passed in is likely to be (or lead to) an Overnet window. /// /// [in] Handle to a window /// [in] Specifies the application-defined value given to the Enum function /// To continue enumeration, the callback function must return TRUE; to stop enumeration, it must return FALSE. private static bool EnumWindowCallBack(int hwnd, int lParam) { // get the Class & Window names StringBuilder sbTitle = new StringBuilder(256); StringBuilder sbClass = new StringBuilder(256); GetClassName(hwnd, sbClass, sbClass.Capacity); GetWindowText(hwnd, sbTitle, sbTitle.Capacity); if (sbClass.Length > 0) { if (sbClass.ToString().Equals(sHiddenClass)) { // this is a hidden window container, we need to check all the child windows too EnumChildWindows(hwnd, EnumWindowCallBackFunction, lParam + 1); } if (sbClass.ToString().Equals(sOvernetClass) && (sbTitle.Length > 0) && (sbTitle.ToString().StartsWith(sOvernetTitle))) { // it's an Overnet window - save it to the ArrayList alOvernet.Add(hwnd); } } return true; } } /// /// Win32Api helper class. ///

This class imports the appropriate Win32Api calls.

///
/// /// Written by: Norman Rasmussen ///

Many of these defs are just copied directly from Winuser.h and others. The XML details are copied from MSDN help

///
public abstract class Win32Api { /// /// The EnumWindows function enumerates all top-level windows on the screen by passing the handle to each window, in turn, to an application-defined callback function. EnumWindows continues until the last top-level window is enumerated or the callback function returns FALSE /// /// [in] Pointer to an application-defined callback function. For more information, see EnumWindowsProc. /// [in] Specifies an application-defined value to be passed to the callback function. /// ///

If the function succeeds, the return value is nonzero.

///

If the function fails, the return value is zero. To get extended error information, call GetLastError.

///

If EnumWindowsProc returns zero, the return value is also zero.

///
[DllImport("user32.Dll")] public static extern int EnumWindows(CallBack lpEnumFunc, int lParam); /// /// The EnumChildWindows function enumerates the child windows that belong to the specified parent window by passing the handle to each child window, in turn, to an application-defined callback function. EnumChildWindows continues until the last child window is enumerated or the callback function returns FALSE. /// /// [in] Handle to the parent window whose child windows are to be enumerated. If this parameter is NULL, this function is equivalent to EnumWindows. /// [in] Pointer to an application-defined callback function. /// [in] Specifies an application-defined value to be passed to the callback function. /// ///

If the function succeeds, the return value is nonzero.

///

If the function fails, the return value is zero. To get extended error information, call GetLastError.

///
[DllImport("user32.Dll")] public static extern int EnumChildWindows(int hWndParent, CallBack lpEnumFunc, int lParam); /// /// The GetWindowText function copies the text of the specified window's title bar (if it has one) into a buffer. If the specified window is a control, the text of the control is copied. However, GetWindowText cannot retrieve the text of a control in another application. /// /// [in] Handle to the window or control containing the text. /// [out] Pointer to the buffer that will receive the text. If the string is as long or longer than the buffer, the string is truncated and terminated with a NULL character. /// [in] Specifies the maximum number of characters to copy to the buffer, including the NULL character. If the text exceeds this limit, it is truncated. /// ///

If the function succeeds, the return value is the length, in characters, of the copied string, not including the terminating NULL character. If the window has no title bar or text, if the title bar is empty, or if the window or control handle is invalid, the return value is zero. To get extended error information, call GetLastError.

///

This function cannot retrieve the text of an edit control in another application.

///
[DllImport("User32.Dll")] public static extern int GetWindowText(int hWnd, StringBuilder lpString, int nMaxCount); /// /// The GetClassName function retrieves the name of the class to which the specified window belongs. /// /// [in] Handle to the window and, indirectly, the class to which the window belongs. /// [out] Pointer to the buffer that is to receive the class name string. /// [in] Specifies the length, in TCHAR, of the buffer pointed to by the lpClassName parameter. The class name string is truncated if it is longer than the buffer and is always null-terminated. /// ///

If the function succeeds, the return value is the number of TCHAR copied to the specified buffer.

///

If the function fails, the return value is zero. To get extended error information, call GetLastError.

///
[DllImport("User32.Dll")] public static extern int GetClassName(int hWnd, StringBuilder lpString, int nMaxCount); /// /// The GetDlgItem function retrieves a handle to a control in the specified dialog box. /// /// [in] Handle to the dialog box that contains the control. /// [in] Specifies the identifier of the control to be retrieved. /// ///

If the function succeeds, the return value is the window handle of the specified control.

///

If the function fails, the return value is NULL, indicating an invalid dialog box handle or a nonexistent control. To get extended error information, call GetLastError.

///
[DllImport("user32.Dll")] public static extern int GetDlgItem(int hDlg, int nIDDlgItem); /// ///

The SendMessage function sends the specified message to a window or windows. It calls the window procedure for the specified window and does not return until the window procedure has processed the message.

///

To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.

///
/// [in] Handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows. /// [in] Specifies the message to be sent. /// [in] Specifies additional message-specific information. /// [in] Specifies additional message-specific information. /// The return value specifies the result of the message processing; it depends on the message sent. /// Used for when wParam is an int & lParam is an int [DllImport("user32.Dll",EntryPoint="SendMessage")] public static extern int SendMessage(int hWndControl, int Msg, int wParam, int lParam); /// ///

The SendMessage function sends the specified message to a window or windows. It calls the window procedure for the specified window and does not return until the window procedure has processed the message.

///

To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.

///
/// [in] Handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows. /// [in] Specifies the message to be sent. /// [in] Specifies additional message-specific information. /// [in] Specifies additional message-specific information. /// The return value specifies the result of the message processing; it depends on the message sent. /// Used for when wParam is an int & lParam is a StringBuidler [DllImport("user32.Dll",EntryPoint="SendMessage")] public static extern int SendMessage_StringBuilder(int hWndControl, int Msg, int wParam, StringBuilder lParam); /// ///

The SendMessage function sends the specified message to a window or windows. It calls the window procedure for the specified window and does not return until the window procedure has processed the message.

///

To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.

///
/// [in] Handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows. /// [in] Specifies the message to be sent. /// [in] Specifies additional message-specific information. /// [in] Specifies additional message-specific information. /// The return value specifies the result of the message processing; it depends on the message sent. /// Used for when wParam is an IntPtr & lParam is a StringBuidler [DllImport("user32.Dll",EntryPoint="SendMessage")] public static extern int SendMessage_GETTEXTEX(int hWndControl, int Msg, IntPtr wParam, StringBuilder lParam); /// ///

The PostMessage function places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.

///

To post a message in the message queue associate with a thread, use the PostThreadMessage function.

///
/// [in] Handle to the window whose window procedure is to receive the message. The following values have special meanings. ///

HWND_BROADCAST

///

The message is posted to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows. The message is not posted to child windows.

///

NULL

///

The function behaves like a call to PostThreadMessage with the dwThreadId parameter set to the identifier of the current thread.

/// /// [in] Specifies the message to be posted. /// [in] Specifies additional message-specific information. /// [in] Specifies additional message-specific information. /// ///

If the function succeeds, the return value is nonzero.

///

If the function fails, the return value is zero. To get extended error information, call GetLastError.

///
[DllImport("user32.Dll",EntryPoint="PostMessage")] public static extern int PostMessage(int hWndControl, int Msg, int wParam, int lParam); /// /// An application sends a WM_SETTEXT message to set the text of a window. /// public static int WM_SETTEXT = 0x000C; /// /// An application sends a WM_GETTEXT message to copy the text that corresponds to a window into a buffer provided by the caller. /// public static int WM_GETTEXT = 0x000D; /// /// The WM_USER constant is used by applications to help define private messages for use by private window classes, usually of the form WM_USER+X, where X is an integer value. /// public static int WM_USER = 0x0400; /// /// The EM_EXGETSEL message retrieves the starting and ending character positions of the selection in a rich edit control. /// public static int EM_EXGETSEL = WM_USER + 52; /// /// The EM_EXSETSEL message selects a range of characters and/or Component Object Model (COM) objects in a Microsoft® Rich Edit control. /// public static int EM_EXSETSEL = WM_USER + 55; /// /// The EM_GETTEXTEX message allows you to get all of the text from the rich edit control in any particular code base you want. /// public static int EM_GETTEXTEX = WM_USER + 94; /// /// The EM_GETTEXTLENGTHEX message calculates text length in various ways. It is usually called before creating a buffer to receive the text from the control. /// public static int EM_GETTEXTLENGTHEX = WM_USER + 95; /// /// The WM_KEYDOWN message is posted to the window with the keyboard focus when a nonsystem key is pressed. A nonsystem key is a key that is pressed when the ALT key is not pressed. /// public static int WM_KEYDOWN = 0x0100; /// /// ENTER key /// public static int VK_RETURN = 0x0D; /// /// The GETTEXTEX structure contains information about an operation to get text from a rich edit control. This structure is passed in the wParam in the EM_GETTEXTEX message. /// [StructLayout(LayoutKind.Sequential)] public struct GETTEXTEX { public int cb; public int flags; public int codepage; public int lpDefaultChar; public int lpUsedDefChar; }; /// /// The CallBack function is an application-defined callback function used with the callback functions. /// public delegate bool CallBack(int hwnd, int lParam); } }