[c++] WINAPI Anwendung gerät aus der Form

radazong

Mitglied
Hallo!
Also, um gleich auf mein Problem zu sprechen zu kommen:

Ich habe eine Winapi-Anwendung, bei der durch Drücken eines Buttons(bzw. Menüauswahl) durch die "MoveWindow()-Funktion" die Größe des Hauptfensters geändert wird.
Nun ist es so, dass dies auch einwandfrei funktioniert, bis man den Knopf zu oft/schnell (Hab ich noch nicht wirklich rausgefunden) drückt. Dann verliert das Fenster seine Titelleiste, und seinen Rahmen, nimmt eine willkürliche Größe an und verteilt seine Child-Elemente auf dem Desktop.
Ich hatte dieses Problem schonmal, da ging es aber nicht um Größenänderung, sondern um häufiges Neuzeichnen der Client-Area (Kleines Paint mit SetPixel() usw.).

Jetzt könnte man ja meinen, dass mein Compiler sch**ße implementiert sei, oder irgendwo in meiner IDE der Wurm drin ist- Jedoch habe ich das Paint mit dem Borland C++BuilderX und dem BorlandCompiler erstellt, und das oben genannte mit DevC++ und dem gcc Compiler.

Gibt es bei der Programmierung irgendetwas spezielles zu beachten, oder muss ich als Hobby-er mit solchen Mängeln leben?
Ich bin noch nicht ganz grün mit der WindowsProgrammierung - habe bisher alles aus dem Buch "Spieleprogrammierung mit DirectX" und einigen Online-Tutorials. Habe mir zwar den Petzold gegönnt, habe jedoch noch andere C++ Lektüre und wollte nicht alles durcheinander lesen ;).

Also, ich bin für jede Hilfe dankbar und hoffe auf viele hilfreiche Antworten

Greetz,

RadaZOng
 
Zeig doch mal den Codeschnipsel, der das MoveWindow aufruft. Eine Beispielanwendung mit vollem Code wäre auch hilfreich. Vor allem auch die WindowProc.
 
Hallo!
Klar doch, hab ich garnicht dran gedacht. Hier die MoveWindow Funktion:
C++:
case IDI_GRAPHICS: if(show==true)
                                {
                                 MoveWindow(hWnd,PosX,PosY,310,410,TRUE);
                                 show=false;
                                 break;
                                }
                                 else
                                {
                                  MoveWindow(hWnd,PosX,PosY,310+230,410,TRUE);
                                  show=true;            
                                }
                            InvalidateRect(hWnd,0,TRUE);
                            SendMessage(hButton,WM_LBUTTONDOWN,0,0);
                            SendMessage(hButton,WM_LBUTTONUP,0,0);
break;

Also, die show-Variable ist bloß ein boolscher Wert, der den aktuellen Status des Fensters zurückgibt - ist sie true, so wird der gesamte Fenster-Bereich gezeigt, sonst nicht.
PosX und PosY fange ich in der WM_MOVE Nachricht, diese enthalten die aktuelle Position des Fensters.

Die WM_LBUTTONDOWN und -UP Nachricht sende ich, da in dem versteckten Bereich an einer bestimmten Position ein Kreis gezeichnet werden soll, der sonst nach dem aufdecken des versteckten Bereiches aus irgendeinem Grund nicht sichtbar ist.

Die ganze WndProc möchte ich eigentlich nicht posten. Der case "IDI_GRAPHICS" ist eine Reaktion auf eine Menüauswahl, die durch eine Rescource definiert wurde und in WM_COMMAND gefangen wird.
Wie gesagt funktioniert dies ja auch eine ganze Weile, bloß mit einem Mal verschwinden bei meinen Editfeldern Rahmen, die Edits erscheinen irgendwo in den Bildschirmecken, Die Titelleiste und der Rahmen des Hauptanwendungsfensters verschwinden gänzlich.


Ich hoffe, dass diese Infos ausreichen und hoffe weiter auf hilfreiche Antworten.

Greetz,

RadaZOng
 
Zuletzt bearbeitet von einem Moderator:
Da paßt irgendetwas ganz und gar nicht. Das mit WM_LBUTTONDOWN und -UP würde ich schnellstmöglich wieder loswerden. Die beiden Nachrichten sind nicht wirklich zum selbst Rumsenden gedacht. Vor allem stimmen ja auch die beiden Parameter nicht.

Wird durch den Buttondruck wiederum irgendetwas ausgelöst?


