如何从未创建该窗口的线程更新该窗口

How to update a Window from a thread that did not create that Window?

本文关键字:窗口 线程 更新 创建      更新时间:2023-10-16

我想创建一个能够在主线程(创建 GUI)运行一些长计算时更新 GUI 元素的线程,我不知道该怎么做。我正在使用MSVC++中的win32 API。

由于这些计算很长且占用大量 RAM,因此我想避免弄乱它们并将它们放在线程中。这意味着我希望能够直接从线程处理此 GUI 更新,而无需主窗口处理任何 WndProc 消息。

在最简单的情况下,我只想能够从线程内部更新单个静态控件,但最终我希望能够在主窗口上绘制或在数据从外部设备滚入时更新其中的位图图像。我并不是说线程会完全接管窗口过程。

我尝试过非常简单的方法,例如:

// Global
HWND display;
DWORD WINAPI myThread(LPVOID threadParameter);
int APIENTRY WinMain(_In_ HINSTANCE hInstance,
                 _In_opt_ HINSTANCE hPrevInstance,
                 _In_ LPWSTR    lpCmdLine,
                 _In_ int       nCmdShow){
    // Blah Blah Create main Window and display object, which is a "STATIC" Blah Blah
    HANDLE myThreadHandle = CreateThread(0, 0, myThread, (LPVOID)display, 0, &myThreadID);
    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT7));
    MSG msg;
    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    CloseHandle(myThreadHandle);
    return (int) msg.wParam;
}
// other function outside WinMain(){
DWORD WINAPI myThread(LPVOID threadParameter) {
    // I've passed in my static handle here.
    HWND hwnd = (HWND)threadParameter;
    // My hope was that this would update the text of the static window, but...
    PostMessage(hwnd, WM_SETTEXT, 0, (LPARAM)"10");
    // After this message the static window still hasn't updated with the text "10".
    return 0;
};

但这不起作用(静态控件只是不更新),这只是一个猜测,所以我可能正在做一些愚蠢的事情。我找不到任何关于在C++中执行此操作的正确过程的资源,但我正在寻找与此 MSDN 资源(在 C# 中)类似的内容。

如果这有用,我当然可以上传我尝试的整个代码,但我认为我可能走错了路,所以我只是包含了这个片段。

不能让 UI 线程执行工作,并从工作线程更新 UI。系统根本不以这种方式工作。主线程需要保持响应并及时处理其消息队列。与窗口的交互需要从 UI 线程执行。

您只需反转工作分配即可。让 UI 线程在 UI 上工作,并让工作线程执行密集型工作。

您似乎担心密集的工作会花费时间并使用内存,并且线程不适合该任务。但事实并非如此。线程可用于执行长时间运行的计算。线程能够使用内存。

似乎你已经为任何事情而感到头晕目眩。在 UI 线程上处理 UI,并在工作线程上执行工作。仅此而已。

你需要

传递一个指向HWND display的指针。

CreateThread()使用

HANDLE myThreadHandle = CreateThread(0, 0, myThread, (LPVOID)&display, 0, &myThreadID);

在您的线程使用中:

HWND hwnd = (HWND)(*threadParameter);

我想创建一个能够更新 GUI 元素的线程 而主线程(创建 GUI)运行时间较长 计算

如注释中所述,工作应该在工作线程中完成,让主线程处理绘图、鼠标、键盘等。

就个人而言,我更喜欢为此使用用户消息,并将它们发布到父窗口(而不是直接发布WM_SETTEXT子窗口),并让父窗口处理其余部分。