【问题标题】:Win32 C++ using HWND in separate file/thread to start timerWin32 C++ 在单独的文件/线程中使用 HWND 来启动计时器
【发布时间】:2020-01-01 04:48:03
【问题描述】:

背景:

应用程序类型:Win32 应用程序

语言:C++(也有 C 函数)

问题:想在另一个文件中使用主窗口句柄。

更新 1:在另一个线程中使用 TCP 服务器。该服务器从客户端接收信息,然后需要在程序中启动一个计时器。

项目布局:

主文件:main.cpp/main.h,有WinMain、WndProc等

其他生成的文件:Visual Studio 生成的 Resource.h、main.rc、stdafx.h 等

自制文件:functions.cpp/functions.h &calculation.cpp/calculation.h

更新 1:服务器线程在 main.cpp 文件中,并且在服务器线程上调用启动计时器。我还更新了一些代码以更准确地反映我所拥有的。

信息:

我可以在calculation.cpp文件中以某种方式调用SetTimer(hwnd, TIMER_INT, TIMER_INTERVAL, NULL),并在WndProc中为WM_TIMER触发TIMER_INT定时器吗?

所以例如(当然foo是在calculation.h中定义的,等等其他函数)。

//calculation.cpp
void foo(HWND hwnd)
{
    SetTimer(hwnd, TIMER_INT, TIMER_INTERVAL, NULL);
}

//functions.cpp

void ThreadStart()
{
    /* This code initializes a working server that is visible to main.cpp */
    /* The Server socket and Accept socket are extern for main.cpp */
}

//main.cpp
HWND hwnd;
int WinMain(...)
{
    //... Set hwnd here
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, ...)
{
    static PARAMS params; //Thread params
    switch(message)
    {

    case WM_CREATE:
        //This initializes a blocking Server (which works)
        params.hwnd = hWnd;
        params.bContinue = TRUE;
        _beginthread(ThreadServer, 0, &params);
        break;

    case WM_TIMER:
        case TIMER_INT:
            MessageBox(NULL, L"Timer was triggered from foo", L"FOO", NULL);
            //continuous messageboxes will appear based on TIMER_INTERVAL if it works...
            break;
        break;

     }
}

void ThreadServer(PVOID pvoid)
{
    ThreadStart(); //calls accept() until client connects
    while(1)
    {
        memset(&RecvBuffer[0], 0, 512 * sizeof(RecvBuffer[0])); //Clear recv
        TCPServer.iRecv = recv(AcceptSocket, RecvBuffer, iRecvBuffer, 0);

        if(strlen(RecvBuffer) > 1){
            memset(&SendBuffer[0], 0, 512 * sizeof(SendBuffer[0]));
                //Clears SendBuffer
            std::string retString = "";
            retString = process(RecvBuffer); //processes RecvBuffer

                if(condition == true){
                    foo(hwnd);
                }

            if(strlen(retString.c_str()) > 0){
                TCPServer.iSend = send(AcceptSocket, retString.c_str(), strlen(retString.c_str()), 0);
            }else{
                retString = "";
                TCPServer.iSend = send(AcceptSocket, retString.c_str(), strlen(retString.c_str()), 0);
            }

            if(TCPServer.iSend == SOCKET_ERROR){
                break;
            }
        }
        //Determine if socket fails and breaks if failure occurs
        //*
        memset(&SendBuffer[0], 0, 512 * sizeof(SendBuffer[0]));
        TCPServer.iSend = send(AcceptSocket, SendBuffer, iSendBuffer, 0);
            if(TCPServer.iSend == SOCKET_ERROR){
             break;
        }//*/

        Sleep(1);

    }
}

问题是试图将 hwnd 的引用从服务器线程传递给计算.cpp。我可以将 hwnd 传递给函数 foo(HWND),但没有设置计时器。有没有办法在单独的线程中设置计时器,或者这是不可能的?使用 winsock 和服务器是否有其他解决方法?

【问题讨论】:

  • 您的代码应该按原样运行,并且是安全的。有什么问题?该代码中没有指针。为了改进,您可以将其更改为 case WM_TIMER: if(wParam == TIMER_INT){...} 以确保它是正确的计时器 ID。 MessageBox 通常使用 hWnd 作为所有者窗口。 WndProc 应该返回 DefWindowProc 默认情况...
  • 对不起,我之前的问题可能不够详细。我更新了原始问题的更详细部分。我验证它可以与单线程应用程序一起使用,但我无法让它与服务器线程一起使用。
  • 目前还不清楚。您正在创建与 GUI 线程分开的第二个线程。 foo 是从 GUI 线程调用的,与第二个线程无关。你应该解释你的程序试图做什么,以及你遇到了什么问题。提供有关 VB6 代码的详细信息似乎无关紧要。
  • 我知道我一定忘记将 foo 移动到线程中。我已经更新了它应该在的线程中的 foo 函数。基本上当 retString 有一定的条件时,它会调用 foo
  • SetTimer 的文档说 “这个窗口必须由调用线程拥有。”(我不确定为什么会这样)所以你应该调用 SetTimer在 GUI 线程 WM_CREATE 中。对于您的工作线程,您可以设置一个全局变量,例如 g_started = TRUE,然后根据该变量继续操作。

标签: winapi visual-c++ c++98


【解决方案1】:

作为document 状态,您不能为来自不同线程的窗口创建计时器。对你来说,不同的线程是服务器线程。

也许你可以在定时器超时时将WM_TIMER消息(PostMessage)从服务器线程发送到主线程。

或者您需要Synchronization Objects 来实现线程同步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-28
    相关资源
    最近更新 更多