对于我的应用程序,我一直在使用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();
}
答案 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的线程冻结。