gpt4 book ai didi

winapi - 在 win32 应用程序中嵌入 cmd 并且文本不可选择

转载 作者:行者123 更新时间:2023-12-03 18:19:32 25 4
gpt4 key购买 nike

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

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

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

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

如何让它可选?是否还有其他替代控制台应用程序可用于嵌入我的应用程序中?(我尝试过 ConEmu 但没有成功)

最佳答案

SetParent documentation声明如果你在另一个进程中使用这个函数,你必须同步两个 Windows 的 UISTATE:

When you change the parent of a window, you should synchronize the UISTATE of both windows. For more information, see WM_CHANGEUISTATE and WM_UPDATEUISTATE.



但是您无权访问控制台的消息循环。有两个消息循环,Windows 必须阻止一些消息。你马上就会看到对焦和绘画的问题。单击它时控制台窗口不会获得焦点,或者它不会被绘制。使用 WS_CLIPCHILDREN将改善绘画。要重定向焦点,您必须调用 SetForeground(console)SetFocus(console)从您自己的窗口(这必须在 WM_CREATE 返回后完成,例如您可以在 WM_LBUTTONDOWN 中处理此问题,或者使用 PostMessage ),但随后您会遇到更多问题。即使您确实可以访问其他进程,也并不容易。同步线程已经够难了,同步进程会更糟。

另请参阅:拥有跨进程的父/子或所有者/拥有的窗口关系是否合法?
https://blogs.msdn.microsoft.com/oldnewthing/20130412-00/?p=4683

你有更简单的选择。您可以稍微修改您的代码以写入 std::ostringstream并将流粘贴到编辑控件中,或重定向 cout到编辑控件。

下面的示例使用 RichEdit 控件来支持颜色和字体样式,松散地基于 Bash 编码:
#include <sstream>
#include <string>
#include <iomanip>
#include <Windows.h>
#include <Richedit.h>

class my_stream
{
HWND hedit;
public:
std::wostringstream oss;

HWND create(HWND hwnd, int x, int y, int w, int h, HINSTANCE hinst, int menu_id)
{
//create rich edit control
LoadLibrary(L"Msftedit.dll");
hedit = CreateWindow(MSFTEDIT_CLASS, 0,
ES_READONLY | ES_MULTILINE | WS_CHILD | WS_VISIBLE, x, y, w, h,
hwnd, HMENU(menu_id), NULL, NULL);

//default background color
SendMessage(hedit, EM_SETBKGNDCOLOR, 0, (LPARAM)RGB(0, 0, 0));

//default text color
CHARFORMAT cf = { sizeof(cf) };
cf.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE;
cf.yHeight = 220;
cf.crTextColor = RGB(255, 255, 255);
//Consolas font is available since Vista
wcscpy_s(cf.szFaceName, _countof(cf.szFaceName), L"Consolas");
SendMessage(hedit, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
SendMessage(hedit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
return hedit;
}

template<typename T>
my_stream& operator<<(const T& rhs)
{
//write to stream
oss.str(L"");
oss << rhs;
std::wstring s = oss.str();

if(s.find(L"\033[") == 0)
{
bool bold = false;
if(s.find(L"\033[1") == 0)
{
bold = true;
s[2] = L'0';
}

COLORREF color = RGB(255, 255, 255);
if(s == L"\033[0m") color = RGB(255, 255, 255);
if(s == L"\033[0;30m") color = RGB(0, 0, 0);//black
if(s == L"\033[0;31m") color = RGB(255, 0, 0);//red
if(s == L"\033[0;32m") color = RGB(0, 255, 0);//green
if(s == L"\033[0;33m") color = RGB(128, 64, 0);//brown
if(s == L"\033[0;34m") color = RGB(0, 128, 255);//blue
if(s == L"\033[0;35m") color = RGB(255, 0, 255);//magenta
if(s == L"\033[0;36m") color = RGB(0, 255, 255);//cyan
if(s == L"\033[0;37m") color = RGB(192, 192, 192);//light gray

CHARFORMAT cf = { sizeof(cf) };
cf.dwMask = CFM_BOLD | CFM_COLOR;
cf.dwEffects = bold ? CFE_BOLD : 0;
cf.crTextColor = color;
SendMessage(hedit, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
SendMessage(hedit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
}
else
{
append_to_richedit(s.c_str());
}

return *this;
}

//this is for std::endl
my_stream& operator<<(std::wostream& (*func)(std::wostream&))
{
oss.str(L"");
oss << func;
append_to_richedit(oss.str().c_str());
return *this;
}

void append_to_richedit(const wchar_t *text)
{
if(text && wcslen(text))
{
SendMessage(hedit, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
SendMessage(hedit, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)text);
}
}
};

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
static my_stream cout;
switch(msg)
{
case WM_CREATE:
{
RECT rc;
GetClientRect(hwnd, &rc);
InflateRect(&rc, -10, -10);
cout.create(hwnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
((LPCREATESTRUCT)lparam)->hInstance, 0);

cout << "\033[0;31m" << "red\n";
cout << "\033[1;31m" << "bold red\n";
cout << "\033[0m" << "reset\n";
cout << "\033[0;32m" << "green\n";
cout << "\033[0;34m" << std::showbase << std::hex << 17 << std::endl;
cout << "\033[1m";
cout << L"bold, unicode ☺ ελληνική\n";
cout << L"Win10 symbols 🙂\n";
cout.oss.precision(3);
cout << "numbers " << std::setw(10) << 3.1415 << std::endl;
break;
}

case WM_DESTROY:
PostQuitMessage(0);
return 0;
}

return DefWindowProc(hwnd, msg, wparam, lparam);
}

int WINAPI wWinMain(HINSTANCE hinst, HINSTANCE, LPTSTR, int)
{
WNDCLASSEX wcex = { sizeof(WNDCLASSEX) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hinst;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wcex.lpszClassName = L"Test";
RegisterClassEx(&wcex);

CreateWindow(wcex.lpszClassName, L"Test", WS_VISIBLE | WS_OVERLAPPEDWINDOW,
100, 100, 600, 400, 0, 0, hinst, 0);

MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return (int)msg.wParam;
}

enter image description here

这是一个只读的富编辑控件,它应该支持鼠标选择和 Ctrl+C 复制。您可以继承 Richedit 控件以添加菜单功能。

关于winapi - 在 win32 应用程序中嵌入 cmd 并且文本不可选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50043663/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com