Благодаря усилиям многих программистов, СП-Форт стал стабильной и удобной системой разработки 32-разрядных приложений. Однако в нем имеется существенный пробел: программы с графическим интерфейсом разрабатывать достаточно неудобно. Можно, конечно, напрямую вызывать Windows API, но это долгий и чреватый ошибками путь. Сам API сделан некрасиво (чего стоит один вызов создания окна с 12 (!) аргументами) и имеет сильный уклон в сторону языка Си. Настоящая библиотека ставит своей целью если и не до конца скрыть вызов системных функций (в полном объеме, не ограничив существенно свободу программиста, сделать это нельзя), то хотя бы замаскировать самые одиозные места.
Поскольку я не люблю объектно-ориентированное программирование, считая его уместным лишь в некоторых специализированных задачах, постольку и библиотека далека по своим концепциям от MFC. Во время написания я вдохновлялся идеями графической среды Tcl/Tk и своей предыдущей работой Blank.
Так как библиотека получилась достаточно большой, она разделена на три отдельных уровня, чтобы уменьшить размер программ, для которых не нужна полная функциональность. В первую часть (WinLib) входит базовая работа с окнами: создание, уничтожение, обработка сообщений, меню, быстрые клавиши. Вторая часть (WinCtl) содержит средства создания элементов управления и их автоматическое размещение в окне; третья часть (WinCC) - работу с общими элементами управления (то есть, новыми, введенными в Windows 95 и выше).
Библиотека писалась год с перерывами, а работа над ней оказалась неожиданно сложной. С большой вероятностью в ней можно найти множество мелких ошибок. Я буду признателен всем, кто сообщит мне о них.
Библиотека в большой степени базируется на специальных структурах-таблицах. Окна и элементы управления представляются такими таблицами - по большому счету, списками свойств. Часть свойств могут быть прочитаны и записаны, некоторые - только записаны. Свойство -prop читается словом -prop@ и записывается словом -prop!.
Таблицы являются пассивными элементами - все операции над ними выполняют процедуры-слова. В дальнейшем тексте такие таблицы для упрощения будут называться просто окнами и обозначаться в стековой нотации как win. Не путайте их с системными дескрипторами окон (hwnd).
В библиотеке используются в основном value-переменные. Поэтому в описании под словом "переменные" будут подразумеваться именно они, если не будет оговорено иное. Они будут указываться без стековой нотации.
Инициализацию библиотеки проводит слово WINDOWS.... После него
объявляются окна и производится запуск системы выборки сообщений словом
...WINDOWS. Управление вернется после закрытия главного окна программы.
Создает стандартное окно со всеми полагающимися элементами - заголовком, рамкой, кнопками. Для создания дочернего окна передается объект окно-родитель, для окна верхнего уровня - 0. Если окно по какой-то причине не может быть создано, возвращается 0, иначе - объект-окно.
dialog-window ( winparent -- win/0 )Создает стандартное диалоговое окно - немасштабируемое, только с кнопкой "закрыть".
tool-window ( winparent -- win/0 )Создает стандартное окно-палитру - с узким заголовком, без кнопок.
create-window-with-styles ( winparent style exstyle -- win/0 )Создает окно любого вида. Передаются стиль окна (константы WS_xxx) и расширенный стиль окна (WS_Ex_xxx).
destroy-window ( win -- )Уничтожает указанное окно. Перед уничтожением окну посылается сообщение wm_destroy.
Переменная, в которой хранится главное окно программы. Занести его туда вы должны самостоятельно, сразу после создания главного окна. Окно winmain обладает следующими свойствами: а) оно служит родителем модальных диалоговых окон и окон сообщений; б) к нему подключается меню программы; в) при его закрытии заканчивается цикл выборки сообщений окна и управление передается за слово ...WINDOWS для завершения программы.
current-windowПоследнее созданное окно.
Системный дескриптор окна. Часто требуется для прямого вызова функций Windows, не предусмотренных в библиотеке.
-styleСтиль окна. Свойство можно читать и записывать.
![]() | Многие стили окна фиксируются системой при его создании и в дальнейшем их изменить нельзя. |
Цвет текста окна. См. раздел Цвета.
-bgcolorЦвет фона окна. См. раздел Цвета.
-bgbrush
Кисть для закрашивания фона окна. Если ваше окно просто
закрашивается каким-нибудь цветом, это свойство лучше не трогать. Оно
полезно, если вы хотите какой-нибудь необыкновенный эффект типа полосатого
окна или окна с фоном. Делается это примерно так:
\ уничтожаем стандартную кисть
w -bgbrush@ DeleteObject DROP
\ заносим новую
blue >bgr W: hs_horizontal CreateHatchBrush w -bgbrush!
-xsize, -ysize
Размеры окна. Для перекрывающихся окон здесь указывается размер лишь клиентской части окна. Эти свойства можно только читать. Для изменения размеров пользуйтесь словами winresize или ctlresize.
-parentРодитель окна, если таковой имеется.
-textТекст, присвоенный окну. Для перекрывающихся окон - это текст заголовка, для элементов управления - обычно текст надписи. Максимальный размер этого текста - 255 байтов. Чтение текста производится в буфер следующим образом: -text@ ( a win -- ). Кстати, длину текста можно узнать заранее с помощью слова -text# ( ctl -- n)
-dialogФлаг. Если он установлен, в окне будут работать стандартные клавиши перемещения по элементам диалога (Tab, Shift+Tab, стрелки).
Большая и маленькая иконки, присвоенные окну. По умолчанию ставятся иконки 1 и 2 из ресурсов исполняемого файла.
-painterПроцедура отрисовки окна. При вызове в переменной windc хранится контекст устройства рисования, в переменной paint-rect - координаты прямоугольника, подлежащего отрисовке. Фон окна в этой процедуре рисовать не нужно - к моменту вызова он уже закрашен нужным цветом или кистью.
-wndprocСписок (MESSAGES:...MESSAGES;) обработчиков сообщений окна. Вызывается после системной обработки. Можно пользоваться следующими переменными: thiswin - окно, к которому пришло сообщение, hwnd - дескриптор этого окна, wparam, lparam - параметры сообщения.
-preСписок (MESSAGES:...MESSAGES;) обработчиков сообщений окна. Вызывается перед системными обработчиками. Рекомендуется использовать только при крайней необходимости, отдавая предпочтение -wndproc, поскольку можно легко нарушить стандартную обработку.
-hscroll, -vscrollСписок обработчиков сообщений от полос прокрутки окна. Полосы прокрутки окна могут быть включены функцией ShowScrollBar.
-userdataПользовательские данные, связанные с окном. Библиотека это поле никак не использует.
Показать окно.
winhide ( win -- )Спрятать окно.
winminimize ( win -- )Свернуть окно.
winmaximize ( win -- )Развернуть окно до максимального размера.
winrestore ( win -- )Восстановить размер окна.
windisable ( win -- )Запретить работу окна. Запрещенное окно не принимает ввод от пользователя.
winenable ( win -- )Разрешить работу окна.
winfocus ( win -- )Установить на окно фокус ввода.
winmove ( x y win -- )Переместить окно в указанную точку. Координаты измеряются в пикселях от левого верхнего угла экрана - для окон верхнего уровня - или клиентской области родительского окна.
winresize ( w h win -- )Изменить размер окна. Слово работает только для перекрывающихся окон, w и h - размер новой клиентской области окна. Для элементов управления используйте ctlresize.
![]() | Для обыкновенных (не диалоговых) окон Windows почему-то не выдерживает размер окна по горизонтали. Можно гарантировать только, что новый размер окна будет не меньше запрошенного. При запросе ширины окна в 100 точек система может установить 104, 106 и даже 112 - в зависимости от фаз Луны. Размер окон с фиксированной границей выдерживается правильно. |
Расположить окно в центре экрана (для окон верхнего уровня) или в центре родительского окна (для остальных)
Послать окну сообщение msg с указанными параметрами и вернуть результат.
?send ( win msg -- result )Послать окну сообщение msg с параметрами 0, 0
wsend ( wparam win msg -- result )Послать окну сообщение msg с параметрами wparam и lparam=0
lsend ( lparam win msg -- result )Послать окну сообщение msg с параметрами wparam=0 и lparam
send-to-window ( wparam lparam msg hwnd -- result )Послать окну с дескриптором hwnd сообщение msg с указанными параметрами и вернуть результат.
Начать список сообщений с именем name.
MESSAGES; ( -- )Закончить список сообщений.
M: ( ->bl)Начать обработчик сообщения message (константы WM_xxx).
M; ( result -- )Завершить обработчик сообщения. Если обработчик оставил на стеке FALSE, сообщение считается необработанным и продолжается поиск следующих обработчиков. Если TRUE - сообщение обработано и Windows возвращается в качестве результата 0 или значение, предварительно установленное словом RETURN.
RETURN ( code -- )Устанавливает код возврата из обработчика сообщения.
Начать описание меню.
MENU; ( -- )Закончить описание меню.
MENUITEM ( ->eol; xt -- )Вставить в меню новый пункт. При выборе этого пункта будет выполнено слово xt.
SUBMENU ( ->bl; menu -- )Вставить указанное меню как подменю.
LINE ( -- )Вставить в меню разделительную линию.
CHECKED ( -- )Текущий пункт меню будет отмечен.
DISABLED ( -- )Текущий пункт меню будет отключен.
MENU: mainmenu
['] file MENUITEM &Файл
LINE
\ в следующем пункте указывается заодно и горячая клавиша. Впрочем,
\ она будет только прописана в соответствующем месте меню. Чтобы по
\ Ctrl+O действительно что-то вызывалось, не забудьте добавить в таблицу
\ горячих клавиш ['] proc ONKEY ctrl+vk_O
['] open MENUITEM &Открыть файл...\tCtrl+O
MENU;
Присоединить меню к указанному окну.
detach-menubar ( win -- )Отсоединить от окна меню.
show-menu ( menu x y -- )Показать раскрывающееся меню menu в точке с указанным экранными координатами. Слово возвращает управление после того, как пользователь выберет какой-нибудь пункт меню или закроет его. show-menu работает только при установленном главном окне (winmain).
default-menu-item ( no menu -- )Сделать пункт меню с указанным номером пунктом, выбираемым по умолчанию. В этом и следующих словах номера пунктов меню отсчитываются от нуля.
enable-menu-item ( no menu -- )Включить указанный пункт меню.
disable-menu-item ( no menu -- )Отключить указанный пункт меню.
check-menu-item ( no menu -- )Отметить указанный пункт меню.
uncheck-menu-item ( no menu -- )Убрать отметку с указанного пункта меню.
(un)check-me ( -- ?)Слово предназначено для использования в обработчиках пунктов меню. Оно ставит или сбрасывает отметку текущего пункта и возвращает флаг, показывающий новое состояние пункта.
check-menu-radio ( firstno lastno no menu -- )Устанавливает отметку на пункт меню номер no. Отметки со всех остальных пунктов от первого firstno до последнего lastno сбрасываются.
Начать описание таблицы быстрых клавиш.
KEYTABLE; ( -- )Закончить описание таблицы быстрых клавиш.
ONKEY ( ->bl; xt -- )Определить быструю клавишу. При ее нажатии будет вызвано слово xt. Клавиши описываются в виде констант VK_xxx, перед которыми в произвольном порядке могут стоять модификаторы "ctrl+", "alt+", "shift+".
['] f5 ONKEY vk_f5 ['] sp ONKEY ctrl+alt+vk_space
Показать окно сообщения. Title - заголовок окна, text - текст окна (может состоять из нескольких строк, разделяется символом \n", flags - набор констант MB_xxx.
msg ( text -- )Окно-предупреждение. Заголовок берется из mbox-title.
err ( text -- )Окно-ошибка. Заголовок берется из mbox-title.
mbox-titleПеременная, в которой хранится адрес строки - заголовка окон сообщений. Если не установлена, в окнах ставится заголовок "Ошибка".
Создает шрифт с указанным именем. Размер указывается в типографских пунктах. Необязательные параметры шрифта задаются модификаторами.
delete-font ( font -- )Уничтожить шрифт. Теоретически, ОС должна уничтожать все графические объекты, включая шрифты, после закрытия программы. Однако имеются подозрения, что Windows 95/98/Me этого не делают, поэтому не забывайте стирать шрифты вручную.
bold ( -- )Модификатор: определяемый шрифт будет жирным.
italic ( -- )Модификатор: определяемый шрифт будет курсивным.
underline ( -- )Модификатор: определяемый шрифт будет подчеркнутым.
strike-out ( -- )Модификатор: определяемый шрифт будет перечеркнутым.
" Times New Roman Cyr" 12 bold italic create-font TO ff
default-font ( font -- )
Устанавливает стандартный шрифт, который с этого момента будет использоваться для всех элементов управления, кроме всплывающих подсказок. Не забудьте уничтожить этот шрифт в конце работы программы (он хранится в переменной def-font). Если вызвать это слово с аргументом 0, для элементов будет использоваться стандартный системный шрифт.
-sysfont ( -- )Устанавливает последнему определенному элементу системный шрифт.
| red | green | blue | white | black | yellow | violet | cyan |
Возвращает в формате RGB один из системных цветов, определяемых константами color_xxx.
>bgr ( rgb -- bgr )Переводит цвет из внутреннего формата Windows (0x00bbggrr) в формат RGB (0x00rrggbb) или наоборот.
rgb ( r g b -- rgb )Собирает цвет из трех отдельных компонентов.
Возвращает размер экрана по горизонтали или по вертикали соответственно.
hdu ( hdu -- pixels)Пересчитывает горизонтальные диалоговые единицы (это своеобразные измерительные величины, которыми используются в Windows при описании диалогов как ресурсов) в пикселы.
vdu ( hdu -- pixels)Пересчитывает вертикальные диалоговые единицы в пикселы.
dunits ( hdu vdu -- w h)Пересчитывает размеры в диалоговых единицах в пикселы.
Пример работы с окнами