Page 2 of 4

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 12:58 pm
by whertz
I don't understand that code much srod, but could this code be modified to remove the trayicon of a program killed with killprogram?

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 1:05 pm
by UserOfPure
whertz wrote:sending it Alt+F4 minimizes it, it is just the way the program works
Of course it won't close it in such circumstances. You should close it via some macro keystrokes then, using whatever key combo actually exits the app. Do a search for "SendKeys" here for the code.

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 1:16 pm
by srod
whertz wrote:I don't understand that code much srod, but could this code be modified to remove the trayicon of a program killed with killprogram?
Only if you can identify the handle of the relevant icon which you would probably need to do by enumerating all the taskbar icons. The only way to do this is to make some inter-process calls to the explorer process in order to retrieve the individual toolbar buttons data etc. Quite fiddly (but very possible). Whilst enumerating the various buttons you would retrieve each icons NOTIFYICONDAT structure and examine the hWnd field etc. Once found, you then delete the button with Shell_NotifyIcon_().

It is too much work and too reliant on using FindWindow_() and on things which probably shouldn't be messed with (e.g. firing messages at the relevant explorer toolbar etc.)

If I were you I'd follow UserOfPure's advice. :)

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 1:55 pm
by whertz
srod wrote:
whertz wrote:I don't understand that code much srod, but could this code be modified to remove the trayicon of a program killed with killprogram?
Only if you can identify the handle of the relevant icon which you would probably need to do by enumerating all the taskbar icons. The only way to do this is to make some inter-process calls to the explorer process in order to retrieve the individual toolbar buttons data etc. Quite fiddly (but very possible). Whilst enumerating the various buttons you would retrieve each icons NOTIFYICONDAT structure and examine the hWnd field etc. Once found, you then delete the button with Shell_NotifyIcon_().

It is too much work and too reliant on using FindWindow_() and on things which probably shouldn't be messed with (e.g. firing messages at the relevant explorer toolbar etc.)

If I were you I'd follow UserOfPure's advice. :)
Sounds way too complicated. :shock: As for UserOfPure's method, there is no key combo to exit it! I think I'll just have to put up with the messy icons on the system tray. :roll:

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 3:25 pm
by Michael Vogel
Some more solutions for AutoIt can be found here(like in the first link, you have only to check the newest postings there)

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 4:13 pm
by skywalk
@whertz
I am kinda confused?
Did the code I submitted work for you?
It works for me running Windows XP sp3, PB 4.41.

