Vordergrund / Hintergrund zeichnen
-
Hey alle ;)!
Beim testen / rumprobieren ist mir aufgefallen, das ich z. B. nicht noch einmal was in das Fenster hinein zeichnen kann, ohne das ich vorher InvalidateRect() benutzte, wobei ich bei der Funktion den letzten Parameter auf TRUE setzen muss, damit der Hintergrund (!) neu gezeichnet wird!
Was ich daran nicht ganz versteh ist: Was ist der unterschied zwischen Hintergrund und Vordergrund (bei einem Fenster) und wie zeichne ich in den Vordergrund (ohne den Hintergrund neu zu zeichnen)? Kann ich auch ohne WM_PAINT zu senden etwas reinzeichnen (Vordergrund dann w*****einlich?!) ??Danke im voraus für eure Mühe!!!!!!
-
Windows zeichnet für den Hintergrund einfach das, was du in WNDCLASS(EX) bei hbrBackground angegeben hast, wenn du InvalidateRect() mit TRUE als letzten Parameter aufrufst (damit ist dein Fenster wieder leer - nur der Hintergrund ist da).
Ansonsten zeichnest du in WM_PAINT halt einfach immer wieder über das drüber, was schon da ist.
Du kannst zwar auch außerhalb von WM_PAINT etwas zeichnen (GetDC & ReleaseDC), aber dies ist meist nicht sinnvoll. Was hält dich davon ab, in WM_PAINT zu zeichnenPS: Eigentlich gibt es nichts sowas wie Hintergrund und Vordergrund, außer dass Windows eben deine Zeichenfläche mit dem Angegebenen Backgroun-Brush vollmalt.
[ Dieser Beitrag wurde am 29.06.2003 um 14:02 Uhr von flenders editiert. ]
-
Ansonsten zeichnest du in WM_PAINT halt einfach immer wieder über das drüber, was schon da ist.
Das hat mich auf den richtigen Weg gebracht
!
Danke sehr flenders !!!!
Aber:
case WM_PAINT: hDc = BeginPaint(hWnd, &ps); // zeichne irgendwas if(/*irgendeine Anbfrage die noch NICHT true ist*/) // zeichne irgendwas EndPaint(hWnd, &ps); return 0;
Wenn ich nun die Funktion
SendMessage(hWnd, WM_PAINT, NULL, NULL);
aufrufe und vorher die Abfrage von oben auf true setze, werden die Anweisungen unter der Bedingung ausgeführt aber nicht gezeichnet.
Wenn ich die Funktion
InvalidateRect(hWnd, &rect, true);
benutze und wieder die Abfrage vorher auf true setze, wird der Code unter der Anweisung ausgeführt und auch gezeichnet... versteh ich nicht ;)!
-
Was verstehst du unter
ausgeführt aber nicht gezeichnet
Du siehst natürlich, wenn du die Zeichenfläche vorher nicht löscht nicht, dass er nochmal drüberzeichnet, weil es ja schon da ist
-
Ich mein damit, das ich es überprüft habe und er zumindest die Anweisungen in der Bedingung nicht übergeht .. hab das mit ner MessageBox() "überprüft"!
Aber das was die Funktionen bewirken sollen bzw. zeichnen, sieht man halt leider nicht .. hmm kann das vielleicht sein das das dann hinter die Hintergrundfarbe gezeichnet wird :)? Überzeichnet wirds zumindest von nichts anderem!
-
Anweisungen in der Bedingung
Es wird immer konfuser
Wenn du noch weitere Hilfe brauchst solltest du mal konkreten Code posten
-
Mit den "Anweisungen" mein ich die versch. Funktionen, die von der Bedingung abhängig sind .. also die, die ausgeführt werden wenn die Bedingung true ist.
case WM_PAINT: hDc = BeginPaint(hWnd, &ps); // zeichne irgendwas if(/*irgendeine Abfrage die noch NICHT true ist*/) // zeichne irgendwas <- "Anweisungen in der Bedingung" .. schlecht // Ausgedrückt! Die MessageBox die ich hier Testweise eingefügt // hatte wurde ausgeführt! EndPaint(hWnd, &ps); return 0;
Im mom. schlag ich mich noch mit einem anderen Prob rum .. lol!
Wenn ich einen Timer (SetTimer()) hab, der bei jedem Aufruf InvalidRect() (im case WM_TIMER) aufruft passiert nix (der sollte etwas bewegen .. z. B. so ein Menü das dann schön sichtbar / langsam in der Seite verschwindet), sondern erst wenn der Timer zerstört ist.
Und ich find den verdammten Fehler nicht .. lol!
-
hast du auch eine Variable, die du bei WM_TIMER veränderst und deren Status du dann in WM_PAINT abfragst, oder wie hast du versucht das zu lösen?
Poste doch bitte mal konkreten Quellcode. Nur anhand von irgendeinem Pseudocode kann ich dir wie schon gesagt nicht weiterhelfen
-
Original erstellt von <CyberCraCk>:
**Das hat mich auf den richtigen Weg gebracht!
Wenn ich nun die Funktion
SendMessage(hWnd, WM_PAINT, NULL, NULL);
aufrufe und vorher die Abfrage von oben auf true setze, werden die Anweisungen unter der Bedingung ausgeführt aber nicht gezeichnet.
Wenn ich die Funktion
InvalidateRect(hWnd, &rect, true);
benutze und wieder die Abfrage vorher auf true setze, wird der Code unter der Anweisung ausgeführt und auch gezeichnet.
**Nein nein nein!
Du sollst nicht WM_PAINT an Dein Fenster senden! Das macht Windows, sobald Du InvalidateRect() aufrufst!
Nicht selber WM_PAINT senden!
-
Hmm, ok dachte das der "Pseudocode" (wie du das nennst ;)) besser wäre da man sich nicht großartig "einlesen" muss!!
Ich bitte darüber nicht zu lachen
.. ich bin noch Anfänger und probier deshalb nur rum ;)! Soll sowas wie "Ping Pong" werden lol.
Ausn Quellcode entnommen:
case WM_PAINT: { if(Zahl == 1) // soll nur einmal ausgeführt werden { lPosition = rect.bottom / 2 - 16; rPosition = rect.bottom / 2 - 16; Zahl = 2; } hDc = BeginPaint(hWnd, &ps); MoveToEx(hDc, rect.left + 20, lPosition, NULL); LineTo(hDc, rect.left + 20, lPosition + rect.bottom / 10 + 10); MoveToEx(hDc, rect.right - 20, rPosition, NULL); LineTo(hDc, rect.right - 20, rPosition + rect.bottom / 10 + 10); if(Zahl == 3) // die besagte Bedingung, die ich in einem anderen // Teil des Codes auf true setzte also "Zahl = 3;" { SelectObject(hDc, GetStockObject(DC_BRUSH)); SetDCBrushColor(hDc, RGB(0, 0, 0)); Ellipse(hDc, punkt.x, punkt.y, punkt.x + 10, punkt.y + 10); } // die Funktionen in der Bedingung werden nur mit InvalidateRect() // gezeichnet (die Ellipse), mit SendMessage(hWnd, WM_PAINT, NULL, // NULL) wird das nicht gezeichnet, zumindest nicht sichtbar EndPaint(hWnd, &ps);
Also, das Problem mit SetTimer() hab ich mittlerweile gelöst woraufhin ein neues entstanden ist, was ich mir wirklich überhaupt nicht erklären kann, weil es irgendwie widersprüchlich ist ..!
Die WindowProc() wird ja bei jeder Message wie z. B. WM_TIMER neu aufgerufen .. aber warum werden die Variablen die am Anfang dieser Funktion deklariert sind nicht wieder zurück gesetzt (auch wenn sie sofort / nicht sofort deklariert werden)? (bei mir zumindest nicht)
In WM_TIMER hab ich nun eine eigene Klasse benutzt die ich am Anfang der WindowProc() deklariert hatte. Mein Problem war, das die Variablen die in der Klasse durch den Konstruktor initialisiert werden, gleich beim ersten Aufruf von WM_TIMER wieder zurück gesetzt werden, also neu initialisiert woraufhin der veränderte Wert verloren ging.
Wieso werden Klassen anscheinend neu initialisiert und Variablen nicht??#include "Punkt.h" LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { // ... Punkt punkt; // ... case WM_CHAR: switch(wParam) { case 's': Zahl = 3; punkt.x = rect.right; // diese beiden werden wieder punkt.y = rect.bottom; // zurück gesetzt SetTimer(hWnd, NULL, 50, (TIMERPROC) NULL); return 0; } // ... case WM_TIMER: punkt.MovePoint(hWnd, &rect); if(punkt.x > rect.right) // Timer wird zerstört beim überschreiten KillTimer(hWnd, NULL); // der Fensterbreite return 0; // ist nur ein verkürzter und abgeänderter Ausschnitt // ... } class Punkt // eigene Klasse { public: // alles Public int x; // Variablen die beim ersten Aufruf von int y; // WM_TIMER zurückgesetzt werden int SetMoveX; int SetMoveY; Punkt() : x(1), y(1), SetMoveX(-1), SetMoveY(1) // initialisierung { } bool MovePoint(HWND hWnd, RECT* rect) // Methode für { // Positionsveränderung der Ellipse x = x + 1 * SetMoveX; y = y + 1 * SetMoveY; InvalidateRect(hWnd, rect, true); // da SendMessage() nicht // funktioniert return true; } };
So ich hoffe das ich nix vergessen hab und man jetzt alles nachvollziehen kann .. ist ein bisschen lang geworden aber es ging nicht anderst! Ich habs auch noch teilweise verkürzt und unnötiges weggelassen!!
-
Uhhh .. bin schon ganz durcheinander .. mir ist heiß und mein Gehirn brutzelt!!
Also, das Schlüsselwort "static" hab ich davor vergessen! Dennoch hab ich es überprüft und ich konnte punkt.x und punkt.y verändern (siehe oben quellcode) die beim ersten Aufruf, wie gesagt, wieder zurück gesetzt werden!!
-
Original erstellt von <CyberCraCk>:
Dennoch hab ich es überprüft und ich konnte punkt.x und punkt.y verändern (siehe oben quellcode) die beim ersten Aufruf, wie gesagt, wieder zurück gesetzt werden!!Verstehe nicht so ganz was du meinst
x(1), y(1), SetMoveX(-1), SetMoveY(1)
Kann man Variablen auch so einen Wert zuweisen
oder hast du mich jetzt auch schon angesteckt mit dem "Durcheinander sein"
-
Hmm, ich habs nicht anderst gelernt .. lol!
In meiner Dokumentation steht drin, das dies die schneller Art und Weise ist, um Variablen in einer Klasse zu initialisieren! Aber irgendwas (Ausnahmefall) .. was ich vergessen hab .. musste man dabei beachten ;)!
Die Klasse hab ich üprigens 1zu1 ausn Quellcode kopiert und lässt sich compilieren!Also, wenn ich
Punkt punkt;
ohne static davor schreib, kann ich durch punkt.x die Variable verändern die aber dann beim ersten WM_TIMER durchlauf schon wieder zurück gesetzt ist .. wenn ich das so
static Punkt punkt;
deklariere funktioniert alles einwandfrei ;)!
-
Dann läuft jetzt alles wi gewünscht?
-
Also Ping Pong funktst!! lol
Willst eine Version davon?
Ne, es läuft jetzt alles wie gewünscht! Nur ..
Gibt es eine bessere Möglichkeit als "static" zu benutzen?
<- ich denk mal die Antwort werd ich über suchen schon findenAuf jedenfall Danke dir flenders !!!! und auch ein Danke an Hepi