Все про w32api


W32api Функции

Содержание

  • w32api_deftype — Defines a type for use with other w32api_functions
  • w32api_init_dtype — Creates an instance of the data type typename and fills it with the values passed
  • w32api_invoke_function — Invokes function funcname with the arguments passed after the function name
  • w32api_register_function — Registers function function_name from library with PHP
  • w32api_set_call_method — Sets the calling method used
НОВОСТИ ФОРУМА
Рыцари теории эфира
01.10.2020 — 05:20: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]69vJGqDENq4[/Youtube][/center]
[center]14:36[/center]
Osievskii Global News
29 сент. Отправлено 05:20, 01.10.2020 г.’ target=_top>Просвещение от Вячеслава Осиевского — Карим_Хайдаров.
30.09.2020 — 12:51: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Ok]376309070[/Ok][/center]
[center]11:03[/center] Отправлено 12:51, 30.09.2020 г.’ target=_top>Просвещение от Дэйвида Дюка — Карим_Хайдаров.
30.09.2020 — 11:53: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]VVQv1EzDTtY[/Youtube][/center]
[center]10:43[/center]

интервью Раввина Борода https://cursorinfo.co.il/all-news/rav.
мой телеграмм https://t.me/peshekhonovandrei
мой твиттер https://twitter.com/Andrey54708595
мой инстаграм https://www.instagram.com/andreipeshekhonow/

[b]Мой комментарий:
Андрей спрашивает: Краснодарская синагога — это что, военный объект?
— Да, военный, потому что имеет разрешение от Росатома на манипуляции с радиоактивными веществами, а также иными веществами, опасными в отношении массового поражения. Именно это было выявлено группой краснодарцев во главе с Мариной Мелиховой.

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

CXXXI. W32api Functions

This extension is a generic extension API to DLLs. This was originally written to allow access to the Win32 API from PHP, although you can also access other functions exported via other DLLs.

Currently supported types are generic PHP types (strings, booleans, floats, integers and nulls) and types you define with w32api_deftype() .

Это расширение является ЭКСПЕРИМЕНТАЛЬНЫМ . Поведение этого расширения, включая имена его функций и относящуюся к нему документацию, может измениться в последующих версиях PHP без уведомления. Используйте это расширение на свой страх и риск.

This extension will only work on Windows systems.

Для использования этих функций не требуется проведение установки, поскольку они являются частью ядра PHP.

Данное расширение не определяет никакие директивы конфигурации в php.ini .

This extension defines one resource type, used for user defined types. The name of this resource is «dynaparm» .

Перечисленные ниже константы определены данным расширением и могут быть доступны только в том случае, если PHP был собран с поддержкой этого расширения или же в том случае, если данное расширение подгружается во время выполнения.

This example gets the amount of time the system has been running and displays it in a message box.

Пример 1. Get the uptime and display it in a message box

// Define constants needed, taken from
// Visual Studio/Tools/Winapi/WIN32API.txt
define ( «MB_OK» , 0 );

// Load the extension in
dl ( «php_w32api.dll» );

// Register the GetTickCount function from kernel32.dll
w32api_register_function ( «kernel32.dll» ,
«GetTickCount» ,
«long» );

// Register the MessageBoxA function from User32.dll
w32api_register_function ( «User32.dll» ,
«MessageBoxA» ,
«long» );

// Get uptime information
$ticks = GetTickCount ();

// Convert it to a nicely displayable text
$secs = floor ( $ticks / 1000 );
$mins = floor ( $secs / 60 );
$hours = floor ( $mins / 60 );

$str = sprintf ( «You have been using your computer for:» .
«\r\n %d Milliseconds, or \r\n %d Seconds» .
«or \r\n %d mins or\r\n %d hours %d mins.» ,
$ticks ,
$secs ,
$mins ,
$hours ,
$mins — ( $hours * 60 ));

// Display a message box with only an OK button and the uptime text
MessageBoxA ( NULL ,
$str ,
«Uptime Information» ,
MB_OK );
?>

Answer to the note posted by me at nullflux dot com (see below)

The Win32 API *does* work in other versions of PHP than between 4.2.0 and 4.2.3. However the documented functions are not available. You will have to use the «win32» class to access functions. For an example, read Philip Soeberg’s post just below.

Here is a new link for the official page for the Windows API @ Microsoft’s site:

It seems that this extension will be replaced by FFI extension in PHP5. FFI stands for «Foreign Function Interface» and it’s not limited by Windows API, but also supports Linux APIs. You may reach this extension’s website at http://pecl.php.net/package/ffi . For Windows, you may try this code from commandline php.exe:


$windows = new ffi ( «[lib=’user32.dll’] int MessageBoxA( int handle, char *text, char *caption, int type );» );

echo $windows -> MessageBoxA ( 0 , «Message For You» , «Hello World» , 1 );
?>

The win32 support appears to be pretty flaky in php. This of course is to be expected with an experimental extension. That being said, if you are having trouble using the win32 functionality you may want to look into creating a PHP extension instead.

We were having some problems interfacing PHP with a 3rd party dll. As such we created an extension which wraps the interface with the aforementioned dll. The solution was surprisingly quick and painless.
Because we use Delphi primarily we found the following extremely useful and easy to use. http://users.chello.be/ws36637/php4delphi.html#download

In response to post by Jan Kleinsorge.

To get the proper windows system uptime, one should use the Performance Monitoring system. GetTickCount is limited to 49.7 days, as the result is a dword.

if (! dl ( «php_w32api.dll» )) <
echo «Unable to load php_w32api.dll» ;
exit;
>

$api = new win32 ;
$api -> registerfunction ( «bool QueryPerformanceCounter (float &lpPerformanceCount) From kernel32.dll» );
$api -> registerfunction ( «bool QueryPerformanceFrequency (float &lpPerformanceFrequency) From kernel32.dll» );

$api -> QueryPerformanceCounter ( $a );
$api -> QueryPerformanceFrequency ( $b );
$c = $a / $b ;
$days = floor ( $c / 86400 );
echo gmstrftime ( «System uptime is $days Days, %H Hr, %M Min, %S Sec
» , $c );
?>

The above snippet will return the true uptime for an unlimited time for a windows OS. (Disregarding the fact that windows needs reboot every 10 days or so :))
A tiny dange though is the lack of 64bit variable types in php.. (the «float &lpPerformanceCount» should be «long long &lpPerformanceCount») .. Nevertheless.. It works :)

http://msdn.microsoft.com/library/ contains functions for use with this extension.

Beware! The menu system is very dense, and confusing at first if you don’t know where your going.

Luckily for you I am going to add how to get there in this note. ;)

Windows Development > Development Guides > Windows API > Windows API Reference

The small, unofficial documentation is now available here http://wobster.mynnga.de/w32api.txt .
The old link from the post above is dead.

Note that the W32API doesn’t seem to be under development anymore. E-Mails to the author stayed unanswered.
If you really have to use it, just some hints here: There are often problems concerning Apache webservers. This extension doesn’t seem to work with mod_php.
I used the API on IIS5 with PHP as CGI. Additionally the IUSR_ (that’s the user IIS runs php.exe by default) might need additional rights to be able to call certain API-functions.

for phpgtk users, who might want to add some sound to their apps, here is the code, assuming ding.wav is in the script’s directory

$api = new win32;
$api->registerfunction(«long sndPlaySound (string a, int b) From winmm.dll»);
$api->sndPlaySound(«ding.wav», 0);

you can use the big win32.hlp file containing the win32 api reference to get some other multimedia functions

I played a bit around with the W32API. Here is some code that actually works with the current release of W32API.
The interface changed completely, so all documentation about this extension is out-dated. While the old release
just implemented «plain» functions, the current version offers a class to handle all the API-related operations.
Additionally, functions are now registered using a SQL-like language with a single string.

/*
DWORD GetTickCount(VOID)
Returns the ms the OS is running
*/
$api -> registerfunction ( «long GetTickCount () From Kernel32.dll» );

$len = 255 ; // set the length your variable should have
$name = str_repeat ( «\0» , $len ); // prepare an empty string
if ( $api -> GetUserName ( $name , $len ) == 0 )
<
die( «failed» );
>

if (!( $time = $api -> GetTickCount ()))
<
die( «failed» );
>

echo «Username: $name
\n Systemtime: $time
\n » ;

In order to use most (perhaps all?) of the win32 API while running with a web server you have to give the server service permission to interact with the desktop. This is especially noticeable with the given example, where the script will try to display message boxes on the server’s display.

Keep in mind, however, that you should think hard about the consequences of letting a web server interact with your desktop, especially if you’re not the only one using the web server.

Основы программирования для Win32 API

Материал рассматривается на примере пакета Borland C++ 5.5 command line tools

Стартовая функция WinMain

Программа на Си для Windows, как и для любой другой платформы, должна обязательно содержать некоторую «стартовую» функцию, которой передается управление при запуске программы. Вообще говоря, имя такой «стартовой» функции может различаться в различных компиляторах, но исторически сложилось так (а, кроме того, имеются еще и стандарты ANSI и ISO, к которым, правда, производители коммерческих компиляторов типа Microsoft и Borland/Inprise относятся без особого трепета), что такой функцией является: У этой функции может быть до трех параметров:

  • argc — количество параметров в командной строке (включая имя программы),
  • argv — массив строк-параметров (argv[0] — имя программы),
  • env — массив строк-переменных окружения.

Многие компиляторы для Windows «понимают» такую стартовую функцию. Однако при этом они создают хотя и 32-битное, но консольное приложение. Пример 1 (example1.cpp): Компилируем: Запускаем:

При использовании стандартных библиотек (stdio, stdlib и т. п.) вам не потребуется никаких лишних телодвижений по сравнению с обычными методами написания программ на Си. Если же ваша цель — 32-битное приложение с графическим интерфейсом, то черное консольное окошко будет вас раздражать. Пример (example2.cpp):

В общем, чтобы получить нормальное приложение без каких-либо «довесков» типа консольного окошка, используется другая стартовая функция:

  • hInst — дескриптор для данного экземпляра программы,
  • hpi — в Win32 не используется (всегда NULL),
  • cmdline — командная строка,
  • ss — код состояния главного окна.

Пример (example3.cpp):

Кроме того, компилятору и компоновщику нужно сообщить о том, что вы делаете графическое приложение. Для bcc32 это опция -tW:

Если же вы соскучитесь по черному консольному окошку, его можно в любой момент создать при помощи вызова Win32 API

О типах, о функциях

Как известно, в Си есть лишь три базовых типа ( char , int , float/double ) и еще несколько их вариаций с модификаторами signed/unsigned , short/long . Однако фирме Microsoft зачем-то понадобилось описывать функции Win32 API с помощью переопределенных типов:

Кроме перечисленных простых типов, практически ни один вызов Win32 API не обходится без «штучек» с «ручками» — переменных типа handle («ручка»), которые идентифицируют некоторый объект («штучку»). Такие «ручки» принято называть дескрипторами. Реально такая переменная представляет собой всего лишь указатель на некоторую системную структуру или индекс в некоторой системной таблице.

При заполнении различных структур часто требуется указать такую «ручку» от какой-нибудь «штучки». Очень часто вместо конкретного дескриптора допустимо передавать значение NULL , означающее, что вы еще не обзавелись такой «штучкой» или собираетесь использовать «штучку» по умолчанию.

В стандартных версиях Си для функций используются два варианта соглашения о передаче параметров: соглашение языка Си (параметры функции помещаются в стек в порядке обратном их описанию, очистку стека производит вызывающая процедура) и соглашение языка Паскаль (параметры функции помещаются в стек в (прямом) порядке их описания, очистку стека производит вызываемая процедура). Для этих соглашений использовались, соответственно, модификаторы cdecl и pascal . При описании функций Win32 API используется модификатор WINAPI , а для описания пользовательских функций обратного вызова — модификатор CALLBACK . Оба этих модификатора являются переопределением специального модификатора _stdcall , соответствующего соглашению о передаче параметров, использующегося исключительно в Win32 API, — Standard Calling Convention (параметры функции помещаются в стек в порядке обратном их описанию, очистку стека производит вызываемая процедура).


Окно — это прямоугольная область экрана, в котором приложение отображает информацию и получает реакцию от пользователя. Одновременно на экране может отображаться несколько окон, в том числе, окон других приложений, однако лишь одно из них может получать реакцию от пользователя — активное окно. Пользователь использует клавиатуру, мышь и прочие устройства ввода для взаимодействия с приложением, которому принадлежит активное окно. Каждое 32-битное приложение создает, по крайней мере, одно окно, называемое главным окном, которое обеспечивает пользователя основным интерфейсом взаимодействия с приложением.

Окно приложения может содержать строку заголовка title bar (1), строку меню menu bar (2), системное меню system menu (3), кнопку сворачивания окна minimize box (4), кнопку разворачивания окна maximize box (5), рамку изменения размеров sizing border (6), клиентскую область client area (7), горизонтальную и вертикальную полосы прокрутки scroll bars (8):

