• SetTimer 与回调函数


    在控制台应用程序中,SetTimer的函数原型为:

    UINT_PTR SetTimer(
      HWND hWnd,              // handle to window
      UINT_PTR nIDEvent,      // timer identifier
      UINT uElapse,           // time-out value
      TIMERPROC lpTimerFunc   // timer procedure
    );


    具体的解释可以看MSDN,主要是第四个参数,定义的参数类型为 TIMERPROC
    VOID CALLBACK TimerProc(
      HWND hwnd,         // handle to window
      UINT uMsg,         // WM_TIMER message
      UINT_PTR idEvent,  // timer identifier
      DWORD dwTime   // current system time
    );

    怎样在控制台应用程序中定义自己的回调函数呢?

    回调函数说白了就是 事件 响应程序,Windows的每个消息可以理解为一个事件,事件的响应代码要由用户自己来定义。用户定义了事件响应的代码,但还要Windows知道这段代码的位置(要不然Windows就不知道如何去调用,这也没有用),于是用户需要将回调函数的指针告诉Windows,最典型的例子是在窗口类的结构(WNDCLASS)中给lpfnWndProc分量赋回调函数指针值。    回调函数的参数格式是由回调函数的调用者(一般是Windows)来定义的,而回调函数的实现者必须遵循这种格式。Windows程序是以事件驱动模型为基础的,这就必然要用到回调函数这种机制。

            如果有时间,不妨看看MESSAGE_MAP宏,消息映射是回调函数,只是这种回调函数的用法不同而已。普通的回调函数是要你提供地址,传进某个函数,由它去调用;而消息映射函数,却是由你定义函数,由MESSAGE_MAP宏去取得地址,并实现它的调用。

            回调函数是一个程序员不能显式调用的函数;通过将回调函数的地址传给调用者从而实现调用。要实现回调,必须首先定义函数指针。尽管定义的语法有点不可思议,但如果你熟悉函数声明的一般方法,便会发现函数指针的声明与函数声明非常类似。

          

    typedef void ( *f1 ) (       );// 为函数指针声明类型定义
    void ( *p ) (   ); //p是指向某函数的指针

    //定义一个函数
    void func1() 

     /* do something */
     printf("From func1(), Hello World!/n");
    }

    //定义一个调用函数指针的回调函数

    void caller(     void(*ptrfunc1)(   )    )
    {
     ptrfunc1(    ); /* 调用ptr指向的函数 */ 
    }

    //typedef bool (*f2) (int *);// 为函数指针声明类型定义
    //bool (*q) (int *); //p是指向某函数的指针

    bool func2(int* t_i) 
    {
     printf("From func2() = %d, Hello World!/n", (*t_i)++);
     return true;
    }

    void caller2    (   bool (*ptrfunc2)(int *),       int * i      )
    {
     ptrfunc2(i); /* 调用ptr指向的函数 */ 
    }


    int main(int argc, char* argv[])
    {
     printf("From main(), Hello World!/n");
     printf("/n");

     //无参数调用
     p = func1; /* 传递函数地址地址 */
     caller(p); /* 传递函数地址到调用者 */

     //有参数调用
     int i = 0; 
     for (int j = 0; j < 10; j++)
     {
      caller2(func2, &i); //* 传递函数地址到调用者 */
     }

     //有参数调用第二次

      i = 0;
     //q = func2; /* 传递函数地址地址 */
     //caller2(q, &i); /* 传递函数地址到调用者 */

     printf("/n");
     printf("From main(), Hello World!/n");

     getchar();

     return 0;
    }

    我们以在控制台中定义一个SetTimer函数为例子,见如下代码:

    #include <iostream>
    #include <windows.h>
    using namespace std;

    VOID CALLBACK Func(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime )
    {
    MessageBox(NULL,"Hello","ALARM",1);
    }


    void main()
    {

    MSG msg;
    SetTimer(NULL,1,1000, (TIMERPROC)Func);
    while( GetMessage(&msg,NULL,NULL,NULL))
    {
    if (msg.message == WM_TIMER)
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }

    }
    }

    刚开始的时候以为不用设置消息循环,所以没有写循环,才出现了各种错误。

  • 相关阅读:
    动画编程1
    驾照助手
    《机器学习进阶》Udacity 机器学习基础 决策树+迷你项目
    《机器学习进阶》Udacity 机器学习基础 异常值+交叉验证
    《机器学习进阶》Udacity 机器学习基础 评估指标
    《机器学习进阶》Udacity 监督学习 决策树
    《机器学习进阶》Udacity 监督学习 SVM支持向量机
    入门模拟(图形输出)——B1036.跟奥巴马一起编程( 注意行数为偶数或奇数的情况)
    入门模拟——A1036.Boys vs Girls
    leetcode 深搜广搜
  • 原文地址:https://www.cnblogs.com/CBDoctor/p/3007370.html
Copyright © 2020-2023  润新知