[C++] virtual member function als callback procedure

Pagina: 1
Acties:

  • El Psycho
  • Registratie: September 2002
  • Laatst online: 17-08 21:45
Mijn probleem is als volgt...

Ik wil in Visual C++ 6 een class maken die alle functies met betrekking tot een bepaalde window afhandelt. Nu wil ik toevalig ook dat dit window een timer krijgt. Maar om de timer messages af te handelen moet ik dus een callback procedure krijgen (één opgeven in SetTimer of bij het creëeren van het window de callback procedure van alle message opgeven, 2e optie heeft mijn voorkeur da's logisch). (Toevallig kwam ik het nu tegen bij een timer... als ik het beter had gedaan was ik het al eerder tegengekomen :-D)

Deze callback procedure will ik natuurlijk ook in de class hebben. En daar komt nu mijn probleem. Visual C++ is niet echt blij met mijn pogingen een virtual member function door te geven aan CreateWindow of SetTimer. Dit zal hoogstwaarschijnlijk te maken hebben met het feit dat dit eigenlijk mijn eerste experiment met de classes in C++ is.

Het internet tot dusverre is me nog niet echt behulpzaam geweest. Ik heb deze zelfde vraag al op een ander forum gezien waarbij het antwoord was er maar een static functie van te maken. Dat hielp degene die op het andere forum de vraag had gesteld wel maar in mijn geval kan mijn timer dan niet meer doen wat hij eigenlijk moest doen, namelijk andere virtual members aanroepen :-).

Een paar stukken over virtual member function pointers heb ik ook al gevonden maar die hielpen ook niet echt dat je zegt. (Wellicht doordat ik wat fout deed maar toch).

In het kort dus:

stel ik heb een

class window {
int window();
int timercallback(benodigde parameters hier);
}

hoe kan ik dan in de constructor window() het adres van timercallback krijgen in zo'n vorm dat ik het ook nog kan doorgeven aan SetTimer or CreateWindow (via de structure wiens naam ik momenteel ff vergeten ben)?

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Hier zijn wat threads met ongeveer hetzelfde probleem, data (object pointer bijvoorbeeld) associeren met een window (dan wel andere soorten callbacks):
[rml][ C++/win32] Data met windows associeren[/rml]
[rml][ C++] WndProc in class[/rml]
[rml][ C++] Van __cdecl naar __thiscall ?[/rml]

Voor de timer kun je wel een globale map gebruiken van timer id naar object adres. Je kan idd geen virtual functies als callback gebruiken omdat callbacks anders aangeroepen worden (gewone C/stdcall functies zonder 'this' pointer).

[ Voor 5% gewijzigd door madwizard op 21-09-2003 23:35 ]

www.madwizard.org


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dit zal hoogstwaarschijnlijk te maken hebben met het feit dat dit eigenlijk mijn eerste experiment met de classes in C++ is.
logisch, een memberfunctie heeft een instantie nodig om op te werken. Je zou je instantie mee kunnen geven als nIDEvent parameter bij de SetTimer () functie. Je maakt dan een normale globale functie, en gebruik je de idEvent parameter als class, waarop je vervolgens de juiste methode aanroept

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

.oisyn schreef op 21 september 2003 @ 23:34:
logisch, een memberfunctie heeft een instantie nodig om op te werken. Je zou je instantie mee kunnen geven als nIDEvent parameter bij de SetTimer () functie. Je maakt dan een normale globale functie, en gebruik je de idEvent parameter als class, waarop je vervolgens de juiste methode aanroept
Das natuurlijk het makkelijkst, ik meende dat de timer ID gelimiteerd was tot iets van 0xFFFF (zoals wel vaker met windows APIs) maar kon het niet vinden dus ik zal dat wel verward hebben met iets anders :).
edit:
oh ja, hotkey IDs waren beperkt..

[ Voor 5% gewijzigd door madwizard op 21-09-2003 23:41 ]