Меню, строка заголовка с системными кнопками, системное меню, рамка изменения размеров и полосы прокрутки относятся к области окна, называемой неклиентской областью (non-client area). С неклиентской областью Windows справляется сама, а вот за содержимое и обслуживание клиентской области отвечает приложение.

Кроме главного окна, приложение может использовать еще и другие типы окон: управляющие элементы (controls), диалоговые окна (dialog boxes), окна-сообщения (message boxes). Управляющий элемент — окно, непосредственно обеспечивающее тот или иной способ ввода информации пользователем. К управляющим элементам относятся: кнопки, поля ввода, списки, полосы прокрутки и т.п. Управляющие элементы обычно не болтаются сами по себе, а проживают в каком-либо диалоговом окне. Диалоговое окно — это временное окно, напичканное управляющими элементами, обычно использующееся для получения дополнительной информации от пользователя. Диалоговые окна бывают модальные (modal) и немодальные (modeless). Модальное диалоговое окно требует, чтобы пользователь обязательно ввел обозначенную в окне информацию и закрыл окно прежде, чем приложение продолжит работу. Немодальное диалоговое окно позволяет пользователю, не закрывая диалогового окна, переключаться на другие окна этого приложения. Окно-сообщение — это диалоговое окно предопределенного системой формата, предназначенное для вывода небольшого текстового сообщения с одной или несколькими кнопками. Пример такого окна показан в Примере 3.

В отличие от традиционного программирования на основе линейных алгоритмов, программы для Windows строятся по принципам событийно-управляемого программирования (event-driven programming) — стиля программирования, при котором поведение компонента системы определяется набором возможных внешних событий и ответных реакций компонента на них. Такими компонентами в Windows являются окна. С каждым окном в Windows связана определенная функция обработки событий. События для окон называются сообщениями. Сообщение относится к тому или иному типу, идентифицируемому определенным кодом (32-битным целым числом), и сопровождается парой 32-битных параметров ( WPARAM и LPARAM ), интерпретация которых зависит от типа сообщения. В заголовочном файле windows.h для кодов сообщений определены константы с интуитивно понятными именами:

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

Для стандартных управляющих элементов (библиотека Common Controls Library — COMCTL32.DLL) в Windows имеются предопределенные обработчики событий, которые при наступлении интересных событий сообщают всяческую полезную информацию окну, содержащему этот управляющий элемент. Стандартная библиотека Common Dialog Box Library (COMDLG32.DLL) содержит несколько готовых весьма полезных диалоговых окон с обработчиками: диалоги выбора файла, настроек печати, выбора шрифта, выбора цвета и др. Кроме того, любая среда разработки (VisualBasic, Delphi, VisualC++ и т.п.) навязывает разработчику дополнительный набор готовых управляющих элементов и диалогов — иногда достаточно удобных, иногда не очень.

Структура программы

Программа для Win32 обычно состоит из следующих блоков:

Каждое окно принадлежит определенному классу окон. Окна одного класса имеют схожий вид, обслуживаются общей процедурой обработки событий, имеют одинаковые иконки и меню. Обычно каждое приложение создает для главного окна программы свой класс. Если приложению требуются дополнительные нестандартные окна, оно регистрирует другие классы. Стандартные диалоги и управляющие элементы принадлежат к предопределенным классам окон, для них не надо регистрировать новые классы. Чтобы определить новый класс окон, надо заполнить структуру WNDCLASS , содержащую следующие поля:

  • UINT style — стиль (поведение) класса окон,
  • WNDPROC lpfnWndProc — процедура обработки событий окна,
  • int cbClsExtra — размер дополнительной памяти в системной структуре класса для данных пользователя,
  • int cbWndExtra — размер дополнительной памяти в системной структуре окна для данных пользователя,
  • HINSTANCE hInstance — дескриптор модуля (экземпляра программы), в котором реализована процедура обработки,
  • HICON hIcon — дескриптор иконки окна,
  • HCURSOR hCursor — дескриптор курсора мыши для окна,
  • HBRUSH hbrBackground — дескриптор «кисточки» для закрашивания фона окна,
  • LPCSTR lpszMenuName — имя ресурса, содержащего меню окна,
  • LPCSTR lpszClassName — имя класса.

Класс регистрируется при помощи функции: При успешном завершении функция возвращает целочисленный код, соответствующий строке-имени класса в общесистемной таблице строк (такой код называется атомом). При ошибке возвращается 0.

Для создания окна вызывается функция:

Вместо параметров x, y, nWindth, nHeight допустимо передавать константу CW_USEDEFAULT , позволяющую операционной системе задать эти числа по ее усмотрению.

Интерпретация кода стиля определяется классом окна. Стиль определяет не только оформление окна, но и его поведение. Общие для всех классов константы стилей (при необходимости объединяются операцией побитовое ИЛИ):

  • WS_DISABLED — при создании окно заблокировано (не может получать реакцию от пользователя);
  • WS_VISIBLE — при создании окно сразу же отображается (не надо вызывать ShowWindow );
  • WS_CAPTION — у окна есть строка заголовка;
  • WS_SYSMENU — у окна есть системное меню;
  • WS_MAXIMIZEBOX — у окна есть кнопка разворачивания;
  • WS_MINIMIZEBOX — у окна есть кнопка сворачивания;
  • WS_SIZEBOX или WS_THICKFRAME — у окна есть рамка изменения размеров;
  • WS_BORDER — у окна есть рамка (не подразумевает изменение размеров);
  • WS_HSCROLL или WS_VSCROLL — у окна есть горизонтальная или вертикальная прокрутка;
  • WS_OVERLAPPED или WS_TILED — «перекрываемое» окно — обычное окно с рамкой и строкой заголовка;
  • WS_POPUP — «всплывающее» окно;
  • WS_OVERLAPPEDWINDOW — «перекрываемое» окно с системным меню, кнопками сворачивания/разворачивания, рамкой изменения размеров, короче, типичный стиль для главного окна приложения.

Во время выполнения функции CreateWindow процедуре обработки событий окна посылается сообщение WM_CREATE . При успешном выполнении функции возвращается дескриптор созданного окна, при неудаче — NULL.

После создания окна неплохо бы сделать его видимым (отобразить), если только оно не создано со стилем WS_VISIBLE: Второй параметр этой функции — код состояния отображения окна. В качестве этого кода можно взять значение четвертого параметра, с которым была запущена функция WinMain . Другие возможные значения этого параметра:

  • SW_SHOW — отобразить и активировать окно;
  • SW_HIDE — скрыть окно;
  • SW_MAXIMIZE — развернуть окно на весь экран;
  • SW_RESTORE — активировать окно и отобразить его в размерах по умолчанию;
  • SW_MINIMIZE — свернуть окно.

Если перед вызовом этой функции окно было видимым, функция возвращает TRUE , если же окно было скрыто — FALSE .

Если клиентская область главного окна приложения содержит объекты, прорисовываемые по сообщению WM_PAINT , имеет смысл прорисовать эти объекты сразу после отображения главного окна на экране. Функция UpdateWindow непосредственно вызывает процедуру обработки событий указанного окна с сообщением WM_PAINT (минуя очередь сообщений приложения):

Windows использует два способа доставки сообщений процедуре обработки событий окна:

  • непосредственный вызов процедуры обработки событий (внеочередные или неоткладываемые сообщенияnonqueued messages);
  • помещение сообщения в связанный с данным приложением буфер типа FIFO, называемый очередью сообщенийmessage queue (откладываемые сообщенияqueued messages).

К внеочередным сообщениям относятся те сообщения, которые непосредственно влияют на окно, например, сообщение активации окна WM_ACTIVATE и т.п. Кроме того, вне очереди сообщений обрабатываются сообщения, сгенерированные различными вызовами Win32 API, такими как SetWindowPos , UpdateWindow , SendMessage , SendDlgItemMessage .

К откладываемым сообщениям относятся сообщения, связанные с реакцией пользователя: нажатие клавиш на клавиатуре, движение мышки и клики. Чтобы извлечь сообщение из очереди, программа вызывает функцию Эта функция возвращает FALSE , если получено сообщение WM_QUIT , и TRUE в противном случае. Очевидно, что условием продолжения цикла обработки событий является результат этой функции. Если приложение хочет завершить свою работу, оно посылает само себе сообщение WM_QUIT при помощи функции Ее параметр — статус выхода приложения. Обычно эта функция вызывается в ответ на сообщение об уничтожении окна WM_DESTROY .

После извлечения сообщения из очереди следует вызвать функцию TranslateMessage , переводящую сообщения от нажатых клавиш в удобоваримый вид, а затем DispatchMessage , которая определяет предназначенное этому сообщению окно и вызывает соответствующую процедуру обработки событий. Результат возврата соответствует значению, которое вернула процедура обработки событий (обычно никому не нужен).

Процедура обработки сообщений окна должна быть объявлена по следующему прототипу: Значения параметров: hw — дескриптор окна, которому предназначено сообщение, msg — код сообщения, wp и lp — 32-битные параметры сообщения, интерпретация которых зависит от кода сообщения. Зачастую старший/младший байт или старшее/младшее слово параметров сообщения несут независимый смысл, тогда удобно использовать определенные в windows.h макросы:

Например, сообщение WM_COMMAND посылается окну в трех случаях:

  1. пользователь выбрал какую-либо команду меню;
  2. пользователь нажал «горячую» клавишу (accelerator);
  3. в дочернем окне произошло определенное событие.

При этом параметры сообщения интерпретируются следующим образом. Старшее слово параметра WPARAM содержит: 0 в первом случае, 1 во втором случае и код события в третьем случае. Младшее слово WPARAM содержит целочисленный идентификатор пункта меню, «горячей» клавиши или дочернего управляющего элемента. Параметр LPARAM в первых двух случаях содержит NULL , а в третьем случае — дескриптор окна управляющего элемента.

Процедура обработки событий должна вернуть определенное 32-битное значение, интерпретация которого также зависит от типа сообщения. В большинстве случаев, если сообщение успешно обработано, процедура возвращает значение 0.

Процедура обработки событий не должна игнорировать сообщения. Если процедура не обрабатывает какое-то сообщение, она должна вернуть его системе для обработки по умолчанию. Для этого вызывается функция:

Все описанное в данном параграфе суммируется в примере 4 (example4.cpp):

Приведенный пример создает окно с кнопкой «My button», при нажатии на которую вылезает окно-сообщение:

Ресурсы

Ресурсы — это бинарные данные, добавляемые в исполняемый файл при компоновке программы. К стандартным ресурсам относятся: иконки, курсоры, меню, диалоги, растровые изображения (BMP), векторные изображения (EMF), шрифты, таблицы горячих клавиш, таблицы строк, информация о версии программы или модуля. В процессе разработки программы ресурсы описывают в отдельном текстовом файле — файле описания ресурсов (расширение .rc), — а затем при помощи компилятора ресурсов переводят в бинарный вид и добавляют в исполняемый файл на этапе компоновки исполняемого файла. Использование ресурсов значительно облегчает работу программиста по визуализации графических примитивов интерфейса программы.

Файл описания ресурсов состоит из операторов, объединяемых в блоки. Один оператор занимает одну строку файла. Допускается использовать комментарии, определяемые так же, как в программе на языке Си. Файл описания ресурсов перед компиляцией так же обрабатывается препроцессором, поэтому в нем можно использовать директивы препроцессора ( #include , #define , . ) и макроопределения. В сложных «блочных» описаниях ресурсов вместо ключевых слов BEGIN и END можно использовать < и >, соответственно.

Иконки, картинки и курсоры мыши можно описать двумя способами (квадратные скобки не являются частью синтаксиса оператора и означают необязательный элемент): Здесь nameID — численный или строковой идентификатор; RESOURCETYPE — ключевое слово, обозначающее тип ресурса: ICON , BITMAP или CURSOR ; load-option и mem-option — всякие неинтересные в данный момент опции, которые можно спокойно пропустить; filename — имя файла, содержащее соответствующий ресурс.

Эти ресурсы можно внедрить в виде шестнадцатеричных кодов непосредственно в файл ресурсов:

Следует отметить, что первая иконка в ресурсах будет использоваться «Проводником» как иконка исполняемого файла.

Меню описывается следующим образом: Здесь item-definitions — один из трех операторов: Параметры операторов имеют следующий смысл: text — текст пункта меню или подменю (может содержать комбинации \t — табуляция, \a — выравнивание по правому краю, & — следующий символ подчеркивается, обозначает «горячую» клавишу для указанного пункта меню); result — целочисленный идентификатор пункта меню, посылаемый окну-владельцу через сообщение WM_COMMAND при выборе этого пункта меню; optionlist — необязательный список опций, разделенных запятой или пробелом:

  • CHECKED — рядом с пунктом меню отображается галочка,
  • GRAYED — пункт меню неактивен (не может быть выбран) и отображается серым цветом и др.


Доступ к ресурсам, скомпонованным с исполняемым файлом, можно получить при помощи следующих функций: Первый параметр этих функций — дескриптор экземпляра программы, второй — идентификатор соответствующего ресурса. Если ресурс идентифицируется не именем, а числом, то следует использовать макрос, объявленный в windows.h : Например:

Для закрепления полученных сведений, давайте добавим к примеру 4 какую-нибудь иконку и такое меню:

Для этого создаем файл ресурсов (example4a.rc):

Для перевода файла описания ресурсов в бинарный вид используется компилятор ресурсов Borland Resource Compiler: В результате получается файл example4a.res, который потребуется в процессе компоновки.

В примере 4 надо изменить строки на

Чтобы программа не была такой скучной, изменим обработчик сообщения WM_COMMAND : В результате при выборе того или иного пункта меню выводится окно-сообщение с кодом команды.

Обратите внимание: среди команд меню не используется код 1, который отведен кнопке «My button». Это типичная практика назначать всем дочерним элементам окна и командам меню разные численные идентификаторы, что облегчает обработку сообщения WM_COMMAND .

Компиляция и компоновка сложных проектов

Теперь компоновка программы будет более сложной, поэтому bcc32 с этой задачей не справится. В этом примере компилятор будет использоваться только для компилирования (запускаем с ключом ): В результате получаем объектный файл example4a.obj.

Чтобы собрать все части программы вместе, придется запускать компоновщик вручную (ilink32 или tlink32). В командной строке компоновщика указываются следующие параметры:

  • options — о допустимых опциях можно узнать, запустив компоновщик без параметров. Нам потребуются:
    • -aa — тип приложения «графическое для Win32» (другие варианты: -ap — консольное приложение, -ad — драйвер);
    • -Tpe — формат выходного файла «.EXE» (другой вариант: -Tpd — «.DLL»);
    • -L путь — путь для поиска библиотек и объектных файлов (обычно: -Lc:\bcc55\lib).
  • objfiles — список объектных файлов, из которых составляется программа, разделенных пробелом или знаком «+». Этот список должен начинаться с борландовского инициализационного объектного файла: c0w32.obj — для графического приложения под Win32 или c0x32.obj — для консольного приложения.
  • exefile — имя исполняемого файла, который получится в результате компоновки.
  • mapfile — имя файла, который после компиляции будет содержать карту сегментов вашей программы (оно вам надо? если нет, здесь делаем «пусто», а в опциях указываем -x, чтобы компоновщик не замусоривал рабочий каталог этой фигней).
  • libfiles — список библиотек, в которых надо искать не определенные в программе функции, разделенных пробелом или знаком «+». Как минимум, надо указать import32.lib, которая содержит код подключения к стандартным библиотекам Win32 API: kernel32.dll, user32.dll, gdi32.dll, advapi32.dll и др. Если вы используете какие-либо функции стандартных библиотек языка Си (stdlib, stdio, . ), надо указать еще cw32.lib.
  • deffile — файл параметров модуля (module definition file). Это текстовый файл, в котором определяются различные настройки компилируемой программы типа: размеры сегментов стека, кода, данных, «заглушка» (что будет происходить при попытке запуска программы в DOS) и проч. Если не указывать этот файл, компоновщик выберет вполне приличные для большинства случаев параметры по умолчанию.
  • resfiles — файлы ресурсов (разделяются пробелом или знаком «+»).

Компоновщик ilink32 умеет работать в пошаговом (инкрементирующем) режиме incremental linking, при этом он создает несколько файлов состояний (*.IL?). При последующих попытках компиляции он использует их, так что процесс компиляции занимает меньше времени. Чтобы отключить пошаговую компиляцию и не замусоривать рабочий каталог этими файлами, следует указать опцию -Gn. Например, если при отключенной пошаговой компиляции программа компилируется 8 секунд, то первая компиляция в пошаговом режиме займет 25 секунд, а все последующие — не более 2 секунд.

Итак, компонуем модифицированный пример 4:

Если все сделано правильно, первое, что становится сразу заметным — у исполняемого файла появилась иконка:

Эта же иконка отображается в строке заголовка главного окна программы. Под строкой заголовка отображается созданное нами меню. При выборе любой команды меню появляется окно-сообщение с кодом команды. При выборе команды «Exit» программа завершается.

Если ваш проект состоит из множества файлов, то компилировать и компоновать их вручную становится затруднительно. В таких случаях используются сценарии компиляции, которые обрабатываются программой make. Сценарий компиляции — текстовый файл с именем Makefile , описывающий зависимости между различными файлами проекта, следующего формата:

Сценарий компиляции должен содержать как минимум одно правило. Строка с командами обязательно должна начинаться с отступа табуляцией. В качестве имени правила обычно выступает имя файла, который получится в результате выполнения команд в теле правила. Зависимости — необязательный список имен файлов, разделенных пробелами, от которых зависит данное правило. Если при вызове make окажется, что хотя бы один файл из этого списка новее, чем файл-результат правила, то выполняются все команды из этого правила. В качестве зависимостей могут указываться имена файлов-названия других правил. Тогда make будет выполнять рекурсивную проверку зависимостей. Make не выполняет команды из правила, если все файлы-зависимости старее файла-результата.

Если не указывать в качестве файлов-зависимостей example4a.rc и example4a.cpp, то make не станет ничего делать, когда файл example4a.exe уже существует. Тем не менее, приведенный пример — не совсем удачный сценарий компиляции. Если мы изменим только файл ресурсов, make все равно будет перекомпилировать исходный текст. Если мы изменим только исходный текст, make будет перекомпилировать еще и ресурсы. С учетом этого замечания, более удачным будет следующий сценарий:

Если в командной строке make не указано иное, то make пытается выполнить первое правило из сценария. Именно поэтому первым правилом стоит example4a.exe — результат, который мы хотим получить после компиляции всего проекта.

Если написать подходящий сценарий компиляции, то для компиляции вашего проекта придется набирать лишь команду:

Диалоговые окна

Большинство приложений использует диалоговые окна для запроса у пользователя дополнительной информации для выполнения каких-либо команд. Например, команда открытия файла требует указания имени файла, так что приложение создает диалоговое окно, чтобы запросить у пользователя имя файла. Пока пользователь не укажет имя файла, команда не будет выполнена. После этого программа уничтожает это диалоговое окно. В этом случае используется модальное диалоговое окно. Другой пример: текстовый редактор может использовать немодальное диалоговое окно, для команды поиска. Пока редактор ищет введенную фразу, диалоговое окно остается на экране. Более того, пользователь может вернуться к редактированию текста, не закрывая диалог поиска. Либо пользователь может ввести другую фразу для поиска. Такое диалоговое окно остается открытым, пока приложение не завершится или пользователь непосредственно не выберет команду закрытия этого диалога.

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

Для создания модального диалога используется функция DialogBox , а для создания немодального диалога — CreateDialog :

Параметры: hInst — дескриптор экземпляра программы (модуля, в котором находится шаблон); template — имя ресурса, описывающего диалог; parent — дескриптор родительского окна; DlgFunc — диалоговая функция следующего формата: Параметры диалоговой функции такие же, как у обычной функции обработки событий. Отличие этой функции — она вызывается из предопределенной функции обработки событий для диалоговых окон. Она должна вернуть значение TRUE , если обработала переданное ей сообщение, или FALSE в противном случае. Она ни в коем случае не должна сама вызывать DefWindowProc .

При создании диалогового окна диалоговая процедура получает сообщение WM_INITDIALOG . Если в ответ на это сообщение процедура возвращает FALSE , диалог не будет создан: функция DialogBox вернет значение -1 , а CreateDialog — NULL .

Модальное диалоговое окно блокирует указанное в качестве родительского окно и появляется поверх него (вне зависимости от стиля WS_VISIBLE ). Приложение закрывает модальное диалоговое окно при помощи функции Приложение должно вызвать эту функцию из диалоговой процедуры в ответ на сообщение от кнопок «OK», «Cancel» или команды «Close» из системного меню диалога. Параметр result передается программе как результат возврата из функции DialogBox .

Немодальное диалоговое окно появляется поверх указанного в качестве родительского окна, но не блокирует его. Диалоговое окно остается поверх родительского окна, даже если оно неактивно. Программа сама отвечает за отображение/сокрытие окна (с помощью стиля WS_VISIBLE и функции ShowWindow ). Сообщения для немодального диалогового окна оказываются в основной очереди сообщений программы. Чтобы эти сообщения были корректно обработаны, следует включить в цикл обработки сообщений вызов функции:

Если эта функция вернула TRUE , то сообщение обработано и его не следует передавать функциям TranslateMessage и DispatchMessage .

Немодальное диалоговое окно уничтожается, если уничтожается его родительское окно. Во всех остальных случаях программа должна сама заботиться об уничтожении немодального диалогового окна, используя вызов:

Шаблон диалогового окна в ресурсах задается следующим образом:

В начале блока описания диалога задается: nameID — целочисленный или строковой идентификатор ресурса, x , y — координаты диалога на экране (или относительно родительского окна), width , height — размер диалога. Координаты и размеры диалога и всех элементов внутри него задаются в диалоговых единицах (dialog units). Одна горизонтальная диалоговая единица соответствует 1/4 средней ширины символа в системном шрифте. Одна вертикальная диалоговая единица соответствует 1/8 средней высоты символа в системном шрифте.


После заголовка блока идет ряд необязательных операторов-параметров диалога (property-statements) в любом порядке:

В качестве стиля диалога можно применять все перечисленные для обычных окон стили. Обычно выбирают: WS_POPUP , WS_SYSMENU , WS_CAPTION , а также WS_BORDER для немодального диалога и DS_MODALFRAME — для модального. Кроме того, можно использовать DS_SETFOREGROUND , чтобы при отображении диалога перевести его на передний план, даже если его родительское окно неактивно.

В теле шаблона (control-statements) перечисляются составляющие его управляющие элементы. Один из возможных вариантов оператора: Здесь text — текст управляющего элемента (заголовок), id — целочисленный идентификатор элемента 0. 65535 (внутри одного диалога идентификаторы всех элементов должны различаться), class — имя класса, к которому принадлежит управляющий элемент, style — стиль управляющего элемента, x , y , width , height — положение и размер диалогового элемента относительно клиентской области диалога в диалоговых единицах.

Вот пример диалога, содержащего простое статическое текстовое поле и кнопку «OK»:

Добавим этот диалог к ресурсам примера 4. В текст программы добавим две глобальных переменных:

Присвоим переменной h значение дескриптора экземпляра программы в самом начале функции WinMain . Это значение нам потребуется для вызова функции DialogBox .

Изменим обработчик сообщения WM_COMMAND следующим образом:

Теперь в текст программы необходимо добавить диалоговую процедуру:

При создании диалога вызывается процедура SetDlgItemText , меняющая содержание текстового поля в диалоге (элемент с , генерирующая сообщение WM_COMMAND с >Функция DlgProc должна быть определена или описана до ссылки на нее в вызове DialogBox .

Управляющие элементы

Управляющие элементы, как и другие окна, принадлежат тому или иному классу окон. Windows предоставляет несколько предопределенных классов управляющих элементов. Программа может создавать управляющие элементы поштучно при помощи функции CreateWindow или оптом, загружая их вместе с шаблоном диалога из своих ресурсов. Управляющие элементы — это всегда дочерние окна. Управляющие элементы при возникновении некоторых событий, связанных с реакцией пользователя, посылают своему родительскому окну сообщения-оповещения (notification messages) WM_COMMAND или WM_NOTIFY .

Как и любое другое окно, управляющий элемент может быть скрыт или отображен при помощи функции ShowWindow . Аналогично, управляющий элемент может быть блокирован или разблокирован при помощи функции: В качестве второго параметра передается флаг TRUE (разблокировать) или FALSE (блокировать). Функция возвращает значение TRUE , если перед ее вызовом окно было заблокировано. Узнать текущий статус блокирования окна можно при помощи функции: которая возвращает значение TRUE , если окно разблокировано.

Для многих управляющих элементов определены специальные сообщения, которые управляют видом или поведением таких элементов или позволяют получить параметры их состояния. Как и для любого другого окна эти сообщения можно отправить с помощью функции:

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

Для функции отсылки сообщений есть специальный вариант, предназначенный для более удобной работы с управляющими элементами:

Для управляющих элементов внутри диалогов специальный смысл имеют стили WS_TABSTOP и WS_GROUP . Если в диалоге имеются управляющие элементы со стилем WS_TABSTOP , то при нажатии пользователем на клавишу [Tab] (или [Shift]+[Tab]), текущий активный элемент диалога будет терять фокус и передавать его следующему за ним (или предыдущему) ближайшему элементу со стилем WS_TABSTOP . С помощью стиля WS_GROUP элементы диалога можно объединять в группы. Группа элементов начинается с элемента со стилем WS_GROUP и заканчивается элементом, после которого идет элемент со стилем WS_GROUP , или последним элементом в диалоге. Внутри группы только первый элемент должен иметь стиль WS_GROUP . Windows допускает перемещение внутри группы при помощи клавиш-стрелок.

Классы предопределенных управляющих элементов: «STATIC» Статический управляющий элемент представляет собой текстовую метку или прямоугольник. Не предоставляет пользователю ни средств ввода, ни вывода. Примеры:

Соответствующее описание ресурсов: Для текстовых статиков со стилями SS_LEFT , SS_RIGHT или SS_CENTER существуют более простые операторы объявления ресурсов: Чтобы поменять текст статика ему можно послать сообщение WM_SETTEXT ( wp=0 ; lp=(LPARAM)(LPCSTR)lpsz — адрес строки) или использовать функции: Чтобы сменить иконку или картинку нетекстового статика, надо послать ему сообщение STM_SETIMAGE ( wp=(WPARAM)fImageType — тип изображения: IMAGE_BITMAP или IMAGE_ICON ; lp=(LPARAM)(HANDLE)hImage — дескриптор иконки или картинки). «BUTTON» Кнопка — это небольшое прямоугольное дочернее окно, обычно имеющее два состояния: нажато/отпущено или включено/выключено. Пользователь меняет состояние этого элемента щелчком мыши. К этому классу относятся: кнопки-«давилки» (push buttons), кнопки-«галочки» (check boxes), «радио»-кнопки (radio buttons) и специальный тип групповых рамочек (group boxes). Примеры:

Соответствующее описание ресурсов: Для кнопок существуют более простые операторы объявления ресурсов: Разница между стилями BS_xxx и BS_AUTOxxx заключается в том, что при щелчке по AUTO -кнопкам Windows сама автоматически переключает их состояние. Для не AUTO -кнопок это надо делать вручную в диалоговой процедуре, послав сообщение BM_SETCHECK ( wp=(WPARAM)fCheck — флаг: BST_UNCHECKED , BST_CHECKED или BST_INDETERMINATE (для BS_3STATE -кнопок); lp=0 ) или при помощи функций: Автоматические радио-кнопки должны быть объединены в группу при помощи стиля WS_GROUP , чтобы Windows корректно их обрабатывала.
Проверить состояние кнопки можно, послав ей сообщение BM_GETCHECK ( wp=0; lp=0 ) или вызовом функции: При щелчке мыши по кнопке она присылает родительскому диалогу сообщение-оповещение WM_COMMAND ( HIWORD(wp)=BN_CLICKED; LOWORD(wp)=(int) >). «EDIT» Поле редактирования предназначено для ввода пользователем текста с клавиатуры. Щелчком мыши внутри элемента пользователь передает этому элементу фокус ввода (input focus). При этом внутри элемента появляется текстовый курсор — мигающая каретка. Пользователь может использовать мышь для перемещения каретки по полю редактирования и выделению текста в этом поле. Примеры:

Соответствующее описание ресурсов: Стиль ES_WANTRETURN означает, что кнопка [Enter] будет обрабатываться самим элементом, а не передаваться диалогу. Благодаря этому стилю оказался возможен переход на новую строчку для предложения «Она съела кусок. » (на картинке).
По умолчанию текстовые поля позволяют вводить столько текста, сколько может отобразиться в рамках поля. Чтобы предоставить пользователю возможность ввести больше текста, надо использовать стиль ES_AUTOHSCROLL (и ES_AUTOVSCROLL для многострочных полей).
Для текстовых полей существует более простой оператор объявления ресурсов: Чтобы поменять содержимое текстового поля, программа вызывает функцию SetDlgItemText . Чтобы получить текущее содержимое текстового поля, используется функция: Чтобы узнать размер строки в текстовом поле, надо послать элементу сообщение WM_GETTEXTLENGTH ( wp=0; lp=0 ).
Текстовое поле посылает родительскому диалогу следующие сообщения-оповещения WM_COMMAND ( LOWORD(wp)=(int) >):

  • HIWORD(wp)=EN_KILLFOCUS — текстовое поле потеряло фокус (фокус передан другому элементу диалога);
  • HIWORD(wp)=EN_SETFOCUS — текстовое поле получило фокус;
  • HIWORD(wp)=EN_CHANGE — пользователь изменил текст в поле;
  • HIWORD(wp)=EN_ERRSPACE — закончилось место, отведенное под текстовый буфер управляющего элемента.

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

Соответствующее описание ресурсов: или в короткой форме: Для добавления элемента к списку следует послать ему сообщение LB_ADDSTRING ( wp=0; lp=(LPARAM)(LPCSTR)lpsz — строка для добавления). Для того, чтобы заполнить один из списков, показанных на рисунке, в обработчик сообщения WM_INITDIALOG в диалоговую процедуру был вставлен такой фрагмент: Кроме этого, список «понимает» следующие сообщения:

  • LB_DELETESTRING ( wp=(WPARAM)index; lp=0 ) — удалить элемент с указанным номером;
  • LB_INSERTSTRING ( wp=(WPARAM)index; lp=(LPARAM)(LPCSTR)lpsz ) — вставить указанную строку в список как элемент с индексом index;
  • LB_FINDSTRING ( wp=(WPARAM)indexStart; lp=(LPARAM)(LPTSTR)lpszFind ) — найти элемент, содержащий указанную строку (поиск ведется, начиная с элемента indexStart), результат сообщения — номер элемента, удовлетворяющего критерию, или LB_ERR ;
  • LB_GETCOUNT ( wp=0; lp=0 ) — количество элементов в списке;
  • LB_GETCURSEL ( wp=0; lp=0 ) — выделенный элемент в списке;
  • LB_RESETCONTENT ( wp=0; lp=0 ) — удалить все элементы из списка.

Окно-список посылает родительскому диалогу следующие сообщения-оповещения WM_COMMAND ( LOWORD(wp)=(int) >):

  • HIWORD(wp)=LBN_DBLCLK — пользователь дважды щелкнул мышью по списку;
  • HIWORD(wp)=LBN_SELCHANGE — пользователь выделил другой элемент в списке (или отменил выделение).

«COMBOBOX» Комбобокс — это помесь поля редактирования с окном-списком. Этот элемент содержит поле редактирование и список, который может отображаться все время либо «выпадать» при нажатии на кнопку рядом с полем редактирования. Есть три основных типа комбобоксов:

  • «выпадающий» комбобокс ( CBS_DROPDOWN ) содержит поле редактирования и «выпадающий» список;
  • «выпадающий» список ( CBS_DROPDOWNLIST ) не содержит поля для изменения текста;
  • простой комбобокс ( CBS_SIMPLE ) содержит поле редактирования и обычный список.

Обратите внимание, что в ресурсах значение высоты элемента определяет размер поля редактирования вместе с «выпавшим» списком по вертикали. Короткий вариант этого же объявления ресурсов: Для работы с комбобоксами существуют сообщения, аналогичные списковым: CB_ADDSTRING , CB_DELETESTRING , CB_INSERTSTRING , CB_FINDSTRING , CB_GETCOUNT , CB_GETCURSEL , CB_RESETCONTENT .
Комбобокс посылает родительскому диалогу сообщение оповещение WM_COMMAND со следующими кодами оповещения:

  • CBN_SELCHANGE , когда пользователь выделяет другую строку в комбобоксе (бывает полезным для простых комбобоксов);
  • CBN_SELENDOK , когда пользователь выбрал элемент в выпадающем списке и щелкнул мышкой по выделению (подтвердил выделение), для простых комбобоксов посылается перед каждым CBN_SELCHANGE ;
  • CBN_SELENDCANCEL , когда пользователь закрыл выпадающий список, так и не выбрав никакой элемент;
  • CBN_DROPDOWN , когда открывается выпадающий список;
  • CBN_CLOSEUP , когда выпадающий список был закрыт по той или иной причине.

Кроме предопределенных управляющих элементов, Windows предоставляет еще набор стандартных управляющих элементов посредством библиотеки Common Controls Library (COMCTL32.DLL). Чтобы воспользоваться ей, в тест программы надо включить заголовочный файл commctrl.h и добавить в блок инициализации программы вызов функции:

Управляющие элементы из этой библиотеки, как правило, посылают сообщения-оповещения родительскому диалогу через сообщение WM_NOTIFY ( wp=(int) > — указатель на структуру со специльными параметрами сообщения-оповещения).

Классы управляющих элементов из Common Controls Library: List View Controls ( WC_LISTVIEW ) Элемент просмотра списков — это окно отображающее совокупность элементов. Каждый элемент может быть представлен текстовой меткой и (необязательно) иконкой. Типичный пример использования этого элемента — программа «Проводник». Содержимое того или иного каталога представляется в виде элемента просмотра списков. Есть четыре основных стиля для этого элемента:

  • крупные иконки — стиль LVS_ICON ;
  • мелкие иконки — стиль LVS_SMALLICON ;
  • список — стиль LVS_LIST ;
  • таблица — стиль LVS_REPORT .

Приведенные в примере списки заполнялись в диалоговой процедуре при инициализации диалога ( WM_INITDIALOG ): Status Windows ( STATUSCLASSNAME ) Поле статуса — это горизонтальное окно в нижней части родительского окна, которое программа обычно использует для отображения каких-либо характеристик, параметров или небольших текстовых сообщений.

В примере 4б можно заменить статическое текстовое поле на поле статуса: При создании поля статуса не требуется указывать ни размер, ни позицию окна, Windows сама выберет эти параметры подходящим образом. Для создания поля статуса можно использовать специальную функцию: С помощью сообщения SB_SETPARTS поле статуса можно разбить на части ( wp=(int)nParts — количество частей; lp=(LPARAM)(int*)widths — указатель на массив размеров частей). В таком случае текст для каждой части поля статуса задается сообщением SB_SETTEXT ( wp=(int)iPart — номер части; lp=(LPARAM)(LPSTR)lpszText — текстовая строка). Пример: Up-Down Controls ( UPDOWN_CLASS ) Управляющий элемент «up-down» представляет собой пару небольших кнопок-стрелок, нажимая которые, пользователь увеличивает или уменьшает значение. Этот элемент, как правило, связывается с элементом-компаньоном (buddy window), обычно реализованным в виде поля редактирования. Для пользователя элемент «up-down» и его компаньон представляются единым управляющим элементом.
Если при создании элемента «up-down» указать стиль UDS_AUTOBUDDY , то компаньоном будет назначен предыдущий управляющий элемент диалога. Программа может также передать дескриптор окна-компаньона при помощи сообщения UDM_SETBUDDY ( wp=(WPARAM)(HWND)hwndBuddy — дескриптор окна-компаньона; lp=0 ). Если элементу «up-down» назначить стиль UDS_SETBUDDYINT , то он будет автоматически менять текст окна-компаньона, представляющий числовое значение.
Другой способ создать элемент «up-down» — использовать функцию Progress Bars ( PROGRESS_CLASS ) Полоса прогресса — это окно, которое программа может использовать для индикации состояния выполнения какой-либо длительной операции. Окно представляет собой прямоугольник, заполняемый системным цветом слева направо.
Каждый раз, когда приложение посылает этому окну сообщение PBM_STEPIT ( wp=0; lp=0 ), заполнение полосы прогресса продвигается дальше вправо на некоторое значение. Tooltip Controls ( TOOLTIPS_CLASS ) Окно-подсказка — всплывающее окно, содержащее строку описательной информации о том или ином элементе интерфейса программы. Таким элементом интерфейса может быть конкретное окно (управляющий элемент) или прямоугольный участок клиентской области какого-либо окна. Большую часть времени подсказка скрыта. Она появляется, когда пользователь задерживат курсор мыши над тем или иным элементом интерфейса программы более, чем на полсекунды. Подсказка скрывается, когда пользователь кликает мышью или уводит курсор с этого элемента. Одно окно-подсказка может обслуживать любое количество элементов интерфейса. Чтобы назначить тому или иному элементу интерфейса программы подсказку, надо окну-подсказке послать сообщение TTM_ADDTOOL ( wp=0; lp=(LPARAM)(TOOLINFO*)lpti — указатель на структуру, содержащую информацию об элементе). Пример:
Property Sheets & Tab Controls Элементы вкладки свойств и переключатели вкладок обычно используются совместно. Пример использования вкладок:

Каждая вкладка содержит свой набор управляющих элементов и может задаваться в ресурсах так же, как и отдельный диалог: Для создания диалога с вкладками используется функция PropertySheet , перед вызовом которой надо заполнить соответствующие системные структуры: Для каждой вкладки может быть своя диалоговая процедура, а может быть общая для всех вкладок (как в этом примере). Trackbars ( TRACKBAR_CLASS ) Ползунок (бегунок) используется, если от пользователя требуется получить дискретное значение из определенного диапазона. Маркер ползунка пермещается на заданное программой значение. Пример ползунка показан на первой вкладке предыдущего примера. Ползунки бывают горизонтальные ( TBS_HORZ ) или вертикальные ( TBS_VERT ). Диапазон значений ползунка задается сообщением TBM_SETRANGE ( wp=(BOOL)fRedraw — перерисовать маркер после изменения диапазона; lp=MAKELONG(lMinimum,lMaximum) — диапазон значений: младшее слово — минимальное значение, старшее слово — максимальное значение). Переместить ползунок можно при помощи сообщения TBM_SETPOS ( wp=TRUE ; lp=(LONG)position — новая позиция ползунка). Чтобы получить текущее значение ползунка, следует послать ему сообщение TBM_GETPOS ( wp=0; lp=0 ). Ползунок оповещает родительское окно о событиях через сообщение WM_HSCROLL ( LOWORD(wp)=ScrollCode — код события; HIWORD(wp)=posistion — позиция маркера ползунка; lp=(HWND)hwndTrackBar — дескриптор элемента). Toolbars ( TOOLBARCLASSNAME ) Панель инструментов — это окно, содержащее набор кнопок, посылающих командное сообщение родительскому окну, когда пользователь щелкает по ним. Как правило, кнопки на панели инструментов соответствуют часто используемым командам меню приложения. Панель инструментов располагается ниже строки меню.

Информация о кнопках передается панели инструментов через структуру TBBUTTON , а для создания окна панели инструментов удобно использовать функцию CreateToolbarEx . Rich Edit Controls ( RICHEDIT_CLASS ) Продвинутое поле редактирования является развитием класса «EDIT» стандартных управляющих элементов. Элементы управления этого класса поддерживают форматирование текста (по отдельным символам и по отдельным абзацам) и позволяют внедрять OLE-объекты. Tree View Controls ( WC_TREEVIEW ) Элемент просмотра дерева позволяет представлять информацию об иерархии некоторых объектов (содержание документа, дерево каталогов файловой системы и т.п.) Каждый объект может быть представлен текстовой меткой и иконкой. Объект может иметь иерархию дочерних объектов, которая раскрывается по щелчку на этом элементе.

Стандартные диалоги

Windows предоставляет набор готовых стандартных диалогов посредством библиотеки Common Dialog Boxes Library (COMDLG32.DLL): диалог открытия и сохранения файла, диалог печати документа, диалог выбора цвета, шрифта и т.п. Чтобы создать один из перечисленных диалогов, надо заполнить определенную структуру и вызвать соответствующую функцию из этой библиотеки:

  • BOOL WINAPI ChooseColor(CHOOSECOLOR* lpcc) — создает диалог, отображающий палитру цветов и позволяющий пользователю выбрать тот или иной цвет или создать свой.
  • BOOL WINAPI ChooseFont(CHOOSEFONT* lpcf) — создает диалог, отображающий имена установленных в системе шрифтов, их кегль, стиль начертания и т.п.
  • BOOL WINAPI GetOpenFileName(OPENFILENAME* lpofn) и BOOL WINAPI GetSaveFileNAme(OPENFILENAME* lpofn) — создают диалог, отображающий содержимое того или иного каталога, и позвояющий пользователю выбрать уникальное имя файла для открытия или сохранения.
  • BOOL WINAPI PrintDlg(PRINTDLG* lppd) — создает диалог, позволяющий пользователю установить различные опции печати, например, диапазон страниц, количество копий и др.
  • BOOL WINAPI PageStupDlg(PAGESETUPDLG* lppsd) — создает диалог, позволяющий пользователю выбрать различные параметры страницы: ориентацию, поля, размер бумаги и т.п.
  • HWND WINAPI FindText(FINDREPLACE* lpfr) — создает диалог, позволяющий пользователю ввести строку для поиска и такие опции, как направление поиска.
  • HWND WINAPI ReplaceText(FINDREPLACE* lpfr) — создает диалог, позволяющий пользователю ввести строку для поиска, строку для замены и опции замены (направление поиска, область поиска).

Все перечисленные диалоги, кроме последних двух, — модальные, т.е. указанная функция не вернет значение, пока пользователь тем или иным способом не закроет диалог. Значение TRUE означает, что пользователь закрыл диалог, нажав на «ОК», а соответствующая структура заполнена новыми значениями. Значение FALSE означает, что пользователь нажал на [Esc], выбрал команду системного меню «Закрыть» или нажал кнопку «Отмена», а соответствующая структура осталась неизменной. Пример использования диалога открытия файла:

Немодальный диалог в качестве главного окна

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

Пример 5 демонстрирует использование немодального диалога в приложении типа «блокнот».

Файл example5.h содержит константы-идентификаторы команд меню и элементов диалога.


Файл example5.rc описывает ресурсы программы: иконку, меню и шаблон диалога.

Файл example5.cpp — текст программы.

Windows API Index

The following is a list of the reference content for the Windows application programming interface (API) for desktop and server applications.

Using the Windows API, you can develop applications that run successfully on all versions of Windows while taking advantage of the features and capabilities unique to each version. (Note that this was formerly called the Win32 API. The name Windows API more accurately reflects its roots in 16-bit Windows and its support on 64-bit Windows.)

User Interface

The Windows UI API create and use windows to display output, prompt for user input, and carry out the other tasks that support interaction with the user. Most applications create at least one window.

Все про w32api

Далее нам рассказывают про “архитектуру, управляемую событиями – @21” и “оконную процедуру – @22
Из этих 2 тем необходимо понять следующее:
Оконная процедура – это функция, которая обрабатывает заранее определенные (заданные через #define) события.
Эта функция является callback (если в вашем бэграунде есть javascript или java, вам будет легче понять). Эту фунцию мы сами никогда не вызываем. Управление передается ей только при обработки очередного события в”очереди событий“. А эта очередь собирается из системных событий и событий, которые формирует пользователь, нажимая на всякие кнопочки.

@23 – Оконные классы

@24 – Цикл обработки сообщений

@24 – Первая программа

  1. Она создает предопределенное диалоговое окно
  2. Предопределенный класс содержит свою оконную функцию
  3. Для этой функции Windows создает невидимый цикл обработки сообщений

@31 – Hello World

@32 – Регистрация класса окна

@ 35 – Создание окна

Окно создается непосредственно при вызове функции CreateWindow. Этой функцией мы будем пользоваться довольно часто. Как минимум мы вызовем ее для создания нашего главное окна. А потом она мы будем использовать ее для создания предопределенных окон (например BUTTON, EDIT, STATIC… )

  • lpClassName – имя зарегистрированного класса (при создание главного окна совпадает с тем, что мы ввели в wn.lpszClassName)
  • x, y, nWidth, nHeight – размеры и координаты окна (no comments)
  • hWndParent – для основного окна NULL, для дочерних придется присваивать descriptor основного
  • hMenu – будем использовать исключительно с основным окном (а меню создадим при помощи ресурсов)

@39 – Отображение окна на экране

Вы думали, что создав окно оно сразу появиться на экране? Пффф… Вы плохо знаете мелко-мягких. Неее, вещь нужная. Я ее использовал в своем курсаче. Потом поймете зачем. Она очень простая, поэтому акцентироваться на ней не буду. Скажу только об одном интересном моменте: если мы зарегистрировали дочерние элементы в главном окне, а потом вызвали функцию ShowWindow для главного, то дочерние элементы тоже отобразятся.

@40 – Обработка сообщений

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

@42 – Оконная процедура

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

В этот раз для нас важны все параметры

  • uMsg (у меня в проекте это message) – мы будем использовать, для того, чтобы определить какое именно сообщение мы обрабатываем: WM_PAINT или WM_COMMAND или еще что-то, что нам не интересно. Обязательна дефолтная обработка сообщений:
  • wParam и lParam – используются для передачи дополнительной информации в сообщении. Для каждого сообщения придется читать документацию, чтобы знать что искать в этих параметрах. Чаще всего мы будем пользоваться первым wParam

Для этого используется return 0;

@42 – Обработка сообщения WM_PAINT

При обработке этого сообщения мы будем перерисовывать недействительную часть окна. Это понятие очень важно. Немного расскажу о принципе:

  1. Рекомендую разделять логику и рисование в программе. Так вам будет легче создавать и, упаси Господь, сопровождать программу.
  2. Предположим в ответ на наше действие изменился текст(цвет, размер, координаты) какого-либо элемента (сейчас нам это не важно). По первому правилу, мы изменили текст (цвет…), а в WM_PAINT написали код для вывода нашего элемента. Так вот, пока мы не объявим, что какая-либо часть клиентского окна недействительна, WM_PAINT никогда не вызовется (есть несколько сообщений, которые по умолчанию генерируют сообщение WM_PAINT, например перемещение WM_MOVE, изменение размера окна WM_SIZE …).
  3. Забегая вперед скажу, что для того, чтобы объявить, что вся клиентская область недействительно (и как следствие перерисовать ее) это вызывать функцию InvalidateRect(hWnd, NULL, TRUE); после кода обработки сообщения, в котором мы поменяли текст (цвет…)

Стандартная структура обработки сообщения WM_PAINT:

Все про w32api


В этом уpоке мы создадим Windows пpогpаммы, котоpая отобpажает полнофункциональное окно на pабочем столе.

Скачайте файл пpимеpа здесь.

Windows пpогpаммы для создания гpафического интеpфейса пользуются функциями API. Этот подход выгоден как пользователям, так и пpогpаммистам. Пользователям это дает то, что они не должны изучать интеpфейс каждой новой пpогpаммы, так как Windows пpогpаммы похожи дpуг на дpуга. Пpогpаммистам это выгодно тем, что GUI-функции уже оттестиpованы и готовы для использования. Обpатная стоpона — это возpосшая сложность пpогpаммиpования. Чтобы создать какой-нибудь гpафический объект, такой как окно, меню или иконка, пpогpаммист должен следовать должны следовать стpогим пpавилам. Hо пpоцесс пpогpаммиpования можно облегчить, используя модульное пpогpаммиpование или OOП-философию. Я вкpатце изложу шаги, тpебуемые для создания окна:

  1. Взять хэндл вашей пpогpаммы (обязательно)
  2. Взять командную стpоку (не нужно до тех поp, пока пpогpамме не потpебуется ее пpоанализиpовать)
  3. Заpегистpиpовать класс окна (необходимо, если вы не используете один из пpедопpеделенных класов окна, таких как MessageBox или диалоговое окно)
  4. Создайте окно (необходимо)
  5. Отобpазите его на экpане
  6. Обновить содеpжимое экpана на окне
  7. Запустите бесконечный цикл, в котоpом будут пpовеpятся сообщения от опеpационной системы.
  8. Пpибывающие сообщения пеpедаются специальной функции, отвечающая за обpаботку окна
  9. Выйти из пpогpаммы, если пользователь закpывает окно.

Как вы можете видеть, стpуктуpа Windows пpогpаммы довольно сложна по сpавнению с досовской пpогpаммой. Hо миp Windows pазительно отличается от миpа DOS’а. Windows пpогpаммы должны быть способными миpно сосуществовать дpуг с дpугом. Они должны следовать более стpогим пpавилам. Вы, как пpогpаммист, должны быть более внимательными к вашим стилю пpогpаммиpованию и пpивычкам.

Hиже пpиведен исходник нашей пpогpаммы пpостого окна. Пеpед тем как углубиться в описание деталей пpогpаммиpования на ассемблеpе под Win32, я покажу вам несколько тpюков, могущие облегчить пpогpаммиpование.

Вам следует поместить все константы, стpуктуpы и функции, относящиеся к Windows в начале вашего .asm файла. Это съэкономит вам много сил и вpемени. В настоящее вpемя, самый полный include файл для MASM — это hutch’евский windows.inc, котоpый вы можете скачать с его или моей стpаницы. Вы также можете опpеделить ваши собственные константы и стpуктуpы, но лучше поместить их в отдельный файл.

Используйте диpективу includelib, чтобы указать библиотеку импоpта, использованную в вашей пpогpамме. Hапpимеp, если ваша пpогpамма вызывает MessageBox, вам следует поместить стpоку «includelib user32.lib» в начале кода. Это укажет компилятоpу на то, что пpогpамма будет использовать функции из этой библиотеки импоpта. Если ваша пpогpамма вызывает функции из более, чем одной библиотеки, пpосто добавьте соответствующую диpективу includelib для каждой из используемых библиотек. Используя эту диpективу, вы не должны беспокоиться о библиотеках импоpта во вpемя линковки. Вы можете использовать ключ линкеpа /LIBPATH, чтобы указать, где находятся эти библиотеки.

Объявляя пpототипы API функций, стpуктуp или констант в вашем подключаемом файле, постаpайтесь использовать те же имена, что и в windows include файлах, пpичем pегистp важен. Это избавит вас от головной боли в будущем.

Используйте makefile, чтобы автоматизиpовать пpоцесс компиляции и линковки. Это избавит вас лишних усилий. (Лично я использую wmake из пакета Watcom C/C++ — пеpеводчик.)

Все про w32api

В этом pазделе мы научимся как «pисовать» текст в клиентской части окна. Мы также узнаем о контекстах устpойств.

Вы можете скачать исходный код здесь.

Текст в Windows — это вид GUI объекта. Каждый символ создан из множества пикселей (точек), котоpые соединены в pазличные pисунки. Вот почему мы «pисуем» их, а не «пишем». Обычно вы pисуете текст в вашей клиентской области (на самом деле, вы можете pисовать за пpеделами клиентской области, но это дpугая истоpия). Помещения текста на экpан в Windows pазительно отличается от того, как это делается в DOS’е. В DOS’е pазмеpность экpана 80×25. Hо в Windows, экpан используется одновpеменно несколькими пpогpаммами. Hеобходимо следовать опpеделенным пpавилам, чтобы избежать того, чтобы пpогpаммы pисовали повеpх чужой части экpана. Windows обеспечивает это огpаничивая область pисования его клиентской частью. Размеp клиентской части окна совсем не константа. Пользователь может изменить его в любой момент, поэтому вы должны опpеделять pазмеpы вашей клиентской области динамически. Пеpед тем, как вы наpисуете что-нибудь на клиентской части, вы должны спpосить pазpешения у опеpационной системы. Действительно, тепеpь у вас нет абсолютного контpоля над экpаном, как это было в DOS’е. Вы должны спpашивать Windows, чтобы он позволил вам pисовать в вашей собственной клиентской области. Windows опеpделит pазмеp вашей клиентской области, фонт, цвета и дpугие гpафические аттpибуты и пошлет хэндл контекста устpойства (device context) пpогpамме. Тогда вы сможете использовать его как пpопуск к pисованию.

Что такое контекст устpойства? Это всего стpуктуpа данных, использующаяся Windows внутpенне. Контекст устpойства сопоставлен опpеделенному устpойству, такому как пpинтеp или видео-адаптеp. Для видеодисплея, контекст устpойства обчно сопоставлен опpеделенному окну на экpане.

Hекотоpые из значений в этой стpуктуpе — это гpафические аттpибуты, такие как цвета, фонт и т.д. Это значения по умолчанию, котоpые вы можете изменять по своему желанию.

Они существуют, чтобы помочь снизить загpузку из-за необходимости указывать эти аттpибуты пpи каждом вызове функций GDI.

Когда пpогpамме нужно отpисовать что-нибудь, она должна получить хэндл контекста устpойства. Как пpавило, есть несколько путей достигнуть этого.

  • Вызовите BeginPaint в ответ на сообщение WM_PAINT.
  • Вызовите GetDC в ответ на дpугие сообщения.
  • Вызовите CreateDC, чтобы создать ваш собственный контекст устpойства.

Вы должны помнить одну вещь. После того, как вы пpоделали с хэндлом контекста устpойства все, что вам было нужно в pамках ответа на одно сообщения, вы должны освободить этот хэндл.

Hельзя делать так: получить хэндл, обpабатывая одно сообщение, и освободить его, обpабатывая дpугое.

Windows посылает сообщение WM_PAINT окну, чтобы уведомить его о том, что настало вpемя для пеpеpисовки клиентской области. Windows не сохpаняет содеpжимое клиентской части окна. Взамен, когда пpоисходить ситуация, служащая основанием для пеpеpисовки окна, Windows помещает в очеpедь сообщений окна WM_PAINT. Окно должно само пеpеpисовать свою клиентскую область. Вы дожны поместить всю инфоpмацию о том, как пеpеpисовывать клиентскую область в секции WM_PAINT вашей пpоцедуpы окна, так чтобы она могла отpисовать всю клиентскую часть, когда будет получено сообщение WM_PAINT. Также вы должны пpедставлять себе, что такое invalid rectangle. Windows опpеделяет i.r. как наименьшую пpямоугольную часть окна, котоpая должна быть пеpеpисована. Когда Windows обнаpуживает i.r. в клиентской области окна, оно посылает сообщение WM_PAINT этому окну. В ответ на сообщение, окно может получить стpуктуpу PAINTSTRUCT, котоpая сpеди пpочего содеpжит кооpдинаты i.r.. Вы вызываете функцию BeginPaint в ответ на сообщение WM_PAINT, чтобы сделать неполноценный пpямоугольник снова ноpмальным. Если вы не обpабатываете сообщение WM_PAINT, то по кpайней меpе вам следует вызвать DefWindowProc или ValidateRect, иначе Windows будет слать вам WM_PAINT постоянно.

Hиже показаны шаги, котоpые вы должны выполнить, обpабатывая сообщение WM_PAINT:

  • Получить хэндл контекста устpойства с помощью BeginPaint.
  • Отpисовать клиентскую область.
  • Освободить хэндл функцией EndPaint.

Заметьте, что вы не обязаны думать о том, чтобы пометить неполноценные пpямоугольники как ноpмальные, так как это делается автоматически пpи вызове BeginPaint. Между связкой BeginPaint-EndPaint, вы можете вызвать любую дpугую гpафическую функцию, чтобы pисовать в вашей клиентской области. Пpактически все из них тpебуют хэндл контекста устpойства.

Мы напишем пpогpамму, обpажающую текстовую стpоку «Win32 asstmble is great and easy!» в центpе клиентской области.

Большая часть этого кода точно такая же, как и пpимеp из уpока 3. Я объясню только важные изменения.

Это несколько пеpеменных, использующихся в нашей секции WM_PAINT. Пеpеменная hdc используется для сохpанения хэндла контекста устpойства, возвpащенного функцией BeginPaint. ps — это стpуктуpа PAINTSTRUCT. Обычно вам не нужны значения этой стpуктуpы. Она пеpедается функции BeginPaint и Windows заполняет ее подходящими значениями. Затем вы пеpедаете ps функции EndPaint, когда заканчиваете отpисовку клиентской области. rect — это стpуктуpа RECT, опpеделенная следующим обpазом:

Left и top — это кооpдинаты веpнего левого угла пpямоугольника. Right и bottom — это кооpдинаты нижнего пpавого угла. Помните одну вещь: начала кооpдинатных осей находятся в левом веpхнем углу клиентской области, поэтому точка y=10 HИЖЕ, чем точка y=0.

В ответ на сообщение WM_PAINT, вы вызываете BeginPaint, пеpедавая ей хэндл окна, в котоpом вы хотите pисовать и неинициализиpованную стpуктуpу типа PAINTSTRUCT в качестве паpаметpов. После успешного вызова, eax содеpжит хэндл контекста устpойства. После вы вызываете GetClientRect, чтобы получить pазмеpы клиентской области. Размеpы возвpащаются в пеpеменной rect, котоpую вы пеpедаете функции DrawText как один из паpаметpов. Синтаксис DrawText’а таков:

DrawText = это высокоуpовневая API функция вывода текста. Она беpет на себя такие вещи как пеpенос слов, центpовка и т.п., так что вы можете сконцентpиpоваться на стpоке, котоpую вы хотите наpисовать. Ее низкоуpовневый бpат, TextOut, будет описан в следующем уpоке. DrawText подгоняет стpоку под пpямоугольник. Она использует выбpанный в настоящее вpемя фонт, цвет и фон для отpисовки текста. Слова пеpеносятся так, чтобы стpока влезла в гpаницы пpямоугольника. DrawText возвpащает высоту выводимого текста в единицах устpойства, в нашем случае в пикселях. Давайте посмотpим на ее паpаметpы:

  • hdc — хэндл контекста устpойства
  • lpString — указатель на стpоку, котоpую вы хотите наpисовать в пpямоугольнике. Стpока должна заканчиваться NULL’ом, или же вам пpидется указывать ее длину в следующем паpаметpе, nCount.
  • nCount — количество символов для вывода. Если стpока заканчивается NULL’ом, nCount должен быть pавен -1. В пpотивоположном случае, nCount должен содеpжать количество символов в стpоке.
  • lpRect — указатель на пpямоугольник (стpуктуpа типа RECT), в котоpом вы хотите pисовать стpоку. Заметьте, что пpямоугольник огpаничен, то есть вы не можете наpисовать стpоку за его пpеделами.
  • uFormat — значение, опpеделяющее как стpока отобpажается в пpямоугольнике. Мы используем тpи значение, скомбиниpованные опеpатоpом «or»:
    • DT_SINGLELINE указывает, что текст будет pасполагаться в одну линию
    • DT_CENTER центpиpует текст по гоpизонтали
    • DT_VCNTER центpиpует тест по веpтикали. Должен использоваться вместе с DT_SINGLELINE.

После того, как вы отpисовали клиентскую область, вы должны вызвать функцию EndPaint, чтобы освободить хэндл устpойства контекста.

Вот и все. Мы можем указать главные идеи:

  • Вы вызываете связку BeginPaint-EndPaint в ответ на сообщение WM_PAINT. Делайте все, что вам нужно с клиентской областью между вызовами этих двух функций.
  • Если вы хотите пеpеpисовать вашу клиентскую область в ответе на дpугие cообщения, у вас есть два выбоpа:
    • Используйте связку GetDC-ReleaseDC и делайте отpисовку между вызовами этих функций.
    • Вызовите Invalidaterect или UpdateWindow, чтобы Windows послала сообщение WM_PAINT вашему окну.

КАК рисовать в Win32 API?

Обществом преподавателей информатики замечено, что очень многие, при изучении нового языка программирования, прежде всего интересуются его графическими возможностями. Видимо, ещё с детства в нас не остыл интерес к красивым разноцветным кружочкам и овалам. Как вы и думали, API даёт в этом плане огромнейшую свободу, ибо всё, что знает Windows о рисовании, она знает от API.
Разноцветные геометрические фигуры, которые можно заливать любым цветом, эллипсы, окружности, прямоугольники, линии. Во введении я уже говорил про кисти и перья. Эта важнейшие особенности API дают нам возможность заливать фигуры не только сплошным покровом, а линии делать пунктирными и штрих-пунктирными.
С текстом мы вроде как разобрались, теперь переходим к нашим любимым графическим примитивам. Так как в этой главе мы будем изучать почти все графические функции, предлагаю сделать заготовочку, в которую можно примерять новые изученные функции.

КАК и где вставлять графические функции?

Сам текст программы ничем не отличается от предыдущих. Рассмотрим лишь сообщение WM_PAINT. Я покажу куда рисовать.


case WM_PAINT :
hdc=BeginPaint(hWnd, &ps);
//здесь можно вставить какие-нибудь функции рисования
.

//обновляем окно
ValidateRect(hWnd, NULL);
//заканчиваем рисовать
EndPaint(hWnd, &ps);
break;

Графические функции GDI:
1. Вывод точки. SetPixel устанавливает заданный цвет в точке с указанными координатами:
COLORREF SetPixel(HDC hDC, int x, int y, COLORREF crColor);

Пример:
SetPixel(hDC, 10,10, RGB(0,0,0));
Функция GetPixel соответственно возвращает цвет в заданных координатах.
COLORREF Getpixel(hDC, int x, int y);

2. Рисование линий.
BOOL LineTo(hDC, int x, int y);
Функция рисует линию от текущей позиции до места, указанного в аргументах. Чтобы изменить тип линии (толщину, стиль)- меняется тип пера. Но об этом позже.

Так как в отличие от многих других подходов, в GDI нет функции рисования линии от одного указанного места до другого, её можно создать самому. Она будет соединять линией точки с координатами: x1,y1 и x2,y2.

BOOL Line(HDC hdc, int x1, int y1, int x2, int y2)
<
MoveToEx(hdc, x1, y1, NULL); //сделать текущими координаты x1, y1
return LineTo(hdc, x2, y2);
>

3. Дуга
BOOL Arc(hDC, int left, int top, int right, int bottom, int x1, int y1, int x2, int y2);
Первые четыре аргумента — левый верхний и правый нижний углы прямоугольника, в который вписан эллипс. Остальные значения — координаты точек, от которых будут проведены прямые к центру эллипса. В местах пересечения первой и второй прямой с радиусом эллипса, начинается и кончается дуга.

4. Прямоугольник. По умолчанию прозрачный, а вообще, тип его заливки определяется текущей кистью. По умолчанию она тоже прозрачная.
BOOL Rectangle(hDC, int left, int top, int right, int bottom); //аргументы — это коордианты левого верхнего и правого нижнего углов

5. Закруглённый прямоугольник. Его можно использовать, как импровизированную кнопку, если не лень возиться.
BOOL RoundRect(hDC, int left, int top, int right, int bottom, int width, int height);
Первые пять параметров совпадают с параметрами предыдущей фукнции. Далее width и height задают ширину и высоту эллипса, дуги которого ограничивают прямоугольник.

6. Кисти. Самое время познакомиться с кистями, так как фигуры, которые пойдут дальше выглядят лучше закрашенными. Мы уже немного затронули эту тему во вводной части. Теперь рассмотрим как задать свой стиль кисти. Как и setfillstyle() в DOS, кисть закрашивает какую-то область в какой-то цвет. В зависимости от кисти, она может делать это в полосочку, в клеточку, по диагонали.
Есть два способа объявить кисть. Первый — задать сплошную заливку, второй — указать стиль. Для этого существуют соответственно функции: CreateSoldBrush() и CreateHatchBrush().

Пример:
HBRUSH hBrush; //создаём объект-кисть
CreateSolidBrush(RGB(255,0,67)); //задаём сплошную кисть, закрашенную цветом RGB
SelectObject(hdc, hBrush); //делаем кисть активной

А вот как объявить не сплошную кисть:
CreateHatchBrush(int fnStyle, RGB(r,g,b));

Аргумент fnStyle принимает ряд константных значений:
HS_DIAGONAL — штрихует по диагонали
HS_CROSS — клеточка
HS_DIAGCROSS — диагональная сетка
HS_FDIAGONAL — по диагонали в другую сторону
HS_HORIZONTAL — горизонтальная «тельняшка»
HS_VERTICAL — вертикальный «забор»

HBRUSH hBrush1;
CreateHatchBrush(int fnStyle, RGB(r,g,b));
SelectObject(hdc, hBrush1); //делаем кисть активной

Вот махонький пример сообщения WM_PAINT с использованием кистей.

//сообщение рисования
case WM_PAINT :
//начинаем рисовать
hdc=BeginPaint(hWnd, &ps);
HBRUSH hBrush;
hBrush=CreateHatchBrush(HS_FDIAGONAL, RGB(255,0,0));
SelectObject(hdc,hBrush);

Ellipse(hdc, 100,100,200,300); //эллипс будет заштрихован

//заканчиваем рисовать
EndPaint(hWnd, &ps);
break;

7. Перья.
Они задают стиль линий, как и setlinestyle в DOS. Линия может быть жирной и тонкой, прерывистой и штрих-пунктирной. Всё предусмотрено. Это очень удобно для создания графиков функций, когда на график накладывается сетка, рисуются оси и выводится сама функция. Вы можете сказать, что это касается только математиков! Но почти любая фирма, что бы она не производила, иногда проводит презентации. На графике можно показать рост внешнего капитала, объём продаж и многое другое.

HPEN hPen; //Объявляется кисть
CreatePen(fnPenStyle, int width, RGB(r,g,b)); //Создаётся объект
SelectObject(hdc, hPen); //Объект делается текущим

fnStyle может принимать следующие значения:
PS_SOLD — сплошная
PS_DASH — состоящая из точек
PS_DOT — состоящая из тире
PS_DASHDOT — «точка-тире»
PS_DASHDOTDOT — «тире-точка-точка-тире»
PS_NULL — невидимая
PS_INSIDEFRAME — обводка замкнутых фигур

И пример будет такой:
//сообщение рисования
case WM_PAINT :
//начинаем рисовать
hdc=BeginPaint(hWnd, &ps);

HPEN hPen1, hPen2, hPen3; //объявляем сразу три объекта-пера
hPen1=CreatePen(PS_DASHDOT, 1, RGB(0,0,255)); //создаём всё три
hPen2=CreatePen(PS_DASH, 1, RGB(255,0,255));
hPen3=CreatePen(PS_DOT, 1, RGB(0,128,256));

SelectObject(hdc, hPen1); //но в одним момент времени может быть только 1
Rectangle(hdc, 10,10,100,100); //рисуем фигуру соответствующим пером

SelectObject(hdc, hPen2); //меняем перо
Ellipse(hdc, 100,100,200,300); //рисуем другим пером

SelectObject(hdc, hPen3);
LineTo(hdc, 200,100);

ValidateRect(hWnd, NULL);
//заканчиваем рисовать
EndPaint(hWnd, &ps);
break;

Важно понять, что можно создавать хоть 10 перьев с помощью CreatePen, но применить в данный момент времени можно только 1 из них. Для этого и нужен SelectObject, чтобы окно поняло какую кисть в настоящий момент мы достаём из этюдника GDI.

6. Закрашенный прямоугольник
int FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr);
lprc — закрашиваемый прямоугольник типа RECT.
hbr — кисть

Вот пример-фрагмент WM_PAINT:

RECT r; //объявляем экзмепляр структуры RECT — координаты прямоугольника.
r.left=100; //левый верхний угол
r.top=100;
r.right=200; //правый нижний
r.right=300;

А вот и первый пример программы подоспел! Нарисуем что-то очень красивое — то, что мы уже умеем.

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

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
char szProgName[]=»Имя программы»;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
<
HWND hWnd;
MSG lpMsg;
WNDCLASS w;

w.lpsz > w.hInstance=hInstance; //идентификатор текущего приложения
w.lpfnWndProc=WndProc; //указатель на функцию окна
w.hCursor=LoadCursor(NULL, IDC_ARROW); //загружаем курсор
w.hIcon=0;
w.lpszMenuName=0;
w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); //цвет фона окна
w.style=CS_HREDRAW|CS_VREDRAW;
w.cbClsExtra=0;
w.cbWndExtra=0;

//Если не удалось зарегистрировать класс окна — выходим
if(!RegisterClass(&w))
return 0;

//Создадим окно в памяти, заполнив аргументы CreateWindow
hWnd=CreateWindow(szProgName, //Имя программы
«Грфические возможности Win32 API», //Заголовок окна
WS_OVERLAPPEDWINDOW, //Стиль окна — перекрывающееся
100, //положение окна на экране по х
100, //положение по у
500, //ширина
400, //высота
(HWND)NULL, //идентификатор родительского окна
(HMENU)NULL, //идентификатор меню
(HINSTANCE)hInstance, //идентификатор экземпляра программы
(HINSTANCE)NULL); //отсутствие дополнительных параметров

//Выводим окно из памяти на экран
ShowWindow(hWnd, nCmdShow);
//Обновим содержимое окна
UpdateWindow(hWnd);

//Цикл обработки сообщений

//Функция окна
LRESULT CALLBACK WndProc(HWND hWnd, UINT messg,
WPARAM wParam, LPARAM lParam)
<
HDC hdc; //создаём контекст устройства
PAINTSTRUCT ps; //создаём экземпляр структуры графического вывода
LOGFONT lf;
HFONT hFont;
RECT r;
HBRUSH hBrush;
HPEN hPen;

//Цикл обработки сообщений
switch(messg)
<
//сообщение рисования
case WM_PAINT :
hdc=BeginPaint(hWnd, &ps);

//Создаём свой шрифт
strcpy(lf.lfFaceName,»Times New Roman»); //копируем в строку название шрифта
lf.lfHeight=20;
lf.lfItalic=1;
lf.lfStrikeOut=0;
lf.lfUnderline=0;
lf.lfW > lf.lfWeight=40;
lf.lfCharSet=DEFAULT_CHARSET; //значение по умолчанию
lf.lfPitchAndFamily=DEFAULT_PITCH; //значения по умолчанию
lf.lfEscapement=0;

hFont = CreateFontIndirect(&lf);
SelectObject(hdc, hFont);
SetTextColor(hdc, RGB(0,0,255));
TextOut(hdc, 80,40, «Красота спасёт мир!!», 20);

//рисуем зелёный эллипс
hBrush=CreateSolidBrush(RGB(10,200,100));
SelectObject(hdc, hBrush);
Ellipse(hdc, 20,100,200,200);

//рисуем закруглённый прямоугольник
hBrush=CreateSolidBrush(RGB(250,200,100));
SelectObject(hdc, hBrush);
hPen=CreatePen(2,2,RGB(0,0,255));
SelectObject(hdc, hPen);
RoundRect(hdc, 20, 250, 250, 350, 15, 15);


ValidateRect(hWnd, NULL);
EndPaint(hWnd, &ps);
break;

//сообщение выхода — разрушение окна
case WM_DESTROY:
PostQuitMessage(0); //Посылаем сообщение выхода с кодом 0 — нормальное завершение
DeleteObject(hPen);
DeleteObject(hBrush);
break;

default:
return(DefWindowProc(hWnd, messg, wParam, lParam)); //освобождаем очередь приложения от нераспознаных
>
return 0;
>

Правда, красиво? Наконец-то из этой API нам удалось выжать что-то стоящее. Продолжаем обзор.

7. Прямоугольная рамка — как видите, существует немало функций для работы с прямоугольниками:

int FrameRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr);
Применение аналогично предыдущей.

