Programm "verstopft" Pc

alixander

Mitglied
Hi Leute,
ich bin grad dabei ein DirectDraw Prgramm zu schreiben. Da es mein erstes sein wird schreibe ich das meißte da bei aus einem Tutorial im Internet ab(für Interessierte:/www.codeworx.org)
Nun hab ich aber ein Problem wenn ich das Prgramm beende, durch Drücken der ESC-Taste dann versopft es meinen Pc, so dass mein Pc voll ausgelastet ist.Da muss ja irgentwas schief gelaufen sein, da ich aber noch ein Anfänger bin,weiß ich nicht was-Wäre nett wenn mir einer (oder alle) helfen würde. Hier ist der Code:
Code:
#include <windows.h>
#include <ddraw.h>

#define  WindowTitle      "DirectDraw-Tutorial"
#define  WindowClassName  "DDWinClass"

bool running;


	LPDIRECTDRAW7		lpDirectDraw;	// DirectDraw-Objekt
	LPDIRECTDRAWSURFACE7 lpddsPrimary; 
	LPDIRECTDRAWSURFACE7 lpddsBack;
	DDSURFACEDESC2		ddsd;
	DDSCAPS2			ddscaps;
	HRESULT				ddrval;
	DDBLTFX				ddbltfx;
	RECT				fill_area;
	




bool InitDDraw(HWND hwnd)
{
	ddrval = DirectDrawCreateEx(NULL, (VOID**)&lpDirectDraw, IID_IDirectDraw7, NULL); 
	if (ddrval != DD_OK)
	{
		return false;
	}
	
	ddrval = lpDirectDraw->SetCooperativeLevel (hwnd, DDSCL_EXCLUSIVE |	DDSCL_FULLSCREEN);
	if (ddrval != DD_OK)
	{
		lpDirectDraw->Release();
		lpDirectDraw = NULL;
		return false;
	}

	ddrval = lpDirectDraw->SetDisplayMode (800, 600, 8, 0, 0);
	if (ddrval != DD_OK)
	{
		lpDirectDraw->Release();
		lpDirectDraw = NULL;
		return false;
	}
	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
	ddsd.dwBackBufferCount = 1; 
	ddrval = lpDirectDraw->CreateSurface (&ddsd, &lpddsPrimary, NULL);
	if (ddrval != DD_OK)
	{
		lpDirectDraw->Release();
		lpDirectDraw = NULL;
		return false;
	}
	ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
	lpddsPrimary->GetAttachedSurface(&ddscaps, &lpddsBack); 

	

	return true;
}
void SpecialInit()
{
	ddbltfx.dwSize = sizeof(DDBLTFX);
	ddbltfx.dwFillColor = RGB(0, 0, 0);
	SetRect(&fill_area, 0, 0, 800, 600);
}
void ReleaseDDraw() //lert den speicher aus,wenn nötig
{
	if (lpDirectDraw != NULL)
	{
		lpDirectDraw->Release();
		lpDirectDraw = NULL;
	}
	if(lpddsPrimary!=NULL)
	{
		lpddsPrimary->Release();
		lpddsPrimary = NULL;
	}
	if (lpddsBack != NULL)
	{
		lpddsBack->Release();
		lpddsBack = NULL;
	}

}
LONG FAR WINAPI WndProc (HWND , UINT , UINT , LONG) ;

int WINAPI WinMain (HINSTANCE hInstance , HINSTANCE hPrevInstance , 
					LPSTR lpCmdLine , int nCmdShow)
{
	MSG      msg      ;  
	HWND     hwnd     ;   
	WNDCLASS wndclass ;
	
	if (!hPrevInstance)
    {
		wndclass.style         = CS_HREDRAW | CS_VREDRAW  ;
		wndclass.lpfnWndProc   = WndProc ;
		wndclass.cbClsExtra    = 0 ;
		wndclass.cbWndExtra    = 0 ;
		wndclass.hInstance     = hInstance   ;
		wndclass.hIcon         = LoadIcon (NULL , IDI_APPLICATION) ;
		wndclass.hCursor       = LoadCursor (NULL , IDC_ARROW)  ; 
		wndclass.hbrBackground = (HBRUSH)GetStockObject (LTGRAY_BRUSH)  ;
		wndclass.lpszMenuName  = NULL              ;
		wndclass.lpszClassName = WindowClassName ; 
		RegisterClass (&wndclass) ;    
	}
	hwnd = CreateWindow (WindowClassName , 
                         WindowTitle , 
                         WS_OVERLAPPEDWINDOW , 
			             CW_USEDEFAULT , 
						 CW_USEDEFAULT ,
                         CW_USEDEFAULT , 
                         CW_USEDEFAULT ,     
                         NULL , NULL , 
                         hInstance , NULL) ;     
	ShowWindow   (hwnd , nCmdShow) ;  
	UpdateWindow (hwnd) ;
	if(!InitDDraw(hwnd))
	{
		MessageBox(NULL,"Konnte DirectX nicht initialisieren","ERROR",MB_OK|MB_ICONEXCLAMATION);
		return 0;
	}
	SpecialInit();
	running=true;  

	while(running)
	{
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{ 
			if (msg.message == WM_QUIT) break;
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			lpddsBack->Blt(&fill_area, NULL, NULL, DDBLT_COLORFILL    | DDBLT_WAIT, &ddbltfx);
			while(lpddsPrimary->Flip(NULL, DDFLIP_WAIT) != DD_OK);

			
		}
		
	}
	

	return msg.wParam ;
}


LONG FAR WINAPI WndProc (HWND hwnd , UINT message , 
                         UINT wParam , LONG lParam) 
{ 
	switch (message)
	{
		case WM_DESTROY:
		{
			
			PostQuitMessage (0) ;
			
			return 0 ;
		} break;
		case WM_KEYDOWN:
			switch(wParam)
			{
			case VK_ESCAPE:
		
				PostMessage(hwnd,WM_CLOSE,0,0);
				//running=false;
				break;
			}break;
	} // switch (message)
	return DefWindowProc (hwnd , message , wParam , lParam) ;
} // WndProc
 
Was lastet den dein PC aus? Ist es dein eigenes Programm, daß auf volle Prozessorlast läuft oder wie?
Wenn es dein Programm ist, wo hängt es (mal mit dem Debugger durchsteppen). Evtl. produziert irgend ein falscher Aufruf von dir eine Endlosschliefe.
Ich habe zwar von DirectX keine Ahnung, aber du hast eine Funktion geschrieben: ReleaseDDraw() die wird nirgendwo aufgerufen?! Evtl. behebt das schon das Problem.

Gruß Homer
 
Also ich meinte dass das Programm den pc zu 99% auslastet(das kann ja eigentlich nicht sein, da ich einen wirklich aktuellen Pc hab);
Ich hab die ReleaseDDraw() Funktion nun hinter die while schleife getan, so dass beim beenden sie eigentlich aufgerufen werden sollte. Nun wenn man das Programm aber du Drücken des X-Button ,der oben rechts ist beendet, dann ist dass Programm immer noch als Prozess im Taskmanager zu sehen und laste den Pc weiterhin zu fast 100% aus.
Wieso? Ich hab es doch eigentlich beendet-Wenn man das Programm so beendet , dann wird doch die Message WM_DESROY aufgerufen, oder?
Da hab eigentlich alles so gemacht wie immer(bei normalen WinMain Programmen hat es auch immer geklatpp) . Was ist der Fehler?
mfg
 
Also ich habe meine Nachrichtenschleife immer so konstruiert, vielleicht hilft das ja:
Code:
while(!done)										
{
	if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))		
	{
		if (msg.message == WM_QUIT)					
		{
			done = true;								
		}
		else										
		{
			TranslateMessage(&msg);					
			DispatchMessage(&msg);					
		}
	}
	else											
	{	
		Run(); //an dieser Stelle einfügen, was pro Schleifendurchlauf passieren soll, oder halt in Funktion auslagern
	}
}

Die Schleife funktioniert auf alle Fälle.

Ansonsten zur Auslastung: Und wenn du ne Milliarde Ghz hast, der Rechner versucht immer alles so schnell auszuführen, wie er kann. Und wenn er dabei weder von Festplatte noch Grafikkarte noch Arbeitsspeicher behindert wird und alles schön aufeinander eingespielt arbeitet, dann kommt der Prozessor auf hundert Prozent, selbst wenn du nur ein Strichmännchen zeichnest.
Das das Programm nicht ordentlich beendet, ist mir nicht ganz klar, aber vielleicht liegt's ja an der Nachrichtenverarbeitung.
 