www.madwizard.org


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ja ik moet zeggen dat het wel een beetje vaag is. De id is iig user-defined, maar in de docs over SetTimer staat:
nIDEvent
[in] Specifies a nonzero timer identifier. If the hWnd parameter is NULL, this parameter is ignored. If the hWnd parameter is not NULL and the window specified by hWnd already has a timer with the value nIDEvent, then the existing timer is replaced by the new timer. When SetTimer replaces a timer, the timer is reset. Therefore, a message will be sent after the current time-out value elapses, but the previously set time-out value is ignored.
Zie het dikgedrukte gedeelte. Maar in de TimerProc krijg je wel weer de id als parameter:
idEvent
[in] Specifies the timer's identifier.
terwijl een timerproc alleen wordt aangeroepen als de hWnd parameter van SetTimer NULL is :? Spreekt elkaar een beetje tegen.
Verder staat er idd niets over een limiet, de waarde is gewoon een UINT_PTR (unsigned int) :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Inderdaad vaag, later staat er nog:
The timer identifier, nIDEvent, is specific to the associated window. Another window can have its own timer which has the same identifier as a timer owned by another window. The timers are distinct.
Zo lijkt het alsof je een window handle nodig hebt om de timer ID ermee te kunnen associeren, maar dan staat er weer:
SetTimer can reuse timer IDs in the case where hWnd is NULL.
:?

www.madwizard.org


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Heren heren.... je krijgt een ID terug uit de SetTimer functie :)

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

En je wilt de timer sowieso weer op stop kunnen zetten, dus dan heb je ook een zinnige id nodig. Of kun je maar 1 unowned timer per thread aanmaken?

Curry: UINT_PTR is een unsigned int, geen pointer zoals de naam doet vermoeden. Bovendien staat er [in], niet [out] ;)

.edit: oh wacht:
If the function succeeds and the hWnd parameter is NULL, the return value is an integer identifying the new timer. An application can pass this value to the KillTimer function to destroy the timer.
dan wordt idevent blijkelijk wel gewoon geignored, en kun je die dus niet gebruiken om userdata mee te geven aan de TimerProc () (wat ik wel erg fout vind overigens)

[ Voor 71% gewijzigd door .oisyn op 22-09-2003 00:07 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • El Psycho
  • Registratie: September 2002
  • Laatst online: 17-08 21:45
*had er nog niet aan gedacht de timer ID hetzelfde te maken als het adres* *had wel al gekeken of er niet een ongebruikte lparam of zo was*

Hmm zou in ieder geval het huidige probleem omzeilen :-) en ik zal die andere threads ook es bekijken.. (had ik toch niet op de goede keywords gezocht)..

edit:
Dus als ik bij SetTimer de hwnd doorgeef, kan ik via de timerID doen wat ik wil doen... (door gewoon this mee te geven als id, en dan een statische callback die de virtuele aanroept door een (Window)timerID.timercallback), toch?

[ Voor 31% gewijzigd door El Psycho op 22-09-2003 00:15 ]


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Net ff snel getest:
hWnd = null, nIDEvent = 0x1234, lpTimerFunc geset:
Retourneert een andere waarde dan nIDEvent (0x58F0 ofzo, gewoon een willekeurig id), deze waarde krijgt de TimerProc ook mee.

hWnd = niet null, nIDEvent = 0x1234, lpTimerFunc geset:
Retourneert nIDEvent (0x1234), krijgt TimerProc ook mee als ID

Blijkbaar heb je dus een window handle nodig om zelf je timer ID te kiezen.. hWnd en lpTimerFunc zijn niet mutually exclusive dus het kan wel zo, maar het zou handiger zijn als je ook een id zou kunnen kiezen zonder window handle...

www.madwizard.org


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

El Psycho schreef op 22 September 2003 @ 00:08:
edit:
Dus als ik bij SetTimer de hwnd doorgeef, kan ik via de timerID doen wat ik wil doen... (door gewoon this mee te geven als id, en dan een statische callback die de virtuele aanroept door een (Window)timerID.timercallback), toch?
Ja, als je het zo doet: ((Window*)timerID)->timercallback, of helemaal in C++ stijl: reinterpret_cast<Window*>(timerID)->timercallback.
edit:
--sorry die reply had ook wel als edit gekunt

[ Voor 11% gewijzigd door madwizard op 22-09-2003 00:18 ]

www.madwizard.org


  • El Psycho
  • Registratie: September 2002
  • Laatst online: 17-08 21:45
't is laat, ging zich om het idee, LoL ;) bedankt mensen :D (goh.. dit ging een stuk sneller als toen ik het net aan't afstruinen was...)

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

madwizard schreef op 22 September 2003 @ 00:14:
hWnd en lpTimerFunc zijn niet mutually exclusive dus het kan wel zo, maar het zou handiger zijn als je ook een id zou kunnen kiezen zonder window handle...
oh ja klopt idd, want een DefWindowProc van zo'n message roept gewoon de TimerProc aan

maar ik weet niet of de window messages ook al gewoon in een memberfunction van de Window class aankomen, zo ja is het natuurlijk gewoon handiger om hem daar af te vangen :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1