Page 1 of 2

Save & Restore Desktop Icons Position[Windows]

Posted: Sat Dec 01, 2018 4:36 am
by RASHAD
Hi all
Compile with PB x86
Based on work by Thunder93
Tested with PB x86 Windows 10 x64 ,windows 7 x86

Code: Select all

CompilerIf #PB_Compiler_Processor <> #PB_Processor_x86
  End
CompilerEndIf

Prototype GetNativeSystemInfo(*lpSystemInfo.SYSTEM_INFO)

#PROCESSOR_ARCHITECTURE_AMD64 = 9
#PROCESSOR_ARCHITECTURE_IA64  = 6
#PROCESSOR_ARCHITECTURE_INTEL = 0
#PROCESSOR_ARCHITECTURE_UNKNOWN = $ffff
#SHCNE_ASSOCCHANGED = $8000000
#SHCNF_IDLIST       = $1000

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

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

Global Dim GlobalDeskinfo.DeskInfo(0)
Global Explorer, GlobalLVItem , GlobalBuffer ,hDesktopListView ,String$,count
String$ = Space(#MAX_PATH)

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   
EndIf


Procedure refresh()
  ClearGadgetItems(0)
  If ExamineDirectory(0, GetHomeDirectory(), "*.dmr")
    n = 1
    While NextDirectoryEntry(0)
      AddGadgetItem(0,-1,Str(n)+Chr(10)+ DirectoryEntryName(0))
      n+1
    Wend
    FinishDirectory(0)
  EndIf
EndProcedure 

Import ""
  GetNativeSystemInfo(*info)
EndImport

Procedure Is64bitOS()
  Protected Info.SYSTEM_INFO
  GetNativeSystemInfo(Info)
  If info\wProcessorArchitecture
    ProcedureReturn #True
  EndIf
EndProcedure

Procedure DesktopProcessOpen()
  Protected ExplorerID
  Protected Flags = #PROCESS_VM_OPERATION | #PROCESS_VM_READ | #PROCESS_VM_WRITE | #PROCESS_QUERY_INFORMATION
 
  GetWindowThreadProcessId_(hDesktopListView,@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.s DesktopGetIconString(Index)
  SendMessage_(hDesktopListView,#LVM_GETITEMTEXT,Index, GlobalLVItem)
  ReadProcessMemory_(Explorer,GlobalBuffer,@String$,#MAX_PATH, #Null) 
  ProcedureReturn String$   
EndProcedure

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

Procedure SaveDesktopIconsPositions() 
  Protected fn,index,pt.point,name.s
  file$ = FormatDate("%yy-%mm-%dd-%hh-%ii-%ss", Date())+".dmr"
  fn = OpenFile(#PB_Any,GetHomeDirectory()+file$)
 
  If fn
    DesktopProcessOpen()
    Count = SendMessage_(hDesktopListView,#LVM_GETITEMCOUNT,#Null,#Null)
    ReDim GlobalDeskinfo.DeskInfo(count)
   
    WriteData(fn,@count,SizeOf(Integer))
   
    For index = 0 To Count-1
     
      GlobalDeskinfo(index)\name = DesktopGetIconString(index) 
      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()
  MessageRequester("Info","Desktop Icons Position Saved",#MB_ICONINFORMATION|#MB_OK)
EndProcedure

Procedure RestoreDesktopIconsPositions()
  Protected count,*buf,name.s,len,pt.point,fn,index 
  ShowWindow_(hDesktopListView,#SW_HIDE)
   For no = 1 To 3 
  *buf = AllocateMemory(#MAX_PATH)
    count = ArraySize(GlobalDeskinfo()) 
    DesktopProcessOpen()  
    file$ = GetGadgetItemText(0,GetGadgetState(0),1)
    fn = ReadFile(#PB_Any,GetHomeDirectory()+file$)
    If fn
      ReadData(fn,@count,SizeOf(Integer))
      If count > 0   
        For index = 0 To count-1
          FillMemory(*buf, #MAX_PATH)
          ReadData(fn,@len,SizeOf(Integer))
          ReadData(fn,*buf,len)
          name = PeekS(*buf,len)
          ReadData(fn,@PT,SizeOf(point))
          For item = 0 To count - 1
            If DesktopGetIconString(item) = name              
              SendMessage_(hDesktopListView,#LVM_SETITEMPOSITION,item, pt\y<<16|pt\x)
              Break
            EndIf
          Next
        Next
      EndIf
      CloseFile(fn)
      ;MessageRequester("Info","Desktop Icons Position Restored",#MB_ICONINFORMATION|#MB_OK)
    EndIf
;   EndIf 
  DesktopProcessClose()
  FreeMemory(*buf)
  Next
  ShowWindow_(hDesktopListView,#SW_SHOW)             
  ;SHChangeNotify_(#SHCNE_ASSOCCHANGED, #SHCNF_IDLIST, 0, 0)
EndProcedure


Define Event
UsePNGImageDecoder()
LoadFont(0,"Consolas",14)
OpenWindow(0,0,0,500,300,"Desktop Icons", #PB_Window_SystemMenu |#PB_Window_ScreenCentered)
SetWindowColor(0,$C3C3C3)
  If CreateToolBar(0, WindowID(0))
    ToolBarID = ToolBarID(0)
    TBIL = SendMessage_(ToolBarID, #TB_GETIMAGELIST , 0, 0)
    ImageList_SetIconSize_(TBIL,24,24)
    SetWindowLongPtr_(ToolBarID(0),#GWL_STYLE, GetWindowLongPtr_(ToolBarID(0),#GWL_STYLE)|#CCS_NODIVIDER)
    SendMessage_(ToolBarID,#TB_SETBUTTONSIZE,0,24 | 24 << 16)
    SendMessage_(ToolBarID,#TB_AUTOSIZE,0,0)
    
    ToolBarImageButton(0, 0)
    ToolBarImageButton(1, LoadImage(0, #PB_Compiler_Home + "examples/sources/Data/ToolBar/Save.png"))   
    ToolBarToolTip(0, 1, "Save Icons")
    ToolBarImageButton(2, 0) 
    ToolBarImageButton(3, LoadImage(0, #PB_Compiler_Home + "examples/sources/Data/ToolBar/Paste.png"))
    ToolBarToolTip(0, 3, "Restore Icons")
    ToolBarImageButton(4, 0) 
    ToolBarImageButton(5, LoadImage(0, #PB_Compiler_Home + "examples/sources/Data/ToolBar/Cut.png"))
    ToolBarToolTip(0, 5, "Delete Item")
  EndIf
  DisableToolBarButton(0,0,1)
  DisableToolBarButton(0,2,1)
  DisableToolBarButton(0,2,1)
  
  ListIconGadget(0,10,32,480,256,"",40,#PB_ListIcon_FullRowSelect | #PB_ListIcon_GridLines)
  AddGadgetColumn(0,1,"",436)
  SetWindowLongPtr_(GadgetID(0), #GWL_STYLE, GetWindowLongPtr_(GadgetID(0), #GWL_STYLE)|#LVS_NOCOLUMNHEADER)
  SetGadgetFont(0,FontID(0))
  SetGadgetColor(0,#PB_Gadget_BackColor,$EBEBEB)
  SetGadgetColor(0,#PB_Gadget_FrontColor,$FE0B06)
  refresh()

Repeat
  Event = WaitWindowEvent()
  Select Event     
    Case #PB_Event_Menu
      Select EventMenu()
        Case 1
          SaveDesktopIconsPositions()
          refresh()
        Case 3 
          RestoreDesktopIconsPositions()
        Case 5
          DeleteFile(GetHomeDirectory()+GetGadgetItemText(0, GetGadgetState(0),1))
          refresh()
      EndSelect
  EndSelect
Until Event = #PB_Event_CloseWindow
Edit : - Bugs fixed
- More speed
- Good looking
- Dude bug fixed and more

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Sat Dec 01, 2018 7:30 am
by Dude
Hi Rashad,

First, I appreciate all your work on this. :)

Unfortunately, it still fails after I right-click the desktop and select "Sort by -> Name".

I'm on Windows 7 Ultimate, 64-bit, using PureBasic v5.70 Beta 2 (32-bit).

Here's a video showing the problem in realtime for you: https://imgur.com/LhK09jc

See how after restoring, the "Computer" and "Google Chrome" icons are not in their saved positions?

Here's a before-and-after image comparison of saving and restoring:

Image

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Sat Dec 01, 2018 3:40 pm
by CELTIC88
hi mr Rashad,

why do you use a hack for that?
I do not like, and your antivirus will not like it.

fast example :D

Code: Select all

;by CELTIC1888 2018

Macro DEFINE_GUID(name, ll, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8):DataSection:name:Data.l ll:Data.w w1:Data.w w2:Data.b b1, b2, b3, b4, b5, b6, b7, b8:EndDataSection:EndMacro
DEFINE_GUID(IID_IShellWindows,$85CB6900,$4D95,$11CF,$96,$0C,$00,$80,$C7,$F4,$EE,$85)
DEFINE_GUID(CLSID_ShellWindows,$9BA05972,$F6A8,$11CF,$A4,$42,$00,$A0,$C9,$0A,$8F,$39)
DEFINE_GUID(SID_STopLevelBrowser,$4C96BE40, $915C, $11CF, $99, $D3, $00, $AA, $00, $4A, $E8, $37)
DEFINE_GUID(IID_IShellBrowser, $000214E2, 0, 0, $C0,0,0,0,0,0,0,$46)
DEFINE_GUID(IID_IFolderView, $cde725b0, $ccc9, $4519, $91, $7e, $32, $5d, $72, $fa, $b4, $ce)
DEFINE_GUID(IID_IShellFolder, $000214E6, $0000, $0000, $C0, $00, $00, $00, $00, $00, $00, $46)
DEFINE_GUID(IID_IEnumIDList, $000214F2,$0000,$0000,$C0,$00,$00,$00,$00,$00,$00,$46)

OpenLibrary(0,"shlwapi")
Prototype IUnknown_QueryService(punk,guidService,riid,ppvOut)
Global IUnknown_QueryService.IUnknown_QueryService = GetFunction(0,"IUnknown_QueryService")
Prototype StrRetToStrW(pstr,pidl,ppsz)
Global StrRetToStrW.StrRetToStrW = GetFunction(0,"StrRetToStrW")

Structure STRRET
  uType.l
  StructureUnion
    *pOleStr
    uOffset.l
    cStr.c[260]
  EndStructureUnion
EndStructure

#CLSCTX_ALL = $17
#SWC_DESKTOP = $00000008
#SWFO_NEEDDISPATCH = $00000001
#SVGIO_ALLVIEW	= $2
#SHGDN_NORMAL	= 0
#SVSI_POSITIONITEM	= $80
EnableExplicit

CoInitializeEx_(0,0)

Structure DeskInfo
  name.s
  pt.point
EndStructure

;SaveOrRestore = 1 save icons position
Procedure DesktopiconsSaveAndRestorePos(List GlobalDeskinfo.DeskInfo(),SaveOrRestore = 1)
  If SaveOrRestore = 1
    ClearList(GlobalDeskinfo())
  EndIf
  Protected spShellWindows.IShellWindows
  Protected vtLoc.Variant\vt =#VT_I4:vtLoc\lVal = #CSIDL_DESKTOP
  Protected vtEmpty.Variant,spdisp.IDispatch,spBrowser.IShellBrowser,spshView.IShellView,
            spView.IFolderView,lhwnd ,
            spFolder.IShellFolder,spEnum.IEnumIDList,spidl, po.POINT,str.STRRET,spszName 
  
  If CoCreateInstance_(?CLSID_ShellWindows, 0, #CLSCTX_ALL,
                       ?IID_IShellWindows, @spShellWindows) = 0
    If spShellWindows\FindWindowSW(vtLoc, vtEmpty,
                                   #SWC_DESKTOP, @lhwnd, #SWFO_NEEDDISPATCH, @spdisp) = 0
      If IUnknown_QueryService(spdisp,?SID_STopLevelBrowser,?IID_IShellBrowser,@spBrowser) = 0
        
        If spBrowser\QueryActiveShellView(@spshView) = 0
          
          If spshView\QueryInterface(?IID_IFolderView, @spView) = 0
            
            If spView\GetFolder(?IID_IShellFolder,@spFolder) = 0
              
              If spView\Items(#SVGIO_ALLVIEW, ?IID_IEnumIDList,@spEnum) = 0
                
                While spEnum\Next(1, @spidl, 0) = 0
                  If spView\GetItemPosition(spidl,@po) = 0 
                    If spFolder\GetDisplayNameOf(spidl, #SHGDN_NORMAL, str) = 0
                      StrRetToStrW(str,spidl,@spszName)
                      If SaveOrRestore = 1
                        AddElement(GlobalDeskinfo())
                        GlobalDeskinfo()\name = PeekS(spszName)
                        GlobalDeskinfo()\pt\x = po\x
                        GlobalDeskinfo()\pt\y = po\y
                        Debug GlobalDeskinfo()\name
                      Else 
                        ForEach GlobalDeskinfo()
                          If GlobalDeskinfo()\name = PeekS(spszName)
                            po\x = GlobalDeskinfo()\pt\x
                            po\y = GlobalDeskinfo()\pt\y
                            spView\SelectAndPositionItems(1,@spidl,@po,#SVSI_POSITIONITEM)
                          EndIf
                        Next
                      EndIf
                    EndIf
                  EndIf
                Wend
                
                spEnum\Release()
              EndIf
              spFolder\Release()
            EndIf
            spView\Release()
          EndIf
          spshView\Release()
        EndIf
        spBrowser\Release()
      EndIf
      spdisp\Release()
    EndIf
    spShellWindows\Release()
  EndIf
EndProcedure

Global NewList GlobalDeskinfo.DeskInfo()
MessageRequester("click OK","save icons position")
DesktopiconsSaveAndRestorePos(GlobalDeskinfo(),1)
MessageRequester("click OK","restore icons position")
DesktopiconsSaveAndRestorePos(GlobalDeskinfo(),0)

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Sat Dec 01, 2018 5:29 pm
by RASHAD
@All
Previous post updated

@CELTIC88
Thanks for the contribution
But it did not work as it should be
Read Dude comments

Code: Select all

Global NewList GlobalDeskinfo.DeskInfo()
MessageRequester("click OK","save icons position")
DesktopiconsSaveAndRestorePos(GlobalDeskinfo(),1)
Delay(5000) ;while Delay time try to sort by name as Dude pointed the icons will be scattered all around
MessageRequester("click OK","restore icons position")
DesktopiconsSaveAndRestorePos(GlobalDeskinfo(),0)
Waiting for your next version :wink:

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Sat Dec 01, 2018 7:21 pm
by Kwai chang caine
Hello my two heroes :D
I have clicked "automatic reorganisation" of windows for move all my icons to the left
And here... the two codes works, W10 x64 / v5.62 x86 and replace all icons at their place 8) fortunately for me :mrgreen:
Thanks at you two for sharing 8)

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Sat Dec 01, 2018 9:40 pm
by CELTIC88
Delete by author.

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Sun Dec 02, 2018 12:11 am
by Dude
RASHAD wrote:- Dude bug fixed
Thanks Rashad! :) Can confirm that it's fixed for me. You truly are amazing.

But you still have one tiny bug: in the SaveDesktopIconsPositions() procedure, the DesktopProcessClose() call is outside the If/EndIf block, which means it will be called even if DesktopProcessOpen() isn't called, such as when fn=0. ;) It needs to go directly after CloseFile(fn).

And a question: should "Count" be both global and protected?

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Tue Dec 04, 2018 2:13 pm
by RSBasic
Thank you for sharing. :)

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Thu Dec 06, 2018 12:20 pm
by Kwai chang caine
@CELTIC88
Yeeess !!! really faster :shock:
Works perfectly here W10 x64 / v5.62 x86
Thanks again a lot 8)

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Thu Dec 06, 2018 1:12 pm
by Kwai chang caine
@CELTIC88
I don't know if it's your code, but a little time after using it, each texts of all my dektop icons are all in only one line and after another little time all move to the corner, like if i automaticaly organize by windows :shock:

Then for try to fix this behavior, i have the bad idea to reboot my machine, and this time it's worst :|
My desktop are disappear and be replace by a big white window with collumn header and scrollbar on all the screen, and impossible to retrieve my desktop :cry:
But the more surprising, it's i can when even move each icon like if i have a real desktop :shock:

In finally, i have a Desktop with column header + ScrollBar + one line text with medium icon and return at the line with big icon but no image :shock:

Someone understand something to this behavior ?
I use W10 X64

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Thu Dec 06, 2018 5:17 pm
by Kwai chang caine
@CELTIC88
I got to fix alone my desktop problem, i have run W10 in "without failure" mode, and another time in normal mode, and my normal desktop become with all my icons, and without scrollbar and column header in the top of screen 8)
I'm not sure it's your code who have do that :wink:
But i was so afraid of having to reinstall W10, than excuse me, i not dare to run it another time :oops: we never know... :wink:

Suddently, i remember than when i was young, my parents always say to me

Image

It's dangerous to play with the matches :lol:

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Thu Dec 06, 2018 6:02 pm
by RASHAD
@KCC :mrgreen:
I should tell you that before you play with it
Your desktop listview changed to List Mode & no icons Yes?
CELTIC88 is playing with windows resources
Too dangerous

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Thu Dec 06, 2018 6:53 pm
by Kwai chang caine
Hello RASHAD happy to talk to you :D
Rashad wrote:Your desktop listview changed to List Mode & no icons Yes?
Apparently yes, a style of that, in fact a real "whorehouse" like we say in french :lol:
And the more funny, is the effect not appear immediatly :shock:
I have run the nice CELTIC code, reorganize automaticaly my icons desktop by windows, for move all the icons in the top left corner of the screen
After, i have click the MsgBox of Celtic for restore the position of all icons, and all are done 8)

I write the first message on the forum, and after some time, i close Firefox and see no icons on my desktop :shock:
The text of each icon have on only one line and furthermore a header on the top of the screen with column, exactely like my desktop became a full explorer windows with right scrollbar, but without the three top right buttons (close/restore/minimize)
And impossible to exit this windows :|
I have search, do several manipulations, and reboot several time without succes :|
And thinking to reboot windows in "without faillure" mode, thanks to internet advice 8)
Rashad wrote:CELTIC88 is playing with windows resources
Too dangerous
CELTIC is apparently like you...a magician, perhaps a "little bit" more young :wink:
He create powerfull codes, than i not understand one line :oops:
Perhaps this time he have playing a little bit too much at the sorcerer's apprentice with my Desktop :lol:

Image

Normally it's KCC the champion to create very bad or dangerous code ...it's the world upside down :mrgreen:

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Thu Dec 06, 2018 7:48 pm
by CELTIC88
:( I am very very sorry, in fact it's true my code causes a strange desktop display "with the second code"

I will see where is the problem

: ( re-sorry

Re: Save & Restore Desktop Icons Position[Windows]

Posted: Thu Dec 06, 2018 8:02 pm
by Kwai chang caine
You have right, only the second code is a little bit .... "Dangerous" Image

Image
Celtic88 wrote: I am very very sorry,
No problem my friend :wink:
For me it's the price to pay, for have really great code like all you create 8)
Fortunately...i'm not forcing to buy another PC :mrgreen: :lol: :lol:

One time more...that proof the real powerfull of PB 8)