Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как напечатать файл HTML?  (Прочитано 15566 раз)
0 Пользователей и 8 Гостей смотрят эту тему.
jur
Помогающий

lt
Offline Offline

« : 02-05-2017 12:42 » 

Привет!

Да здравствует фирма Микрософт, никогда не дающая нам расслабиться и утратить тонус! :-)

Все было хорошо до недавних пор. Я как раз успел расслабиться - ан нет! В 10-й Винде (на некоторых компьютерах) моя старая приборная программа перестала печатать файлы HTML, которые я подготавливаю в программе. Они очень простые: картинка, несколько строк текста и все. Теперь стало выскакивать окошко с ошибкой:

"This file does not have a program associated with it for performing this action. Please install a program or, if one is already installed, create an association in the Default Programs control panel."

Ассоциации на месте (HTM и HTML привязаны к Firefox). Печатаю посредством ShellExecuteEx указав:
lpExecInfo.lpVerb = "print";
и
lpExecInfo.lpFile = "C:\1my\_Work\Temp\tmp_report.html"

А ведь все было так хорошо...

Покопавшись в Интернете я начал осознавать, что масленица коту закончилась... Нужно делать печать "по-взрослому". Но как?! Для моего случая, как ни странно, ничего не нашел.

Вот моя среда разработки:
- Windows 10 x64 и x86 (на двух компах)
- Visual Studio 2008 (более новые пробую по чуть-чуть, но полностью удовлетворяет и эта)
- Модуль для печати - самая обычная DLL-ка, никаких MFC или CLR, просто C++
- Проект под x86

Микрософт по этому поводу говорит следующее: "Используй XPS Print API", а на соответствующей странице еще страшнее: "[The XPS Print API is not supported and may be altered or unavailable in the future. Client applications should use the Print Document Package API instead.]".

Помогите, пожалуйста, с наименьшими кровопотерями решить эту, в общем-то несложную, задачу! Может кто знает простой класс или простой и доходчивый пример?

Спасибо!

P.S. В другой DLL-ке я печатаю на принтере картинку - никаких проблем. В этом случае я просто использую WinGDI.
Записан

MPEG-4 - в массы!
Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 02-05-2017 17:02 » 

А конечная цель в чём? Судя по названию файла, печатается какой-то отчёт. Если так, то я сейчас поступаю так: формирую макет для отчёта в виде файла EMF. Затем, изменяющиеся элементы прибавляю к нему, используя WINAPI GDI, далее вывожу итог на печать.

Надо отметить, что меня тоже мучает поиск надёжной системы отображения и печати.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 02-05-2017 20:53 » 

В составе VS входит CrystalReports — гибкая система создания отчетов. Стандартный источник для отчетов - БД, но API позволяет ввести данные напрямую. Я через нее печатал на принтер, экспортировал в PDF и XLS.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
jur
Помогающий

lt
Offline Offline

« Ответ #3 : 03-05-2017 06:00 » 

А конечная цель в чём? Судя по названию файла, печатается какой-то отчёт.

Да, именно так. Я наделал много разных HTML-заготовок (шаблонов), заменяю в них нужные поля (картинка, текст с результатами измерений и т.п.) и сохраняю во временный файл "tmp_report.html". Далее я просто распечатываю этот файл на принтере. Все легко и просто. И подправить, если что, можно прямо в простейшем текстовом редакторе. Захотел, к примеру, врач уменьшить картинку в два раза - просто пишет в шаблоне: width="50%".

Если так, то я сейчас поступаю так: формирую макет для отчёта в виде файла EMF. Затем, изменяющиеся элементы прибавляю к нему, используя WINAPI GDI, далее вывожу итог на печать.

Глянул я на этот формат. Он, зараза, двоичный... Замучаешься заготовки делать, а уж что-то в них корректировать - просто невозможно (без соответствующей программы). Правильно я про Микрософт сказал: по их мнению гораздо интереснее на лыжах, в гамаке и с аквалангом! :-)

В составе VS входит CrystalReports — гибкая система создания отчетов. Стандартный источник для отчетов - БД, но API позволяет ввести данные напрямую. Я через нее печатал на принтер, экспортировал в PDF и XLS.

Мне бы попроще чего-нибудь... Ведь не может быть, чтобы нельзя было просто и элементарно распечатать HTML-файл!

Записан

MPEG-4 - в массы!
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #4 : 03-05-2017 09:03 » new

Мне бы попроще чего-нибудь... Ведь не может быть, чтобы нельзя было просто и элементарно распечатать HTML-файл!

