Enumerate Icons in the notification area

Share your advanced PureBasic knowledge/code with the community.
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Enumerate Icons in the notification area

Post by luis »

I was a little hesitant to post this here since it's something certainly imperfect and unsupported, probably easy to break etc., but maybe can be of some interest, or someone can build upon this so... here it is

Code: Select all

EnableExplicit

; TaskBar Icons enumerator
; By Luis
; PB 4.61 x86/x64

; Based on work from:
;
; Nish Sivakumar
; http://www.codeproject.com/Articles/10807/Shell-Tray-Info-Arrange-your-system-tray-icons
;
; Netmaestro
; http://www.purebasic.fr/english/viewtopic.php?p=302528#p302528
;
; and various people from http://social.msdn.microsoft.com/Forums/en/vbgeneral/thread/70d29077-84e6-43cd-b1b2-d84328276ae6
;
; Tested on Windows XP x86, Windows 7 x86, Windows 7 x64
; It's hackish, unsupported, dirty, etc., expect to see weird things.
; Probably it's more for educational purpose than real usage.
; DeviceNameToDosName() and NormalizeDevicePath() can be useful though.

; Known limitations:

; The bitmap of the icon is not always present, some programs update their icons dinamically in different ways (sendmessage, etc) and sometime the bitmap results blank.
; I'm not 100% sure why.

; The program must be compiled to 32 bit for 32 bit oses and to 64 bit for 64 bit oses.
; The 32 bit version cannot work on a 64 bit os (the 32 bit process cannot read the infos from the 64 bit shell).

; If you find problems and you are able to fix it, thanks.
; If you know a cleaner and less hackish way and want to share it, thanks.


#ICON_POSITION_TASKBAR = 0 ; icons in the notification area of the taskbar
#ICON_POSITION_OVERFLOW = 1 ; icons in the overflow window of Windows 7

; set to 1 to see the kernel-ish device name used in the path
; set to 0 to see the usual C:\ dos name instead (hopefully)
#SHOW_DEVICE_PATH = 0
                       

Structure T_TASKBAR_PROGRAMS
 Position.i ; #ICON_POSITION_TASKBAR or #ICON_POSITION_OVERFLOW
 IconHandle.i ; the bitmap handle
 WinHandle.i ; the handle of icon's window
 PID.i ; the pid of the process
 Image$ ; the image name of the process
 Path$ ; path name of the executable
EndStructure

Structure NOTIFYICONDATA_EX
  hWnd.i
  uID.l
  uFlags.l
  uCallbackMessage.l
  pad1.b[4]
  hIcon.l
EndStructure

