Форум по программированию Delphi Sources

 


   Сайт  
   Исходники  
   Компоненты  
   Статьи  
   FAQ  
   Поиск по исходникам  
   Футболки  

Вернуться   Форум по программированию Delphi Sources > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 12.07.2017, 22:45
Kotser Kotser вне форума
Прохожий
 
Регистрация: 12.07.2017
Адрес: Москва
Сообщения: 4
Версия Delphi: Delphi 10
Репутация: 10
По умолчанию Как распечатать контент на принтере с точностью до миллиметра?

Хех...
Код:
var PixelsX, PixelsY:integer;
    PrinterCoordX, PrinterCoordY:integer;
begin
   PixelsX:=GetDeviceCaps(printer.Handle, LogPixelsX);
   PixelsY:=GetDeviceCaps(printer.Handle, LogPixelsY);
   PrinterCoordX:=round(PixelsX/25.4*15);
   PrinterCoordY:=round(PixelsY/25.4*11.7);
   image2.Canvas.Rectangle(0,0, PrinterCoordX, PrinterCoordY);

   {Form1.масшатб: poProportional установлен}
   Form1.Print;
end;
Админ: Пользуемся тегами при оформлении кода!

15см на 11.7 см, принтер не печатает прямоугольник с такими размерами. Что я делаю не так?

Последний раз редактировалось Kotser, 12.07.2017 в 23:03.
Ответить с цитированием
  #2  
Старый 13.07.2017, 00:32
Аватар для lmikle
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 6,863
Репутация: 49086
По умолчанию

И не будет, т.к. разрешение и dpi у экрана и принтера разные. Тебе надо картинку рисовать прямо на канве принтера.
Приду домой, если не забуду - скину пример как это делается.
Ответить с цитированием
  #3  
Старый 13.07.2017, 03:09
Аватар для lmikle
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 6,863
Репутация: 49086
По умолчанию

Вот кое какие куски:
Код:
procedure TPrintForm.GetPrinterInfo;

  function GetSizeMM(ALengthPX, AResolutionDPI : Integer) : Integer;
  begin
    Result := Round(ALengthPX / (AResolutionDPI / MM_IN_INCH));
  end;

begin
  // Paper width and height in mm
  FPaperWidthMM := GetDeviceCaps(Printer.Handle,HORZSIZE);
  FPaperHeightMM := GetDeviceCaps(Printer.Handle,VERTSIZE);

  // Horizontal and Vertical resolution
  FHResolutionDPI := GetDeviceCaps(Printer.Handle,LOGPIXELSX);
  FVResolutionDPI := GetDeviceCaps(Printer.Handle,LOGPIXELSY);

  // Paper width and height in pixels
  FPaperWidthPX := GetDeviceCaps(Printer.Handle,PHYSICALWIDTH);
  FPaperHeightPX := GetDeviceCaps(Printer.Handle,PHYSICALHEIGHT);

  // Horizontal and vertical offset in pixels
  FHOffsetPX := GetDeviceCaps(Printer.Handle,PHYSICALOFFSETX);
  FVOffsetPX := GetDeviceCaps(Printer.Handle,PHYSICALOFFSETY);

  // Fill info about printer
  lbPaperSizeVal.Caption := Format('%dx%d mm',[GetSizeMM(FPaperWidthPX,FHResolutionDPI),GetSizeMM(FPaperHeightPX,FVResolutionDPI)]);
  If FHResolutionDPI = FVResolutionDPI
    Then lbResolutionVal.Caption := Format('%d dpi',[FHResolutionDPI])
    Else lbResolutionVal.Caption := Format('%dx%d dpi',[FHResolutionDPI,FVResolutionDPI]);
  Case Printer.Orientation Of
    poPortrait : lbOrientationVal.Caption := 'Portrait';
    poLandscape : lbOrientationVal.Caption := 'Landscape';
    Else lbOrientationVal.Caption := '';
  End;
end;

procedure TSinglePrintForm.PrintContent;
var
  X, Y : Integer;
  ARect : TRect;
  ABitmap : TBitmap;
  AWidthPX, AHeightPX : Integer;
