WinApi SetTimer cannot compile - c++

I need timer to start function every 1 second.
I have tried SetTimer, my code:
const UINT_PTR TIMER_ID = 1000;
DWORD DownloadThread()
{
SetTimer(NULL, TIMER_ID, 1000, (TIMERPROC)DownloadSpeedCounter);
/*some stuff*/
}
void DownloadSpeedCounter()
{
/*some stuff*/
}
I cannot compile this code and get error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'TIMERPROC'
Also it is class member method.

This is because you are trying to use a normal function as an application-defined callback function. What you are probably looking for is this application-defined callback function which could look like this:
VOID CALLBACK DownloadSpeedCounter(
HWND hwnd, // handle to window for timer messages
UINT message, // WM_TIMER message
UINT idTimer, // timer identifier
DWORD dwTime) {
/* some stuff */
}
For additional information on using callback functions for timers see this article.

One of the problems is that TIMERPROC functions should look like this: typedef VOID (CALLBACK* TIMERPROC)(HWND, UINT, UINT_PTR, DWORD); So your method definition should look like this:
VOID CALLBACK DownloadSpeedCounter(HWND, UINT, UINT_PTR, DWORD);
Also, as this is a method, not just a function, it must be static. So it is calling like static but to access private non-static data may be used this technique.

Related

C++ Windows: LRESULT CALLBACK and WNDPROC

I have a class:
class SomeClass
{
public:
void Init ();
private:
LRESULT CALLBACK WndProc (HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam);
};
Also, in another file I have a function:
void MakeWindow (WNDPROC wnd_proc, DWORD style, HICON lg_icon, ...);
The first parameter is supposed to take a LRESULT CALLBACK function as input. Somewhere I also have a definition for the Init function:
void SomeClass::Init ()
{
MakeWindow (this->WndProc, WM_POPUP, NULL, ...);
}
This gives me error C3867 in VS2012 when I try to pass this->WndProc to WNDPROC wnd_proc. Is there any way I can pass the LRESULT CALLBACK WndProc function to MakeWindow?
The problem is that your WndProc method is an instance method and so does not match WNDPROC. Because it is an instance method it receives an extra, implict, this parameter.
You need to declare it as a static method in order for it to be compatible with WNDPROC.

EnumWindows Pointer error

I'm getting a weird error trying to EnumWindows to a function inside a class. Here's my code
EnumWindows(&ConsoleDetector::EnumWindowsProc, NULL);
BOOL CALLBACK ConsoleDetector::EnumWindowsProc(HWND wnd, LPARAM lParam)
{
char className[200];
GetClassName(wnd, className, 200);
if (strcmp(className, "ConsoleWindowClass"))
m_result.push_back(wnd);
return TRUE;
}
Here's the error im getting:
ConsoleDetector.cpp:30: error: cannot convert 'BOOL (ConsoleDetector::*)(HWND__*, LPARAM)' to 'BOOL (*)(HWND__*, LPARAM)' for argument '1' to 'BOOL EnumWindows(BOOL (*)(HWND__*, LPARAM), LPARAM)'
Using MingW.
Thanks for help.
You are passing an instance method. You need to pass a plain function rather than a method bound to an instance.
It has to be declared like this:
BOOL CALLBACK EnumWindowsProc(HWND wnd, LPARAM lParam)
Pass the instance of the ConsoleDetector to the lParam parameter of EnumWindows and it will in turn be passed to your callback.
Like this:
BOOL CALLBACK EnumWindowsProc(HWND wnd, LPARAM lParam)
{
ConsoleDetector cd = static_cast<ConsoleDetector*>(lParam);
//do stuff with cd and wnd
}
ConsoleDetector *cd = ...
EnumWindows(EnumWindowsProc, static_cast<LPARAM>(cd));
You can't use the windows callback function with class member functions in c++. Only static class functions or non class functions are allowed.
How should the EnumWindows function kown the instance of a class? You can only supply a function pointer, not an instance pointer to EnumWindows

Passing User Data with SetTimer

