桌面快捷方式的位置存储在哪里?
Where are positions of desktop shortcuts stored?
Windows 桌面快捷方式的位置存储在哪里?
我问的是图标的屏幕位置,而不是实际图标本身。我知道图标本身存储在各种 DLL、EXE 等中。这些位置显然存储在一些非易失性存储中,因为它们通过重新启动持续存在。
我的最终目标是编写一个应用程序来显示,并可选择在我的桌面上重新排列图标。
我知道这是可能的,因为许多可用的应用程序都可以这样做(例如,"WinTidy")。
我发现很多关于 "Windows Shell Bags" 的讨论。 http://williballethin.com.forensics/shellbags 中有一篇关于这些的有趣文章,但它只涉及 目录 而不是快捷方式。这些在不同地方的注册表中,包括
`HKEY_CURRENT_USER/Software/Microsoft/Windows/Shell/Bags/1/Desktop`
`HKEY_USERS/.DEFAULT/Software/Microsoft/Windows/Shell/Bags/1/Desktop`
我写了一个程序来提取这些,但是键值的格式无法理解。
有人知道它们存放在哪里以及如何存放吗?
20 年 6 月 3 日更新
++++++++++++++++++++++++++++++++++++++++
我刚换了一台Win10 64位的机器,发现下面的解决方法已经不行了。我相信是因为桌面内部结构发生了变化。我想出了如何做到这一点。请参阅此答案末尾的“WIN10 ADDENDUM”。
++++++++++++++++++++++++++++++++++++++++
我终于想出了如何做我想做的事(显示和重新排列桌面图标)。我最初的问题是关于定位、读取和写入存储图标信息的文件,但这是不是有用的方法。这是我学到的:
Explorer.exe 在覆盖整个桌面的巨大 ListView 中显示桌面项目,ListView 项目对应于每个可见图标。在启动时,Explorer 从一些神秘的文件中读取信息并填充 ListView。退出时,它会从 ListView 重新写入该文件。所以修改文件 没有 帮助,因为它会在退出时被覆盖。
操作桌面项的正确方法是直接操作ListView中的项。任何更改在更改时立即可见,并在退出时保存。要访问项目,我们可以使用几个 Windows 消息:LVM_GETITEM、LVM_GETITEMCOUNT、LVM_GETITEMPOSITION 和 LVM_SETITEMPOSITION。这些消息使用起来相当简单,但有一个复杂之处:有些需要指向参数结构的指针。这些结构必须在 Explorer 的 地址 space 而不是 我的应用程序的地址中,因此需要一些技巧。这是如何做的。我以LVM_GETITEMPOSITION为例,它需要一个指向POINT结构的指针。
在您的应用中声明一个 POINT 结构。
使用APIVirtualAllocEx()Explorer地址space分配一个镜像结构。
将 LVM_GETITEMPOSITION 发送到资源管理器,指定指向此结构的指针。
使用 APIReadProcessMemory() 将结果读回您的应用程序的 POINT。这个函数可以跨不同地址读取内存 spaces.
我已经对这些操作进行了原型设计,它们按我的意愿工作。我的代码很长,但我会在整理后立即post摘录。
2019 年 10 月 4 日更新 ----------------------------------
代码摘录
创建了一组常用的实用函数,使代码更加紧凑和可读。这些被命名为“exp*()”并包含在末尾。可以在 http://ramrodtechnology.com/explorer. Much of the basic technique herein was shamelessly stolen from https://www.codeproject.com/Articles/5570/Stealing-Program-s-Memory
找到参考
设置
// COMMONLY USED VARS
HANDLE hProcess; // explorer process handle
HWND hWndLV; // explorer main window
// SET UP CONVENIENCE VARS
hProcess = expGetProcessHandle(); // get explorer process handle
if( !hProcess ) exit( 1 );
hWndLV = expGetListView(); // get main ListView of Desktop
if( !hWndLV ) exit( 1 );
打印所有项目名称的函数
//@ Process a list view window and print item names
int
printAllNames()
{
int ok,icount,indx;
LVITEM item; // point in app space
LVITEM *_pitem; // point in exp space
char text[512];
char *_ptext;
int nr,nwrite; // count of bytes read/written
printf( "\n" );
// ALLOC ITEMS IN EXP SPACE
_pitem = expAlloc( sizeof(LVITEM) );
_ptext = expAlloc( sizeof(text ) );
printf( " NAME\n" );
printf( " ==================================\n" );
icount = expGetItemCount();
for( indx=0; indx<icount; indx++ ) { // for each item in LV
// SETUP ITEM IN EXP SPACE
memset( &item, 0, sizeof(LVITEM) ); // preclear
item.iItem = indx; // index of item to read
item.iSubItem = 0; // sub index (always 0)
item.mask = LVIF_TEXT; // component to read
item.pszText = _ptext; // buffer to recv text
item.cchTextMax = sizeof(text); // size of buffer
// WRITE ITEM REQ TO EXP SPACE
ok = WriteProcessMemory( hProcess, _pitem, &item, sizeof(LVITEM), &nwrite );
// SEND MESSAGE TO GET ITEM INTO EXP SPACE
ok = SendMessage( hWndLV, LVM_GETITEM, indx, (LPARAM)_pitem );
// READ EXP TEXT INTO APP SPACE
memset( &item, 0, sizeof(LVITEM) );
ok = ReadProcessMemory( hProcess, _pitem, &item, sizeof(POINT), &nr );
ok = ReadProcessMemory( hProcess, _ptext, &text, sizeof(text), &nr );
// PRINT RESULT
printf( " %s\n", text );
}
ok = expFree( _pitem );
ok = expFree( _ptext );
return( TRUE );
//r Returns TRUE on success, FALSE on error
}
打印所有项目位置的函数
//@ Process a list view window and print position
int
printAllPositions()
{
int ok,icount,indx,nr;
POINT pt; // point in app space
POINT *_ppt; // point in exp space
icount = expGetItemCount();
_ppt = expAlloc( sizeof(POINT) );
if( !_ppt ) return( FALSE );
printf( " X Y\n" );
printf( "---- ----\n" );
for( indx=0; indx<icount; indx++ ) { // for each item in LV
ok = SendMessage( hWndLV, LVM_GETITEMPOSITION, indx, (LPARAM)_ppt );
ok = ReadProcessMemory( hProcess, _ppt, &pt, sizeof(POINT), &nr );
printf( "%4d %4d\n", pt.x, pt.y );
}
ok = expFree( _ppt );
return( TRUE );
//r Returns TRUE on success
}
移动项目的功能
请参阅下面的 'expSetItemPosition'。 19 年 10 月 6 日更新
Explorer 实用函数
// EXPLORER UTILITY FUNCTIONS
//@ Allocate a block of memory in explorer space
void *
expAlloc(
int size) // size of block
{
void *p;
p = VirtualAllocEx(
hProcess,
NULL,
size,
MEM_COMMIT,
PAGE_READWRITE );
return( p );
//r Returns addr of memory in EXPLORER space or NULL on error
}
//@ Free virtual memory in EXPLORER space
int
expFree(
void *p) // pointer to free
{
int ok;
ok = VirtualFreeEx( hProcess, p, 0, MEM_RELEASE );
return( ok );
//r Returns TRUE on success, else FALSE
}
static int aBiggest; // biggest area so far
static HWND hWndBiggest; // hWnd with biggest area
//@ Find main list view of explorer
HWND
expGetListView()
{
//n Approach: Enumerate all child windows of desktop and find largest.
//n This will be the main explorer window.
HWND hWndDesktop;
hWndDesktop = GetDesktopWindow();
if( !hWndDesktop ) return( NULL );
aBiggest = -1; // init
hWndBiggest = NULL; // init
EnumChildWindows( hWndDesktop, CallbackDesktopChild, 0 );
return( hWndBiggest );
//r Returns hWnd of largest explorer list view
}
//@ Callback for EnumChildWindows
BOOL CALLBACK CallbackDesktopChild(
HWND hWnd,
LPARAM dwUser)
{
//n Get size of child. If biggest, save hWnd.
int i,w,h,a;
char classname[MAXPATH+1];
RECT rect;
i = GetClassName( hWnd, classname, MAXPATH ); // get class
if( stricmp( classname, "SysListView32" ) ) { // not a list view?
return( TRUE ); // skip it
}
// CALC SIZE
i = GetWindowRect( hWnd, &rect );
w = rect.right - rect.left;
h = rect.bottom - rect.top;
// CHECK IF BIGGEST
a = w * h;
if( a > aBiggest ) { // is biggest?
aBiggest = a;
hWndBiggest = hWnd;
}
return( TRUE ); // TRUE to continue enumeration
}
//@ Get process handle of explorer.exe
HANDLE
expGetProcessHandle()
{
//n Approach: take process snapshot and loop through to find "explorer.exe"
//n Needs tlhelp32.h and comctl32.lib
int i,stat;
PROCESSENTRY32 pe;
HANDLE hSnapshot;
char *name;
HANDLE h;
// TAKE A SNAPSHOT
hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( !hSnapshot ) return( NULL );
// LOOP THROUGH PROCESSES AND FIND "explorer.exe"
for( i=0;;i++ ) {
pe.dwSize = sizeof( PROCESSENTRY32 );
if( i == 0 ) stat = Process32First( hSnapshot, &pe );
else stat = Process32Next ( hSnapshot, &pe );
if( !stat ) break; // done or error?
name = pe.szExeFile;
if( !stricmp( name, "explorer.exe" ) ) { // matches?
h = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID );
return( h );
}
}
return( NULL );
//r Returns explorer process handle or NULL on error
}
//@ Get count of items in explorer list view
int
expGetItemCount()
{
int count;
count = SendMessage( hWndLV, LVM_GETITEMCOUNT, 0, 0 );
return( count );
//r Returns count of item
}
//@ Get position of list view icon by index
int
expGetItemPosition(
int indx, // index of item
int *x, // ptr to int to recv x
int *y) // ptr to int to recv y
{
int i,ok,icount;
char classname[MAXPATH+1];
POINT pt; // point in app space
POINT *_ppt; // point in exp space
int nr; // count of bytes read
//int w,h;
i = GetClassName( hWndLV, classname, MAXPATH );
// GET COUNT OF ITEMS IN LIST VIEW
icount = expGetItemCount();
if( indx < 0 || indx >= icount ) return( FALSE );
// ALLOC POINT IN EXP SPACE
_ppt = expAlloc( sizeof(POINT) );
if( !_ppt ) return( FALSE );
// SEND MESSAGE TO GET POS INTO EXP SPACE POINT
ok = SendMessage( hWndLV, LVM_GETITEMPOSITION, indx, (LPARAM)_ppt );
if( !ok ) return( FALSE );
// READ EXP SPACE POINT INTO APP SPACE POINT
ok = ReadProcessMemory( hProcess, _ppt, &pt, sizeof(POINT), &nr );
if( !ok ) return( FALSE );
ok = expFree( _ppt );
if( !ok ) return( FALSE );
if( x ) *x = pt.x;
if( y ) *y = pt.y;
//r Returns TRUE on success
return( TRUE );
}
//@ Move item
int
expSetItemPosition(
char *name, // icon name
int x, // new x coord
int y) // new y coord
{
int ok,indx;
LPARAM lParam;
indx = expGetItemIndex( name );
if( indx < 0 ) return( FALSE );
lParam = MAKELPARAM( x, y );
ok = SendMessage( hWndLV, LVM_SETITEMPOSITION, indx, lParam );
if( !ok ) return( FALSE );
return( TRUE );
//r Returns TRUE on success
}
WIN10 附录
20 年 6 月 19 日
++++++++++++++++++++++++++++++++++++
在Win10下,解决方法就复杂多了。您必须使用各种 COM 对象和接口,例如IShellWindows,等等(上帝,我讨厌 COM)。我没有创建库,而是在下面提供了一个完整的工作程序。我使用 MSVC 2019 编译了它。为清楚起见,省略了错误检查(但你应该这样做)。
// icons.cpp - Display (and optionally move) desktop icons
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <ShlObj.h>
#include <atlbase.h>
int
main(int argc,char** argv)
{
CComPtr<IShellWindows> spShellWindows;
CComPtr<IShellBrowser> spBrowser;
CComPtr<IDispatch> spDispatch;
CComPtr<IShellView> spShellView;
CComPtr<IFolderView> spView;
CComPtr<IShellFolder> spFolder;
CComPtr<IEnumIDList> spEnum;
CComHeapPtr<ITEMID_CHILD> spidl;
CComVariant vtLoc(CLSID_ShellWindows);
CComVariant vtEmpty;
STRRET str;
int count=0;
HRESULT hr;
long lhWnd;
// INITIALIZE COM
CoInitialize(NULL);
// GET ShellWindows INTERFACE
hr = spShellWindows.CoCreateInstance(CLSID_ShellWindows);
// FIND WINDOW
hr = spShellWindows->FindWindowSW(
&vtLoc, &vtEmpty, SWC_DESKTOP, &lhWnd, SWFO_NEEDDISPATCH, &spDispatch);
// GET DISPATCH INTERFACE
CComQIPtr<IServiceProvider>(spDispatch)->
QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&spBrowser));
spBrowser->QueryActiveShellView(&spShellView);
spShellView->QueryInterface(IID_PPV_ARGS(&spView) );
hr = spView->GetFolder(IID_PPV_ARGS(&spFolder));
// GET ENUMERATOR
spView->Items(SVGIO_ALLVIEW, IID_PPV_ARGS(&spEnum)); // get enumerator
// ENUMERATE ALL DESKTOP ITEMS
for (; spEnum->Next(1, &spidl, nullptr) == S_OK; spidl.Free()) {
// GET/PRINT ICON NAME AND POSITION
char* name;
POINT pt;
spFolder->GetDisplayNameOf(spidl, SHGDN_NORMAL, &str);
StrRetToStr(&str, spidl, &name);
spView->GetItemPosition(spidl, &pt);
printf("%5d %5d \"%s\"\n", pt.x, pt.y, name);
#define MOVE_ICON
#ifdef MOVE_ICON
// OPTIONAL: MOVE *SINGLE* SELECTED ITEM
{
if( !_stricmp(name, "ICON_NAME_TO_MOVE") ) {
PCITEMID_CHILD apidl[1] = { spidl };
int numitems = 1;
// SET pt TO NEW POSITION HERE
hr = spView->SelectAndPositionItems(numitems, apidl, &pt, 0);
}
}
#endif
count++;
}
CoUninitialize(); // release COM
fprintf(stderr, "enumerated %d desktop icons\n", count);
fprintf(stderr, "Press any key to exit...\n");
_getch();
exit(0 );
}
Windows 桌面快捷方式的位置存储在哪里?
我问的是图标的屏幕位置,而不是实际图标本身。我知道图标本身存储在各种 DLL、EXE 等中。这些位置显然存储在一些非易失性存储中,因为它们通过重新启动持续存在。
我的最终目标是编写一个应用程序来显示,并可选择在我的桌面上重新排列图标。
我知道这是可能的,因为许多可用的应用程序都可以这样做(例如,"WinTidy")。
我发现很多关于 "Windows Shell Bags" 的讨论。 http://williballethin.com.forensics/shellbags 中有一篇关于这些的有趣文章,但它只涉及 目录 而不是快捷方式。这些在不同地方的注册表中,包括
`HKEY_CURRENT_USER/Software/Microsoft/Windows/Shell/Bags/1/Desktop`
`HKEY_USERS/.DEFAULT/Software/Microsoft/Windows/Shell/Bags/1/Desktop`
我写了一个程序来提取这些,但是键值的格式无法理解。
有人知道它们存放在哪里以及如何存放吗?
20 年 6 月 3 日更新
++++++++++++++++++++++++++++++++++++++++
我刚换了一台Win10 64位的机器,发现下面的解决方法已经不行了。我相信是因为桌面内部结构发生了变化。我想出了如何做到这一点。请参阅此答案末尾的“WIN10 ADDENDUM”。
++++++++++++++++++++++++++++++++++++++++
我终于想出了如何做我想做的事(显示和重新排列桌面图标)。我最初的问题是关于定位、读取和写入存储图标信息的文件,但这是不是有用的方法。这是我学到的:
Explorer.exe 在覆盖整个桌面的巨大 ListView 中显示桌面项目,ListView 项目对应于每个可见图标。在启动时,Explorer 从一些神秘的文件中读取信息并填充 ListView。退出时,它会从 ListView 重新写入该文件。所以修改文件 没有 帮助,因为它会在退出时被覆盖。
操作桌面项的正确方法是直接操作ListView中的项。任何更改在更改时立即可见,并在退出时保存。要访问项目,我们可以使用几个 Windows 消息:LVM_GETITEM、LVM_GETITEMCOUNT、LVM_GETITEMPOSITION 和 LVM_SETITEMPOSITION。这些消息使用起来相当简单,但有一个复杂之处:有些需要指向参数结构的指针。这些结构必须在 Explorer 的 地址 space 而不是 我的应用程序的地址中,因此需要一些技巧。这是如何做的。我以LVM_GETITEMPOSITION为例,它需要一个指向POINT结构的指针。
在您的应用中声明一个 POINT 结构。
使用APIVirtualAllocEx()Explorer地址space分配一个镜像结构。
将 LVM_GETITEMPOSITION 发送到资源管理器,指定指向此结构的指针。
使用 APIReadProcessMemory() 将结果读回您的应用程序的 POINT。这个函数可以跨不同地址读取内存 spaces.
我已经对这些操作进行了原型设计,它们按我的意愿工作。我的代码很长,但我会在整理后立即post摘录。
2019 年 10 月 4 日更新 ----------------------------------
代码摘录
创建了一组常用的实用函数,使代码更加紧凑和可读。这些被命名为“exp*()”并包含在末尾。可以在 http://ramrodtechnology.com/explorer. Much of the basic technique herein was shamelessly stolen from https://www.codeproject.com/Articles/5570/Stealing-Program-s-Memory
找到参考设置
// COMMONLY USED VARS
HANDLE hProcess; // explorer process handle
HWND hWndLV; // explorer main window
// SET UP CONVENIENCE VARS
hProcess = expGetProcessHandle(); // get explorer process handle
if( !hProcess ) exit( 1 );
hWndLV = expGetListView(); // get main ListView of Desktop
if( !hWndLV ) exit( 1 );
打印所有项目名称的函数
//@ Process a list view window and print item names
int
printAllNames()
{
int ok,icount,indx;
LVITEM item; // point in app space
LVITEM *_pitem; // point in exp space
char text[512];
char *_ptext;
int nr,nwrite; // count of bytes read/written
printf( "\n" );
// ALLOC ITEMS IN EXP SPACE
_pitem = expAlloc( sizeof(LVITEM) );
_ptext = expAlloc( sizeof(text ) );
printf( " NAME\n" );
printf( " ==================================\n" );
icount = expGetItemCount();
for( indx=0; indx<icount; indx++ ) { // for each item in LV
// SETUP ITEM IN EXP SPACE
memset( &item, 0, sizeof(LVITEM) ); // preclear
item.iItem = indx; // index of item to read
item.iSubItem = 0; // sub index (always 0)
item.mask = LVIF_TEXT; // component to read
item.pszText = _ptext; // buffer to recv text
item.cchTextMax = sizeof(text); // size of buffer
// WRITE ITEM REQ TO EXP SPACE
ok = WriteProcessMemory( hProcess, _pitem, &item, sizeof(LVITEM), &nwrite );
// SEND MESSAGE TO GET ITEM INTO EXP SPACE
ok = SendMessage( hWndLV, LVM_GETITEM, indx, (LPARAM)_pitem );
// READ EXP TEXT INTO APP SPACE
memset( &item, 0, sizeof(LVITEM) );
ok = ReadProcessMemory( hProcess, _pitem, &item, sizeof(POINT), &nr );
ok = ReadProcessMemory( hProcess, _ptext, &text, sizeof(text), &nr );
// PRINT RESULT
printf( " %s\n", text );
}
ok = expFree( _pitem );
ok = expFree( _ptext );
return( TRUE );
//r Returns TRUE on success, FALSE on error
}
打印所有项目位置的函数
//@ Process a list view window and print position
int
printAllPositions()
{
int ok,icount,indx,nr;
POINT pt; // point in app space
POINT *_ppt; // point in exp space
icount = expGetItemCount();
_ppt = expAlloc( sizeof(POINT) );
if( !_ppt ) return( FALSE );
printf( " X Y\n" );
printf( "---- ----\n" );
for( indx=0; indx<icount; indx++ ) { // for each item in LV
ok = SendMessage( hWndLV, LVM_GETITEMPOSITION, indx, (LPARAM)_ppt );
ok = ReadProcessMemory( hProcess, _ppt, &pt, sizeof(POINT), &nr );
printf( "%4d %4d\n", pt.x, pt.y );
}
ok = expFree( _ppt );
return( TRUE );
//r Returns TRUE on success
}
移动项目的功能
请参阅下面的 'expSetItemPosition'。 19 年 10 月 6 日更新
Explorer 实用函数
// EXPLORER UTILITY FUNCTIONS
//@ Allocate a block of memory in explorer space
void *
expAlloc(
int size) // size of block
{
void *p;
p = VirtualAllocEx(
hProcess,
NULL,
size,
MEM_COMMIT,
PAGE_READWRITE );
return( p );
//r Returns addr of memory in EXPLORER space or NULL on error
}
//@ Free virtual memory in EXPLORER space
int
expFree(
void *p) // pointer to free
{
int ok;
ok = VirtualFreeEx( hProcess, p, 0, MEM_RELEASE );
return( ok );
//r Returns TRUE on success, else FALSE
}
static int aBiggest; // biggest area so far
static HWND hWndBiggest; // hWnd with biggest area
//@ Find main list view of explorer
HWND
expGetListView()
{
//n Approach: Enumerate all child windows of desktop and find largest.
//n This will be the main explorer window.
HWND hWndDesktop;
hWndDesktop = GetDesktopWindow();
if( !hWndDesktop ) return( NULL );
aBiggest = -1; // init
hWndBiggest = NULL; // init
EnumChildWindows( hWndDesktop, CallbackDesktopChild, 0 );
return( hWndBiggest );
//r Returns hWnd of largest explorer list view
}
//@ Callback for EnumChildWindows
BOOL CALLBACK CallbackDesktopChild(
HWND hWnd,
LPARAM dwUser)
{
//n Get size of child. If biggest, save hWnd.
int i,w,h,a;
char classname[MAXPATH+1];
RECT rect;
i = GetClassName( hWnd, classname, MAXPATH ); // get class
if( stricmp( classname, "SysListView32" ) ) { // not a list view?
return( TRUE ); // skip it
}
// CALC SIZE
i = GetWindowRect( hWnd, &rect );
w = rect.right - rect.left;
h = rect.bottom - rect.top;
// CHECK IF BIGGEST
a = w * h;
if( a > aBiggest ) { // is biggest?
aBiggest = a;
hWndBiggest = hWnd;
}
return( TRUE ); // TRUE to continue enumeration
}
//@ Get process handle of explorer.exe
HANDLE
expGetProcessHandle()
{
//n Approach: take process snapshot and loop through to find "explorer.exe"
//n Needs tlhelp32.h and comctl32.lib
int i,stat;
PROCESSENTRY32 pe;
HANDLE hSnapshot;
char *name;
HANDLE h;
// TAKE A SNAPSHOT
hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( !hSnapshot ) return( NULL );
// LOOP THROUGH PROCESSES AND FIND "explorer.exe"
for( i=0;;i++ ) {
pe.dwSize = sizeof( PROCESSENTRY32 );
if( i == 0 ) stat = Process32First( hSnapshot, &pe );
else stat = Process32Next ( hSnapshot, &pe );
if( !stat ) break; // done or error?
name = pe.szExeFile;
if( !stricmp( name, "explorer.exe" ) ) { // matches?
h = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID );
return( h );
}
}
return( NULL );
//r Returns explorer process handle or NULL on error
}
//@ Get count of items in explorer list view
int
expGetItemCount()
{
int count;
count = SendMessage( hWndLV, LVM_GETITEMCOUNT, 0, 0 );
return( count );
//r Returns count of item
}
//@ Get position of list view icon by index
int
expGetItemPosition(
int indx, // index of item
int *x, // ptr to int to recv x
int *y) // ptr to int to recv y
{
int i,ok,icount;
char classname[MAXPATH+1];
POINT pt; // point in app space
POINT *_ppt; // point in exp space
int nr; // count of bytes read
//int w,h;
i = GetClassName( hWndLV, classname, MAXPATH );
// GET COUNT OF ITEMS IN LIST VIEW
icount = expGetItemCount();
if( indx < 0 || indx >= icount ) return( FALSE );
// ALLOC POINT IN EXP SPACE
_ppt = expAlloc( sizeof(POINT) );
if( !_ppt ) return( FALSE );
// SEND MESSAGE TO GET POS INTO EXP SPACE POINT
ok = SendMessage( hWndLV, LVM_GETITEMPOSITION, indx, (LPARAM)_ppt );
if( !ok ) return( FALSE );
// READ EXP SPACE POINT INTO APP SPACE POINT
ok = ReadProcessMemory( hProcess, _ppt, &pt, sizeof(POINT), &nr );
if( !ok ) return( FALSE );
ok = expFree( _ppt );
if( !ok ) return( FALSE );
if( x ) *x = pt.x;
if( y ) *y = pt.y;
//r Returns TRUE on success
return( TRUE );
}
//@ Move item
int
expSetItemPosition(
char *name, // icon name
int x, // new x coord
int y) // new y coord
{
int ok,indx;
LPARAM lParam;
indx = expGetItemIndex( name );
if( indx < 0 ) return( FALSE );
lParam = MAKELPARAM( x, y );
ok = SendMessage( hWndLV, LVM_SETITEMPOSITION, indx, lParam );
if( !ok ) return( FALSE );
return( TRUE );
//r Returns TRUE on success
}
WIN10 附录
20 年 6 月 19 日
++++++++++++++++++++++++++++++++++++
在Win10下,解决方法就复杂多了。您必须使用各种 COM 对象和接口,例如IShellWindows,等等(上帝,我讨厌 COM)。我没有创建库,而是在下面提供了一个完整的工作程序。我使用 MSVC 2019 编译了它。为清楚起见,省略了错误检查(但你应该这样做)。
// icons.cpp - Display (and optionally move) desktop icons
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <ShlObj.h>
#include <atlbase.h>
int
main(int argc,char** argv)
{
CComPtr<IShellWindows> spShellWindows;
CComPtr<IShellBrowser> spBrowser;
CComPtr<IDispatch> spDispatch;
CComPtr<IShellView> spShellView;
CComPtr<IFolderView> spView;
CComPtr<IShellFolder> spFolder;
CComPtr<IEnumIDList> spEnum;
CComHeapPtr<ITEMID_CHILD> spidl;
CComVariant vtLoc(CLSID_ShellWindows);
CComVariant vtEmpty;
STRRET str;
int count=0;
HRESULT hr;
long lhWnd;
// INITIALIZE COM
CoInitialize(NULL);
// GET ShellWindows INTERFACE
hr = spShellWindows.CoCreateInstance(CLSID_ShellWindows);
// FIND WINDOW
hr = spShellWindows->FindWindowSW(
&vtLoc, &vtEmpty, SWC_DESKTOP, &lhWnd, SWFO_NEEDDISPATCH, &spDispatch);
// GET DISPATCH INTERFACE
CComQIPtr<IServiceProvider>(spDispatch)->
QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&spBrowser));
spBrowser->QueryActiveShellView(&spShellView);
spShellView->QueryInterface(IID_PPV_ARGS(&spView) );
hr = spView->GetFolder(IID_PPV_ARGS(&spFolder));
// GET ENUMERATOR
spView->Items(SVGIO_ALLVIEW, IID_PPV_ARGS(&spEnum)); // get enumerator
// ENUMERATE ALL DESKTOP ITEMS
for (; spEnum->Next(1, &spidl, nullptr) == S_OK; spidl.Free()) {
// GET/PRINT ICON NAME AND POSITION
char* name;
POINT pt;
spFolder->GetDisplayNameOf(spidl, SHGDN_NORMAL, &str);
StrRetToStr(&str, spidl, &name);
spView->GetItemPosition(spidl, &pt);
printf("%5d %5d \"%s\"\n", pt.x, pt.y, name);
#define MOVE_ICON
#ifdef MOVE_ICON
// OPTIONAL: MOVE *SINGLE* SELECTED ITEM
{
if( !_stricmp(name, "ICON_NAME_TO_MOVE") ) {
PCITEMID_CHILD apidl[1] = { spidl };
int numitems = 1;
// SET pt TO NEW POSITION HERE
hr = spView->SelectAndPositionItems(numitems, apidl, &pt, 0);
}
}
#endif
count++;
}
CoUninitialize(); // release COM
fprintf(stderr, "enumerated %d desktop icons\n", count);
fprintf(stderr, "Press any key to exit...\n");
_getch();
exit(0 );
}