А тогда зачем заморачиваться?

Начнём с того, что Ваша программа НИКОГДА САМА не печатала HTML.
Печатаю посредством ShellExecuteEx указав:
lpExecInfo.lpVerb = "print";
и
lpExecInfo.lpFile = "C:\1my\_Work\Temp\tmp_report.html"

А то, что при новой инсталляции изменяются ассоциации типов с приложениями, так при чём здесь микрософт? Пользователь сам может их изменить. У меня, например, они ассоциированы с текстовым редактором.

То, что
Ассоциации на месте (HTM и HTML привязаны к Firefox).

ещё ничего не значит. Ассоциация для печати не выполнена или ошибочна, о чём собственно и говорит сообщение
Цитата
This file does not have a program associated with it for performing this action.

Надо посмотреть, что делает ассоциативный с HTML print и, либо поменть его, либо (что предпочтительней) использовать его сторочку. Например в 10-ке

* ss1.png (13.99 Кб - загружено 1565 раз.)
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
jur
Помогающий

lt
Offline Offline

« Ответ #5 : 03-05-2017 10:50 » 

Наконец-то! Как там у Архимеда? Эврика? Вот она и есть! :-)

А то, что при новой инсталляции изменяются ассоциации типов с приложениями, так при чём здесь микрософт? Пользователь сам может их изменить. У меня, например, они ассоциированы с текстовым редактором.

Так-то оно так, но прокопавшись полтора дня я так и не нашел этой информации. У Честертона отец Браун хорошо сказал: "Где нужно прятать лист? В лесу." Это он стопудово про Интернет... :-)

На stackoverflow.com вообще кошмар, отвечают на все, что угодно, кроме того, о чем ты спросил :-) Впрочем, на многих других сайтах не лучше...

Ассоциации на месте (HTM и HTML привязаны к Firefox).

ещё ничего не значит. Ассоциация для печати не выполнена или ошибочна, о чём собственно и говорит сообщение
Цитата
This file does not have a program associated with it for performing this action.

Так сообщение-то я понял, но где это настраивается - не нашел...

Надо посмотреть, что делает ассоциативный с HTML print и, либо поменть его, либо (что предпочтительней) использовать его сторочку.

Точно! Именно это я и обнаружил в одном из ответов на вышеупомянутом сайте ( я его больше критиковать не буду! :-) ). Сделал - работает. Просто, доступно и почти ничего править не пришлось.

Весь Интернет ломится от подобных вопросов. Поэтому привожу образец моего кода. Возможно он кому-нибудь поможет.
Код:
/*
  From: http://stackoverflow.com/questions/16604844/shellexecute-print

  Thank you David, works excellent, just as expected!
  sprintf(sfile, "%s%s%s%s", "mshtml.dll,PrintHTML \"", cwd, afile, "\"");
  ShellExecute(NULL, "open", "rundll32.exe", sfile, NULL, SW_SHOWNORMAL);
 */
void Print_Report_to_Printer()
{
  CString sfile;

  sfile.Format("mshtml.dll,PrintHTML \"%s\"", Path_report_tmp);  // Path_report_tmp вроде такого: "C:\Temp\tmp_report.html"

  SHELLEXECUTEINFO ShExecInfo = { 0 };

  ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
  ShExecInfo.fMask  = SEE_MASK_NOCLOSEPROCESS;
  ShExecInfo.lpVerb = "open";
  ShExecInfo.lpFile = "rundll32.exe";
  ShExecInfo.lpParameters = sfile;
  ShExecInfo.nShow  = SW_SHOWNORMAL;

  if( ShellExecuteEx(&ShExecInfo) ) {
    if( ShExecInfo.hProcess ) {
      WaitForSingleObject(ShExecInfo.hProcess, INFINITE);  // Жду завершения диалога печати
      CloseHandle( ShExecInfo.hProcess );
    }
  }
  else {
    UtilsR1_ShowLastErrorMessage("Print_Report_to_Printer() error");  // Показывает пояснительный текст последней ошибки
  }
}

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

P.S. Спасибо друзья! Вы меня здорово подтолкнули в поисках решения! Оказалось, что все не просто, а очень просто. Как у Е. Айсберга :-)
« Последнее редактирование: 03-05-2017 10:54 от jur » Записан

MPEG-4 - в массы!
Aether
Специалист

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 03-05-2017 10:53 » 