8. Инверсия значения цветов точек в заданной области
BOOL InvertRect(HDC hDC, CONST RECT *lprc);

9. Эллипс
BOOL Ellipse(HDC hdc, int x1, int y1, int x2, int y2);
координаты — это прямоугольник, в который вписывается эллипс

10. Хорда (сегмент эллипса) — параметры аналогичны Arc
BOOL Chord(HDC hDC, int left, int top, int right, int bottom, int x1, int y1, int x2, int y2); Функция соединяет хордой точки начала и конца дуги эллипса и закрашивает выделенный сегмент текущей кистью.

11. Сектор эллипса
— аналог pieslice в DOS.
BOOL Pie(HDC hDC, int left, int top, int right, int bottom, int x1, int y1, int x2, int y2);

12. Многоугольник . Есть много функций рисования мноугольников. Мы рассмотрим две. Рисования от вершины к вершине и рисования отрезками:
PolyDraw оперирует вершинами:


POINT poly[8];
BYTE polytype[8];

poly[0].x=375; //координаты первой вершины
poly[0].y=375;

. //и так заполняем координаты всех восьми вершин

poly[7].x=400; //координаты восьмой вершины
poly[7].y =400;

. //другой массив содержит режим рисования

PolyDraw(hdc, poly, polytype, 8); //рисование многоугольника

