C++ MFC关于静态强制转换的\u WM\u TIMER()问题

C++ MFC关于静态强制转换的\u WM\u TIMER()问题,c++,mfc,C++,Mfc,我的类CDATA BaseApplicationApp中的ON\U WM\U计时器存在问题,该类扩展了CWinApp > 1>c:\programs\databaseapplication\databaseapplication\databaseapplication.cpp(20): > error C2440: 'static_cast' : cannot convert from 'void (__thiscall > CDatabaseApplicationApp

我的类CDATA BaseApplicationApp中的ON\U WM\U计时器存在问题,该类扩展了CWinApp

> 1>c:\programs\databaseapplication\databaseapplication\databaseapplication.cpp(20):
> error C2440: 'static_cast' : cannot convert from 'void (__thiscall
> CDatabaseApplicationApp::* )(UINT_PTR)' to 'void (__thiscall CWnd::*
> )(UINT_PTR)' 1>          Types pointed to are unrelated; conversion
> requires reinterpret_cast, C-style cast or function-style cast
我已经包含了函数
OnTimer

class CLifescanDatabaseApplicationApp : public CWinApp
{
public:
    CLifescanDatabaseApplicationApp();
protected:
    CLifescanDatabaseApplicationDlg * m_ptheWindow;
// Overrides
public:
    virtual BOOL InitInstance();

// Implementation
    afx_msg void OnTimer(UINT_PTR nTimerID);
    DECLARE_MESSAGE_MAP()
};
OnTimer
只是:

void CDatabaseApplicationApp::OnTimer(UINT_PTR nTimerID)
{
    AfxMessageBox(_T("Help"));
}
使用源文件顶部的定义设置计时器:

#define ID_TIMER_DATABASEQUERY 1
SetTimer
是在中定义的

BOOL CDatabaseApplicationApp::InitInstance()
{
    // InitCommonControlsEx() is required on Windows XP if an application
    // manifest specifies use of ComCtl32.dll version 6 or later to enable
    // visual styles.  Otherwise, any window creation will fail.
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    // Set this to include all the common control classes you want to use
    // in your application.
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);

    CWinApp::InitInstance();


    AfxEnableControlContainer();
AfxInitRichEdit2();
    // Create the shell manager, in case the dialog contains
    // any shell tree view or shell list view controls.
    CShellManager *pShellManager = new CShellManager;

    // Standard initialization
    // If you are not using these features and wish to reduce the size
    // of your final executable, you should remove from the following
    // the specific initialization routines you do not need
    // Change the registry key under which our settings are stored
    // TODO: You should modify this string to be something appropriate
    // such as the name of your company or organization
    SetRegistryKey(_T("Local AppWizard-Generated Applications"));



    m_ptheWindow = new CDatabaseApplicationDlg();
    m_pMainWnd = m_ptheWindow;
    if(m_ptheWindow!=nullptr)
    {
        m_ptheWindow->Create(CDatabaseApplicationDlg::IDD,CWnd::GetDesktopWindow());
        m_ptheWindow->ShowWindow(SW_SHOW);
    }
    // Delete the shell manager created above.
    if (pShellManager != NULL)
    {
        delete pShellManager;
    }

    if(!m_ptheWindow->SetTimer(ID_TIMER_DATABASEQUERY,10000,nullptr))
    {
        return false;
    }
    // Since the dialog has been closed, return FALSE so that we exit the
    //  application, rather than start the application's message pump.
    return TRUE;
}

你知道我如何解决这个问题吗?

如果你在主窗口调用
SetTimer

if(!m_ptheWindow->SetTimer(ID_TIMER_DATABASEQUERY,10000,nullptr))
 {
     return false;
 } 

OnTimer
重写可能应该在window类(派生自
CWnd
)中,而不是在application类中。

CWnd::SetTimer
将指向函数的指针作为最后一个参数,该函数将被调用以处理WM\u计时器消息(回调函数)

如果此参数设置为NULL,将调用该窗口的
OnTimer
方法,这意味着您必须重写
CDatabaseApplicationDlg
类的
OnTimer
方法

如果不想这样做,则需要显式指定回调函数,即将被调用以处理消息的其他函数。这可以是全局函数或静态类成员。然而,非静态类成员将无法开箱即用,因为成员函数指针不是真正的指针,所以您需要将它们包装到其他内容中

如果您的
CDatabaseApplication
类将有一个静态成员,如:

void CDatabaseApplicationApp::OnTimer(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
   // in your case:
   // hWnd => HWND of your ID_TIMER_DATABASEQUERY instance
   // nMsg => WM_TIMER
   // nIDEvent => ID_TIMER_DATABASEQUERY, unless you also set other timers
   // dwTime => elapsed time, same as value of GetTickCount()
   AfxMessageBox(_T("Help"));
}
然后您可以按如下方式设置计时器:

m_ptheWindow->SetTimer(ID_TIMER_DATABASEQUERY, 10000, CDatabaseApplicationApp::OnTimer)

这是真的密码吗?在SetTimer中不使用
OnTimer
,也没有
static\u cast
是的,这是真正的代码。不确定你在SetTimer中所说的OnTimer是什么意思,Proise书中的例子和internet上的例子都有。编译器抱怨databaseapplication.cpp第20行中的
static\u cast
。这在您提交的代码中没有显示。由于您没有在
SetTimer
中指定回调,它将在调用
SetTimer
的类中调用
OnTimer
方法,该类是
CDatabaseApplicationDlg
,因此您需要在那里重写
OnTimer
。因此,对于没有窗口的类,我如何调用SetTimer呢。您必须解释回调,因为我以前没有使用过回调,对不起。我已经添加了答案。但是,我仍然不清楚
静态\u cast
是从哪里来的。该应用程序只是一个提供查询数据库选项的无模式对话框,但我不想在那里进行处理。我需要将mpthewindow->part放入,否则它需要一个带有四个参数的SetTimer,这是没有意义的。“四个参数版本”是Win32 API,在MFC之外。错误消息表示它需要一个
CWnd
成员函数,您可以从window类获得该函数。您可以让窗口的
onTimer
函数将消息传递给app类。MFC本身不想这样做,这不起作用;错误C2664:'CWnd::SetTimer':无法将参数3从'void(uu cdecl*)(UINT_PTR)'转换为'void(u stdcall*)(HWND,UINT,UINT_PTR,DWORD)'1>范围内具有此名称的函数中没有一个与目标类型匹配抱歉,我太快了:)SetTimer接受与Win API签名兼容的回调,而不是MFC签名。我已经更新了exampleOk,通过删除所有ON_WM_TIMER()并将静态函数更改为static void CALLBACK OnTimer(HWND HWND、UINT uMsg、UINT_PTR idEvent、DWORD dwTime)来解决;而SetTimer to if(!::SetTimer(NULL,ID\u TIMER\u DATABASEQUERY,10000,clifescandabaseapplicationapp::OnTimer))并没有给人留下深刻的印象,因为你必须走一条非常复杂的路线才能得到简单的工作。实际上,它非常简单-你只需要覆盖
CWnd的OnTimer
。您希望应用程序如何知道在所有不相关的类中调用哪个OnTimer方法?