Is it possible to move the desktop shortcuts?? perhaps let them flee when the cursor wants to click them ;)
I've never tried it but, IIRC the desktop is nothing more than a big list-view control. So use FindWindow(Ex) to get a handle to the SysListView32 (it should be a child control of a window called 'program manager') and then send LVM_SETITEMPOSITION messages to rearrange the icons. Also use SetWindowLong() to remove the LVS_AUTOARRANGE style, and maybe use SetWindowPos() to make sure the style was removed.
If that doesn't work try subclassing the control and blocking some messages that it might be using to keep other applications from messing with it.
If that doesn't work try subclassing the control and blocking some messages that it might be using to keep other applications from messing with it.
thanx a lot.
I'll try that
I'll try that
I wasn't able to retrieve the SysListView32 Handle via FindWindowEx(). So i had to call WindowFromPoint() and finally got the handle.
Now my Question:
Is there another way to get the handle beside mine WindowFromPoint() call, wich means also minimizin all opened windows to get the handle?
Now my Question:
Is there another way to get the handle beside mine WindowFromPoint() call, wich means also minimizin all opened windows to get the handle?
Try this :
The handle of the Listview is returned in hListview
invoke GetDesktopWindow
invoke EnumChildWindows,eax,OFFSET EnumProc,OFFSET hListview
EnumProc FRAME hwnd,lParam
LOCAL ClassName[256] :B
invoke GetClassName,[hwnd],OFFSET ClassName,256
invoke lstrcmpi,OFFSET ClassName,"SysListView32"
or eax,eax
jnz >
mov ecx,[lParam]
mov eax,[hwnd]
mov [ecx],eax
mov eax,FALSE
ret
:
RET
ENDF
The handle of the Listview is returned in hListview
A quick scan with WinSpy yields this window hierarchy:
That's on Windows XP, I don't know about the other windows versions.
So the window you want is a few more levels deep than I had originally thought.
I just tried moving the icons around and it works. But for some reason LVM_GETITEMPOSITION fails to report the correct item positions, so I was unable to return the icons to their original positions. LVM_GETITEMPOSITION returns TRUE, but still it fails to fill in the POINT struct I send to it.
/shrug.
#32769 (Desktop window)
|
|____Progman (Program Manager)
|
|____SHELLDLL_DefView
|
|____SysListView32 (FolderView)
That's on Windows XP, I don't know about the other windows versions.
So the window you want is a few more levels deep than I had originally thought.
I just tried moving the icons around and it works. But for some reason LVM_GETITEMPOSITION fails to report the correct item positions, so I was unable to return the icons to their original positions. LVM_GETITEMPOSITION returns TRUE, but still it fails to fill in the POINT struct I send to it.
/shrug.
Hi Iblis
Working on the assumption that it is the lowest listview in the Z-Order no matter what, the proc I posted should acutally be like this, then it will find it reliably :
Working on the assumption that it is the lowest listview in the Z-Order no matter what, the proc I posted should acutally be like this, then it will find it reliably :
invoke GetDesktopWindow
invoke EnumChildWindows,eax,OFFSET EnumProc,OFFSET hListview
EnumProc FRAME hwnd,lParam
LOCAL ClassName[256] :B
invoke GetClassName,[hwnd],OFFSET ClassName,256
invoke lstrcmpi,OFFSET ClassName,"SysListView32"
or eax,eax
jnz >
mov ecx,[lParam]
mov eax,[hwnd]
mov [ecx],eax
:
[b]mov eax,TRUE[/b]
ret
ENDF
The way I did it was just:
Whatever works is fine I suppose. Finding the window is easy.
I'm still trying to figure out why the desktop list-view ignores the LVM_GETITEMPOSITION message. Or rather, it ignores the reference to the POINT structure. I know that it is acknowledging the reference because, just to test, I sent a NULL reference and received a FALSE return value, and then I tried an invalid address, and explorer crashes. So apparently it's doing something with that POINT reference, but whatever it's doing, it's not filling in the structure with the requested info.
So not being able to retrieve the position of the desktop items will make it more difficult to perpetuate the idea that chromos had, which was to make the icon dance around the screen out of the user's reach as the mouse moves over it.
invoke FindWindow, "progman", 0
invoke FindWindowEx, eax, 0, "SHELLDLL_DefView", 0
invoke FindWindowEx, eax, 0, "SysListView32", 0
mov hListView, eax
Whatever works is fine I suppose. Finding the window is easy.
I'm still trying to figure out why the desktop list-view ignores the LVM_GETITEMPOSITION message. Or rather, it ignores the reference to the POINT structure. I know that it is acknowledging the reference because, just to test, I sent a NULL reference and received a FALSE return value, and then I tried an invalid address, and explorer crashes. So apparently it's doing something with that POINT reference, but whatever it's doing, it's not filling in the structure with the requested info.
So not being able to retrieve the position of the desktop items will make it more difficult to perpetuate the idea that chromos had, which was to make the icon dance around the screen out of the user's reach as the mouse moves over it.
If I remember correctly, the only way to get this to work is to make a dll that gets injected into explorer.exe's address space. A Jeffrey Richter book I have at work explains how and why. I'll post more details when I bring it home.
Cool, Mercurius.
That would be great.
That would be great.
Mmmm,
I think you would just be required to create a memory buffer in the process of the desktop. This doesn't necessarily imply a DLL, I will try to experiment with VirtualAllocEx and create a buffer in the desktop process. Might be simpler and you could handle it inside the app.
I think you would just be required to create a memory buffer in the process of the desktop. This doesn't necessarily imply a DLL, I will try to experiment with VirtualAllocEx and create a buffer in the desktop process. Might be simpler and you could handle it inside the app.
This appears to work :
GetItemPos FRAME hlv,iItem,pPoint
LOCAL pMem :D
LOCAL PID :D
LOCAL hProcess :D
LOCAL cbWritten :D
invoke GetWindowThreadProcessId, [hlv], OFFSET PID
invoke OpenProcess, PROCESS_VM_OPERATION + \
PROCESS_VM_READ + PROCESS_VM_WRITE,NULL,[PID]
mov [hProcess], eax
invoke VirtualAllocEx, eax, NULL, 1024, MEM_COMMIT, PAGE_READWRITE
mov [pMem], eax
invoke SendMessage, [hlv], LVM_GETITEMPOSITION, [iItem], [pMem]
invoke ReadProcessMemory, [hProcess], [pMem], [pPoint], 8,OFFSET cbWritten
invoke VirtualFreeEx, [hProcess], [pMem], 1024, MEM_RELEASE
invoke CloseHandle, [hProcess]
RET
ENDF
A little more complex is to read and write to the desktop to get the LV_ITEM structure, you must also take into account the buffer that will be used to hold the text:
Called it with this:
GetRemoteItem FRAME hlv,pLVItem
uses ebx
LOCAL pMem :D
LOCAL PID :D
LOCAL hProcess :D
LOCAL cbWritten :D
invoke GetWindowThreadProcessId,[hlv],OFFSET PID
invoke OpenProcess,PROCESS_VM_OPERATION + \
PROCESS_VM_READ + PROCESS_VM_WRITE,NULL,[PID]
mov [hProcess],eax
invoke VirtualAllocEx, eax, NULL, 1024, MEM_COMMIT, PAGE_READWRITE
mov [pMem],eax
mov eax,[pMem]
add eax,256
mov ecx,[pLVItem]
mov ebx,[ecx+LV_ITEM.pszText]
mov [ecx+LV_ITEM.pszText],eax
invoke WriteProcessMemory, [hProcess], [pMem],\
[pLVItem], SIZEOF LV_ITEM, OFFSET cbWritten
invoke SendMessage,[hlv],LVM_GETITEM,0,[pMem]
invoke ReadProcessMemory, [hProcess], [pMem], \
[pLVItem], SIZEOF LV_ITEM, OFFSET cbWritten
mov eax,[pLVItem]
mov ecx,[eax+LV_ITEM.cchTextMax]
mov [eax+LV_ITEM.pszText],ebx
mov eax,[pMem]
add eax,256
invoke ReadProcessMemory, [hProcess], eax, ebx, ecx, OFFSET cbWritten
invoke VirtualFreeEx, [hProcess], [pMem], 1024, MEM_RELEASE
invoke CloseHandle, [hProcess]
RET
ENDF
Called it with this:
mov D[lvi.imask],LVIF_TEXT
mov D[lvi.pszText],OFFSET lvtext
mov D[lvi.cchTextMax],255
mov D[lvi.iItem],0
invoke GetRemoteItem,[hListView],OFFSET lvi
PrintString(lvtext)
Output was :
Line 50: lvtext = My Documents
wow cool that some people find dancing icon as interesting as i do :).
I'll try some of your ways.
I'll try some of your ways.
wow cool that some people find dancing icon as interesting as i do :).
I'll try some of your ways.
Well, more interested in the problem actually, I'm not quite clear on what the icons will do or why but it is an interesting coding problem given that it requires a little thinking to get the information you need.
Oh, I see. I had figured that since it was a systemwide control that interprocess issues wouldn't be a problem. I guess explorer subclasses it or something.
Good job Donkey. I wonder if the IShell interface has any means to do this? I haven't worked with it enough to know.
Good job Donkey. I wonder if the IShell interface has any means to do this? I haven't worked with it enough to know.
Hi iblis,
My first instinct was IShellView2, the SelectAndPositionItem method might be used for this if you can get an interface to the destop listview. Haven't tried it but I imagine it could be done.
My first instinct was IShellView2, the SelectAndPositionItem method might be used for this if you can get an interface to the destop listview. Haven't tried it but I imagine it could be done.
There was a rather disasterous memory leak in the code I posted, the VirtualFreeEx line should read:
invoke VirtualFreeEx,,,0,MEM_RELEASE
This is the final version :
invoke VirtualFreeEx,,,0,MEM_RELEASE
This is the final version :
GetItemPos FRAME hlv,iItem,pPoint
LOCAL pMem :D
LOCAL PID :D
LOCAL hProcess :D
LOCAL cbWritten :D
invoke GetWindowThreadProcessId,[hlv],OFFSET PID
invoke OpenProcess,PROCESS_VM_OPERATION + \
PROCESS_VM_READ + PROCESS_VM_WRITE,NULL,[PID]
mov [hProcess],eax
invoke VirtualAllocEx, eax, NULL, 8, MEM_COMMIT, PAGE_READWRITE
mov [pMem],eax
invoke SendMessage, [hlv], LVM_GETITEMPOSITION, [iItem], [pMem]
invoke ReadProcessMemory, [hProcess], [pMem], [pPoint], 8, OFFSET cbWritten
invoke VirtualFreeEx,[hProcess],[pMem],0,MEM_RELEASE
invoke CloseHandle,[hProcess]
RET
ENDF
GetRemoteItem FRAME hlv,pLVItem
uses ebx,edi,esi
LOCAL pMem :D
LOCAL PID :D
LOCAL hProcess :D
LOCAL cbWritten :D
invoke GetWindowThreadProcessId,[hlv],OFFSET PID
invoke OpenProcess,PROCESS_VM_OPERATION + \
PROCESS_VM_READ + PROCESS_VM_WRITE,NULL,[PID]
mov [hProcess],eax
mov edi,[pLVItem]
mov ecx,SIZEOF LV_ITEM
add ecx,[edi+LV_ITEM.cchTextMax]
inc ecx
invoke VirtualAllocEx, eax, NULL, ecx, MEM_COMMIT, PAGE_READWRITE
mov [pMem],eax
; Substitute the address of the local pszText buffer for the remote one
mov esi,eax
add esi,SIZEOF LV_ITEM
mov ebx,[edi+LV_ITEM.pszText]
mov [edi+LV_ITEM.pszText],esi
invoke WriteProcessMemory,[hProcess],[pMem],[pLVItem],\
SIZEOF LV_ITEM,OFFSET cbWritten
invoke SendMessage,[hlv],LVM_GETITEM,0,[pMem]
invoke ReadProcessMemory,[hProcess],[pMem],[pLVItem],\
SIZEOF LV_ITEM,OFFSET cbWritten
; reset the address of the pszText buffer
mov [edi+LV_ITEM.pszText],ebx
; copy the text from the remote buffer
invoke ReadProcessMemory,[hProcess],esi,ebx,\
[edi+LV_ITEM.cchTextMax],OFFSET cbWritten
invoke VirtualFreeEx,[hProcess],[pMem],0,MEM_RELEASE
invoke CloseHandle,[hProcess]
RET
ENDF
perhaps i should have said that i write in c, i understand also most of your code, but i dont understand, why i do not get the Handle via inline asm, how Iblis got it.
invoke FindWindow, "progman", 0
invoke FindWindowEx, eax, 0, "SHELLDLL_DefView", 0
invoke FindWindowEx, eax, 0, "SysListView32", 0
mov hListView, eax
PS: Of course I didn't use the masm Syntax in c.
Perhaps i was yesterday also only too tired, to get the code working. I'll have a look at it this evening.
invoke FindWindow, "progman", 0
invoke FindWindowEx, eax, 0, "SHELLDLL_DefView", 0
invoke FindWindowEx, eax, 0, "SysListView32", 0
mov hListView, eax
PS: Of course I didn't use the masm Syntax in c.
Perhaps i was yesterday also only too tired, to get the code working. I'll have a look at it this evening.
wow hm pretty amazing, the FindWindow calls return always 0 as handle, although they got the handle of "SysListView32".
According to the msdn Description of the return value, I quoute :
"If the function fails, the return value is NULL."
hm strange, and this took me 3 days to solve .... omg.
According to the msdn Description of the return value, I quoute :
"If the function fails, the return value is NULL."
hm strange, and this took me 3 days to solve .... omg.