在控制台中突出显示文本会使窗口无响应

时间:2016-06-03 22:11:31

标签: c++ winapi

对于我的应用程序,我一直在使用Windows API,即为窗口功能创建一个非常小的包装器。由于我也喜欢控制台输出,我通过AllocConsole()创建了一个控制台。然后我注意到在这个控制台中突出显示文本(如果你想复制一些东西)'冻结'打开的窗口,即。不会处理任何消息,也不会点击或关闭。消息循环和wndProc都是标准的。

两个问题:是有意/有记录的行为(我无法找到任何关于它的内容),如果有,是否有办法禁用它?这有点烦人。

提前致谢

编辑:根据要求,控制台创建代码:

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();
}

1 个答案:

答案 0 :(得分:1)

我使用基本的Win32项目创建了一个测试Win32应用程序。我添加了一个简单的类来处理控制台创建并测试了两个场景。我发现控制台窗口输出将停止,就好像生成输出的线程在完成编辑 - >标记时暂停,直到标记完成复制或取消。

使用Win32应用程序测试的两个场景是:(1)在单独的线程中打印到控制台窗口,以及(2)在主窗口消息处理逻辑中打印到控制台窗口。

测试程序的细节和测试的两个场景的细节如下。

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;
}

在Win32项目向导放置一些全局变量的顶部附近的主文件中,我为我的控制台添加了一个额外的全局变量CConsole myConsole;,然后我进一步向下添加了一个简单的函数,即_beginthreadex()的目标。该函数如下所示:

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;
}

InitInstance(HINSTANCE hInstance, int nCmdShow)语句之前的return中,我添加了以下两行代码:

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

最后,在处理主窗口消息的主消息循环中,我添加了一个额外的消息目标:

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

然后我通过在我的函数中注释掉_beginthreadex()的目标中的两行之一来尝试两个不同的实验。

一个是在该线程中使用fprintf()打印到控制台窗口。第二个测试用例是向主窗口发送WM_USER消息,并要求它使用fprintf()打印到控制台窗口。

我发现,当线程完成打印时,当我使用Edit-&gt; Mark开始标记要复制的文本的过程时,我发现了以下行为:

  • 主窗口响应菜单选项

  • 控制台窗口输出已停止

  • 当我清除标记或复制文本时,控制台窗口输出恢复

行为就好像写入控制台窗口的线程暂停,直到Mark和Copy程序完成。

当处理WM_USER消息时,主窗口的消息循环完成打印时,当我使用Edit-&gt;标记开始将文本标记到的过程时,我观察到以下行为副本:

  • 主窗口对菜单选项没有反应

  • 控制台窗口输出已停止

  • 当我清除标记或复制文本时,主窗口响应性和控制台输出一样返回

有关控制台窗口子系统的一些其他信息,请参阅Consoles。有关该技术的一些信息,请参阅WinEventProc Callback Function以及SetWinEventHook,它在某种程度上描述了此功能以及What Are WinEvents?In-Context Hook Function Precautions

有关控制台窗口子系统的简要概述,另请参阅Windows Internals一书中的Console Window Host

有关架构更改的介绍,请参阅Windows 7 / Windows Server 2008 R2: Console Host

最后,来自Windows调试内容的The Console Host Process in Windows 7显示了如何发现printf序列中涉及的各个层&#34;。

可以使用较低级别的控制台功能直接与控制台窗口子系统连接,以防止正在对控制台窗口执行I / O的线程冻结。