Jak przekonwertować hIcon do TBitmap?

0

Mam uchwyt do ikony w zmiennej

Icon: hIcon;

Wykonuję:

procedure HIconToBitmap(Icon: HICON; Bitmap: TBitmap);
begin
  DrawIconEx(Bitmap.Canvas.Handle, 0, 0, Icon, 16, 16, 0, 0, DI_NORMAL);
end;

procedure TForm1.Button1(Sender: TObject);
var
  bmp: TBitmap;
begin
  Bmp := TBitmap.Create;
  try;
    HIconToBitmap(Icon, Bmp);
    Image1.Picture.Bitmap.Assign(bmp);
  finally
    Bmp.Free;
  end;
end;

Ale komponent Image1. jest pusty. Natomiast jak zrobię:

Image1.Picture.Icon.Handle := Icon;

To obrazek się podstawia. Co robię nie tak?

Zrobiłem w ten sposób:

Bmp := TBitmap.Create;
        MyIcon:=TIcon.Create;
        try;
          MyIcon.Handle:=Icon;
          bmp.Width := MyIcon.Width;
          bmp.Height := MyIcon.Height;
          bmp.Canvas.Draw(0, 0, MyIcon ) ;
         // HIconToBitmap(Icon, Bmp);
        //  Image1.Picture.Bitmap := nil;

          Image1.Picture.Bitmap.Assign(bmp);

          // Bmp.Handle = HBITMAP
          // Bmp.Canvas.Handle = HDC
        finally
          MyIcon.Free;
          Bmp.Free;
        end;

i działa, ale nie podoba mi się to, że muszę konwertować do ikony a później do BMP....

1
user322 napisał(a):

(...) ale nie podoba mi się to, że muszę konwertować do ikony a później do BMP....

Hehe, następny dzisiaj ;) Który lubi sobie stwarzać problemy tam, gdzie ich w ogóle nie ma. No to podstawiaj od razu swój HICON do Picture.Icon.Handle i "wuala"! Gotowe :) Bez problemów.

Ewentualnie wywołuj funkcję LoadImage tak, żebyś miał od razu HICON w żądanych rozmiarach. I wiadomo można "mieszać" WinAPI z VCL. Bo i VCL bazuje na WinAPI oczywiście. Ale za bardzo sobie gmatwasz, robiąc problem, gdzie go nie ma. No ale to już pisałem, także kończe :P

2

Jeśli używasz instancji klasy TBitmap osobno, to po wywołaniu konstruktora musisz nadać bitmapie rozmiar; Ty tego nie robiłeś, więc rozmiar bitmapy był równy 0;

Zobacz na poniższy przykład; Na formularzu jest komponent imgIcon - domyślnie bez załadowanej grafiki; Teraz aby namalować na nim ikonę posiadaną przez formularz, wystarczy stworzyć klasę TBitmap, nadać jej rozmiar i przerysować ikonę formularza na kanwę bitmapy, za pomocą Windows.DrawIcon lub Windows.DrawIconEx; Na koniec skojarzyć bitmapę komponentu z tą tymczasową i gotowe;

Kod:

procedure TForm1.Button1Click(Sender: TObject);
var
  bmpIcon: TBitmap;
begin
  bmpIcon := TBitmap.Create();
  try
    bmpIcon.Width := imgIcon.Width;
    bmpIcon.Height := imgIcon.Height;
    Windows.DrawIconEx(bmpIcon.Canvas.Handle, 50, 50, Self.Icon.Handle, 16, 16, 0, 0, DI_NORMAL);
    imgIcon.Picture.Bitmap.Assign(bmpIcon);
  finally
    bmpIcon.Free();
  end;
end;

Poniżej zrzuty - z lewej przed wywołaniem kodu, z prawej po jego wywołaniu (po przyciśnięciu przycisku):

icon-drawing.png

W załączniku masz źródła do przetestowania, jakbyś miał problem z przepisaniem/przeniesieniem kodu;


Zresztą, dokładnie to samo możesz zrobić bezpośrednio na bitmapie komponentu, jednak rozmiar początkowo i tak trzeba ustawić:

procedure TForm1.Button1Click(Sender: TObject);
begin
  imgIcon.Picture.Bitmap.Width  := imgIcon.Width;
  imgIcon.Picture.Bitmap.Height := imgIcon.Height;
  Windows.DrawIconEx(imgIcon.Picture.Bitmap.Canvas.Handle, 50, 50, Self.Icon.Handle, 16, 16, 0, 0, DI_NORMAL);
end;

Tego rozwiązania użyj w przypadku, gdy potrzebujesz porysować coś więcej, niż tylko samą ikonę (np. z wybranym tłem); Jeśli to jest niepotrzebne i ikona ma być tylko wyświetlona - przepisz jedynie uchwyt, tak jak podał poprzednik; Nie ma co utrudniać sobie życia.

0

Zadziałało :)

Całość wygląda tak:

procedure HIconToBitmap(Icon: HICON; Bitmap: TBitmap);
begin
  Bitmap.Width := 16;
  Bitmap.Height := 16;
  DrawIconEx(Bitmap.Canvas.Handle, 0, 0, Icon, 16, 16, 0, 0, DI_NORMAL);
end;

procedure JakasTam(Sender: TObject);
var
  bmp: TBitmap;
begin
  ...
        Bmp := TBitmap.Create;
        try;
          // Konwersja hIcon do TBitmap
          HIconToBitmap(Icon, Bmp);

          ms := TMemoryStream.Create;
          try
            bmp.SaveToStream(ms);
            ms.Position := 0;

            // Podstawienie strumienia z Bitmapa do pola SQL (INSERT)
            IBSQL1.ParamByName('icon').LoadFromStream(ms);

            IBSQL1.ExecQuery;
            IBTransaction1.Commit;

            // Przypisz do Image1
            Image1.Picture.Bitmap.Assign(bmp);
          finally
            ms.Free;
          end;

        finally
          Bmp.Free;
        end;
end;

Musiałem to przekonwertować, żeby zrobić inserta do bazy z obrazkiem i później go odczytać.

@olesio, problemem było to, że pobierałem ikonkę procesu na podstawie pozycji kursora i okna, które znajduje się pod nim, następnie chciałem tą ikonkę zapisać do bazy danych SQL w postaci obrazka, by móc później ją wczytać do drzewka tak jak pisałem w poprzednim temacie (repozytorium, gdzie miałem problem właśnie z pobraniem PID okna głównego). Nawet nie sprawdzałem czy się da, ale hIcon nie załaduję do bazy, a bitmapę jako stream tak, co wykonałem powyżej, aczkolwiek nie wiem, może jest jeszcze prostszy i bardziej wydajny sposób na to.

Dzięki za pomoc!

1 użytkowników online, w tym zalogowanych: 0, gości: 1