Programmprozess schließt sich nicht
-
Hallo ich hab folgendes Problem:
Wenn ich mein Programm debugge und es danach wieder schließe, dann beendet sich der Debugger nicht und ich muss es manuell erledigen. Ich hab das Programm einmal zum Test als EXE geöffnet und ich guckte im Taskmanager nach dem Prozess. Als ich den Prozess gefunden hatte, hab ich das Programm geschlossen und ich sah, dass der Prozess sich nicht geschlossen hat. Kann mir jemand sagen wieso? Ist ein Fehler in meinem Code?
Main
#include <d3d9.h> #include <d3dx9.h> #include "CDirect3D.h" CDirect3D Direct3D; // ************************************************************************************* // Window Procedure // ************************************************************************************* LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { switch(Msg) { case WM_KEYDOWN: switch(wParam) { case VK_ESCAPE: DestroyWindow(hWnd); break; } case WM_PAINT: { Direct3D.BeginScene(); Direct3D.DrawTextA("Text1", 50, 10, D3DCOLOR_XRGB(0xFF, 0, 0)); Direct3D.DrawTextA("Text2", 50, 30, D3DCOLOR_XRGB(0, 0, 0xFF)); Direct3D.EndScene(); break; } case WM_QUIT: return 0; break; case WM_DESTROY: PostQuitMessage(0); return 0; break; } return DefWindowProc(hWnd, Msg, wParam, lParam); } // ************************************************************************************* // Funktion zum Erstellen eines Standardfensters // ************************************************************************************* HWND CreateStdWnd(HINSTANCE hInstance, LPCSTR lpszClassName) { // Member initialisieren WNDCLASSEX w; w.cbClsExtra = NULL; w.cbSize = sizeof(WNDCLASSEX); w.cbWndExtra = NULL; w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); w.hCursor = NULL; w.hIcon = NULL; w.hIconSm = NULL; w.hInstance = hInstance; w.lpfnWndProc = WndProc; w.lpszClassName = lpszClassName; w.lpszMenuName = NULL; w.style = NULL; RegisterClassEx(&w); // Registrieren der Fensterklasse // Fenster erzeugen HWND hWnd = CreateWindowEx(WS_EX_CLIENTEDGE, lpszClassName, "Fenstertitel", WS_OVERLAPPEDWINDOW | WS_VISIBLE, NULL, NULL, 800, 600, NULL, NULL, hInstance, NULL); if(hWnd == 0) MessageBox(NULL, "Fehler beim Erzeugen eines Fensters!", "Allgemeiner Fehler", MB_OK | MB_ICONERROR); return hWnd; } // ************************************************************************************* // Main-Funktion // ************************************************************************************* int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR CmdLine, int CmdShow) { HWND hWnd1 = CreateStdWnd(hInstance, "WndClass1"); MSG Msg; if(!Direct3D.Init(hWnd1)) { return -1; } Direct3D.SetClearColor(D3DCOLOR_XRGB(0, 0, 0)); Direct3D.CreateFontA(); while(GetMessage(&Msg, hWnd1, NULL, NULL)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } Direct3D.CleanUp(); return 0; }
CDirect3D
#include <d3d9.h> #include <d3dx9.h> class CDirect3D { protected: LPDIRECT3D9 m_lpD3D; // Direct3D Objekt LPDIRECT3DDEVICE9 m_lpD3DDevice; // Direct3D Device (Gerät) LPD3DXFONT m_lpD3DFont; // Direct3D Schrift LPDIRECT3DSURFACE9 m_lpD3DSurface; // Direct3D Surface D3DCOLOR m_ClearColor; //Backbufferfarbe public: // Standardkonstruktor CDirect3D() : m_lpD3D(NULL), m_lpD3DDevice(NULL), m_lpD3DFont(NULL), m_ClearColor(NULL) { } //Destruktor virtual ~CDirect3D() { CleanUp(); } // Direct3D initialisieren BOOL Init(HWND hWnd, BOOL bWindowed = TRUE) { m_lpD3D = Direct3DCreate9(D3D_SDK_VERSION); if(m_lpD3D == NULL) return FALSE; D3DPRESENT_PARAMETERS pParam; ZeroMemory(&pParam, sizeof(pParam)); pParam.SwapEffect = D3DSWAPEFFECT_DISCARD; pParam.hDeviceWindow = hWnd; pParam.Windowed = bWindowed; pParam.BackBufferWidth = 800; pParam.BackBufferHeight = 600; pParam.BackBufferFormat = D3DFMT_A8R8G8B8; if(FAILED(m_lpD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &pParam, &m_lpD3DDevice))) return FALSE; return TRUE; } // Leeren der Direct3D-Objekte void CleanUp(void) { if(m_lpD3DDevice != NULL) { m_lpD3DDevice->Release(); m_lpD3DDevice = NULL; } if(m_lpD3D != NULL) { m_lpD3D->Release(); m_lpD3D = NULL; } } // Schrift erstellen void CreateFont(void) { D3DXFONT_DESC FontDesc = { 0 }; strcpy_s(FontDesc.FaceName, "Arial"); D3DXCreateFontIndirect(m_lpD3DDevice, &FontDesc, &m_lpD3DFont); } // Setze Backbuffer-Farbe void SetClearColor(D3DCOLOR Color) { m_ClearColor = Color; } // Text ausgeben void DrawText(LPCSTR Text, int x, int y, D3DCOLOR TextColor) { RECT r = { x, y, 0, 0 }; m_lpD3DFont->DrawTextA(NULL, Text, -1, &r, DT_CALCRECT, TextColor); m_lpD3DFont->DrawTextA(NULL, Text, -1, &r, DT_CENTER, TextColor); } void BeginScene(void) { m_lpD3DDevice->Clear(0, 0, D3DCLEAR_TARGET, m_ClearColor, 0, 0); m_lpD3DDevice->BeginScene(); } void EndScene(void) { m_lpD3DDevice->EndScene(); m_lpD3DDevice->Present(0, 0, 0, 0); } };
-
case WM_CLOSE -> DestroyWindow
-
Das lustige ist, dass es bei nem anderen Programm ohne dem funktioniert
-
Dann zeig doch mal ein Beispiel davon.
-
Also ich hab es mal ausprobiert und der Prozess beendet sich trotzdem nicht
-
Bei GetMessage im zweiten Parameter NULL angeben.
-
hwnd=> schrieb:
Bei GetMessage im zweiten Parameter NULL angeben.
Dan würde ich aber doch nicht auf Nachrichten eingehen können oder nicht? Also den Fehler hab ich gefunden ->
while(GetMessage(&Msg, hWnd1, NULL, NULL) > NULL) { TranslateMessage(&Msg); DispatchMessage(&Msg); }
das "> NULL" hat schlicht gefehlt
-
Dann solltest du Micorsoft mitteilen, dass deren Dokumentation wohl fehlerhaft ist:
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0) { if (bRet == -1) { // handle the error and possibly exit } else { TranslateMessage(&msg); DispatchMessage(&msg); } }
Quelle: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx
-
Wieso ist die Doku falsch?
Es ist doch dokumentiert, dass bei Angabe von hWnd nur Nachrichten bzgl. dieses Fensters gelesen werden...
-
case WM_CLOSE : PostQuitMessage(0); break;
PostQuitMessage sendet WM_QUIT und GetMessage liefert 0 zurück.
Mit GetMessage war alles richtig.
Mit WM_CLOSE schlißt man den Fenster z.B. Dialogfenster.
usw.
-
Sigie schrieb:
case WM_CLOSE : PostQuitMessage(0); break;
PostQuitMessage sendet WM_QUIT und GetMessage liefert 0 zurück.
Mit GetMessage war alles richtig.
Mit WM_CLOSE schlißt man den Fenster z.B. Dialogfenster.
usw.Es ist defintiv nicht korrekt PostQuitMessage zu senden ohne das Main Fenster zu zerstören.
WM_CLOSE erhält die Aktion: DestroyWindow
Auf WM_DESTIY wird mit PostQuitMessage reagiert.Und mit WM_CLOSE schließt man schon keine Dialogfenster. Das macht man mit EndDialog... Ansonsten ist auch hier einfach DestroyWindow bei nicht modalen Fenster vorzuziehen.
Nur als Info: PostQuitMessage sendet definitv gar nichts! Es setzt ein Flag und daruf hin reagiert GetMessage mit WM_QUIT!