C++ 在新线程中从控制台新建 Window (Win32)
C++ Create New Window From Console in New Thread (Win32)
工作环境:
我在 VS 2015 和 win32 控制台中工作。
概览:
我正在创建一个新的 window 作为工作线程来执行一些无法在控制台中完成的功能。
创建新 window 和完成任务的代码运行良好。但是它冻结了控制台。
我有代码从控制台创建线程并在控制台未冻结时完成任务。这也很好用。
问题:
我无法加入这两段代码,我想 运行 线程中的新 window 这样它就不会阻塞控制台。
代码:
=============== int main ================== ====
开始线程
x = 0;
hPrintMutex = CreateMutex(NULL, false, NULL);
HANDLE hThread1 = (HANDLE)_beginthread(printNumber, 0, &x);
WaitForSingleObject(hThread1, INFINITE);
新建window
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
0, myclass, LoadIcon(0,IDI_APPLICATION) };
if (RegisterClassEx(&wndclass))
{
HWND window = CreateWindowEx(0, myclass, "title",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
if (window)
{
ShowWindow(window, SW_SHOWDEFAULT);
MSG msg;
while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
}
}
======== 在主线之外 ========================= ==============
在新线程中执行某些操作的代码
( * 实际内容仅为示例,将被删除并替换为 window 代码 * )
void printNumber(void* pInt)
{
int* xp = (int*)pInt;
while (*xp<100)
{
WaitForSingleObject(hPrintMutex, INFINITE);
++*xp;
cout << *xp << endl;
ReleaseMutex(hPrintMutex);
Sleep(10);
}
}
用于创建新 window 并执行某些操作的代码
long __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case something: {
}
default:
return DefWindowProc(window, msg, wp, lp);
}
}
有什么想法吗?谢谢。
***** 解决方案 *****
请参阅下面我发布的解决方案,该解决方案经过测试并且可以正常工作。
得到这个工作,我想我会 post 帮助其他同样刚起步并遇到困难的人
在你的主线程中启动
HANDLE myhandle;
myhandle = (HANDLE)_beginthreadex(0, 0, &mythread, 0, 0, 0);
如果您的控制台在循环中运行,那么您不需要调用 WaitForSingleObject,否则您将需要调用它,这样控制台就不会关闭。
外主
创建线程,并在线程内创建您的 window
unsigned int __stdcall mythread(void* data)
{
cout << "/n created monitor window /n";
const char* const myclass = "myclass";
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
0, myclass, LoadIcon(0,IDI_APPLICATION) };
if (RegisterClassEx(&wndclass))
{
HWND window = CreateWindowEx(0, myclass, "title",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
if (window)
{
ShowWindow(window, SW_SHOWDEFAULT);
MSG msg;
while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
}
}
return 0;
}
还外主,新window
long __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case checksomethinghere: {
}
default: // fall thru
return DefWindowProc(window, msg, wp, lp);
}
}
现在您可以让您的监视器 window 与您的控制台一起工作,而不会阻塞控制台 activity。
已经过测试,运行良好。
根据我的阅读,您不必担心为创建的线程调用 CloseHandle,因为当控制台关闭时它会终止线程和您创建的 window。
在我的场景中,window 和线程在控制台应用 运行 的整个时间内保持活动状态。
是否可以向 UI 线程发送消息?
完整示例 + PostMessage 到 UI 线程 ?
#include <Windows.h>
#include <process.h>
UINT test_message = 0;
long __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
if (test_message == msg) {
printf("Got it !\n"); // to console
return 0;
}
else
return DefWindowProc(window, msg, wp, lp);
}
static HWND window = NULL;
void SendMeMessage(HWND _window)
{
window = _window;
test_message = RegisterWindowMessage("TEST");
PostMessage(window, test_message, 0, 0);
}
unsigned int __stdcall mythread(void* data)
{
const LPCSTR myclass = "myclass";
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
0, myclass, LoadIcon(0,IDI_APPLICATION) };
if (RegisterClassEx(&wndclass))
{
window = CreateWindowEx(0, myclass, "title",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
if (window)
{
SendMeMessage(window);
ShowWindow(window, SW_SHOWDEFAULT);
MSG msg;
while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
}
}
return 0;
}
int main()
{
HANDLE myhandle;
myhandle = (HANDLE)_beginthreadex(0, 0, &mythread, 0, 0, 0);
// ...
工作环境:
我在 VS 2015 和 win32 控制台中工作。
概览:
我正在创建一个新的 window 作为工作线程来执行一些无法在控制台中完成的功能。
创建新 window 和完成任务的代码运行良好。但是它冻结了控制台。
我有代码从控制台创建线程并在控制台未冻结时完成任务。这也很好用。
问题:
我无法加入这两段代码,我想 运行 线程中的新 window 这样它就不会阻塞控制台。
代码:
=============== int main ================== ====
开始线程
x = 0;
hPrintMutex = CreateMutex(NULL, false, NULL);
HANDLE hThread1 = (HANDLE)_beginthread(printNumber, 0, &x);
WaitForSingleObject(hThread1, INFINITE);
新建window
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
0, myclass, LoadIcon(0,IDI_APPLICATION) };
if (RegisterClassEx(&wndclass))
{
HWND window = CreateWindowEx(0, myclass, "title",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
if (window)
{
ShowWindow(window, SW_SHOWDEFAULT);
MSG msg;
while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
}
}
======== 在主线之外 ========================= ==============
在新线程中执行某些操作的代码
( * 实际内容仅为示例,将被删除并替换为 window 代码 * )
void printNumber(void* pInt)
{
int* xp = (int*)pInt;
while (*xp<100)
{
WaitForSingleObject(hPrintMutex, INFINITE);
++*xp;
cout << *xp << endl;
ReleaseMutex(hPrintMutex);
Sleep(10);
}
}
用于创建新 window 并执行某些操作的代码
long __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case something: {
}
default:
return DefWindowProc(window, msg, wp, lp);
}
}
有什么想法吗?谢谢。
***** 解决方案 *****
请参阅下面我发布的解决方案,该解决方案经过测试并且可以正常工作。
得到这个工作,我想我会 post 帮助其他同样刚起步并遇到困难的人
在你的主线程中启动
HANDLE myhandle;
myhandle = (HANDLE)_beginthreadex(0, 0, &mythread, 0, 0, 0);
如果您的控制台在循环中运行,那么您不需要调用 WaitForSingleObject,否则您将需要调用它,这样控制台就不会关闭。
外主
创建线程,并在线程内创建您的 window
unsigned int __stdcall mythread(void* data)
{
cout << "/n created monitor window /n";
const char* const myclass = "myclass";
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
0, myclass, LoadIcon(0,IDI_APPLICATION) };
if (RegisterClassEx(&wndclass))
{
HWND window = CreateWindowEx(0, myclass, "title",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
if (window)
{
ShowWindow(window, SW_SHOWDEFAULT);
MSG msg;
while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
}
}
return 0;
}
还外主,新window
long __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case checksomethinghere: {
}
default: // fall thru
return DefWindowProc(window, msg, wp, lp);
}
}
现在您可以让您的监视器 window 与您的控制台一起工作,而不会阻塞控制台 activity。
已经过测试,运行良好。
根据我的阅读,您不必担心为创建的线程调用 CloseHandle,因为当控制台关闭时它会终止线程和您创建的 window。
在我的场景中,window 和线程在控制台应用 运行 的整个时间内保持活动状态。
是否可以向 UI 线程发送消息?
完整示例 + PostMessage 到 UI 线程 ?
#include <Windows.h>
#include <process.h>
UINT test_message = 0;
long __stdcall WindowProcedure(HWND window, unsigned int msg, WPARAM wp, LPARAM lp)
{
if (test_message == msg) {
printf("Got it !\n"); // to console
return 0;
}
else
return DefWindowProc(window, msg, wp, lp);
}
static HWND window = NULL;
void SendMeMessage(HWND _window)
{
window = _window;
test_message = RegisterWindowMessage("TEST");
PostMessage(window, test_message, 0, 0);
}
unsigned int __stdcall mythread(void* data)
{
const LPCSTR myclass = "myclass";
WNDCLASSEX wndclass = { sizeof(WNDCLASSEX), CS_DBLCLKS, WindowProcedure,
0, 0, GetModuleHandle(0), LoadIcon(0,IDI_APPLICATION),
LoadCursor(0,IDC_ARROW), HBRUSH(COLOR_WINDOW + 1),
0, myclass, LoadIcon(0,IDI_APPLICATION) };
if (RegisterClassEx(&wndclass))
{
window = CreateWindowEx(0, myclass, "title",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, GetModuleHandle(0), 0);
if (window)
{
SendMeMessage(window);
ShowWindow(window, SW_SHOWDEFAULT);
MSG msg;
while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg);
}
}
return 0;
}
int main()
{
HANDLE myhandle;
myhandle = (HANDLE)_beginthreadex(0, 0, &mythread, 0, 0, 0);
// ...