Click here to Skip to main content
15,888,984 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm using Win32 API timer procedure like this:
C++
typedef struct my_parameter {
    //...
}MyParam,*pMyParam;

pMyParam my_param;

void MyTimeProc(HWND hwnd,UINT msg,UINT_PTR nIDEvent,DWORD tickCount) {
    //operations on varibale my_param.
    //......
}

//......
int MyStartTimerProcedure(HWND hwnd) {
    UINT msg=WM_TIMER;
    UINT_PTR nIDEvent;
    UINT uElapse=1000;
    TIMERPROC timeProc=MyTimeProc;

    SetTimer(hwnd,nIDEvent,uElapse,timeProc);

    //......


    return 0;
}
As you see,win32 function pointer TIMERPROC and Win32 API SetTimer both have serval parameters. If I want to change the global variable my_param as a parameter passing between SetTimer and TimerProc, the interface seems not supported.

What I have tried:

In order to replace the global variable , from what I know, I have to write some code to manage the variable between SetTimer and TimerProc, like this:

C++
typedef struct timer_param {
    UINT_PTR param_idevent;
    void* param_data;
    timer_param* next;
}TimerParam,pTimerParam;
pTimerParam global_timerparam;
pTimerParam NewGlobalTimerParam() {
    pTimerParam param=(pTimerParam)calloc(sizeof(Timer),1);
    return param;
}
pTimerParam GetTimerParam() {
    return global_timerparam;
}
int AppendNewGlobalTimerParam(UINT_PTR nIDEvent,void* data) {
    pTimerParam param=NewGlobalTimerParam();
    if(param==NULL) return -1;
    param->param_idevent=nIDEvent;
    param->param_data=data;
    
    pTimerParam tmp=GetTimerParam();
    pTimerParam pre=tmp;
    while(tmp) {
        pre=tmp;
        tmp=tmp->next;
    }
    if(pre==NULL) pre=param;
    else pre->next=param;
    
    return 0;
}

pTimerParam FetchParamFromIDEvent(UINT_PTR nIDEvent) {
    pTimerParam tmp=GetTimerParam();
    while(tmp) {
        if(tmp->param_idevent==nIDEvent) return tmp;
        tmp=tmp->next;
    }
    return NULL;
}

//.....
typedef struct my_parameter {
    //...
}MyParam,*pMyParam;

void MyTimeProc(HWND hwnd,UINT msg,UINT_PTR nIDEvent,DWORD tickCount) {
    //get param from nIDEvent.
    pMyParam param=(pMyParam)FetchParamFromIDEvent(nIDEvent);
    if(param) {
        // operations on param.
        //....
    }
}

//......
int MyStartTimerProcedure(HWND hwnd) {
    UINT msg=WM_TIMER;
    UINT_PTR nIDEvent;
    UINT uElapse=1000;
    TIMERPROC timeProc=MyTimeProc;
    
    pMyParam my_param;
    //assignment of my_param
    // ......

    AppendNewGlobalTimerParam(nIDEvent,my_param);
    SetTimer(hwnd,nIDEvent,uElapse,timeProc);

    //......


    return 0;
}
Yes, it would work. But it's too much inconvenient. I have to do a lot to manage the parameters passing into the timerprocedure.
Is there a more easy way to pass parameters into the TIMERPROC function ?
Posted
Updated 8-Oct-22 4:25am
Comments
Richard MacCutchan 9-Oct-22 10:54am    
Assuming the event handler is in the same thread as the process that starts the timer you can use a global variable. But the main question remains: what exactly are you trying to achieve?

No, there is no way to pass more parameters into the timer procedure. You can vary the event identifier though. For example, when you service EventIdent1 in MyTimeProc you can call KillTimer( hwnd, EventIdent1 ) and then set a timer for a different event, like EventIdent2 and it can also call a different timer procedure if you want to. You can play ping-pong with several events and timer procedures like this if you want. Maybe the event transitions can correspond to various states in your application. As far as I know, that's the only thing that can be varied in a call to a timer procedure.
 
Share this answer
 
Comments
Yount_0701 11-Sep-22 6:21am    
Thank you.
I'm waiting for some kind of breakthrough.
If you want to pass some data from SetTimer to TimerProc you need to pass it via 2nd parameter during call SetTimer(). Its type is UINT_PTR which will be able to store any pointer type (up to 64 bytes on x64 machines).
This i believe is the intended way to pass info to TimerProc and that's how i passed info in my applications.

C++
// setting the timer...
SetTimer(wnd, UINT_PTR(this), 1000, MyTimeProc);

// timer proc
void MyTimeProc(HWND hwnd,UINT msg,UINT_PTR nIDEvent,DWORD tickCount) 
{
    // nIDEvent is your data passed during SetTimer call (this in my example)
    MyParam* param { reinterpret_cast<MyParam*>(uIDEvent) };
    // do with param whatever you need
}


P.S. your MyStartTimerProcedure() has undefined behavior because you passing an uninitialized variable UINT_PTR nIDEvent; (and that's the variable that will be the data you pass)
 
Share this answer
 
v2
Comments
Richard MacCutchan 8-Oct-22 12:10pm    
The second parameter is specifically used to pass the event id of the timer, so using it for other purposes is not guaranteed by Windows.
Yount_0701 9-Oct-22 8:22am    
I have to admit that the variable nIDEvent should be initialized with a specified event value which I missed in my codes.
I have tried your idea before I posted this question. Frankly It does not work as I expected, which crashed at the explicit conversion.
Some articles show a different way of catching the message loop by interfering the message translating and distributing. It's just not what I want.
Avtem 9-Oct-22 8:26am    
Can you show your code for the SetTimer and TimerProc? If the types are the same, it shouldn't crash

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900