Procedure.s DeviceNameToDosName (Device$)
; [DESC]
; Return the DOS name for the specified kernel device mapping.
;
; [INPUT]
; Device$ : The kernel name (like "\Device\HarddiskVolume4", "\Device\Harddisk0\Partition1", etc.)
;
; [RETURN]
; The DOS logical name (A: - Z:)
;
; [NOTES]
; Windows XP
; Ascii/Unicode
; Debug DeviceNameToDosName("\Device\HarddiskVolume1") ; "C:"
 
 Protected Buffer$ = Space(128 + 1)
 Protected iNumChars, iCounter, CurrChar.c
 Protected Dos$, Dev$
 
 iNumChars = GetLogicalDriveStrings_(128, @Buffer$)
 
 If iNumChars <= 128 And iNumChars > 0
    Repeat
        CurrChar = PeekC(@Buffer$ + iCounter * SizeOf(Character))
        If CurrChar <> 0
            Dos$ + Chr(CurrChar)
        Else           
            If Right(Dos$, 1) = "\"
                Dos$ = Left(Dos$, Len(Dos$) - 1)
            EndIf
            Dev$ = Space(#MAX_PATH + 1)
            QueryDosDevice_(@Dos$, @Dev$, #MAX_PATH)           
            If Device$ = Dev$
                ProcedureReturn Dos$
            EndIf
            Dos$ = ""
        EndIf
        iCounter + 1
    Until iCounter >= iNumChars
 EndIf
 
 ProcedureReturn ""
EndProcedure

Procedure.s NormalizeDevicePath (DevicePath$)
; [DESC]
; Return the Windows path using drive letters from the specified kernel device path.
;
; [INPUT]
; DevicePath$ : The kernel pathname (like "\Device\HarddiskVolume2\foo\bar\prog.exe")
;
; [RETURN]
; The Windows path using drive letters.
;
; [NOTES]
; Windows XP
; Debug NormalizeDevicePath("\Device\HarddiskVolume2\foo\bar\prog.exe") ; "C:\foo\bar\prog.exe"
 
 Protected iPos
 Protected Dev$, Dos$
 
 iPos = FindString(DevicePath$, "\Device\", 1)
 If iPos
    iPos = FindString (DevicePath$, "\", Len("\Device\") + 1)
    If iPos
        Dev$ = Left(DevicePath$, iPos - 1)
        Dos$ = DeviceNameToDosName(Dev$)
        DevicePath$ = ReplaceString(DevicePath$, Dev$, Dos$)
    EndIf
 EndIf
   
 ProcedureReturn DevicePath$
EndProcedure

Procedure.s GetDeviceFileNameFromPID (iPID)
; [DESC]
; Return the path + filename (in device format) of the executable associated with the process id.
;
; [INPUT]
; The process id of the executable.
;
; [RETURN]
; The path + filename of the process.
; 
; [NOTES]
; Returns something like "\Device\HarddiskVolume2\Windows\System32\taskmgr.exe"

 Protected hDLL = OpenLibrary(#PB_Any, "psapi.dll")     
 Protected hProc, *fp
 Protected fname$ = Space(#MAX_PATH + 1)
 
 If hDLL

CompilerIf (#PB_Compiler_Unicode = 1)
    *fp = GetFunction(hDLL, "GetProcessImageFileNameW")
CompilerElse 
    *fp = GetFunction(hDLL, "GetProcessImageFileNameA")
CompilerEndIf
 
    If *fp
        hProc = OpenProcess_(#PROCESS_QUERY_INFORMATION, #False, iPID)  
        If hProc 
            CallFunctionFast(*fp, hProc, @fname$, #MAX_PATH)
            CloseHandle_(hProc)
        EndIf
    EndIf
    CloseLibrary(hDLL)
 EndIf 

 ProcedureReturn Trim(fname$)
EndProcedure

Procedure.s GetFileNameFromPID (iPID)
; [DESC]
; Return the path + filename of the executable associated with the process id.
;
; [INPUT]
; The process id of the executable.
;
; [RETURN]
; The path + filename of the process.
; 
; [NOTES]
; Returns something like "C:\Windows\System32\taskmgr.exe"

 ProcedureReturn NormalizeDevicePath(GetDeviceFileNameFromPID(iPID))
EndProcedure

Procedure.s GetImageNameFromPid (iPID)
; [DESC]
; Return only the filename of the executable associated with the process id.
;
; [INPUT]
; The process id of the executable.
;
; [RETURN]
; The filename of the process.
; 
; [NOTES]
; Returns something like "taskmgr.exe"
; Replaced GetModuleBaseName(), see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683196%28v=vs.85%29.aspx

 Protected iPos
 Protected image$, path$ = GetDeviceFileNameFromPID(iPID)
 
 If path$
    path$ = ReverseString(Path$)
    iPos = FindString(path$, "\", 1)
    If iPos
        image$ = ReverseString(Left(path$, iPos - 1))
    EndIf    
 EndIf
 
 ProcedureReturn image$
EndProcedure

Procedure.i FindTaskbarToolbarWindow()
 Protected hWnd, hDLL = OpenLibrary(#PB_Any, "psapi.dll")
 
 If hDLL   
    hWnd = FindWindow_("Shell_TrayWnd", #Null)
    If hWnd
        hWnd = FindWindowEx_(hWnd, #Null, "TrayNotifyWnd", #Null)
        If hWnd
            hWnd = FindWindowEx_(hWnd, #Null, "SysPager", #Null)
            If hWnd
                hWnd = FindWindowEx_(hWnd, #Null, "ToolbarWindow32", #Null)                       
            EndIf
       EndIf
    EndIf
    CloseLibrary(hDLL)
 EndIf
 
 ProcedureReturn hWnd
EndProcedure

Procedure.i FindTaskbarToolbarWindowOverflow()
 Protected hWnd, hDLL = OpenLibrary(#PB_Any, "psapi.dll")

 If hDLL   
    hWnd = FindWindow_("NotifyIconOverflowWindow", #Null)
    If hWnd
        hWnd = FindWindowEx_(hWnd, #Null, "ToolbarWindow32", #Null)                       
    EndIf
    CloseLibrary(hDLL)
 EndIf
 
 ProcedureReturn hWnd
EndProcedure

Procedure.i TaskBarCountIcons (hToolBarWindow)
 ProcedureReturn SendMessage_(hToolBarWindow, #TB_BUTTONCOUNT, 0, 0)
EndProcedure

Procedure GetIconInfo (hProc, i, hToolBarWindow, *TBP.T_TASKBAR_PROGRAMS, iPosition)
 Protected TBB.TBBUTTON
 Protected NID.NOTIFYICONDATA_EX
 Protected INFO.ICONINFO
 Protected iBytesCount, *pdata
 Protected fname$, iPID, image$
 
 *pdata = VirtualAllocEx_(hProc, #Null, SizeOf(TBBUTTON), #MEM_COMMIT, #PAGE_READWRITE)
 
 SendMessage_(hToolBarWindow, #TB_GETBUTTON, i, *pData)
 
 ReadProcessMemory_(hProc, *pData, @TBB, SizeOf(TBBUTTON), @iBytesCount)
 
 ReadProcessMemory_(hProc, TBB\dwData, @NID, SizeOf(NOTIFYICONDATA_EX), @iBytesCount)

 GetWindowThreadProcessId_(NID\hWnd, @iPID)
 
 CompilerIf #SHOW_DEVICE_PATH = 1
    fname$ = GetDeviceFileNameFromPID(iPID)
 CompilerElse
    fname$ = GetFileNameFromPID(iPID)   
 CompilerEndIf
 
 image$ = GetImageNameFromPid(iPID)
 
 If GetIconInfo_(NID\hIcon, @INFO)
    *TBP\IconHandle = NID\hIcon
 Else
    *TBP\IconHandle =0
 EndIf
 
 *TBP\WinHandle = NID\hWnd
 *TBP\Position = iPosition
 *TBP\Image$ = image$
 *TBP\Path$ = fname$
 *TBP\PID = iPID
 
 VirtualFreeEx_(hProc, *pData, #Null, #MEM_RELEASE)
EndProcedure


Procedure GetIconizedPrograms (hToolBarWindow, iCount, List lstTBP.T_TASKBAR_PROGRAMS(), iPosition)
 Protected iPID, hProc, i
 Protected TBP.T_TASKBAR_PROGRAMS
 
 GetWindowThreadProcessId_(hToolBarWindow, @iPID)
 hProc = OpenProcess_(#PROCESS_VM_OPERATION | #PROCESS_VM_READ, #False, iPID)
 For i = 0 To iCount - 1
    AddElement(lstTBP())
    GetIconInfo(hProc, i, hToolBarWindow, @lstTBP(), iPosition)
 Next
 
 CloseHandle_(hProc)
EndProcedure

Procedure.i GetTaskBarPrograms (List lstIcons.T_TASKBAR_PROGRAMS()) 
 Protected hTaskBarToolBarWin = FindTaskbarToolbarWindow()
 Protected hTaskBarToolBarOverflowWin = FindTaskbarToolbarWindowOverflow()
 
 ClearList(lstIcons())
 
 If hTaskBarToolBarWin
     Protected iIconsCount = TaskBarCountIcons(hTaskBarToolBarWin)
     If iIconsCount
        GetIconizedPrograms(hTaskBarToolBarWin, iIconsCount, lstIcons(), #ICON_POSITION_TASKBAR)
     EndIf
     
     If hTaskBarToolBarOverflowWin
        Protected iIconsOverflowCount = TaskBarCountIcons(hTaskBarToolBarOverflowWin)
        If iIconsOverflowCount
            GetIconizedPrograms(hTaskBarToolBarOverflowWin, iIconsOverflowCount, lstIcons(), #ICON_POSITION_OVERFLOW)
        EndIf
     EndIf
                     
     ProcedureReturn 1
 EndIf
 
 ProcedureReturn 0
EndProcedure


; *****************
; * USAGE EXAMPLE *
; *****************

 
Procedure Main()
 Protected iEvent
 Protected Row$
 Protected NewList lstIcons.T_TASKBAR_PROGRAMS()
 
 GetTaskBarPrograms(lstIcons())
 
 If OpenWindow(0, 10, 10, 800, 600, "Taskbar Notification Area Icons", #PB_Window_SystemMenu)
 
    ListIconGadget(0,0,0,800,600,"Icon", 100, #PB_ListIcon_GridLines)   
    AddGadgetColumn(0, 1, "Win Handle", 80)
    AddGadgetColumn(0, 2, "OVF ?", 45)
    AddGadgetColumn(0, 3, "PID", 50)
    AddGadgetColumn(0, 4, "Image name", 150)
    AddGadgetColumn(0, 5, "Path", 400)
   

    ForEach lstIcons()
        Row$ = " (" + Str(lstIcons()\IconHandle) + ")"
       
        Row$ + Chr(10) + Str(lstIcons()\WinHandle)
       
        If lstIcons()\Position = #ICON_POSITION_OVERFLOW
            Row$ + Chr(10) + "Y"
        Else
            Row$ + Chr(10)
        EndIf
               
        Row$ + Chr(10) + Str(lstIcons()\PID)
       
        Row$ + Chr(10) + lstIcons()\Image$
       
        Row$ + Chr(10) + lstIcons()\Path$
               
        If lstIcons()\IconHandle
            AddGadgetItem(0,-1, Row$, lstIcons()\IconHandle)
        Else
            AddGadgetItem(0,-1, Row$)
        EndIf
    Next
 
    Repeat
         iEvent = WaitWindowEvent()
         
         Select iEvent
             Case #PB_Event_Gadget
                 Select EventGadget()
                 EndSelect
         EndSelect       
    Until iEvent = #PB_Event_CloseWindow   
 EndIf
 
 EndProcedure
 
Main() 


EDIT: Replaced GetModuleBaseName() and made some small changes (comments, flags for openprocess, etc.)
Last edited by luis on Thu Oct 04, 2012 9:27 pm, edited 1 time in total.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
falsam
Enthusiast
Enthusiast
Posts: 632
Joined: Wed Sep 21, 2011 9:11 am
Location: France
Contact:

Re: Enumerate Icons in the notification area

Post by falsam »

Yes it is awesome.

Works well with Window 7 when I compile in 64bits.
Image

But it does not work when I compile in 32 bits.
Image

Luis, thank you for the time you spent on this code. :)

Suggestion: Add a button to refresh the list and another to kill the selected process. I could do it I think, but you are the father of this code. See you soon Luis:)

➽ Windows 11 64-bit - PB 6.21 x64 - AMD Ryzen 7 - NVIDIA GeForce GTX 1650 Ti

Sorry for my bad english and the Dunning–Kruger effect 🤪
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Enumerate Icons in the notification area

Post by luis »

falsam wrote: Luis, thank you for the time you spent on this code. :)
No problem as I said I was curios about it. I'm afraid it's not a very clean way to do it and has certainly some problems, but that's the only way I found looking around the Net. Maybe someone else will do better.
Please note I didn't use GetModuleFileNameEx() to retrieve the path of the process by choice. It's not reliable in many situations even if it would be more comfortable to use.
So I went with the conversion of the device name in the path etc.
falsam wrote: Suggestion: Add a button to refresh the list and another to kill the selected process. I could do it I think, but you are the father of this code. See you soon Luis:)
No no ! It was only a little test program, I will not enhance it, do with it as you wish :)

Bye !
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5494
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Enumerate Icons in the notification area

Post by Kwai chang caine »

Thanks LUIS for your useful works, and for sharing 8)
ImageThe happiness is a road...
Not a destination
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Enumerate Icons in the notification area

Post by RASHAD »

Code by NM
Modified by RASHAD
Need more work to do

Tested with PB x86,PB x64 Win 7 x64

Code: Select all

;Coded by NM
;Modified by RASHAD

  Structure TRAYDATA
    hwnd.i
    uID.l             
    uCallbackMessage.l
    Reserved.l[2]     
    hIcon.i           
  EndStructure
  Structure TRAYDATA_wow64
    hwnd.q
    uID.l             
    uCallbackMessage.l
    Reserved.l[2]     
    hIcon.i           
  EndStructure
  Structure TBBUTTON_wow64
    iBitmap.l
    idCommand.l
    fsState.b
    fsStyle.b
    bReserved.b[6]
    dwData.q
    iString.q
  EndStructure 


Procedure Is64Bit()
Protected bIsWow64.l = #False, fnIsWow64Process
 
  fnIsWow64Process = GetProcAddress_(GetModuleHandle_("kernel32"), "IsWow64Process")
 
  If fnIsWow64Process
    If Not CallFunctionFast(fnIsWow64Process, GetCurrentProcess_(), @bIsWow64)
    EndIf
  EndIf
 
  ProcedureReturn bIsWow64
EndProcedure

Global count,turn,hWnd,HDN,Name$

Global Dim Stray$(20),Dim Icon(20),Dim HDname$(12)


Procedure.s GetImageName(PID)
OpenLibrary(0, "psapi.dll") 
 IName$ = Space(#MAX_PATH) 
 CompilerIf #PB_Compiler_Unicode
    *dfn = GetFunction(0, "GetProcessImageFileNameW")
 CompilerElse
    *dfn = GetFunction(0, "GetProcessImageFileNameA")
 CompilerEndIf
  hProc = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, #False, PID)
  CallFunctionFast(*dfn, hProc, @IName$, #MAX_PATH)
 ProcedureReturn IName$
EndProcedure

Procedure Find_PB_TrayIcons()

  Protected hwnd
  If Is64Bit()
    Dim button_td2.TRAYDATA_wow64(20)
    Dim button2.TBBUTTON_wow64   (20)
  Else
    Dim button_td.TRAYDATA(20)
    Dim button.TBBUTTON   (20)
  EndIf
  For n = 1 To 2
      If n = 1
          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)
      ElseIf n = 2
            hWnd = FindWindow_("NotifyIconOverflowWindow", #Null)
            If hWnd
                hTray = FindWindowEx_(hWnd, #Null, "ToolbarWindow32", #Null)
            Else
              ProcedureReturn 0
            EndIf
          count = count + SendMessage_(hTray, #TB_BUTTONCOUNT, 0, 0)
      EndIf
     
 
  dwExplorerThreadId=GetWindowThreadProcessId_(hTray, @dwExplorerProcessId)
  hProc = OpenProcess_(#PROCESS_ALL_ACCESS, #False, dwExplorerProcessId)
  If Is64Bit()
    *lpData = VirtualAllocEx_(hProc, #Null, SizeOf(TBBUTTON_wow64)*count, #MEM_COMMIT, #PAGE_READWRITE)
  Else
    *lpData = VirtualAllocEx_(hProc, #Null, SizeOf(TBBUTTON)*count, #MEM_COMMIT, #PAGE_READWRITE)
  EndIf
  *lpRect = VirtualAllocEx_(hProc, #Null, SizeOf(RECT)*count, #MEM_COMMIT, #PAGE_READWRITE)

  For i = 0 To count - 1
    If Is64Bit()
      SendMessage_(hTray, #TB_GETBUTTON, i, *lpData+i*SizeOf(TBBUTTON_wow64) )
      ReadProcessMemory_(hProc, *lpData+(i*SizeOf(TBBUTTON_wow64)), @button2.TBBUTTON_wow64(i), SizeOf(TBBUTTON_wow64), #Null)
      ReadProcessMemory_(hProc, button2(i)\dwData, @button_td2.TRAYDATA_wow64(i), SizeOf(TRAYDATA_wow64), #Null)
      hIcon = button_td2.TRAYDATA_wow64(i)\hIcon
      hWnd = button_td2.TRAYDATA_wow64(i)\hwnd
      uID = button_td2.TRAYDATA_wow64(i)\uID
      iState = button2.TBBUTTON_wow64(i)\fsState
      IName$ = GetImageName(uID)
      If Trim(IName$) = ""
         IName$ = "System Icon"
      Else
          For x = 1 To 3
            Position = FindString(IName$,"\",Position+1)
          Next
          IName$ = Right(IName$,Len(IName$)-Position)
          For x = 0 To HDN
             IName$ = HDname$(x)+IName$
             If FileSize(IName$) > 0
                Break
             EndIf
          Next
      EndIf
      If n = 1
         turn = i
         STray$(turn) = "     " + Str(hIcon) +  Chr(10) + Str(hWnd) + Chr(10) + Str(iState) + Chr(10) + Str(uID) + Chr(10) + IName$
      Else
        turn = turn + 1
        STray$(turn) = "     " + Str(hIcon) +  Chr(10) + Str(hWnd) + Chr(10) + "OFN" + Chr(10) + Str(uID) + Chr(10) + IName$
      EndIf        
        Icon(turn) = hIcon
    Else
      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)
      hIcon = button_td.TRAYDATA(i)\hIcon
      hWnd = button_td.TRAYDATA(i)\hwnd
      uID = button_td.TRAYDATA(i)\uID
      iState = button.TBBUTTON(i)\fsState
      IName$ = GetImageName(uID)
      If Trim(IName$) = ""
         IName$ = "System Icon"
      Else
          For x = 1 To 3
            Position = FindString(IName$,"\",Position+1)
          Next
          IName$ = Right(IName$,Len(IName$)-Position)
          For x = 0 To HDN
             IName$ = HDname$(x)+IName$
             If FileSize(IName$) > 0
                Break
             EndIf
          Next
      EndIf
      If n = 1
         turn = i
         STray$(turn) = "     " + Str(hIcon)  + Chr(10) + Str(hWnd) + Chr(10) + Str(iState) + Chr(10) + Str(uID) + Chr(10) + IName$
      Else
        turn = turn + 1
        STray$(turn) = "     " + Str(hIcon)  + Chr(10) + Str(hWnd) + Chr(10) + "OFN" + Chr(10) + Str(uID) + Chr(10) + IName$
      EndIf        
        Icon(turn) = hIcon
    EndIf
  Next
    
  Next
 
  VirtualFreeEx_(hProc, *lpData, #Null, #MEM_RELEASE)
  VirtualFreeEx_(hProc, *lpRect, #Null, #MEM_RELEASE)
  CloseHandle_(hProc)
  
 
EndProcedure

Drives$ = Space(#MAX_PATH)
Result = GetLogicalDriveStrings_(#MAX_PATH,@Drives$)

For x = 0 To Result Step 4
    Type$ = PeekS(@Drives$+x,3)
    If GetDriveType_(Type$) = #DRIVE_FIXED Or GetDriveType_(Type$) = #DRIVE_REMOTE
       HDname$(HDN) = Type$
       HDN+1
    EndIf
Next

OpenWindow(0, 0, 0, 800, 600, "SysTray Notification Icons", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)

ListIconGadget(0,10,10,780,580,"Icon-Icon Handle", 100, #PB_ListIcon_GridLines)
SetGadgetColor(0, #PB_Gadget_FrontColor, $FD4B0B)
SetGadgetColor(0, #PB_Gadget_BackColor, $E8FEFE)
   
AddGadgetColumn(0, 1, "Win Handle", 80)
AddGadgetColumn(0, 2, "Status", 45)
AddGadgetColumn(0, 3, "PID", 50)
AddGadgetColumn(0, 4, "Image name", 500)

Find_PB_TrayIcons()

For x = 0 To count-1
    AddGadgetItem(0,-1, STray$(x), Icon(x))
Next


    Repeat
         iEvent = WaitWindowEvent()
         
         Select iEvent
             Case #PB_Event_Gadget
                 Select EventGadget()
                 EndSelect
         EndSelect       
    Until iEvent = #PB_Event_CloseWindow  
   
Edit :Modified for NotifyIcon Overflow Window
Last edited by RASHAD on Wed Oct 03, 2012 7:03 am, edited 2 times in total.
Egypt my love
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Enumerate Icons in the notification area

Post by luis »

Hi RASHAD, sorry but I'm missing the point of this version.
Doesn't look better (seem worse actually if that's possible!).
Maybe it's my fault but there were no comments with the post so I tried to understand it by myself.

Unless the idea was to make it work under a 64 bit os even if the program is 32 bit (it seem so looking at the code) ?

The different structures were interesting but sadly I don't think it's a viable solution.
If virtualallocex() need to return a pointer for virtual space allocated in the 64 bit process of the shell too far away (or if dwData used in readprocess() is again too far) the 32 bits version will fail.
If it doesn't it's by chance.
Try to add this key to the registry of a 64 bit os:

Code: Select all

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management\AllocationPreference
and set it to $100000 (hex)

then reboot and try again the 32 bit compilation.

The key above "simulate" a 64 bit system with a lot of ram occupied and force the os apis to return higher values for pointers. Then the 32 bit version of the program could fail (it does on my test system).

I believe the problem lies here first than the fact the structures must be different since the target process is 64 bit. At least this is how I interpreted it.

If I misunderstood or I'm saying something wrong (I fear it's possible) correct me brutally !
"Have you tried turning it off and on again ?"
A little PureBasic review
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: Enumerate Icons in the notification area

Post by RASHAD »

Hi luis
I did that long time back
But when you get involved I said to myself let us get something new from luis
So you did
And yes it is only for x86 and x64 nothing more maybe less :)
I just updated my previous post for OVNI
Egypt my love
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Enumerate Icons in the notification area

Post by luis »

Updated first post.
"Have you tried turning it off and on again ?"
A little PureBasic review
BarryG
Addict
Addict
Posts: 4128
Joined: Thu Apr 18, 2019 8:17 am

Re: Enumerate Icons in the notification area

Post by BarryG »

Thanks for your code, luis! (And Nish and NetMaestro as being the original sources, of course). I needed this today.

BTW, Luis, in your little PureBasic review you've got 6 bugs listed that you lamented have never been fixed... but I checked them today and they're all marked as "[Done]". So maybe update your review to reflect this?
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Enumerate Icons in the notification area

Post by luis »

@BarryG

I noticed that viewtopic.php?p=594087#p594087

My next update will mention it (with that and the introduction of the C backend the review it's worth updating for the first time). Anyway it's still valid and if today someone following the links see these bugs fixed I'm sure he will be able to reach some conclusion on his own in the meantime :)

Glad the 10 year old code from my former self was helpful, thanks for your post.

EDIT: I've updated it.
Last edited by luis on Thu Mar 23, 2023 11:51 am, edited 1 time in total.
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
jacdelad
Addict
Addict
Posts: 1993
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Enumerate Icons in the notification area

Post by jacdelad »

I tried it under Win10 x64 but everything except OVF is either 0 or empty?!
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Enumerate Icons in the notification area

Post by luis »

jacdelad wrote: Wed Mar 01, 2023 2:42 pm I tried it under Win10 x64 but everything except OVF is either 0 or empty?!
Did you compile it for 64 bits ? The process must be the same bitness of the OS (or at least I thought so 10 years ago)
; The program must be compiled to 32 bit for 32 bit oses and to 64 bit for 64 bit oses.
; The 32 bit version cannot work on a 64 bit os (the 32 bit process cannot read the infos from the 64 bit shell).
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
jacdelad
Addict
Addict
Posts: 1993
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: Enumerate Icons in the notification area

Post by jacdelad »

Yes, I did. Also, now it works...
I seem to have problems on my computer, like I wrote in the other post. Please ignore me...
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Post Reply