Beim TimerInterrupt Variable übergeben
-
Also, ich arbeite mit Borland und hab ein kleines Form, in welchem ich 9 Timer verbaut habe (die ich auch brauche). Jeder Timer ruft ein und die selbe Funktion auf, nur mit einem unterschiedlichen Parameter. Ist es möglich, in das OnTimer-Ereignis eine Konstante zu schreiben, die dann an die aufgerufene Funktion übergeben wird?
Folgendes funktioniert nicht:(...) object Timer1: TTimer OnTimmer = Timer1Timer(1) end (...) void __fastcall TForm1::Timer1Timer(TObject *Sender, int i) { EineFunktion(i); } (...)
Ach ja, Sinn und Zweck der ganzen Sache ist, dass ich mir 8 Funktionen sparen kann und alles über eine Funktion regle.
Darauf aufbauend wäre ich bereit für Lösungsvorschläage
-
Kann auch sein, dass ich gerade quer denke, aber ich denke, es geht. Habe ich glaubich auch selber mal gemacht...
Jeder Timer hat eine ID und solange deine Konstanten nicht 0 sind (was evtl. auch geht, weiß nich) oder gleich sind, kannst du die Konstante als ID nehmen.Ich kenne mich mit dem Borland-Kram nicht aus, aber die Timer-Funktionen dort scheinen ja auch einen Parameter übergeben zu kriegen. Müsste ja die ID des ausgelösten Timers sein. Damit haste ja deinen Parameter...
Mit WinApi-Funktionen:
... SetTimer( hWnd, DeineKonstante, uElapse, DeineTimerFunktion ); ... void CALLBACK DeineTimerFunktion( HWND hWnd, UINT Msg, UINT Event, DWORD Time ) { UINT DeineKonstante = Event; ... }
Eventueller Delphi-Code:
object Timer1: TTimer OnTimmer = Timer4All( Konstante1 ) // Hier musst du für "Konstante1" natürlich deinen (Integer-)Wert angeben! end object Timer2: TTimer OnTimmer = Timer4All( Konstante2 ) // ... end (...) void __fastcall TForm1::Timer4All(TObject *Sender, int i) { EineFunktion(i); // i ist in diesem Fall deine Konstante }
-
Die normalen Standard-Timer haben keine User-Params. Da musst du entweder auf glob. Variablen oder auf die User-Daten eines Fensters (wenn in deinem Fall möglich, mittels Get/SetWindowLongPtr und GWL_USERDATA) zurück greifen.
Oder du nutzt Multimedia-Timer mittels timeSetEvent. Da kannst du einen Parameter übergeben, der dann auch deiner TimerProc übergeben wird.
Diese Timer haben übrigens auch ne bessere Auflösung.
-
CodeFinder schrieb:
Die normalen Standard-Timer haben keine User-Params.
#include <windows.h> LRESULT CALLBACK WinProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) { switch ( Msg ) { case WM_TIMER: { HWND hStatic = GetDlgItem( hWnd, 1 ); SetWindowText( hStatic, (LPCTSTR)wParam ); break; } case WM_CLOSE: { PostQuitMessage( 0 ); break; } } return DefWindowProc( hWnd, Msg, wParam, lParam ); } int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { // Create main-window WNDCLASSEX ex; ZeroMemory( &ex, sizeof( WNDCLASSEX ) ); ex.cbSize = sizeof(WNDCLASSEX); ex.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC; ex.lpfnWndProc = WinProc; ex.hInstance = hInstance; ex.hIcon = LoadIcon( NULL, IDI_APPLICATION ); ex.hCursor = LoadCursor( NULL, IDC_ARROW ); ex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); ex.lpszClassName = "SomeClassName"; RegisterClassEx(&ex); HWND hWnd = CreateWindowEx( NULL, "SomeClassName", "Window", WS_OVERLAPPEDWINDOW, 0, 0, 300, 300, NULL, NULL, hInstance, NULL ); ShowWindow( hWnd, SW_SHOW ); UpdateWindow( hWnd ); // Create static-text-control CreateWindow( "STATIC", "asd", WS_CHILD|WS_VISIBLE, 10, 10, 200, 20, hWnd, (HMENU)1, hInstance, NULL ); // Set Timers const char* ParamStrs[5] = { "This", "Could", "Be", "A", "Sentence" }; for ( ULONG i=0; i<5; i++ ) { SetTimer( hWnd, (ULONG)ParamStrs[i], 2000, NULL ); Sleep( 400 ); } // Enter Msg-loop MSG Msg; while ( 1 ) { GetMessage( &Msg, NULL, 0, 0 ); if ( Msg.message == WM_QUIT ) break; TranslateMessage( &Msg ); DispatchMessage( &Msg ); } // Clean up for ( ULONG i=0; i<5; i++ ) KillTimer( hWnd, (ULONG)ParamStrs[i] ); UnregisterClass( "SomeClassName", hInstance ); return Msg.lParam; }
Die Initialisierung des Fensters dauert etwas lange, aber sonst...
-
@Badestrand:
Das Beispiel ist nicht sehr gelungen...MSDN zu SetTimer(...) schrieb:
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.Was du da rum-castet ist in meinen Augen eher gefährlich...Adressen werden i.d.R. in long-Varialben gespeichert...du castet einen Adresswert erst nach unsigned long, um ihn anschließend implizit nach unsigned int casten zu lassen
. Wohl eher nicht empfehlenswert. Außerdem: Starte mal zwei Timer und versuch dann mal mitihlfe deiner 'Adress-ID' diese zu differenzieren
. Das ist nur gefriemel.
BTW...das:
while ( 1 ) { GetMessage( &Msg, NULL, 0, 0 ); if ( Msg.message == WM_QUIT ) break; TranslateMessage( &Msg ); DispatchMessage( &Msg ); }
ist so wesentlich kürzer
:
while (GetMessage( &Msg, NULL, 0, 0 )) { TranslateMessage( &Msg ); DispatchMessage( &Msg ); }
Außerdem steht der Exit-Code nicht in lParam, sondern in wParam.
kurz, es muss:return (Msg.wParam);
heißen.
-
Den Code hab ich aus einem alten Projekt rauskopiert, brauchte ja nur schnell ein Beispielprogramm
Das mit dem casten finde ich gar nicht schlimm. Gut, Pointer als ID sind nicht unbedingt empfehlenswert, aber sind (unter Win32 jedenfalls) auch 32-Bit Werte. Die meisten Konstanten, die man gebraucht sind auch 32-Bit Werte und die Timer-ID ist auch ein 32-Bit-Integer.
Ich kann mich auch nie wirklich entscheiden, ob ich ints oder longs nehmen soll. Ints waren für mich immer der Inbegriff für 32-Bit-Werte, aber sind ja leider vom System abhängigAlso nehme ich nur noch longs. Außer vielleicht in schnell geposteten Beispielen
Naja, aber ich habe mal in einem kleineren Projekt so mittels der Timer-IDs Parameter übergeben, und ich sah keine Probleme. Ich finde es übersichtlich und simpel.
Man weiß halt, dass man als Timer-ID einen Wert übergibt und dieser in der WM_TIMER als Parameter übergeben wird. Solange man den Überblick hat und auf Null- bzw. gleiche Parameter achtet, sollte nichts schiefgehen.
Das ist vielleicht nicht für Anfänger zu empfehlen, aber in manchen Situationen kann es durchaus Arbeit und unübersichtliches drumherum-coden ersparen.Meine Meinung...
Edit: Ich habe gerade mal nachgeschaut, was das für ein Projekt war:
Habe eine Klasse CTrayIcon geschrieben, in der das Icon u.a. auch blinken kann. Dafür habe ich einen Timer erstellt, der in der TimerProc (static in den Klasse) bearbeitet wurde. Als ID dann den this-Pointer genommen. In der TimerProc die ID zum CTrayIcon*-Pointer umgewandelt und damit gearbeitet. Wäre auf jeden Fall umständlicher geworden, wenn ich das versucht hätte, anders zu lösen. Wüsste spontan gar nicht, wie
-
Badestrand schrieb:
Das ist vielleicht nicht für Anfänger zu empfehlen, aber in manchen Situationen kann es durchaus Arbeit und unübersichtliches drumherum-coden ersparen.
Meine Meinung...
Hm ich versteh dich zwar...aber das hat ja nichts mit Anfängern zu tun...