SetParent
документация гласит, что если вы используете эту функцию с другим процессом, вы должны синхронизировать UISTATE для обеих Windows:
Когда вы меняете родителя окна, вы должны синхронизировать
UISTATE обоих окон. Для получения дополнительной информации см. WM_CHANGEUISTATE
и 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;
}
Это элемент управления редактирования только для чтения, он должен поддерживать выделение мышью и Ctrl + C для копирования. Вы можете создать подкласс richedit для добавления возможностей меню.