Все легко и просто. И подправить, если что, можно прямо в простейшем текстовом редакторе. Захотел, к примеру, врач уменьшить картинку в два раза - просто пишет в шаблоне: width="50%".
Вот это, зря, другой специалист, будь то врач, пекарь, токарь, не обязан знать внутреннее устройство формата. Если требуется распечатать отдельно, например, снимок в формате А0, то хорошо бы сделать такую кнопочку.

Глянул я на этот формат. Он, зараза, двоичный... Замучаешься заготовки делать, а уж что-то в них корректировать - просто невозможно (без соответствующей программы).
А то, нормальный векторный формат. Сохранение в него и его чтение производится программистом при помощи готовых функций WINAPI, например:
GetEnhMetaFile()
https://msdn.microsoft.com/en-us/library/windows/desktop/dd144880(v=vs.85).aspx
PlayEnhMetaFile()
https://msdn.microsoft.com/en-us/library/windows/desktop/dd162800(v=vs.85).aspx

EMF шаблоны я создаю преимущественно средствами CAD.

Если будет цель в создании полноценного печатающего приложения, то я бы начал изучение с того, как происходит рисование в Windows. Затем, перешёл бы к изучению печати, настройкам принтера и диалогу печати.
Записан
jur
Помогающий

lt
Offline Offline

« Ответ #7 : 03-05-2017 11:02 » 

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

Все верно. Но я смотрю с точки зрения реальной жизни. Позвонил врач из Бангладеш, просит: "Мне бы картинку уменьшить чуток...". Нет ничего легче, чем сказать: "Открой в Блокноте файл шаблона такой-то и в строчке такой-то исправь "width="512"" на "width: 75%"" (просто пример). Так гораздо меньше мороки, проверено.

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

Так я-ж в первом посте написал, что печатаю на принтере картинку с текстами, все нормально, никаких проблем.

« Последнее редактирование: 03-05-2017 11:05 от jur » Записан

MPEG-4 - в массы!
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #8 : 03-05-2017 14:15 » 

Сделал - работает. Просто, доступно и почти ничего править не пришлось.

Весь Интернет ломится от подобных вопросов. Поэтому привожу образец моего кода. Возможно он кому-нибудь поможет.

Только опять прежние грабли. А если в след. версии опять что-то изменится?

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

Находится в два приёма:

1. в HKEY_CLASSES_ROOT ищем расширение файла, например .html и смотрим стандартное значение (грубо говоря ник) - это htmlfile

2. в HKEY_CLASSES_ROOT\<ник> ищем подключ \shell\print\command и используем его стандартное значение в программе
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
jur
Помогающий

lt
Offline Offline

« Ответ #9 : 04-05-2017 10:52 » 

Только опять прежние грабли. А если в след. версии опять что-то изменится?

С Микрософтом все может быть! :-)

Собственно под "посмотреть" я имел ввиду "получить из реестра код печати для данного типа файла". Те не кодить строчку жёстко, а "читать" то, что настроено в реестре.
Находится в два приёма:
1. в HKEY_CLASSES_ROOT ищем расширение файла, например .html и смотрим стандартное значение (грубо говоря ник) - это htmlfile
2. в HKEY_CLASSES_ROOT\<ник> ищем подключ \shell\print\command и используем его стандартное значение в программе

Темное это дело... Под ключом [HKEY_CLASSES_ROOT\.html] лежат:

[HKEY_CLASSES_ROOT\.html\OpenWithProgids]
[HKEY_CLASSES_ROOT\.html\PersistentHandler]

С какими-то неудобоваримыми значениями.

Под ключом [HKEY_CLASSES_ROOT\htmlfile] тоже что-то не то:

[HKEY_CLASSES_ROOT\htmlfile\shell\Print\command]
@="\"C:\\Program Files (x86)\\Microsoft Office\\Office12\\msohtmed.exe\" /p %1"

А вот в ветке ...printto похоже на правду:

[HKEY_CLASSES_ROOT\htmlfile\shell\printto\command]
@="\"C:\\WINDOWS\\system32\\rundll32.exe\" \"C:\\WINDOWS\\system32\\mshtml.dll\",PrintHTML \"%1\" \"%2\" \"%3\" \"%4\""

Что-то такое можно сообразить. Кстати, а почему ShellExecuteEx с вербом "print" не рОбит? Ведь указано же что с этим файлом делать, как печатать!

В этой связи возникает новый вопрос: как на этапе компиляции узнать, под Виндой какой разрядности я работаю? Т.е. не TARGET (который 32 или 64 бита), а именно разрядность Винды. Че-то я этого никак не найду...

Спасибо за помощь, друзья!

P.S. Хм... Я тут подумал, а какая нафик разница, под какой Виндой идет компиляция? Да хоть под 8-битной! Или в Линуксе каком-нить кросс-компилером. Важно подо что, под какую разрядность. Хотя соответствующий макрос про Винду тоже полезно было бы узнать...
« Последнее редактирование: 04-05-2017 14:53 от jur » Записан

MPEG-4 - в массы!
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #10 : 04-05-2017 22:56 » 

Кстати, а почему ShellExecuteEx с вербом "print" не рОбит? Ведь указано же что с этим файлом делать, как печатать!

Как всё запущено... Жаль Учите матчасть. Кто такая фантастическая ShellExecute, которая каким-то волшебным образом может сделать ВСЁ: открыть любой файл, распечатать его (может ваще тогда другие программы не нужны, раз есть такая волшебница)? Как это работает, если в Проводнике кликнуть на файл правой кнопкой и в контекстном меню выбрать a la Печатать, Открыть и тп? Да просто щёлкнуть два раза по файлу? И зачем эти ключи в реестре? И как они со всем этим связаны? Но начать лучше с вопроса: что такое Shell?
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
darkelf
Молодой специалист

ua
Online Online

« Ответ #11 : 05-05-2017 08:41 » 

P.S. Хм... Я тут подумал, а какая нафик разница, под какой Виндой идет компиляция? Да хоть под 8-битной! Или в Линуксе каком-нить кросс-компилером. Важно подо что, под какую разрядность. Хотя соответствующий макрос про Винду тоже полезно было бы узнать...
Код: (C)
#ifdef _WIN64
/*put some code there*/
#endif
не оно?
Записан
jur
Помогающий

lt
Offline Offline

« Ответ #12 : 05-05-2017 14:54 » 

Как всё запущено... :( Учите матчасть. Кто такая фантастическая ShellExecute, которая каким-то волшебным образом может сделать ВСЁ: открыть любой файл, распечатать его (может ваще тогда другие программы не нужны, раз есть такая волшебница)? Как это работает, если в Проводнике кликнуть на файл правой кнопкой и в контекстном меню выбрать a la Печатать, Открыть и тп? Да просто щёлкнуть два раза по файлу? И зачем эти ключи в реестре? И как они со всем этим связаны? Но начать лучше с вопроса: что такое Shell?

Знамо запущено! :-) Для всего на свете места "на чердаке" может и не хватить. Не сомневаюсь, что про Shell написано очень много полезного и интересного, но мне-то это зачем? Мои задачи довольно просты. Просто в кои-то веки понадобилось напечатать HTML-файл и все. К тому же мне непонятно, чего этому ShellExecute еще нужно, если ключи в реестре говорят, как следует печатать этот файл? А в хелпе по этой команде ничего полезного по ее применению (как в моем случае) не говорится. "Куда крестьянину податься?..." (С) Впрочем, хоть и не на все последующие века, но хотя бы на годы вперед я проблему решил :-)

Код: (C)
#ifdef _WIN64
/*put some code there*/
#endif
не оно?

Так оно-ж, зараза, похоже только к таргету относится. Да и то, нужно самому ручками прописывать в обоих опциях компилирования (Debug/Release). А у меня выскочила такая смешная проблема:

#define COMPILE_UNDER_WIN64   0
#if COMPILE_UNDER_WIN64
  #include "C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\dsound.h"
  #pragma comment(lib,"C:\\Program Files (x86)\\Microsoft DirectX SDK (June 2010)\\Lib\\x86\\dsound.lib")
#else
  #include "C:\Program Files\Microsoft DirectX SDK (June 2010)\Include\dsound.h"
  #pragma comment(lib,"C:\\Program Files\\Microsoft DirectX SDK (June 2010)\\Lib\\x86\\dsound.lib")
#endif

Приходится вручную корректировать макрос "COMPILE_UNDER_WIN64". Тут выходит без разницы, что мой макрос, что эту _WIN64. Ее даже хуже, т.к. нужно нудно лезть в конфигурфцию проекта и править в двух местах. А так только в одном, и заметно ближе :-) (Дело в том, что тот же самый проект я компилирую то на одном компе (64-битовом), то на другом (32-битовом). Исправлять "0" на "1" не сложно, конечно, но достаточно лениво :-) )
Записан

MPEG-4 - в массы!
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines