Überprüfen ob Mein Programm den Focus hat, bzw. im Fordergrund läuft.

Meronax

Mitglied
Hallo zusammen,

entweder ich sehe momentan den Wald vor lauter Bäumen nicht, oder es ist tatsächlich komplizierter als ich mir dachte :)

Zu meinem Problem:

Ich habe einen Messenger für meine Firma Programmiert. Wenn der Messenger minimiert ist, erhält der User über einen Baloontooltip eine benachrichtigung sobald eine Nachricht ankommt.
Ob ein Fenster Minimiert ist lässt sich ja ganz einfach über den windowstate abfragen.

Sollte jedoch ein Benutzer das fenster nicht minimiert haben und ein anderes Fenster, z.b Outlook, davor liegen, erhält der User keinen Baloontip, da das Programm ja nicht minimiert wurde.

Wie kann ich abfragen ob mein Programm im Vordergrund läuft, bzw. den Focus hat?

ich wäre um eure Hilfe sehr dankbar.

lg Phil
 

Turri

Erfahrenes Mitglied
Hallo,

du könntest doch bei eingehender Nachricht dein Fenster einfach immer nach vorn bringen.
C#:
this.BringToFront();
 

Cromon

Erfahrenes Mitglied
Hallo Meronax

Du kannst die Funktion GetForegroundWindow verwenden und prüfen ob der Handle der Handle deiner Form ist. Wenn ja, dann ist dein Fenster das aktuell aktive, sonst nicht.

Grüsse
Cromon
 

Meronax

Mitglied
Hallo Cromon,

vielen dank für deinen Tip, damit hat es funktioniert!
für alle die ebenso ein solches Problem haben hier ein Beispielcode mit dem es klappt:

Diese Funktion im Code einbauen:
Code:
Private Declare Function GetForegroundWindow Lib "user32.dll" () As Long

danach kann über diese if abfrage geprüft werden ob das eigene Programm im Vordergrund ist:

Code:
If hwnd = GetForegroundWindow Then

elseif hwnd <> GetForegroundWindow then

end if

lg Phil
 

Shakie

Erfahrenes Mitglied
Hallo Meronax,

bedenke aber auch folgende Situation: es kann sein, dass das Fenster deines Programms vollständig auf dem Bildschirm angezeigt wird, obwohl es nicht den Fokus hat. Denke nur an zwei Fenster nebeneinander und keines davon maximiert. Meiner Meinung nach sollte in diesem Fall kein Baloon-Tip kommen.
Das heißt, was du wirklich wissen willst, ist nicht, ob das Fenster den Fokus hat, sondern ob es vollständig oder nur verdeckt gezeichnet wird. Oder?
 

Meronax

Mitglied
Hallo Shakie,

damit hast du vollkommen recht!
Ich kann mit dieser kleinen unschönheit leben, da die User vermutlich meistens Outlook oder andere Officeanwendungen im Fullscreenmode im Vordergrund laufen haben, aber wenn du zufällig einen weg kennst wie ich eine solche Abfrage bewerkstelligen könnte, wäre ich natürlich dankbar :)
 

Cromon

Erfahrenes Mitglied
Hallo Meronax

Auch da hast du eine Möglichkeit, das ist dann aber etwas komplizierter. Ich habe bei mir das ganze mal in einen Thread gepackt der das regelmässig prüft, aber du kannst das auch einfach als eine Funktion ohne Schleife und das ganze Threadzeugs machen. Die Idee dahinter ist sich kurz alle Desktopfenster auflisten zu lassen, zu prüfen ob das Fenster vor unserem Fenster liegt und wenn ja ob sich die Rechtecke überschneiden.

Da ich gerade kein .NET-Projekt zum Testen zur Hand hatte mit all den Imports habe ich es kurz in C++ gemacht, ich habe aber die thread- und C++-spezifischen Sachen versucht so kompakt wie möglich zu machen:
C++:
// TRUE -> weiter enumerieren
// FALSE -> aufhören
BOOL WINAPI EnumProc(HWND hWindow, LPARAM param) {
	struct ParamStruct {
		HWND hWindow;
		bool isObstructed;
	}* u = (ParamStruct*)param;

	// Das sollte eigentlich nie eintreffen, aber sobald wir mal obstructed sind
	// müssen wir nicht mehr weiter prüfen, wir können nicht plötzlich wieder visible werden
	if(u->isObstructed)
		return FALSE;

	// EnumDesktopWindows wird auch unser Fenster enumerieren -> ignorieren
	if(hWindow == u->hWindow)
		return TRUE;

	// Minimierte oder nicht sichtbare Fenster interessieren uns nicht
	if(!IsWindowVisible(hWindow))
		return TRUE;
	
	RECT rc = { 0 };
	GetWindowRect(hWindow, &rc);
	
	RECT myRc = { 0 };
	GetWindowRect(u->hWindow, &myRc);

	HWND hCurWnd = hWindow;
	bool isBehind = false;

	// GetNextWindow mit GW_HWNDNEXT gibt das auf der imaginären z-Achse
	// nächste Fenster zurück. Wenn das irgendwann unser Fenster ist sind wir also
	// von der z-Orientierung her hinter dem aktuellen Fenster
	while((hCurWnd = GetNextWindow(hCurWnd, GW_HWNDNEXT)) != nullptr) {
		if(hCurWnd == u->hWindow) {
			isBehind = true;
			break;
		}
	}

	// Ein Fenster hinter dem wir nicht sind kann uns auch nicht überdecken
	if(!isBehind)
		return TRUE;

	RECT dstRc = { 0 };
	if(IntersectRect(&dstRc, &rc, &myRc) != FALSE) {
		u->isObstructed = true;
		return FALSE;
	}

	return TRUE;
}

DWORD WINAPI testThread(LPVOID /* unused */) {
	HWND hWindow = sGxDevice->getWindow()->getHandle();
	struct { HWND hWindow; bool isObstructed; } u = { hWindow, false };

	while(isRunning) {
		u.isObstructed = false;

		if(GetForegroundWindow() != hWindow)
			EnumDesktopWindows(GetThreadDesktop(GetCurrentThreadId()), EnumProc, (LPARAM)&u);

		sDebugLog->notice(L"Window", (u.isObstructed ? L"obstructed": L"visible"));
		Sleep(1000);
	}

	ExitThread(0);
}

Was du mit diesem Code nicht erhälst ist wie stark das Fenster überdeckt ist, da müsstest du das was IntersectRect in dstRect schreibt auswerten und eine Art Liste führen welche Regionen deines Fensters schon überdeckt sind und welche nicht. Das ist dann aber ja nicht mehr so eine grosse Geschichte und hat nichts mehr API-spezifisches an sich :)

Viele Grüsse
Cromon
 
Zuletzt bearbeitet: