![]() |
Systray-Icon in eigener Klasse
Hallo erstmal an alle,
ich probiere grad für eine Applikation eine Unit mit einer Klasse zu erstellen damit ich einfach ein Icon im Systray plazieren kann und ein Menü bei Rechtsklick darauf anzuzeigen. Das mit dem Icon klappt auch alles ganz gut aber ich bekomme die CallbackMessage nicht mit -> will sagen bei Mausklick wird meine Prozedur nicht aufgerufen :( Folgendes zu dem Thema hab ich mir angesehen aber hat mir leider nciht weitergeholfen: Hier mal meine Unit:
Delphi-Quellcode:
Die Prozedur onTrayiconMessage wird einfach nie aufgerufen, wäre nett wenn mir jemand da n Tipp
(* *****************************************************************************
Author := Mika Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Unit mit Methoden um ein Icon in der Trayleiste zu plazieren und auf dessen Ereignisse zu achten. ***************************************************************************** *) unit uSystray; interface uses ShellApi, Windows, Messages, Forms; Type TSystrayIcon = Class Trayicon: TNotifyIconData; Constructor newCreate(IconHint: String); Destructor newDestroy; private Procedure onTrayiconMessage(Var Msg: TMsg); message WM_USER; Procedure AddIconToSystray(TrayiconDescription: String); Procedure RemoveIconFromSystray; end; implementation Constructor TSystrayIcon.newCreate(IconHint: String); Begin Inherited Create; AddIconToSystray(IconHint); End; Destructor TSystrayIcon.newDestroy; Begin RemoveIconFromSystray; Inherited Destroy; End; (* ***************************************************************************** Author := Mika Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Fügt dem Systray ein neues Icon hinzu das auf Mausklicks reagiert um ein Menü anzuzeigen. ***************************************************************************** *) Procedure TSystrayIcon.AddIconToSystray(TrayiconDescription: String); begin Fillchar(Trayicon.szTip, SizeOf(Trayicon.szTip), 0); Move(TrayiconDescription[1], Trayicon.szTip, Length(TrayiconDescription)); Trayicon.cbSize := SizeOf(Trayicon); Trayicon.Wnd := Application.Handle; Trayicon.uFlags := NIF_ICON or NIF_TIP or NIF_MESSAGE; Trayicon.hIcon := Application.Icon.Handle; Trayicon.uID := 27787552; Trayicon.uCallbackMessage := WM_USER; Shell_NotifyIcon(NIM_DELETE, @Trayicon); Shell_NotifyIcon(NIM_ADD, @Trayicon); end; (* ***************************************************************************** Author := Mika Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Entfernt das Trayicon aus dem Systray. ***************************************************************************** *) Procedure TSystrayIcon.RemoveIconFromSystray; Begin Shell_NotifyIcon(NIM_DELETE, @Trayicon); End; (* ***************************************************************************** Author := Mika Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Reagiiert auf Mausklicks auf das Trayicon und zeigt ein Menü an bei Rechtsklick ***************************************************************************** *) Procedure TSystrayIcon.onTrayiconMessage(Var Msg: TMsg); Var Point: Tpoint; Begin GetCursorPos(Point); if (Msg.wParam = WM_LBUTTONDOWN) then begin end else if (Msg.wParam = WM_RBUTTONDOWN) then begin end; End; end. geben könnte ! Alles gute, Michael. |
Re: Systray-Icon in eigener Klasse
Schau dir mal TrackPopupMenu und Brüderchen TrackPopupMenuEx an ;)
|
Re: Systray-Icon in eigener Klasse
Delphi-Quellcode:
uses
Menus; type TSystrayIcon = class ... private FHandle: cardinal; FPopupMenu: TPopupMenu; WM_TASKBAREVENT: cardinal; WM_TASKBARCREATED: cardinal; procedure MessageHandler(var Msg: TMessage); ... end; implementation constructor TSystrayIcon.Create; begin inherited; FHandle := AllocateHWnd(MessageHandler); WM_TASKBAREVENT := RegisterWindowMessage(ClassName); WM_TASKBARCREATED := RegisterWindowMessage('TaskbarCreated'); // wenn der explorer abscheißt, das das icon von deinem progrämmchen wiederhergestellt wird ... end; destructor TSystrayIcon.Destroy; begin DeallocateHWnd(FHandle); ... inherited; end; procedure TSystrayIcon.MessageHandler(var Msg: TMessage); begin if Msg.Msg = WM_TASKBAREVENT then begin ... hier dein GetCursorPos(ptCursor); ... if Assigned(FPopupMenu) then FPopupMenu.Popup(ptCursor.X, ptCursor.Y); ... end else if Msg.Msg = WM_TASKBARCREATED then AddIconToSysTray('blah'); end; |
Re: Systray-Icon in eigener Klasse
Hallo zusammen!
@olli: Ich glaube nicht, dass er das meint :wink: @barf00s: Ich bin auch grade bei dem Thema und habe das so gelöst (jetzt nur ausm Kopf):
Delphi-Quellcode:
Grüße, Marco
uses
{...,} ShellAPI; type TForm1 = class(TForm) // ... procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); // ... private { Private-Deklarationen } FOldWndProc: TWndMethod; FTrayCallbackMsg: Cardinal; procedure MyWndProc(var Msg: TMessage); // ... end; // ... implementation // ... procedure TForm1.MyWndProc(var Msg: TMessage); begin if Msg.Msg = FTrayCallbackMsg then begin case Msg.LParam of WM_LBUTTONDBLCLK: begin // ... end; WM_RBUTTONDOWN: begin // ... end // Weitere abzufragende Tray-Icon-Botschaften... end; end; FOldWndProc(Msg); end; procedure TForm1.FormCreate(Sender: TObject); var TrayIcon: NOTIFYICONDATA; begin // Tray-Icon hinzufügen // ... FTrayCallbackMsg := RegisterWindowMessage('MyTrayCallbackMessage'); TrayIcon.uCallbackMessage := FTrayCallbackMsg; // ... // Eigene Window Procedure "registrieren" FOldWndProc := WindowProc; WindowProc := MyWndProc; end; procedure TForm1.FormDestroy(Sender: TObject); begin WindowProc := FOldWndProc; end; |
Re: Systray-Icon in eigener Klasse
Oops, den janzen Code hast du ja schon... Na jendenfalls, bei mir funktioniert's (nach meinem Code antürlich :stupid:).
Gruß, Marco |
Re: Systray-Icon in eigener Klasse
naja, aber dann hasts nichmehr so schön gekapselt ... naja wers brauch
|
Re: Systray-Icon in eigener Klasse
Hmm, was machst du da mit AllocateWnd herum?!
Delphi-Quellcode:
Gruß, Marco
procedure TSystrayIcon.Create(AOwnerForm: TForm);
// ... FHandle := AOwnerForm.Handle; FOldWndProc := AOwnerForm.WindowProc; // Member hinzufügen! AOwnerForm.WindowProc := MessageHandler; // ... end; procedure TSystrayIcon.Destroy(); // ... AOwnerForm.WindowProc := FOldWndProc; // ... end; |
Re: Systray-Icon in eigener Klasse
mit dem AllocateHWnd erstellt mirn Handle für meine klasse, ohne das ich auf ne ParentForm/Application zurückgreifen muss und deren WindowProcs verändern muss
so kannst das traydingen für jedes andere program auch benutzen - auch wenns keine Form enthält |
Re: Systray-Icon in eigener Klasse
Danke schonmal für die Antworten !!
@ Olli: Das mit dem TrackPopupMenu schau ich mir nachher mal an! @ barf00s: Hab den Code so eingebaut bekomme aber in dem newCreate bei der Zeile:
Delphi-Quellcode:
Die Fehlermeldung: Inkompatible Typen Shortstring und PChar! Stumpfes Typecasten hat
WM_TASKBAREVENT := RegisterWindowMessage(ClassName);
auch nicht geholfen mittels PChar() Wisst Ihr Rat? [Edit] Ja ich will das gerne schön abgekapselt haben damits universeller bleibt und ich möcht auch nicht wirklich gerne mit Forms arbeiten dabei ;) Will halt ne schöne saubere Klasse haben wenns fertig ist. [/Edit] |
Re: Systray-Icon in eigener Klasse
Zitat:
|
Re: Systray-Icon in eigener Klasse
hab ich auch nicht abgestritten - jedoch ist dieser weg besser als mit den windowprocs von irgendwelchen forms zumzuspieln - find ich :)
|
Re: Systray-Icon in eigener Klasse
Hab mir da jetzt was zusammengebastelt das sich auch kompilieren lässt ;)
Allerdings wenn ich mit der Maus auf mein Symbol klicke gibt er in Msg.Msg einen anderen Code an als den den ich in WM_TASKBAREVENT durch das RegisterWindowMessage bekommen habe: Will heissen er springt in der CallbackProzedur nicht in den richtigen Teil der If Abfrage. Hier mal mein jetziger Code:
Delphi-Quellcode:
(* *****************************************************************************
Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Unit mit Methoden um ein Icon in der Trayleiste zu plazieren und auf dessen Ereignisse zu achten. ***************************************************************************** *) unit uSystray; interface uses ShellApi, Windows, Messages, Forms, Menus, Classes; Const FMyCallbackMessage = 'TSystrayCallback'; Type TSystrayIcon = Class FHandle: THandle; WM_TASKBAREVENT: Cardinal; WM_TASKBARCREATED: Cardinal; FTrayicon: TNotifyIconData; FTrayDescription: String; FPopupMenu: TPopupMenu; Constructor newCreate(IconHint: String); Destructor newDestroy; private Procedure MessageHandler(Var Msg: TMessage); Procedure AddIconToSystray(Description: String); Procedure RemoveIconFromSystray; end; implementation (* ***************************************************************************** Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Erzeugt ein Objekt der Klasse und erstellt das Icon im Systray, falls der Explorer abstürzt wird das Icon beim Start wieder hergestellt. ***************************************************************************** *) Constructor TSystrayIcon.newCreate(IconHint: String); Begin Inherited Create; FHandle := AllocateHWnd(MessageHandler); WM_TASKBAREVENT := RegisterWindowMessage(fMyCallbackMessage); // Hier bekomme ich einen // Wert von 49774 zurück WM_TASKBARCREATED := RegisterWindowMessage('TaskbarCreated'); FTrayDescription := IconHint; AddIconToSystray(FTrayDescription); End; (* ***************************************************************************** Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Zerstört das Objekt und entfernt das Icon aus dem Systray ***************************************************************************** *) Destructor TSystrayIcon.newDestroy; Begin DeallocateHWnd(FHandle); RemoveIconFromSystray; Inherited Destroy; End; (* ***************************************************************************** Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Reagiiert auf Mausklicks auf das Trayicon und zeigt ein Menü an bei Rechtsklick ***************************************************************************** *) Procedure TSystrayIcon.MessageHandler(Var Msg: TMessage); Var ptCursor: Tpoint; Begin if Msg.Msg = WM_TASKBAREVENT then // Wenn ich mit der Maus auf mein Symbol klicke // Bekomme ich in Msg.Msg den Wert 28 zurück :( begin GetCursorPos(ptCursor); if Assigned(FPopupMenu) then FPopupMenu.Popup(ptCursor.X, ptCursor.Y); end else if Msg.Msg = WM_TASKBARCREATED then begin AddIconToSysTray(FTrayDescription); end; End; (* ***************************************************************************** Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Fügt dem Systray ein neues Icon hinzu das auf Mausklicks reagiert um ein Menü anzuzeigen. ***************************************************************************** *) Procedure TSystrayIcon.AddIconToSystray(Description: String); begin Fillchar(FTrayicon.szTip, SizeOf(FTrayicon.szTip), 0); Move(Description[1], FTrayicon.szTip, Length(Description)); FTrayicon.cbSize := SizeOf(FTrayicon); FTrayicon.Wnd := Application.Handle; FTrayicon.uFlags := NIF_ICON or NIF_TIP or NIF_MESSAGE; FTrayicon.hIcon := Application.Icon.Handle; FTrayicon.uID := 27787552; FTrayicon.uCallbackMessage := WM_TASKBAREVENT; Shell_NotifyIcon(NIM_DELETE, @FTrayicon); Shell_NotifyIcon(NIM_ADD, @FTrayicon); end; (* ***************************************************************************** Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Entfernt das Trayicon aus dem Systray. ***************************************************************************** *) Procedure TSystrayIcon.RemoveIconFromSystray; Begin Shell_NotifyIcon(NIM_DELETE, @FTrayicon); End; end. |
Re: Systray-Icon in eigener Klasse
Hallo Mika,
dann will ich mal ein bisschen klugscheißen :mrgreen: Zitat:
Zitat:
Zitat:
Zitat:
Zitat:
Grüße, Marco |
Re: Systray-Icon in eigener Klasse
Zitat:
der rest funktioniert ansonsten prima |
Re: Systray-Icon in eigener Klasse
Zitat:
Zitat:
Zitat:
Zitat:
als den den ich zurückbekomme. Schönen Gruß und Danke für eure Hilfe ich guck mal ob ichs mit den ganzen Tipps hinbekomme, meld mich nachher nochmal. |
Re: Systray-Icon in eigener Klasse
Hmmmmm
nichtsdestotrotz bekomme ich es irgendwie nicht hin das in Msg.Msg der Wert steht den ich mittels RegisterWindow ermittelt und beim erzeugen des Icons in uCallbackMessage eingetragen habe! Das mit dem LParam abfragen ist erst mal nicht so wichtig ich will erstmal nur das er merkt: Ahhh das Icon das angeklickt wurde ist meins also muss ich auch was machen! |
Re: Systray-Icon in eigener Klasse
Hallo mika,
war nich bös gemeint :wink: Zitat:
Delphi-Quellcode:
Wenn das Label beim Überfahren resp. Anklicken des Tray-Icons seine Beschriftung nicht ändert, melde dich nochmal... :nerd:
Label1.Caption := 'Tray Message.';
Gruß, Marco |
Re: Systray-Icon in eigener Klasse
Ich fass sowas auch nciht bös auf ;)
So nu aber nochmal zur Problematik
Delphi-Quellcode:
Er geht in die Prozedur wenn ich auf irgendein(!) Icon in dem Systray klicke, mein Problem
Procedure TSystrayIcon.MessageHandler(Var Msg: TMessage);
Var ptCursor: Tpoint; Begin if Msg.Msg = FTaskbarEvent then begin If Msg.LParam = WM_RBUTTONDOWN then begin GetCursorPos(ptCursor); if Assigned(FPopupMenu) then FPopupMenu.Popup(ptCursor.X, ptCursor.Y); end else If Msg.LParam = WM_LBUTTONDOWN then begin MessageBox(Application.Handle, 'Test', 'test', MB_OK) end; end else if Msg.Msg = FTaskbarCreated then begin AddIconToSysTray(FTrayDescription); end; End; ist halt bloss das in Msg.Msg immer 28 drinsteht, egal ob ich auf mein Icon oder das von der Lautstärkeregelung von Windows klicke.... Ergo ist (Msg.Msg = FTaskbarevent) nie TRUE :( |
Re: Systray-Icon in eigener Klasse
Na alsooooo jetzt hab ichs :)
mein Fehler war das ich beim erstellen des Icons als Handle das Handle der Applikation angegeben habe nicht das Handle das ich bei newCreate für den MessageHandler ermittelt habe! Hier noch mal der Code falls den jemand braucht, ich fang jetzt an da mal n bisschen Funktionalität einzubasteln :) Und dank an alle die sich mit mir bemüht haben :D
Delphi-Quellcode:
(* *****************************************************************************
Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Unit mit Methoden um ein Icon in der Trayleiste zu plazieren und auf dessen Ereignisse zu achten. ***************************************************************************** *) unit uSystray; interface uses ShellApi, Windows, Messages, Forms, Menus, Classes, StdCtrls; Type TSystrayIcon = Class FHandle: Cardinal; FOldWndProc: TWndMethod; FTaskbarEvent: Cardinal; FTaskbarCreated: Cardinal; FTrayicon: TNotifyIconData; FTrayDescription: String; FPopupMenu: TPopupMenu; Constructor newCreate(IconHint: String); Destructor newDestroy; private Procedure MessageHandler(Var Msg: TMessage); Procedure AddIconToSystray(Description: String); Procedure RemoveIconFromSystray; end; implementation (* ***************************************************************************** Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Erzeugt ein Objekt der Klasse und erstellt das Icon im Systray, falls der Explorer abstürzt wird das Icon beim Start wieder hergestellt. ***************************************************************************** *) Constructor TSystrayIcon.newCreate(IconHint: String); Begin Inherited Create; FHandle := AllocateHWnd(MessageHandler); FTaskbarEvent := RegisterWindowMessage('SystrayCallback'); FTaskbarCreated := RegisterWindowMessage('TaskbarCreated'); FTrayDescription := IconHint; AddIconToSystray(FTrayDescription); End; (* ***************************************************************************** Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Zerstört das Objekt und entfernt das Icon aus dem Systray ***************************************************************************** *) Destructor TSystrayIcon.newDestroy; Begin DeallocateHWnd(FHandle); RemoveIconFromSystray; Inherited Destroy; End; (* ***************************************************************************** Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Reagiert auf Mausklicks auf das Trayicon und zeigt ein Menü an bei Rechtsklick ***************************************************************************** *) Procedure TSystrayIcon.MessageHandler(Var Msg: TMessage); Var ptCursor: Tpoint; Begin if Msg.Msg = FTaskbarEvent then begin If Msg.LParam = WM_RBUTTONDOWN then begin GetCursorPos(ptCursor); if Assigned(FPopupMenu) then FPopupMenu.Popup(ptCursor.X, ptCursor.Y); end else If Msg.LParam = WM_LBUTTONDOWN then begin MessageBox(Application.Handle, 'Test', 'test', MB_OK) end; end else if Msg.Msg = FTaskbarCreated then begin AddIconToSysTray(FTrayDescription); end; End; (* ***************************************************************************** Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Fügt dem Systray ein neues Icon hinzu das auf Mausklicks reagiert um ein Menü anzuzeigen. ***************************************************************************** *) Procedure TSystrayIcon.AddIconToSystray(Description: String); begin Fillchar(FTrayicon.szTip, SizeOf(FTrayicon.szTip), 0); Move(Description[1], FTrayicon.szTip, Length(Description)); FTrayicon.cbSize := SizeOf(FTrayicon); FTrayicon.Wnd := FHandle; FTrayicon.uFlags := NIF_ICON or NIF_TIP or NIF_MESSAGE; FTrayicon.hIcon := Application.Icon.Handle; FTrayicon.uCallbackMessage := FTaskbarEvent; FTrayicon.uID := 27787552; Shell_NotifyIcon(NIM_DELETE, @FTrayicon); Shell_NotifyIcon(NIM_ADD, @FTrayicon); end; (* ***************************************************************************** Datum der Erstellung := 07-06-2005 Datum der letzten Änderung := 07-06-2005 Entfernt das Trayicon aus dem Systray. ***************************************************************************** *) Procedure TSystrayIcon.RemoveIconFromSystray; Begin Shell_NotifyIcon(NIM_DELETE, @FTrayicon); End; end. |
Re: Systray-Icon in eigener Klasse
-.-°
auf das newCreate / newDestroy solltest verzichten und stattdessen die methoden "Create" und "Destroy" auch benutzen die schon vorhanden sind, denn sonst würdest du deinen "newDestroy" in etwa direkt aufrufen, und DAS soll man vermeiden...
Delphi-Quellcode:
implementation
public
constructor Create(const AHint: string); destructor Destroy; override; end; und dann hier dementsprechend definieren... ohne dieses "new" davor :) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:57 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz