dポイントプレゼントキャンペーン実施中!

デスクトップ上の座標を指定し、そこに配置してあるアイコン名(ファイル名)
を返すようにする方法ってないですか?
但し、アイコンの配置はあらかじめ知らないとします。

つまり、座標を与えることでリアルタイムにデスクトップ上の
情報を得ることは可能でしょうか。
返してくれるのはアイコン名(ファイル名)だけで構いません。

環境はwindows vista又はXP、言語はc++(Eclipse+MinGW)です。

A 回答 (1件)

 こんにちは。


 デスクトップはアイコンスタイルのリストビューなので、マウス下のアイテム情報さえ取り出せれば、可能と言えば可能です。
 但し、デスクトップは自プロセス外にある為、プロセス間共有メモリを割り当てて遣り取りしなければいけません。
 とてもではありませんが、簡単に説明できる物ではありません。以下参考程度に。

#include<windows.h>
#include<commctrl.h>
#include<tchar.h>
#include"resource.h"

#pragma comment(lib, "comctl32.lib")

typedef struct ProcessMemory
{
DWORD dwProcessID;
DWORD dwThreadID;
HANDLE hProcess;
union
{
LPVOID pVoid;
LPBYTE pByte;
LPTSTR pTStr;
LPARAM lParam;
};
} PROCESSMEMORY, *LPPROCESSMEMORY;

static BOOL OpenProcessMemory(LPPROCESSMEMORY p, HWND hWndOutProcess, DWORD dwSize)
{
p->dwThreadID = ::GetWindowThreadProcessId(hWndOutProcess, &p->dwProcessID);
if(!p->dwThreadID || !p->dwProcessID)
return FALSE;

p->hProcess = ::OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, p->dwProcessID);
if(!p->hProcess)
return FALSE;

p->pVoid = ::VirtualAllocEx(p->hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
return p->pVoid != NULL;
}

static BOOL CloseProcessMemory(LPPROCESSMEMORY p)
{
if(!p->hProcess)
return FALSE;

::VirtualFreeEx(p->hProcess, p->pVoid, 0, MEM_RELEASE);
::CloseHandle(p->hProcess);
::ZeroMemory(p, sizeof(PROCESSMEMORY));
return TRUE;
}

static DWORD WriteProcessMemory(LPPROCESSMEMORY p, DWORD dwByteOfOffset, const void* pIn, DWORD dwSizeOfIn)
{
DWORD dwLen = 0;
::WriteProcessMemory(p->hProcess, &p->pByte[dwByteOfOffset], pIn, dwSizeOfIn, &dwLen);
return dwLen;
}

static DWORD ReadProcessMemory(const LPPROCESSMEMORY p, DWORD dwByteOfOffset, void* pOut, DWORD dwSizeOfOut)
{
DWORD dwLen = 0;
::ReadProcessMemory(p->hProcess, &p->pByte[dwByteOfOffset], pOut, dwSizeOfOut, &dwLen);
return dwLen;
}

int WINAPI DlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_INITDIALOG:
::SetTimer(hWnd, 1, 33, NULL);
break;

case WM_CLOSE:
::DestroyWindow(hWnd);
::KillTimer(hWnd, 1);
break;

case WM_NCDESTROY:
::PostQuitMessage(0);
break;

case WM_TIMER:
{
//マウス下のウィンドウを取り出す
POINT pt;
::GetCursorPos(&pt);
HWND hWndUnder = ::WindowFromPoint(pt);

//此処に名前が入ってくる
TCHAR buffer[MAX_PATH + 1];

//プロセス間共有メモリ(サイズは余裕をもって適当に割り当てる)
ProcessMemory pm = {0};
::OpenProcessMemory(&pm, hWndUnder, sizeof(LVHITTESTINFO) + sizeof(LVITEM) + sizeof(buffer));

//プロセス間共有メモリに必要なデータを書き込む
LVHITTESTINFO lhif = {0};
lhif.pt = pt;
::WriteProcessMemory(&pm, 0, &lhif, sizeof(lhif));

//プロセス間共有メモリを使ってデスクトップに対してマウス下の状態を問い合わせる
ListView_HitTest(hWndUnder, pm.pVoid);

//プロセス間共有メモリに書かれた情報を、此方側に複写する
::ReadProcessMemory(&pm, 0, &lhif, sizeof(lhif));

//マウス下がアイコンだったら、
if(lhif.flags == LVHT_ONITEMICON)
{
//アイコンの情報を取り出すための準備
LVITEM item = {LVIF_TEXT};
item.iItem = lhif.iItem;
item.iSubItem = lhif.iSubItem;

//文字を受け取るバッファ オフセットはLVITEM構造体のサイズ
item.pszText = &pm.pTStr[sizeof(item)];
item.cchTextMax = MAX_PATH;

//プロセス間共有メモリに書く
::WriteProcessMemory(&pm, 0, &item, sizeof(item));

//プロセス間共有メモリを使ってデスクトップアイコンの状態を問い合わせる
ListView_GetItem(hWndUnder, pm.pVoid);

//プロセス間共有メモリに書かれた情報を、此方側に複写する
::ReadProcessMemory(&pm, 0, &item, sizeof(item));

//プロセス間共有メモリに書かれた情報を、此方側に複写する(LVITEM::pszTextの分)
::ReadProcessMemory(&pm, sizeof(item), buffer, sizeof(buffer));

//bufferにファイル名が入ってくる筈
}

::CloseProcessMemory(&pm);
}
break;
}
return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
MSG msg;
HWND hDlg = ::CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, &::DlgProc);
::ShowWindow(hDlg, SW_SHOW);

while(::GetMessage(&msg, NULL, 0, 0) == TRUE)
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}

return msg.wParam;
}
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!