@srod
Thanks for your answers.
Still not working completely though. :(
1. Yes, able to write string into the existing NOTIFYICONDATA\szTip.c[64] structure element.
2. Yes, the "POLINK" error is gone using your createimage trick.
(never would have discovered that.)
(What does POLINK mean anyway?)
3. No, the tooltip text does not appear when I hover over the systray icon.
It does when I use the API command
This works -> Shell_NotifyIcon_(#NIM_ADD, nid)
This doesn't -> AddSysTrayIcon(0,hWnd,hicon)

So, I have a working solution, just would like to understand why the internal PB command isn't.

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 4:33 pm
by whertz
skywalk wrote:@whertz
I am kinda confused?
Did the code I submitted work for you?
It works for me running Windows XP sp3, PB 4.41.
No, it's like srod said about getting the handle (see his post). I just want to make it clear, it is not any program I have written that I am trying to remove the icon after I kill it, it is an external program.

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 5:09 pm
by skywalk
Ok, but I didn't write "c:\windows\notepad.exe" and its icon is added and removed.
I added calls to start notepad.exe below and it still works.

Code: Select all

Structure m_NOTIFYICONDATA
  cbSize.i
  hwnd.i
  uId.i
  uFlags.i
  uCallBackMessage.i
  hIcon.i
  szTip.s{64}
EndStructure

ImportC "SHELL32.LIB" 
  Shell_NotifyIcon_.i(dwMessage.i, pnid.i) As "_Shell_NotifyIconA" 
EndImport
Define.i hWnd, hIcon, ri
Define.s Prog2run
Define.m_NOTIFYICONDATA nid  

prog2run = "c:\windows\notepad.exe"
hwnd = GetDesktopWindow_()
hicon = ExtractIcon_(0,prog2run,0)

With nid
  \cbSize = SizeOf(nid)
  \hWnd = hWnd
  \uId = #Null
  \uFlags = #NIF_ICON | #NIF_TIP | #NIF_MESSAGE
  \uCallBackMessage = #WM_MOUSEMOVE
  \hIcon = hicon
  \szTip = "Some Text Here" + #NULL$
EndWith
ri = RunProgram(Prog2run, #NULL$, #NULL$, #PB_Program_Open)
Shell_NotifyIcon_(#NIM_ADD, nid)
  Debug "...Hold mouse over SysTray icon now..."
  Delay(5000)
  Debug "...Attempting to remove SysTray icon..."
  Debug ""
Shell_NotifyIcon_(#NIM_DELETE, nid)
  Debug "...Quitting in 3 sec..."
DestroyIcon_(hIcon)
  Delay(3000)
KillProgram(ri):CloseProgram(ri)
End

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 6:55 pm
by srod
Skywalk, even with your code there is still the problem of identifying the icon handle in the more general case etc.

As for AddSysTrayIcon(0,hWnd,hicon), this is not set up for adding tooltips. For that you need to use SysTrayIconToolTip() etc.

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 7:04 pm
by whertz
SkyWalk: Your code works, but only for the systray icon you create not for removing an icon that is already there. Thanks anyway...

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 7:35 pm
by RASHAD
Hi

Code: Select all

; Enumerate Systray Icons
; netmaestro October 2009
; Tested on XP and Vista, doesn't work for Windows 7
; Just for fun

; Modified by RASHAD 17/02/2010
; Tested on XP x86 ,Vista x86 and Win 7 X64 PB x64
; Have fun

Structure TRAYOWNER
  bitmap.l
  hwnd.s
  filename.s
EndStructure

Structure TRAYDATA
    hwnd.l                
    uID.l             
    uCallbackMessage.i    
    Reserved.l[2]      
    hIcon.l                
EndStructure

Structure _TBBUTTON
    iBitmap.l 
    idCommand.l
    fsState.b 
    fsStyle.b 
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
    bReserved.b[6]
CompilerElse
    bReserved.b[2]
CompilerEndIf
    dwData.i 
    iString.i 
EndStructure

Global NewList TrayIcons.TRAYOWNER()

Procedure Enumerate_TrayIcons()

  lib = OpenLibrary(#PB_Any, "psapi.dll")
  
  ; Find the System Tray Icon Toolbar
  Protected hwnd
  hWnd = FindWindow_("Shell_TrayWnd", #Null)
  If hWnd
    hWnd = FindWindowEx_(hWnd, #Null, "TrayNotifyWnd", #Null)
    If hWnd
      hWnd = FindWindowEx_(hWnd,#Null, "SysPager", #Null)
      If hWnd 
        hTray = FindWindowEx_(hWnd, #Null, "ToolbarWindow32", #Null)
      Else
        ProcedureReturn 0
      EndIf
    Else
      ProcedureReturn 0
    EndIf
  Else
    ProcedureReturn 0
  EndIf
  
  count = SendMessage_(hTray, #TB_BUTTONCOUNT, 0, 0)
  
  Dim button._TBBUTTON(count)
  Dim button_td.TRAYDATA(count)  
  
  dwExplorerThreadId=GetWindowThreadProcessId_(hTray, @dwExplorerProcessId)
  hProc = OpenProcess_(#PROCESS_ALL_ACCESS, #False, dwExplorerProcessId)
  *lpData = VirtualAllocEx_(hProc, #Null, SizeOf(_TBBUTTON)*count, #MEM_COMMIT, #PAGE_READWRITE)
  
  For i = 0 To count-1
    SendMessage_(hTray, #TB_GETBUTTON, i, *lpData+i*SizeOf(_TBBUTTON) )
    ReadProcessMemory_(hProc, *lpData+(i*SizeOf(_TBBUTTON)), @button._TBBUTTON(i), SizeOf(_TBBUTTON), #Null)    
    ReadProcessMemory_(hProc, button(i)\dwData, @button_td.TRAYDATA(i), SizeOf(TRAYDATA), #Null)
    ;The error 299 is ERROR_PARTIAL_COPY
    
    thisbmp = button_td(i)\hIcon    
    thishwnd = button_td(i)\hwnd    
    thisfilename$ = Space(#MAX_PATH)

    GetWindowThreadProcessId_(thishwnd, @thisprocessID.i)
    hthisProcess = OpenProcess_(#PROCESS_ALL_ACCESS, #False, thisprocessID )              ;|#PROCESS_QUERY_INFORMATION
    CallFunction(lib, "GetProcessImageFileNameA", hthisProcess, @thisfilename$, 255)
    CloseHandle_(hthisProcess)
    
    AddElement(TrayIcons())
    TrayIcons()\hwnd = Str(thishwnd)
    trayIcons()\filename = thisfilename$
    TrayIcons()\bitmap = thisbmp
  Next
  
  VirtualFreeEx_(hProc, *lpData, #Null, #MEM_RELEASE)

  CloseHandle_(hProc)
  If IsLibrary(lib) : CloseLibrary(lib) : EndIf
  
EndProcedure

Enumerate_TrayIcons()

OpenWindow(0,0,0,600,400,"System Tray Icon Owners",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
ListIconGadget(0,0,0,600,400,"Icon", 60, #PB_ListIcon_GridLines)
AddGadgetColumn(0, 1, "Owner hWnd",100)
AddGadgetColumn(0, 2, "Owner Location",250)
AddGadgetColumn(0, 3, "Icon hWnd",200)
ForEach TrayIcons()
  AddGadgetItem(0,-1, Chr(10)+TrayIcons()\hwnd +Chr(10)+TrayIcons()\filename+Chr(10)+Str(TrayIcons()\bitmap),TrayIcons()\bitmap)
Next
Repeat:Until WaitWindowEvent()=#PB_Event_CloseWindow

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 7:39 pm
by srod
Yep, nice code.

Does that work on Win 7 then Rashad?

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 7:42 pm
by RASHAD
Yes Win 7 x64 using PB x64
Now waiting for your magic srod
I wish to see this job finished

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 7:48 pm
by srod
All the work is done with that execellent code Rashad. All whertz has to do is examine the window handles and match up the one belonging to the application he is messing around with and then use Shell_NotifyIcon_() etc. :)

Still, I think this is too much work for such a simple thing.

@Whertz : could you be sending #WM_CLOSE to the wrong window? Could the window you are sending the message to have a parent? Does the application have other windows?

Re: How to remove systray icon?

Posted: Wed Feb 17, 2010 7:51 pm
by whertz
srod wrote:All the work is done with that execellent code Rashad. All whertz has to do is examine the window handles and match up the one belonging to the application he is messing around with and then use Shell_NotifyIcon_() etc. :)

Still, I think this is too much work for such a simple thing.

@Whertz : could you be sending #WM_CLOSE to the wrong window? Could the window you are sending the message to have a parent? Does the application have other windows?
No, there are no other windows, when the program gets sent a close command it minimizes instead. Like msn messenger etc. does when you close the window, it doesn't really close it's still running on the taskbar.