2

for an application of mine I have been playing around with the Windows API a bit, namely creating a very small wrapper for window functionality. Since I like to have console output as well, I created a console via AllocConsole(). I then noticed that highlighting text in this console (like if you want to copy something) 'freezes' the open window, ie. no messages will be processed, it is not click- or closable. Message loop and wndProc are both standard.

Two questions: is that intended/documented behaviour (I couldn't find anything about it) and if yes, is there a way to disable it? It's kind of annoying.

Thanks in advance

EDIT: as requested, the console creation code:

FILE *conOut = NULL;
FILE *conIn = NULL;

if (::AllocConsole())
{
    ::freopen_s(&conIn, "CONOUT$", "r", stdin);
    ::freopen_s(&conOut, "CONOUT$", "w", stdout);

    // ...

    if (conOut != NULL)
        ::fclose(conOut);
    if (conIn != NULL)
        ::fclose(conIn);

    ::FreeConsole();
}
IGarFieldI
  • 515
  • 3
  • 12
  • Sounds to me like highlighting text in the console window is causing your Windows message pump to stall. Something that I would try would be to spin off a new thread that then creates the console so that your main thread will not be blocked by any activity in the console. Here is the Windows MSDN main page on Consoles https://msdn.microsoft.com/en-us/library/windows/desktop/ms682055(v=vs.85).aspx with a series of links to more specific topics. See also http://stackoverflow.com/questions/192294/how-to-write-to-the-console-in-a-gui-application which has a link to a codeproject sample. – Richard Chambers Jun 03 '16 at 22:31
  • I also suggest you add a code sample into your question showing how you are doing the console creation. And this article may be helpful as well http://dslweb.nwnexus.com/~ast/dload/guicon.htm – Richard Chambers Jun 03 '16 at 22:32
  • 2
    How do you expect the user to highlight anything in a scrolling console window? It is not the only way to pause output, a simple Ctrl+S gets the job done as well. Killer poke. It is a lot like the old USSR jokes, implicit in using a user interface from the 1970s is that the user interface controls you. If you want to control the user interface then you use the winapi to create your own window. And you make the clipboard work. It is more work. – Hans Passant Jun 03 '16 at 22:47
  • Yes, this is standard, intended behavior. Entering selection mode causes console scrolling/refresh to be suspended. Very surprising that you haven't noticed this before now. – Cody Gray - on strike Jun 04 '16 at 03:47

1 Answers1

1

I created a test Win32 application with a basic Win32 project. I added a simple class to handle the console creation and tested two scenarios. What I found was the console window output will stop as if the thread generating the output is suspended when an Edit->Mark is done until the Mark is completed with a Copy or canceled.

The two scenarios tested with the Win32 application were: (1) printing to console window in a separate thread and (2) printing to console window in the main window message handling logic.

The particulars of the test program and details of the two scenarios tested are as follows.

Console.h

#pragma once

#include <stdio.h>

class CConsole
{
public:
    CConsole(void);
    ~CConsole(void);

    int Create(void);

public:
    FILE *m_conOut;
    FILE *m_conIn;
};

Console.cpp

#include "StdAfx.h"
#include "Console.h"

CConsole::CConsole(void)
{
}

CConsole::~CConsole(void)
{
}

int CConsole::Create(void)
{
    if (::AllocConsole())
    {
        ::freopen_s(&m_conIn, "CONIN$", "r", stdin);
        ::freopen_s(&m_conOut, "CONOUT$", "w", stdout);
    }

    return 0;
}

In the main file at the near the top where the Win32 project wizard put some global variables, I added an additional global variable CConsole myConsole; for my console and then I added a bit further down a simple function that is the target of a _beginthreadex(). The function looks like:

unsigned __stdcall myThread( void *x )
{
    HWND  hWnd = (HWND)x;

    // allow for two different test scenarios depending on whether the
    // SendMessage() is commented out or the fprintf() is commented out.
    // if SendMessage() is live then the main window will write to the console window
    // if fprintf() is live then this thread will write to the console window.
    for (int i = 0; i < 50; i++) {
//      SendMessage (hWnd, WM_USER, i, 0);    // send a message to main window to request print
        fprintf (myConsole.m_conOut, "This is line %d\n", i);  // print from this thread
        Sleep (1000);
    }
    return 0;
}

In the InitInstance(HINSTANCE hInstance, int nCmdShow) just before the return statement, I added the following two lines of code:

myConsole.Create();
_beginthreadex (NULL, 0, myThread, hWnd, 0, NULL);

Finally in the main message loop that handles the messages for the main window I added an additional message target:

case WM_USER:
    fprintf (myConsole.m_conOut, "This is line %d\n", wParam);
    break;

I then tried two different experiments by commenting out one of the two lines in my function that is the target of the _beginthreadex().

One was to print to the console window using fprintf() within that thread. The second test case was to send a message of WM_USER to the main window and ask it to use fprintf() to print to the console window.

What I found was that with the printing being done by the thread then I observed the following behavior when I used the Edit->Mark to begin the procedure of marking text to copy:

  • the main window was responsive to menu choices

  • the console window output stopped

  • when I cleared the mark or copied text, console window output resumed

The behavior was as if the thread writing to the console window was suspended until the Mark and Copy procedure was completed.

When the printing was done by the main window's message loop when handling the WM_USER message then I observed the following behavior when I used the Edit->Mark to begin the procedure of marking text to copy:

  • the main window was unresponsive to menu choices

  • the console window output stopped

  • when I cleared the mark or copied text, main window responsiveness returned as did console output

For some additional information about the Console Window Subsystem see Consoles. For a bit of information about the technology see WinEventProc Callback Function along with SetWinEventHook which describes this functionality to some extent as well as What Are WinEvents? and In-Context Hook Function Precautions.

See also Console Window Host in the book Windows Internals for a brief overview of the Console Window Subsystem.

And see Windows 7 / Windows Server 2008 R2: Console Host for an introduction to the architecture changes.

Finally The Console Host Process in Windows 7 from the book Inside Windows Debugging shows how to "discover the various layers involved in the printf sequence".

It may be possible to use the Console functions at a lower level to directly interface with the Console Window Subsystem in order to prevent the freezing of the thread which is doing I/O to the console window.

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106