PeekMessage

Thomasio

Erfahrenes Mitglied
Ich hatte mal das Problem, dass in einem loop der 100 mal das selbe Fenster neu zeichnen soll, das Fenster erst am Ende vom loop neu gezeichnet wird, weil die Message erst verarbeitet wird, wenn der loop durch ist.
Daraufhin hat mir jemand hier folgenden Tipp gegeben:

Code:
void MyFunction()
{

MSG msg;

for(int i = 0; i < 100; i++)
{

// berechne neuen Inhalt
// und das rect was neu zu zeichnen ist

InvalidateRect(MyChild,&rect,false);

// jetzt die Message verschicken, bevor der loop neu durchläuft

while(PeekMessage(&msg, hwnd, 0, 0, PM_NOREMOVE))
{
GetMessage(&msg, hwnd, 0, 0 );
TranslateMessage( &msg );
DispatchMessage( &msg );
}

}

return;

}

Damit dies aus jeder beliebigen Funktion heraus geht, habe ich das HWND vom MainWindow global gemacht, und erstmal keine Probleme, lief alles sauber.

Jetzt habe ich mein Programm etwas erweitert, es gibt jetzt timer und threads, die im Hintergrund werkeln, aber nichts, was das Fenster neu zeichnen würde, sollte sich also nicht ins Gehege kommen.
Dazu gibt es jetzt einen weiteren loop, der 4 mal hintereinander MyFunction() aufruft und der läuft nicht sauber.
Ich kann es nicht exakt reproduzieren, weil es nicht jedesmal passiert, aber so etwa jedes dritte Mal, wenn ich mache:

Code:
for(int i = 0; i < 4; i++)
{
MyFunction();
}

dann kommt von PeekMessage nur noch die Hälfte an, sprich er zeichnet das Fenster zwar immer wieder neu, aber statt 100 mal, nur 80 mal oder noch weniger.
Ich habe schon alles mögliche probiert, mit MessageBox() oder separatem debug-Fenster im Ablauf alle möglichen Variablen anzeigen lassen, aber da scheint immer alles ok zu sein.
Dabei tritt der Fehler um so häufiger auf, je weniger er für den Fensterinhalt berechnen muss, sprich je kürzer und damit schneller der loop läuft, desto öfter fehlen ein paar Peek´s.

Hat jemand eine Idee woran das liegen könnte, oder wie ich dem Fehler auf die Spur kommen könnte?
 
Jo, warum mischt du PeekMessage u. GetMessage? Das sollte nicht korrekt sein ;)

int (schon garnicht signed) ist wohl der falsche Datentyp zum hochzählen in dem Fall (das is aber nicht der Fehler ;) ) ... unsigned char würde reichen.
 
Über Feinheiten im Code brauchen wir nicht streiten, ich Anfänger bin zufrieden, wenn es erstmal läuft, besser machen kann ich es immer noch, wenn ich mal gelernt habe, wie es grundsätzlich funktioniert.

Derweil habe ich das Problem etwas weiter eingekreist.
Tatsächlich liegt es weder am loop noch am Peek, sondern am InvalidateRect() bzw. dem daraus resultierenden WM_PAINT.

Ich habe mir die Rückgabewerte von BitBlt() im case WM_PAINT des Child angeschaut, und festgestellt, dass BitBlt() Errors produziert, wenn es zu oft in zu kurzen Abständen aufgerufen wird.
Error Code ist entweder ERROR_INVALID_HANDLE oder ERROR_RESOURCE_TYPE_NOT_FOUND.
Was ich daran nicht verstehe ist, wie kann das handle mal valid sein und mal nicht, bzw. wie kann der resource type mal gefunden werden und mal nicht, wobei das scheinbar abhängig davon ist, wie schnell der Rechner ist, auf meinem Notebook, mit Core2Duo 1,67Ghz taucht der Fehler nie auf, auf meinem PC, PentiumD 3,4Ghz, sehr oft.
 
Naja du überspringt durch dein doppeltes Peek und Get ne Nachricht usw. also irrelevant is das bestimmt nicht :D
 
Peek schaut ob eine Message vorhanden ist, PM_NOREMOVE sorgt dafür, dass die Message bleibt wo sie ist.
Get holt die Message ab und liefert sie aus.

Davon abgesehen, nachdem ich das Problem jetzt weiter eingekreist habe, kann ich es auch ohne den loop reproduzieren.
Ich mache einfach im WndProc vom Child:

Code:
case WM_PAINT:
{

UINT myCounter = 0;
UINT ErrorCounter = 0;

PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);

HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmMem = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_irgendwas));
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem,hbmMem);
while(1)
{
myCounter++;

if(BitBlt(hdc, 0, 0, 50, 50, hdcMem, 0, 0, SRCCOPY) == 0)
{
ErrorCounter++;
}

if(ErrorCounter > 10 || myCounter > 1000)
{

std::stringstream s;
s << "In " << myCounter << " Durchläufen gab es " << ErrorCounter << " Errors";
MessageBox(NULL,s.str().c_str(),"Ergebnis",MB_OK);
break;
}

}

SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
DeleteObject(hbmMem);
EndPaint(hWnd, &ps);

return 0;
}
break;

Damit bekomme ich auf einem Core2Duo mit 1,67Ghz NULL Errors, auf einem PentiumD mit 3,4Ghz, nach Laune, meistens über 10 in etwa 500 Durchläufen.

Edit:
Ganz witzig wird das, wenn ich mache:
Code:
while(BitBlt(hdc, 0, 0, 50, 50, hdcMem, 0, 0, SRCCOPY) == 0)
{
continue;
}

Da wiederholt er bei Error den BitBlt, produziert nach wie vor Dutzende Errors, aber kommt auch nach 10000 Durchläufen immer mit 10000 fehlerfrei ausgeführten BitBlt() an.

Oder anders gesagt, ich sag BitBlt(..), Windows sagt INVALID_HANDLE, ich sag, machs nochmal, Windows sagt, alles ok.
Nach meiner Logik kann das handle auf die HDC aber nicht mal valid und mal invalid sein, solange ich im loop nichts am handle ändere.
 
Zuletzt bearbeitet:
Zurück