Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Можно ли создать контекст (DC) с кастомным DPI?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 4960
Все из-за печати RTF на принтер. Принтера может и не быть, тогда надо сохранить битмап с изображением листа.
Я тут накропал по-быстрому функцию, которая создает битмап с нужным DPI.
Проблема в том, что RichEdit, когда "печатает" в битмап, использует заданный контекст ABitmapDC, который с 96 пикселей на дюйм, ибо берется от дисплея. А я хочу печатать с произвольным DPI.

Мне нужно получить контекст "чего-угодно-сам-пока-не-знаю-чего", где я выставлю DPI руками. Это возможно?


procedure MakeBitmap(AWidth, AHeight, ADPI: Integer; var ABitmapHandle: HBITMAP; var ABitmapDC: HDC);
var
  Bits: PRGBQuad;
  BitsPtr: Pointer;
  PPM: Integer;
  BitmapInfo: TBitmapInfo;
begin
  PPM := Round((ADPI * 10000.0) / 254.0);
  ABitmapDC := CreateCompatibleDC(0);
  BitmapInfo.bmiHeader.biSize := SizeOf(BITMAPINFOHEADER);
  BitmapInfo.bmiHeader.biWidth := AWidth;
  BitmapInfo.bmiHeader.biHeight := AHeight;
  BitmapInfo.bmiHeader.biPlanes := 1;
  BitmapInfo.bmiHeader.biBitCount := 32;
  BitmapInfo.bmiHeader.biCompression := BI_RGB;
  BitmapInfo.bmiHeader.biSizeImage := 0;
  BitmapInfo.bmiHeader.biXPelsPerMeter := PPM;
  BitmapInfo.bmiHeader.biYPelsPerMeter := PPM;
  BitmapInfo.bmiHeader.biClrUsed := 0;
  BitmapInfo.bmiHeader.biClrImportant := 0;
  BitsPtr := Addr(Bits);
  ABitmapHandle := CreateDIBSection(ABitmapDC, BitmapInfo, DIB_RGB_COLORS, BitsPtr, 0, 0)
end;


When a movie is over, it's a black
11 янв 17, 16:59    [20094764]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 43382

Квейд
Мне нужно получить контекст "чего-угодно-сам-пока-не-знаю-чего", где я выставлю DPI
руками. Это возможно?

Используй CreateDC вместо CreateCompatibleDC.

Posted via ActualForum NNTP Server 1.5

11 янв 17, 17:27    [20094888]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 4960
Объясню, что у меня не получается.

Я "рендерю" RTF в битмап, это делается путем отправки сообщения компоненту RichEdit:

Result := SendMessage(ARichEditHandle, EM_FORMATRANGE, 1, Longint(@Range));


При этом заполняю структуру Range типа TFormatRange, где, среди прочего, есть такие поля:

TFormatRange = FORMATRANGE;
//...
 FORMATRANGE = record
    hdc: HDC;  // Это контекст, куда мы "рендерим", в нашем случае канва битмапа
    hdcTarget: HDC; //Это контекст, откуда берутся параметры для "рендеринга", в том числе DPI



Так вот, если в hdcTarget указать DC "настоящего" принтера, который печатает 200 точек на дюйм, то в битмапе получится изображение, отформатированное под 200 точек на дюйм.

Так вот, представим, что принтера нет в наличии, а пользователь хочет битмап с 200 точек на дюйм.
Если в hdcTarget передать нечто вроде GetDC(0), то получим DPI экрана, 96 точек на дюйм.

Так вот, можно ли создать DC некоего "несуществующего физически устройства" или хоть черта лысого (простите), но в котором я выставлю эти 200 точек на дюйм программно?
11 янв 17, 17:57    [20095025]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 4960
У CreateDC параметром передается структура lpInitData, где DPI можно указать программно, выставив поля dmPelsWidth и dmPelsHeight. Но для какого "устройства" вызвать эту функцию?
11 янв 17, 18:01    [20095043]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 43382

Квейд
Но для какого "устройства" вызвать эту функцию?

Я бы для начала попробовал nil, nil.

Posted via ActualForum NNTP Server 1.5

11 янв 17, 18:17    [20095106]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 4960
Dimitry Sibiryakov
Квейд
Но для какого "устройства" вызвать эту функцию?

Я бы для начала попробовал nil, nil.
Первым параметром тоже nil?
11 янв 17, 18:23    [20095138]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 43382

Квейд
Первым параметром тоже nil?

Да. Хотя скорее всего это приведёт к ошибке.

Вот, нагуглилось: https://www.codeproject.com/Articles/224754/Guide-to-Win-Memory-DC

