Графический интерфейс GDI в Microsoft Windows© Александр Фролов, Григорий ФроловТом 14, М.: Диалог-МИФИ, 1993, 288 стр. 6.2. Функция PrintDlgС помощью функции PrintDlg приложение может вывести на экран одну из двух диалоговых панелей, представленных на рис. 6.1 и 6.2, с помощью которых пользователь может напечатать документ, выбрать нужный принтер или изменить его параметры.
Рис. 6.1. Диалоговая панель "Print" В верхней части диалоговой панели "Print" в поле "Printer" указано название принтера, который будет использован для печати. Вы можете выбрать другой принтер, если нажмете кнопку "Setup...". С помощью группы органов управления "Print Range" вы можете выбрать диапазон страниц, которые должны быть распечатаны. Можно распечатать все или отдельные страницы, выделенный фрагмент текста или страницы в указанном диапазоне номеров страниц (поля "From" и "To"). Можно задать качество печати (поле "Print Quality"), указать количество копий (поле "Copies"), выполнить печать в файл (поле "Print to File"). С помощью переключателя "Collate Copies" можно выбрать порядок печати отдельных листов многостраничного документа, который должен быть напечатан в нескольких копиях. Если этот переключатель находится во включенном состоянии, вначале следует напечатать все страницы первой копии, затем - второй, и так далее. Если же этот переключатель выключен, вначале печатается несколько копий первой страницы, затем несколько копий второй страницы и так до конца документа. Последний режим печати удобен для лазерных принтеров, где время подготовки одной страницы для печати больше времени печати готовой страницы. Если нажать на кнопку "Setup...", на экране появится диалоговая панель "Print Setup" (рис. 6.2).
Рис. 6.2. Диалоговая панель "Print Setup" В группе органов управления "Printer" вы можете выбрать для печати либо принтер, принятый по умолчанию ("Default Printer"), либо выбрать другой принтер из списка "Specific Printer". С помощью переключателей группы "Orientation" вы можете выбрать вертикальное ("Portrait") либо горизонтальное ("Landscape") расположение текста на листе бумаги. Группа "Paper" содержит два списка, с помощью которых вы можете выбрать размер бумаги (список "Size") или устройство подачи бумаги ("Source"). Нажав в этой диалоговой панели кнопку "Options...", вы сможете выполнить настройку параметров принтера при помощи диалоговой панели "Options" (рис. 6.3).
Рис. 6.3. Диалоговая панель "Options" для лазерного принтера HP LaserJet III Внешний вид диалоговой панели "Options" зависит от драйвера принтера, так как эта панель формируется функцией DeviceMode или ExtDeviceMode, расположенными в соответствующем драйвере принтера. Для сравнения на рис. 6.4 представлен внешний вид диалоговой панели "Options" для матричного принтера Epson FX-850.
Рис. 6.4. Диалоговая панель "Options" для матричного принтера Epson FX-850 Если вас не устраивает внешний вид диалоговых панелей "Print" и "Print Options", вы можете использовать вместе с функцией PrintDlg свои собственные шаблоны диалоговых панелей. Можно также подключить функцию фильтра для обеспечения дополнительной обработки сообщений. Приведем прототип функции PrintDlg, описанный в файле commdlg.h: BOOL PrintDlg(PRINTDLG FAR* lppd); При успешном завершении функция возвращает значение TRUE. В случае ошибки, отмены печати или отмены выбора принтера (если функция PrintDlg используется только для выбора принтера) функция возвращает значение FALSE. Структура PRINTDLGВ качестве параметра функции PrintDlg необходимо передать адрес предварительно подготовленной структуры типа PRINTDLG , описанной в файле commdlg.h: typedef struct tagPD { DWORD lStructSize; HWND hwndOwner; HGLOBAL hDevMode; HGLOBAL hDevNames; HDC hDC; DWORD Flags; UINT nFromPage; UINT nToPage; UINT nMinPage; UINT nMaxPage; UINT nCopies; HINSTANCE hInstance; LPARAM lCustData; UINT (CALLBACK* lpfnPrintHook)(HWND, UINT,WPARAM,LPARAM); UINT (CALLBACK* lpfnSetupHook)(HWND, UINT,WPARAM,LPARAM); LPCSTR lpPrintTemplateName; LPCSTR lpSetupTemplateName; HGLOBAL hPrintTemplate; HGLOBAL hSetupTemplate; } PRINTDLG; typedef PRINTDLG FAR* LPPRINTDLG; Рассмотрим назначение отдельных полей этой структуры. lStructSizeРазмер структуры PRINTDLG в байтах. Это поле следует заполнить перед вызовом функции PrintDlg. hwndOwnerИдентификатор окна, создавшего диалоговую панель. Если в поле Flags не указано значение PD_SHOWHELP, в поле hwndOwner можно указать NULL. hDevModeИдентификатор глобального блока памяти, содержащего структуру типа DEVMODE, которая используется для инициализации параметров принтера. Если содержимое этого поля указать как NULL, после возвращения из функции PrintDlg поле будет содержать идентификатор глобального блока памяти, заказанного функцией. В этом блоке памяти будет расположена структура DEVMODE, заполненная выбранными параметрами принтера. Структура DEVMODE будет описана позже. hDevNamesИдентификатор глобального блока памяти, содержащего структуру типа DEVNAMES, содержащей три текстовые строки. Первая строка определяет имя драйвера принтера, вторая - имя принтера, и третья - имя порта вывода, к которому подключен принтер. Если содержимое этого поля указать как NULL, после возвращения из функции PrintDlg поле будет содержать идентификатор глобального блока памяти, заказанного функцией для структуры DEVNAMES. В структуре будут находиться строки, соответствующие выбранному принтеру. hDCКонтекст устройства или информационный контекст. Это поле заполняется после возвращения из функции PrintDlg, если в поле Flags указано одно из значений: PD_RETURNDC или PD_RETURNIC. В первом случае возвращается контекст принтера, который можно использовать для печати, во втором - информационный контекст, который можно использовать для получения разнообразной информации о принтере. FlagsЭто поле должно содержать флаги инициализации: PD_ALLPAGES Переключатель "All" в диалоговой панели "Print" должен находиться во включенном состоянии, при этом предполагается что необходимо распечатать весь текст, а не отдельные страницы или выделенный фрагмент текста. PD_SELECTION Переключатель "Selection" в диалоговой панели "Print" должен находиться во включенном состоянии, при этом предполагается что необходимо распечатать выделенный фрагмент текста, но не весь текст или отдельные страницы. PD_PAGENUMS Переключатель "Page" в диалоговой панели "Print" должен находиться во включенном состоянии, при этом предполагается что необходимо распечатать отдельные страницы текста, но не выделенный фрагмент текста или весь текст. PD_NOSELECTION Переключатель "Selection" должен находиться в заблокированном состоянии. PD_NOPAGENUMS Переключатель "Pages" и связанные с ним органы управления должны находиться в заблокированном состоянии. PD_COLLATE Переключатель "Collate" должен находиться во включенном состоянии. PD_PRINTTOFILE Переключатель "Print to File" должен находиться во включенном состоянии. PD_PRINTSETUP При вызове функции PrintDlg вместо диалоговой панели "Print" отображается диалоговая панель "Print Setup". PD_NOWARNING Отмена вывода сообщения о том, что в системе не установлен принтер по умолчанию. PD_RETURNDC Функция PrintDlg должна вернуть в поле hDC идентификатор контекста устройства, который можно использовать для печати. PD_RETURNIC Функция PrintDlg должна вернуть в поле hDC идентификатор информационного контекста, который можно использовать для получения информации о принтере. PD_RETURNDEFAULT После возвращения из функции PrintDlg поля hDevMode и hDevNames будут содержать идентификаторы блоков памяти структур DEVMODE и DEVNAMES, заполненных параметрами принтера, выбранного по умолчанию. Если указан флаг PD_RETURNDEFAULT, перед вызовом функции PrintDlg поля hDevMode и hDevNames должны содержать значения NULL, в противном случае функция вернет признак ошибки. PD_SHOWHELP В диалоговой панели необходимо отобразить кнопку "Help". PD_ENABLEPRINTHOOK Разрешается использовать функцию фильтра для диалоговой панели "Print". PD_ENABLESETUPHOOK Разрешается использовать функцию фильтра для диалоговой панели "Print Setup". PD_ENABLEPRINTTEMPLATE Разрешается использовать шаблон диалоговой панели "Print", определяемой полями hInstance и lpPrintTemplateName. PD_ENABLESETUPTEMPLATE Разрешается использовать шаблон диалоговой панели "Print Setup", определяемой полями hInstance и lpSetupTemplateName. PD_ENABLEPRINTTEMPLATEHANDLE Поле hPrintTemplate содержит идентификатор блока памяти с загруженным шаблоном диалоговой панели "Print". Содержимое поля hInstance игнорируется. PD_ENABLESETUPTEMPLATEHANDLE Поле hSetupTemplate содержит идентификатор блока памяти с загруженным шаблоном диалоговой панели "Print Setup". Содержимое поля hInstance игнорируется. PD_USEDEVMODECOPIES Орган управления "Copies" блокируется, если принтерный драйвер не способен печатать несколько копий. PD_DISABLEPRINTTOFILE Блокируется переключатель "Print to File". PD_HIDEPRINTTOFILE Переключатель "Print to File" блокируется и удаляется из диалоговой панели. nFromPageНачальное значение для инициализации органа управления "From" диалоговой панели "Print". Используется только в том случае, если в поле Flags указан флаг PD_PAGENUMS. Максимальное значение для поля nFromPage составляет 0xfffe. После возвращения из функции PrintDlg это поле содержит номер страницы документа, с которой должна начинаться печать. nToPageНачальное значение для инициализации органа управления "To" диалоговой панели "Print". Используется только в том случае, если в поле Flags указан флаг PD_PAGENUMS. Максимальное значение для поля nFromPage составляет 0xfffe. После возвращения из функции PrintDlg это поле содержит номер страницы документа, до которой должна выполняться печать. nMinPageМинимальное количество страниц, которое можно задать при помощи органов управления "From" и "To". nMaxPageМаксимальное количество страниц, которое можно задать при помощи органов управления "From" и "To". nCopiesЗначение для инициализации органа управления "Copies", если поле hDevMode содержит значение NULL. hInstanceИдентификатор модуля, который содержит шаблоны диалоговых панелей. Используется только в том случае, если указаны флаги PD_ENABLEPRINTTEMPLATE или PD_ENABLESETUPTEMPLATE. lCustDataПроизвольные данные, которые приложение может передать функции фильтра. lpfnPrintHookАдрес функции фильтра для диалоговой панели "Print". lpfnSetupHookАдрес функции фильтра для диалоговой панели "Print Setup". lpPrintTemplateNameАдрес текстовой строки, закрытой нулем, содержащей имя ресурса для шаблона диалоговой панели "Print". Для использования этого поля необходимо указать флаг PD_ENABLEPRINTTEMPLATE. lpSetupTemplateNameАдрес текстовой строки, закрытой нулем, содержащей имя ресурса для шаблона диалоговой панели "Print Setup". Для использования этого поля необходимо указать флаг PD_ENABLESETUPTEMPLATE. hPrintTemplateИдентификатор блока памяти, содержащего предварительно загруженный шаблон диалоговой панели "Print". Для использования этого поля необходимо указать флаг PD_ENABLEPRINTTEMPLATEHANDLE. hSetupTemplateИдентификатор блока памяти, содержащего предварительно загруженный шаблон диалоговой панели "Print Setup". Для использования этого поля необходимо указать флаг PD_ENABLESETUPTEMPLATEHANDLE. Работа с функцией PrintDlgПеред вызовом функции PrintDlg следует проинициализировать нужные поля, записав в остальные поля нулевые значения: memset(&pd, 0, sizeof(PRINTDLG)); pd.lStructSize = sizeof(PRINTDLG); pd.hwndOwner = hwnd; pd.Flags = PD_RETURNDC; fResult = PrintDlg(&pd); Если перед вызовом функции PrintDlg в полях hDevMode и hDevNames было значение NULL, функция заказывает глобальные блоки памяти для структур DEVMODE и DEVNAMES, заполняя их перед возвратом управления. Структура DEVMODE определена в файле print.h, который находится в каталоге include системы разработки Borland Turbo C++ for Windows: typedef struct tagDEVMODE { char dmDeviceName[CCHDEVICENAME]; UINT dmSpecVersion; UINT dmDriverVersion; UINT dmSize; UINT dmDriverExtra; DWORD dmFields; int dmOrientation; int dmPaperSize; int dmPaperLength; int dmPaperWidth; int dmScale; int dmCopies; int dmDefaultSource; int dmPrintQuality; int dmColor; int dmDuplex; int dmYResolution; int dmTTOption; } DEVMODE; typedef DEVMODE* PDEVMODE, NEAR* NPDEVMODE, FAR* LPDEVMODE; Эта структура содержит разнообразную информацию о конфигурации и параметрах принтера. Она подробно описана в документации, которая поставляется вместе с SDK. Из за ограниченного объема книги мы приведем краткое описание полей этой структуры.
Структура DEVNAMES , как мы уже говорили, содержит имя драйвера, имя принтера и имя порта вывода, к которому подключен принтер: typedef struct tagDEVNAMES { UINT wDriverOffset; UINT wDeviceOffset; UINT wOutputOffset; UINT wDefault; } DEVNAMES; typedef DEVNAMES FAR* LPDEVNAMES; Первые три слова структуры содержат смещения текстовых строк с именами, соответственно, драйвера, принтера и порта вывода. Строки расположены в памяти непосредственно за структурой DEVNAMES. Поле wDefault может содержать флаг DN_DEFAULTPRN , в этом случае все три строки описывают принтер, выбранный по умолчанию. Вы можете подготовить свои значения для двух описанных выше структур, заказать глобальные блоки памяти и передать их идентификаторы функции PrintDlg, записав в соответствующие поля структуры PRINTDLG. После возврата из функции PrintDlg необходимо освободить эти блоки памяти, взяв их идентификаторы из полей hDevMode и hDevNames структуры PRINTDLG. Учтите, что функция PrintDlg может изменить значения последних двух полей, поэтому надо освобождать блоки памяти с идентификаторами, взятыми из структуры PRINTDLG после возврата из функции PrintDlg: if(pd.hDevMode != 0) GlobalFree (pd.hDevMode); if(pd.hDevNames != 0) GlobalFree (pd.hDevNames); Если перед вызовом функции PrintDlg вы указали флаги PD_RETURNDC или PD_RETURNIC, после возврата поле hDC будет содержать, соответственно, идентификатор контекста устройства или идентификатор информационного контекста: if(fResult) return pd.hDC; else return NULL; |