VCL/VXL ähnlicher Win32API Wrapper
-
Hi,
ihr kennt doch sicherlich das Verfahren von Buttons in VCL. Buttons sind Instanzen, die ihre eigenen Nachrichten verarbeiten und nicht das Elternfenster.
Soetwas möchte ich gerne auch machen

Ich hatte mir das folgendermaßen gedacht: Eine Klasse namens "button" bekommt einen Funktionspointer auf eine Funktion die aufgerufen werden soll, wenn der Button gedrückt wird (Also WM_COMMAND an das Elternfenster gesendet wird).
Ich habe mit Subclassing meinen Button meine WndProc aufgetragen und das läuft auch Prima, WM_PAINT kommt an usw. leider jedoch nicht WM_COMMAND.

Jetzt hab ich mir gedacht, wie ich das emulieren könnte: Alle möglichen Fensternachrichten abfangen und zusammenfügen, die dieses Ereignis auslösen könnten. Leider eine unzähmbare arbeit.

Also bin ich zu extrem radikalen mitteln gegangen und habe im Elternfenster folgendes gemacht:
case WM_COMMAND: SendMessage ((HWND)lParam, WM_COMMAND, wParam, lParam); break;Klappt wunderbar, nur na ja: nicht das wahre und extrem radikal!
Jetzt meine Frage daher (und nein, ich möchte nicht rumdiskutieren wieso ich es so wie die VCL haben möchte!) : Wie kann ich es erreichen, das mein Button den Funktionspointer aufruft, wenn ich auf ihn klicke und an das Elternfenster WM_COMMAND gesendet würde?
Danke im voraus

-
Ach das Thema hast du doch schonmal hier reingestellt...
-
Hi,
ich habe es jetzt mal wie folgt ausprobiert:
#include <windows.h> typedef bool (*action)(void); static const unsigned long WM_COMMAND_BUTTON = WM_APP+1; class IButton { public: IButton (::HWND__* parent, HINSTANCE instance, unsigned long x, unsigned long y, action on_command) { m_on_command = on_command; m_hwnd = ::CreateWindow ("button", "Test", WS_CHILD | WS_VISIBLE, x, y, 100, 100, parent, NULL, instance, 0); set_wndproc (m_hwnd); } private: void set_wndproc(HWND hwndCombo) { LONG OldComboProc; OldComboProc = GetWindowLong(hwndCombo, GWL_WNDPROC); SetWindowLong(hwndCombo, GWL_USERDATA, OldComboProc); OldComboProc = SetWindowLong(hwndCombo, GWL_WNDPROC, (LONG)WndProc); } static LRESULT WINAPI WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { WNDPROC OldComboProc = (WNDPROC)GetWindowLong(hwnd, GWL_USERDATA); switch(msg) { case WM_COMMAND_BUTTON: m_on_command (); break; } return CallWindowProc(OldComboProc, hwnd, msg, wParam, lParam); } action m_on_command; HWND m_hwnd; }; LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_COMMAND: SendMessage ((HWND)lParam, WM_COMMAND_BUTTON, 0, 0); break; case WM_DESTROY: PostQuitMessage(0); return(0); default: break; } return(DefWindowProc(hWnd, uMsg, wParam, lParam)); } bool button1 (void) { MessageBox (NULL, "", "Button 1", MB_OK); return(true); } bool button2 (void) { MessageBox (NULL, "", "Button 2", MB_OK); return(true); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int nCmdShow) { WNDCLASSEX wc; HWND hWnd; MSG msg; wc.cbSize = sizeof(wc); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = (HICON)LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = (HCURSOR)LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); wc.lpszMenuName = NULL; wc.lpszClassName = TEXT("Buttontest"); wc.hIconSm = (HICON)LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) return(0); if(NULL == (hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW | WS_EX_APPWINDOW, wc.lpszClassName, wc.lpszClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL))) return(0); IButton test_button1(hWnd, hInstance, 10, 10, button1); IButton test_button2(hWnd, hInstance, 210, 10, button2); ShowWindow (hWnd, nCmdShow); while(GetMessage(&msg, NULL, 0, 0)) { if(!IsDialogMessage(hWnd, &msg)) { TranslateMessage(&msg); DispatchMessage (&msg); } } return(msg.wParam); }Jedoch sagt er mir in der WndProc:
button_test.cpp(40) : error C2597: illegal reference to non-static member 'IButton::m_on_command'Wie kann ich dieses problem beheben? Wenn ich es static mache, bekomme ich linkerfehler

-
kannst de aber ruhig static machen... musst dann nur halt folgendes net vergessen:
action IButton::m_on_command = 0;
-
return CallWindowProc(OldComboProc, hwnd, msg, wParam, lParam); } static action IButton::m_on_command = 0; HWND m_hwnd; };error C2864: 'IButton::m_on_command' : only static const integral data members can be initialized within a class
oder war das anders gemeint?

-
ja war anders gemeint

Das ist sowas ähnliches wie nen konstruktor

Also:
return CallWindowProc(OldComboProc, hwnd, msg, wParam, lParam); } static action m_on_command; HWND m_hwnd; }; static action IButton::m_on_command = 0;
-
genial, das geht! aber klicke ich auf button1 wird die falsche Funktion aufgerufen?

-
*push*
-
Schau Dir das hier an:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-149120.htmlUnd wie dort schon erwähnt: Schau Dir MFC/wxWidget oder sonstige "Frameworks" an, die genau das gemacht haben...
PS: Und eine "static"-Variable zu definieren ist für eine "Framework" fast immer tödlich.
-
Jo... das ist klar
War aber auch klar das die Frage von ihm kommt 