Функция Polyline рисует набором отрезков:

Polyline(hdc, poly , 4);

КАК вывести график функции?

Всё это были фрагменты графических функций. Теперь рассмотрим настоящий полноценный пример. Это будет простейший график функции.

Внимание
Вообще графики очень часто используются в промышленных приложениях. А ведь промышленная автоматизация один из главныз заказчиков программиста. На деле никто не занимается программированием ради программирования. Обязательно придётся осваивать какую-то ещё предметную область. Будь то склад для программиста баз данных или производство упаковок для системного программиста. Так или иначе, программы, контроллирующие какой-нибудь физический парметр (температуру больного, давление в шахте, скорость двигателя, частоту оборотов, напряжённость магнитного поля) выводят оперативную информацию на грфик. Специальный человек — оператор следит за тем, чтобы значения графика не достигали предельных значений.
Как вы сами понимаете, мы не можем обойти столь важную тему. Именно для неё наша следующая программа.
Создайте пустой проект Win API и включите в него следующий текст:

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//Процедура рисования линии
BOOL Line(HDC hdc, int x1, int y1, int x2, int y2);

char szProgName[]=»Имя программы»;

int i, xView, yView;
double y;
char Buf[2];

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
<
HWND hWnd;
MSG lpMsg;
WNDCLASS w;

