netying 2024-02-13 11:56 采纳率: 0%
浏览 8

关于TCanvas的Handle的奇怪问题

关于TCanvas的Handle的奇怪问题
C++ Builder 6.0

void __fastcall TForm1::Button1Click(TObject *Sender)
{

    for(int i=0;i<100;i++)
    {
        Graphics::TBitmap *bitmap=new  Graphics::TBitmap();
        bitmap->PixelFormat=pf24bit;
        bitmap->Width=256;
        bitmap->Height=256;
        HDC h=bitmap->Canvas->Handle;

        Memo1->Lines->Add("");//如果注释掉此句,则显示结果为OK,否则为HandleAllocated error

        if(bitmap->Canvas->HandleAllocated())
        {
                         Memo1->Lines->Add("OK:"+String(i));
        }
        else
        {
            Memo1->Lines->Add("HandleAllocated error: "+String(i));
        }
        delete bitmap;
    }
}

在上述代码中,运行结果为HandleAllocated error;如果注释掉则显示结果为OK,百思不得其解。

  • 写回答

4条回答 默认 最新

  • 叫兽-郭老师 Java领域新星创作者 2024-02-13 11:57
    关注

    参考通义千问和郭老师的小迷弟雅思莫了-编写提供,主要是为了帮助您快速解决问题,如下回答,您可以参考下,如有问题,评论区留言。

    您在代码中遇到的问题与TCanvas的Handle和内存管理有关。在C++ Builder 6.0环境下,当您创建一个TBitmap对象时,其Canvas属性会自动关联一个HDC(设备上下文句柄)。然而,由于TCanvas的Handle属性访问的是一个底层Windows GDI资源,它依赖于TBitmap对象的存在。

    在您的循环中,每迭代一次,都会创建一个新的TBitmap对象并获取其Canvas的Handle,然后立即将其删除。但是,由于Windows GDI资源的释放时机可能滞后于TBitmap对象的析构,所以在删除TBitmap后立即检查Canvas的Handle有效性时,可能会导致HandleAllocated()函数返回错误结果。

    当您在删除TBitmap之前调用Memo1->Lines->Add("")时,由于字符串操作和界面更新引入了额外的延迟,这恰好为GDI资源的释放提供了一些时间,所以此时检查Handle的有效性更有可能得到正确的结果(即"OK")。

    为了解决这个问题,并确保正确释放资源,建议在不再使用TBitmap及其Canvas之后,显式地调用ReleaseHandle()方法来释放关联的GDI资源,然后再删除TBitmap对象:

    void __fastcall TForm1::Button1Click(TObject *Sender) {
        for(int i = 0; i < 100; i++) {
            Graphics::TBitmap *bitmap = new Graphics::TBitmap();
            bitmap->PixelFormat = pf24bit;
            bitmap->Width = 256;
            bitmap->Height = 256;
            HDC h = bitmap->Canvas->Handle;
    
            // ... 进行您需要的绘图操作 ...
    
            bitmap->Canvas->ReleaseHandle(); // 显式释放关联的GDI资源
            delete bitmap;
    
            // 在这里检查Handle的有效性
            if (/*...*/) {
                Memo1->Lines->Add("...");
            } else {
                Memo1->Lines->Add("...");
            }
        }
    }
    

    请注意,上述代码仅解决了问题的现象,但在实际应用中,请确保根据您的实际需求合理安排绘图、资源释放和对象销毁逻辑。

    评论

报告相同问题?

问题事件

  • 创建了问题 2月13日

悬赏问题

  • ¥30 求给定范围的全体素数p的(p-2)的连乘积
  • ¥15 VFP如何使用阿里TTS实现文字转语音?
  • ¥100 需要跳转番茄畅听app的adb命令
  • ¥50 寻找一位有逆向游戏盾sdk 应用程序经验的技术
  • ¥15 请问有用MZmine处理 “Waters SYNAPT G2-Si QTOF质谱仪在MSE模式下采集的非靶向数据” 的分析教程吗
  • ¥50 opencv4nodejs 如何安装
  • ¥15 adb push异常 adb: error: 1409-byte write failed: Invalid argument
  • ¥15 nginx反向代理获取ip,java获取真实ip
  • ¥15 eda:门禁系统设计
  • ¥50 如何使用js去调用vscode-js-debugger的方法去调试网页