首页 文章

工作线程中的GDI打印机设备上下文随机失败

提问于
浏览
0

我设法创建了一个基于GDI的位图文件打印机例程 . 它工作稳定,没有任何泄漏 . 唯一的缺点当然是它在假脱机程序tranfser期间冻结了UI . 解决方案是将打印例程移动到工作线程中 . 这是代码(错误检查已删除):

void __fastcall PRINT_THREAD::Execute()
{
  while(!Terminated)
  {
   Synchronize(&TalkToOwningThread);
   if(PrintFilePath!="") PrintImage(PrintFilePath);
   Sleep(10);
  }
}


void __fastcall PRINT_THREAD::PrintImage(WideString PrintFilePath)
{
  HDC     hDC;
  DOCINFO di;
  int     w,h;
  bool    success=true;
  TCHAR   szString[32]  = TEXT("Printed from a thread");
  WideString PrinterName="FinePrint";

  TBitmap  *bmp = new TBitmap();
  TPicture *pic = new TPicture();

  hDC=CreateDC(TEXT("WINSPOOL"),PrinterName.c_bstr(),NULL,NULL);

  w=GetDeviceCaps(hDC, HORZRES);
  h=GetDeviceCaps(hDC, VERTRES);

  SecureZeroMemory(&di,sizeof(DOCINFO));
  di.cbSize = sizeof(DOCINFO);
  di.lpszDocName = TEXT("Print Job");

  StartDoc(hDC,&di);
  StartPage(hDC);

  try
  {
    pic->LoadFromFile(PrintFilePath);

    bmp->Width=w;  // set the bitmap dimensions to the printer dimensions
    bmp->Height=h;

    // fill the bitmap with 1:1 print content
    bmp->Canvas->StretchDraw(TRect(0,0,w-1,h-1),pic->Graphic); 
  }
  catch(...){success=false;}

  if(success)
  {
      BitBlt(hDC,0,0,w,h, bmp->Canvas->Handle,0,0, SRCCOPY);
      TextOut(hDC,0,100,szString,lstrlen(szString));
  }

  EndDoc(hDC);
  if(hDC) DeleteDC(hDC);

  delete pic;
  delete bmp;

}

结果:

  • 每次打印调用都通过打印机在页面上生成 - 好的

  • 仅10页中的大约2页包含位图 - 不行

  • 所有页面都包含测试行 - 确定

  • 每次调用都会再添加一个GDI-ressource(任务管理器) - 不行

我已经尝试将CreateDC / DeleteDC函数移回主线程并将hDC转发到工作线程 - 结果相同 .

有没有想法让这种动物运转?

环境:C Builder 10.1 Berlin,Windows10,16GB

谢谢 .

1 回答

  • 1

    正如Remy所说,我添加了锁定/解锁对:

    TBitmap  *bmp = new TBitmap();
    TPicture *pic = new TPicture();
    
    bmp->Canvas->Lock();
    
    ----
    ----
    
    EndPage(hDC);
    EndDoc(hDC);
    
    bmp->Canvas->Unlock();
    
    if(hDC) DeleteDC(hDC);
    delete pic;
    delete bmp;
    

    最后,动物像魅力一样运行 - 不再缺少图形,也没有更多的GDI泄漏 .

相关问题