Viele Fehler: Speicherreservierung und GetWindowText



  • Hallo.

    Ich schreibe mal wieder an einem Windowsprogramm und ecke ständig mit kleinen Fehlern irgendwo an. Ich habe 2 Edit-Boxen, wo ich gerne jeweils einen Integer einlesen will.

    Mit GetWindowText lade ich das erst in einen Buffer und wandle das dann in einen int um. Das geht allerdings nicht, weil der Buffer nach GetWindowText wieder leer ist.

    Weiterhin habe ich noch einen Fehler beim Schließen des Programms. Da kommt eine Fehlermeldung:

    "Die Anwendung 0x00401e7b verweist auf den Speicher 0xccccccccc0. Der Vorgang read konnte nicht auf dem Speicher ausgeführt werden."

    Kann da mal bitte einer nachschauen, ob die Speicherreservierung auch richtig gemacht worden ist?

    Hier ist ersteinmal mein Programmcode soweit:
    Main.cpp

    # include <windows.h>
    # include <stdio.h>
    //# include "matrix.h" //Klasse mit der ich noch arbeiten will
    
    TCHAR szAppName[] = TEXT("Matrizen");
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    					LPSTR lpszCmdLine, int iCmdShow)
    {
    	HWND hwnd;
    	WNDCLASS wndclass;
    	MSG msg;
    
    	wndclass.style = CS_HREDRAW| CS_VREDRAW;
    	wndclass.cbClsExtra = 0;
    	wndclass.cbWndExtra = 0;
    	wndclass.lpfnWndProc = WndProc;
    	wndclass.hInstance = hInstance;
    	wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    	wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	wndclass.lpszMenuName = (NULL);
    	wndclass.lpszClassName = szAppName;
    	wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
    
    	if(!RegisterClass(&wndclass))
    	{
    		MessageBox(NULL, TEXT("Fehler: Programm setzt Unicode voraus."), szAppName, MB_ICONERROR);
    		return 0;
    	};
    
    	hwnd = CreateWindow (szAppName,
    						 szAppName,
    						 WS_CAPTION | WS_THICKFRAME | WS_OVERLAPPED | 
    						 WS_MINIMIZEBOX | WS_SYSMENU,
    						 100,
    						 100,
    						 500,
    						 500,
    						 NULL,
    						 NULL,
    						 hInstance,
    						 NULL);
    
    	ShowWindow(hwnd, iCmdShow);
    	UpdateWindow(hwnd);
    
    	while(GetMessage(&msg, NULL, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	};
    	return msg.wParam;
    };
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	HWND hEditM, hEditN, hButtonCreate, hGroupAdd;
    	HWND* hEditElements;
    	HDC hdc;
    	PAINTSTRUCT ps;
    	TCHAR buffer[4];
    	//matrix *mat;
    	static int ctr=0, m, n;
    	int i, j;
    
    	switch(message){
    		case WM_PAINT:
    			hdc = BeginPaint(hwnd, &ps);
    			TextOut(hdc, 50, 35, TEXT("Dimension:"),10); 
    			TextOut(hdc, 215, 35, TEXT("x"), 1);
    			EndPaint(hwnd, &ps);
    			return 0;
    		case WM_CREATE:
    			hButtonCreate = CreateWindow (TEXT("button"),
    										  TEXT("Matrix erstellen"),
    										  WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
    										  330, 30, 130, 30,
    										  hwnd, NULL, 
    										  ((LPCREATESTRUCT) lParam)->hInstance, NULL);
    
    			hGroupAdd =     CreateWindow (TEXT("button"),
    										  TEXT("Neue Matrix hinzufügen"),
    										  WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
    										  20, 10, 460, 60,
    										  hwnd, NULL, 
    										  ((LPCREATESTRUCT) lParam)->hInstance, NULL);
    
    			hEditM =        CreateWindow (TEXT("edit"), NULL, WS_CHILD | WS_BORDER | 
    										  WS_VISIBLE | ES_CENTER, 150, 35, 40, 20, hwnd, NULL,
    								          ((LPCREATESTRUCT) lParam)->hInstance, NULL);
    
    			hEditN =        CreateWindow (TEXT("edit"), NULL, WS_CHILD | WS_BORDER | 
    										  WS_VISIBLE | ES_CENTER, 250, 35, 40, 20, hwnd, NULL,
    								          ((LPCREATESTRUCT) lParam)->hInstance, NULL);
    			return 0;
    		case WM_DESTROY:
    			delete []hEditElements;
    			PostQuitMessage (0);
    			return 0;
    		case WM_COMMAND:
    			if(LOWORD(wParam)==GetWindowLong (hButtonCreate, GWL_ID) && 
    				HIWORD(wParam)==BN_CLICKED)
    			{
    				ctr++;
    
    				GetWindowText(hEditM, buffer, 3);
    				m=atoi(buffer);
    				GetWindowText(hEditN, buffer, 3);
    				n=atoi(buffer);
    
    				hEditElements = new HWND[m*n];
    				MessageBox(hwnd, buffer, szAppName, NULL); // buffer ist anscheinend leer
    				for(i=0;i<=m-1;i++){
    					for(j=0;j<=n-1;j++)
    					{	hEditElements[i*n+j] = CreateWindow
    											("edit",
    											 NULL,
    											 WS_CHILD | WS_BORDER | ES_CENTER | WS_VISIBLE,
    											 20+80*i, 180+30*j, 70, 20,
    											 hwnd, NULL,
    											 ((LPCREATESTRUCT) lParam)->hInstance, NULL);
    					};
    				};
    
    			};
    			return 0;
    	};
    	return DefWindowProc(hwnd, message, wParam, lParam);
    };
    

    Wäre toll wenn jemand den Fehler findet.

    Schonmal Danke.
    Gruß
    Max


  • Mod

    Der ganz Code macht doch keinen Sinn. Deine HWND Variablen sind lokale Variablen, die nur bis zur nächsten Nachricht überleben. Sprich nach WM_CREATE sind die wieder leer, und beim WM_COMMAND natürlich nciht zu gebrauchen.

    Vergib beim CreateWindow doch einfach IDs, dann kannst Du mit GetDlgItemCtrl Dir das entsprechende Handle jederzeit besorgen und auch prüfen von welchem Control die WM_COMMAND Nachricht kam.



  • Erstmal vielen Dank.

    Ich habe jetzt ersteinmal die EditFenster statisch gemacht und jetzt kann ich das auch ordentlich auslesen.
    Mit deinem Lösungsvorschlag mit GetDlgItemCtrl beschäftige ich mich später nochmal.

    Allerdings stürzt das Programm jetzt immer noch ab, wenn ich das Programm schließe oder auf den Button klicke und die Editfelder entwickeln lasse. Ich habe die Speicherreservierung auch im C-Stil mit calloc und delete vorgenommen, das macht aber keinen unterschied. Mich wundert nur, dass das manchmal irgendwie doch klappt, wenn ich z.B. grad neu gebootet habe.
    Weiß jemand was da falsch ist?


  • Mod

    Wo genau schmiert das Programm ab. Wie sieht Dein Code aus?

    AN dem Code, den Du hier gepostet hast, sehe ich kein Problem.

    Es gibt übrigens auch GetDlgItemInt!



  • Ich hab eine MessageBox eingeschoben, in die Zeile bevor der Fehler kommt.

    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	static HWND hEditM, hEditN;
    	HWND hButtonCreate, hGroupAdd;
    	HWND* hEditElements;
    	HDC hdc;
    	PAINTSTRUCT ps;
    	TCHAR buffer[4];
    	//matrix *mat;
    	static int ctr=0, m, n;
    	int i, j;
    
    	switch(message){
    		case WM_PAINT:
    			hdc = BeginPaint(hwnd, &ps);
    			TextOut(hdc, 50, 35, TEXT("Dimension:"),10); 
    			TextOut(hdc, 215, 35, TEXT("x"), 1);
    			EndPaint(hwnd, &ps);
    			return 0;
    		case WM_CREATE:
    			hButtonCreate = CreateWindow (TEXT("button"),
    										  TEXT("Matrix erstellen"),
    										  WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
    										  330, 30, 130, 30,
    										  hwnd, NULL, 
    										  ((LPCREATESTRUCT) lParam)->hInstance, NULL);
    
    			hGroupAdd =     CreateWindow (TEXT("button"),
    										  TEXT("Neue Matrix hinzufügen"),
    										  WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
    										  20, 10, 460, 60,
    										  hwnd, NULL, 
    										  ((LPCREATESTRUCT) lParam)->hInstance, NULL);
    
    			hEditM =        CreateWindow (TEXT("edit"), NULL, WS_CHILD | WS_BORDER | 
    										  WS_VISIBLE | ES_CENTER, 150, 35, 40, 20, hwnd, NULL,
    								          ((LPCREATESTRUCT) lParam)->hInstance, NULL);
    
    			hEditN =        CreateWindow (TEXT("edit"), NULL, WS_CHILD | WS_BORDER | 
    										  WS_VISIBLE | ES_CENTER, 250, 35, 40, 20, hwnd, NULL,
    								          ((LPCREATESTRUCT) lParam)->hInstance, NULL);
    			return 0;
    		case WM_DESTROY:
    			delete []hEditElements;
    			PostQuitMessage (0);
    			return 0;
    		case WM_COMMAND:
    			if(LOWORD(wParam)==GetWindowLong (hButtonCreate, GWL_ID) && 
    				HIWORD(wParam)==BN_CLICKED)
    			{
    				ctr++;
    
    				GetWindowText(hEditM, buffer, 3);
    				m=atoi(buffer);
    				GetWindowText(hEditN, buffer, 3);
    				n=atoi(buffer);
    
    				hEditElements = new HWND[m*n];
    
    				for(i=0;i<=m-1;i++){
    					for(j=0;j<=n-1;j++)
    					{	
    					MessageBox(hwnd, TEXT("Genau danach kommt dann die Fehlermeldung"), szAppName, NULL);						
    						hEditElements[i*n+j] = CreateWindow
    											("edit",
    											 NULL,
    											 WS_CHILD | WS_BORDER | ES_CENTER | WS_VISIBLE,
    											 20+80*i, 180+30*j, 70, 20,
    											 hwnd, NULL,
    											 ((LPCREATESTRUCT) lParam)->hInstance, NULL);
    
    					};
    				};
    
    			};
    			return 0;
    	};
    	return DefWindowProc(hwnd, message, wParam, lParam);
    };
    

  • Mod

    Was erwartest Du?

    ((LPCREATESTRUCT) lParam)->hInstance
    

    Wenn eine WM_COMMAND Nachricht behandelt wird, dann ist lPaam eben kein Zeiger auf eine CREATESTRUCT!



  • Wie kann man das dann machen? Ich habe diesen Parameter nie wirklich verstanden, sondern nur so hingenommen, wie er im Buch steht.



  • Tja da sieht man wieder, einfach nur abschreiben brings wohl doch nicht :p
    Probier es mit

    GetModuleHandle(NULL)
    

    schirrmie


  • Mod

    Ich habe noch nie verstanden warum alle diese GetModuleHandle(NULL) empfehlen.
    Dieser Code rächt sich in dem Moment in dem man einen Codeschnippsel in eine DLL, Service oder TSP kopiert und meint dort geht es dann auch...

    hInstance ist ein Parameter, der sowohl durch WinMain als auch durcch DllMain übergeben wird. Dieser sollte in einem Modul als globale Variable gespeichert werden und steht dann bei solchen Operationen, wie CreateWindow zur Verfügung.



  • Es gibt aber viele die sich extrem gegen globale Variablen oder unnötige streuben und da ist der code gut. Naja und falls dein Fall wirklich eintritt mit der dll oder so dann kann man immernoch ne globale Variable nehmen. Also ich seh da jetzt kein Problem drin aber jeder wie er mag.

    schirrmie


Anmelden zum Antworten