begin
  Try
    Screen.Cursor := crHourGlass;
    ABitmap := TBitmap.Create;
    Try
      AWidthPX := Round(FWidthMM * HResolutionDPI / MM_IN_INCH);
      AHeightPX := Round(FHeightMM * VResolutionDPI / MM_IN_INCH);

      ABitmap.PixelFormat := pf24Bit;
      ABitmap.Width := AWidthPX;
      ABitmap.Height := AHeightPX;

      ABitmap.Canvas.Brush.Color := clWhite;
      ABitmap.Canvas.Brush.Style := bsSolid;
      ABitmap.Canvas.FillRect(Rect(0,0,AWidthPX,AHeightPX));

      Case rgFitMode.ItemIndex Of
        0 : // Fit
          ARect := GetFitDrawRect(AWidthPX,AHeightPX,FGraphic);
        1 : // Crop
          ARect := GetCropDrawRect(AWidthPX,AHeightPX,FGraphic);
        2 : // Stretch
          ARect := Rect(0,0,AWidthPX,AHeightPX);
      End;
      ABitmap.Canvas.StretchDraw(ARect,FGraphic);

      Printer.Title := ExtractFileName(FFileName);
      Printer.BeginDoc;
      Try
        X := Round((PaperWidthPX - AWidthPX)/2);
        Y := Round((PaperHeightPX - AHeightPX)/2);
        BltTBitmapAsDib(Printer.Handle,X,Y,AWidthPX,AHeightPX,ABitmap);

        If cbDrawFrame.Checked Then
          With Printer.Canvas Do
            Begin
              Pen.Color := clBlack;
              Pen.Style := psSolid;
              MoveTo(X,Y);
              LineTo(X+AWidthPX,Y);
              LineTo(X+AWidthPX,Y+AHeightPX);
              LineTo(X,Y+AHeightPX);
              LineTo(X,Y);
            End;
      Finally
        Printer.EndDoc;
      End;
    Finally
      ABitmap.Free;
      Screen.Cursor := crDefault;
    End;
  Except
    On E : Exception Do
      Win7MessageDlg('Error printing image.',E.Message,mtError,[mbOK]);
  End;
end;
Ответить с цитированием
  #4  
Старый 13.07.2017, 15:58
Kotser Kotser вне форума
Прохожий
 
Регистрация: 12.07.2017
Адрес: Москва
Сообщения: 4
Версия Delphi: Delphi 10
Репутация: 10
По умолчанию Спасибо.

Спасибо. Но какой большой код, однако. "кое-какие куски"...
Я думал всё будет проще. Круто.
Ответить с цитированием
  #5  
Старый 13.07.2017, 19:12
Аватар для lmikle
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 6,863
Репутация: 49086
По умолчанию

Ну дык я из проекта просто пару кусочков выдернул.
Там тебе, в основном, можно смотреть где идеи конкретно печать плюс расчет некоторых размеров и как они получаются от принтера.
FWidthMM и FHeightMM - берутся из интерфейса в милиметрах (там выбор из списка или ввод вручную). Остальное - собственно пересчеты и рисование.
Ответить с цитированием
  #6  
Старый 13.07.2017, 23:45
Kotser Kotser вне форума
Прохожий
 
Регистрация: 12.07.2017
Адрес: Москва
Сообщения: 4
Версия Delphi: Delphi 10
Репутация: 10
По умолчанию Спасибо

Ясно. будем грызть)))

Последний раз редактировалось Kotser, 14.07.2017 в 00:07.
Ответить с цитированием
  #7  
Старый 14.07.2017, 11:21
Kotser Kotser вне форума
Прохожий
 
Регистрация: 12.07.2017
Адрес: Москва
Сообщения: 4
Версия Delphi: Delphi 10
Репутация: 10
По умолчанию Засада?

Чуть изменил строчку и принтер напечатал квадрат чётко по нужному размеру:
Код:
PrinterCoordX:=round(96/2.54*15);
PrinterCoordY:=round(96/2.54*11.7);

Цифру 96, чесно-говоря, взял из свойства формы "PixelsPerInch", да еще в инете, часто встречал такое решение.

Но только, чувствую, тут где-то должна быть "засада"?

Последний раз редактировалось Kotser, 14.07.2017 в 11:33.
Ответить с цитированием
  #8  
Старый 14.07.2017, 21:00
Аватар для lmikle
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 6,863
Репутация: 49086
По умолчанию

Засада может всплыть при HiRes. Или при разном разрешении по X и Y на принтере. Я ж не просто так писал всесь этот код, который привел. Он, хочется надеяться, учитывает все приколы.
Ответить с цитированием
  #9  
Старый 15.07.2017, 17:21
Аватар для NumLock
NumLock NumLock сейчас на форуме
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,336
Версия Delphi: 7, XE5
Репутация: 59584
По умолчанию

Вместо 96 есть правильное решение.
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Ответ



Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 14:09.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources", 2004-2017

ВКонтакте   Facebook   Twitter