|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
#1
|
|||
|
|||
|
Result:TBitmap Memory Leak???
Ok this is driving me nutso
![]() I am trying to capture the client area of a window and have it returned as a bitmap. The idea is to put it in a 1 second timer. Here's code that is similar to what I'm trying to do (it's just been edited to make it usable by others who want to test it) and it shows the leak (you can watch it eat it up in the Task Manager, until it crashes). It takes 30-60 seconds to start leaking on my machine. Making the timer faster (ie: 500ms) makes it leak quicker as well. If I don't assign values to the Result.Width and Result.Height properties it doesn't leak; and the smaller/larger you make them it directly affects how fast the memory leaks. Obviously a 0x0 resulting bitmap isn't much use. ![]() It's like I need to free the result after I'm done with it, but I don't know how I can do that and still pass it back to the caller? How can I do this and not have it leak? Any ideas are appreciated.Thanks in advance! Code:
Unit projleaktest;
Interface
Uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;
Type
TForm1 = Class(TForm)
Timer1: TTimer;
Image1: TImage;
Procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
End;
Var
Form1: TForm1;
TheHandle: Integer;
Implementation
{$R *.dfm}
Function CaptureScreen: TBitmap;
Var
DC: HDC;
Begin
DC := GetDC(TheHandle);
Try
Result := TBitmap.Create;
Try
Result.Width := 600;
Result.Height := 500;
BitBlt(Result.Canvas.Handle, 0, 0, Result.Width, Result.Height, DC, 0, 0,
SRCCOPY);
Result.Modified := True;
Finally
ReleaseDC(TheHandle, DC);
End;
Except
Result.Free;
Result := Nil;
End;
End;
Procedure TForm1.Timer1Timer(Sender: TObject);
Begin
TheHandle := 0;
image1.Picture.Bitmap := CaptureScreen;
End;
End.
|
|
#2
|
|||
|
|||
|
TBitmap is using a windows system bitmap internally. So it's not only a memory leak but even resources. After some hours your PC will lock completely.
If you want to return a TBitmap from a function, the caller has to free it later. (edit) Sorry, stupid code removed. Use a temporary variable to store the bitmap reference before assigning it to the bitmap. Then you can use: if Assigned(tmpBitmap) then tmpBitmap.Free; tmpBitmap:=CaptureScreen; M.
__________________
-- Manuel Hirsch - Linux, FreeBSD, programming, administration articles, tutorials and more. |
|
#3
|
|||
|
|||
|
Quote:
Hi, and thanks for the responce! So I'd be aiming to do this(?): Code:
Procedure TForm1.Timer1Timer(Sender: TObject); var tmpBitMap: TBitmap Begin TheHandle := 0; if Assigned(tmpBitmap) then tmpBitmap.Free; tmpBitmap:=CaptureScreen; image1.Picture.Bitmap := tmpBitmap; End; |
|
#4
|
|||
|
|||
|
Yes. Only that "tmpBitmap" has to be persistent between calls of Timer1Timer which a local variable isn't. Add it to the private declarations of your form or outside of the function declaration (move it just above "Procedure...", this is fine IMO since this makes it a unit-local variable and not a global).
HTH, M. |
|
#5
|
|||
|
|||
|
Quote:
Sweet! Works like a charm. I even cranked it up to 20fps and it ran no problem for an hour .Thank you very much. I was thinking I was going to have to make a global variable and convert the function to a procedure, this is much better. Always good to learn some technique! ![]() |
![]() |
| Viewing: Dev Shed Forums > Programming Languages - More > Delphi Programming > Result:TBitmap Memory Leak??? |
| Thread Tools | Search this Thread |
| Display Modes | Rate This Thread |
|
|
|
|