[gelöst] ComboBox-Problem: Stack-Overflow bei CB_SHOWDROPDOWN



  • Hallo miteinander

    Ich möchte, dass sich die Liste einer ComboBox öffnet, wenn ich den Pfeil drücke (also ganz normales CB-Verhalten). Wähle ich allerdings diesen Pfeil an, so wird mein Programm unterbrochen und meldet einen Stack-Überlauf. Kann mir jemand sagen, was ich da falsch mache?

    Code zum Erstellen und Füllen der ComboBox:

    case WM_CREATE:	cmbTest = CreateWindow(	L"combobox",
    												NULL,
    												WS_VISIBLE | WS_CHILD | WS_BORDER | CBS_DROPDOWN,
    												20, 30,
    												120, 25,
    												hwnd,
    												(HMENU) ID_CMB_1,
    												((LPCREATESTRUCT) lParam)->hInstance,
    												NULL);
    
    						wcscpy_s(szTmp, L"Eintrag1");
    						SendMessage(cmbTest, (UINT) CB_ADDSTRING, (WPARAM) 0, (LPARAM) szTmp);
    						wcscpy_s(szTmp, L"Eintrag2");
    						SendMessage(cmbTest, (UINT) CB_ADDSTRING, (WPARAM) 0, (LPARAM) szTmp);
    						wcscpy_s(szTmp, L"Eintrag3");
    						SendMessage(cmbTest, (UINT) CB_ADDSTRING, (WPARAM) 0, (LPARAM) szTmp);
    
    						SendMessage(cmbTest, (UINT) CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);
    
    						return 0;
    

    Code (zunächst nur) zum Öffnen der CB-Liste:

    case WM_COMMAND:	switch(LOWORD(wParam))
    						{
    						case ID_CMB_1:	SendMessage(cmbTest, (UINT) CB_SHOWDROPDOWN,
    													(WPARAM) TRUE, (LPARAM) 0);
    
    											break;
    						}
    
    						return 0;
    

    Lasse ich den Code unter WM_COMMAND von einem Knopf ausführen, öffnet sich die Liste genauso wenig, allerdings stürzt das Programm nicht ab.

    Einer 'ne Idee, wo ich einen Fehler eingebaut haben könnte?

    Danke euch

    Gruß
    Kai



  • Wie hast du denn szTmp angelegt?



  • Die habe ich so angelegt:

    TCHAR szTmp[10];
    


  • Bei mir funktioniert das einwandfrei. Ich habe dennoch die Vermutung, dass dein Buffer zu klein gewählt ist. wcscpy_s setzt ein NULL-Zeichen ans Ende des Strings, so dass dein Buffer immer Stringlänge + 1 Platz haben sollte.

    Ist cmbTest als static bzw. global deklariert? Ich könnte mir vorstellen, dass CB_SHOWDROPDOWN , was du über SendMessage bei WM_COMMAND sendest, gar nicht ankommt.

    Ohne voll compilierbares Minimalbeispiel, welches immer noch diesen Fehler erzeugt, lässt sich aber sonst nur die Glaskugel befragen ...



  • Was sagt denn der Aufrufstack?



  • roflo schrieb:

    Was sagt denn der Aufrufstack?

    Bin mir nicht sicher, ob das die Info ist, nach der du fragst, aber die Unterbrechungsmeldung lautet:

    Unbehandelte Ausnahme bei 0x77741180 (ntdll.dll) in Exporttool.exe: 0xC00000FD: Stack overflow (Parameter: 0x00000001, 0x00172FFC)

    Fake oder Echt schrieb:

    Bei mir funktioniert das einwandfrei. Ich habe dennoch die Vermutung, dass dein Buffer zu klein gewählt ist. wcscpy_s setzt ein NULL-Zeichen ans Ende des Strings, so dass dein Buffer immer Stringlänge + 1 Platz haben sollte.

    Den Buffer habe ich auch schon einmal von 10 auf 100 hochgeschraubt - keine Veränderung. Die Einträge sind auch keine 10 Zeichen lang.

    Ist cmbTest als static bzw. global deklariert? Ich könnte mir vorstellen, dass CB_SHOWDROPDOWN , was du über SendMessage bei WM_COMMAND sendest, gar nicht ankommt.

    cmbTest ist als static deklariert.

    Ohne voll compilierbares Minimalbeispiel, welches immer noch diesen Fehler erzeugt, lässt sich aber sonst nur die Glaskugel befragen ...

    Habe den Code mal auf das Wesentlichste gekürzt - ist kompilierbar:

    #include <windows.h>
    
    #define ID_CMB_VERSION	1
    
    LRESULT	CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK EditWndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int iCmdShow)
    {
    	WNDCLASS	wndClass;
    	HWND		hwnd;
    	MSG			msg;
    	TCHAR		szAppName[] = TEXT("NAV Objekt Export");
    
    	wndClass.style			= CS_HREDRAW | CS_VREDRAW;
    	wndClass.lpfnWndProc	= WndProc;
    	wndClass.cbClsExtra		= 0;
    	wndClass.cbWndExtra		= 0;
    	wndClass.hInstance		= hInstance;
    	wndClass.hbrBackground	= (HBRUSH) GetStockObject(WHITE_BRUSH);
    	wndClass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
    	wndClass.hCursor		= LoadCursor(NULL, IDC_ARROW);
    	wndClass.lpszMenuName	= NULL;
    	wndClass.lpszClassName	= szAppName;
    
    	if(!RegisterClass(&wndClass))
    	{
    		MessageBox(NULL, TEXT("Unicode fehler"), TEXT("Fehler"), MB_ICONERROR);
    		return 1;
    	}
    
    	hwnd = CreateWindow(	szAppName,
    							szAppName,
    							WS_OVERLAPPEDWINDOW,
    							CW_USEDEFAULT,
    							CW_USEDEFAULT,
    							CW_USEDEFAULT,
    							CW_USEDEFAULT,
    							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)
    {
    	HDC					hdc;
    	PAINTSTRUCT			ps;
    	static	HWND		cmbVersion;
    	TCHAR				szCmbStringTmp[10], szCmbVersionStr[4][5] = { L"V602", L"V700", L"V710", L"V800" };
    	int					i;
    
    	switch(message)
    	{
    	case WM_CREATE:		cmbVersion = CreateWindow(	TEXT("combobox"),
    													NULL,
    													WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP | CBS_DROPDOWNLIST,
    													80, 125, 65, 25,
    													hwnd,
    													(HMENU) ID_CMB_VERSION,
    													((LPCREATESTRUCT) lParam)->hInstance,
    													NULL);
    
    						//*** Start: ComboBoxen füllen
    						memset(&szCmbStringTmp, 0, sizeof(szCmbStringTmp));
    						for(i=0; i<4; i++)
    						{
    							wcscpy_s(szCmbStringTmp, sizeof(szCmbStringTmp)/sizeof(TCHAR), szCmbVersionStr[i]);
    							SendMessage(cmbVersion, (UINT) CB_ADDSTRING, (WPARAM) 0, (LPARAM) szCmbStringTmp);
    						}
    
    						SendMessage(cmbVersion, (UINT) CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0); 
    						//*** Ende: ComboBoxen füllen
    
    						return 0;
    
    	case WM_PAINT:		hdc=BeginPaint(hwnd, &ps);
    
    						EndPaint(hwnd, &ps);
    
    						return 0;
    
    	case WM_COMMAND:	switch(LOWORD(wParam))
    						{
    						case ID_CMB_VERSION:	SendMessage(cmbVersion, (UINT) CB_SHOWDROPDOWN, (WPARAM) 0, (LPARAM) 0);
    
    												return 0;
    
    						default:				return 0;
    						}
    
    	case WM_DESTROY:	PostQuitMessage(0);
    
    						return 0;
    	}
    
    	return DefWindowProc(hwnd, message, wParam, lParam);
    }
    


  • Der Overflow kommt glaube ich daher, dass der Code unter ID_CMB_VERSION zweimal aufgerufen wird. Demnach werden beim Klick auf die Combobox zwei WM_COMMAND-Nachrichten ans Parent-Fenster gesendet.
    Aber es gibt doch sicherlich ein ganz normales Vorgehen (welcher Auslöser, welche Nachricht, ...) für das Öffnen einer ComboBox-Liste. Das ist doch eigentlich eine völlig triviale Sache.



  • Die Verwendung von SendMessage bewirkt einen rekursiven Aufruf von WndProc. Ohne näher darauf einzugehen, dass du mit den Nachrichten vermutlich Unsinn anstellst, musst du PostMessage benutzen.



  • Gibt es denn irgendwo brauchbaren Beispielcode dazu. Alles was ich bisher gefunden habe, sah so aus, wie ich es mache.
    Außerdem will ich keinen Unsinn anstellen, sondern einfach nur die DropDown-Liste öffnen.
    Aber verstehe ich das jetzt richtig, dass ich mit einem Aufruf von SendMessage, Nachrichten an die Aufrufende WindowProzedur schicke?


  • Mod

    Warum sendest Du überhaupt CB_SHOWDROPDOWN?
    Damit die Box öffnet musst Du nichts machen.

    Du solltest der guten Box aber etwas mehr Größe spendieren. Die Höhe, die beim Create angegeben wird, ist die Höhe der aufgeklappten Box!



  • Martin Richter schrieb:

    Warum sendest Du überhaupt CB_SHOWDROPDOWN?
    Damit die Box öffnet musst Du nichts machen.

    Du solltest der guten Box aber etwas mehr Größe spendieren. Die Höhe, die beim Create angegeben wird, ist die Höhe der aufgeklappten Box!

    DAS WAR ES!!!!

    Ich danke dir. Dat hab ich nit jewusst.

    DANKESCHÖN

    Gruß
    Kai



  • Beide Änderungen waren notwendig, wie Martin gesagt hat; SendMessage löschen ...


Log in to reply