Сімейства шрифтів у Windows

[ виправити ] текст може містити помилки, будь ласка перевіряйте перш ніж використовувати.

скачати

1. Сімейства шрифтів у Windows
По трьох із розглянутих ознак (ширина штриха, ширина символів і наявності зарубок) в Windows прийнято виділяти так звані сімейства шрифтів. Для того, що б пояснити різницю між прийнятими сімействами, наведемо невелику табличку, що містить зведення характеристик різних родин шрифтів у Windows:
Сімейство
Ширина штриха
Ширина символів
Наявність засічок
приклади
MODERN
постійна
постійна
-
Courier New
ROMAN
мінлива
мінлива
є
Times New Roman, Antiqua, Garamond, Palatino, Bodoni
SWISS
мінлива
мінлива
немає
Arial, Helvetica, Futura, Avantgarde, Optima, Swiss
SCRIPT
-
-
-
Script, Odessa Script FWF, Decor, Jikharev, Parsek
DECORATIVE
-
-
-
Windings, MusicalSymbols, Symbol
DONTCARE
-
Зазвичай до сімейства MODERN відносять всі шрифти фіксованої ширини. Назва MODERN вказує на порівняно недавню історію цих шрифтів - вони набули поширення з розвитком друкарської техніки і комп'ютерів, тоді як інші види шрифтів виникали з XV століття, коли закінчувалася епоха готичного шрифту.
У ті часи починав формуватися шрифт, схожий за своїм накресленню на один з найдавніших шрифтів - римський капітальний. Це був пропорційний шрифт із зарубками і нормальної контрастністю, пізніше він отримав дуже широке поширення в друкарському справі і дожив до наших днів. За свою довгу історію він багаторазово видозмінювався і став родоначальником великого числа поколінь шрифтів. У Windows такі шрифти відносяться до сімейства ROMAN.
Реально цього сімейства відповідає дуже велике число різних шрифтів, що виділяються в інших класифікаційних системах. Зокрема, можна виділити так звані брускові шрифти, звичайно зі слабо вираженим контрастом і зарубками, перпендикулярними штрихами і мають приблизно таку ж ширину (приклад - Courier); У XX столітті виникли шрифти, отримали дуже широке поширення. Найбільш поширена назва для цих шрифтів - рубані. Ці шрифти не мають контрасту і зарубок (sans serif), в Windows їм відповідає сімейство SWISS. Сімейство DONTCARE реально не відповідає ніякий групі шрифтів. Воно використовується тільки за умов згадування, з якого сімейства треба вибирати шрифт - при цьому воно позначає "будь-яке сімейство".
1.1 Стандартні шрифти Windows
У стандартному постачанні Windows присутній невеликий набір шрифтів, що представляє всі (визначені у Windows) сімейства шрифтів. Цей набір включає в себе растрові, векторні та TrueType шрифти, інформація про які зведена в невелику таблицю:
Ім'я шрифту
сімейство
кодова таблиця
файл (и)
растрові шрифти
System
SWISS
ANSI
xxx SYS.FON
FixedSys
DONTCARE
ANSI
xxx FIX.FON
Terminal
MODERN
OEM
xxx OEM.FON
Courier
MODERN
ANSI
COUR y. FON
MS Sans Serif
SWISS
ANSI
SSERIF y. FON
MS Serif
ROMAN
ANSI
SERIF y. FON
Small Fonts
ROMAN
ANSI
SMALL y. FON
Symbol
DECORATIVE
SYMBOL
SYMBOL y. FON
векторні шрифти
Modern
MODERN
OEM
MODERN.FON
Roman
ROMAN
OEM
ROMAN.FON
Script
SCRIPT
OEM
SCRIPT.FON
TrueType
Arial
SWISS
ANSI
ARIAL zz. TTF (. FOT)
Courier New
MODERN
ANSI
COUR zz. TTF (. FOT)
Times New Roman
ROMAN
ANSI
TMSRMN.TTF (. FOT)
Windings
DONTCARE
ANSI
WINDINGS.TTF (. FOT)
У цій таблиці слід уважно розглянути імена файлів. У цих іменах маленькими літерами (xxx, y, zz) позначені змінюються частини.
Так xxx означає пристрій, для якого був спроектований шрифт. Замість цієї послідовності реально написано CGA, EGA, VGA або 8514.
Символ y позначає категорію пристроїв, до якої належить цей шрифт. Можливі значення можна знайти в таблиці:
Буква
Співвідношення сторін
Роздільна здатність X / Y (пікселів / дюйм)
Пристрій
A
200
96/48
CGA
B
133
96/72
EGA
C
83
60/72
Okidata printers
D
167
120/72
IBM, Epson printers
E
100
96/96
VGA
F
100
120/120
IBM 8514
Послідовність zz вказує, якого типу шрифт описаний в цьому файлі: нормальний (порожня послідовність), жирний BD, похилий I або жирний похилий BI.
1.2 Отримання хендла шрифту
Для того, що б Ви могли застосовувати шрифт у Вашій програмі, Ви повинні спочатку отримати хендл відповідного шрифту. Шрифт є об'єктом GDI, тому робота з ним схожа на роботу з іншими об'єктами GDI. Як правило ви повинні виконати наступні дії:
отримати хендл або стандартного шрифту, або створивши "новий" шрифт
При створенні "нового" шрифту створюється відповідний об'єкт GDI, а не новий файл опису шрифту.
вибрати шрифт у контекст пристрою
здійснити вивід, використовуючи поточний шрифт
якщо шрифт був створений, то його треба знищити.
Створення шрифтів займає деякий час (особливо для відображення TrueType шрифтів - Windows автоматично генерує проміжний растровий шрифт, який і використовується при виведенні). Якщо треба створювати шрифти, то це зручно робити при створенні вікна або навіть під час запуску програми, а знищувати - при закритті вікна або при завершенні програми (як і всі об'єкти GDI, створений шрифт знищується за допомогою функції DeleteObject).
Якщо Вам треба отримати хендл стандартного шрифту, то Ви можете скористатися функцією:
HFONT GetStockObject (nIndex);
Параметр nIndex може бути:
ANSI_FIXED_FONT
відповідає шрифту Courier
ANSI_VAR_FONT
відповідає шрифту MS Sans Serif
OEM_FIXED_FONT
відповідає шрифту Terminal
SYSTEM_FONT
відповідає шрифту System; цей шрифт використовується за умовчанням
SYSTEM_FIXED_FONT
відповідає шрифту FixedSys; До версії Windows 3.0 системний шрифт був фіксованої ширини, він включений в Windows 3.1 для сумісності.
DEVICE_DEFAULT_FONT
відповідає шрифту, завантаженому в пристрій; для дисплея не визначено

Якщо Вам треба створювати власний шрифт, то Ви можете скористатися однією з двох функцій:
HFONT CreateFont (
nHeight, nWidth, nEscapement, nOrientation, nWeight,
bItalic, bUnderline, bStrikeOut,
bCharSet, bOutputPrecision, bClipPrecision, bQuality, bPitchAndFamily,
lpszFacename);
або
HFONT CreateFontIndirect (lpLogFont);
Частіше застосовується функція CreateFontIndirect (), яка отримує в якості параметра покажчик на структуру LOGFONT. Поля цієї структури збігаються з аргументами функції CreateFont ().
typedef struct tagLOGFONT {
int lfHeight;
int lfWidth;
int lfEscapement;
int lfOrientation;
int lfWeight;
BYTE lfItalic;
BYTE lfUnderline;
BYTE lfStrikeOut;
BYTE lfCharSet;
BYTE lfOutPrecision;
BYTE lfClipPrecision;
BYTE lfQuality;
BYTE lfPitchAndFamily;
BYTE lfFaceName [LF_FACESIZE];
} LOGFONT;
Розглянемо призначення полів цієї структури:
lfHeight задає необхідний розмір шрифту в точках (пунктах). Якщо значення позитивно, то в висоту включається міжрядковий проміжок, а якщо негативно, то модуль вказує висоту символу шрифту. Значення 0 вказує, що використовується значення висоти за замовчуванням.
lfWidth задає середню ширину символів у пунктах. Значення 0 відповідає ширині за замовчуванням.
lfEscapement задає нахил базової лінії рядка в десятих частках градуса. Для растрових шрифтів ігнорується.
lfOrientation задає орієнтацію символу щодо базової лінії в десятих частках градуса. Ігнорується для растрових і TrueType шрифтів, для векторних використовуються значення: 0, 900, 1800 і 2700
lfWeight задає вагу символу (жирність). Відповідає кількості зафарбованих піксел з 1000. Передбачені умовні позначення для визначення ваги, що починаються на FW_ ... Наприклад, стандартний текст (400) відповідає FW_NORMAL (FW_REGULAR), жирний (700) FW_BOLD.
lfItalic ненульове значення задає нахил символів (накреслення slanted). Значення 0 відповідає звичайному тексту.
lfUnderline ненульове значення задає підкреслення рядки тексту лінією. Значення 0 відповідає звичайному тексту.
lfStrikeOut ненульове значення задає перекреслення рядки тексту лінією. Значення 0 відповідає звичайному тексту.
lfCharSet задає кодову таблицю, яку повинен підтримувати даний шрифт. Використовуються такі умовні позначення:
ANSI_CHARSET кодова таблиця ANSI
OEM_CHARSET кодова таблиця OEM
SYMBOL_CHARSET символи
SHIFTJIS_CHARSET японська абетка
DEFAULT_CHARSET будь-яка кодова таблиця.
lfOutPrecision вказує, наскільки точно повинен відповідати підбираний шрифт вказаною розміром. (Реально Ви можете замовити растровий шрифт неіснуючого розміру). Див умовні позначення виду OUT_? _PRECIS В windows.h.
lpClipPrecision вказує, як повинен відображатися частково невидимий символ. Див умовні позначення виду CLIP_? _PRECIS В windows.h.
lfQuality вказує якість одержуваного шрифту. Зазвичай використовується значення PROOF_QUALITY (або DEFAULT_QUALITY). Якщо розмір растрового шрифту менше, ніж потрібно, то Windows може масштабувати шрифт. Однак при цьому різко погіршується якість, тому масштабування можна заборонити, використовуючи значення PROOF_QUALITY.
lfPitchAndFamily два молодших біта задають тип шрифту - DEFAULT_PITCH (будь-який тип), VARIABLE_PITCH (пропорційний) або FIXED_PITCH (моно); старший байт вказує сімейство, яке задається одним з таких символів: FF_DECORATIVE, FF_DONTCARE, FF_MODERN, FF_ROMAN, FF_SCRIPT, FF_SWISS.
lfFaceName масив з LF_FACESIZE символів, що містить закінчується \ 0 ім'я шрифту. Пусте ім'я відповідає шрифту пристрою.
1.3 Основи підбору шрифтів в Windows
Коли Ви викликаєте функцію, яка створює шрифт, Windows перебирає всі наявні шрифти, визначаючи шрифт, найточніше відповідний бажаного.
При підборі шрифту використовується система "пенальті": для кожного з шрифтів він обчислює "пенальті", відповідні відмінності даного шрифту від бажаного. Шрифт з мінімальним пенальті вважається найбільш точно відповідним бажаному.
Пенальті обчислюються наступним чином: для істотних параметрів вводяться бальні оцінки. Якщо замовлений параметр відповідає шрифту, пенальті дорівнює 0, а якщо відрізняється, то розмір пенальті залежить від параметра. Значення пенальті приведені в наступній таблиці:
параметр
пенальті
fCharSet
4
fPitchAndFamily: pitch
family
3
3
lfFaceName
3
lfHeight
2
lfWidth
2
lfItalic
1
lfUnderline
1
lfStrikeOut
1
У цій таблиці можна помітити кілька цікавих особливостей. Наприклад, пенальті за невідповідність кодової таблиці більше, а за не-приналежність до сімейства дорівнює пенальті за невідповідність імені шрифту. Практично, якщо Ви хочете використовувати шрифт з конкретним ім'ям, то Ви повинні обов'язково вказати правильні кодову сторінку і сімейство шрифтів, інакше Windows може використовувати шрифт з іншим ім'ям.
1.4 Функції для роботи зі шрифтами
Після того, як Ви отримали хендл шрифту, Ви можете здійснити виведення тексту, використовуючи цей шрифт. Для цього Ви повинні вибрати шрифт у контекст пристрою за допомогою функції
SelectObject (hDC, hFont);
Усі наступні операції виведення будуть використовувати той шрифт, який Ви вибрали в контекст пристрою. Якщо Вам треба отримати інформацію про завантаженому шрифті, то Ви можете скористатися функціями:
int GetTextFace (hDC, nMaxBuffer, lpsBuffer);
int GetObject (hFont, sizeof (LOGFONT), & stLogfont);
Функція GetTextFace () заповнює вказаний буфер ім'ям застосовуваного шрифту, а функція GetObject () дозволяє заповнити структуру LOGFONT інформацією про конкретний шрифті.
Більш складним є все-таки вибір шрифту і визначення характеристик новостворюваного шрифту. Це пов'язано з тим, що в більшості випадків Ви заздалегідь не знаєте, які шрифти використовуються в даному комплекті Windows, тобто Ви повинні вміти вибирати потрібний шрифт з числа наявних у Windows.
Це можна здійснити двома різними способами - Ви можете перебирати всі шрифти і вибрати з них потрібний Вам (наприклад створити меню, що містить імена шрифтів), або Ви можете скористатися функцією ChooseFont () для виклику стандартного діалогу вибору шрифту.
Спочатку ми розберемося з основними правилами перебору шрифтів. У Windows для цих цілей існує дві функції:
int EnumFonts (hDC, lpszFace, lpfnEnumProc, lParam);
int EnumFontFamilies (hDC, lpszFace, lpfnEnumProc, lParam);
Обидві ці функції здійснюють перебір шрифтів, які можуть бути застосовані на зазначеному пристрої, і мають задане ім'я (значення NULL вказує на перебір всіх доступних шрифтів). Ці функції здійснюють перебір трохи розрізняються чином.
Різниця пов'язана з тим, що TrueType шрифти звичайно існують в декількох варіантах, що відрізняються зображенням (жирний, похилий і ін.) Ці варіанти існують як окремі шрифти, тому функція EnumFonts () перераховує один і той-же TrueType шрифт кілька разів, відповідно до кількості різних накреслень. Функція EnumFontFamilies () перебирає тільки по одному зображенню кожного TrueType шрифту.
Для кожного перечисляемого шрифту викликається функція lpfnEnumProc (), якій передається структури типу LOGFONT і TEXTMETRIC (функція EnumFontFamilies () передає структури NEWLOGFONT і NEWTEXTMETRIC, що містять додаткові дані), номер типу шрифту (DEVICE_FONTTYPE, RASTER_FONTTYPE або TRUETYPE_FONTTYPE) і параметр lParam, який Ви вказали для функції EnumFonts () або EnumFontFamilies ().
Загальний вигляд функції, що викликається при переборі шрифтів, наступний:
int CALLBACK _export EnumFontProc (lpLF, lpTM, nType, lParam);
int CALLBACK _export EnumFontFamProc (lpNLF, lpNTM, nType, lParam);
Параметри:
lpLF є далеким адресою структури LOGFONT
lpNLF є далеким адресою структури NEWLOGFONT
lpTM є далеким адресою структури TEXTMETRIC
lpNTM є далеким адресою структури NEWTEXTMETRIC
nType вказує тип шрифту
lParam додатковий параметр, який визначається Вами.
Здійснюючи перебір шрифтів, Ви можете, наприклад, заповнити меню, що містить імена потрібних Вам шрифтів, або вибрати той шрифт, який Вас влаштовує і т.д.
У багатьох випадках зручніше, однак, не перебирати шрифти, а скористатися яким-небудь діалогом для вибору потрібного шрифту. Це можна зробити за допомогою функції ChooseFont (), описаної у файлі COMMDLG.H.
Файл COMMDLG.H містить опис декількох функцій і структур даних, що дозволяють викликати "діалоги загального користування" (COMMon DiaLoGs). Крім файлу COMMDLG.H Ви повинні включити в Ваше застосування файл COMMDLG.LIB, за допомогою якого здійснюється зв'язування Вашого застосування з динамічною бібліотекою COMMDLG.DLL, що містить необхідні функції.
Функція, що викликає діалог для вибору шрифту виглядає наступним чином:
BOOL ChooseFont (lpChooseFont);
причому параметр lpChooseFont вказує на структуру типу CHOOSEFONT:
typedef struct tagCHOOSEFONT {/ * cf * /
DWORD lStructSize; / / = sizeof (CHOOSEFONT)
HWND hwndOwner;
HDC hDC; / / використовується тільки для принтера
LOGFONT FAR * lpLogFont;
int iPointSize;
DWORD Flags;
COLORREF rgbColors;
LPARAM lCustData;
UINT (CALLBACK * lpfnHook) (HWND, UINT, WPARAM, LPARAM);
LPCSTR lpTemplateName;
HINSTANCE hInstance;
LPSTR lpszStyle;
UINT nFontType;
int nSizeMin;
int nSizeMax;
} CHOOSEFONT;
Ви повинні заповнити потрібні поля цієї структури і викликати функцію ChooseFont () для вибору потрібного шрифту. Функція повертає результат TRUE (не 0), якщо шрифт був обраний, або FALSE (0), якщо була натиснута кнопка "Cancel".
Заповнення полів цієї функції елементарно, розглянути варто тільки поле Flags, що описує характеристики діалогу і вибираного шрифту. За допомогою цього поля Ви можете уточнити, з якої групи Ви збираєтеся вибирати шрифт:
по пристроях:
CF_PRINTERFONTS шрифти принтера (Ви повинні вказати hDC принтера)
CF_SCREENFONTS дисплейні шрифти
CF_BOTH всі
за типами шрифтів:
CF_TTONLY тільки TrueType
CF_NOVECTORFONTS растрові і TrueType
CF_SCALABLEONLY векторні, TrueType і деякі шрифти принтера
CF_WYSIWYG шрифти, що використовуються та дисплеєм і принтером. (Разом з CF_WYSIWYG треба встановити CF_BOTH | CF_SCALABLEONLY)
за кодуванням:
CF_ANSIONLY тільки ANSI шрифти
CF_NOOEMFONTS всі шрифти крім OEM
за особливостями
CF_FIXEDPITCHONLY тільки Шрифт фіксованої ширини
CF_FORCEFONTEXIST шрифт з вибраними атрибутами повинен існувати (не допускається автоматичне перетворення) за розміром
CF_LIMITSIZE встановивши цей прапор Ви повинні задати поля nSizeMin і nSizeMax, які визначать допустимі розміри шрифтів.
А також Ви можете кілька видозмінювати діалог:
по наявності кнопок:
CF_APPLY присутня кнопка "Apply" (Застосувати)
CF_USEHELP присутня кнопка "Help" (Довідка)
за правилами ініціалізації:
CF_INITTOLOGFONTSTRUCT використовувати дані структури LOGFONT (зазначеної в CHOOSEFONT) для ініціалізації діалогу
по можливості вибирати параметри:
CF_EFFECTS діалог дозволить встановити стилі підкреслення (underline) і перекреслення (overstrike)
CF_NOFACESEL не можна вибирати ім'я шрифту зі списку
CF_NOSIMUALTIONS заборонена імітація шрифту за допомогою GDI
CF_NOSIZESEL не можна вибирати розмір шрифту
CF_NOSTYLESEL не можна вибирати стиль шрифту.
Додаткові можливості цієї функції пов'язані з можливістю видозмінювати сам діалог, (у тому числі самостійно спроектувати шаблон діалогу), і функцію діалогу, для виконання додаткових дій.

2. Шрифти в якості ресурсів
2.1 Застосування шрифтових ресурсів
Зараз ми розглянемо останню тему, пов'язану зі шрифтами, а саме - створення власних шрифтових ресурсів. Раніше ми зустрічалися з однією з різновидів ресурсів - бітмапами. Тоді бітмапами включався в ресурс і ставав доступним додатком. Для цього ми у файлі опису ресурсів включали рядок виду:
name BITMAP "file.bmp"
За аналогією хочеться вчинити також і зі шрифтом, тим більше, що існує такий вид ресурсів - FONT. Однак цей метод не працює. Це пов'язано з тим, що всі шрифти в Windows доступні всіх програм. У цьому випадку включати шрифт у додаток стає неможливим - тому що в момент його завершення шрифт може використовуватися іншою програмою. Тому шрифтові ресурси в Windows оформляються у вигляді окремих файлів.
Так як шрифти доступні всім додаткам, то ми спочатку повинні включити свій шрифт в системну таблицю шрифтів. При цьому шрифт стає доступним всім додаткам Windows (у тому числі і нашому). Тепер ми можемо викликати функцію CreateFont () або CreateFontIndirect () для отримання хендла шрифту, а в кінці роботи, після знищення створеного шрифту, ми повинні видалити його з системної таблиці.
У деяких випадках може бути зручним додавання шрифту в список шрифтів, автоматично потрапляють в системну таблицю при запуску Windows. Для цього Ви повинні додати рядок у файл WIN.INI, секція [fonts] (як це робиться - пізніше, коли будемо розглядати налаштування додатків). При цьому всі подальші запуски Windows буде автоматично додавати Ваш шрифт у системну таблицю. Однак у поточному сеансі цього автоматично не відбувається, так що Ви повинні самі додати його в таблицю.
Для включення шрифту в системну таблицю треба скористатися функцією:
int AddFontResource (lpszFileName);
повертається значення вказує число шрифтів, доданих в системну таблицю з цього файлу, значення 0 вказує на помилку.
Зазвичай шрифтові файли мають розширення. FON; Такий файл може містити декілька шрифтів із загальним ім'ям, але різними розмірами символів. Windows буде використовувати шрифт того розміру, який найбільш точно підходить до запитуваного.
Якщо доданий шрифт не призначений строго для внутрішнього використання, то Ви повинні послати всіх програм повідомлення про зміну шрифту:
SendMessage (HWND_BROADCAST, WM_FONTCHANGE, 0, 0L);
Для видалення шрифту з системної таблиці Ви повинні скористатися функцією
BOOL RemoveFontResource (lpszFileName);
Як і при додаванні шрифту, якщо цей шрифт може застосовуватися іншими додатками, то Ви повинні надіслати повідомлення WM_FONTCHANGE.
Додавати або видаляти шрифти з системної таблиці зручно або на початку та в кінці програми, або при створенні та видаленні головного вікна програми.
2.2 Створення шрифтових ресурсів
У цьому розділі ми будемо говорити тільки про створення власних растрових шрифтових ресурсів. Це пов'язано з тим, що стандартні редактори шрифтових ресурсів (що включаються в SDK і компілятори) дозволяють створювати тільки растрові шрифти.
Для початку ми повинні намалювати необхідні нам шрифти за допомогою якого-небудь редактора ресурсів. Растрові шрифти зазвичай розміщуються у файлах з розширенням. FNT (це не шрифтів файл, а окремий ресурс, як, скажімо, бітмапами). Нам може знадобиться намалювати декілька шрифтів різного розміру, але мають загальне накреслення. Ці шрифти будуть збережені в різних. FNT файлах.
Далі ми повинні побудувати шрифтів файл. FON, що містить наші шрифти. Цей файл бути бібліотекою ресурсів. Практично він оформлений як звичайне Windows додаток, що містить тільки ресурси. Ми можемо описати такий додаток, як додаток взагалі не має сегмента коду, або як бібліотеку.
Так як наша бібліотека повинна містити шрифтові ресурси, то ми повинні поставити файл опису ресурсів. RC, що містить список намальованих нами шрифтів, наприклад:
1 FONT fonta.fnt
2 FONT fontb.fnt
3 FONT fontc.fnt
Звичайно нам знадобиться файл опису програми. DEF в кілька специфічному вигляді:
LIBRARY
DESCRIPTION 'FONTRES DISPLAY: 40-char terminal'
EXETYPE WINDOWS
STUB 'WINSTUB.EXE'
DATA NONE
Треба звернути увагу на використання слова LIBRARY, замість NAME, для вказівки того, що це не звичайна програма, а бібліотека. Далі ми повинні вказати, що наша бібліотека не має даних 'DATA NONE' і скласти опис нашого шрифту. Для цього ми повинні в DESCRIPTION зазначити рядок спеціального формату:
DESCRIPTION 'FONTRES aspect, logpixelsx, logpixelsy: comment'
DESCRIPTION 'FONTRES DEVICESPECIFIC device: comment'
DESCRIPTION 'FONTRES DISPLAY: comment'
Тут представлені три різних формати таких описів. Перший формат вказує характеристики пристрою, для якого розроблений шрифт; значення характеристик можна знайти, отримавши інформацію про контекст пристрою, або з таблички із зведенням системних шрифтів, наведеної вище.
Другий формат задає шрифт, створений для конкретного пристрою. Параметр device задає ім'я пристрою, для якого шрифт спроектований, наприклад: IBM 8514. Третій формат вказує, що шрифт спроектований для дисплея.
Далі ми повинні побудувати бібліотеку ресурсів. Як вже говорилося, це можна зробити двома способами - створивши додаток не має коду або створивши додаток, що є поділюваної бібліотекою.
Якщо ми хочемо описати додаток не має коду, то нам буде зручніше скористатися компіляторами Borland, так як побудовники завдань інших фірм часто, зустрівши сегмент нульової довжини, припускають довжину 65536. Для створення модуля не має коду, нам треба написати найпростіший асемблерний файл:
_TEXT Segment byte public 'CODE'
_TEXT Ends
end
Цей файл описує тільки один сегмент нульової довжини.
Після цього ми можемо приступити до побудови шрифтового файлу. Для цього ми спочатку компілюємо асемблерний файл:
tasm file.asm
потім ми повинні побудувати нашу бібліотеку і включити в неї спроектовані ресурси:
tlink file.obj, file.exe, nul,, file.def
rc file.rc
rename file.exe file.fon
Тепер ми маємо в своєму розпорядженні власним шрифтовим ресурсом, який ми можемо застосовувати в нашому застосуванні. Ще раз треба зазначити, що обов'язкове застосування 'Borland TLINK' для побудови файлу, тому що інші складальники можуть побудувати невірний модуль.
Раніше ми зробили зауваження про те, що ми можемо будувати шрифтів файл двома способами - як бібліотеки не має коду, або як звичайну бібліотеку. Якщо ми хочемо будувати звичайну бібліотеку, то замість ассемблерного файлу нам треба написати невеликий файл на C:
# Include <windows.h>
extern "C" {
int CALLBACK LibMain (
HANDLE hInstance, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine) {
/ / Зазвичай функція LibMain () розблокує сегмент даних
/ / Якщо він має динамічний heap.
/ / If (cbHeapSize) UnlockData (0);
/ / Так як ми взагалі не маємо даних (і heap теж)
/ / То можемо цього не робити.
return 1;}
int CALLBACK WEP (int bSystemExit) {
return TRUE;}}
Цей файл містить дві процедури - LibMain () - яка замінює звичайний WinMain () і викликається при ініціалізації бібліотеки - і процедуру WEP (), яка викликається при видаленні непотрібної бібліотеки.
У цьому файлі треба звернути увагу на те, що функція LibMain описана як CALLBACK (PASCAL FAR), на відміну від WinMain. На жаль, деякі компілятори припускають, що вона повинна бути NEAR для моделей пам'яті з одним сегментом коду. Як вихід можна змінити ім'я, наприклад, написати його тільки великими буквами. Тоді компілятор не розпізнає цю функцію як стандартну і не зробить помилки, а складальник здійснить правильне зв'язування, так як функція декларована як CALLBACK (PASCAL FAR).
Друга особливість - вказівка, що імена функцій не повинні кодуватися як C + + імена (extern "C"). Це знову-ж таки пов'язано з особливостями деяких компіляторів, які не розпізнають функцію WEP () (Windows Exit Procedure) як стандартну, і здійснюють для неї C + + кодування імені - при цьому збирач не може правильно побудувати завдання.
В іншому побудова шрифтового файлу не відрізняється від розглянутого, звичайно окрім компіляції вихідного тексту, що виконується як для звичайного Windows-програми:
bcc-ms-W file.c file.def
2.3 Особливості TrueType шрифтів
Зараз ми розглянемо деякі особливості застосування власних TrueType шрифтів. Ці особливості пов'язані з тим, що TrueType шрифт представлений в абсолютно іншій формі, ніж растрові шрифти. Якщо Ви за допомогою будь-якого інструментального засоби (наприклад, FontoGrapher) створите TrueType шрифт, то виявите, що він представлений у вигляді файлу з розширенням. TTF.
Однак застосовувати. TTF файл безпосередньо не можна. Для того, що б можна було використовувати TrueType шрифт треба побудувати проміжний файл, зазвичай з розширенням. FOT, який можна використовувати замість файлу. FON для додавання шрифту в таблицю ресурсів. Для побудови цього файлу Ви повинні скористатися функцією
BOOL CreateScalableFontResource (
nHidden, lpszResourceFile, lpszFontFile, lpszPath);
Ця функція створює файл з ім'ям lpszResourceFile для доступу до. TTF файлу, заданому параметром lpszFontFile, параметр lpszPath вказує шлях до. TTF файлу. Останній залишився параметр nHidden вказує можливість використання шрифту іншими додатками. Якщо він 0, то інші програми мають доступ до цього шрифту, а якщо 1, то доступ заборонений і цей шрифт не перераховується при переборі шрифтів (EnumFonts (), EnumFontFamilies ()).
2.4 Настроювання програм
Закінчуючи розмову про шрифти, зручно розглянути ще один компонент Windows - засоби для налаштування додатків. Під настройкою (іноді "профілюванням") розуміється завдання характеристик програми та їх збереження для використання при наступному запуску.
Зазвичай такі завдання вирішуються за допомогою створення конфігураційних файлів. Проте конфігурація описується кожної завданням по-своєму, що не завжди зручно. Windows пропонує загальний для всіх додатків механізм опису їх характеристик, з використанням файлів налаштування.
Такі файли (що зазвичай мають розширення. INI) є звичайними ASCII-файлами, розділеними на секції, що починаються з імені секції, укладеного у квадратні дужки. Далі слідує список параметрів у вигляді 'параметр = значення', кожен параметр розміщується в окремому рядку. У цей файл можна вставляти коментарі - рядки починаються з ';'.
Приклад взятий з файлу WORKSHOP.INI:
[User Controls]
BorShade = E: \ BORLANDC \ WORKSHOP \ BWCC.DLL
[RWS_Bitmap]
PercentLeft = 50
ZoomLeft = 1
ZoomRight = 1
bVert = 0
[RWS_Font]
PercentLeft = 50
ZoomLeft = 4
ZoomRight = 1
bVert = 1
Для роботи з такими файлами Windows надає набір функцій, що здійснюють запис і читання параметрів:
int GetProfileInt (lpszSection, lpszEntry, nDefault);
int GetProfileString (lpszSection, lpszEntry, lpszDefault, lpsBuffer, nMaxBuffer);
BOOL WriteProfileString (lpszSection, lpszEntry, lpszString);
Параметр lpszSection задає ім'я секції (дужок в імені вказувати не треба), lpszEntry - ім'я параметра. Якщо ми отримуємо значення параметра, то можемо вказати значення за замовчуванням, яке повертається, якщо цей параметр не знайдений.
За допомогою функції GetProfileString () можна отримати список імен всіх параметрів у секції, вказавши lpszEntry = NULL. При цьому імена параметрів секції будуть скопійовані в буфер послідовно один за одним, кожне ім'я буде закінчуватися 0 і після останнього імені будуть стояти два 0.
Функція WriteProfileString () дозволяє не тільки записувати параметри, але і видаляти, для чого треба вказати lpszString = NULL. Можна видалити повністю всю секцію, вказавши lpszEntry = NULL.
Всі три розглянутих функцій використовують файл WIN.INI. При цьому ім'я секції часто асоціюється з ім'ям програми. (Тому в документації ім'я секції часто називається іменем додатка).
Звичайно, часто буває незручно використовувати загальний файл налаштування для всіх існуючих додатків (при цьому, зокрема, важко організувати видалення додатків). Windows надає можливість використовувати власний файл налаштування (і навіть декілька). Для роботи з власними файлами налаштування передбачені ще три функції:
int GetPrivateProfileInt (lpszSection, lpszEntry, nDefault, lpszIniFile);
int GetPrivateProfileString (
lpszSection, lpszEntry, lpszDefault, lpsBuffer, nMaxBuffer, lpszIniFile);
BOOL WritePrivateProfileString (
lpszSection, lpszEntry, lpszString, lpszIniFile);
Останній параметр цих функцій задає ім'я файлу налаштування. Якщо Ви не вказуєте шлях до файлу, то він розміщується у каталозі Windows.
2.5 Інформація стандартних файлів налаштування (win.ini і system.ini) про шрифти і про принтері
Розглядаючи настройку додатків треба докладніше зупинитися на файлі WIN.INI. Цей файл містить велику кількість характеристик, що визначають роботу як самого Windows, так і багатьох його застосувань. Пізніше ми будемо іноді посилатися на цей файл, наприклад, при визначенні дати і часу.
Зараз ми розглянемо інформацію, що зберігається в цьому файлі, що стосується шрифтів. Найсуттєвіша для нас секція - [fonts]. У цій секції перераховані всі шрифти, що містяться в системну таблицю при запуску Windows. Формат записів:
face name = file.fon
face name - це ім'я шрифту, а file.fon - ім'я шрифтового файлу, що містить растровий або векторний шрифт, або file.fot - TrueType шрифт.
Приклад:
[Fonts]
Academy (TrueType) = ACADEMY.FOT
Academy Bold (TrueType) = ACADEMY0.FOT
Наступна секція, що відноситься до шрифтів, [FontSubstitutes], вказує, які шрифти, що входять в Windows 3.1 повинні використовуватися замість деяких шрифтів, що входили в Windows 3.0. Формат записів:
new name = old name
Приклад:
[FontSubstitutes]
Helv = MS Sans Serif
Courier = Helv
Якщо Ви адаптуєте додаток Windows 3.0 для роботи в Windows 3.1, то Вам треба посилатися на цю секцію для визначення імен шрифтів, які Ви повинні застосовувати.
Додатково інформація про системні шрифти міститься у файлі SYSTEM.INI, де в секції [boot] вказуються системний (ANSI), термінальний (OEM) і системний фіксованої ширини (ANSI) шрифти. Це робиться за допомогою параметрів:
[Boot]
fonts.fon = vgasys.fon
fixedfon.fon = vgafix.fon
oemfonts.fon = vgaoem.fon
Ці шрифти використовуються Windows при завантаженні, коли системна таблиця шрифтів ще не ініціалізований. Крім того деякі шрифти, використовувані DOS вікном у Windows визначені в секціях:
[Boot.description]
woafont.fon = English (437)
[386Enh]
woafont = dosapp.fon
EGA80WOA.FON = EGA80WOA.FON
EGA40WOA.FON = EGA40WOA.FON
CGA80WOA.FON = CGA80WOA.FON
CGA40WOA.FON = CGA40WOA.FON
Розгляд стандартних файлів налаштування ми продовжимо, перейшовши до параметрів принтера. Для цього ми повертаємося до файлу WIN.INI, секція [devices]. У цій секції перераховані всі принтери, які були використані інстальовані. Кожна запис визначає ім'я принтера, ім'я драйвера та ім'я вихідного пристрою (послідовний або паралельний порт, файл); формат записів:
printer name = driver, port1 [, port2 [,...]]
де printer name - ім'я принтера, driver - ім'я драйвера і portN - ім'я вивідного пристрою.
Приклад:
[Devices]
Epson FX-80 = EPSON9, FILE:, LPT1:
тобто: принтер 'Epson FX-80' обслуговується драйвером 'EPSON9.DRV' і може направляти висновок у файл або в паралельний порт # 1.
Характеристики вивідних пристроїв повинні бути зазначені ще у двох місцях - в секції [ports], де перераховані імена всіх дозволених вивідних пристроїв і задані характеристики послідовних портів, і в секції [PrinterPorts], де вказані граничні часи очікування готовності і помилки.
У секції [ports] записується приблизно така інформація:
[Ports]
LPT1: =
LPT2: =
COM1: = 9600, n, 8,1
COM2: = 9600, n, 8,1, x
EPT: =
FILE: =
LPT1.DOS =
А в секції [PrinterPorts] запису схожі на секцію [device] з додатково зазначеними часом очікування готовності і повторення для кожного пристрою.
[PrinterPorts]
Epson FX-80 = EPSON9, FILE:, 15,45, LPT1:, 15,45
За допомогою всіх розглянутих параметрів описуються встановлені в даний момент принтери, однак нас часто не цікавлять всі мислимі принтери, а тільки один - той, який підключений безпосередньо зараз. Для того, щоб визначити цей принтер треба звернути увагу на секцію [windows], в якій є параметр:
device = printer name, driver, port
Описує ім'я поточного принтера, обслуговуючого його драйвера і використовується вивідний пристрій. Зазвичай доводиться користуватися саме цією інформацією.

3. Робота з принтером
3.1 Отримання контексту пристрої
Тепер, коли ми навчилися визначати характеристики принтера, ми можемо перейти безпосередньо до роботи з ним. Для початку нам треба отримати хендл контексту пристрою, пов'язаного з принтером. Існує дві можливості зробити це: самим розібратися з файлом WIN.INI і створити контекст пристрою або скористатися стандартним діалогом для вибору і настройки принтера. Частіше застосовується другий спосіб (як більш "дружній"), однак іноді простіше все зробити самим (особливо, якщо Ви повинні самі перевірити наявність та характеристики принтерів - наприклад при інсталяції програми).
Якщо ми хочемо самі розібратися з принтером, то для створення контексту принтера ми повинні скористатися процедурою:
HDC CreateDC (lpszDriver, lpszDevice, lpszOutput, lpvData);
При цьому ми спочатку повинні визначити ім'я драйвера lpszDriver, ім'я принтера lpszDevice та ім'я вивідного пристрою lpszOutput. Параметр lpvData ми будемо встановлювати в NULL, для того, що б зробити ініціалізацію за замовчуванням (так як це було визначено при інсталяції принтера або змінена через "Control Panel").
Всю потрібну для створення контексту пристрою інформацію ми отримаємо з параметра "device =" секції [windows]:
HDC GetPrinterDC (void) {
char buf [80];
char * Device, * Drive, * Output;
static char delimiters [] = ",";
GetProfileString ("windows", "device", ",,,", buf, sizeof (buf) -1);
Device = strtok (buf, ",");
Drive = strtok (NULL, delimiters);
Output = strtok (NULL, delimiters);
return Device & & Drive & & Output?
CreateDC (Drive, Device, Output, NULL): NULL;}
Цей спосіб дозволяє легко отримати хендл контексту поточного вибраного принтера. А якщо нам бажано вибирати або настроювати принтер, то самим зручним буде спосіб з використанням стандартного діалогу (кожен драйвер принтера містить власний діалог використовуваний для його налаштування; цей діалог ми можемо викликати, звернувшись до функції ExtDeviceMode драйвера - однак те-ж саме робить стандартний діалог ).
При використанні стандартного діалогу ми повинні викликати функцію PrintDlg (...), визначену в COMMDLG.H:
# Include "commdlg.h"
BOOL PrintDlg (PRINTDLG FAR * lppd);
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;
Ви повинні заповнити потрібні поля (зазвичай майже всі - 0) цієї структури і викликати функцію PrintDlg () для вибору поточного принтера і його налаштування. Функція повертає результат TRUE (не 0), якщо контекст принтера успішно створений, або FALSE (0), якщо була натиснута кнопка "Cancel" або виникла помилка.
Параметр lStructSize задає розмір даної структури, він повинен бути рівний sizeof (PRINTDLG), hwndOwner задає хендл вікна-користувача діалогу (може бути 0).
Два хендла глобальних об'єктів hDevMode і hDevNames використовуються для початкової ініціалізації діалогу. Зазвичай вони задаються 0, а функція PrintDlg () сама створює ці блоки і вказує їх хендла. Якщо Ви не плануєте більше звертатися до функції PrintDlg (), то ви повинні їх знищити (за допомогою функції GlobalFree ()). Проте зазвичай ці блоки знищуються тільки при завершенні всього програми - так що при повторному виклику PrintDlg () у структурі PRINTDLG вже міститися ці хендла та інформація з цих блоків використовується для повторної ініціалізації діалогу.
Поле hDC при виклику діалогу ігнорується, а після завершення може (якщо Ви це замовите) містити хендл створеного контексту принтера.
Цікаво розглянути тільки деякі значення поля Flags:
PD_PRINTSETUP замість діалогу "вибір принтера" викликати діалог "настройка принтера".
PD_RETURNDC створити контекст принтера і повернути його хендл в полі hDC
PD_RETURNIC створити інформаційний контекст принтера і повернути його хендл в полі hDC
PD_RETURNDEFAULT не викликати ніякого діалогу, просто ініціалізувати глобальні блоки hDevMode і hDevNames (перед таким викликом функції PrintDlg () вони повинні бути рівні 0)
Після отримання хендла контексту пристрою принтера ми можемо перейти до виводу на принтер. Але спочатку нам треба розібратися в тому, як Windows організовує роботу з принтером.
3.2 Основи друку
Коли Ви отримали контекст пристрою для принтера, насправді Ви не отримали доступу до самого принтера, а тільки лише до проміжного метафайл. Поки Ви малюєте на принтері, всі потрібні команди запам'ятовуються в цьому метафайлу і тільки після того, як Ви оголосіть про завершення роботи з сторінкою, Windows здійснить друк підготовленої сторінки з метафайлу.
Реальний механізм складніше, тому що спулінг принтера може бути відключений, а, крім того, Ваша програма може використовувати спеціальний метод пополосно друку, який помітно ускладнює внутрішню логіку друку.
Такий складний механізм дозволяє здійснити спулінг друку і більш-менш ефективне розділення принтера між різними додатками.
Загальні правила, з точки зору програми, зводяться до наступного:
починаючи роботу з принтером, Ви повинні зареєструвати власне завдання на друк. Це виключає одночасне друкування даних різними додатками.
Далі Ви повинні заповнити сторінку потрібними даними і подати команду на друк цієї сторінки і на перехід до наступної.
Коли всі сторінки надруковані, Ви повинні сказати Windows про завершення друку Вашого завдання.
У цій схемі є кілька недоліків:
По-перше, процес друку навіть однієї сторінки може бути дуже тривалим (до 30-60 хвилин) - а при такій схемі Ви не можете навіть перервати процес друку;
По-друге, графічний образ однієї сторінки на принтері високого дозволу (особливо кольоровому) може займати десятки мегабайт, що достатньо жорстко обмежує можливості друку.
Для того, щоб вирішити ці проблеми застосовують різні прийоми. Для того, що б можна було виконувати будь-яку іншу роботу одночасно з печаткою, і що б друк можна було перервати у будь-який момент, додають спеціальну функцію, звану AbortProc (), яка викликається автоматично під час друку для обробки повідомлень і для того, що б роботу принтера можна було перервати.
У цьому випадку, крім реєстрації завдання, Ви повинні встановити власну AbortProc до початку самого друку.
Для вирішення другого завдання вводять спеціальний метод пополосно друку (banding). У цьому випадку Ви запитуєте у принтера дані про смугу, яку треба відобразити і заповнюєте цю смугу (або всю сторінку - контекст пристрою реально відповідає тільки цій смузі). Тоді максимальний розмір тимчасового файлу, що містить образ сторінки, обмежений розмірами смуги.
У цьому випадку Вам треба мати на увазі кілька нюансів:
при пополосно друку функція AbortProc () автоматично викликається занадто рідко, тому Ви повинні самі передбачити виклики цієї функції з достатньою частотою.
орієнтація смуг не обов'язково горизонтальна, так як принтер може друкувати як в режимі "портрет" (Portrait), так і в режимі "ландшафт" (Landscape).
Смугу для друку у Вас запитує Windows. Ви не знаєте заздалегідь ні орієнтацію цієї смуги, ні її розміри. Windows формує запит для друкування смуги до тих пір, поки не буде надрукована вся сторінка.
Тепер нам треба розглянути безпосередньо текст програми, що здійснює друк.
3.3 Друкування на принтері
Взагалі для управління печаткою достатньо тільки однієї процедури - Escape (), яка використовувалася в колишніх версіях Windows.
int Escape (hDC, nEscape, cbInput, lpsInData, lpvOutput);
Параметр nEscape вказує код виконуваної операції, параметри cbInput і lpsInData вказують вихідні дані для операції, а lpvOutput - результат операції. Застосування і форма вихідних даних та результатів залежить від операції.
У версії Windows 3.1 до цієї процедури доданий ряд допоміжних, які просто виконують окремі операції.
Зараз ми розглянемо деякі основні операції, необхідні для друку. Перша операція реєструє наше завдання на друк:
Escape (hDC, STARTDOC, cbName, lpsName, NULL);
або
StartDoc (hDC, lpDocInfo);
struct DOCINFO {
int cbSize;
LPSTR lpszDocName;
LPSTR lpszOutput;};
Параметри cbName і lpsName визначають назву нашого завдання. Значення, що повертається, більше 0, вказує на успішну постановку завдання в чергу, а значення 0 і менше вказує на виниклу помилку.
Далі, якщо ми хочемо друкувати сторінку цілком, то після її заповнення ми повинні подати команду на друк сторінки:
/ / Заповнити сторінку
Escape (hDC, NEWFRAME, 0, NULL, NULL);
або
StartPage (hDC);
/ / Заповнити сторінку
EndPage (hDC);
У разі успішного завершення завдання ми повинні повідомити про це за допомогою операції ENDDOC:
Escape (hDC, ENDDOC, 0, NULL, NULL);
або
EndDoc (hDC);
Однак нам може знадобиться перервати друк достроково. Для цього ми повинні розробити та встановити нашу власну процедуру AbortProc. Припустимо, що така функція нами написана і її ім'я AbortProc (). Тоді ми можемо встановити її наступним способом:
FARPROC lpfnAbortProc = MakeProcInstance ((FARPROC) AbortProc, hInstance);
Escape (hDC, SETABORTPROC, 0, (LPSTR) lpfnAbortProc, NULL);
/ / Друкуємо ...
FreeProcInstance (lpfnAbortProc);
або
FARPROC lpfnAbortProc = MakeProcInstance ((FARPROC) AbortProc, hInstance);
SetAbortProc (hDC, (ABORTPROC) lpfnAbortProc);
/ / Друкуємо ...
FreeProcInstance (lpfnAbortProc);
При цьому, якщо наше завдання буде достроково знято з друку, то ми повинні повідомити про це (що б завдання було коректно видалено з черги):
Escape (hDC, ABORTDOC, 0, NULL, NULL);
або
AbortDoc (hDC);
Невеликий приклад (пояснюючий правила розробки процедури AbortProc):
static BOOL bAbort;
BOOL PASCAL FAR _export AbortProc (HDC hdcPRN, short nCode) {
MSG msg;
while (! bAbort & & PeekMessage (& msg, NULL, 0,0, PM_REMOVE)) {
TranslateMessage (& msg);
DispatchMessage (& msg);}
return! bAbort;}
static BOOL DoPrint (void) {
static char szName [] = "Test Printing";
FARPROC lpfnAbort;
BOOL answer = FALSE;
HDC hdcPRN;
hdcPRN = GetPrinterDC (); / / отримання hdcPRN див. вище
lpfnAbort = MakeProcInstance ((FARPROC) AbortProc, hInstance);
Escape (hdcPRN, SETABORTPROC, 0, (LPSTR) lpfnAbort, NULL);
if (Escape (hdcPRN, STARTDOC, sizeof (szName) -1, szName, NULL)> 0) {
while (! bAbort & & / * є що друкувати * /) {
/ / Малюємо на сторінці
if (Escape (hdcPRN, NEWFRAME, 0, NULL, NULL) <= 0) bAbort = TRUE;}
if (bAbort) {
Escape (hdcPRN, ABORTDOC, 0, NULL, NULL);
} Else {
Escape (hdcPRN, ENDDOC, 0, NULL, NULL);
answer = TRUE;}}
FreeProcInstance ((FARPROC) lpfnAbort);
DestroyDC (hdcPRN);
return answer;}
У цьому прикладі треба звернути увагу на змінну bAbort. Вона може бути встановлена ​​в значення TRUE для завершення друку. У даному прикладі дострокове завершення не передбачено, хоча його легко можна зробити, встановлюючи цю змінну, наприклад, у відповідь на вибір пункту меню, на натиснення кнопки діалогу або навіть за таймером.
Якщо ми будемо використовувати пополосно друк, то нам треба замість операції NEWFRAME виконувати серію операцій NEXTBAND до тих пір, поки смуга для друку не виявиться порожньою (що відповідає повністю надрукованій сторінці); при цьому внутрішній цикл для друку сторінок доведеться дещо змінити:
... RECT rc;
... While (! BAbort & & / * є що друкувати * /) {
while (Escape (hdcPRN, NEXTBAND, 0, NULL, (LPSTR) & rc)> 0) {
if (IsRectEmpty (& rc)) goto ok_page;
/ / Заповнюємо смугу або всю сторінку, іноді викликаючи AbortProc:
lpfnAbortProc (hdcPRN, 0);
/ / Увага! використовується покажчик на функцію, а не вона сама!}
bAbort = TRUE;
ok_page :;}...
Додати в блог або на сайт

Цей текст може містити помилки.

Програмування, комп'ютери, інформатика і кібернетика | Лекція
127кб. | скачати


Схожі роботи:
Завантажувач шрифтів
Робота з гарячими клавішами в ОС Windows Призначення гарячих клавіш в ОС WINDOWS -функції
Операційні системи WINDOWS NT NetWare UNIX Оперцiйна система Windows NT
Пошук даних в ОС Windows Основні прийоми роботи із пошуком в ОС WINDOWS
Аналіз шрифтів дитячої друкованої продукції
Влада народу - відносні розміри шрифтів
Налаштування локальної мережі і підключення до мережі інтернет для Windows XP і Windows 7
Панель керування в ОС Windows Панель управління пристороями Пк у середовищі Windows
Мікропроцесори сімейства Intel
© Усі права захищені
написати до нас