Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Winapi 在win32应用程序中嵌入cmd,文本不可选_Winapi_Win32gui_Windows Console - Fatal编程技术网

Winapi 在win32应用程序中嵌入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

我编写gui和控制台程序。对于控制台,我使用颜色输出,如\33[0m。对于gui,我需要编写更多代码,如果我切换到另一个gui库,我需要重写代码。一些简单库(我当前使用的)甚至没有api自定义文本颜色。因此,我尝试使用cmd作为所有应用程序的输出

问题是我无法在控制台中选择文本,即使我将控制台设置为默认的快速编辑模式

代码:(如果cmd没有出现,请调整主窗口的大小,然后它应该出现)

#包括
#包括
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);
}