Notification Area aktualisieren

18/11/2009 - 01:51 von Martin Speer | Report spam
Guten Morgen zusammen,

wie kann ich den Systray-Bereich / Notification Area aktualisieren um
beispielsweise "Geist-Icons" verschwinden zu lassen? Diese können auf
verschiedene Arten entstehen, z.B. wenn ein Programm mit Icon über
process.kill beendet wird. Also, es geht um den refresh.

Über Spy++ hab ich versucht an die Klassennamen zu gelangen um ein WM_Paint
an das Handle zu schicken. Da ich nicht ganz sicher bin an welche Klasse die
Message muß, habe ich mit mehreren probiert. Siehe hier meine Versuche:

Public Const WM_PAINT As Integer = &HF

<System.Runtime.InteropServices.DllImport("user32",
EntryPoint:="FindWindowEx")> _
Public Shared Function FindWindowExA(ByVal hWnd1 As Integer, ByVal hWnd2
As Integer, ByVal lpsz1 As String, ByVal lpsz2 As String) As Integer
End Function

<System.Runtime.InteropServices.DllImport("user32.dll",
EntryPoint:="FindWindow", SetLastError:=True,
CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
Private Shared Function FindWindowByClass(ByVal lpClassName As String,
ByVal zero As IntPtr) As IntPtr
End Function

<System.Runtime.InteropServices.DllImport("USER32.DLL")> _
Public Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal msg As
Integer, ByVal character As Integer, ByVal lpsText As IntPtr) As Integer
End Function


Private shelltraywnd As Integer = FindWindowByClass("Shell_TrayWnd",
Nothing)
Private traynotifywnd As Integer = FindWindowExA(shelltraywnd, 0,
"TrayNotifyWnd", Nothing)
Private trayclockwclass As Integer = FindWindowExA(traynotifywnd, 0,
"TrayClockWClass", Nothing)

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
SendMessage(traynotifywnd, WM_PAINT, 0, IntPtr.Zero)
End Sub

Wieso scheitern meine Versuche? Wie kann ich den Systray richtig
aktualisieren?

Viele Grüße,

Martin
 

Lesen sie die antworten

#1 Armin Zingler
18/11/2009 - 03:19 | Warnen spam
Martin Speer schrieb:
Wieso scheitern meine Versuche? Wie kann ich den Systray richtig
aktualisieren?



Schalte zuerst Option Strict On ein und behebe die Fehler. Geht's immer noch nicht?

Du hast ein buntes Durcheinander von Integer und IntPtr. Wenn es nur auf 32-Bit Windows
laufen soll, dürfte das aber nicht das Problem sein. Ich hab's trotzdem mal umgestellt.
Sorry für die "Declares" (und die Umschreiberei), denn ich kenne mich mit dem <dllimport>-Attribut
nicht so gut aus. Musst du ja nicht verwenden, aber die Typen solltest du übernehmen.

Aber zum Thema: Es wird nichts nützen, das Fenster neu zu zeichnen, denn wer sagt denn,
dass dabei das Icon entfernt wird? Der Explorer prüft ja nicht bei jedem Zeichen, ob
der Prozess, der das Icon erstellt hat, noch làuft. Zumindest bei XP ist das so.
Wenn ein verwaistes icon angezeigt wird und du Strg+Alt+Entf drückst und das Fenster mit Esc
wieder schließt, wird der Bereich ja auch neu gezeichent und das Icon wird trotzdem nicht entfernt.
Ich kenne es nur so, dass man die Maus darüber bewegen muss, damit das Icon entfernt wird.

Trotzdem noch der Code, mit dem ich getestet habe: (ich bekomme "success" angezeigt; wie gesagt,
relevant sind nur die Typen aus den Deklarationen)


Public Const WM_PAINT As Integer = &HF

Private Declare Auto Function FindWindowEx Lib "user32.dll" _
(ByVal hwndParent As IntPtr, ByVal hwndChildAfter As IntPtr, _
ByVal lpszClass As String, ByVal lpszWindow As String) _
As IntPtr

Private Declare Auto Function FindWindow Lib "user32.dll" _
(ByVal lpClassName As String, ByVal lpWindowName As IntPtr) As IntPtr

Private Declare Auto Function SendMessage Lib "user32.dll" _
(ByVal hwnd As IntPtr, ByVal msg As UInteger, ByVal wParam As UIntPtr, _
ByVal lParam As IntPtr) _
As IntPtr


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button1.Click

Dim shelltraywnd, traynotifywnd, trayclockwclass, result As IntPtr

shelltraywnd = FindWindow("Shell_TrayWnd", Nothing)

If shelltraywnd = IntPtr.Zero Then
ThrowWin32Exception("Fehler bei FindWindow")
End If

traynotifywnd = FindWindowEx(shelltraywnd, IntPtr.Zero, "TrayNotifyWnd", Nothing)

If traynotifywnd = IntPtr.Zero Then
ThrowWin32Exception("Fehler bei FindWindowEx")
End If

trayclockwclass = FindWindowEx(traynotifywnd, IntPtr.Zero, "TrayClockWClass", Nothing)

If trayclockwclass = IntPtr.Zero Then
ThrowWin32Exception("Fehler bei FindWindowEx")
End If

result = SendMessage(traynotifywnd, WM_PAINT, UIntPtr.Zero, IntPtr.Zero)

If result <> IntPtr.Zero Then
ThrowWin32Exception("Fehler bei SendMessage")
End If

MsgBox("success!")

End Sub

Private Shared Sub ThrowWin32Exception(ByVal Message As String)

Throw New System.ComponentModel.Win32Exception( _
Runtime.InteropServices.Marshal.GetLastWin32Error, _
Message _
)

End Sub

Armin

Ähnliche fragen