Receiving a Windows Message in a Console Application
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4

Thread: Receiving a Windows Message in a Console Application

  1. #1
    Join Date
    May 2010
    Location
    .Net 4.0
    Posts
    58

    Receiving a Windows Message in a Console Application

    Hello,

    I'm trying to write a program that passes Windows messages back and forth from another program that controls a laboratory instrument. I'm in a bit over my head but with the help of the manual I was able to write a program that successfully passes instructions, as evidenced by the instrument doing what I tell it. However, I am having trouble getting a return status from the instrument. The manual instructs the following:

    // demo code, etc.

    // send message to the instrument operating software here...

    SendMessage(hwnd, WM_COPYDATA, tag, (LPARAM) &cd)

    Either a completion message or return data is returned. Remote commands ReturnStatus,
    ReturnTiming, and ReturnData return data. In either case, data is received through an
    asynchronous windows message inside Win32 COPYDATASTRUCT type data packet.
    For example, a typical OnCopyData window callback is shown below, where the string
    data retrieved is finally stored into a Microsoft CString object. Note the use of variable
    replyTag, discussed above, which is used to isolate the correct windows message returned.
    BOOL CUserDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* cd)
    {
    ….
    if (cd->dwData == replyTag)
    {
    /* String pointing to status */
    CString retStatus = (char*) cd->lpData;
    }
    ….
    }
    I can't tell if my problem is in generating the replyTag, getting the HWND to my own console window, or the actual receiving part of the code.

    When setting the replyTag, the manual instructs: UINT replyTag = RegisterWindowMessage(“SOFTMaxProReplyMsg”);. However, I have to put an "L" in front of the string or I get a data type error (can't convert const char* to LPCWSTR).

    When setting a HWND for myself, the manual instructs: HWND MyWnd = GetSafeHwnd().
    That produces an error because GetSafeHwnd is a function of the Cwnd class, and I don't have a Cwnd. I have replaced it with HWND MyWnd = GetConsoleWindow();

    When listening for the reply message, the manual instructs what I quoted above. However, I again don't have a Cwnd. I therefore simply used

    if (cd.dwData == replyTag)
    {
    CString retStatus = (char*) cd.lpData;
    }

    The above if statement always evaluates false, and the cd.lpdata contains the message that I had sent out instead of a reply message. If anyone could help me figure out how to get a reply using my console application, I would really appreciate it. Here is the full code of my function:

    Code:
    #include "stdafx.h"
    #include<iostream>
    #include<vector>
    #include<string>
    #include<afxwin.h>
    
    using namespace std;
    
    void SendCommand(string command)
    {
                  // Get tags to identify the receiving and sending messages
    	UINT tag = RegisterWindowMessage(L"SOFTMaxProMsg");
    	UINT replyTag = RegisterWindowMessage(L"SOFTMaxProReplyMsg");
    
    	// Get the window handles for the receiving software and my program
    	HWND hwnd = FindWindowA("SOFTMaxProMainWnd", "SoftMax Pro");
    	HWND MyWnd = GetConsoleWindow();
    
    	// convert the function's parameter appropriately for a COPYDATASTRUCT
    	char *cmdStr = (char*) command.c_str();
    	char *msgStr = _strdup(cmdStr);
    
    	// Generate the COPYDATASTRUCT to send
    	COPYDATASTRUCT cd;
    	cd.dwData = (DWORD) MyWnd;
    	cd.cbData = strlen(msgStr)+1;
    	cd.lpData = msgStr;
    
    	// Send message to the receving software
    	SendMessage(hwnd, WM_COPYDATA, tag, (LPARAM) &cd);
    
    	// Message gets successfully sent.
    	
    	// Attempt to receive message (not successful and don't know why).
    	if (cd.dwData == replyTag)
    		{
    			cout << "here" << endl;
    			// String pointing to status //
    			CString retStatus = (char*) cd.lpData;
    			cout << retStatus << endl;
    		}
    	else
    	{
    		cout << "else" << endl;
    		cout << (char*) cd.lpData;
    	}
    	
    }

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    11,197

    Re: Receiving a Windows Message in a Console Application

    To receive messages, the program is going to have a message pump. By default, a console application does not have a message pump. What you can do is to create a second worker thread inside the console app, and pump messages within this thread. Of course you will need to synchronize any data that is shared between the main console app thread and the worker thread.

  3. #3
    Join Date
    May 2010
    Location
    .Net 4.0
    Posts
    58

    Re: Receiving a Windows Message in a Console Application

    Quote Originally Posted by Arjay View Post
    To receive messages, the program is going to have a message pump. By default, a console application does not have a message pump. What you can do is to create a second worker thread inside the console app, and pump messages within this thread. Of course you will need to synchronize any data that is shared between the main console app thread and the worker thread.
    Thanks for your help! I tried the multithreading and that was too tough for me but I read a few Win32 tutorials over the weekend and was just able to construct a simple program to send and receive messages from the spec. Thanks for putting me on the message pump trail!

  4. #4
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    3,763

    Re: Receiving a Windows Message in a Console Application

    There's a big difference in how a console program typically works, and how a GUI program works.

    console programs tend to be "linear", the program does stuff in specific order. Any output is "forgotten" as far as the program is concerned (the console manager will handle display) and any input is typically synchronous (the program stops and waits until the necessary input has been given).

    GUI programs or any program needing to handle windows messages are "event driven". You don't know what wil happen in what order (although there are some guarantees of course). ANd the application is expected to promptly service each incoming message and return appropriately within a very short timeframe or the application will appear to 'hang' (=not responsive). Again, for a console app, it's the console manager that takes care of all this.

    You will need to somehow integrate these different approaches, and as Arjay pointed out, a worker thread is the most Obvious way out. It'll require the "console" end of your app to synchronise with the workerthread to "wait" for the data from the windows message.
    Getting this to work properly is tricky.

    It might be easier to look into changing your app to be a simple GUI based program.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center