I have a paintbox and I draw a TBitmap like this:
procedure MyForm.PaintBoxPaint(Sender: TObject); // ONPAINT
begin
PaintBox.Canvas.Lock;
MyBitMap.Canvas.Lock;
PaintBox.Canvas.Draw(0, 0, MyBitMap);
PaintBox.Canvas.UnLock;
MyBitMap.Canvas.UnLock;
end;
I would like to "map"/"copy" a JPEG or BMP from the PaintBox. There are some challenges tho that I have to think about first. The first thing is that I want to save a JPEG or BMP to a file that supports a WidePath/WideFileName. I use Delphi 7 and the .SaveToFile procedures only supports AnsiPaths/AnsiFileNames. The next thing is that I want to make a copy that is independent from the "MainGUI Thread". So the GUI should be still active and drawing to the paintbox while it saves the copy in the background (so NO TTimer). The last thing is the actual filename of the "copy". I would like to set a counter that goes from 1.jpg ... to 2.jpg ... to N.jpg The problem is the counting of an Integer that can cause access violations due to every function tries to increment the counter.
My Idea was the following:
A structure for the saving Thread:
type
PTRTSaveImage = ^TSaveImage;
TSaveImage = record
Number : Integer;
Pic : TBitMap;
end;
The actual SaveImageThread:
function SaveImageToHDD ( p : pointer ) : Integer; stdcall;
var
jpg : TJpegImage;
jpgStr : TStringStream;
_infos : TSaveImage;
begin
CopyMemory(@_infos, p, SizeOf(_infos));
jpg := TJpegImage.Create;
jpgStr := TStringStream.Create ('');
jpg.assign (_infos.Pic);
_infos.Pic.Free;
jpg.SaveToStream(jpgStr);
jpg.Free;
StrToFile ('C:\' + inttostr(_infos.Number) + '.jpg',0,jpgStr.DataString); // for WidePath/WideFileName Support.
jpgStr.Free;
end;
That's how I call the Thread:
procedure MyForm.PaintBoxPaint(Sender: TObject); // ONPAINT
var
Saving : PTRTSaveImage;
BackUp : TBitMap;
begin
PaintBox.Canvas.Lock;
MyBitMap.Canvas.Lock;
PaintBox.Canvas.Draw(0, 0, MyBitMap);
BackUp := TBitMap.Create;
BackUp.Assign (MyBitMap); // Immediate copy of the actual drawing!
Saving := PTRTSaveImage(LocalAlloc(LPTR, SizeOf(TSaveImage)));
Saving^.Pic := BackUp;
Saving^.Number := Counter;
inc (Counter);
PaintBox.Canvas.UnLock;
MyBitMap.Canvas.UnLock;
end;
it takes a few pictures just fine but then the debugger shows me an exception:
Debugger Fault Notification Project C:....exe faulted with message: 'application-defined exception (code 0x0eedfade) at 0x759d9617'. Process Stopped. Use Step or Run to continue.
Is there any "better way" to do this? Saving and drawing at the same time...?!
Thanks for your help.
EDIT:
Then I also thought about just making 1 thread as a replacement for a TTimer that goes like this:
function SaveImages ( p : TMyForm ) : Integer; stdcall
var
jpg : TJpegImage;
jpgStr : TStringStream;
begin
while true do begin // ---> constant LOOP that saves pictures in the intervall
sleep (1000); // Intervall
jpg := TJpegImage.Create;
jpg.assign (p.MyBitMap);
jpgStr := TStringStream.Create ('');
jpg.SaveToStream(jpgStr);
jpg.Free;
StrToFile ('C:\' + inttostr(p.Counter) + '.jpg',0,jpgStr.DataString); // for WidePath/WideFileName Support.
inc (p.Counter);
jpgStr.Free;
end;
end;
but the same error/exception occurs.