Avatar billede borrisholt Novice
03. juli 2003 - 16:31 Der er 16 kommentarer og
1 løsning

TCanvas til BMP

Hej

Jeg har brug for at convetere en TCanvas til en TBitmap.

Det er ikke så svært :
procedure CustomControlToBitmap(const aControl : TWinControl; FileName : TFileName);
var
  aDC: HDc;
  aCanvas: TCanvas;
  aRect: TRect;
  Bitmap: TBitmap;
begin
  aDC := GetWindowDC(aControl.Handle);
  aCanvas := TCanvas.Create;
  aCanvas.Handle := aDC;
  aRect := Rect(0,0,aControl.Width,aControl.Height);
  Bitmap := TBitmap.Create;
  with Bitmap do
  begin
    Width := aControl.Width;
    Height:= aControl.Height;
    PixelFormat := pfDevice;
  end;
  Bitmap.Canvas.CopyRect(aRect,aCanvas,aRect);
  Bitmap.SaveToFile (FileName);
  Bitmap.Free;
  aCanvas.Free;
  ReleaseDC(aControl.Handle, aDC);
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  CustomControlToBitmap(Panel1, 'C:\hest.bmp');
end;


Problmet er blot hvis mit panel er skjult, så får jeg pixels fra det overnliggende vindue ....

Problemet er jeg har en masse kontroller som generer på runtime. Dem sætter jeg på en TPanel. Det panel skal jeg siden bruge som et Bitmap. Problemet er blot at mit panel IKKE er synligt, og ikke kan blive det !

Så jeg skal bruge en løsning på enten det ene eller andet problem !

JEns B
Avatar billede athlon-pascal Juniormester
03. juli 2003 - 16:44 #1
Hvad med at have panelet på en anden form, som aldrig bliver vist for brugeren?
Avatar billede zerohero Nybegynder
03. juli 2003 - 16:54 #2
Prøv dette Jens:

procedure CustomControlToBitmap(const aControl : TWinControl; FileName : TFileName);
var
  MyCanvas: TControlCanvas;
  MyBitmap : TBitmap;
  MyRect: TRect;
begin
  MyCanvas := TControlCanvas.Create;
  MyBitmap := TBitmap.Create;
  MyBitmap.Width := TWinControl(AControl).Width;
  MyBitmap.Height := TWinControl(AControl).Height;
  with MyCanvas do
  try
    //Assigner en Canvas til Panelen
    Control := TControl(AControl);
    //Tegner på Panelen's Canvas
    MyCanvas.TextOut(10,10,'Hej BorrisHolt');
    //Kopiér Canvas til Bitmap
    with TWinControl(AControl) do
    MyCanvas.CopyRect(ClientRect,MyBitmap.Canvas,ClientRect);
    //Gemmer
    MyBitmap.SaveToFile(FileName);
  finally
    Free;
    MyBitmap.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  CustomControlToBitmap(Panel1,'C:\HestTest.bmp');
end;

