zoukankan      html  css  js  c++  java
  • VC计时器的一个使用心得

                                                                                   朱金灿
     
    最近使用VC的计时器。计时器一般是先设置一个Timer,然后响应WM_TIMER消息,然后销毁计时器。但是我发现在哪里设置计时器和销毁计时器是有讲究的。
     
    开始我的代码是这样的:
    CMainFrame::CMainFrame()
    {
           // TODO: add member initialization code here
           SetTimer(1, 5000, 0);
    }
    // WM_TIMER消息响应函数
    void CMainFrame::OnTimer(UINT nIDEvent)
    {
           // TODO: Add your message handler code here and/or call default
           AfxMessageBox("Hello World!");
           CFrameWnd::OnTimer(nIDEvent);
    }
     
    CMainFrame::~CMainFrame()
    {
           KillTimer(1);
    }
     
    编译结果是,debug模式编译下出现Assertion Fauled,

    调试时发现出错是在BOOL CTestTimerApp::InitInstance()函数中的一句:
           if (!ProcessShellCommand(cmdInfo))
                  return FALSE;
    发生的。
     
    但是在release模式编译成功。想来是因为release模式忽略Assert宏的缘故,但是运行程序却没有Hello World!的对话框弹出。
     
         后来我想莫非是SetTimer(1, 5000, 0);函数放置的地方不对的缘故。后来我把它
    框架类的OnCreate函数。
    int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
    {
           if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
                  return -1;
          
           if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
                  | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
                  !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
           {
                  TRACE0("Failed to create toolbar/n");
                  return -1;      // fail to create
           }
     
           if (!m_wndStatusBar.Create(this) ||
                  !m_wndStatusBar.SetIndicators(indicators,
                   sizeof(indicators)/sizeof(UINT)))
           {
                  TRACE0("Failed to create status bar/n");
                  return -1;      // fail to create
           }
     
           // TODO: Delete these three lines if you don't want the toolbar to
           // be dockable
           m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
           EnableDocking(CBRS_ALIGN_ANY);
           DockControlBar(&m_wndToolBar);
        SetTimer(1, 5000, 0); // 在这里设置计时器
           return 0;
    }
     
    这样编译debugm通过, Hello World!的对话框也出来了。但是在程序退出时检测到有内存泄露:Detected memory leaks!
     
    我估计在销毁计时器的代码有问题。于是我把放到响应WM_DESTROY消息的函数里。
    void CMainFrame::OnDestroy()
    {
           CFrameWnd::OnDestroy();
          
           // TODO: Add your message handler code here
           KillTimer(1);
    }
          为什么设置计时起不能放在窗口类构造函数,销毁计时器不能放在窗口类的析构函数里?让我们看看MFC的源码:
    CWnd::SetTimer(UINT nIDEvent, UINT nElapse,
                  void (CALLBACK* lpfnTimer)(HWND, UINT, UINT, DWORD))
           { ASSERT(::IsWindow(m_hWnd)); return ::SetTimer(m_hWnd, nIDEvent, nElapse,
                  (TIMERPROC)lpfnTimer); }
     
    果然有一个ASSERT宏。而且这个宏很明确地告诉我们必须在窗口句柄有效的时候才能设置计时器。同样道理,在销毁计时器时也必须确保窗口句柄是有效的。
     
  • 相关阅读:
    反Secure Boot垄断:兼谈如何在Windows 8电脑上安装Linux
    火车售票系统(数据结构课设)
    货物管理系统(数据结构链式表)
    货物管理系统(数据结构顺序表)
    进制转换器(十进制转n进制)
    大学生成绩管理系统(C语言)
    如何对Linux的grub进行加密
    戴文的Linux内核专题:07内核配置(3)
    戴文的Linux内核专题:06配置内核(2)
    戴文的Linux内核专题:05配置内核(1)
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6471261.html
Copyright © 2011-2022 走看看