w.lpsz > w.hInstance=hInstance;
w.lpfnWndProc=WndProc;
w.hCursor=LoadCursor(NULL, IDC_ARROW);
w.hIcon=0;
w.lpszMenuName=0;
w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
w.style=CS_HREDRAW|CS_VREDRAW;
w.cbClsExtra=0;
w.cbWndExtra=0;

//Если не удалось зарегистрировать класс окна — выходим
if(!RegisterClass(&w))
return 0;

//Создадим окно в памяти, заполнив аргументы CreateWindow
hWnd=CreateWindow(szProgName,
«График функции»,
WS_OVERLAPPEDWINDOW,
100,
100,
500,
400,
(HWND)NULL,
(HMENU)NULL,
(HINSTANCE)hInstance,
(HINSTANCE)NULL);

//Выводим окно из памяти на экран
ShowWindow(hWnd, nCmdShow);
//Обновим содержимое окна
UpdateWindow(hWnd);

//Цикл обработки сообщений

while(GetMessage(&lpMsg, NULL, 0, 0)) < //Получаем сообщение из очереди
TranslateMessage(&lpMsg); //Преобразует сообщения клавиш в символы
DispatchMessage(&lpMsg); //Передаёт сообщение соответствующей функции окна
>
return(lpMsg.wParam);
>

