Q&A

  • 바탕화면 아이콘 위치 (좌표값) 알아내기
안녕하세요.
가령 바탕화면에 있는 '휴지통', '메모장',,, 이런 단축아이콘의
좌표(픽셀)값을 알고 싶습니다.
이곳에서 찾아본 결과 바탕화면 리스트뷰는 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.

0  COMMENTS