안녕하세요.
가령 바탕화면에 있는 '휴지통', '메모장',,, 이런 단축아이콘의
좌표(픽셀)값을 알고 싶습니다.
이곳에서 찾아본 결과 바탕화면 리스트뷰는 SysListView32 이며
ListView_GetItemPosition 함수를 쓰면 된다고 최용일님이 알려주셨더군요.
그래서 해보았는데,,
로컬폼에 리스트뷰를 하나 올려놓고 SHGetDesktopFolder로 바탕화면 폴더
에 있는 아이콘과 시스템 아이콘을 아이템으로 얻어서 위 함수로 아이콘
좌표를 읽으면 제대로 됩니다.
ListView_GetItemPosition(hwnd <-- ListView1.handle 이런식으로..)
그런데 SysListView32의 핸들을 넣어서 좌표를 구하면 이상한 값만 나옵니
다. 또는 모든 아이템에 대해서 0+0 으로 나오구요.
데이터 타입때문에 그런건지,, 포인터 사용이 잘못된건지,,
여기에 소스를 올리면서 질문해도 되는지는 잘 모르겠지만..
양해 바랍니다..
바탕화면 리스트뷰 핸들은 모 사이트의 민성기님 서브클래싱 강좌 소스를
통해 해결했습니다.
필요한 API 나 힌트라도 좀 알려주시기 바랍니다. 부탁드립니다.
감사합니다..
* 소스에서 버튼 2를 클릭해서 SysListView32의 핸들값을 얻은 다음
버튼 1을 클릭합니다..
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, CommCtrl, ImgList, ShellAPI, ShlObj;
type
TForm1 = class(TForm)
ListView1: TListView;
Button1: TButton;
Button2: TButton;
Button3: TButton;
ImageList1: TImageList;
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
procedure GetDesktopImageList(Images : TImageList);
public
{ Public declarations }
end;
var
Form1: TForm1;
DTHwnd : THandle;
implementation
{$R *.DFM}
// 바탕화면 리스트뷰의 핸들을 얻기 위한 프로시져
procedure SetDTHWnd;
function GetClassText(Hwnd : THandle) : String;
begin
setLength(Result, Max_Path);
GetClassName(Hwnd, PChar(Result), Max_Path);
SetLength(Result, StrLen(PChar(Result)));
end;
function EnumChildWindowsProc(Hwnd : THandle; var lParam : DWord) : boolean; stdcall;
begin
Result := True;
if GetClassText(Hwnd) = 'SysListView32' then
// if GetClassText(Hwnd) = 'Progman' then
begin
DTHwnd := Hwnd;
ShowMessage(IntToStr(DTHwnd));
Result := false;
end;
end;
begin
DTHwnd := 0;
EnumChildWindows(FindWindow('Progman', 'Program Manager'), @EnumChildWindowsProc, 0);
end;
// 바탕화면 아이콘들의 위치(픽셀값) 읽어오기
procedure TForm1.Button1Click(Sender: TObject);
var
// ShellFolder : IShellFolder;
// EnumIDList : IEnumIDList;
// Pidl : PItemIDList;
// FileInfo : TSHFileInfo;
tempHwnd : HWND;
i, j, counter : Integer;
ppt : TPoint;
p : PPoint; // = ^TPoint;
ItemX, ItemY : Longint;
pszText : PChar;
icontext : array[0..32] of Char;
s1, s2 : String;
// pt : PChar;
// text : array[0..12] of Char;
lvitem : LV_ITEM;
begin
// i := 0;
ListView1.Items.Clear;
counter := ListView_GetItemCount(DTHwnd);
// ShowMessage(IntToStr(counter));
i := ListView_GetTopIndex(DTHwnd);
// ShowMessage(IntToStr(i));
For j := 0 to counter-1 do
begin
ListView_GetItemPosition(DTHwnd, i, ppt);
p := @ppt;
ItemX := p^.x; //ItemX := ppt.x;
ItemY := p^.y; //ItemY := ppt.y;
Str(ItemX, s1);
Str(ItemY, s2);
ShowMessage(IntToStr(i+1) + '번째 아이템 좌표는 ' + s1 + '+' + s2);
//ShowMessage(IntToStr(ItemX) + '+' + IntToStr(ItemY));
Inc(i);
// p := nil;
end;
end;
// 바탕화면 리스트뷰(SysListView32)의 핸들값 얻어오기 (call procedure)
procedure TForm1.Button2Click(Sender: TObject);
begin
SetDTHWnd;
end;
// 바탕화면의 해상도 정보 (메소드 이용)
procedure TForm1.Button3Click(Sender: TObject);
var
ResX, ResY : Integer;
begin
ResX := Screen.Width;
ResY := Screen.Height;
ShowMessage(IntToStr(ResX) + '+' + IntToStr(ResY));
end;
procedure TForm1.GetDesktopImageList(Images : TImageList);
var
dtImageList : HImageList; // 해당 리스트뷰 컨트롤의 이미지리스트 핸들
begin
Images.ShareImages := True;
// 바탕화면 이미지 리스트의 핸들 얻기 -> 작은 아이콘으로 얻는다.
dtImageList := ListView_GetImageList(DTHwnd, LVSIL_SMALL);
// Image List에 있는 아이콘의 width와 height 설정
Images.Width := GetSystemMetrics(SM_CXSMICON);
Images.Height := GetSystemMetrics(SM_CXSMICON);
// 이미지 리스트의 핸들을 바탕화면 이미지 리스트의 핸들과 맞춘다.
ImageList1.Handle := dtImageList;
end;
end.