2007. február 2., péntek

How to get the icon of a window for which you know the handle


Problem/Question/Abstract:

How to get the icon of a window for which you know the handle

Answer:

Solve 1:

function GetWindowIcon(Wnd: HWND): TIcon;
{Wnd: Handle to window whose icon you want
Returns: TIcon instance holding the window's icon}
begin
  {Create a TIcon instance to hold the icon information}
  Result := TIcon.Create;
  {As the Win32 API help states, getclasslong will return the handle to the window's icon. Assign that value to the TIcon's Handle property as described in the VCL help.}
  Result.Handle := GetClassLong(Wnd, GCL_HICON);
end;

Additional note:
In my opinion, memory should be allocated and freed on the same level (if possible). So I would recommend changing the above code to this:

procedure GetWindowIcon(Wnd: HWND; Icon: TIcon);
begin
  if not Assigned(Icon) then
    raise Exception.Create('Create instance of Icon ' + 'before calling GetWindowIcon')
      Icon.Handle := GetClassLong(Wnd, GCL_HICON);
end;


Solve 2:

Use GetClassLong to obtain the icon handle and then use CopyIcon to create a new icon from this icon handle. Assuming the Delphi help is open for testing, following are examples:

{Returns true if icon is retrieved and copied to AIcon succesfully}

function CopyIconFromWindowHandle(AHandle: THandle; AIcon: TIcon): boolean;
var
  hWindowIcon: THandle; {HICON}
  tmpIcon: TIcon; {temporary TIcon}
begin
  Result := true;
  if (not (AHandle > 0)) or (AIcon = nil) then
  begin
    Result := false;
    exit;
  end;
  hWindowIcon := GetClassLong(AHandle, GCL_HICON);
  if hWindowIcon = 0 then
  begin
    Result := false;
    exit;
  end;
  tmpIcon := TIcon.Create;
  try
    {exactly the same icon is copied}
    tmpIcon.Handle := CopyIcon(hWindowIcon);
    if tmpIcon.Handle = 0 then
    begin
      Result := false;
      exit;
    end;
    {AIcon is changing}
    try
      AIcon.Assign(tmpIcon);
    except
      Result := false;
      raise;
    end
  finally
    tmpIcon.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  wHandle: THandle;
  TestIcon: TIcon;
begin
  wHandle := FindWindow(nil, pchar('Delphi Help'));
  if not (wHandle > 0) then
    exit;
  TestIcon := TIcon.Create;
  try
    TestIcon.Handle := CopyIcon(Application.Icon.Handle);
    Canvas.Draw(0, 0, TestIcon);
    if CopyIconFromWindowHandle(wHandle, TestIcon) = true then
      Canvas.Draw(0, 80, TestIcon);
  finally
    TestIcon.Free;
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése