Page 2 of 2

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

Posted: Mon Feb 10, 2014 11:41 pm
by idle
sorry I can't help don't have win7

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

Posted: Tue Feb 11, 2014 1:26 am
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.

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

Posted: Tue Feb 11, 2014 1:43 am
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

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

Posted: Tue Feb 11, 2014 1:50 am
by Thunder93
Are you using PB x86 on Win7 x64?

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

Posted: Tue Feb 11, 2014 1:53 am
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?)

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

Posted: Tue Feb 11, 2014 2:05 am
by Thunder93
Alright. Your problem is different. That information is properly retrieved with PB x64 & x86 running on Win7 x64.

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

Posted: Tue Feb 11, 2014 3:04 am
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.

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

Posted: Tue Feb 11, 2014 4:17 am
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
:)

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

Posted: Tue Feb 11, 2014 11:49 am
by Thade
Wow - big surprise after getting up in the morning :)

Thank you very much. This works!

.

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

Posted: Wed Feb 12, 2014 1:04 am
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

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

Posted: Sat Mar 15, 2014 12:08 pm
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

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

Posted: Sat Mar 15, 2014 12:28 pm
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