Das da etwas eine Weile funktioniert, und dann plötzlich nicht mehr, klingt nach einem Resourcen-Problem. Prüf mal, ob du bei der Darstellung alle Handles wieder sauber freigibst.
 
Huch, nicht?!
Naja, wenn ich das Fenster vergrößern würde ohne diese Nachrichten zu schicken, würde der dann sichtbar werdende Bereich aus irgendeinem Grund nicht mehr neu gezeichnet. Selbst mit InvalidateRect() nicht.
Mit diesen Funktionen jedoch klappt es.

Ich weiss gerade nicht so recht, wie du das mit dem Handle freigeben meinst

MfG,

RadaZOng
 
Hello again! Erstmal sorry, es ist nicht meine Absicht die Frage zu pushen.
Aber ich muss doch loswerden, dass scheinbar alles im Lot ist, seitdem ich die LBUTTONDOWN und -UP Messages rausgenommen habe.
Ich weiss zwar nicht was ich letztes mal falsch, oder dieses mal richtig gemacht habe, jedoch funktioniert nun auch das zeichnen in dem aufzudeckenden Bereich einwandtfrei.

Ich mache noch einige kleine Belastungstests um ganz sicher zu gehen, so lange lasse ich die Frage nochmal offen.

Vielen Dank auf jeden Fall für deine Hilfe.
Greetz,

RadaZOng
 
Hallo, ich nochmal.
Ich war wohl etwas voreilig, das Problem besteht weiterhin, jedoch nicht so häufig. Ich bin wirklich ratlos wie das passieren kann....die Anwendung funktioniert bsplw. 10 Minuten tadelos, und dann "verläuft" alles über den ganzen Desktop^^....

Ich habe doch auch zu keiner Zeit versucht direkt auf dem Desktop zu zeichnen oder den als Parent zu setzen.

Greetz,

RadaZOng
 
Das muss nicht direkt mit dem Desktop zu tun haben.

Zeig mal deinen Paint-Code. Gibst du alle HDCs wieder richtig frei? Stellst du auch die alten GDI-Objekte wieder zurück (SelectObject)?
 
Hallo!
Also, ich gebe den DC nach dem Zeichnen ganz normal mit EndPaint frei. Mehr DCs habe ich nicht am laufen. Eventuelle Brushes und Pens gebe ich nachher auch ordentlich mit DeleteObject frei. Hier mein Code:
C++:
case WM_PAINT:    hDC=BeginPaint(hWnd,&ps);
                      
                      if(show)
                      {
                      SelectObject(hDC,bg);
                      TextOut(hDC,30+374,30,"- 0° +",6);
                      TextOut(hDC,30+366,255,"- 180° +",8);
                      
                      val=100.0/value;
                      
                      TmpX=XPt*val;
                      TmpY=YPt*val;
                      
                      Ellipse(hDC,320,50,520,250);
                      SelectObject(hDC,pt);
                      Ellipse(hDC,410-(int)TmpY,140-(int)TmpX,430-(int)TmpY,160-(int)TmpX);
                      sprintf(Gradval,"%d°",(int)degree);
                      TextOut(hDC,410-(int)TmpY,120-(int)TmpX,Gradval,strlen(Gradval));
                      
                      DeleteObject(bg);
                      DeleteObject(pt);
                      }
                      
                      EndPaint(hWnd,&ps);
                      
    break;

So, die Variablen TmpX und -Y sind nur da, um die Koordinaten auf einem Kreis zu berechnen, und diese Stelle zu markieren(t auch). Naja, und die Zeichenoperation habe ich in die if(show) Bedingung gesetzt, damit alles auch nur gezeichnet wird, wenn man die Grafik auch anzeigen lassen will. Begin- und EndPaint habe ich dabei außen vor gelassen, weil sonst meine Childs irgendwie nicht richtig gezeichnet werden würden ^^.

Sonst gibt es dazu glaub ich nicht weiter viel zu sagen. Ich hoffe, das hilft dir dabei mir zu helfen, hrhr.

Greetz,

RadaZOng
 
Zuletzt bearbeitet von einem Moderator:
Hallo,

"DeleteObject" ist nur die halbe Miete. Wenn mit "SelectObject" irgendwelche Objekte gewählt werden, muss am Ende wieder das Ursprungsobjekt eingesetzt werden:
C++:
 // Sicherung des Ursprungsobjektes beim ersten Aufruf von SelectObject
HGDIOBJ hgdiOrg = SelectObject( hDC,  ... );

// ...

 // Wiederherstellen des Ursprungsobjektes
SelectObject( hDC,  hgdiOrg );
Gruß
MCoder
 
Zurück