Held og Lykke
ZeroHero
Avatar billede zerohero Nybegynder
03. juli 2003 - 16:59 #3
Nu ved jeg ikke nøjagtig din idé. Men det jeg har gjort er at overskrive din Panel's canvas (som af en eller anden grund ikke er sat Public i sin klasse) med en ny Canvas som du har 100% kontrol over. Ideén er så at Skrive/Tegne alt det som du har lyst til på den nye Canvas! Du kan selvfølgelig gøre MyCanvas til en global variant!
Avatar billede zerohero Nybegynder
03. juli 2003 - 17:00 #4
PS: MyRect bliver ikke brugt!!!!
Avatar billede athlon-pascal Juniormester
03. juli 2003 - 17:05 #5
zerohero -> Din ide virker ikke hos mig :-(

Jens -> Min ide med at bruge en anden form virker heller ikke hos mig :-(
Måske virker zeroheros forslag hos dig, evt. med lidt flere heste ;-)
Avatar billede athlon-pascal Juniormester
03. juli 2003 - 17:07 #6
(Zeroheros funktion giver et hvidt bitmap hos mig...)
Avatar billede zerohero Nybegynder
03. juli 2003 - 17:09 #7
He he selvfølgeligt det er jo en helt "ren" canvas!
Avatar billede zerohero Nybegynder
03. juli 2003 - 17:10 #8
Så skal der jo bare tegnes på den!!!!
Avatar billede dkn Nybegynder
03. juli 2003 - 18:05 #9
hvis noget af det andet ikke virker, prøvede jeg lige med denne metode. Den ser altså ud til at virke:


procedure TForm1.Button1Click(Sender: TObject);
var
  Rect              : TRect;
  ScreenDC          : HDC;
  fBitmap, fbitmap2 : TBitmap;
begin
  ScreenDC := GetWindowDC(Handle);

  fBitmap := TBitmap.Create;
  fbitmap2 := TBitmap.Create;

  GetWindowRect(Handle, Rect);
  try
    fBitmap.Width := Rect.Right - Rect.Left;
    fBitmap.Height := Rect.Bottom - Rect.Top;
    BitBlt(fBitmap.Canvas.Handle, 0, 0, fBitmap.Width, fBitmap.Height, ScreenDC, 0, 0, SRCCOPY);
    ReleaseDC(Handle, ScreenDC);

    // Ok nu har vi screenshot af hele formen, så skal vi jo bare have fundet
    // det der ligger på panel
    // pga af et eller anden kan man ikke bruge clientrect, eller BoundsRect
    // ved at lave recten selv, kan man nok også få den anden kode til at virke
    // som capture control

    fbitmap2.Width := panel1.Width;
    fbitmap2.Height := panel1.Height;
    fbitmap2.Canvas.CopyRect(Classes.rect(0, 0, panel1.width, panel1.height), fbitmap.Canvas, Classes.Rect(panel1.Left, panel1.Top, panel1.Width + panel1.Left, panel1.Height + panel1.Top));
    fbitmap2.SaveToFile('.\Test.bmp');
  finally
    ReleaseDC(Handle, ScreenDC);
    fBitmap.Free;
    fbitmap2.Free;
  end;
end;


Men tror sku den anden function CustomControlToBitmap også ville virke, hvis man selv lavede det rect.
Avatar billede zerohero Nybegynder
03. juli 2003 - 18:28 #10
dkn>> BitBlt har desværre også den ulempe at den tager en screen-shot (det man ser på skærmen) og ikke bare kopiere pixels direkte fra canvas'en!
Avatar billede athlon-pascal Juniormester
03. juli 2003 - 18:31 #11
Såvidt jeg kan se er Jens' ønske at kunne kovertere en controls (med Visible := false; //!!!) canvas til bitmap... eller, som jeg har forstået, at lave et "screenshot" af noget der ikke vises på skærmen...

Er der nogen af jer der tolker Jens' spørgsmål anderledes end jeg gør?
Avatar billede dkn Nybegynder
03. juli 2003 - 18:37 #12
ok så havde jeg ikke lige læst spm ordenligt
Avatar billede zerohero Nybegynder
03. juli 2003 - 19:49 #13
Problemet er bare, at du ikke kan lave en screen-shot af noget som ikke eksitere på skærmen (hvilket egentligt også er logisk nok) uden at lave en kreativ løsning (grifisk simulering). Det vil sige, at hvis det er Panel'ens Canvas du vil bruge som udgangs punkt (Parent Canvas), skal man vel bare assigne en canvas til din panel (som jeg har vist) og kopiér de andre control's canvas (i de rigtige positioner selvfølig) til panelens canvas. Men Jens har ikke rigtigt præciseret i hvilken sammenhæng koden skal bruges. Hvis han laver er mere detaljeret beskrivelse af sit projekt vil det også være nemmere at hjælpe ham!

ZeroHero
Avatar billede athlon-pascal Juniormester
03. juli 2003 - 21:54 #14
ZeroHero -> Det er derfor jeg skrev "screenshot" og ikke screenshot :-)
Avatar billede borrisholt Novice
04. juli 2003 - 08:23 #15
OKI Jeg er tilbage !!

fbitmap2.Canvas.CopyRect virker ikke den baserer sig på BitBlt !

Jeg tegner et diagram vha. nogle kontroller. Det skal blive til en TBitmap, fordi jeg skal bruge det til en raport.

Disse kontroller bliver sat på en TPanel, fordi jeg så har et vel defineret område jeg kan konvetere til en Bitmap.

JEg vil helst være fri for at skulle tegne det i hånden.

Jens B
Avatar billede borrisholt Novice
04. juli 2003 - 09:07 #16
PaintTo var løsningen.

Jeg har hacket lidt om. Men det her virker :

function WinControlToBitmap(const aControl: TWinControl): TBitmap;
begin
  Result := TBitmap.Create;
  with Result do
  try
    Width := aControl.Width;
    Height := aControl.Height;
    PixelFormat := pfDevice;
    aControl.PaintTo(Canvas.Handle, 0, 0);
  except
    Free;
  end;
end;


Sæt et TPanel på en form og prøv så det her :

procedure TForm1.Button1Click(Sender: TObject);
begin
  Panel1.Left := -400;
  Image1.Picture.Bitmap.Assign(WinControlToBitmap(Panel1));
end;
Avatar billede athlon-pascal Juniormester
04. juli 2003 - 11:16 #17
Det er godt du fandt en løsning :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester