错误 C2440,“static_cast”: 无法从UNIT转为UINT_PTR的解决(【转】)

从Win32到Win64的OnTimer函数问题:

OnTimer函数相关的错误是将应用程序从Win32系统移植到Win64系统时遇到的最常见的错误。函数OnTimer几乎在每个应用程序中使用,您可能会遇到一些编译错误。早期(在Visual Studio 6中)此函数具有原型“OnTimer(UINT nIDEvent)”,并且最有可能以相同的形式出现在用户类中。现在这个函数有原型“OnTimer(UINT_PTR nIDEvent)”,它会导致64位系统的编译错误。

例子:

class CPortScanDlg : public CDialog
{
  ...
  afx_msg void OnTimer(UINT nIDEvent);
  ...
};
BEGIN_MESSAGE_MAP(CPortScanDlg, CDialog)
...
  ON_WM_TIMER()
END_MESSAGE_MAP()

对于此代码,在编译阶段将公布以下错误:

1>.\Src\Portscandlg.cpp(136) : error C2440: 'static_cast' :
cannot convert from 'void (__cdecl CPortScanDlg::* )(UINT)' to
'void (__cdecl CWnd::* )(UINT_PTR)'
1> Cast from base to derived requires dynamic_cast or static_cast

错误关键是函数类型在宏ON_WM_TIMER中显式转换:UINT和UINT_PTR:

#define ON_WM_TIMER() \
{ WM_TIMER, 0, 0, 0, AfxSig_vw, \
  (AFX_PMSG)(AFX_PMSGW) \
  (static_cast< void (AFX_MSG_CALL CWnd::*)(UINT_PTR) > \
    ( &ThisClass :: OnTimer)) },

解释:构建32位版本时转换能成功,是因为UINT和UINT_PTR类型重合。但是在64位模式下,这些是不同的类型,并且函数类型转换是不可能的,并且导致编译错误。

错误修复

此错误很容易修复。您应该在用户类中更改函数OnTimer的定义。以下是更正后代码的示例:

class CPortScanDlg : public CDialog
{
  ...
  afx_msg void OnTimer(UINT_PTR nIDEvent); //Fixed
  ...
};

有时OnTimer函数不止一次在程序中使用。

我们建议您在编译之前搜索“OnTimer(UINT”行),并将其替换为“OnTimer(UINT_PTR”。您也可以使用“查找和替换”功能。如下图:
错误	C2440,“static_cast”: 无法从UNIT转为UINT_PTR的解决(【转】)
注意:不要忘记,线的末端必须有一个空格。如果没有空格,您将获得“OnTimer(UINT_UINT_PTR nIDEvent)

参考资料

https://www.viva64.com/en/k/0011/