Combo Box Subclassen



  • hallo Leute,

    ich bastel mir gerade eine eigen Kommandozeile.
    Dabei habe ich die Ausgabe in einem RichEdit und die Eingabe macht man in eine Combo Box Control.

    jetzt wollte ich, dass wenn in der Combo Box [Enter] gedrückt wird, der Befehl ausgeführt wird,
    also habe ich eine NewComboProc geschrieben und per SetWindowLongPtr die alte überschrieben.

    funktioniert auch alles soweit...

    jetzt wollte ich die WM_KEYDOWN abfangen und auf VK_RETURN reagieren und TADA, da läuft nichts.

    seltsamer Weise empfängt die Funktion keine WM_KEYDOWN Nachricht.
    noch schlimmer: scheinbar empfängt sie auch keine WM_SYSKEYDOWN, WM_INPUT, WM_CHAR und was sonst noch für Tastatureingaben zur verfügung steht.

    jetzt ist die Frage: wie kann ich auf die Enter-Taste reagieren?
    verwendet die Combo-Box intern andere Nachrichten?

    schonmal danke

    MfG DrakoXP



  • Hmm, aber deine Combo-Box hat da auch den Keyboard-Fokus? (Prüf mal mit GetFocus() - Ich hab die Erfahrung gemacht das ein lustiges Cursors-Blinken nicht unbedingt auch keyboard-fokus heist ;/)



  • ich habe die Entertaste gedrückt, direkt als ich den Befehl eingegeben habe,
    also folglich muss die Combobox den Focus haben.

    tollerweise erhält die Combo nicht mal bei normalen Tasten ala "A" eine WM_KEYDOWN-Nachricht 😞



  • Hatte mal ein ähnliches Problem. Sollte eigentlich mit 'abfragen' der Message WM_GETDLGCODE und Rückgabe des entsprechenden Wertes funktionieren.

    The WM_GETDLGCODE message is sent to the window procedure associated with a control. By default, the system handles all keyboard input to the control; the system interprets certain types of keyboard input as dialog box navigation keys. To override this default behavior, the control can respond to the WM_GETDLGCODE message to indicate the types of input it wants to process itself.



  • DrakoXP schrieb:

    funktioniert auch alles soweit...
    jetzt wollte ich die WM_KEYDOWN abfangen und auf VK_RETURN reagieren und TADA, da läuft nichts.
    seltsamer Weise empfängt die Funktion keine WM_KEYDOWN Nachricht.

    Hast Du auch das Edit-Child der Combobox gesubclassed ?

    POINT pt;
     pt.x = 1;
     pt.y = 1;
    
    HWND hComboBox = CreateWindow         ("COMBOBOX",...);
    HWND hEdit     = ChildWindowFromPoint (hComboBox,  pt); // hEdit subclassen !
    

    🙂



  • @merker: ups^^, nee xD
    muss ich mal ausprobieren, thx



  • hm, ich mach irgendwas falsch 😞
    ich empfange immer noch keine WM_KEYDOWN 😞

    ich kann ja mal den Code posten...
    vllt findet ihr ja was

    // XP-Themes
    #if defined _M_IX86 
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 
    #elif defined _M_IA64 
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") 
    #elif defined _M_X64 
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 
    #else 
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 
    #endif
    
    // Microsoft Common Controls
    #pragma comment(lib, "comctl32.lib")
    
    // Windows Application Programming Interface
    #ifdef STRICT
    #undef STRICT
    #endif
    #include <windows.h>
    
    // Microsoft Common Controls
    #include <commctrl.h>
    
    // Rich Edit Control
    #include <richedit.h>
    
    // Shell Objects
    #include <shlobj.h>
    
    // Resource IDs
    #include "resource.h"
    
    // Hauptfensterklasse
    const wchar_t szWindowClass[] = L"1B1C5E88_3712_4E9F_9BB4_83B81E99078D";
    
    // Programm Instanz
    HINSTANCE g_hInstance;
    
    // Das Rich Edit
    HWND g_hRichEdit;
    
    // Die Combo-Box
    HWND g_hInputCombo;
    
    // kann beendet werden?
    bool g_bCanExit;
    
    // Der Prompt
    wchar_t g_szPrompt[1024];
    
    // Aktuelles Verzeichnis
    wchar_t g_szCurrentDir[MAX_PATH];
    
    // Die alte Fensterprozedur der Combo Box
    WNDPROC g_pOldEditProc;
    
    // Fehlermeldung
    void ErrorMessage(const wchar_t* szMessage)
    {
    	DWORD dwError = GetLastError();
    	wchar_t szError[1024];
    	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0x0407, szError, 1024, NULL);
    	wchar_t szBuffer[4096];
    	wsprintf(szBuffer, L"Fehler: %s\nFehlercode: %d\nBeschreibung: %s", szMessage, dwError, szError);
    	MessageBox(GetDesktopWindow(), szBuffer, L"Fehler!", MB_OK|MB_ICONERROR);
    }
    
    // Konsolenbefehl ausführen
    int DoCommand(int argc, wchar_t** argv)
    {
    	return 0;
    }
    
    // Gesubclassede Combo Box
    LRESULT CALLBACK NewEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch (msg)
    	{
    	case WM_KEYDOWN:
    		{
    			switch (wParam)
    			{
    			case VK_RETURN:
    				{
    					wchar_t szInput[1024];
    					ComboBox_GetCueBannerText(g_hInputCombo, szInput, 1024);
    					LRESULT result = SendMessage(g_hInputCombo, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)szInput);
    					if (result == CB_ERR)
    						SendMessage(g_hInputCombo, CB_INSERTSTRING, (WPARAM)0, (LPARAM)szInput);
    					int iArgc;
    					wchar_t** szArgv = CommandLineToArgvW(szInput, &iArgc);
    					int ret = DoCommand(iArgc, szArgv);
    					LocalFree(szArgv);
    					return ret;
    				} break;
    			default:
    				return CallWindowProc(g_pOldEditProc, hWnd, msg, wParam, lParam);
    			}
    			return 0;
    		} break;
    	}
    	return CallWindowProc(g_pOldEditProc, hWnd, msg, wParam, lParam);
    }
    
    // Die Window-Procedure des Hauptfensters
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch (msg)
    	{
    	case WM_CREATE:
    		{
    			wchar_t szRichInitText[4096];
    			wsprintf(szRichInitText, L"Microsoft Windows XP [Version 5.1.2600]\n(C) Copyright 1985-2001 Microsoft Corp.\n\n%s", g_szPrompt);
    			g_hRichEdit = CreateWindowEx(0, RICHEDIT_CLASS, szRichInitText, WS_BORDER|WS_VSCROLL|WS_HSCROLL|WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL|ES_AUTOVSCROLL|ES_MULTILINE|ES_READONLY, 10, 10, 50, 50, hWnd, (HMENU)IDC_RICHEDIT, g_hInstance, NULL);
    			if (IsWindow(g_hRichEdit) == FALSE)
    			{
    
    				DestroyWindow(hWnd);
    				ErrorMessage(L"Ausgabefenster konnte nicht erstellt werden!");
    				return 0;
    			}
    			SendMessage(g_hRichEdit, EM_SETBKGNDCOLOR, FALSE, RGB(0, 0, 0));
    			CHARFORMAT cf = { 0 };
    			cf.bCharSet = ANSI_CHARSET;
    			cf.bPitchAndFamily = FF_DONTCARE;
    			cf.cbSize = sizeof(CHARFORMAT);
    			cf.crTextColor = RGB(0, 255, 0);
    			cf.dwEffects = 0;
    			cf.dwMask = CFM_CHARSET|CFM_COLOR|CFM_FACE;
    			wsprintf(cf.szFaceName, L"%s", L"Courier New");
    			SendMessage(g_hRichEdit, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
    			g_hInputCombo = CreateWindowEx(0, L"COMBOBOX", L"", WS_VISIBLE|WS_BORDER|WS_CHILD|CBS_DROPDOWN|CBS_NOINTEGRALHEIGHT|CBS_HASSTRINGS, 10, 70, 50, 50, hWnd, (HMENU)IDC_INPUTCOMBO, g_hInstance, NULL);
    			if (IsWindow(g_hInputCombo) == FALSE)
    			{
    
    				DestroyWindow(hWnd);
    				ErrorMessage(L"Eingabefenster konnte nicht erstellt werden!");
    				return 0;
    			}
    			POINT pt = { 1, 1 };
    			HWND hEdit = ChildWindowFromPoint(g_hInputCombo, pt);
    			g_pOldEditProc = (WNDPROC)SetWindowLongPtr(hEdit, GWLP_WNDPROC, (LONG)NewEditProc);
    			return 0;
    		} break;
    	case WM_CLOSE:
    		{
    			DestroyWindow(hWnd);
    			return 0;
    		} break;
    	case WM_DESTROY:
    		{
    			PostQuitMessage(0);
    			return 0;
    		} break;
    	case WM_SIZE:
    		{
    			int width = LOWORD(lParam);
    			int height = HIWORD(lParam);
    			MoveWindow(g_hRichEdit, 10, 10, width - 20, height - 50, TRUE);
    			MoveWindow(g_hInputCombo, 10, height - 30, width - 20, 20, TRUE);
    			return 0;
    		} break;
    	}
    	return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    
    // Unicode main function
    int wmain(int argc, wchar_t** argv)
    {
    	WNDCLASSEX wce;
    	wce.cbClsExtra = 0;
    	wce.cbSize = sizeof(WNDCLASSEX);
    	wce.cbWndExtra = 0;
    	wce.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
    	wce.hCursor = LoadCursor(NULL, IDC_ARROW);
    	HICON hIcon = LoadIcon(NULL, IDI_WINLOGO);
    	wce.hIcon = hIcon;
    	wce.hIconSm = hIcon;
    	wce.hInstance = g_hInstance;
    	wce.lpfnWndProc = WndProc;
    	wce.lpszClassName = szWindowClass;
    	wce.lpszMenuName = NULL;
    	wce.style = CS_VREDRAW|CS_HREDRAW|CS_BYTEALIGNCLIENT|CS_BYTEALIGNWINDOW|CS_OWNDC|CS_DBLCLKS;
    	RegisterClassEx(&wce);
    	HWND hWnd = CreateWindowEx(0, szWindowClass, L"Console", WS_OVERLAPPEDWINDOW, (GetSystemMetrics(SM_CXSCREEN) - 800) / 2, (GetSystemMetrics(SM_CYSCREEN) - 600) / 2, 800, 600, GetDesktopWindow(), NULL, g_hInstance, NULL);
    	if (IsWindow(hWnd) == FALSE)
    	{
    		ErrorMessage(L"Hauptfenster konnte nicht erstellt werden!");
    		return 0;
    	}
    	ShowWindow(hWnd, SW_SHOW);
    	UpdateWindow(hWnd);
    	MSG msg;
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    	return (int)(msg.wParam);
    }
    
    // Program Entry Point
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
    {
    	SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, g_szCurrentDir);
    	SetCurrentDirectory(g_szCurrentDir);
    	wsprintf(g_szPrompt, L"%s: ", g_szCurrentDir);
    	g_bCanExit = true;
    	g_hInstance = hInstance;
    	InitCommonControls();
    	HMODULE hRichLib = LoadLibrary(L"riched20.dll");
    	if (hRichLib == INVALID_HANDLE_VALUE)
    	{
    		ErrorMessage(L"Riched20.dll konnte nicht geladen werden!");
    		return 0;
    	}
    	wchar_t* pCmdLine = GetCommandLine();
    	int iArgc;
    	wchar_t** szArgv = CommandLineToArgvW(pCmdLine, &iArgc);
    	int ret = wmain(iArgc, szArgv);
    	LocalFree((HLOCAL)szArgv);
    	FreeLibrary(hRichLib);
    	return ret;
    }
    

    ...



  • Könnte ev. sein, dass ChildWindowFromPoint () das Edit-Child nicht gefunden hat, weil z.B. der Rand von der ComboBox sehr "dick" ist.
    Probier mal pt zu vergrössern :

    // POINT pt = { 1, 1 };
     POINT pt = { 4, 4 }; // oder ev. grösser
    

    🙂



  • jippieh 😃 klappt, thx an alle, die sich beteiligt haben


Anmelden zum Antworten