我有一个paintbox,我画了这样的TBitmap:
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;
我想从PaintBox“映射”/“复制”JPEG或BMP。 我必须先考虑一些挑战。 首先,我想将JPEG或BMP保存到支持WidePath / WideFileName的文件中。我使用Delphi 7,而.SaveToFile程序只支持AnsiPaths / AnsiFileNames。接下来就是我要创建一个独立于“MainGUI线程”的副本。因此GUI应该仍然是活动的并且在将副本保存在后台时绘制到绘图框(所以没有TTimer)。最后一件事是“副本”的实际文件名。我想设置一个从1.jpg ...到2.jpg ...到N.jpg的计数器 问题是由于每个函数都试图递增计数器而导致访问违规的整数计数。
我的想法如下:
保存线程的结构:
type
PTRTSaveImage = ^TSaveImage;
TSaveImage = record
Number : Integer;
Pic : TBitMap;
end;
实际的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;
这就是我称之为线程的方式:
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;
它只需要几张照片就可以了,但调试器给我看了一个例外:
调试器故障通知 项目C:.... exe出现错误信息:'应用程序定义的异常(代码0x0eedfade)位于0x759d9617'。流程已停止。使用步骤或运行继续。
有没有“更好的方法”来做到这一点?同时保存和绘图......?!
感谢您的帮助。
编辑:
然后我还考虑过将1个线程替换为这样的TTimer:
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;
但发生相同的错误/异常。
答案 0 :(得分:1)
AVI文件......我确实想知道......我会创建一个从TPaintBox派生的新Paintbox控件。 (你可能已经这样做了吗?)
为它添加一个计数器属性和代码,使用BitBlit捕获画布到Bmp然后创建一个线程来转换并将位图保存为jpg,并在启动时递增计数器。 (您将需要使用Synchronize进行该调用)。将其命名为CaptureCanvas。
最后添加一个名为say afterChange或afterTimePeriod的方法,调用captureCanvas。确保你有一个尝试...最终确保如果保存出现任何问题,位图和Jpeg将被销毁。它然后全部在一个地方(在TNewPaintbox内部,如果它落后,那么正在创建的图像已经有它们的索引,你不会将它们保存在乱序中......只是一个想法:)
抱歉,添加表单代码然后会简化为:
Form1.Paintboxpaint()
begin
.
.
PaintBox.Canvas.Draw(x, y, bitmap);
Paintbox.AfterChange;
.
很抱歉为了简洁,编辑答案,看不到原帖