桌面快捷方式的位置存储在哪里? [英] Where are positions of desktop shortcuts stored?

查看:498
本文介绍了桌面快捷方式的位置存储在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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`

我编写了一个程序来提取这些值,但是键值的格式却令人费解。



任何机构都知道它们的存储位置和方式吗?

解决方案

更新6/3/20

+++++++++++++++++++++++++++++ +++++++++
我刚刚切换到Win10 64位计算机上,发现下面的解决方案不再起作用。我相信是由于台式机内部的变化。我想出了怎么做。参见 WIN10 ADDENDUM。在此答案的结尾。

+++++++++++++++++++++++++++++++++++ +++


我终于弄清楚了该怎么做(显示并重新排列桌面图标)。我最初的问题是查找,读取和写入存储图标信息的文件,但这不是一种有用的方法。这是我学到的东西。启动时,资源管理器从一些奥秘文件中读取信息,并填充ListView。退出时,它将从ListView重写该文件。因此修改文件不会有帮助,因为退出时会被覆盖。


操纵桌面项目的正确方法是直接操纵ListView中的项目。任何更改在更改后立即可见,并在退出时保存。要访问这些项目,我们可以使用几种Windows消息:LVM_GETITEM,LVM_GETITEMCOUNT,LVM_GETITEMPOSITION和LVM_SETITEMPOSITION。这些消息使用起来很复杂,但很复杂:有些消息需要指向参数结构的指针。这些结构必须位于我的应用程序的资源管理器的地址空间不是中,因此需要一些技巧。这样做的方法。我以LVM_GETITEMPOSITION为例,它需要一个指向POINT结构的指针。



  • 在您的应用程序中声明一个POINT结构。



  • 使用API​​ VirtualAllocEx()在资源管理器的地址空间中分配镜像结构。



  • 将LVM_GETITEMPOSITION发送到资源管理器,以指定指向该结构的指针。



  • 将结果读回应用程序的使用API​​ ReadProcessMemory()进行POINT。该函数可以读取不同地址空间中的内存。




我已经对这些操作进行了原型设计,并且可以按需要工作。我的代码很长,但我会在清理后立即发布摘录。


UPDATE 10/4/2019 --------------- ---------------------


代码例外


创建了一组常用的实用程序功能,以使代码更紧凑和更易读。这些被命名为 exp *()。并包含在最后。可以在 http://ramrodtechnology.com/explorer 中找到参考。本文中的许多基本技术都是从 https:// www。 codeproject.com/Articles/5570/Stealing-Program-s-Memory


设置

  //常用变量
处理hProcess; //资源管理器进程
HWND hWndLV; //浏览器主窗口

//设置便捷变量
hProcess = expGetProcessHandle(); //获取资源管理器进程句柄
if(!hProcess)exit(1);
hWndLV = expGetListView(); //获取桌面
的主ListView if(!hWndLV)exit(1);

用于打印所有项目名称的功能

  // @处理列表视图窗口并打印项目名称
int
printAllNames()
{
int ok,icount,indx;
LVITEM项; //指向应用程序空间
LVITEM * _pitem; //指向exp空间
char text [512];
char * _ptext;
int nr,nwrite; //读取/写入的字节数

printf( \n);

// EXP空间中的ALLOC项目
_pitem = expAlloc(sizeof(LVITEM));
_ptext = expAlloc(sizeof(text));


printf( NAME\n);
printf(" =============================== n
icount = expGetItemCount();
for(indx = 0; indx< icount; indx ++){//对于LV

//在EXP空间中设置项目
memset(& item,0 ,sizeof(LVITEM)); //预先清除
item.iItem = indx; //要读取的项目的索引
item.iSubItem = 0; //子索引(始终为0)
item.mask = LVIF_TEXT; //读取
item.pszText = _ptext;的组件//缓冲以接收文本
item.cchTextMax = sizeof(text); //缓冲区的大小

//写入项目请求以扩展空间
ok = WriteProcessMemory(hProcess,_pitem,& item,sizeof(LVITEM),& nwrite);

//发送消息以将项目放入EXP空间
ok = SendMessage(hWndLV,LVM_GETITEM,indx,(LPARAM)_pitem);

//将EXP文本读入应用程序空间
memset(& item,0,sizeof(LVITEM));
ok = ReadProcessMemory(hProcess,_pitem,& item,sizeof(POINT),& nr);
ok = ReadProcessMemory(hProcess,_ptext,& text,sizeof(text),& nr);

//打印结果
printf(%s\n,text);
}
ok = expFree(_pitem);
ok = expFree(_ptext);

return(TRUE);
// r成功返回TRUE,错误返回FALSE
}

函数为打印所有项目位置

  // @处理列表视图窗口并打印位置
int
printAllPositions( )
{
int ok,icount,indx,nr;
分pt; //指向应用程序空间
POINT * _ppt; //指向exp空间

icount = expGetItemCount();

_ppt = expAlloc(sizeof(POINT));
if(!_ppt)return(FALSE);

printf( X Y\n);
printf( ---- ---- \n);
for(indx = 0; indx< icount; indx ++){//对于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成功返回TRUE
}

移动项目的功能

请参见下面的 expSetItemPosition。 19/10/6更新


资源管理器实用程序功能

  // EXPLORER实用函数

// @在资源管理器空间中分配一个内存块
void *
expAlloc(
int size)//块
{
无效* p;

p = VirtualAllocEx(
hProcess,
NULL,
size,
MEM_COMMIT,
PAGE_READWRITE);
return(p);
// r返回EXPLORER空间中的内存addr,或者在错误
时返回NULL}

// @ EXPLORER空间中的可用虚拟内存
int
expFree (
void * p)//指向免费
的指针{
int ok;
ok = VirtualFreeEx(hProcess,p,0,MEM_RELEASE);
return(ok);
// r成功返回TRUE,否则返回FALSE
}

static int aBiggest; //迄今为止最大的区域
静态HWND hWndBiggest; // hWnd具有最大面积

// @查找资源管理器的主列表
HWND
expGetListView()
{
// n方法:枚举桌面的所有子窗口并找到最大的子窗口。
// n这将是资源管理器的主窗口。

HWND hWndDesktop;
hWndDesktop = GetDesktopWindow();
if(!hWndDesktop)return(NULL);

aBiggest = -1; //初始化
hWndBiggest = NULL; //初始化
EnumChildWindows(hWndDesktop,CallbackDesktopChild,0);

return(hWndBiggest);
// r返回最大资源管理器列表视图的hWnd
}

// @ EnumChildWindows的回调
BOOL CALLBACK CallbackDesktopChild(
HWND hWnd,
LPARAM dwUser)
{
// n获取孩子的大小。如果最大,请保存hWnd。

int i,w,h,a;
char classname [MAXPATH + 1];
RECT rect;

i = GetClassName(hWnd,classname,MAXPATH); //获得类
if(stricmp(classname, SysListView32)){//不是列表视图?
return(TRUE); //跳过
}

//计算尺寸
i = GetWindowRect(hWnd,& rect);
w = rect.right-rect.left;
h =矩形底部-矩形顶部;

//检查是否最大
a = w * h;
if(a> aBiggest){//最大吗?
aBiggest = a;
hWndBiggest = hWnd;
}

return(TRUE); //为继续枚举而设置为TRUE
}


// @获取explorer.exe的进程句柄
处理
expGetProcessHandle()
{
// n方法:获取进程快照并循环遍历以找到 explorer.exe。
// n需要tlhelp32.h和comctl32.lib

int i,stat;
PROCESSENTRY32 pe;
处理hSnapshot;
char * name;
处理h;

//拍摄快照
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(!hSnapshot)return(NULL);

//通过过程循环并查找 explorer.exe;
for(i = 0 ;; i ++){
pe.dwSize = sizeof(PROCESSENTRY32);
if(i == 0)stat = Process32First(hSnapshot,& pe);
else stat = Process32Next(hSnapshot,& pe);
if(!stat)中断; //完成还是出错?
名称= pe.szExeFile;
if(!stricmp(name, explorer.exe)){//是否匹配?
h = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pe.th32ProcessID);
return(h);
}
}

return(NULL);
// r返回资源管理器进程句柄或错误时为NULL
}

// @在资源管理器列表视图中获取项目计数
int
expGetItemCount( )
{int count
;

count = SendMessage(hWndLV,LVM_GETITEMCOUNT,0,0);
return(count);
// r返回项目计数
}

// @通过索引
int
expGetItemPosition(
获取列表视图图标的位置int indx,//项目索引
int * x,//将ptr转换为要接收的int x
int * y)//将ptr转换为要接收的int y
{
int我,我,我
char classname [MAXPATH + 1];
分pt; //指向应用程序空间
POINT * _ppt; //指向exp空间
int nr; //读取的字节数
// int w,h;

i = GetClassName(hWndLV,classname,MAXPATH);

//在列表视图中获取项目数
icount = expGetItemCount();
if(indx< 0 || indx> = icount)return(FALSE);

//展示空间中的ALLOC点
_ppt = expAlloc(sizeof(POINT));
if(!_ppt)return(FALSE);

//发送消息以使POS进入EXP空间点
ok = SendMessage(hWndLV,LVM_GETITEMPOSITION,indx,(LPARAM)_ppt);
if(!ok)return(FALSE);

//将EXP的空间点读入应用程序的空间点
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成功返回TRUE
return(TRUE);
}

// @移动项目
int
expSetItemPosition(
char * 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成功返回TRUE
}

WIN10附加值
20/6/19

++++++++++++++++++++++++++++++++++++


在Win10中,解决方案要复杂得多。您必须使用各种COM对象和接口,例如IShellWindows等。(上帝,我讨厌COM)。我没有创建一个库,而是在下面提供了一个完整的工作程序。我使用MSVC 2019进行了编译。为了清楚起见,省略了错误检查(但您应该这样做)。

  // icons.cpp-Display(并有选择地移动)桌面图标

#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计数= 0;
HRESULT小时;
长lhWnd;

//初始化COM
CoInitialize(NULL);

//获取ShellWindows接口
hr = spShellWindows.CoCreateInstance(CLSID_ShellWindows);

//查找窗口
hr = spShellWindows-> FindWindowSW(
& vtLoc,& vtEmpty,SWC_DESKTOP,& lhWnd,SWFO_NEEDDISPATCH,& spDispatch);

//获取调度界面
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));

//获取枚举器
spView-> Items(SVGIO_ALLVIEW,IID_PPV_ARGS(& spEnum)); //获取枚举

//枚举所有桌面项
for(; spEnum-> Next(1,& spidl,nullptr)== S_OK; spidl.Free()){
//获取/打印图标名称和位置
char *名称;
分pt;
spFolder-> GetDisplayNameOf(spidl,SHGDN_NORMAL,& str);
StrRetToStr(& str,spidl,& name);
spView-> GetItemPosition(spidl,& pt);
printf(%5d%5d \%s\ \n,pt.x,pt.y,名称);

#define MOVE_ICON
#ifdef MOVE_ICON
//可选:MOVE * SINGLE *选定项目
{
if(!_stricmp(name," ICON_NAME_TO_MOVE))){
PCITEMID_CHILD apidl [1] = {spidl};
int数量= 1;
//在此处设置新位置
hr = spView-> SelectAndPositionItems(numitems,apidl,& pt,0);
}
}
#endif

count ++;
}
CoUninitialize(); //发布COM

fprintf(stderr,枚举的%d桌面图标\n,计数);
fprintf(stderr,按任意键退出... \n);
_getch();
exit(0);
}


Where are the positions of Windows desktop shortcuts stored?

I am asking about the screen positions of the icons not the actual icons themselves. I know the icons themselves are stored in various DLLs, EXEs etc. The positions are clearly stored in some non-volatile store because they persists through re-boots.

My end goal is to write an app to display, and optionally re-arrange icons on my desktop.
I know this is possible because many available apps do this (e.g., "WinTidy").

I find much talk about "Windows Shell Bags". An interesting article about these are in http://williballethin.com.forensics/shellbags, but that only addresses directories not shortcuts. These are in the registry at various places including

`HKEY_CURRENT_USER/Software/Microsoft/Windows/Shell/Bags/1/Desktop`  
`HKEY_USERS/.DEFAULT/Software/Microsoft/Windows/Shell/Bags/1/Desktop`  

I wrote a program to extract these but the format of the key values is incomprehensible.

Any body know where and how they are stored?

解决方案

UPDATE 6/3/20
++++++++++++++++++++++++++++++++++++++
I just switched over to a Win10 64-bit machine and find the solution below no longer works. I believe because of a change in the desktop internals. I figured out how to do this. See "WIN10 ADDENDUM" at the end of this answer.
++++++++++++++++++++++++++++++++++++++

I finally figured out how to do what I want (display and re-arrange desktop icons). My original question concerned locating, reading and writing to the file where the icon info is stored, but this is not a useful approach. Here is what I learned:

Explorer.exe displays desktop items in a giant ListView covering the whole desktop with ListView items corresponding to each visible icon. At startup, Explorer reads info from some arcane file and populates the ListView. On exit, it re-writes that file from the ListView. So modifying the file would not help because it would be overwritten on exit.

The right way to manipulate desktop items is to directly manipulate items in the ListView. Any changes are immediately visible on change, and are saved on exit. To access the items, we can use several Windows messages: LVM_GETITEM, LVM_GETITEMCOUNT, LVM_GETITEMPOSITION and LVM_SETITEMPOSITION. These messages are fairly simple to use with one complication: some require pointers to parameter structures. These structures must be in Explorer's address space not my app's, so some trickery is needed. Here's how to do it. I use LVM_GETITEMPOSITION as an example, which requires a pointer to a POINT structure.

  • Declare a POINT structure in your app.

  • Allocate a mirror structure in Explorer's address space using API VirtualAllocEx().

  • Send LVM_GETITEMPOSITION to Explorer specifying a pointer to this structure.

  • Read back the result into your app's POINT using API ReadProcessMemory(). This function can read memory across different address spaces.

I have prototyped these operations and they work as I wanted. My code is quite long but I will post excerpts as soon as I clean it up.

UPDATE 10/4/2019 ------------------------------------

CODE EXCERPTS

A set of commonly used utility functions was created to make code more compact and readable. These are named "exp*()" and are included at the end. A reference can be found at http://ramrodtechnology.com/explorer. Much of the basic technique herein was shamelessly stolen from https://www.codeproject.com/Articles/5570/Stealing-Program-s-Memory

Setup

// 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 );

Function to Print All Item Names

//@ 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
}  

Function To Print All Item Positions

//@ 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
}

Function To Move Item
See 'expSetItemPosition' below. UPDATED 10/6/19

Explorer Utility Functions

// 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 ADDENDUM 6/19/20
++++++++++++++++++++++++++++++++++

Under Win10, the solution is much more complicated. You must use various COM objects and interfaces, e.g. IShellWindows, etc. (God, I hate COM). I did not create a library but rather offer a complete working program below. I compiled this using MSVC 2019. Error checking has been omitted for clarity (but you should do it).

//  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 );
}

这篇关于桌面快捷方式的位置存储在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