Winapi 在win32应用程序中嵌入cmd,文本不可选
我编写gui和控制台程序。对于控制台,我使用颜色输出,如\33[0m。对于gui,我需要编写更多代码,如果我切换到另一个gui库,我需要重写代码。一些简单库(我当前使用的)甚至没有api自定义文本颜色。因此,我尝试使用cmd作为所有应用程序的输出 问题是我无法在控制台中选择文本,即使我将控制台设置为默认的快速编辑模式 代码:(如果cmd没有出现,请调整主窗口的大小,然后它应该出现)Winapi 在win32应用程序中嵌入cmd,文本不可选,winapi,win32gui,windows-console,Winapi,Win32gui,Windows Console,我编写gui和控制台程序。对于控制台,我使用颜色输出,如\33[0m。对于gui,我需要编写更多代码,如果我切换到另一个gui库,我需要重写代码。一些简单库(我当前使用的)甚至没有api自定义文本颜色。因此,我尝试使用cmd作为所有应用程序的输出 问题是我无法在控制台中选择文本,即使我将控制台设置为默认的快速编辑模式 代码:(如果cmd没有出现,请调整主窗口的大小,然后它应该出现) #包括 #包括 LRESULT回调WndProc(HWND、UINT、WPARAM、LPARAM); int WI
#包括
#包括
LRESULT回调WndProc(HWND、UINT、WPARAM、LPARAM);
int WINAPI WinMain(HINSTANCE HINSTANCE,
HINSTANCE HPPrevenstance,
LPSTR lpCmdLine,
int nShowCmd)
{
静态TCHAR lpszAppName[]=文本(“HelloWin”);
HWND-HWND;
味精;
WNDCLASS wc;
wc.style=CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc=WndProc;
wc.cbClsExtra=0;
wc.cbWndExtra=0;
wc.hInstance=hInstance;
wc.hIcon=LoadIcon(空,IDI_应用程序);
wc.hCursor=LoadCursor(空,IDC_箭头);
wc.hbrBackground=(HBRUSH)GetStockObject(白色画笔);
wc.lpszMenuName=NULL;
wc.lpszClassName=lpszAppName;
如果(!注册表类(&wc))
{
MessageBox(空,文本(“此程序需要Windows NT!”),
lpszAppName,MB_i错误);
返回0;
}
hwnd=CreateWindow(lpszAppName,
文本(“Hello程序”),
WS_重叠窗口,
CW_使用默认值,
CW_使用默认值,
CW_使用默认值,
CW_使用默认值,
无效的
无效的
hInstance,
无效);
显示窗口(hwnd、nShowCmd);
更新窗口(hwnd);
while(GetMessage(&msg,NULL,0,0))
{
翻译信息(&msg);
发送消息(&msg);
}
返回msg.wParam;
}
LRESULT回调WndProc(HWND HWND,UINT消息,WPARAM WPARAM,LPARAM LPARAM)
{
开关(信息)
{
案例WM_创建:
{
使用名称空间std;
allocsole();
freopen(“CONOUT$,“w”,stdout);//将std::cout重定向到控制台
cout通过添加对INVALIDATE(console,NULL,TRUE);
和重画窗口(console,NULL,NULL,RDW\u INVALIDATE)的调用,可以部分解决此问题
。尝试在WM\u CREATE
、WM\u MOVE
和WM\u SIZE
内部调用这两个函数。但只在WM\u PAINT
内部调用重画窗口,因为程序似乎会冻结
在WM_PAINT
和其他消息之后调用DefWindowProc()
。只有在确保不需要标准windows处理时,才应返回0
,除非响应自定义消息,否则这种情况很少发生
最后,控制台窗口是一个独立的进程。将一个进程的窗口嵌入另一个进程本身是不可靠的。例如,控制台通常有一个标准的窗口框架,因此文本区域不会绘制在客户端矩形的[0,0]处。它绘制到该窗口的右下角。如果没有窗口框架,文本区域现在绘制在[0,0]但是它的大小是相同的,周围的客户端rect也是一样。它在文本区域的右侧和底部留下空白的未上漆的空间。在窗口上设置WS_HSCROLL
和WS_VSCROLL
,以立即显示滚动条,显示文本区域和滚动条之间的空白
一般来说,将一个进程窗口嵌入到另一个进程中是不平凡的。快速搜索揭示了一些相关的主题。如果你想将STDUT重定向到子文本窗口,而不使用控制台,那么另一个相关的主题是:如果你只想打印调试消息,考虑使用<代码> OutPuxDebug字符串< /代码。>打印到Visual Studio输出窗口。指出,如果将此功能用于另一个进程,则必须同步两个窗口的UISTATE:
更改窗口的父级时,应同步
两个窗口的UISTATE。有关更多信息,请参阅WM\u CHANGEUISTATE
和WM_UPDATEUISTATE
但您无法访问控制台的消息循环。有两个消息循环,Windows必须阻止某些消息。您马上就会看到焦点和绘制问题。当您单击控制台窗口时,它无法获得焦点,或者无法绘制。使用WS\u CLIPCHILDREN
将改进绘制。要重定向焦点,您必须从您自己的窗口调用SetForeground(console)
和SetFocus(console)
(这必须在WM\u CREATE
返回后完成,您可以在WM\u LBUTTONDOWN
中处理,例如,或使用PostMessage
)但是你会遇到更多的问题。即使你有权访问另一个进程,这也不容易。同步线程已经够难了,同步进程会更糟
另请参见:跨流程父/子窗口或所有者/所有者窗口关系是否合法?
您有更简单的选择。您可以稍微修改代码以写入std::ostringstream
,并将流粘贴到编辑控件,或将cout
重定向到编辑控件
下面的示例使用RichEdit控件支持颜色和字体样式,松散地基于Bash编码:
#包括
#包括
#包括
#包括
#包括
给我的学生上课
{
HWND-hedit;
公众:
std::wostringstream-oss;
HWND创建(HWND HWND,int x,int y,int w,int h,HINSTANCE hinst,int menu_id)
{
//创建丰富的编辑控件
加载库(L“Msftedit.dll”);
hedit=CreateWindow(MSFTEDIT_类,0,
ES|U只读| ES|U多行| WS|U子级| WS|U可见,x,y,w,h,
hwnd,HMENU(菜单id),空,
#include <windows.h>
#include <iostream>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
static TCHAR lpszAppName[] = TEXT("HelloWin");
HWND hwnd;
MSG msg;
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = lpszAppName;
if (!RegisterClass(&wc))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"),
lpszAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(lpszAppName,
TEXT("The Hello Program"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, nShowCmd);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
using namespace std;
AllocConsole();
freopen("CONOUT$", "w", stdout); // redirect std::cout to console
cout << "test console" << endl;
// get console handle
HWND console = GetConsoleWindow();
SetParent(console, hwnd);
SetWindowLong(console, GWL_STYLE, WS_CHILD | WS_VISIBLE);
// ShowWindow(console, SW_MAXIMIZE);
DWORD prev_mode;
GetConsoleMode(console, &prev_mode);
SetConsoleMode(console, prev_mode | ENABLE_QUICK_EDIT_MODE);
cout << "aaaaaaaaaa" << endl;
cout << "aaaaaaaaaa" << endl;
cout << "aaaaaaaaaa" << endl;
cout << "aaaaaaaaaa" << endl;
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}