I am calling SetTimer in a function of a Class.
SetTimer(NULL, 0, 10000, (TIMERPROC) TimerCallBack);
Where TimerCallBack is:
static VOID CALLBACK TimerCallBack(HWND, UINT, UINT, DWORD)
Now my need is to call one of the method of class which initiated timer, since TimerCallBack is static it has no access to the class object anymore.
I cant find any way to pass object pointer along with the SetTimer so that I can receive it back on Callback function.
Is there any other way to achieve this, if its not supported using SetTimer then which other way I can implement this.
You don't need a map. Use the idEvent parameter. Microsoft gave it the UINT_PTR type so it fits a pointer, even in 64 bits:
SetTimer(hwnd, (UINT_PTR)bar, 1000, MyTimerProc);
void CALLBACK MyTimerProc(HWND, UINT, UINT_PTR idEvent, DWORD)
{
Bar* bar = (Bar*)idEvent;
}
Note that you need to use an actual HWND. If the HWND is null, Windows will generate the idEvent internally.
Obviously, if you were directing timer messages at a window, you could just store the user data with the window.
The only way to do this with a TimerProc is to make a class that manages a statically scoped map of timer-id's to user data objects.
Something like this (As this is a c++ question, Im just implementing a quick and dirty functor type thing so that the TimerMgr can arrange callbacks directly to members of classes, which is usually why you are trying to store user data:
// Timer.h
#include <map>
class CTimer {
public:
class Callback {
public:
virtual void operator()(DWORD dwTime)=0;
};
template<class T>
class ClassCallback : public Callback {
T* _classPtr;
typedef void(T::*fnTimer)(DWORD dwTime);
fnTimer _timerProc;
public:
ClassCallback(T* classPtr,fnTimer timerProc):_classPtr(classPtr),_timerProc(timerProc){}
virtual void operator()(DWORD dwTime){
(_classPtr->*_timerProc)(dwTime);
}
};
static void AddTimer(Callback* timerObj, DWORD interval){
UINT_PTR id = SetTimer(NULL,0,interval,TimerProc);
// add the timer to the map using the id as the key
_timers[id] = timerObj;
}
static void CALLBACK TimerProc(HWND hwnd,UINT msg,UINT_PTR timerId,DWORD dwTime){
_timers[timerId]->operator()(dwTime);
}
private:
static std::map<UINT_PTR, Callback*> _timers;
};
// In Timer.cpp
#include <windows.h>
#include <Timer.h>
std::map<UINT_PTR,CTimer::Callback*> CTimer::_timers;
// In SomeOtherClass.cpp
class CSomeClass {
void OnTimer1(DWORD dwTime){
}
public:
void DoTimerStuff(){
CTimer::AddTimer( new CTimer::ClassCallback<CSomeClass>(this,&CSomeClass::OnTimer1), 100);
}
};
Removing timers from the map is left as an exercise for the reader :)
ClassCallback needed to inherit Callback.
static variables need to be defined
Code now builds and runs correctly on MSVC 9.0
Given that you don't appear to be using MFC (CWnd::OnTimer means you'd have access to the class), and you don't have a HWND (you could conceivably set a property on the HWND on timer-creation and get it back in your proc), there is another option.
SetTimer returns a UINT_PTR which is the timer ID. This is what you'll get in your TimerProc and will also pass to KillTimer when you're done with it. Using this, we can create a map that maps a timer ID to some user-defined object of your creation:
class MyAppData
{
}; // eo class MyAppData
typedef std::map<UINT_PTR, MyAppData*> MyDataMap;
MyDataMap dataMap;
Then we create your timer:
MyAppData* _data = new MyAppData(); // application-specific data
dataMap[SetTimer(NULL, 0, 10000, (TIMERPROC)TimerCallBack)] = _data;
And in your procedure:
static void CALLBACK TimerCallBack(HWND _hWnd, UINT _msg. UINT_PTR _idTimer, DWORD _dwTime)
{
MyAppData* data = dataMap[_idTimer];
} // eo TimerCallBack
There exists one more solution, but in order to use that one - HWND parameter in SetTimer should be non-NULL.
It's possible to store extra data into window itself, using API function SetWindowLongPtr with parameter GWLP_USERDATA.
So you could add into your class following function:
void SetLocalTimer(UINT_PTR nIDEvent, UINT nElapse)
{
SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG_PTR)this);
SetTimer(nIDEvent, nElapse, _TimerRouter);
}
and timer router function, which determines what to do on given timer.
static void CALLBACK _TimerRouter(HWND hwnd, UINT, UINT_PTR nEventID, DWORD)
{
YourClassName* inst = (YourClassName*)GetWindowLong(hwnd, GWLP_USERDATA);
if( !inst )
return;
switch (nEventID)
{
case 0:
inst->DoThis();
break;
case 1:
inst->DoThat();
break;
}
}
This allows also to use nEventID as function identifier to be called.
There still exists a risk that user data will be used from more than one place, but I think it's good practice to keep UI window matching it's class model this pointer.

Pointer to a callback in a DLL