//Функция окна
LRESULT CALLBACK WndProc(HWND hWnd, UINT messg,
WPARAM wParam, LPARAM lParam)
<
HDC hdc; //создаём контекст устройства
PAINTSTRUCT ps; //создаём экземпляр структуры графического вывода
HPEN hPen; //создаём перо
//Цикл обработки сообщений
switch(messg)
<

case WM_SIZE:
xView=LOWORD(lParam);
yView=HIWORD(lParam);

//сообщение рисования
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
SetMapMode(hdc, MM_ISOTROPIC); //логические единицы отображаем, как физические
SetWindowExtEx(hdc, 500,500, NULL); //Длина осей
SetViewportExtEx(hdc, xView, -yView, NULL); //Определяем облась вывода
SetViewportOrgEx(hdc, xView/6, yView/2, NULL); //Начало координат

//Рисуем оси координат
Line(hdc,0, 220,0,-220);//ось У
Line(hdc, -100,0,500,0);//ось Х
MoveToEx(hdc, 0,0,NULL); //перемещаемся в начало координат

//Создание красного пера
hPen=CreatePen(1,4,RGB(255,25,0));
SelectObject(hdc, hPen);

//Делаем перо снова чёрным
hPen=CreatePen(1,1,RGB(0,0,0));
SelectObject(hdc, hPen);

