﻿# Распространенная ошибка при компиляции 64\-битного приложения: error C2440, OnTimer

Одной из самых распространенных ошибок, с которыми сталкивается программист при переносе приложений с Win32 на Win64 систему, является ошибка, связанная с использованием функции OnTimer\. Функции OnTimer используется практически в каждом приложении и высока вероятность, что вы получите несколько ошибок компиляции\. Ранее \(в Visual Studio 6\) эта функция имела прототип "OnTimer\(UINT nIDEvent\)" и скорее всего так же представлена в пользовательских классах\. Сейчас эта функция имеет прототип "OnTimer\(UINT\_PTR nIDEvent\)", что приводит к ошибке компиляции для 64\-битной системы\.

Рассмотрим стандартный пример:

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

Для данного кода на этапе компиляции будет выдана следующая ошибка:

```cpp
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 происходит явное приведение типа функции:

```cpp
#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](https://pvs-studio.ru/ru/blog/terms/0051/) совпадают\. В 64\-битном режиме это различные типы и приведение типа функции невозможно, отчего и возникает на первый взгляд не очень понятная ошибка компиляции\.

Исправить данную ошибку достаточно просто\. Необходимо изменить объявление функции OnTimer в пользовательских классах\. Пример исправленного кода:

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

Иногда в программах функция OnTimer используется неоднократно\.

Можно порекомендовать сразу поискать строчку "OnTimer\(UINT " и заменить ее на "OnTimer\(UINT\_PTR "\. Также можно воспользоваться множественной заменой, как показано на рисунке 1\.

![k0011_error_C2440_OnTimer_ru/image1.png](https://import.viva64.com/docx/blog/k0011_error_C2440_OnTimer_ru/image1.png)

_Рисунок 1 \- Использование функции "Find and Replace" для исправления объявления функций OnTimer_

Не забудьте только, что в обоих случаях в конце строк должен стоять пробел\. Этот пробел, к сожалению, не виден на рисунке\. Если пробелов не будет, то у вас может получиться "OnTimer\(UINT\_UINT\_PTR nIDEvent\)"\.