改变桌面图标位置,需要准确计算网格位置。影响网格位置的因数很多,比如注册表的HKEY_CURRENT_USER\ControlPanel\Desktop\WindowMetrics目录下的,IconSpacing,IconVerticalSpacing。还有图标本身大小(大中小图标),title行数,title字体,网格间距(默认8px)等等。而且,目前还没有找到这些因数与网格位置之间的计算公式(惭愧)。后来,经同事协助,找到了一个系统API可以直接获取网格长宽(可以计算网格位置),真是太高兴了。这里分享出来,提供给有需要的童鞋。
// 查找桌面文件视图
void FindDesktopFolderView(REFIID riid, void **ppv)
{
CComPtr<IShellWindows> spShellWindows;
spShellWindows.CoCreateInstance(CLSID_ShellWindows);
CComVariant vtLoc(CSIDL_DESKTOP);
CComVariant vtEmpty;
long lhwnd;
CComPtr<IDispatch> spdisp;
spShellWindows->FindWindowSW(
&vtLoc, &vtEmpty,
SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp);
CComPtr<IShellBrowser> spBrowser;
CComQIPtr<IServiceProvider>(spdisp)->
QueryService(SID_STopLevelBrowser,
IID_PPV_ARGS(&spBrowser));
CComPtr<IShellView> spView;
spBrowser->QueryActiveShellView(&spView);
spView->QueryInterface(riid, ppv);
}
class CCoInitialize {
public:
CCoInitialize() : m_hr(CoInitialize(NULL)) { }
~CCoInitialize() { if (SUCCEEDED(m_hr)) CoUninitialize(); }
operator HRESULT() const { return m_hr; }
HRESULT m_hr;
};
// 获取系统桌面图标信息
/*
返回值格式如下:
工作区域X轴(水平),工作区域Y轴(垂直),图标水平间距,图标垂直间距,自动排序标志,显示模式
*/
const char* GetSystemIconInfo(int bShow)
{
HRESULT m_hr = CoInitialize(NULL);
if (m_hr != S_OK){
return "";
}
CComPtr<IFolderView> spView;
FindDesktopFolderView(IID_PPV_ARGS(&spView));
if (NULL == spView)
{
return "";
}
int index = 1;
CComHeapPtr<ITEMID_CHILD> spidl;
POINT Spacing_PT;
POINT DefaultSpacing_PT;
spView->GetSpacing(&Spacing_PT);
spView->GetDefaultSpacing(&DefaultSpacing_PT);
bool bAutoArrange = spView->GetAutoArrange() == S_OK;
// 显示模式
UINT uViewMode = 0;
spView->GetCurrentViewMode(&uViewMode);
// 桌面工作区域
int workAreaX = GetSystemMetrics(SM_CXFULLSCREEN); //获取最大化窗体的显示区域宽度
int workAreaY = GetSystemMetrics(SM_CYFULLSCREEN); //获取最大化窗体的显示区域高度
char* temBuff = new char[MAX_PATH];
memset(temBuff, '\0', sizeof(char)*MAX_PATH);
sprintf(temBuff, "workareaX=%d,workareaY=%d,spaceX=%d,spaceY=%d,autoArrange=%d,viewMode=%d", workAreaX, workAreaY, Spacing_PT.x, Spacing_PT.y, int(bAutoArrange), uViewMode);
//CoUninitialize();
return temBuff;
}