为什么我不能将静态转换的 Lambda 转换为 settimer 中的 TIMEPROC 函数指针?

Wy can't I cast a statically cast Lambda as a TIMEPROC Function pointer in a settimer?

我对此进行了多次编码。 但它似乎甚至不能在简单的控制台 hello word 应用程序中工作。 hWND 是罪魁祸首,lambda,还是 lambda 的转换?

void sleeper()
{
    Sleep(10000);
}
int main()
{
    SetTimer
    (GetConsoleWindow(), 1, 1000, [](HWND, UINT, UINT_PTR, DWORD)
        {
        printf("Hello World!");
        }
    );
    sleeper();
    return 0;
}

它没有给我警告。

您不能将 lamba 转换为 TIMEPROC* 或使用不同于默认调用约定的任何其他类型的函数指针(不能指定 lambda 的调用约定)。 Lambda 是可调用对象。这个类型类似于class,有一个成员函数

除此之外,您必须为您的 TIMERPROC 挂钩使用正确的声明。它是:

// definition from the MS website.  It is incomplete (typical from MS)
// ref: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nc-winuser-timerproc
void Timerproc(
  HWND unnamedParam1,
  UINT unnamedParam2,
  UINT_PTR unnamedParam3,
  DWORD unnamedParam4
)

// the actual definition from winuser.h.
typedef VOID (CALLBACK* TIMERPROC)(HWND, UINT, UINT_PTR, DWORD):

// note the use of CALLBACK, which expands to __stdcall.  That's the very important 
// detail missing from the actual documentation.

您可以将您的 timeproc 声明为独立函数,或作为 class 的 static 成员函数,不幸的是,您可以将 onluy 参数传递给callback 是一个 HWND,这意味着如果你想将任何额外的参数传递给你的回调,你必须使用静态(又名全局)变量。

示例 1.

void CALLBACK myTimerProc(HWND, UINT, UINT_PTR, DWORD)
{
   printf("Hello World!");
}

int main()
{
    // NOTE nIDEvent, the timer ID has to be unique for the window and NON-ZERO,
    // See MS documentation here: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-settimer
    SetTimer(GetConsoleWindow(), 1, 1000, myTimerProc);
    sleeper();
    return 0;
}

例子2,如果要在本地定义:

int main()
{
    struct local // or any other 
    {
        static void CALLBACK timerProc(HWND, UINT, UINT_PTR, DWORD)
        {
            printf("Hello World!");
        }
    }

    SetTimer(GetConsoleWindow(), 1, 1000, local::timerProc);
    sleeper();
    return 0;
}

编辑:供参考,TIMERPROC 回调的实际参数。

来源:http://www.icodeguru.com/VC%26MFC/MFCReference/html/_mfc_cwnd.3a3a.settimer.htm

void CALLBACK EXPORT TimerProc(
   HWND hWnd,      // handle of CWnd that called SetTimer
   UINT nMsg,      // WM_TIMER
   UINT nIDEvent   // timer identification
   DWORD dwTime    // system time
);