Конференция "WinAPI" » Свойства Принтера
 
  • dmk © (03.12.17 00:13) [0]
    После обновления OS WINDOWS 10 до версии 1709 перестал работать вызов свойств принтера. Код обработки работал еще со времен XP. Win7, Win 8 и даже Win 10 до версии 1709. Права открытия принтера менял на разные PRINTER_READ/WRITE. Ничего не помогает. Выдает ошибку Get Printer Data Size Error. В чем может быть еще проблема?

    function TWinPrinter.UpdateProperties(ShowDialog: boolean): boolean;
    var
     bFlag: boolean;
     lFlag: DWord;
     DataSize: DWord;
     pDefaults: _PRINTER_DEFAULTSW;
     pDevMode: PDeviceModeW;

    begin
     pDefaults.pDatatype := nil;
     pDefaults.pDevMode := nil;
     pDefaults.DesiredAccess := PRINTER_ALL_ACCESS;

     //Попробуем открыть принтер и получить FPrinterHandle
     bFlag := OpenPrinter(PChar(FPrinterName), FPrinterHandle, PPrinterDefaultsW(@pDefaults));
     if bFlag = false then
     begin
       raise Exception.Create('OpenPrinter error: ' + IntToStr(GetLastError));
       exit;
     end;

     //PRINTER_INFO_2
     //Первый вызов для получения размера буфера
     bFlag := GetPrinter(FPrinterHandle, 2, PPrinterInfo2W(FPrinterInfo2W), DataSize, @DataSize);
     if ((bFlag = false) and (DataSize = 0)) then
       begin
         raise Exception.Create('GetPrinter data size error: ' + IntToStr(GetLastError));
         exit;
       end
      else
       begin
         //Выделим память под полную структуру принтера
         GetMem(FPrinterInfo2W, DataSize);

         //Теперь получим информацию о принтере
         bFlag := GetPrinter(FPrinterHandle, 2, PPrinterInfo2W(FPrinterInfo2W), DataSize, @DataSize);
         if (bFlag = false) then
           begin
             raise Exception.Create('GetPrinter info error: ' + IntToStr(GetLastError));
             FreeMem(FPrinterInfo2W);
             FPrinterInfo2W := nil;
             exit;
           end;
       end;

     //Вызов 1
     //Узнаем размер буфера для структуры DevMode
     lFlag := DocumentProperties(0, FPrinterHandle, PChar(FPrinterName), nil, nil, 0);

     if Integer(lFlag) < 0 then
     begin
       raise Exception.Create('UpdateProperties error: ' + IntToStr(GetLastError));
       FreeMem(FPrinterInfo2W);
       FPrinterInfo2W := nil;
       exit;
     end
     else//Иначе выделим память под хранение DevMode
     begin
       GetMem(pDevMode, lFlag);
     end;

     //Вызов 2
     //Данный вызов проверяет параметры в FDevMode, чтобы допустить их для изменения
     case ShowDialog of
     true: lFlag := DocumentProperties(FParentWindow, FPrinterHandle, PChar(FPrinterName), pDevMode^, PPrinterInfo2W(FPrinterInfo2W).pDevMode^, DM_IN_PROMPT or DM_OUT_BUFFER or DM_IN_BUFFER);
     false: lFlag := DocumentProperties(0, FPrinterHandle, PChar(FPrinterName), pDevMode^, PPrinterInfo2W(FPrinterInfo2W).pDevMode^, DM_OUT_BUFFER or DM_IN_BUFFER);
     end;

     if Integer(lFlag) < 0 then
     begin
       raise Exception.Create('UpdateProperties error: ' + IntToStr(GetLastError));
       FreeMem(FPrinterInfo2W);
       FPrinterInfo2W := nil;
       FreeMem(pDevMode);
       exit;
     end;

     //Если вызвали диалог, то заберем новые данные
     if ((lFlag = ID_Ok) and (ShowDialog = true)) then
       begin
         FPaperOrientation := pDevMode^.dmOrientation;
         FCopies := pDevMode^.dmCopies;
       end;

     //Здесь меняем данные
     if lFlag = ID_Ok then
     begin
       pDevMode^.dmOrientation := FPaperOrientation;
       pDevMode^.dmCopies := FCopies;

       pDevMode^.dmFields := pDevMode^.dmFields or DM_ORIENTATION;
       pDevMode^.dmFields := pDevMode^.dmFields or DM_COPIES;
     end;

     //Вызов 3
     //Данный вызов проверяет pDevMode, чтобы допустить их для создания DC
     lFlag := DocumentProperties(0, FPrinterHandle, PChar(FPrinterName), pDevMode^, pDevMode^, DM_OUT_BUFFER or DM_IN_BUFFER);

     if Integer(lFlag) < 0 then
     begin
       raise Exception.Create('UpdateProperties error: ' + IntToStr(GetLastError));
       FreeMem(FPrinterInfo2W);
       FPrinterInfo2W := nil;
       FreeMem(pDevMode);
       exit;
     end;

     //...
     PPrinterInfo2W(FPrinterInfo2W).pDevMode^ := pDevMode^;

     //Меняем данные у принтера
     bFlag := SetPrinter(FPrinterHandle, 2, PPrinterInfo2W(FPrinterInfo2W), 0);

     if bFlag = false then
       begin
         raise Exception.Create('SetPrinter error: ' + IntToStr(GetLastError));
         FreeMem(FPrinterInfo2W);
         FPrinterInfo2W := nil;
         FreeMem(pDevMode);
         exit;
      end;

     //...
     FDevMode^ := pDevMode^;
     if pDevMode <> nil then FreeMem(pDevMode);

     //Ориентация бумаги - 1: DMORIENT_PORTRAIT; 2: DMORIENT_LANDSCAPE
     FPaperOrientation := FDevMode.dmOrientation;
     FCopies := FDevMode.dmCopies;

     //Расчет физических характеристик принтера
     UpdatePhysInfo;

     bFlag := ClosePrinter(FPrinterHandle);
     if bFlag = false then
       begin
         raise Exception.Create('ClosePrinter error: ' + IntToStr(GetLastError));
         FreeMem(FPrinterInfo2W);
         FPrinterInfo2W := nil;
         FreeMem(pDevMode);
         exit;
       end;

     FreeMem(FPrinterInfo2W);
     FPrinterInfo2W := nil;

     Result := true;
    end;

  • QAZ © (04.12.17 16:47) [1]
    ну в 10ке накручивают 3д печать, возможно пора последний сдк смотреть
  • dmk © (04.12.17 23:53) [2]
    Код из книги Фень Юаня. Рекомендуемая Майкрософт конструкция. Все работало до последнего обновления. Инфы пока никакой не нашел.
  • dmk © (08.12.17 02:47) [3]
    Разобрался. Перед вызовом надо DataSize обнулять. Иначе считает, что буфер заполнен.
 
Конференция "WinAPI" » Свойства Принтера
Есть новые Нет новых   [134427   +34][b:0][p:0.003]