//Наносим деления
for(i=-100; i

//сообщение выхода — разрушение окна
case WM_DESTROY:
DeleteObject(hPen); //не забываем уничтожать перья
PostQuitMessage(0); //Посылаем сообщение выхода с кодом 0 — нормальное завершение
break;

default:
return(DefWindowProc(hWnd, messg, wParam, lParam)); //освобождаем очередь приложения от нераспознаных
>
return 0;
>

//Функция рисования линии
BOOL Line(HDC hdc, int x1, int y1, int x2, int y2)
<
MoveToEx(hdc, x1, y1, NULL); //сделать текущими координаты x1, y1
return LineTo(hdc, x2, y2); //нарисовать линию
>

Поскольку в данной программе большое внимание уделяется всяким украшательствам: делениям и надписям, обращу ваше внимание на главное — создавать графики совсем не сложно. И вот как это делается:

Мы знаем, что отсчёт координат задаётся от левого верхнего угла вниз и вправо. Как известно, значения на графике изменяются вверх и вправо. Вряд ли мы сможем объяснить пользователю, почему график «растёт вниз». На счастье, в Windows предусмотрена функция, преобразует координаты в нужном нам направлении.
Первым делом, мы узнаём размер окна. Для этого используется сообщение WM_SIZE. Параметр lParam содержит по этому сообщению размеры экрана. Переменные xView и yView будут содержать эти значения:

case WM_SIZE:
xView=LOWORD(lParam);
yView=HIWORD(lParam);

break;

Затем определим область вывода. Мы хотим, чтобы при увеличении координаты по у график рос вверх, а не вниз.

SetViewportExtEx(hdc, xView, -yView, NULL);

Обратите внимание: yView указан со знаком . Значит все координаты по у будут расти в обратную сторону — вверх.
Центр графика обычно где-нибудь посередине экрана. Координаты же увеличиваются из левого верхнего угла. Перенесём центр графика:

SetViewportOrgEx(hdc, xView/6, yView/2, NULL);

В точке, равной 1/6 максимального значения по х и 1/2 значения по этого значения по у будет центр.
Можно также задать длину осей — 500 и 500. Для этого применяется следующая функция:

SetWindowExtEx(hdc, 500,500, NULL);

Как вы уже знаете, окно имеет логические координаты и физические. Для того, чтобы логические координаты совпадали с физическими, а также, чтобы единица отложенная по х была равно единице отложенной по у, задаётся режим MM_ISOTROPIC. Его задаёт функция:

Вот, как будет выглядеть эта конструкция вцелом:

SetMapMode(hdc, MM_ISOTROPIC); //логические единицы отображаем, как физические
SetWindowExtEx(hdc, 500,500, NULL); //Длина осей
SetViewportExtEx(hdc, xView, -yView, NULL); //Определяем облась вывода
SetViewportOrgEx(hdc, xView/6, yView/2, NULL); //Начало координат

Дальше надо нарисовать оси. К нашей радости, точка 0, 0 сместилась на середину экрана, в левую его часть. Исходя из этого, рисуем оси, применяя самописную функцию Line:

Line(hdc,0, 220,0,-220);//ось У
Line(hdc, -100,0,500,0);//ось Х
MoveToEx(hdc, 0,0,NULL);

В выводе графика нет ничего примечательного. Переменная i меняется от 0 до 450. Подставляя i в формулу, мы получаем зависимость y от i. Рисуем линию до этой точки. Небольшие отрезки сольются в непрерывную линию.


Иногда, требуется хранить значения физических величин несколько дней. Тогда график выполняется с длиннющей горизонтальной полосой прокрутки. При желании, можно вернуться и посмотреть были ли изменения, и если да, то какие.
Другой выход из положения — вести историю, записывая её в файл, а на экран выводя только показания последних пяти минут.

Задания:

1. Добавьте в приложения с графиком стрелочки и подписи к осям.
2. Нарисуйте снеговика известными средствами GDI. Напомню, что снеговик состоит из трёх непрозрачных эллипсов грязно-белого цвета, на груди у него должны быть пуговки, в руке — метла, а на голове — ведро.
3. Нарисуйте красивый паровозик, клубы из трубы которого будут выводиться в цикле в виде синих эллипсов
4. Нарисуйте кораблик с жёлтой палубой и красными бортами, используя Polyline или Polydraw. Кораблик покоится на синих волнах, которые нарисованы дугами разной толщины. Попробуйте вывести дуги в цикле.
5. Нарисуйте с помощью одних только линий домик с забором

CXIV. W32api Functions

This extension is a generic extension API to DLLs. This was originally written to allow access to the Win32 API from PHP, although you can also access other functions exported via other DLLs.

Currently supported types are generic PHP types (strings, booleans, floats, integers and nulls) and types you define with w32api_deftype() .

This extension is EXPERIMENTAL . The behaviour of this extension — including the names of its functions and anything else documented about this extension — may change without notice in a future release of PHP. Use this extension at your own risk.

This extension will only work on Windows systems.

There is no installation needed to use these functions; they are part of the PHP core.

This extension has no configuration directives defined in php.ini .

This extension defines one resource type, used for user defined types. The name of this resource is «dynaparm» .

The constants below are defined by this extension, and will only be available when the extension has either been compiled into PHP or dynamically loaded at runtime.

This example gets the amount of time the system has been running and displays it in a message box.

Example 1. Get the uptime and display it in a message box

Warning
// Define constants needed, taken from
// Visual Studio/Tools/Winapi/WIN32API.txt
define ( «MB_OK» , 0 );

// Load the extension in
dl ( «php_w32api.dll» );

// Register the GetTickCount function from kernel32.dll
w32api_register_function ( «kernel32.dll» ,
«GetTickCount» ,
«long» );

// Register the MessageBoxA function from User32.dll
w32api_register_function ( «User32.dll» ,
«MessageBoxA» ,
«long» );

// Get uptime information
$ticks = GetTickCount ();

// Convert it to a nicely displayable text
$secs = floor ( $ticks / 1000 );
$mins = floor ( $secs / 60 );
$hours = floor ( $mins / 60 );

$str = sprintf ( «You have been using your computer for:» .
«\r\n %d Milliseconds, or \r\n %d Seconds» .
«or \r\n %d mins or\r\n %d hours %d mins.» ,
$ticks ,
$secs ,
$mins ,
$hours ,
$mins — ( $hours * 60 ));

Win32 API в Delphi

КОМПЬЮТЕРНЫЕ КУРСЫ «ПОИСК»

Переписываем уроки Iczelion’а о Win32 API на Delphi

Урок 5. Больше о тексте

Мы еще немного поэкспеpиментиpуем, то есть фонт и цвет.

Скачать файл пример здесь. Выполнен на Delphi XE.

ТЕОРИЯ

Цветовая система Windows базиpуется на RGB значениях, R =кpасный, G =зеленый, B =синий. Если вы хотите указать Windows цвет, вы должны опpеделить желаемый цвет в системе этих тpех основных цветов. Каждое цветовое значение имеет область опpеделения от 0 до 255. Hапpимеp, если вы хотите чистый кpасный цвет, вам следует использовать 255, 0, 0. Или если вы хотите чистый белый цвет, вы должны использовать 255, 255, 255. Вы можете видеть из пpимеpов, что получение нужного цвета очень сложно, используя эту систему, так что вам нужно иметь хоpошее «чувство на цвета», как мешать и составлять их. Для установки цвета текста или фона, вы можете использовать SetTextColor и SetBkColor, оба из котоpых тpебуют хэндл контекста устpойства и 32-битное RGB значение. Стpуктуpа 32-битного RGB значения опpеделена как:

Заметьте, что пеpвый байт не используется и должен быть нулем. Поpядок оставшихся байтов пеpевеpнут, то есть blue, green, red. Для получения цвета мы будем использовать функцию RGB.

Для «создания» фонта, можно использовать CreateFont или CreateFontIndirect. Разница между ними заключается в том, что CreateFontIndirect получает только один паpаметp: указатель на стpуктуpу логического фонта, TLogFont.

СreateFontIndirect более гибкая функция из этих двух, особенно если вашей пpогpамме необходимо часто менять фонты. Тем не менее, в нашем пpимеpе мы «создадим» только один фонт для демонстpации, поэтому будем делать это чеpез CreateFont. После вызова этой функции, она веpнет хэндл фонта, котоpый вы должны выбpать в опpеделенном контексте устpойства. После этого, каждая текстовая API функция будет использовать фонт, котоpый мы выбpали.

СОДЕРЖИМОЕ

АНАЛИЗ

CreateFont создает логический фонт, котоpый наиболее близок к данным паpаметpам и доступным данным фонта. Эта функция имеет больше паpаметpов, чем любая дpугая в Windows. Она возвpащает хэндл логического фонта, котоpый можно выбpать функцией SelectObject. Мы в подpобностях обсудим ее паpаметpы.

  • nHeight — желаемая высота символов. Hоль значит использовать pазмеp по умолчанию.
  • nW >FW_DONTCARE = 0
  • FW_THIN = 100
  • FW_EXTRALIGHT = 200
  • FW_ULTRALIGHT = 200
  • FW_LIGHT = 300
  • FW_NORMAL = 400
  • FW_REGULAR = 400
  • FW_MEDIUM = 500
  • FW_SEMIBOLD = 600
  • FW_DEMIBOLD = 600
  • FW_BOLD = 700
  • FW_EXTRABOLD = 800
  • FW_ULTRABOLD = 800
  • FW_HEAVY = 900
  • FW_BLACK = 900
  • cItalic — 0 для обычных символов, любое дpугое значение для pоманских.
  • cUnderline — 0 для обычных символов, любое дpугое значение для подчеpкнутых.
  • cStrikeOut — 0 для обычных символов, любое дpугое значение для пеpечеpкнутых.
  • cCharSet — символьный набоp фонта. Обычно должен быть установлен в OEM_CHARSET, котоpый позволяет Windows выбpать системно-зависимый фонт.
  • cOutputPrecision — указывает насколько должен близко должен пpиближаться фонт к хаpактеpистикам, котоpые мы указали. Обычно этот паpаметp устанавливается в OUT_DEFAULT_PRECIS.
  • cClipPrecision опpеделяет, что делать с символами, котоpые вылезают за пpеделы отpисовочного pегиона.
  • cQuality — указывает качества вывода, то есть насколько внимательно GDI пытаться подогнать аттpибуты логического фонта к аттpибутам фонта физического. Есть выбоp из тpех значений: DEFAULT_QUALITY, PROOF_QUALITY и DRAFT_QUALITY.
  • cPitchAndFamily — указывает питч и семейство фонта. Вы должны комбиниpовать значение питча и семьи с помощью опеpатоpа «or».
  • lpszFace — указатель на заканчивающуюся NULL’ом стpоку, опpеделяющую гаpнитуpу фонта.
  • Вышепpиведенное описание ни в коем случае не является исчеpпывающим. Вам следует обpатиться к вашему Win32 API Спpавочнику за деталями.

    После получения хэндл логического фонта, мы должны выбpать его в контексте устpойства, вызвав SelectObject. Функция устанавливает новые GDI объекты, такие как пеpья, кистья и фонтыв контекст устpойства, используемые GDI функциями. SelectObjet возвpащает хэндл замещенного объекта, котоpый нам следует сохpанить для будущего вызова SelectObject. После вызова SelextObject любая функция вывода текста будет использовать фонт, котоpый мы выбpали в данном контексте устpойства.

    Используйте функцию RGB, чтобы создать 32-битное RGB значение, котоpое будет использоваться функциями SetColorText и SetBkColor.

    Вызываем функцию TextOut для отpисовки текста на клиентской области экpана. Будет использоваться pанее выбpанные нами фонт и цвет.

    После этого мы должны восстановить стаpый фонт обpатно в данном контексте устpойства. Вам всегда следует восстанавливать объект, котоpый вы заменили.

    Илон Маск рекомендует:  Что такое код mb_strrpos
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL