how enumerate all desktop icons (name/label) ?

Everything else that doesn't fall into one of the other PB categories.
User avatar
idle
Always Here
Always Here
Posts: 5839
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: how enumerate all desktop icons (name/label) ?

Post by idle »

sorry I can't help don't have win7
Windows 11, Manjaro, Raspberry Pi OS
Image
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: how enumerate all desktop icons (name/label) ?

Post by Thunder93 »

I was only using PB x64. The adjustment was required if you was saving with Unicode mode. Without the adjustment the saving wasn't much.

Also the saves from the both modes would be different, so you would want to restore using the correct mode. Little adjustments and I think you can save / load exactly the same information by the both.


With that said.. I did try PB x86 on Win7 x64 and noticed the Icon names aren't being retrieved.

ReadProcessMemory_ is failing or one of the dependencies.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Thade
Enthusiast
Enthusiast
Posts: 266
Joined: Sun Aug 03, 2003 12:06 am
Location: Austria

Re: how enumerate all desktop icons (name/label) ?

Post by Thade »

Thanks for trying and the Info about ReadProcessMemory_

Have obviously to debug it step by step to see why it fails.

Code: Select all

Procedure DesktopHandle()
  Static Desktop 
  If Not Desktop 
   Desktop = FindWindow_("ProgMan",#Null)
   Desktop = GetWindow_ (Desktop,#GW_CHILD)
   Desktop = GetWindow_ (Desktop,#GW_CHILD)
   Debug "Desktop: "+Str(Desktop)
  EndIf  
  ProcedureReturn Desktop
EndProcedure
Debugwindow:
Desktop: 0
Desktop: 0
Desktop: 0
Desktop: 0
Desktop: 0
Desktop: 0
Last edited by Thade on Tue Feb 11, 2014 1:51 am, edited 1 time in total.
--------------
Yes, its an Irish Wolfhound.
Height: 107 cm; Weight: 88 kg
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: how enumerate all desktop icons (name/label) ?

Post by Thunder93 »

Are you using PB x86 on Win7 x64?
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Thade
Enthusiast
Enthusiast
Posts: 266
Joined: Sun Aug 03, 2003 12:06 am
Location: Austria

Re: how enumerate all desktop icons (name/label) ?

Post by Thade »

PB x86

Btw: I edited the post above while you wrote ...


EDIT: Using the same Program on my Gaming PC (see Signature) the result is the same. Something has changed between 21st and 25th of January (after a Windows Update?)
Last edited by Thade on Tue Feb 11, 2014 2:08 am, edited 2 times in total.
--------------
Yes, its an Irish Wolfhound.
Height: 107 cm; Weight: 88 kg
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: how enumerate all desktop icons (name/label) ?

Post by Thunder93 »

Alright. Your problem is different. That information is properly retrieved with PB x64 & x86 running on Win7 x64.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Thade
Enthusiast
Enthusiast
Posts: 266
Joined: Sun Aug 03, 2003 12:06 am
Location: Austria

Re: how enumerate all desktop icons (name/label) ?

Post by Thade »

I found the reason why it was different!

Some weeks ago (around the 22nd of Jan.) I had the *glorious* idea to change my desktop background to slideshow 8) I am switching between 3 different PCs several times a day and I thought its nice to show the latest photos I shot on the two ones which are not actually used.

This obviously makes a big change ... FindWindow does not work when in Slideshow mode as expected ... Desktop Handle is 0 ... etc. That's why the Program didn't work anymore.
Back to one Background and booting the system solved it all.

So if I want the Slideshow and switching between different Icon Sets I will have to find a way to bring Desktop Handle to work.

EDIT: Or - what could be the easiest way - use an own Slideshow program which changes the Desktop Background every 10 Minutes - which I already programmed some years ago. :D Works like a screen saver
Best advantage is that it stops changing backgrounds on the computer where I am working.
--------------
Yes, its an Irish Wolfhound.
Height: 107 cm; Weight: 88 kg
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: how enumerate all desktop icons (name/label) ?

Post by Thunder93 »

Very good!.

That isn't a problem though. Use the following procedure instead.

Code: Select all

Procedure DesktopHandle()
  Protected hProgman, hShellViewWin, hWorkerW, hDesktopWnd
  
  Static hDesktopListView
  If Not hDesktopListView
    
    hProgman = FindWindow_("ProgMan", 0)
    hDesktopWnd = GetDesktopWindow_();
    
    ;// If the main Program Manager window is found
    If hProgman
      ;// Get and load the main List view window containing the icons (found using Spy++).
      
      hShellViewWin = FindWindowEx_(hProgman, 0, "SHELLDLL_DefView", 0);
      If hShellViewWin
        hDesktopListView = FindWindowEx_(hShellViewWin, 0, "SysListView32", 0);
      Else
        ; // When this fails (happens in Windows-7 when picture rotation is turned ON), then look For the WorkerW windows List To get the
        ;// correct desktop List handle.
        ;// As there can be multiple WorkerW windows, so iterate through all To get the correct one
        
        Repeat
          hWorkerW = FindWindowEx_( hDesktopWnd, hWorkerW, "WorkerW", #Null );
          hShellViewWin = FindWindowEx_(hWorkerW, 0, "SHELLDLL_DefView", 0);
        Until hShellViewWin <> #Null And hWorkerW <> #Null
        
        ;// Get the ListView control
        hDesktopListView = FindWindowEx_(hShellViewWin, 0, "SysListView32", 0);	  	
      EndIf
      
    EndIf
    
  EndIf
  
  ProcedureReturn hDesktopListView
EndProcedure
:)
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Thade
Enthusiast
Enthusiast
Posts: 266
Joined: Sun Aug 03, 2003 12:06 am
Location: Austria

Re: how enumerate all desktop icons (name/label) ?

Post by Thade »

Wow - big surprise after getting up in the morning :)

Thank you very much. This works!

.
--------------
Yes, its an Irish Wolfhound.
Height: 107 cm; Weight: 88 kg
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: how enumerate all desktop icons (name/label) ?

Post by Thunder93 »

Your welcome.

With the Unicode support and the improved DesktopHandle() function, will poster the code for convince. Also addressed the annoying multi command submissions per button click, I was seeing 3 and 4 triggers per click.

Including also support for 32bit App running under 64bit OS.

Code: Select all

CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Prototype GetNativeSystemInfo(*lpSystemInfo.SYSTEM_INFO)

#PROCESSOR_ARCHITECTURE_AMD64 = 9
#PROCESSOR_ARCHITECTURE_IA64  = 6
#PROCESSOR_ARCHITECTURE_INTEL = 0
#PROCESSOR_ARCHITECTURE_UNKNOWN = $ffff


Procedure Is64bitOS()
  Protected kernel32, GetNativeSystemInfo.GetNativeSystemInfo
  Protected info.SYSTEM_INFO
  Protected Result = #False
  
  kernel32 = OpenLibrary(#PB_Any, "Kernel32.dll")
  If kernel32
    GetNativeSystemInfo = GetFunction(kernel32, "GetNativeSystemInfo")
    
    If GetNativeSystemInfo
      GetNativeSystemInfo(@info)
      If info\wProcessorArchitecture <> #PROCESSOR_ARCHITECTURE_INTEL ; x86
        Result = #True
      EndIf      
    EndIf
  
    CloseLibrary(kernel32)
  EndIf  

  ProcedureReturn Result
EndProcedure

  Structure LV_ITEM1 Align 2 
    mask.l
    iItem.l
    iSubItem.l
    state.l
    stateMask.l
    Padding.l
    *pszText
    Padding1.l
    cchTextMax.l
    iImage.l
    lParam.l
    Padding2.l
  EndStructure ;: Global 32OnX64.LV_ITEM1
CompilerEndIf

; EnableExplicit
Structure DeskInfo
  sz.i
  name.s
  pt.point
EndStructure

Global Dim GlobalDeskinfo.DeskInfo(0)
Global Explorer
Global GlobalLVItem
Global GlobalBuffer

Procedure DesktopHandle()
  Protected hProgman.l, hDesktopWnd.l, hShellViewWin.l, hWorkerW.l, hDesktopListView.l
  
  hProgman = FindWindow_("ProgMan", 0)
  hDesktopWnd = GetDesktopWindow_()
  
  If hProgman
    
    hShellViewWin = FindWindowEx_(hProgman, 0, "SHELLDLL_DefView", 0);
    If hShellViewWin
      hDesktopListView = FindWindowEx_(hShellViewWin, 0, "SysListView32", 0);
    Else
      
      Repeat
        hWorkerW = FindWindowEx_( hDesktopWnd, hWorkerW, "WorkerW", #Null );
        hShellViewWin = FindWindowEx_(hWorkerW, 0, "SHELLDLL_DefView", 0);
      Until hShellViewWin <> #Null And hWorkerW <> #Null
      
      hDesktopListView = FindWindowEx_(hShellViewWin, 0, "SysListView32", 0);      
    EndIf	 
    
    ProcedureReturn hDesktopListView
  EndIf
EndProcedure

Procedure DesktopProcessOpen()
  Protected ExplorerID
  Protected Flags = #PROCESS_VM_OPERATION | #PROCESS_VM_READ | #PROCESS_VM_WRITE | #PROCESS_QUERY_INFORMATION
  
  GetWindowThreadProcessId_(DesktopHandle(),@ExplorerID)
  Explorer = OpenProcess_(Flags,#Null,ExplorerID)
  GlobalLVItem = VirtualAllocEx_(Explorer,#Null,SizeOf(LV_ITEM),#MEM_COMMIT,#PAGE_READWRITE )
  GlobalBuffer = VirtualAllocEx_(Explorer,#Null,#MAX_PATH,#MEM_COMMIT,#PAGE_READWRITE)
  
  CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
    If Is64bitOS()
      ItemB.LV_ITEM1
      
      With ItemB
        \mask       = #LVIF_TEXT
        \iSubItem   = 0
        \pszText    = GlobalBuffer
        \cchTextMax = #MAX_PATH
      EndWith : WriteProcessMemory_(Explorer,GlobalLVItem,ItemB,SizeOf(ItemB),#Null) 
      
    Else
      ItemA.LV_ITEM
      
      With ItemA
        \mask       = #LVIF_TEXT
        \iSubItem   = 0
        \pszText    = GlobalBuffer
        \cchTextMax = #MAX_PATH
      EndWith : WriteProcessMemory_(Explorer,GlobalLVItem,ItemA,SizeOf(ItemA),#Null) 
    EndIf   
    
  CompilerElse
    ItemA.LV_ITEM
    
    With ItemA
      \mask       = #LVIF_TEXT
      \iSubItem   = 0
      \pszText    = GlobalBuffer
      \cchTextMax = #MAX_PATH
    EndWith : WriteProcessMemory_(Explorer,GlobalLVItem,ItemA,SizeOf(ItemA),#Null) 
  CompilerEndIf  
  
EndProcedure

Procedure DesktopProcessClose ( )
  VirtualFreeEx_(Explorer,GlobalLVItem,#Null,#MEM_RELEASE)
  VirtualFreeEx_(Explorer,GlobalBuffer,#Null,#MEM_RELEASE)
  CloseHandle_(Explorer)
EndProcedure

Procedure DesktopIconCount ( )
  ProcedureReturn SendMessage_(DesktopHandle(),#LVM_GETITEMCOUNT,#Null,#Null)
EndProcedure

Procedure.s DesktopGetIconString(Index)
  Protected String$=Space(#MAX_PATH)
  
  SendMessage_(DesktopHandle(),#LVM_GETITEMTEXT,Index,GlobalLVItem)
  ReadProcessMemory_(Explorer,GlobalBuffer,@String$,#MAX_PATH,#Null)
  
  ProcedureReturn String$   
EndProcedure

Procedure DesktopGetIconPosition(index,*pt.point)
  If SendMessage_(DesktopHandle(),#LVM_GETITEMPOSITION,index,GlobalLVItem )
    ReadProcessMemory_(Explorer,GlobalLVItem,*pt,SizeOf(Point),#Null)
    ProcedureReturn #True
  Else 
    ProcedureReturn #False
  EndIf   
EndProcedure

Procedure DesktopSetIconPos(Index,X,Y)
  ProcedureReturn SendMessage_(DesktopHandle(),#LVM_SETITEMPOSITION,Index,(Y<<16)|(X&$FFFF))
EndProcedure

Procedure SaveDesktopIconsPositions()
  
  Protected fn,Count,index,pt.point,name.s 
  
  fn = OpenFile(-1,"desk.bin")
  
  If fn 
    DesktopProcessOpen()
    Count = DesktopIconCount()
    ReDim GlobalDeskinfo.DeskInfo(count)
    
    WriteData(fn,@count,SizeOf(Integer)) 
    
    For index = 0 To Count - 1
      
      GlobalDeskinfo(index)\name = DesktopGetIconString(index)  :  Debug GlobalDeskinfo(index)\name
      GlobalDeskinfo(index)\sz = StringByteLength(GlobalDeskinfo(index)\name)      
      
      If DesktopGetIconPosition(index,pt)
        GlobalDeskinfo(index)\pt\x = pt\x 
        GlobalDeskinfo(index)\pt\y = pt\y 
      EndIf   
      
      WriteData(fn,@GlobalDeskinfo(index)\sz,SizeOf(Integer))
      WriteData(fn,@GlobalDeskinfo(index)\name,GlobalDeskinfo(index)\sz)
      WriteData(fn,@GlobalDeskinfo(index)\pt,SizeOf(point))
    Next 
    CloseFile(fn)
  EndIf
  
  DesktopProcessClose()
EndProcedure 

Procedure RestoreDesktopIconsPositions()
  Protected count,*buf,name.s,len,pt.point,fn,index  
  *buf = AllocateMemory(#MAX_PATH) 
  count = ArraySize(GlobalDeskinfo())
  
  DesktopProcessOpen()
  If count > 0 
    For index = 0 To count 
      DesktopSetIconPos(index,GlobalDeskinfo(index)\pt\x,GlobalDeskinfo(index)\pt\y) 
    Next 
  Else 
    fn = ReadFile(-1,"desk.bin") 
    If fn 
      ReadData(fn,@count,SizeOf(Integer)) 
      If count > 0  
        For index = 0 To count 
          ReadData(fn,@len,SizeOf(Integer))
          ReadData(fn,*buf,len) 
          name = PeekS(*buf,len) 
          ReadData(fn,@PT,SizeOf(point)) 
          If DesktopGetIconString(index) = name 
            DesktopSetIconPos(index,pt\x,pt\y)
          EndIf 
        Next
      EndIf 
      CloseFile(fn)
    EndIf
  EndIf   
  DesktopProcessClose()
  FreeMemory(*buf) 
  
EndProcedure 

Define Event

OpenWindow(0,200,200,140,30,"desk Icons",#PB_Window_SystemMenu)

ButtonGadget(1,5,5,60,20,"save")
ButtonGadget(2,70,5,60,20,"restore") 

Repeat
  Event = WaitWindowEvent()
  
  Select Event      
    Case #PB_Event_Gadget
      Select EventType()
        Case #PB_EventType_LeftClick
          Select EventGadget()
            Case 1 : Debug "Saving" : SaveDesktopIconsPositions()
            Case 2 : Debug "Restoring" : RestoreDesktopIconsPositions()
          EndSelect          
      EndSelect
  EndSelect
Until Event = #PB_Event_CloseWindow
Last edited by Thunder93 on Sat Mar 15, 2014 12:21 pm, edited 1 time in total.
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Axolotl
Addict
Addict
Posts: 802
Joined: Wed Dec 31, 2008 3:36 pm

Re: how enumerate all desktop icons (name/label) ?

Post by Axolotl »

Hi Thunder93

cannot close the program on win7 64b as x86 because of #WM_CLOSE.
Insertion of

Code: Select all

    Case #PB_Event_CloseWindow :Debug "CloseWindow"
      Break 
in the main Select ... EndSelect part should help.
Take care.
Andreas
Just because it worked doesn't mean it works.
PureBasic 6.04 (x86) and <latest stable version and current alpha/beta> (x64) on Windows 11 Home. Now started with Linux (VM: Ubuntu 22.04).
User avatar
Thunder93
Addict
Addict
Posts: 1788
Joined: Tue Mar 21, 2006 12:31 am
Location: Canada

Re: how enumerate all desktop icons (name/label) ?

Post by Thunder93 »

That was carried over.

It did work with the latest PB at the time. Which was 5.21 LTS, and worked for both platforms. However, better and preferred way is what you've suggested. Thanks.

Like it has been stated countless times over the PB forums...
also to quoting luis post.

(Wait)WindowEvent() was never documented suggesting it can be used to retrieve Windows messages.
It works but can stop to do so for some messages at any moment as you just discovered.
Better to use a callback (that's the "clean" way) or just switch to the new native PB message in your case if you prefer to do so.
” - http://www.purebasic.fr/english/viewtop ... 28#p409328
ʽʽSuccess is almost totally dependent upon drive and persistence. The extra energy required to make another effort or try another approach is the secret of winning.ʾʾ --Dennis Waitley
Post Reply