为什么我不能将静态转换的 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
);
我对此进行了多次编码。 但它似乎甚至不能在简单的控制台 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
);