Problem mit Windowsnachrichten



  • Ok, einen Blick in die betreffende Headerdatei hätte ich schon werfen können, aber danke für den Hinweis 😃

    Damit wäre das Problem mit WM_MOUSEWHEEL beseitigt, nur das Problem mit WM_ACTIVATE besteht noch. WM_ACTIVATE ist dem Compiler bekannt, aber ich bekomme keine betreffende Nachricht.

    MfG
    Shelling


  • Mod

    Dein Child bekommt auch WM_ACTIVATE nicht. Nur das Frame.

    Verwende Spy++ und schau wer die Nachricht erhält.



  • Achso, also landen die WM_ACTIVATE Nachrichten beim Konsolenfenster, das ich zu Debugausgabe noch geöffnet hab? (Ist laut Projekt auch ein Konsolenprogramm)

    Wenn ich das richtig verstanden habe, reicht es dann wenn ich als Projekt eine Win32 Applikation erstelle und da das Fenster erstelle, um die Nachricht an das Fenster zu bekommen?

    //EDIT:

    Es gibt 2 Möglichkeiten, entweder ich kann mit Spy++ nicht umgehen, oder mein Programm lügt mich an 😃

    Laut Spy++ kommt eine WM_ACTIVATE, WM_ACTIVATEAPP und WM_KILLFOCUS an das Fenster an. Ich hab das auch einmal bei einem Win32 Projekt versucht. Auch hier kommen laut Spy++ die Windowsnachrichten an, nur leider scheint das Programm nichts davon zu wissen...

    MfG
    Shelling


  • Mod

    Ist das ein Konsolenprogramm? Dann werden diese vom OS behandelt.
    Nur Winodws UI Programm erhalten über die Fensterprozedur diese Nachrichten.



  • Ja, zu Debugzwecken hab ich ein Konsolenprogramm erstellt, welches mir dann das Fenster erstellt. Es ging mir lediglich um die Möglichkeit etwaige Meldungen in dem Konsolenfenster ausgeben zu lassen, um zu sehen was grade eigentlich passiert.

    Zu Testzwecken hab ich jetzt noch ein Win32 Programm erstellt. Aber auch hier bekommt mein Fenster keine WM_ACTIVATE Nachricht.
    Kann es an der Art der Fenstererstellung liegen? Ich muss zugeben, dass ich noch nie mit CreateWindow gearbeitet hab. Muss ich bestimmte Flags übergeben?

    MfG
    Shelling


  • Mod

    Vergiss doch dann bitte die Consolen Anwendung und erzeuge immer eine entsprechende UI.

    Entweder Du arbeitest mit der Console, oder eben mit einem Windows Programmm. Beides zu mischen ist Unsinnn und in vieler Hinsicht geht dann einiges nicht so wie Du Dir das denkst. Siehe WM_ACTIVATE...



  • Ich hab ja noch ein Win32 Programm erstellt und binde da meine Fensterklasse ein. Da sollte dann nichts mehr, was auch nur irgendwie mit Konsole zutun hat, enthalten sein. Aber auch hier gibt es diese Nachricht nicht.

    Oder irre ich mich und ein "Win32-Anwendung" Projekt ist nicht das was du meinst?
    In der Schule arbeiten wir nur mit dem MFC-Anwendungsassistenten, deswegen kenn ich mich nicht so sehr mit den anderen Optionen aus.

    MfG und vielen Dank für deine Geduld,
    Shelling



  • Also ich kriege auch bei ner Konsolen-App die WM_ACTIVATE. Und ja, "Win32-App" wird das sein, was Martin meint.

    edit: Einfach mal den Source dazu, wenn das bei dir nicht funktioniert, ist was faul

    #include <windows.h>
    #include <string>
    #include <iostream>
    
    const char* WNDCLASSNAME = "bla";
    
    LRESULT CALLBACK WinProc( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam )
    {
    	switch ( Msg )
    	{
    		case WM_CLOSE:
    		{
    			PostQuitMessage( 0 );
    			break;
    		}
    
    		case WM_ACTIVATE:
    		{
    			std::cout << "activated.." << std::endl;
    		} break;
    	}
    	return DefWindowProc( hWnd, Msg, wParam, lParam );
    }
    
    //int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ){
    int main(){	HINSTANCE hInstance = GetModuleHandle(NULL);
    
    	MSG Msg;
    	WNDCLASSEX ex;
    
    	ZeroMemory( &ex, sizeof( WNDCLASSEX ) );
    	ex.cbSize = sizeof(WNDCLASSEX);
    	ex.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
    	ex.lpfnWndProc = WinProc;
    	ex.hInstance = hInstance;
    	ex.hIcon = LoadIcon( NULL, IDI_APPLICATION );
    	ex.hCursor = LoadCursor( NULL, IDC_ARROW );
    	LOGBRUSH lb = { BS_SOLID, GetSysColor(COLOR_3DFACE), 0 };
    	ex.hbrBackground = CreateBrushIndirect( &lb );
    	ex.lpszClassName = WNDCLASSNAME;
    	RegisterClassEx(&ex);
    
    	HWND hWnd = CreateWindowEx( NULL, WNDCLASSNAME, "Window", WS_OVERLAPPEDWINDOW, 0, 0, 300, 300, NULL, NULL, hInstance, NULL );
    	ShowWindow( hWnd, SW_SHOW );
    	UpdateWindow( hWnd );
    
    	while ( 1 )
    	{
    		GetMessage( &Msg, NULL, 0, 0 );
    		if ( Msg.message == WM_QUIT )
    			break;
    		TranslateMessage( &Msg );
    		DispatchMessage( &Msg );
    	}
    	UnregisterClass( WNDCLASSNAME, hInstance );
    	return Msg.lParam;
    }
    

    edit2: Getestet mit MS VS 2003, Release & Debug



  • Ok, vielen Dank, das hat mir einerseits das Brett vom Kopf weggeschlagen und andererseits ein neues festgenagelt... 😃

    Ich hab bisher alle Nachrichten in meiner eigenen Funktion behandelt, d.h. ich hab simpel per GetMessage() auf eine Nachricht gewartet und dann die MSG Struktur mit der erhaltenen Nachricht in meine Funktion übergeben.

    Dies klappt aber scheinbar nicht immer. Bei, wie ich feststellen musste, einigen Nachrichten gibt es Probleme. Ich hab jetzt einfach probiert, ob das Ganze mit TranslateMessage() und DispatchMessage() auch passiert...

    Das komische ist, in meiner WndProc() kommt die WM_ACTIVATE Nachricht an. Das bringt mir aber Nichts, da ich von der WndProc nicht auf die Memberfunktion der Fensterklasse zugreifen kann.

    Ich weiß jetzt nicht ob ich mich freuen soll oder nicht 😃

    Was aber auch merkwürdig ist, ist das hier:

    (main)

    while(GetMessage(&msg,NULL,0,0))  
    {
    	if(msg.message==WM_ACTIVATE) printf("activate");
    	TranslateMessage(&msg);
    	DispatchMessage(&msg);
    }
    

    (WndProc)

    LRESULT CALLBACK CDevice::WndProc(HWND Wnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	if(uMsg==WM_ACTIVATE) printf("aktiv...");
    
    	return DefWindowProc(Wnd,uMsg,wParam,lParam);
    }
    

    Es wird nur das "aktiv..." der WndProc ausgegeben, aber nicht das "activate" der main. Kann mir das einer erklären? Ich versteh das nicht...

    MfG
    Shelling



  • Hier steht was zu Nachrichten beim Selektieren von einem Fenster - evtl bringt dir statt WM_ACTIVATE auch z.B. WM_SETFOCUS was?
    Wie man eine nicht-statische WndProc in einer Klasse hinbekommt, dazu gibt's hier im Forum übrigens einige Beiträge, musste mal suchen oder in die FAQ gucken 😉



  • Sorry erstmal das ich mich hier nicht mehr hab blicken lassen, aber es gab ein paar kleine Probleme...

    Jedenfalls hab ich mir die Sache mit WM_ACTIVATE mal genauer angesehen, d.h. ich hab überprüft mit welchem Wert die Nachricht in meinen MessageHandler ankommt. Da gibt es jetzt ein Problem, der Wert von WM_ACTIVATE ist 257, der selbe Wert wie WM_KEYUP.

    Ich hab schon am Anfang des Projektes im Forum danach gesucht, wie man eine WndProc in eine Klasse integrieren kann. Bin auch fündig geworden und hab es damit versucht einen Pointer per SetWindowLong bei WM_CREATE zu speichern und bei den anderen Nachrichten mit GetWindowLong zu laden. Das hat zwar auch anfangs geklappt, aber irgendwann hab ich rausgefunden, das die Werte in der Klasse nicht die waren, die sie sein sollten. Scheinbar hat da irgendwas bei der Übergabe nicht geklappt...
    (Zudem wurde es durch das gecaste, zumindest auf meinem Rechner, ziemlich langsam...)

    Gibt es sonst noch irgendwelche Ideen? Mich verwirrt das einfach nur noch...

    MfG
    Shelling



  • Sorry, Doppelpost...



  • -Shelling- schrieb:

    Jedenfalls hab ich mir die Sache mit WM_ACTIVATE mal genauer angesehen, d.h. ich hab überprüft mit welchem Wert die Nachricht in meinen MessageHandler ankommt. Da gibt es jetzt ein Problem, der Wert von WM_ACTIVATE ist 257, der selbe Wert wie WM_KEYUP.

    Also bei mir ist WM_ACTIVATE==0x0006 und WM_KEYUP 0x0101 (257), hast du dich da vielleicht vertan?

    -Shelling- schrieb:

    Ich hab schon am Anfang des Projektes im Forum danach gesucht, wie man eine WndProc in eine Klasse integrieren kann. Bin auch fündig geworden und hab es damit versucht einen Pointer per SetWindowLong bei WM_CREATE zu speichern und bei den anderen Nachrichten mit GetWindowLong zu laden. Das hat zwar auch anfangs geklappt, aber irgendwann hab ich rausgefunden, das die Werte in der Klasse nicht die waren, die sie sein sollten. Scheinbar hat da irgendwas bei der Übergabe nicht geklappt...
    (Zudem wurde es durch das gecaste, zumindest auf meinem Rechner, ziemlich langsam...)

    Eigentlich dürfte es zu keinen größeren Geschwindigkeits-Einbußen kommen, zeig doch mal ein wenig Code 😉 Achso, und hast du bei RegisterClass(Ex) auch angegeben, dass du zum Fenster User-Daten brauchst (WNDCLASS::cbWndExtra >= 4)?

    Und sonst kannst du in deiner Fenster-Klasse evtl auch eine statische map HWND->WndClass* einsetzen, spätestens da dürfte von wegen Geschwindigkeit nichts mehr zu merken sein.



  • hast du bei RegisterClass(Ex) auch angegeben, dass du zum Fenster User-Daten brauchst (WNDCLASS::cbWndExtra >= 4)?

    Hab grad nachgesehen, nein hab ich nicht 😃
    Werd ich dann schnellstmöglich ändern, danke 🙂
    Geh ich richtig in der Annahme das die Zahl die Größe des Speichers in Byte ist?

    Der Code der alten WndProc existiert leider nicht mehr, aber ich hatte den Cast wenn ich mich recht erinner in jedem Case-Zweig im switch(uMsg).

    So kann ich jetzt aber auch alles wieder auf die WndProc umstellen. Gibt es vll auch eine Möglichkeit die Windowsnachrichten außerhalb der main zu empfangen? Bisher bekamen GetMessage und PeekMessage nur Nachrichten wenn sie in der main standen. Sobald ich die in einer anderen Funktion hatte, kam nichts mehr.

    //EDIT:

    So, hab meinen Code jetzt etwas abgeändert.

    Meine WndProc:

    CDevice *device;
    	switch(uMsg)
    	{
    	case WM_CREATE:
    
    		printf("CREATE");
    		SetWindowLong(Wnd,GWL_USERDATA,lParam);
    		break;
    
    	case WM_ACTIVATE:
    
    		device=(CDevice*)GetWindowLong(Wnd,GWL_USERDATA);
    		printf("ACTIVATE");
    		if(LOWORD(wParam))
    		{
    			ShowCursor(false);
    			device->OpenGL.activ=true;
    			device->activ=true;
    		}
    		else
    		{
    			ShowCursor(true);
    			device->OpenGL.activ=false;
    			device->activ=false;
    		}
    
    		return 0;
    
    	}
    
    	return DefWindowProc(Wnd,uMsg,wParam,lParam);
    

    Die WNDCLASS

    wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc = (WNDPROC)WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 4;
    wc.hInstance = hInstance;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL,IDC_ARROW);
    wc.hbrBackground = NULL;
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "wigfx";
    

    und die Fenstererstellung

    hWnd = CreateWindow(
    		"wigfx",
    		"wigfx",
    		WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
    		0,0,
    		XRes,YRes,
    		NULL,
    		NULL,
    		hInstance,
    		this);
    

    Leider funktioniert das auch nicht. CDevice bekommt die Änderung von WM_ACTIVATE in der WndProc nicht mit. Welche Kleinigkeit übersehe ich da?

    MfG
    Shelling


Anmelden zum Antworten