Das Forum ist aktuell sporadisch nicht erreichbar - wir arbeiten dran. Laut Fehlermeldung Service Unavailable oder Internal Server Error, wir sind allerdings im Hosting ... x

Userform als Icon TOPMOST über Taskbar
#1
Moin  21

ich habe da einen Windows 11 Multimonitor-PC, bei 2 Monitoren soll in der unteren rechten Ecke des Monitors eine Userform erscheinen (als Icon getarnt), das funktioniert.
Bei einem Rechts-Klick auf das Icon soll eine weitere Userform mit Buttons erscheinen, das funktioniert.
Bei einem Links-Klick sollen die Icons wieder verschwinden, das funktioniert.

Das Problem: Wenn die Icons in der rechten unteren Ecke zu sehen sind und man dann zufällig auf die Taskleiste selber klickt (oder den Infobereich öffnet, oder auf die Uhr klickt) dann verschwindet das Icon hinter der Taskleiste.
SetWindowPos hWnd, HWND_TOPMOST hilft hier offensichtlich nicht.

.xlsm   Mappe1.xlsm (Größe: 112,65 KB / Downloads: 9)

Hat jemand eine Idee wie man das Icon wieder vor die Taskleiste kriegt? Oder verhindert das es verschwindet?

BTW, früher wurde das Icon via Shell_NotifyIcon im Infobereich erzeugt. Das funktionierte weil wir ein Tool "Actual Window Manager" haben der auf jedem Monitor einen Infobereich erzeugt. Das geht zwar immer noch, jedoch lässt sich aktuell die Sichtbarkeit des Icon unter Windows 11 nicht mehr steuern => alle Icons verschwinden im Infobereich und man muss diesen jedesmal wieder neu öffnen. Das ist verständlicher Weise nervig.

Andreas.
Antworten Top
#2
Hallo Andreas,

ein paar Gedanken dazu:

- Ich bin mit 64 Bit-Excel unterwegs. Du scheinbar nicht, denn Du hast zwar sehr oft die Declares nach 64/32 Bit unterschieden, aber nicht konsequent alles und auch das hWnd-Handle nicht.

- Das mit den Icons in der Taskleiste (Shell-NotifyIcon) hatte ich vor ewigen Zeiten gerne auch genutzt, bis sie später unkontrolliert (mal ja, mal nein) in der ausgeblendeten Iconsammlung verschwanden. Da kam Frust bei mir auf, deshalb kann ich deine Aussagen hierzu gut nachvollziehen.

- Die TOPMOST-Funktionalität funktioniert in der Tat nicht. Theoretisch könnte man sie ja mehrmals zuordnen, aber nur ein Fenster kann oben sein. Vielleicht setzt ein Klick auf die Taskleiste diese auf TOPMOST.

- Die Funktionen SetForegroundWindow oder BringWindowToTop setzen Deine Userform wieder nach oben. Man muss natürlich mitbekommen, dass sie weg ist und diese Funktionen dann anstoßen. Das denke ich, ist die schwierige Übung. Bin grad in Urlaub und kann da nicht rumtüfteln und habe zur Zeit außer Timer setzen leider keine Idee dazu.

Eventuell lässt sich auch etwas mit Eventhooking machen über SetWinEventHook.

Vielleicht hat ja noch einer eine zündende Idee dazu.

Gruß
Karl-Heinz
Antworten Top
#3
Hallo Andreas,
 
Ich habe mal den 64 Bit Kram vervollständigt.
Wenn es dich nicht stört, also das Userform scheinminimiert oberhalb der Taskleiste, um das nach hinten rutschen zu verhindern wäre dies so wie in der Datei zu machen. Eingebaut habe ich es im Userform "ufTrayIcon1".
 
Ich habe keinen Weg gefunden, wie man das Userform oberhalb der Taskleiste halten kann. Einzig, aber da fehlen auch mir die Kenntnisse, wäre das Klick-Event der Taskleiste abzufangen, so dies überhaupt mit der Win API möglich ist (vermutlich wohl eher nicht). 
Wenn doch, dann siehe Karl-Heinz.

