schon wieder Hook?

the incredible Leitman

Erfahrenes Mitglied
Hallo ihr!

Ich weiß, es gibt bereits genug Themen, die Hook behandeln, aber die sind zum Teil schon veraltet oder nicht genau was ich brauche...

Wollte nur fragen ob ich mit Visual C++ in Microsoft Visual Studio 8.0 mit .NET Framework 2.0 Windows Messages unter Windows XP mittels Hook immer noch abfangen und verarbeiten kann?

ich erstelle ein Programm, dass wichtige Informationen anzeigt und auf keinen Fall geschlossen (ALT F4) oder mittels ALT TAB, Windows Taste + E, usw minimiert werden darf.
Nun möchte ich die genannten Tastenkombinationen abfangen und vor Windows verarbeiten,

Bisher bin ich soweit:
habe TopMost auf true gesetzt, d.h. mein Programm ist immer im Vordergrund (ist nicht das Gelbe von Ei, da Such- oder Explorerfenster zwar im Hintergrund immer noch aufgehen aber das muss daweil reichen)

habe einen KeyDownEvent Handler in der Form, der Alt F4 abfängt, aber sobalt ein anderer Button oder ein ControlObjekt aktiviert wird, funkt der Eventhandler nicht mehr...

brauche ich dazu Hooks oder gibt es mittlerweile einen einfacheren Weg um das zu lösen?


Vielen Dank im Vorraus
 
Hallo

Also wenn es nur um dein Programm geht, was weder geschlossen werden darf usw. kannst du das wenn mich nicht alles täuscht das ganze auch über die winproc(...) in deinem main behandeln. Einen Hook verwende ich ja eigentlich nur wenn mein Programm alle Messages abfangen soll selbst wenn meine App nicht den Focus hat.

Grüße
R.
 
hm... hab jetzt gesucht, was ich über winproc() finde, aber nichts brauchbares gefunden...
kann mir vielleicht jemand Referenzen / CodeSnippets / examples geben?

MSDN hat mir nicht wirklich weitergeholfen...

Danke,
mfG
 
Hallo,

so könnte die ganze Sache ungefähr aussehen wenn du dir deine App ohne MFC zummenbraust, hoffe es ist soweit verständlich, wenn ich irgendwas vergessen habe möge man es mir verzeihen es sollte auch nur das Prinzip verdeutlichen.




Code:
void main()
{
	WNDCLASSEX myWindow; // unsere Fenster-Instanz

	// Fenster-Attribute setzen
	myWindow.cbSize = sizeof(WNDCLASSEX); // die Grösse
	myWindow.style = CS_HREDRAW | CS_VREDRAW;
	myWindow.lpfnWndProc = WindowProc; // Zeiger (function pointer) zu unserer WindowProc()-Funktion
	myWindow.cbClsExtra = 0; // nicht wichtig
	myWindow.cbWndExtra = 0; // nicht wichtig
	myWindow.hInstance = hInstance; // Handle zur Instanz
	myWindow.hIcon = LoadIcon( NULL, IDI_APPLICATION );// kein spezielles Icon
	myWindow.hCursor = LoadCursor(NULL, IDC_ARROW);// kein spezieller Cursor
	myWindow.hbrBackground = (HBRUSH )GetStockObject(BLACK_BRUSH); // Fenster-Hintergrund: weiss
	myWindow.lpszMenuName = NULL;// kein Menü
	myWindow.lpszClassName = "meinFenster"; // unsere Fensterklasse
	myWindow.hIconSm = LoadIcon(NULL, IDI_APPLICATION );  // kein spezielles Icon, wenn minimiert

	// Fenster registrieren
	// wenn RegisterClassEx() nicht true zurückgibt...
	if(! (RegisterClassEx(&myWindow)))
		return NULL;

	// Fenster erzeugen
	m_hwnd = CreateWindowEx(
				  WS_EX_TOPMOST, // erweiterter Fenster-Style
				  "meinFenster", // unsere Fensterklasse
				  "", // Titel des Fensters
				  WS_POPUPWINDOW | WS_OVERLAPPED | WS_CHILD, // Fenster-Style --> da brauchst du das WS_CHILD wohl nicht
				  300, // horizontale Position
				  300, // vertikale Position
				  100, // maximale Breite
				  100, // maximale Höhe
				  hwndParent, // not used = NULL, Handle zu Mutter-Fenster
				  NULL, // not used, Handle zu Menü
				  hInstance, // not used = NULL, Handle zu unserer Instanz
				  NULL // not used, Zeiger auf spezielle Fensterdaten
	  );
	// wenn dies nicht erfolgreich war...
	if(!m_hwnd)
		return NULL;

	ShowWindow(m_hwnd, 1);
	UpdateWindow(m_hwnd);

	return m_hwnd;
}


LRESULT CALLBACK WindowProc(HWND hWnd,
                              UINT message,
                              WPARAM wParam,
                              LPARAM lParam)
{
    // was ist die message vom Event-Handler?


    switch (message)
    {
        // bei Programmende
		case WM_DESTROY:
            PostQuitMessage(0);
            return 0L;

        // Tasturabfrage
        case WM_KEYDOWN:
            // welche Taste?
            switch (wParam)
            {
                // bei "Escape-Taste" Programmende
                case VK_ESCAPE:
                    PostMessage(hWnd, WM_CLOSE, 0, 0);
                    return 0L;
            } // end switch
        default: break;
    } // end switch

  // alle messages, die wir nicht behandeln
  // an DefWindowProc() senden...
  return DefWindowProc(hWnd, message, wParam, lParam);
} // end windowproc function

Mit MFC bzw. .NetFramework brauchst du einfach nur die
Code:
LRESULT CALLBACK WindowProc(
HWND hwnd, 
UINT uMsg, 
WPARAM wParam, 
LPARAM lParam );
ableiten

Grüße
R.
 
Zuletzt bearbeitet:
Danke echt super *freu*

hm... ist das C#? Mir sagen einige Codezeilen gar nichts :(
ich baue eine einfache Windows Form Applikation in VC++.NET

hab momentan folgenden Code erstellt:

Code:
// TestWinFormApp.cpp : main project file.

#include "stdafx.h"
#include "Form1.h"  //hier steht alles, wie die Form erstellt wird, welche Objekte,...

#include <windows.h>


using namespace TestWinFormApp;

/* 
**********************************************************************************
Keyboard Hook:
MessageBoxen dienen nur zum Anzeigen, dass der Key erkannt wurde
**********************************************************************************/

HHOOK m_hhook;

LRESULT /*__declspec(dllexport)__stdcall*/ CALLBACK KeyboardProc(int nCode,WPARAM wParam, LPARAM lParam)
{
    bool block = false;

    if (((DWORD)lParam & 0x40000000) &&(HC_ACTION==nCode))
    {        
        // ja, ich weiß, eine Switch Anweisung wäre angebrachter :\
        if(wParam==VK_SPACE)
        {
	MessageBox::Show("Event Space handled");
	block = true;
	return 1;
        }

        if(wParam==VK_MENU)
        {
	MessageBox::Show("Event ALT handled");

	if ((wParam==VK_TAB))
		MessageBox::Show("Event TAB handled");

                block = true;
	return 1;
        }

        if ((wParam==VK_LWIN) || (wParam == VK_RWIN))
        {
	MessageBox::Show("Event WIN handled");
	block = true;
	return 1;
        }

        // 2DO:
        // VK_EXECUTE = execute Key
        // VK_APPS = ApplikationKey
        // VK_LWIN = left WindowsKey, VK_RWIN

        // WAS zurückgeben, damit nicht ausgeführt wird?
    }

    LRESULT RetVal;

    if (block == false)
    {
	RetVal = CallNextHookEx( m_hhook, nCode, wParam, lParam );
    }

    return 0;
}

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
//HOOK: 
m_hhook = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,0,(int)AppDomain::GetCurrentThreadId());
	
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false); 

// Create the main window and run it
Form1^ form1 = gcnew Form1();
Application::Run(form1);
return 0;
}

HINWEIS: Fehler sind beabsichtigt und dienen der allgeimeinen Belustigung *gg*
Nein, Scherz, tut mir leid, falls ich etwas vergessen habe bzw. der Code nicht richtig ist...


Eigentlich funktioniert das so, jedoch ist mein Problem nicht gelöst, da das Programm zwar die Tasten erkennt und eine MessageBox erzeugt, aber Windows trotzem die Taskleiste aufruft (bzw. ein ExplorerFenster oder dgl.) wenn man die Windows Taste drückt... Wie kann ich das abschalten? brauche ich dazu nun einen globalen Hook oder geht das sonst irgendwie?

Ahja, und ALT F4 Problem habe ich so gelöst, indem ich die OnCloseFunktion deaktiviert habe *gg*
 
Zuletzt bearbeitet:
Hallo,

ist natürlich kein C# sondern sonder guter alter c/c++ Code. Wenn du die Windowproc implementierst einfach die WM_CLOSE und WM_DESTROY Message abfangen und mit einem
Code:
return 0;
zurückgeben, damit bleibt deine Anwendung offen. Wenn Form1 dein MainWindow ist reicht es wahrscheinlich schon aus wenn du dir hier die WndProc ableitest und darin die beiden Messages abfängst.

Ansonsten ändere in deinem Code nach der Messagebox das return 1 auf return 0 ab, müsste dann auch funktionieren! Aber wie gesagt nur um dein Programm nicht schliessen zu lassen brauchst du keinen Hook.

Grüße
R.
 
Zuletzt bearbeitet:
Dankeschön, das hat mir wirklich geholfen :)

habe das schließen meines Fensters jetzt folgendermaßen unterbunden:
Code:
// to control ClosingEvent
private: static bool closingActive = false;
/...

private: System::Void form1_Closing(System::Object^ sender, System::ComponentModel::CancelEventArgs^ e)
			 {			
				 // if closingActive = false, dont close window
				 e->Cancel = (closingActive == false) ? true : false;
			 }

Das funktionier super, aber was noch immer nicht geht, ist eben dass man trotzdem noch mit der Windows Taste andere Fenster öffnen kann, beziehungsweise mit ALT TAB dieses Switch Fenster erscheint.... Zwar bleibt mein Fenster immer im Vordergrund, jedoch werden die Fenster (eben hinter meiner Anwendung) trotzdem noch erstellt, was ich eigentlich verhindern möchte...

mfG
 
Ich dachte es ginge nur darum das Schliessen deiner App zu verhindern. ... Asche über mein Haupt aber den zweiten Teil deiner Frage habe ich völlig überlesen, für Alt+Tab und andere Keyevents welche schon vor deiner App behandelt werden brauchst du natürlich den Hook.

Grüße
R.
 
Ritchie_Fomm hat gesagt.:
... Asche über mein Haupt

Ja, schäm dich :mad:

Nein,echt jetzt, vielen Dank nochmal, hast mir wirklich weitergeholfen *RoX0r*
tja... bleibt mir halt der Hook nicht erspart :( kann man nichts machen, werd halt schaun, dass ich irgend so etwas bastel...

GreeZ
c ya
 
Zurück