I'm calling a Dialog that has it's resources and dlg-procedure in a DLL.
I'm not using a DEF file or LIB file. The function names are known, the function args are known, I'm using GetProcAddress to get a pointer to the functions I'm interested in.
'Why' I'm doing it this way is of no consequence, it's an experiment in 'learning'.
This works on _cdecl functions, but on the CALLBACK (_stdcall), I can't get a pointer to the actual dialog procedure (it returns 0).
Here's how I'm doing my pointers:
//////////////////// DLL TEST STUFF ////////////////////////////
#define DLLPATH "../../testdll/release/testdll.dll"
//typedef some function pointers
typedef HINSTANCE (__cdecl *INSTPROC )(void);
typedef int (__cdecl *VOIDPROC )(void);
typedef LRESULT (__stdcall *DLGROC )(HWND, UINT, WPARAM, LPARAM );
///////////////////////////////////////////////////////////////
As I said, any function that is NOT a callback returns a valid result, additionally, the dialog pops up as expected, no problems with DLL's HINSTANCE.
But without a pointer to it's dlgproc, no button messages have anywhere to go.
Here's some more test code:
//use DLL funcs without lib or def files
//this works
GetInst = (INSTPROC)GetProcAddress(Loadme,"getinst");
//this works
GetID = (VOIDPROC)GetProcAddress(Loadme,"getid");
//this doesn't work, rets 0
DlgProc = (DLGPROC) GetProcAddress(Loadme,"dllProc");
//test for result
dllid =(GetID)();
dllinst=(GetInst)();
//compare hinst OK
wsprintf(buf,"dllinst=%x Loadme=%x",dllinst, Loadme);
MessageBox(hwnd,buf,"",MB_OK);
//check resOurce ID OK
wsprintf(buf,"GetID returned: %d",dllid);
MessageBox(hwnd,buf,"",MB_OK);
//check dllProc addr NOGO, ret=0
wsprintf(buf,"dllProc=%x",DlgProc);
MessageBox(hwnd,buf,"",MB_OK);
// DLL instance, resource ID, parent, dlgproc
DialogBox(Loadme , MAKEINTRESOURCE(dllid), hwnd, DlgProc);
//dialog loads and shows, can't get dlgproc addr
FreeLibrary(Loadme);
///////////////// END DLL TEST STUFF ///////////////
On the DLL side of things, it looks like this:
__declspec(dllexport) LRESULT CALLBACK dllProc(
HWND hwnd,
UINT Message,
WPARAM wParam,
LPARAM lParam
)
{
hpwnd=hwnd;
switch (Message){
case WM_INITDIALOG:
MessageBox(hwnd,"At DlgProc...","",MB_OK);
return TRUE;
case WM_COMMAND:
switch(LOWORD(wParam)){
case IDEND:
case IDCANEND:
EndDialog(hwnd,0);
return TRUE;
}
return TRUE;
}
return FALSE;
}
Which really doesn't matter at this point, since I can't get a pointer to the callback in the first place.
If anyone happens to know the fix for getting a pointer to the callback, I would very much appreciate your input.
Thanks for your patience.
You need to declare your dllProc inside an extern "C" block to prevent its name being decorated when exported, so that when you ask for a function called "dllProc" such a function is found (instead of "dllProc#blahmoocow" or whatever madness the C++ decoration produces. :-)).
Place this declaration before the dllProc definition:
extern "C"
{
__declspec(dllexport) LRESULT CALLBACK dllProc(
HWND hwnd, UINT Message, WPARAM wParam, PARAM lParam);
}
You can also then drop the __declspec(dllexport) from the dllProc definition.

C++ Timer not working?

I'm trying to make a timer in c++. I'm new to c++. I found this code snippet
UINT_PTR SetTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc);
I put it in my global variables and it tells me
Error 1 error C2373: 'SetTimer' : redefinition; different type modifiers
I'm not sure what this means. Is there a more proper way to define a timer?
I'm not using mfc / afx
Thanks
You should call it like this:
void CALLBACK TimerProc(
HWND hwnd,
UINT uMsg,
UINT idEvent,
DWORD dwTime
)
{
//do something
}
SetTimer(NULL, NULL, 1000, TimerProc);
This would set a timer for 1 second and will call TimerProc when it expires. Read TimerProc MSDN here: http://msdn.microsoft.com/en-us/library/ms644907%28VS.85%29.aspx
That's not a function call -- that's a function declaration, which you are probably already #including from somewhere. What you need is the actual SetTimer call from your code.
Can you post your code where you're trying to set up the timer, and the function you want it to call when it triggers?