Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Tray-Icon entfernen nach Beenden des Prozesses (https://www.delphipraxis.net/144257-tray-icon-entfernen-nach-beenden-des-prozesses.html)

ernschd 3. Dez 2009 15:21


Tray-Icon entfernen nach Beenden des Prozesses
 
Hi,
ich habe eine Routine, um einen Windows-Prozess zu beenden(ein fremdes Programm). Danach wird aber immer noch das Icon im SysTray angezeigt. Also habe ich eine vorhandene(und funktionierende) VB6-Funktion in Delphi konvertiert. Leider funktioniert sie dort jedoch nicht. :(

Ich habe schon die verschiedenen Kombinationen durchprobiert, unter anderem:
Delphi-Quellcode:
InvalidateRect(hSysTray, @rRect, True);
SendMessage(hSysTray, WM_PAINT, 0, 0);
SendMessage(hTray, WM_MOUSEMOVE, 0, 0);
Alles ohne Erfolg.

Hat jemand ein funktionierendes Codebeispiel für mich?

Danke & Gruß,
Ernschd

Luckie 3. Dez 2009 20:50

Re: Tray-Icon entfernen nach Beenden des Prozesses
 
Wie entfernst du denn bei Programmende das Icon aus der TNA?

SirThornberry 3. Dez 2009 21:53

Re: Tray-Icon entfernen nach Beenden des Prozesses
 
@Luckie: lies am besten nochmal den ersten Beitrag :mrgreen: Er killt ein fremdes Programm welches ein Trayicon hat. Und mit dem geposteten Code versucht er dann das Trayicon des fremden Programmes weg zu bekommen.

Luckie 3. Dez 2009 21:59

Re: Tray-Icon entfernen nach Beenden des Prozesses
 
Mist, habe ich überlesen. Aber ich meine das Problem hatten wir schon mal. Hast du mal im Forum gesucht? Stimmt das Handle? Wie ermittelst du es?

toms 4. Dez 2009 01:08

Re: Tray-Icon entfernen nach Beenden des Prozesses
 
Hallo,

Du könntest das TNA Icon vor dem Beenden des Prozesses verstecken. Nach dem Beenden des Prozesses ist es dann ganz weg.
// Achtung: Nur mit D6, Vista 32 getestet....

Delphi-Quellcode:
uses
  PsAPI, CommCtrl;

function HideTNAIcon(ProcPath: AnsiString; HideIcon: Boolean = True): Boolean;

  function GetProcPath(wnd: HWND): AnsiString;
  var
    hProc: HWND;
    ProcId, cbNeeded: DWord;
    hMod: HMODULE;
    ModuleName: array[0..MAX_PATH - 1] of Char;
  begin
    Result := '';
    GetWindowThreadProcessId(wnd, @ProcId);
    hProc := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, ProcId);
    if hProc <> 0 then
      try
        if EnumProcessModules(hProc, @hMod, SizeOf(hMod), cbNeeded) then
          if GetModuleFilenameEx(hProc, hMod, ModuleName, SizeOf(ModuleName)) > 0 then
            Result := string(ModuleName);
      finally
        CloseHandle(hProc);
      end;
  end;

  function FindToolBar: HWND;
  var
    wnd: HWND;
  begin
    Result := 0;
    wnd := FindWindow('Shell_TrayWnd', '');
    if wnd > 0 then
      wnd := FindWindowEx(wnd, 0, 'TrayNotifyWnd', nil);
    if wnd > 0 then
      wnd := FindWindowEx(wnd, 0, 'SysPager', nil);
    if wnd > 0 then
      Result := FindWindowEx(wnd, 0, 'ToolbarWindow32', nil);
  end;

  function FindTrayNotify: HWND;
  var
    wnd: HWND;
  begin
    Result := 0;
    wnd := FindWindow('Shell_TrayWnd', '');
    if wnd > 0 then
      Result := FindWindowEx(wnd, 0, 'TrayNotifyWnd', nil);
  end;

type
  TTrayData2 = record
    cbSize: DWORD;
    Wnd: HWND;
    uID: UINT;
    uFlags: UINT;
    uCallbackMessage: UINT;
    hIcon: HICON;
    szTip: array[0..127] of AnsiChar;
    dwState: DWORD;
    dwStateMask: DWORD;
    szInfo: array[0..255] of AnsiChar;
    uTimeout: UINT;
    szInfoTitle: array[0..63] of AnsiChar;
    dwInfoFlags: DWORD;
  end;

type
  TTrayData = record
    wnd: HWND;
    uID: UINT;
    uCallbackMessage: UINT;
    Reserved: array[0..1] of DWORD;
    hIco: HICON;
  end;
var
  pRem, pLoc: PTBButtonInfo;
  NumBytes, ProcId: Cardinal;
  count, loop: Integer;
  hProc, hToolBar, hTrayNotify: HWND;
  IconData: TTrayData; //TNotifyIconData;
  r, r2: TRect;
begin
  Result := False;
  hToolBar := FindToolBar;
  hTrayNotify := FindTrayNotify;
  if hToolBar > 0 then
  begin
    GetWindowThreadProcessId(hToolBar, @ProcId);
    hProc := OpenProcess(PROCESS_VM_OPERATION or PROCESS_VM_READ or
      PROCESS_VM_WRITE, False, ProcId);
    if hProc = 0 then
      MessageDlg(Format('Fehler bei OpenProcess %s',
        [SyserrorMessage(GetLastError)]), mtError, [mbOk], 0)
    else
      try
        pRem := VirtualAllocEx(hProc, nil, SizeOf(TBButtonInfo), MEM_COMMIT, PAGE_READWRITE);
        if Assigned(pRem) then
          try
            pLoc := VirtualAlloc(nil, SizeOf(TBButtonInfo), MEM_COMMIT, PAGE_READWRITE);
            if Assigned(pLoc) then
              try
                count := SendMessage(hToolBar, TB_BUTTONCOUNT, 0, 0);
                if count = 0 then
                  MessageDlg('Fehler bei TB_BUTTONCOUNT', mtError, [mbOk], 0);
                pLoc^.cbSize := SizeOf(TBButtonInfo);
                pLoc^.dwMask := TBIF_LPARAM or TBIF_STATE;
                if WriteProcessMemory(hProc, pRem, pLoc, SizeOf(TBButtonInfo), NumBytes) then
                  for loop := 0 to count do
                    if SendMessage(hToolBar, TB_GETBUTTONINFO, loop, Cardinal(pRem)) <> 0 then
                      if ReadProcessMemory(hProc, pRem, pLoc, SizeOf(TBButtonInfo), NumBytes) then
                        if ReadProcessMemory(hProc, Pointer(pLoc^.lParam),
                          @IconData.Wnd, SizeOf(TTrayData), NumBytes) then
                          if IsWindow(IconData.Wnd) then
                          begin
                            if SameText(ProcPath, GetProcPath(IconData.Wnd)) then
                            begin
                              if HideIcon then
                              begin
                                if pLoc^.fsState and TBSTATE_HIDDEN = 0 then //sichtbar
                                begin
                                  pLoc^.fsState := pLoc^.fsState or TBSTATE_HIDDEN;
                                  if WriteProcessMemory(hProc, pRem, pLoc, SizeOf(TBButtonInfo), NumBytes) then
                                    if SendMessage(hToolBar, TB_SETBUTTONINFO, loop, Cardinal(pRem)) <> 0 then
                                      Result := True;
                                end;
                              end
                              else
                              begin
                                if pLoc^.fsState and TBSTATE_HIDDEN > 0 then //unsichtbar
                                begin
                                  pLoc^.fsState := pLoc^.fsState and not TBSTATE_HIDDEN;
                                  if WriteProcessMemory(hProc, pRem, pLoc, SizeOf(TBButtonInfo), NumBytes) then
                                    if SendMessage(hToolBar, TB_SETBUTTONINFO, loop, Cardinal(pRem)) <> 0 then
                                      Result := True;
                                end;
                              end;
                              Break;
                            end;
                          end;
              finally
                VirtualFree(pLoc, 0, MEM_RELEASE);
              end;
          finally
            VirtualFreeEx(hProc, pRem, 0, MEM_RELEASE);
          end
        else
          MessageDlg(Format('Fehler bei VirtualAllocEx %s',
            [SyserrorMessage(getLastError)]), mtError, [mbOk], 0);
      finally
        CloseHandle(hProc);
      end;
  end
  else
    MessageDlg(Format('Kein gültiges Fenster Handle %d', [hToolBar]), mtError, [mbOk], 0);
end;

ernschd 4. Dez 2009 11:30

Re: Tray-Icon entfernen nach Beenden des Prozesses
 
Muss ich der Funktion den Namen des Prozesses übergeben, den Dateipfad zur Exe, oder was anderes?
Die ersten beiden Varianten habe ich ausprobiert, aber es hat leider nicht funktioniert.

Madtrax 4. Dez 2009 14:30

Re: Tray-Icon entfernen nach Beenden des Prozesses
 
Hallo

Ich habe das gleiche Problem die Tage auch gehabt und eine sehr einfache und schöne Lösung gefunden.
Das Icon verschwindet wenn man mit der Maus darüber fährt, richtig ?
Also machen wir uns das zunutze und machen das mit Sourcecode. Gesagt sei dabei, dass die Maus nicht wirklich verschoben wird.
Habe den Code im Internet gefunden. Weiß allerdings auch nicht mehr wo genau. Schau es dir mal an....

Delphi-Quellcode:
Procedure KillTrayIcon;
var
    wnd : cardinal;
    rec : TRect;
    w,h : integer;
    x,y : integer;
begin
    // find a handle of a tray
    wnd := FindWindow('Shell_TrayWnd', nil);
    wnd := FindWindowEx(wnd, 0, 'TrayNotifyWnd', nil);
    wnd := FindWindowEx(wnd, 0, 'SysPager', nil);
    wnd := FindWindowEx(wnd, 0, 'ToolbarWindow32', nil);
    // get client rectangle (needed for width and height of tray)
    windows.GetClientRect(wnd, rec);
    // get size of small icons
    w := GetSystemMetrics(sm_cxsmicon);
    h := GetSystemMetrics(sm_cysmicon);
    // initial y position of mouse - half of height of icon
    y := w shr 1;
    while y < rec.Bottom do begin // while y < height of tray
        x := h shr 1; // initial x position of mouse - half of width of icon
        while x < rec.Right do begin // while x < width of tray
            SendMessage(wnd, wm_mousemove, 0, y shl 16 or x); // simulate moving mouse over an icon
            x := x + w; // add width of icon to x position
        end;
        y := y + h; // add height of icon to y position
    end;
end;

generic 4. Dez 2009 14:41

Re: Tray-Icon entfernen nach Beenden des Prozesses
 
Wird nicht einfach durch die Maus ein Invalidate bzw. neu zeichnen ausgelöst?

Madtrax 4. Dez 2009 14:49

Re: Tray-Icon entfernen nach Beenden des Prozesses
 
Gute Frage...

Was auf jeden Fall nicht geht, ist ein Invalidate auf den Tray Bereich, weil der dann komplett ausgehebelt wird (Schwarzer Block auf grauem Grund). Nur ein "Normales" Anzeigen der Tray hilft dir nach dem Invalidate wieder weiter (Tray wird dann wieder korrekt gezeichnet).

ernschd 7. Dez 2009 10:00

Re: Tray-Icon entfernen nach Beenden des Prozesses
 
Mit dem letzten Programmcode funktioniert es wunderbar.

Danke schön. :)


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:49 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