.xlsm   Mappe1.xlsm (Größe: 109,78 KB / Downloads: 2)
 
Gruß Uwe
Antworten Top
#4
(04.05.2026, 19:48)volti schrieb: - Ich bin mit 64 Bit-Excel unterwegs. Du scheinbar nicht, denn Du hast zwar sehr oft die Declares nach 64/32 Bit unterschieden, aber nicht konsequent alles und auch das hWnd-Handle nicht.

- Die Funktionen SetForegroundWindow oder BringWindowToTop setzen Deine Userform wieder nach oben. 

Hallo  Karl-Heinz,

BringWindowToTop ist schon mal eine Idee, das könnte ich evt. mit einem Timer (SetTimer / TimerFunc / KillTimer) alle 500ms anschubsen... wenn man aber tatsächlich mal den Infobereich braucht/öffnet gibt das bestimmt Probleme... mal kucken.

Andreas.

(04.05.2026, 23:36)Egon12 schrieb: Ich habe mal den 64 Bit Kram vervollständigt.

Hallo Uwe,

sehr nett, aber leider völlig überflüssig. Das Gesamtprojekt ist wesentlich größer, die ufPopupMenu macht dann ja auch noch was. 
Ich hatte vor Jahren alles schon mal auf 64-bit probiert, das Verhalten ist leider ein anderes. Es reicht bei weitem nicht einfach einen Code 64-bit fähig zu machen, er muss auch das gleiche bewirken.
Von daher bin ich an 64-bit (für dieses Projekt) nicht interessiert.

Zu meiner Entschuldigung, die Testdatei oben habe ich nur quick&dirty zusammen gepfuscht, daher sieht der Code ein wenig "komisch" aus.

Andreas.
Antworten Top
#5
(05.05.2026, 05:51)Andreas Killer schrieb: BringWindowToTop ist schon mal eine Idee, das könnte ich evt. mit einem Timer (SetTimer / TimerFunc / KillTimer) alle 500ms anschubsen... wenn man aber tatsächlich mal den Infobereich braucht/öffnet gibt das bestimmt Probleme... mal kucken.

Prinzipiell funktioniert das, hat aber einen Nachteil: Dieser API-Aufruf macht das Fenster auch zum Vordergrundfenster, d.h. Tastendrücke (die z.B. von einer programmierbaren Tastatur abgesetzt werden) landen dann ebenso in diesem Fenster.

Ich habe im Timer schon versucht:
Code:
Public Function TrayTimerFunc(ByVal hWnd As Long, ByVal wMsg As Long, ByVal nEvent As Long, ByVal nSecs As Long) As Long
  Dim SavehWnd As Long
  SavehWnd = GetForegroundWindow
  BringWindowToTop hWnd
  'SetWindowPos hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE Or SWP_NOMOVE Or SWP_NOSIZE
  SetForegroundWindow SavehWnd
End Function

Das funktioniert alles nicht.

Kann man Windows veranlassen die Verarbeitung von (Tastatur-)Befehlen auszusetzen (bis meine TrayTimerFunc) gelaufen ist?

Oder gibt es eine Möglichkeit festzustellen ob meine Userform hinter der Taskleiste verborgen ist?

Andreas.
Antworten Top
#6
Hallo Andreas,

nur mal so als Idee: wäre es nicht einfacher, die Userform einfach oberhalb der Taskleiste in der rechten Ecke zu positionieren? Dann gäbe es zumindest keine Interaktionen mit der Taskleiste mehr.

Knobbi38
Antworten Top
#7
Warum nicht in dem QAT ? Das Icon ist nicht notwendig ein Userform, was erscheint nach Klicken doch.
Zum übersetzen von Excel Formeln:

http://dolf.trieschnigg.nl/excel/index.p...gids=en+de
Antworten Top
#8
Hallo Andreas,

wenn alles scheitert hier vielleicht noch eine Idee:

https://www.clever-excel-forum.de/Thread...-Tray-Icon

Gruß KH
Antworten Top
#9
(06.05.2026, 10:29)knobbi38 schrieb: nur mal so als Idee: wäre es nicht einfacher, die Userform einfach oberhalb der Taskleiste in der rechten Ecke zu positionieren? Dann gäbe es zumindest keine Interaktionen mit der Taskleiste mehr.

Ja, allerdings ist sie dann vor dem Fenster und die ufPopupMenu macht ja auch noch was... die interagiert mit dem Fenster (und ggf. weiteren) und dazu muss das Fenster in den Vordergund kommen... welches dann statt der Taskbar vor dem Icon ist.

Die Position ist schon passend, ein besonderes Fenster ist "nicht normal" sondern erstreckt sich über 2 Monitore und hat intern div. "Unterfenster". Übles Konstrukt.

(06.05.2026, 10:48)snb schrieb: Warum nicht in dem QAT ? Das Icon ist nicht notwendig ein Userform, was erscheint nach Klicken doch.

Die QAT geht nicht, weil die Application nicht sichtbar ist. BTW, das ganze läuft in einer 2ten Instanz die dazu auch nicht auf DDE-Befehle reagiert, so das diese quasi abgekoppelt wie ein Hintergrundprozess läuft.

(06.05.2026, 12:30)volti schrieb: wenn alles scheitert hier vielleicht noch eine Idee:
https://www.clever-excel-forum.de/Thread...-Tray-Icon

TrayIcon via Shell_NotifyIcon geht nicht weil ich die Sichtbarkeit des Icon nicht steuern kann. Sagte ich schon, Bug mit "Actual Window Manager" und "Windows 11".

Ich denke ich habe einen gangbaren Workaround gefunden, ich muss die Userform ja nur vor die Taskleiste holen wenn es notwendig ist. Und das ist nur dann der Fall wenn diese HWND_TOPMOST wird, was nur dann (?) der Fall ist wenn der User mit Ihr interagiert. In diesem Moment kann ich eigentlich davon ausgehen das kein Tastaturmakro oder sonstige automatisierte Interaktion läuft.

Code:
Private Function IsTaskbar(ByVal hWnd As Long) As Boolean
  Dim root As Long
  Dim sClass As String
  Dim lLen As Long
  root = GetAncestor(hWnd, GA_ROOT)
  sClass = String(256, " ")
  lLen = GetClassName(root, sClass, 256)
  sClass = Left$(sClass, lLen)
  Select Case sClass
    Case "Shell_TrayWnd", "Shell_SecondaryTrayWnd", "ActualTools_MultiMonitorTaskbar"
      IsTaskbar = True
  End Select
End Function

Public Function TrayTimerFunc(ByVal hWnd As Long, ByVal wMsg As Long, ByVal nEvent As Long, ByVal nSecs As Long) As Long
  Dim hWndPrev As Long
  Dim BehindTaskbar As Boolean
 
  hWndPrev = GetWindow(hWnd, GW_HWNDPREV)
  Do While hWndPrev <> 0
    If IsTaskbar(hWndPrev) Then
      BehindTaskbar = True
      Exit Do
    End If
    hWndPrev = GetWindow(hWndPrev, GW_HWNDPREV)
  Loop
 
  If BehindTaskbar Then
    'Debug.Print "BringWindowToTop", Now
    BringWindowToTop hWnd
  End If
End Function

Mal kucken wie das in der Praxis funktioniert.

Trotzdem vielen Dank für die Ideen.

Andreas.
Antworten Top
#10
Upps,

ich hatte den falschen Link eingefügt.

Ich meinte ein normales Icon in der Taskleiste, kein TrayIcon, wie von Dir ja schon beschrieben.

https://www.clever-excel-forum.de/Thread...e-anzeigen

Aber Du hast ja jetzt eine Lösung....

Gruß KH
Antworten Top


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste