There's mumbo jumbo in the code to create a filename by concatenating the userid and screen res and also win9x vs NT based. You don't need any of that. The relevant parts are in the SaveIcon, RestoreIcon and GetDesktopListView functions.
Also there's some other stuff about trying to turn AutoArrange off, then back on after icons are restored, but that doesn't work anyway. Just didn't pull the code out. The AutoArrange setting has to be disabled or the restore position function won't work.
Also there's an include "autoarray_ptr.h" that's sort of like an auto_ptr with array delete [] in the destructor. It's just a convenience so that I don't have to manually free memory, esp for char arrays. It does it when the class instance goes out of scope. All that's really needed is navigating the desktop listview and gettting and setting info.
And of course there's a whole bunch of ATL crap to be ignored.
header file
// IconSetter.h : Declaration of the CIconSetter
#ifndef __ICONSETTER_H_
#define __ICONSETTER_H_
#include "resource.h" // main symbols
#pragma comment(lib, "comctl32.lib")
#include <comdef.h>
#include <shlobj.h>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <fstream>
using namespace std;
#ifdef _UNICODE
#define string wstring
#endif
typedef list<string> STRINGLIST;
/////////////////////////////////////////////////////////////////////////////
// CIconSetter
class ATL_NO_VTABLE CIconSetter :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CIconSetter, &CLSID_IconSetter>,
public IShellExtInit,
public IContextMenu
{
public:
CIconSetter()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_ICONSETTER)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CIconSetter)
COM_INTERFACE_ENTRY(IShellExtInit)
COM_INTERFACE_ENTRY(IContextMenu)
END_COM_MAP()
public:
STRINGLIST m_listPaths; // use m_listPaths.front().c_str() to get the first file in the list
// IShellExtInit
public:
STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder,LPDATAOBJECT lpdobj,HKEY hkeyProgID);
// IContextMenu
public:
STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici);
STDMETHOD(GetCommandString)(UINT idCmd, UINT uType,UINT* pwReserved,LPSTR pszName,UINT cchMax);
// IIconSetter
public:
protected:
HWND h;
};
#endif //__ICONSETTER_H_
implementation file
// IconSetter.cpp : Implementation of CIconSetter
#include "stdafx.h"
#include "IconSet.h"
#include "IconSetter.h"
#include "autoarray_ptr.h"
/////////////////////////////////////////////////////////////////////////////
// CIconSetter
#define ICON_FILE "IconPos"
struct HItemEntryTag {
int index;
POINT p;
bool operator <(const HItemEntryTag& i)
{
return p.x < i.p.x;
}
};
struct VItemEntryTag {
int index;
POINT p;
bool operator <(const VItemEntryTag& i)
{
return p.y < i.p.y;
}
};
static HWND GetDesktopListView()
{
char ListViewClassName[64];
string LVClassName;
HWND h = FindWindow("ProgMan", NULL);
h = GetWindow(h, GW_CHILD);
h = GetWindow(h, GW_CHILD);
if(! GetClassName(h, ListViewClassName, 63))
return 0;
LVClassName = ListViewClassName;
return (LVClassName == "SysListView32") ? h : 0;
}
static bool MakeIconPosFileName(string& filename)
{
int x = GetSystemMetrics(SM_CXSCREEN);
int y = GetSystemMetrics(SM_CYSCREEN);
DWORD size = MAX_PATH;
char path[MAX_PATH] = "";
char xbuf[8] = "";
char ybuf[8] = "";
itoa(x, xbuf, 10);
itoa(y, ybuf, 10);
string username, suffix;
OSVERSIONINFO os = {0};
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&os);
if(os.dwPlatformId == VER_PLATFORM_WIN32_NT)
suffix = "NT.txt";
else
suffix = "Win.txt";
if(GetUserName(path, &size)) {
for(x = 0;x < strlen(path);x++)
if(path[x] == ' ') path[x] = '_';
username = path;
path[0] = '\0';
}
if(GetModuleFileName(_Module.GetModuleInstance(), path, MAX_PATH)) {
filename = string("\\") + username + string(ICON_FILE) + string(xbuf) + string("X") + string(ybuf) + suffix;
strcpy(strrchr(path, '\\'), filename.c_str());
filename = path;
return true;
}
return false;
}
static HRESULT SaveIcons()
{
HWND h = GetDesktopListView();
if(! h)
return E_FAIL;
string IconPosFile;
char buf[MAX_PATH] = "";
POINT p;
int x, count = ListView_GetItemCount(h);
if(! MakeIconPosFileName(IconPosFile))
return E_FAIL;
fstream outfile(IconPosFile.c_str(), ios::out);
if( !outfile.is_open() ) {
MessageBox(0, IconPosFile.c_str(), "Error Creating Icon Position File", MB_OK | MB_ICONERROR);
return E_FAIL;
}
for(x = 0; x < count; x++) {
ListView_GetItemText(h, x, 0, buf, MAX_PATH);
ListView_GetItemPosition(h, x, &p);
outfile << buf << endl << p.x << " " << p.y << endl;
}
return NOERROR;
}
static HRESULT RestoreIcons()
{
HWND h = GetDesktopListView();
if(! h)
return E_FAIL;
char buf[MAX_PATH] = "";
string IconPosFile;
int x = 0;
POINT p;
if(! MakeIconPosFileName(IconPosFile))
return E_FAIL;
WIN32_FIND_DATA fd = {0};
HANDLE fh = FindFirstFile( IconPosFile.c_str(), &fd);
if(fh == INVALID_HANDLE_VALUE) {
MessageBox(0, IconPosFile.c_str(), "Icon Position File Not Found", MB_OK | MB_ICONERROR);
return E_FAIL;
}
fstream infile(IconPosFile.c_str(), ios::in);
if( !infile.is_open() )
return E_FAIL;
LV_FINDINFO lvfi;
bool RestoreAutoArrange = false;
DWORD dwStyle = GetWindowLong(h, GWL_STYLE);
if(dwStyle & LVS_AUTOARRANGE) {
SetWindowLong(h, GWL_STYLE, dwStyle & ~LVS_AUTOARRANGE);
RestoreAutoArrange = true;
}
for(;;) {
infile.getline(buf, MAX_PATH);
if(! buf[0])
break;
lvfi.flags = LVFI_STRING;
lvfi.psz = buf;
infile >> p.x >> p.y;
x = ListView_FindItem(h, -1, &lvfi);
if(x != -1)
ListView_SetItemPosition(h, x, p.x, p.y);
infile.getline(buf, MAX_PATH);
}
if(RestoreAutoArrange)
SetWindowLong(h, GWL_STYLE, dwStyle);
return NOERROR;
}
HRESULT CIconSetter::Initialize(LPCITEMIDLIST pidlFolder,LPDATAOBJECT lpdobj, HKEY hkeyProgID)
{
if(pidlFolder == NULL)
return E_FAIL;
// MessageBox(NULL, _T("Got To Here!"), _T("Debug MessageBox"), MB_OK);
if(pidlFolder->mkid.cb != 0)
return E_FAIL;
return NOERROR;
}
HRESULT CIconSetter::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
string szItem0 = _T("Save Icon Positions");
string szItem1 = _T("Restore Icon Positions");
UINT idCmd = idCmdFirst;
InsertMenu(hmenu, indexMenu++, MF_STRING | MF_BYPOSITION, idCmd++, szItem0.c_str());
InsertMenu(hmenu, indexMenu++, MF_STRING | MF_BYPOSITION, idCmd++, szItem1.c_str());
// Must return the greatest menu item identifier plus one.
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, idCmd-idCmdFirst);
}
HRESULT CIconSetter::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
{
HRESULT hr = E_INVALIDARG;
if (!HIWORD(lpici->lpVerb))
{
switch (LOWORD(lpici->lpVerb))
{
case 0:
hr = SaveIcons();
break;
case 1:
hr = RestoreIcons();
break;
}
}
return hr;
}
HRESULT CIconSetter::GetCommandString(UINT idCmd, UINT uType,UINT* pwReserved,LPSTR pszName,UINT cchMax)
{
USES_CONVERSION;
string szCmdString;
// TODO: Get your help strings from the Resources
switch (idCmd)
{
case 0:
szCmdString=_T("Save Desktop Icon Positions");
break;
case 1:
szCmdString=_T("Restore Desktop Icon Positions");
break;
}
switch (uType)
{
case GCS_HELPTEXTA:
lstrcpyA((LPSTR)pszName,T2A((TCHAR*)szCmdString.c_str()));
case GCS_HELPTEXTW:
lstrcpyW((LPWSTR)pszName,T2W((TCHAR*)szCmdString.c_str()));
break;
}
return NOERROR;
}