Posted via ActualForum NNTP Server 1.5

11 янв 17, 18:44    [20095214]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 5926
Квейд,

кстати, RichEdit можно не только в Bitmap переводить, но и в Metafile. Не знаю, правда, что лучше. Но это векторный формат (нагуглился пример кода).
11 янв 17, 18:48    [20095227]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 4960
Я вроде как нашел обходной способ, без "создания кастомного DC", через zoom.
То бишь, если надо отрендерить RTF как 200 DPI, то я пересчитываю коэффициент zoomfactor и "рендерю" согласно примеру кода.

На тестовом примере, который выложил автор, это работает. Пока разбираюсь с деталями.
http://www.delphigroups.info/2/5/312892.html
11 янв 17, 19:01    [20095265]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 4960
Кроик Семён
Квейд,

кстати, RichEdit можно не только в Bitmap переводить, но и в Metafile. Не знаю, правда, что лучше. Но это векторный формат (нагуглился пример кода).
Спасибо, тоже попробую.
11 янв 17, 19:01    [20095266]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Соколинский Борис
Member

Откуда: Москва
Сообщений: 6317
Кроик Семён
кстати, RichEdit можно не только в Bitmap переводить, но и в Metafile.
Не можно, а нужно.
В Bitmap-ах DPI вообще роли не играет, там достаточно коэффициенты анизотропного вывода подобрать. При этом
а) картинка будет немерянного размера.
б) при печати все равно будут искажения (шрифты, тонкие линии и т.п.)
11 янв 17, 20:10    [20095461]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 5926
тема заинтересовала

создал тестовый RTF файл и EMF из него (прикладываю)

воспользовался кодом по моей ссылка. Он, правда, начинает бесконечное число файлов генерить, нам нужен первый.

заметно, что нарушены пропорции, но это уже другой вопрос.
но буквы гладкие и хорошо масштабируются

К сообщению приложен файл (test.zip - 19Kb) cкачать
11 янв 17, 21:10    [20095705]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 5926
P.S.
и, кстати, почему вообще про Metafile вспомнил: копался как то в коде, если не путаю, FastReport'a, так там RichEdit перед печатью предварительно в промежуточный Metafile конвертируют
11 янв 17, 21:15    [20095727]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
asviridenkov
Member

Откуда:
Сообщений: 3693
Кроик Семён,

Текст в метафайле при масштабировании, это одна сплошная боль.
11 янв 17, 21:25    [20095763]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 4960
Соколинский Борис
Кроик Семён
кстати, RichEdit можно не только в Bitmap переводить, но и в Metafile.
Не можно, а нужно.
У меня код крутится под вайном, сходу не вспомню, но были проблемы при печати метафайлов, а с битмапами все пучком.
11 янв 17, 23:06    [20096107]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
kealon(Ruslan)
Member

Откуда: Нижневартовск
Сообщений: 1896
Квейд,

я просто SetWorldTransform использовал для масштабирования


PS: в bmp(dib) есть соответствующая инфа о dpi (например Paint хорошо с ней работает и битмап выводит правильно)
 m_lpBMIH.biXPelsPerMeter:=DPI.cx*315 div 8;
 m_lpBMIH.biYPelsPerMeter:=DPI.cy*315 div 8;
12 янв 17, 08:29    [20096627]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 4960
kealon(Ruslan)
Квейд,

я просто SetWorldTransform использовал для масштабирования



А у тебя нету примера? Я тут попробовал нарисовать красный квадратик 50х50, и ожидал изменения масштаба в два раза.
Однако, все рисуется один к одному. ЧЯДНТ?

var
  M: TXForm;
  B: Tbitmap;
begin
  FillChar(M, SizeOf(M), 0);
  M.eM11 := 2;
  M.eM22 := 2;

  B := TBitmap.Create;
  B.PixelFormat := pf32bit;
  B.SetSize(300, 300);

  SetWorldTransform(B.Canvas.Handle, M);

  B.Canvas.Brush.Color := clRed;
  B.Canvas.FillRect(Rect(0, 0, 50, 50));

  B.SaveToFile('D:\transform.bmp');
13 янв 17, 15:26    [20103351]     Ответить | Цитировать Сообщить модератору
 Re: Можно ли создать контекст (DC) с кастомным DPI?  [new]
Noskov
Member

Откуда: Москва
Сообщений: 390
https://msdn.microsoft.com/ru-ru/library/windows/desktop/dd145104(v=vs.85).aspx
The SetWorldTransform function will fail unless the graphics mode for the given device context has been set to GM_ADVANCED by previously calling the SetGraphicsMode function.
13 янв 17, 17:04    [20103853]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить