![]() |
Das Problem mit dem vergessenem TrayIcon
Was ich eigentlich schon seit Jahren fragen wollte es aber immer wieder vergesse, das ist das Problem mit dem nicht mehr gültigen TrayIcon. Wahrscheinlich gibt es dafür eine einfache Lösung und und garantiert 127 Beiträge hier im Forum wie man es lösen kann, aber ich finde es nicht, oder ich benutze die falschen Suchbegriffe.
Und zwar ist es so, dass ich mir für TrayIcon keine Komponente installieren will, also mache ich es immer alleine. Und alles funktioniert auch wie ich es will, nur nicht wenn das Programm beendet wird. Dann bleibt das TrayIcon immer noch sichtbar. Gehe ich mit dem Mauszeiger drüber, verschwindet es. Aber bis dahin bleibt es da. Und wenn ich das Programm fünf weitere Mal starte, dann habe ich fünf Icons da. Also wie räumt man den Bereich auf? |
AW: Das Problem mit dem vergessenem TrayIcon
ich rufe im FormClose
Delphi-Quellcode:
auf, dann ist es bei mir weg.
TrayIcon1.Destroy;
|
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
a) eine Komponente, die auf der Form liegt (liegen sollte) und damit als Owner diese Form hat. Und dieser Owner kümmert sich schon um die Freigabe b) egal was mit
Delphi-Quellcode:
freigeben sollte man besser lassen und dafür
Destroy
Delphi-Quellcode:
verwenden
Free
EDIT: und der TE setzt eben keine Komponente dafür ein |
AW: Das Problem mit dem vergessenem TrayIcon
Genauso, wie du manuell das TrayIcon erstellst, mußt du es natürlich auch manuell wieder freigeben, wenn dein Programm beendet wird. :stupid:
@sHoXx: Wenn ich das richtig mitbekommen hab, dann geht er selber über die WinAPI und nutzt eben keine fertige Komponente. PS: Hat TrayIcon1 deine Form als Owner, dann gibt dieses das automatisch frei. |
AW: Das Problem mit dem vergessenem TrayIcon
@sHoXx
Wie gesagt, ich habe keine Komponente. Ich hab in den Jahren an die zig Varianten ausprobiert und einige sahen sogar gut aus und der Icon verschwand meistens. Aber nur meistens. Irgendwas fehlt da. @himitsu Das versteht sich von selbst. Daran liegt es nicht. |
AW: Das Problem mit dem vergessenem TrayIcon
gut, ich dachte du verwendest die Standardkomponente, und wolltest dir keine anderweitige komponente installieren. Manchmal sind die Finger schneller als der Kopf :D
vielleicht zeigst du etwas code, an dem man sehen kann, wie dein selbst erstelltes tryicon aussieht |
AW: Das Problem mit dem vergessenem TrayIcon
Gibt es eine Standardkomponente in Delphi 7?
Ich hab mit der Zeit so viele Versionen getestet, eigene Kreationen, aber auch aus dem Internet. Somit kann ich einen beliebigen Code zeigen. Ich glaube die habe ich zuletzt verwendet: ![]() Und bevor himitsu wieder fragt, alle enthalten diese Zeile:
Delphi-Quellcode:
Shell_NotifyIcon(NIM_DELETE ...
|
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
|
AW: Das Problem mit dem vergessenem TrayIcon
Hi, meinst du mit:
Zitat:
|
AW: Das Problem mit dem vergessenem TrayIcon
Ich glaube das ist dann der Fall, wenn das Programm abrupt terminiert wird, sodass es nicht aufräumen und somit den Tray wegschießen kann!
Weil unter normalen Umständen verschwindet der auch. |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
a.) Komponente Vorteile: Wiederverwendbar, für den Programmier leicht zu benützen, in der Regel "idiotensicher" und Fehlerfrei Nachteile: muss installiert werden, bringt gewissen Overhead mit sich b.) eine Klasse (von TObject abgeleitet) Vorteile: Wiederverwendbar, relativ leicht zu benützen Nachteile: keine c.) direkter Aufruf von Windows API-Funktionen Vorteile: erlaubt auch spezielle Anpassungen Nachteile: nicht wiederverwendbar, Fehlerträchtig, Code verschmutzt die Anwendung, schlecht auf Veränderungen anpassbar Ein professioneller Programmierer kann eigentlich nur die Ansätze a.) oder b.) verwenden. Die Variante c.) ist für Cowboy-Programmierer. |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
bin ich doch lieber ein Cowboy-Programmierer Anstatt wie du "Ein professioneller Programmierer" Der alles in doppelter ausführung abgelegt haben muss letztendlich ruft auch deine Klasse die selbe API auf halt nur über Umwege und das soll professional sein? Zum Thema da gab es immer schon diverse probleme mit den Tray Icons das diese nicht oder schlecht aktualisiert wurden. Gab irgendwo mal einen Patch vom MS dafür .. hab ihn aber vergessen. gruss |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
Zitat:
Zitat:
b) gegen eine Klasse habe ich nichts und wenn alles fehlerfrei funktioniert, dann mache ich es sofort. Aber auch wenn die letzte Version relativ gut funktioniert, so nicht 100% fehlerfrei. Mich wundert es, dass es hier noch keinem aufgefallen ist, allerdings ist es nicht ein Problem einzig von mir. Ich hatte schon einige Delphi-Fremdprogramme bei denen auch diese Probleme vorkamen. c) mag sein, aber nicht selten schreibe ich die paar Zeilen schneller als das ich eine Unit oder Klasse erst suchen muß. Im Grunde genommen sind es nur paar Zeilen Code, wenn man nichts komplexes will, wie z.B. wechselnde Icons, Reaktionen auf verschiedene Aktionen, usw. Wenn man nur ein PopupMenu aufrufen will, sind es nur paar Zeilen. Aber hier geht es nicht drum was die einzig richtige Methode ist, sondern warum das Problem besteht. Soll ich irgendwann im hohen Alter meinen Enkeln erzählen, ich hatte da ein Problem, ich habe es aber nicht gelöst, ich habe einfach eine Fremdkomponente genommen? |
AW: Das Problem mit dem vergessenem TrayIcon
Du hast doch ne CallBack in der Shell_NotifyIcon API
Welche Message verwendest du denn dafür? Und das wäre eine möglichkeit! FindWindowEx GetClientRect SendMessage gruss |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
Hauptsache es funktioniert irgendwie, ist wohl deine Einstellung. Als "Profi" kann ich mir so etwas nicht leisten. Jede Unsauberkeit rächt sich später irgendwann (zumindest dann wenn man eine Software über mehr als 10 Jahre erweitern, verbessern und warten muss). Ich hab' hier mehrere Projekte mit zusammen 1,4 Mio Zeilen. Um dies zu bewältigen, muss man einfach jeden Zugriff auf die Windows API der etwas komplizierter ist auf irgendeine Art und Weise kapseln. Wenn Windows ein Handle zurückliefert mit dem weitere API-Funktionen aufgerufen werden, ist das ein ganz klares Zeichen, dass man das Handle mit einer Klasse kapseln muss. Auch Programmierer die nur so zum Spaß programmieren können noch was dazulernen indem sie ihre "Hauptsache es funktioniert" Einstellung ablegen. |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
![]() Wobei sich das obere Beispiel in einem Punkt von allen meinen Versuchen unterscheidet: es führt in FormDestroy die ganze Prozedur ein zweites Mal durch. Ich, und eigentlich auch die anderen Beispiele, führten in FormDestroy einfach nur
Delphi-Quellcode:
aus, hier ward alles noch mal zugewiesen. Aber bis auf NotifyIconData.Wnd Zuweisung sehe ich da keinen nennenswerten Unterschied. Trotzdem funktioniert der Code besser als die anderen. Aber auch nicht perfekt.
Shell_NotifyIcon(NIM_DELETE, @NotifyIconData)
Zitat:
|
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
Das sollte gehen. (Auf die schnelle zusammengetippt (Ungetestet)) Warnung API vom Cowboy-Programmierer
Delphi-Quellcode:
gruss
procedure CleanTray;
{Entfernt ungenutzte icons vom system tray} var TrayNotifyHwnd: HWND; ParentHwnd: HWND; TrayWindowRect: TRect; x: integer; y: integer; begin ParentHwnd := FindWindow('Shell_TrayWnd', ''); //Hwnd vom TrayNotifyWnd ermitteln TrayNotifyHwnd := FindWindowEx(ParentHwnd, 0, 'TrayNotifyWnd', ''); //ClientRect von der Classe TrayNotifyWnd einlesen GetClientRect(TrayNotifyHwnd, TrayWindowRect); x :=0; y :=0; while x < TrayWindowRect.Right do begin while y < TrayWindowRect.Bottom do begin SendMessage(TrayNotifyHwnd, WM_MOUSEMOVE, 0, (y shl 16) + x); y := y + 5; end; x := x + 5; end; end; |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
dann muß man nur an einer Stelle, in dieser Klasse, etwas ändern. Außerdem hat man den Code so an einer Stelle vereint, anstatt die verschiedenen Aufrufe/Funktionen eventuell noch sonstwo verteilt zu haben. (leichter zu finden) Und wenn diese Klasse dann auch noch mindestens in 2 Programmen verwendet wird, dann hast du gleich alle Programme automatisch angepaßt. |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
Grundsätzlich hast du aber schon recht. (Was Delphi angeht) PS:
Delphi-Quellcode:
NotifyIconData.uCallbackMessage := WM_TASKABAREVENT;
sollte WM_MOUSEMOVE sein. Deshalb meine Frage nach der CallbackMessage. gruss |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
Natürlich kann ich alles kapseln und ob du es glabst oder nicht, das mache ich auch, aber nicht immer. Warum soll ich die Funktion zum einlesen alle Daten eines Ordners auslagern, wenn das Programm selbst nie mehr als 30 Zeilen haben wird. Es gibt immer einen Unterschied ob man ein professionelles Programm schreibt oder schnell ein Problemlöser. |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
Zitat:
Ich glaub für die Taskleiste hatte ich in der DP mal einen Code gesehn. So, ich hab eventuell nicht alles mitbekommen. Wann bleiben denn nun Icons zurück? Nue wenn das Programm abstürtzt oder über den Debugger hart beendet wird, oder auch beim normalen Beenden? Bei Letzerem wäre es gut, wenn jemand seinen Code eventuell mal zeigen würde. |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
Aber das war ja nicht das Thema, da kamen wir nur so drauf. Zitat:
Zitat:
Zitat:
Zitat:
Wie gesagt: früher oder später kommt es bei jedem vor, bei einem früher, bei einem später. |
AW: Das Problem mit dem vergessenem TrayIcon
Warum wird das Icon nicht entfernt? Wenn du die WinAPI direkt bemühst, dann musst du es auch entfernen beim Beenden deines Programms:
Delphi-Quellcode:
Shell_NotifyIcon(NIM_DELETE, @nid);
|
AW: Das Problem mit dem vergessenem TrayIcon
Wie gesagt, das ist nicht das Problem, das ist klar.
|
AW: Das Problem mit dem vergessenem TrayIcon
Ist es irgend wie nicht. Du sagst, du beendest dein Programm und das deines Programms Icon bleibt übrig. Wenn ich das so mache, wie es Windows vorsieht, bleibt bei mir kein Icon zurück.
|
AW: Das Problem mit dem vergessenem TrayIcon
Seit dem ich denken kann räume ich mit
Delphi-Quellcode:
in FormDestroy das TrayIcon auf. Ich kenne es nicht anders. Seit über 10 Jahren sehe ich das als ein kleines Problem an, dem ich mich mal widmen wollte, wie heute zum Beispiel. Und um ehrlich zu sein, wollte ich gerade paar Beispiele als Code anfügen, kriege aber gerade den Fehler nicht reproduziert. Momentan funktionieren alle Versionen. Entweder es ist der Vorführeffekt oder ich weiß auch nicht. Vielleicht sollten wir die Diskussion fortführen wenn das Problem wieder auftaucht, und nicht wie heute mal zwischendurch die Frage stellen.
Shell_NotifyIcon(NIM_DELETE,
|
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
In dem ich den Aktiven Prozess einer Anwendung mit dem Taskmanager beende. Das hat (kann) zur folge haben dass das TrayIcon nicht entfernt wird. gruss |
AW: Das Problem mit dem vergessenem TrayIcon
Das wäre mir schon aufgefallen.
Wie ich es schon oben erwähnte, habe ich auch bei einigen fremden Programmen (mit Delphi geschrieben) das gleiche Problem beobachtet. Es waren Exe Dateien, die IDE war nicht im Spiel und was über Taskmanager beendet wird, zählt nicht. Aber ich melde mich wieder wenn ich wieder ein Programm geschrieben habe und das vorkommt. |
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
|
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
Darauf wollte ich nur hinweisen. Auch wenn er unten aufgeführtes Zitat als nicht relevant bezeichnet (zählt nicht) Zitat:
Ok! Bin raus aus dem Thread. gruss |
AW: Das Problem mit dem vergessenem TrayIcon
Also wenn ich als Anwender einen Prozess über den Taskmanager abschieße, dann muss mir bewusst sein, dass eventuell Müll zurückbleibt, deswegen würde ich mich als Programmierer nur darum kümmern, dass mein Programm aufräumt, wenn es sauber beendet wird.
|
AW: Das Problem mit dem vergessenem TrayIcon
Ach Leute, was soll das? Das Thema wird jetzt in eine Ecke gedrängt wo nicht hingehört, nur um Recht und das letzte Wort zu behalten. Ich sage nein, ich bin im Sommer auf eine Banane ausgerutscht. Ihr: ja im Winter ist es glatt, da rutscht man schon auf schneebedeckten Straße aus. Man kann sagen was mal will, ihr führt eurer eigenes Gespräch. Mach das, aber dann laßt mich da raus.
Ich spreche von einer Langzeitbeobachtung mit meinen und fremden Programmen und ihr kommt mir hier mit terminieren über Taskmanager. |
AW: Das Problem mit dem vergessenem TrayIcon
Ich habe mal in den Code von
Delphi-Quellcode:
(Delphi XE2-U4) geschaut, an welchen Stellen das Icon wieder gelöscht wird, und siehe da, das passiert nicht nur im Destroy:
TTrayIcon
Delphi-Quellcode:
Das Entscheidende wird wohl hier die Reaktion auf die Nachricht
destructor TCustomTrayIcon.Destroy;
begin if not (csDesigning in ComponentState) then begin Refresh(NIM_DELETE); DeallocateHWnd(FData.Wnd); end; ... end; procedure TCustomTrayIcon.SetVisible(Value: Boolean); begin if FVisible <> Value then begin FVisible := Value; if (not FAnimate) or (FAnimate and FCurrentIcon.Empty) then SetDefaultIcon; if not (csDesigning in ComponentState) then begin if FVisible then Refresh(NIM_ADD) else if not (csLoading in ComponentState) then begin if not Refresh(NIM_DELETE) then raise EOutOfResources.Create(STrayIconRemoveError); end; if FAnimate then FTimer.Enabled := Value; end; end; end; procedure TCustomTrayIcon.WindowProc(var Message: TMessage); ... var Point: TPoint; Shift: TShiftState; begin case Message.Msg of WM_QUERYENDSESSION: Message.Result := 1; WM_ENDSESSION: if TWmEndSession(Message).EndSession then Refresh(NIM_DELETE); ... end;
Delphi-Quellcode:
sein, denn normalerweise geht man ja davon aus, dass die Komponente mit dem Form ins Nirwana gezogen wird ... wozu also dieses Reagieren auf diese Nachricht ... scheint eigentlich überflüssig, da die Form aufgrund dieser Nachricht sich ja verabschiedet.
WM_ENDSESSION
Nein, ich verwende diese Komponente :) aber evtl. hilft das diese sporadischen TrayIcon-Hänger zu eliminieren |
AW: Das Problem mit dem vergessenem TrayIcon
Sieht interessant aus. Ich glaube ich bin etwas unvorbereitet in das Thema gerutscht. Seit Jahren denke ich dran, gestern habe ich die Frage gestellt, aber nicht geachtet, dass ich ein passendes Beispiel habe. Was mir aber gerade jetzt einfällt ist die Unregelmäßigkeit mit der das Problem auftritt. Jedes mal wenn das Problem auftrat, suchte ich was Neues. Und eine Zeit lang funktionierte es dann. Inzwischen frage ich mich ob das evtl. an Windows liegt. Auf jeden Fall habe ich jetzt genug neue Anregungen, so dass ich, sollte es wieder vorkommen, gezielter suchen kann.
Und an die Kollegen die glauben, dass ich seit 10 Jahren meine Programme über den Taskmanager beende: schönes Wochenende ;) |
AW: Das Problem mit dem vergessenem TrayIcon
Also, sämtliche Befehle, die das TNA bzw. Systray "refreshen" (bzw. genaugenommen Windows zum Auffrischen desselben auffordern), wie soll das denn funktionieren? Das kann das Programm doch nur, solang es nicht sich selbst beeendet hat, und so lang ist das Trayicon doch aktiv?! Oder kann man das Trayicon schon vorher deaktivieren, "disablen", "visible falsen", was auch immer?
|
AW: Das Problem mit dem vergessenem TrayIcon
Zitat:
|
AW: Das Problem mit dem vergessenem TrayIcon
Ja, Du hast recht, ich las nicht aufmerksam genug die bisherige Diskussion.
Momentan experimentiere ich mit der Version aus der Delphi-Fundgrube (die wohl Popovs Ausführungen zugrundeliegt), es funktioniert allerdings zuverlässig. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:17 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-2025 by Thomas Breitkreuz