Контекст устройства принтера GDI в рабочем потоке случайно завершается ошибкой - PullRequest
0 голосов
/ 09 декабря 2018

Мне удалось создать процедуру печати растрового файла на основе GDI.Работает стабильно и без каких-либо утечек.Единственный недостаток, конечно, это замораживание пользовательского интерфейса во время передачи спулера.Решением проблемы было перемещение процедуры печати в рабочий поток.Вот код (проверка ошибок удалена):

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;

}

Результаты:

  • Каждый вызов печати производится на странице через принтер - ОК
  • Только около 2 из 10 страниц содержат растровое изображение - Не в порядке
  • Все страницы содержат тестовую строку - ОК
  • При каждом вызове добавляется еще один ресурс GDI (диспетчер задач)- Не в порядке

Я уже пытался переместить функции CreateDC / DeleteDC обратно в основной поток и перенести hDC в рабочий поток - Те же результаты.

Есть ли идеи?чтобы запустить это животное?

Среда: C ++ Builder 10.1 Berlin, Windows10, 16 ГБ

Спасибо.

1 Ответ

0 голосов
/ 10 декабря 2018

По предложению Реми, я добавил пару Блокировка / Разблокировка:

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.

...