Delphi 7,在窗体上移动光标时,句柄无效:)

Delphi 7,在窗体上移动光标时,句柄无效:),delphi,gdi,Delphi,Gdi,下面是运行一个线程的代码片段(准备粘贴并运行)。 此线程获取光盘上jpg文件的列表,然后对其执行某些操作 正常情况下,它工作正常。如果我开始在表单上移动光标,每次都会出现以下错误:) 有什么想法吗? 谢谢 unitutest; 接口 使用 窗口、消息、系统工具、变体、类、图形、控件、窗体、, 对话框,StdCtrls,jpeg,gr32; 类型 TThreadSafeJpegImage=class(TJPEGImage) 受保护的 程序绘制(ACanvas:TCanvas;const Rect:

下面是运行一个线程的代码片段(准备粘贴并运行)。 此线程获取光盘上jpg文件的列表,然后对其执行某些操作

正常情况下,它工作正常。如果我开始在表单上移动光标,每次都会出现以下错误:)

有什么想法吗? 谢谢

unitutest;
接口
使用
窗口、消息、系统工具、变体、类、图形、控件、窗体、,
对话框,StdCtrls,jpeg,gr32;
类型
TThreadSafeJpegImage=class(TJPEGImage)
受保护的
程序绘制(ACanvas:TCanvas;const Rect:TRect);推翻
结束;
TForm1=类(TForm)
btn1:TButton;
程序btn1Click(发送方:TObject);
私有的
公开的
结束;
TWatek=class(TThread)
公众的
程序执行;推翻
结束;
变量
表1:TForm1;
实施
{$R*.dfm}
程序TForm1.btn1Click(发送方:TObject);
变量
thr:TWatek;
开始
thr:=TWatek.Create(true);
thr.FreeOnTerminate:=真;
恢复;
结束;
{TWatek}
程序TWatek.Execute;
变量
弦;
Rec:TSearchRec;
路径:字符串;
I:整数;
函数TestFile(路径:string):WideString;
变量
流:TMemoryStream;
jpg:tthreadsafeejpegimage;
bmp32:TBitmap32;
strStr:TStringStream;
错误:字符串;
开始
尝试
stream:=TMemoryStream.Create;
jpg:=TThreadSafeJpegImage.Create;
尝试
stream.LoadFromFile(路径);
jpg.LoadFromStream(stream);
最后
FreeAndNil(溪流);
结束;
bmp32:=TBitmap32.Create;
尝试
bmp32.分配(jpg);
strStr:=TStringStream.Create(“”);
bmp32.SaveToStream(strstrstr);
strStr.Seek(0,从开始);
最后
FreeAndNil(jpg);
FreeAndNil(bmp32);
结束;
结果:=strStr.DataString;
FreeAndNil(strstrstr);
除了
关于e:exception-do
开始
错误:=e.消息;
showmessage(err);
结束;
结束;
结束;
开始
sciezka:=“d:\pictures\”;
对于I:=1到100 do
开始
路径:=IncludeTrailingPathDelimiter(sciezka);
如果FindFirst(路径+'*.jpg',faAnyFile-faDirectory,Rec)=0,则
开始
尝试
重复
TestFile(Path+Rec.Name);
直到FindNext(Rec)0;
最后
FindClose(Rec);
结束;
结束;
结束;
结束;
{tthreadsafeejpegimage}
过程TThreadSafeJpegImage.Draw(ACanvas:TCanvas;const Rect:TRect);
开始
位图.Canvas.Lock;
尝试
继承的绘图(ACanvas、Rect);
最后
位图.Canvas.Unlock;
结束;
结束;
结束。

不是100%确定,如果我有妄想症,请投票否决我

TThreadSafeJpegImage.Draw锁定画布。
在窗体上移动鼠标时,会强制重新绘制,而窗体无法执行此操作(因为之前已锁定画布),这会导致返回错误

更改绘图代码,如下所示:

procedure TThreadSafeJpegImage.Draw(ACanvas: TCanvas; const Rect: TRect);
var
  OKToDraw: boolean;
begin 
  OKToDraw:= Bitmap.Canvas.TryLock;
  if OKTODraw then try
    inherited Draw(ACanvas, Rect);
  finally
    Bitmap.Canvas.Unlock;
  end; {if try}
end;

Graphics32小组的一个人为我找到了一个解决方案。我们必须对gr32单元进行如下修改:

1) In TBitmap32.AssignTo() replace

  DrawTo(Bmp.Canvas.Handle, 0, 0);

with

  Bmp.Canvas.Lock;
  try
    DrawTo(Bmp.Canvas.Handle, 0, 0);
  finally
    Bmp.Canvas.UnLock;
  end;

2) In TBitmap32.Assign() replace

  TGraphicAccess(Source).Draw(Canvas, MakeRect(0, 0, Width, Height));

with

  Canvas.Lock;
  try
    TGraphicAccess(Source).Draw(Canvas, MakeRect(0, 0, Width, Height));
  finally
    Canvas.UnLock;
  end;

Now it works!

TThreadSafeJpegImage类在这种情况下并不重要。它只是我的标准TJpegImage的替代品,使这个类线程安全。使用tjpegimage或我的ThreadSafeJPEGImage,我在except块中得到这个错误。您再现了此错误吗?位图是jpeg单元的内部位图,而不是形式:)@John,1。这是对代码的复制/粘贴的轻微编辑,您确实看到了右侧2。你测试过这个吗?3.它有用吗?简单的复制/粘贴并运行应该可以告诉您答案。4.此代码中没有对表单的引用。是的,它确实起作用(单元中没有更多的代码行),没有与表单的连接。只需移动光标就会在以下行中引发错误:bmp32.SaveToStream(strstrstr)@John,JPEG图像没有Windows句柄,因此是表单驱动图像的绘制,因为图像从未收到wm_paint消息,表单执行并调用JPEG图像的(继承的)绘制。从何处获得错误?调试器应该中断并向您显示引发异常的行。从那里开始调查。这行有一个错误:bmp32.SaveToStream(strstrstr);问题是我不知道为什么在窗体上移动光标会影响线程,因为行不是问题所在。问题更深。在项目的链接器设置中打开“调试DCU”选项,然后重试。您正在查找调用
raise
的代码行。当您在调试器中找到它时,请查看“调用堆栈”窗口以了解您的程序是如何到达那里的。上面的代码在这里没有问题。(也是D7)该错误是在图形单元的GDIError过程中产生的
1) In TBitmap32.AssignTo() replace

  DrawTo(Bmp.Canvas.Handle, 0, 0);

with

  Bmp.Canvas.Lock;
  try
    DrawTo(Bmp.Canvas.Handle, 0, 0);
  finally
    Bmp.Canvas.UnLock;
  end;

2) In TBitmap32.Assign() replace

  TGraphicAccess(Source).Draw(Canvas, MakeRect(0, 0, Width, Height));

with

  Canvas.Lock;
  try
    TGraphicAccess(Source).Draw(Canvas, MakeRect(0, 0, Width, Height));
  finally
    Canvas.UnLock;
  end;

Now it works!