[C] GDI Problem...

Z

zAD

Gast
hallo,

meine GDI Funktion:
Code:
BOOL GdiTest(void)
{
	HDC hdc;

	hdc = GetDC(hwnd);

	TextOut(hdc, 100,100, "TEST", 4);

	ReleaseDC(hwnd, hdc);

	return TRUE;
}

Wenn die Funktion vor meiner Hauptschleife innerhalb der WINMAIN steht oder in der WM_PAINT Message gibt er den Text aus, stelle ich sie jedoch in die Hauptschleife funktioniert es nicht (gleiches passiert auch bei DirectDraw Funktionen, wenn ich die Onscreen Surface bearbeite)

die Hauptschleife:
Code:
   while (!blnBeenden) {

      while(GetMessage(&message,NULL,0,0))
	      { 
			TranslateMessage(&message);
			DispatchMessage(&message);
         } // GetMessage
      
      dwStartzeit = GetTickCount();

      switch(Spiel_Zustand) {
         case SPIEL_AUSWAHL:
            {
            Spiel_Zustand = SPIEL_START;
            } break;
         case SPIEL_START:
            {
            Spiel_Zustand = SPIEL_LAEUFT;
            } break;
         case SPIEL_LAEUFT:
            {
            GdiTest();
            } break;
         case SPIEL_NEUSTART:
            {
            Spiel_Zustand = SPIEL_START;
            } break;
         default: break;
         } // switch

      while ((GetTickCount() - dwStartzeit) < 40);
      } // Hauptschleife

Hab letztenendes eine Hauptschleife aus einem Tutorial genommen, weil ich nichtmehr weiter wusste - geht dennoch nicht...


Ich kann mir nicht erklären warum, da ich mit keinem PAINTSTRUCT arbeite sollten die Operationen doch auch außerhalb der WM_PAINT message funktionieren - was sie ja auch tuen nur nicht in der Schleife.


edit: blnBeenden = FALSE, Spiel_Zustand = SPIEL_AUSWAHL

mfg zAD
 
Zuletzt bearbeitet von einem Moderator:
Hmm... das klingt kniffelig. Ich würde vermuten, dass Du es an der Stelle dort nicht darfst. Ich bin mir nicht sicher, aber ich meine, dass man nur einen gültigen DC in der PaintMessage bekommen kann. :\ (aus welchem Grund sollte sich ein Formular sonst auch neu zeichnen...)
 
Hmm... das klingt kniffelig. Ich würde vermuten, dass Du es an der Stelle dort nicht darfst. Ich bin mir nicht sicher, aber ich meine, dass man nur einen gültigen DC in der PaintMessage bekommen kann. :\ (aus welchem Grund sollte sich ein Formular sonst auch neu zeichnen...)

Nur warum darf ich es vor der Hauptschleife aber nicht innerhalb? ist ja die gleiche Funktion. Die Hauptschleife hat ja keine andere Aufgabe als immer wieder ein Bild zu erstellen (o. Eingaben zu verarbeiten)...

Wenn man bei diversen WinAPI tutorials guckt findet man auch immer das
Code:
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint(hwnd, &ps);
[Zeichenoperationen mit diesem Kontext]
EndPaint(hwnd, &ps);
innerhalb der WM_PAINT Message benutzt werden MUSS, und
Code:
HDC hdc;
hdc = GetDC(hwnd);
[Zeichenoperationen mit diesem Kontext]
ReleaseDC(hwnd, hdc);
flexibel einsetzbar ist (auch außerhalb).


Habe vor meinem HDD Crash ja auch schon so weit gearbeitet gehabt, dass ich mit der GDI in der Hauptschleife gearbeitet hab....
 
Hm, das ist wirklich komisch. Hast Du mal die Ergebnisse von getDC mit GetLastError überprüft? Vielleicht passiert ja irgendetwas 'komisches'
 
edit:

also er scheint dauerhaft in der Nachrichtenverarbeitung festzuhängen. Wenn ich die ans Ende der Schleife setze durchläuft er sie bis zum Ende aber fängt nicht wieder von oben an. Alle Befehle hinter der Nachrichtenverarbeitung werden auch nicht bearbeitet...
 
Zuletzt bearbeitet von einem Moderator:
Mit was programmierst Du denn? MS VC?

Ich hatte ein ähnliches Problem, dass sich mein Programm in der Mainloop aufgehängt hatte. Allerdings lag es daran, dass es ein Service war und ich die MFC verwendet hatte, was sogar nach offiziellen Aussagen von MS nicht geht.
 
hi,

arbeite mit MS VC 6. ist ne Win32 Application. Also kein MFC o. Konsolenanwendung...


werde aber sobald ich zu Hause bin mal die Projektsettings durchchecken. Der Quellcode scheint aber fehlerfrei...



edit:

also es scheint alles richtig eingestellt zu sein. Er hängt weiterhin in geht weiterhin nicht über die Nachrichtenverarbeitung hinaus - nicht nur in diesem projekt.
 
Zuletzt bearbeitet von einem Moderator:
Hmmm so langsam bin ich auch planlos. Hmm was hast Du da eigentlich... eine Windowmessage-Queue oder eine Threadmessage-Queue?
 
moin :)
ich kann zwar nicht unbedingt c aber mit WinAPI kenn ich mich trotzdem ein bissel aus. könnte sich das hierbei nicht um eine "endlosschleife" handeln?

Code:
  while (!blnBeenden) {

      [b]while(GetMessage(&message,NULL,0,0))
      { 
TranslateMessage(&message);
DispatchMessage(&message);
         } // GetMessage[/b]

//das ist ein endlos loop bis das programm beendet wird, zumindest wenn das bei dir exakt genau so um prog. steht und nicht in der MessageProc.
      
      dwStartzeit = GetTickCount();

      switch(Spiel_Zustand) {
         case SPIEL_AUSWAHL:
            {
            Spiel_Zustand = SPIEL_START;
            } break;
         case SPIEL_START:
            {
            Spiel_Zustand = SPIEL_LAEUFT;
            } break;
         case SPIEL_LAEUFT:
            {
            GdiTest();
            } break;
         case SPIEL_NEUSTART:
            {
            Spiel_Zustand = SPIEL_START;
            } break;
         default: break;
         } // switch

      while ((GetTickCount() - dwStartzeit) < 40);
      } // Hauptschleife
 
LOL..... das stimmt! GetMessage gibt nur auf ein WM_QUIT 0 zurück :D
Manchmal ist man halt einfach mit Blindheit beschlagen :)
 
Hmm nunja, soll er aber nicht auch erst alle ankommenden Messages bearbeiten und dann die hinterstehenden Anweisungen ausführen?

Irgendwie müssen die Nachrichten ja dennoch verarbeitet werden können.

mfg zAD
 
Probier mal, GetMessage durch PeekMessage zu ersetzen:

PeekMessage (&message, hwnd, 0, 0, PM_REMOVE);

Wenn es keine Messages in der Queue gibt, wartet PeekMessage nicht so lange, bis eine Message ankommt, sondern gibt einfach 0 zurück. GetMessage dagegen gibt nur dann 0 zurück, wenn ein WM_QUIT empfangen wurde, also wenn sich die Anwendung eh terminieren soll.
 
Okay, PeekMessage geht einwandfrei =)

na dann kann ich ja nun weiter rumprobieren, dankö


mfg zAD
 
Du hast normalerweise eine Message Loop

Code:
while(GetMessage(&message,NULL,0,0))
{ 
    TranslateMessage(&message);
    DispatchMessage(&message);
} // GetMessage

DispatchMessage ruft dann deine WinProc auf, wo dann dein Message Switch drin steht. Wenn du eine eigene Window Class registrierst, kannst du einen Funktionszeiger zu dieser Proc mitgeben oder der Funktion CreateWindow().

Sinn von PeekMessage ist es eigentlich, Nachrichten aus der Warteschlange nur mal anzuschauen und dabei nicht zu warten ob wieder was ansteht. Das ist bei GetMessage anders. GetMessage legt den Window Thread halt so lange schlafen bis wieder ne Message ansteht. PeekMessage versucht so schnell es geht Nachrichten zu bekommen und wird in 99% keine Nachricht vorfinden wenn dus in so eine Schleife einbaust.
Der Nachteil dran ist, dass dein Rechner mit aktivem Warten (Polling) beschäftigt ist, anstatt den Thread einfach schlafen zu legen.

Schau dir noch ein paar Tutorials zu Win32 Programmierung bzw. Platform SDK / WinAPI Programmierung an, weils ansonsten sein könnte, dass du nicht das bekommst was du eigentlich willst oder erwartest.
 
Japp, da hast Du sicherlich recht. Nur für den Code da oben war PeekMessage ne quick and dirty Lösung *g*. Evtl. könnte man mal probieren, aus dem while ein if zu machen und wieder GetMessage einzusetzen. Bin mir aber nicht sicher, ob das nicht auch noch Nebenwirkungen haben wird.
 
ich würde es so lösen:

Code:
while(msg.message != WM_QUIT)
{
   //überprüfen ob eine Nachricht von windows da ist
   if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
   {
      //wenn ja weiter verarbeiten
      TranslateMessage(&msg);
      DispatchMessage(&msg);
   }
   else
   {
       // Hauptschleife
   }
}
 

Ähnliche Themen

Antworten
5
Aufrufe
2.660
R
Antworten
3
Aufrufe
1.528
Antworten
22
Aufrufe
2.701
Zurück
Oben