Also ich kann dir auch damit nicht weiterhelfen aber ich hab sowas in einem Programm was ich mir aus dem Petzold kopiert habe auch gehabt. Es zeichnet einfach wahllos Rechtecke unterschiedlicher Farbe übereinander und dabei stürzt der PC auch fast ab(musst manchmal 30 sec warten wenn du den Schließbutton drückst bis sich das Prog schliest) das Prog erzeugt auch 100% systemauslastung. Wird aber wahrscheinlich ein Problem mit einer Endlosschleife sein.
mfg Ero_Sennin
 
Hallo zusammen!

Was ist eigentlich das Problem? - Es wäre wirklich bedenklich, wenn das Programm NICHT die volle freie Prozessorzeit beanspruchen würde! Der Computer versucht nur das zu machen, was du ihm gesagt hast nämlich deine Spielschleife immer wieder unmittelbar hintereinander auszuführen!

Wenn es dich stört, dann sage doch dem Prozessor, dass er eine kleine Pause am Ende jedes Schleifendurchlaufs machen soll.
Code:
sleep(1);

Nur so am Rande: DirectX ist eine Multimedia-Bibliothek, die möglichst hardwareunabhängig und schnell sein soll. Wenn du später etwas komplexere DD( oder D3D?)-Anwendungen schreibst, wirst du dich über jedes Fitzelchen Rechenzeit freuen. Also sei froh, dass dir das System 99% der Prozessorleistung zur Verfügung stellt.

Übrigens hat Daniel Toplak recht: Du solltest deine ReleaseDDraw-Funktoin auch aufrufen! DirectX basiert auf dem COM, und dessen Objekte sollten stets "released" werden, damit keine internen Probleme auftreten!

Gruß
Johannes
 
Das Problem ist ja, dass das Programm nicht ordnungsgemäß beendet wird ! Und nur dann wirklich 99 % beanssprucht.
Wenn man durch deuggt kan man es schaffen, dass das Programm richtig geschlossen wird aber wenn man es normal startet nicht.
ich nehem mal an dass nach einem Release es passen müsste.
 
Wenn man in den Debugger rein schaut sieht man, dann dieser Code beim Beenden immer wieder durchlaufen wird:
Code:
004015E0   mov         esi,esp
004015E2   push        1
004015E4   push        0
004015E6   mov         edx,dword ptr [lpddsPrimary (0042accc)]
004015EC   mov         eax,dword ptr [edx]
004015EE   mov         ecx,dword ptr [lpddsPrimary (0042accc)]
004015F4   push        ecx
004015F5   call        dword ptr [eax+2Ch]
004015F8   cmp         esi,esp
004015FA   call        __chkesp (00401840)
004015FF   test        eax,eax
00401601   je          WinMain+215h (00401605)
00401603   jmp         WinMain+1F0h (004015e0)
kann jemand von euch Assembler?
---
Edit:
habe gerade festgestellt, dass das diese Zeile im Quellcode ist:
Code:
while(lpddsPrimary->Flip(NULL, DDFLIP_WAIT) != DD_OK);
Dann ist das Problem wohl, dass Flip(NULL; DDFLIP_WAIT) nie DD_OK zurückgibt, oder?
---
Edit2:
Das schlaueste wäre natürlich im tutorial aus dem du den Code hast nachzuschauen, wie es dort (richtig) gemacht wird ;-)
 
Zuletzt bearbeitet:
Danke erst mal für eure Antworten!
Ich hab alle Lösungsvorschläge mal ausprobiert, doch das Problem besteht immer noch. Ich habe auch mit sicherheit alles richtig aus dem Tutorial abgeschrieben-ich kann mir das einfach nicht erkären- vielleicht habt ihr noch ein Paar gute Tips für micht
mfg
 
Das Problem ist:
PostMessage(hwnd,WM_CLOSE,0,0);

Das Fenster wird geschlossen und danach hängt er scheinbar in :
while(lpddsPrimary->Flip(NULL, DDFLIP_WAIT) != DD_OK);

Beim Debuggen bin ich aber aufs break gekommen was strange ist.

Ersetze :
PostMessage(hwnd,WM_CLOSE,0,0);
durch
PostQuitMessage (0) ;
Ist zwar nich schön geht aber.
 
Zurück