WIN-FORTH для минималистов (проект FOBOS)

Перейти вниз

WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:07 am

Знать, где ловушка,- это первый шаг к тому, чтобы избежать ее. Это похоже на поединок, на дуэль, только масштабы другие. Выпад внутри выпада, а тот - внутри третьего, один финт в другом... и так, кажется, до бесконечности. Нам надо распутать этот проклятый клубок. /Фр.Герберт, Дюна/

ОБЩИЕ МЕСТА:
1. Программирование на FORTH только тогда доставит тебе удовольствие, когда ты сам этот FORTH написал.
2. Объектно-ориентированное программирование - болезнь, а глядя с высот FORTH - болезнь детская. Поэтому, наглые попытки, например, популярного Win32FORTH заставить меня пользоваться оконными классами - провокация и вопиющее головотяпство.
3. За основу первого проекта Win32-программирования взят очень хороший учебник ISZELION'S WIN32 ASM TUTORIAL (см. Приложение). Просто переписываю примеры с языка ассемблера на FORTH.

Конечно, я понимаю, что безнадежно отстал от жизни. Уже давно "бродит по Европе" Win-64... Однако, что имею, то и пою.
Наверняка, где-то да наврал. Найдете ляпы - пишите.

Предыстория - http://gudleifr.forum2x2.ru/t3-topic#9


Последний раз редактировалось: Gudleifr (Ср Авг 16, 2017 10:31 am), всего редактировалось 1 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:09 am

ТРУДНОЕ РЕШЕНИЕ

Must Die (далее просто MD, синоним слова Windows) имеет мерзейшую привычку делить все функции на два класса: а) те, что с огромным числом параметров, и б) те, что с одним параметром - адресом структуры, в которую подобные же параметры упакованы. Как запомнить, где какой случай? Как избавиться от замусоривания области имен ненужными конструкциями? Не спасает даже объектно-ориентированный оптимизм... Если хочешь постоянно использовать подобные конструкции, инкапсуляция всей этой белиберды будет арвиважнейшей задачей. Первоначально, я же не утруждал себя задачей причесывания, но плодил монстров. Потом мне это надоело.
Действительно, в чем разница между случаями (а) и (б)? В рамках традиционного высокоуровневого программирования - огромная. А для FORTH? Стек, ведь,- тоже память. Зачем мучиться с размещением структур в памяти и именованием полей, если их можно выкладывать куда-то поле за полем? Хочется, конечно, не куда-то, а в стек, так проще. Что-то вроде нижеследующего:

: ВЫЗОВ SP@ >R РАЗМЕЩАТЕЛИ-СТРУКТУР ЗАПОЛНИТЕЛИ-СТЕКА WIN-ФУНКЦИЯ CALL R> SWAP >R SP! R> ;

В большинстве случаев, например, при регистрации классов и создании окон, РАЗМЕЩАТЕЛИ и ЗАПОЛНИТЕЛИ могут быть стандартными. Здесь на помощь приходит слово DOER (DEFER мне нравится меньше). Получается пирамида - [DOER-]слово, целиком создающее кадр стека, состоящее из [DOER-]слов задающих группы параметров, в свою очередь, состоящих из DOER-слов отдельных параметров. Например, так:

DOER РАМКА-ОКНА
MAKE РАМКА-ОКНА CW_USEDEFAULT DUP 2DUP ;

Как должны выглядеть РАЗМЕЩАТЕЛИ? Учитываем, что стек данных растет вниз:

DOER РАЗМЕЩАТЕЛЬ
MAKE РАЗМЕЩАТЕЛЬ ПОЛЕ-N ... ПОЛЕ-1 РАЗМЕР SP@ ;

Почему DOER? А вдруг, эта структура будет использоваться неоднократно и, следовательно, будет размещаться в более долговременной памяти.

ЭКРАН 1/3 РАЗМЕР-ОКНА \ изменит слово РАМКА-ОКНА (см.выше)
ОКНО \ вызовет слово РАМКА-ОКНА

Попытавшись провести это решение в жизнь, сразу столкнулся с тремя неприятностями:

1. существуют структуры, которые задом-наперед не заполнить (например, строго последовательные блоки ресурсов),
2. несмотря на обилие вызовов Win-API в программе, количество повторных вызовов очень мало; даже для внешне похожих фиговин (см. ниже) наборы вызываемых для их создания/обслуживания функций могут не иметь ничего общего (например, controls, оставшиеся Win32 в наследство от Win3.1, и controls, реализованные в comctl32.dll),
3. иногда, все-таки, существует потребность в хранении подобных структур и между вызовами Win-API.

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

См. еще - http://gudleifr.forum2x2.ru/t31-topic#247
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:12 am

ОБ ОБРАБОТЧИКАХ СООБЩЕНИЙ

Первоначально, обработчики WIN-сообщений рекомендовалось строить на основе оператора выбора (switch), занимающего в коде несколько страниц. Стараниями Рея Дункана, Эндрю Шульмана и других не-МелкоГибких разработчиков на смену switch-у пришли таблицы указателей на функции. Код стал более читабельным и компактным. Новацию переняла и команда Билла (понятно, присвоив себе славу первооткрывателей). Очевидно, имея в своем распоряжении FORTH, можно попытаться улучшить и это решение, чем я и занялся. Заметив, что в больших WIN-проектах в зависимости от состояния программы изменяются и способы обработки сообщений, я решил придать схеме побольше гибкости. Вот, что получилось:

Алгоритм О. УНИВЕРСАЛЬНЫЙ ОБРАБОТЧИК СООБЩЕНИЙ (Поиск по дереву без возвратов).
Входной параметр: КОД сообщения.
Выходной параметр: результат обработки сообщения (в терминах Windows).
О1. [Защелка.] Если КОД равен ЭТАЛОНУ, перейти к шагу 2, иначе - к 5.
О2. [Лист?] Если обработчик конечный, перейти к шагу 3, иначе - к шагу 4.
О3. [Вернуть результат.] Выполнить обработчик, вернуть его результат. Закончить работу.
О4. [Подобработчик.] Получить новый КОД (из MSG или состояния процесса). Безвозвратно перейти к обработчику-СЫНУ.
О5. [Следующий?] Если обработчика-БРАТА нет - перейти к шагу 3, иначе - к 6.
O6. [Переход.] Безвозвратно перейти к обработчику-БРАТУ. []

Видно, что процедуры шагов О3 (собственно обработчик) и О4 (получение нового КОДА) никогда не требуются одновременно. Значит можно сэкономить место и хранить в узле либо одно, либо другое.
Типовая WIN-ситуация:

1-й уровень - КОД = message
если WM_COMMAND:
2-й уровень - КОД = lpar (различение сообщений меню и органов управления)
3-й уровень - КОД = wpar (ID меню или органа управления)
***

Оказалось, подобный механизм мне понадобился еще раньше - при распознавании чисел в ядре FORTH, поэтому я добавил в ядро новое слово - RECEPTING. Затем, обнаглев, реализовал подобным образом и разбор командной строки. Получилось, что я сделал не просто дерево разбора, а универсальный конечный автомат.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:14 am

ТРЕХФИГОВОЕ ПРОКЛЯТИЕ MUST DIE

В Windows каждая фиговина должна быть описана трижды - а) как фиговина визуальная (размещение на экране, цвет и т.п.), б) как фиговина, что-то делающая (обработчик событий от этой фиговины), в) как фиговина, вызываемая по какому-то сообщению (привязка обработчика к сообщению и регистрация этого факта в функции обработки сообщений). Более того, фиговины должны связываться не только деревом обработки сообщений, но и сетью передач фокуса (по Tab), и матрицей Drag&Drop-ов...
Проблема была настолько удачно (конечно, за счет упрощения) решена в Visual Basic (и его Borland- и MS-потомках), что большинство современных программистов уверено, что виртуальные Events и Properties действительно имеют отношение к тому, что у Windows внутри.
С этой проблемой я бороться не стал (пока?). Хотя, кое-где удалось совместить все три описания.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:15 am

ДВА ЗАМЕЧАНИЯ О КОНСТАНТАХ

Как общеизвестно, MD-API просто перегружен константами: почти каждая из API-функций имеет связанное семейство констант, а то и больше (выбор подфункции, режимы вызова, типовые значения операндов...). Я не стал полностью копировать windows.inc внутрь программы, более того, отказался даже от именования тех констант, которые используются в примерах (за исключением встречающихся неоднократно). Вместо этого, я при описании заполнителей стека указываю из какого семейства берутся константы.
***

Второе замечание касается большого класса однократно рассчитываемых, но многократно используемых значений. Они встречаются в MD-API столь часто, что я ввел слова для их определения:

( иниц.значение) WIN-CONST: слово расчет WIN-CONST;
( нов.иниц.значение) WIN-CONST! слово

Первая конструкция определяет способ расчета такой "константы", который будет выполнен при первом к ней обращении, вторая - дает возможность перерасчета "константы".
Подобный механизм использован и для обращения к API-функциям. При первом обращении происходит связывание и вызов, при последующих - только вызов по уже определенному адресу.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:15 am

СПИСОК ПРИМЕРОВ УЧЕБНИКА  

1. THE BASICS
2. MESSAGEBOX -- удивительно, скольким программам такой MustDie-ности было бы вполне достаточно
3. A SIMPLE WINDOW
4. PAINTING WITH TEXT
5. MORE ABOUT TEXT
6. KEYBOARD INPUT
7. MOUSE INPUT
8. MENU
9. CHILD WINDOW CONTROLS
10. DIALOG BOX AS MAIN WINDOW -- здесь и далее: назначение многих ключей в ресурсе диалога так и остались невыясненными
11. MORE ABOUT DIALOG BOX
12. MEMORY MANAGEMENT AND FILE I/O
13. MEMORY MAPPED FILES
14. PROCESS
15. MULTITHREADING PROGRAMMING
16. EVENT OBJECT
17. DYNAMIC LINK LIBRARIES
18. COMMON CONTROLS
19. TREE VIEW CONTROL -- это нельзя понять, это нужно запомнить!
20. WINDOW SUBCLASSING
21. PIPE
22. SUPERCLASSING
23. TRAY ICON
24. WINDOWS HOOKS -- немного подправил ошибки
25. SIMPLE BITMAP
26. SPLASH SCREEN
27. TOOLTIP CONTROL
28. WIN32 DEBUG API. PART 1
29. WIN32 DEBUG API. PART 2 -- вторая часть этого и следующий пример вызывают справедливое недоумение некоторых антивирусов
30. WIN32 DEBUG API. PART 3 -- глючит, как и исходный пример, под некоторыми версиями MD?, процессорами..? Ошибка, в принципе, известна и описана в MD-документации.
31. LISTVIEW CONTROL -- славный продолжатель дела примера #19, к тому же подглючивает, как и исходный пример: нет пересчета размещения списка при изменении размера окна, и неочевидна реакция на первый doubleclick, если он попадает на поле размера файла
32. MULTIPLE DOCUMENT INTERFACE (MDI) -- Пирамиды, Великая Стена, "Ямато"? Фигушки! MDI!
33. RICHEDIT CONTROL. BASICS -- пока не готово
34. RICHEDIT CONTROL. MORE TEXT OPERATIONS -- пока не готово
35. RICHEDIT CONTROL. SYNTAX HILIGHTING -- пока не готово

Если кому уж совсем нечего делать, он может переписать в подобном ключе другие примеры из masm32 или книги Дж.Рихтера "Создание эффективных WIN32-приложений". Я не столько пытался создать учебник, сколько тестировал FOBOS.

ПОПУТНЫЕ ЗАМЕТКИ

Понятно, пришлось отказаться от статической подгрузки ресурсов и библиотек, поэтому некоторые варианты примеров опущены.
***
Номера сообщений и controls, а так же экранные сообщения и заголовки могут отличаться от приведенных в учебнике. Мне просто лень было их все отслеживать.
***
Куда делась компактность FORTH? 50% шитого кода - просто мусор (т.к. 16-разрядов было бы вполне достаточно). С ностальгией вспоминаю те времена, когда под код отводилось 64 килобайта. При грамотной организации процессов этого и сейчас было бы достаточно для написания ЛЮБОЙ программы.
***
Взяв ассемблер из старой DOS-версии FOBOS, я нашел в нем кучу ошибок. А ведь работало же! Потом заметил, что половина из них "не баги, но фичи", т.е. не так уж все было и неправильно.
***
Для работы всех примеров нет потребности в реализации большинства слов стандарта ANSI 94. Так, я до сих пор так и не ввел слово для операции умножения. Придется создавать для стандарта отдельный текстовый файл.
***
Черт, опять застрял на 33 примере: желание все сломать и начать заново, кажется просто неодолимым. Думаю, в течение недели (писано еще в конце 2009 года) я его все-таки "победю" и "раздувать мировой пожар" начну только после завершения 35-го примера.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:18 am

EXE, DLL, ПРОЦЕССЫ И ПОТОКИ

Не буду вспоминать всю историю Must Die, но только напомню, что изначально планировалось плодить под него исключительно маленькие, однооконные приложения, свободно обменивающиеся данными. Только появление первого MDI-монстра - MS Excell - вернуло все на старые DOS-овские рельсы: "Если Вы хотите многозадачности, значит Вы должны ее поддерживать внутри своего приложения!"
***

Проблему EXE я, допустим, победил, вынеся все, что можно в текстовый файл. Конечно, у Вас остается возможность и дальнейшего вылизывания ядра (при наличии masm32). Для сборки использовал команды (masm32 v.6.14):

\masm32\bin\ml /c /coff g2.asm
\masm32\bin\Link /SUBSYSTEM:WINDOWS /STACK:1048576,65536 /section:.text,RWE g2.obj

Для DLL (см. ниже) - соответственно:

\masm32\bin\ml /c /coff g4.asm
\masm32\bin\Link /SUBSYSTEM:WINDOWS /DLL /DEF:g4.def /section:.text,RWE /section:.bss,RWS g4.obj

Где файл g4.def состоит из 4 строк:

LIBRARY g4
EXPORTS
DLLEXE
DLLCALL

***

ПРОЦЕССЫ? Пожалуйста. Запускай то же ядро, только с другим текстовым файлом. (Сейчас алгоритм следующий - FOBOS открывает текстовый файл (расширение .txt) с тем же именем, что и исполняемый или (в случае наличия в командной строке имени файла) любой указанный (но тоже с расширением .txt).)
***

ПОТОКИ? См. как это сделано в примерах 15-16. Нужно ли это? На мой взгляд, сама идея потоков - следствие недоработки операционной системы. Есть процессы. Если бы они были реализованы по-человечески, то покрывали бы все потребности распараллеливания вычислений, плюс снимали бы с программиста всю головную боль по их изоляции друг от друга. А так мы вынуждены сами организовывать многозадачность и ломать голову над обеспечением синхронизации, сохранения критических данных и прочего.
***

DLL? Тут две проблемы: практическая и философская.
С точки зрения практики, это вопрос о повторном использовании кода. Выиграть в размере программы, используя в нескольких процессах общий кусок кода? Изолировать пространство процедур от пространства программ? Обеспечить совместимость разных программ используя стандартный интерфейс? На протяжении всей истории DOS-Windows принимались самые разные решения, и сейчас, наверное, уже никого не волнует, как это все работает. И, более того, когда программисту лень разбираться в существующих стандартах, он не колеблясь, придумывает собственные, называя их оверлеями, расширениями и т.д.

А все зло - от нерешенности второй проблемы - философской. Что есть подпрограмма? Часть кода, пригодная для повторного решения задач, схожих с текущей? Или - расширение операционной системы для создания цепочки все более мощных машин-бусин (опять Дейкстра)? Каждый решает по-своему. Отсюда и разнобой. Тем более, что приходится отталкиваться от произвольно принимаемых Биллом решений.

Как реализовать DLL в рамках текущего проекта? Так же, как реализовали EXE - ядро и текстовый довесок. Текстовый довесок интерпретируется в ф-ии Dll-main (при подключении к процессу). Вторая точка входа - итерпретация переданного слова (DLLEXE). Способ вызова: заполнить стек параметрами, добавить туда же строку со счетчиком - нужное библиотечное слово, найти адрес DLLEXE и EXECUTE его.
(Для универсальности снабдил DLL-заготовку 64K-блоком разделяемых параметров, и 1K пустым местом под вторую точку входа (DLLCALL). Как это использовать, видно в примере про Hook-исы).
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:22 am

ЖАЛКИЙ БРЕД О ГРАФИЧЕСКОМ ИНТЕРФЕЙСЕ

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

1. Попытка систематизировать все эти API-кубики "как есть", разрешив программисту самому собрать из них что-то полезное. В примерах применялся именно этот подход. Результат - плачевный. Всем понятно, что достигнуть тут хоть какой-то обозримости можно только за счет грубого упрощения - сведения всех (часто) используемых параметров в списки propertie-сов и event-ов.
2. "Игровой подход" - отрисовать красивый экран самому, классифицировать все области пространства на экране и "перемножить" на все возможные действия мышкой (клики, Dbl- и Right-клики, Move, Drag&Drop-ы...) и клавиатуры (по крайней мере, Shift, Alt и Ctrl), привязав к каждой клетке получившейся таблицы осмысленные API-парадигмы.
3. Подход, предложенный в "Комнатной модели",- привязать парадигмы к "желаниям" и "ожиданиям" пользователя, плюнув на "универсальность", вроде бы постулируемую Биллом.

Дальнейший бред на эту тему - http://gudleifr.forum2x2.ru/t34-topic.
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:24 am

ЕЩЕ О ЦИКЛЕ ОБРАБОТКИ СООБЩЕНИЙ И КЛАССАХ ОКОН

Попытаюсь здесь изложить общие места, хотя бы для того, чтобы разобраться самому.

ЦИКЛ ОБРАБОТКИ СООБЩЕНИЙ. Он не нужен тем приложениям, весь интерфейс, которых обеспечивается
- обращениям к MessageBox (примеры 02, 17),
- диалоговыми окнами, созданными функцией DialogBoxIndirectParam (функция DialogBoxParam нам не интересна, т.к. требует статической подгрузки ресурсов) (примеры 10A, 24, 27),
- стандартными диалогами (создаваемыми, например, функцией GetOpenFileName) (пример 28, 30) или
- их комбинацией.

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

Алгоритм Ц. ЦИКЛ ОБРАБОТКИ СООБЩЕНИЙ ПРИЛОЖЕНИЯ (Один на приложение).
Входные параметры: сложная система очередей сообщений Windows.
Выходной параметр: wParam последнего сообщения.
Внутренняя переменная: блок сообщений (структура MSG), состоящий из полей: hwnd - окно, которому адресовано сообщение, message - номер сообщения, wParam и lParam - параметры, time и pt (x и y) - временные и пространственные координаты сообщения.
Ц1. [Получение.] Выполнить GetMessage, если эта функция вернула 0, перейти к шагу 6, иначе - к шагу 2.
Ц2. [Немодальные диалоги.] Для всех [открытых] немодальных диалогов (созданных функцией CreateDialogIndirectParam) выполнить функцию IsDialogMessage, при получении первого ненулевого результата перейти к шагу 1. Если все вызовы вернули 0, перейти к шагу 3. (Обойтись без цикла, определяя нужный диалог по самому сообщению, очень сложно, т.к. диалог обрабатывает не только "свои" сообщения, но и сообщения своих дочерних окон.)
Ц3. [Акселераторы.] Выполнить TranslateAccelerator для текущей таблицы акселераторов (конечно, только если таковая имеется). (Вопрос о наличии нескольких таблиц акселераторов нигде не рассматривается.) В случае ненулевого результата перейти к шагу 1 (в этом случае генерируется новое сообщение, заменяющее старое), иначе - к шагу 4.
Ц4. [Трансляция.] Выполнить TranslateNessage, перейти к шагу 5.
Ц5. [Обработка.] Выполнить DispatchMessage, перейти к шагу 1.
Ц6. [Завершение.] Закончить работу, считая выходным результатом (который может использовать затем функция ExitProcess - завершение приложения) поле wParam. []
В простейшем случае шаги Ц2 и Ц3 обычно опускаются.
***

КЛАССЫ ОКОН. Типов окон в Windows очень много, хотя внутри системы все они описываются одинаковым набором параметров (параметры делятся на параметры класса окна и параметры самого окна - в лучших традициях объектно-ориентированного программирования). Отличаются окна друг от друга: во-первых, различными значениями этих самых параметров, в том числе, параметров, описывающих их (окон) взаимную зависимость; во-вторых, совершенно различными (для пользователя) способами создания окон; в-третьих, различиями (опять, только для пользователя) в управлении окнами (в первую очередь, выражающимися в виде их оконных функций).
Некоторые среды программирования, например фирмы Borland, вообще, абстрагируются от этих различий, предпочитая иметь дело только с окнами общего вида и controls (тоже, ведь, окна).
Еще одна сложность состоит в том, что ни в коем случае нельзя путать то, что рисуется на самом окне (фоновая картинка, текст) с дочерними окнами controls (кнопками, окнами редактирования и т.д.), размещаемыми в окне. Иногда этот вопрос сильно запутывается, например, в случае меню, но в этих случаях Win-API предлагает столько разнообразных функций, что разбираться в том "как все на самом деле" нет никакого резона.
Перечислю типы окон, встреченные в примерах.

ТипСозданиеЧто должна вернуть оконная функция (и нужна ли она)Примечания
КлассОкно# примераЗамечания
Стандартные диалоги-MessageBox, GetOpenFileName и т.п.-2, 11B, 23встречаются и нетривиальные случаи, например, иконка на панели задач
Окно общего видаRegisterClassExCreateWindowEx0 или результат DefWindowProc *3-8, 25во всех примерах - только одно на приложение, обычно имеет меню ***
Control-CreateWindowEx или специальные функции-9, 18, 19, 27, 31, 32controls неявно делятся на две группы - вставляемые преимущественно в окна общего вида (иногда, даже, бывают сильно нетривиальными и/или невидимыми) и используемые преимущественно в диалоговых окнах (обычно простые)
Немодальный диалог в роли окна общего видаRegisterClassExCreateDialogIndirectParam **0 или результат DefWindowProc10такой диалог очень похож на обычное окно и обычно имеет меню
Модальный диалог-DialogBoxIndirectParam1 - в случае, если сообщение обработано, 0 - в противном случае10A, 11A, 24если используется вместо обычного окна, обычно снабжается меню
Немодальный диалог при живом родителе-CreateDialogIndirectParam1 - в случае, если сообщение обработано, 0 - в противном случае11-
Субкласс-CreateWindowEx0 или результат CallWindowProc20изготовляются из обычных сontrols подменой оконной функции
СуперклассRegisterClassExCreateWindowEx0 или результат CallWindowProc22изготовляются из обычных сontrols подменой оконной функции, но не в параметрах окна, а в параметрах класса
MDI фреймRegisterClassExCreateWindowEx0 или результат DefFrameProc32изготовляется из окна общего вида, созданием в нем специального control MDICLIENT
MDI дочернее окноRegisterClassExпосылка сообщения родительскому MDICLIENT0 или результат DefMDIChildProc32практически, окно общего вида, только меню "делегируется" родительскому окну
Примечания:
* - запись вида "0 или результат функции", означает, "если оконная функция считает, что она полностью обработала сообщение, она возвращает 0, иначе - передает сообщение для обработки указанной функции".
** - суффикс Indirect появился у меня в силу того, что моя концепция минимального exe-ядра не позволяет загружать ресурсы напрямую в exe-файл.
*** - меню можно прописывать и в параметры класса и в параметры окна, но первый способ, как и в случае ресурсов, для меня оказался недоступен.

ФУНКЦИИ ЗАКРЫТИЯ ОКОН. Эти функции "размазаны" по дереву обработчика сообщений и отслеживать их затруднительно. Обычно используются три стандартных сообщения (WM_CLOSE, WM_DESTROY и WM_MDIDESTROY) и три функции (PostQuitMessage, DestroyWindow и EndDialog). Я понял это так:
1. функция PostQuitMessage вызывает завершение цикла обработчика сообщений и должна обязательно присутствовать в обязательном обработчике сообщения WM_DESTROY главного окна общего вида или немодальном диалоге, играющим его роль;
2. убить любое окно можно, послав ему сообщение WM_CLOSE;
3. обработчики сообщения WM_CLOSE обязательны для немодальных диалогов с родителем, модальных диалогов (в обоих случаях в них вызывается EndDialog) и дочернем окне MDI (оттуда надо послать сообщение WM_MDIDESTROY MDICLIENT родительского окна);
4. к посылке главному окну сообщения WM_DESTROY приводит функция DestroyWindow (и стандартный обработчик WM_CLOSE в DefWindowProc (?));
5. цепочка обработки сообщений, приводящая к вызову DestroyWindow или EndDialog, может довольно сильно петлять, например, в диалоге получение WM_CLOSE может приводить к передаче какого-то другого сообщения, и только обработка того приведет к вызову EndDialog;
6. вызывать DestroyWindow и EndDialog из любого места, где может понадобиться закрытие окна, или использовать дополнительное сообщение для перехода к тому единственному обработчику (обычно привязываемому к какому-либо "закрывающему" control), в котором стоит подобный вызов - дело вкуса.
***

Можно ли тут что-то FORTH-упростить? Могу только констатировать, что, тупо переписывая примеры учебника на FORTH, допустил ряд ошибок:
- забыл предусмотреть в слове, реализующем цикл обработки сообщений, дырки для встраивания обработки немодальных диалогов и таблиц акселераторов;
- не учел наличия большого числа оконных функций в сложных приложениях;
- не создал типовых слов для переопределения заполнителей при вызове функции CreateWindowEx и не применил к ним механизма восстанавливаемых ассемблеров, тоже для открытия/закрытия файлов;
- не предусмотрел механизмов для поддержки одновременного существования нескольких ресурсов меню и/или диалогов;
- не обрезал возможность различной маршрутизации сигналов закрытия окон путем введения пары-другой типовых слов.
- не привел все call-back функции к одному знаменателю.


Последний раз редактировалось: Gudleifr (Вт Окт 24, 2017 8:23 pm), всего редактировалось 1 раз(а)
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:26 am

РАБОТА НАД ОШИБКАМИ

Пожалуй, полгода я потратил на тщетные попытки как-то рационализировать интерфейсы своих Windows-программ, забросив дописывание примеров, точнее, лишь внося в них какие-то, вроде бы, поясняющие и упрощающие поправки. Постепенно я пришел к пониманию, что ничего из этого не выйдет по очень простой причине - я строю замок на песке. Попытка создать простой и понятный интерфейс "программа-пользователь" заранее была провальной, т.к. потребный для этого частный интерфейс "программа-Windows" так и остался набором разнородных рекомендаций и мутных правил.
Когда-то давным-давно я задался целью создать кнопочку в окне общего вида. О Windows я тогда мало что знал и честно полез в его справочную систему. Практически сразу нашел: "Чтобы создать кнопку в диалоговом окне, в файле ресурсов...". С настойчивостью героя "Улитки на склоне", я продолжил поиски. Нашел: "Кнопка в окне общего вида? Это совсем другое дело! Вот, если Вам нужна кнопка в диалоговом окне, то в файле ресурсов..." Так и сейчас, глядя на свою свалку примеров, вижу только несколько кухонных рецептов, но никакого очевидного практически пригодного способа приготовить на Must Die именно то, что хочется.
Как я писал примеры? Брал очередной-пример из asm-учебника и тупо переписывал на FORTH, заменяя макросы и более-менее общие куски FORTH-словами. Когда встречал Win-константу, лез в masm-файл windows.inc и выдергивал оттуда ее численное определение. Когда встречал вызов Win-функцию, вызывал справочник MSDN (занимающий на копьютере несколько гигабайт) и проверял, в какой dll-библиотеке она "живет", имеет ли ASCII-суффикс, как вызывается и что возвращает... Получилось, что для нормальной работы с моим набором примеров необходимы эти самые справочники, ведь именно в них указано, как видоизменить пример для получения чего-то путного.

Сравнивая любой из примеров с программой, написанной в каком-нибудь визуальном обезьяннике, можно видеть следующие куски:
- Запускающая часть. В примере - обычно вызов общей парадигмы регистрации и отображения универсального окна, определенной в третьем примере. В Borland-программе, ее, например, обычно вообще не видно, а в MS Visual C++ она спрятана в кусках, имеющих страшные комментарии "Не влезай - убьет!" Здесь ситуация обратная детским кубикам, где для построения чего-либо достаточно чертежа - соединение кубиков друг с другом очевидно. MD-программа - это, скорее, красивый розовый домик в разных комнатах которого надо расставлять мебель, селить Барби и Кена (и не дай бог перепутать).
- Определения необходимых Win-API сущностей. В примере - жалкие огрызки бесконечных Win-справочников, а в обезъянниках - гиперссылки на эти самые справочники. По идее, это каталог кубиков (прайс-лист какой-нибудь "икеи" в Барби-модели).
- Win-парадигмы. Вот тут мои примеры немного симпатичнее страшно выглядящих asm- и C-вызовов, т.к. мне удалось хоть как-то засунуть общие куски в универсальные слова. Т.е. хотя бы на этом уровне удалось загнать внутрь "кубиков" хоть немного MD-требухи.
- Смысловая часть примеров. Ни у меня, ни в обезьянниках ее практически невозможно отличить от (3). А ведь здесь было бы самое место чертежу.

А применимо ли вообще понятие "кубика" к программированию? Исторически это очень близко к машинам-бусинам Дейкстры и конструкциям структурного программирования. Объектно-ориентированное программирование - это, скорее, уже отход от данной схемы, т.к. кубики стали в большинстве случаев нестыкуемыми. Т.о. налицо следующие проблемы.
1. Необходим какой-либо справочник, пусть убогий для того, чтобы обрисовать хотя бы примерную область применения показанного в примере API-средства.
2. Необходимо как-то разграничить примененные в примере виды данных и программные структуры на те, которыми можно "поиграть" для модификации примера (цвет фона, позиция Control, текст приглашения...), те, которые важны для примера (стиль окна, обрабатываемые сообщения...), и те, которые должны выступать в жесткой связке (открывающие и закрывающие функции, имена классов, handlers...).

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

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Gudleifr в Ср Авг 16, 2017 10:33 am

ИНСТРУКЦИЯ ПО УСТАНОВКЕ ПРОЕКТА НА ВАШЕМ КОМПЬЮТЕРЕ

(Такие сложности были нужны т.к. на моем старом хостинге не было возможности хранить исполняемые файлы и архивы. Сейчас, конечно, можно сразу использовать .exe и .dll).

Алгоритм У. УСТАНОВКА (Создание работоспособной win-версии FOBOS).
Входные параметры: Набор HTML-ссылок на текстовые файлов.
У1. [Директорий.] Создать в удобном для Вас месте новый директорий (папку, каталог) и загрузить туда текстовые файлы средствами вашего Internet-браузера (следите за именами файлов).
У2. [Командный.] Найти в директории файл install.txt и переименовать его в install.bat . Запустить его на исполнение. []

Немного подробнее:
Команды в install.bat делятся на три группы:

debug <файл -- создание bin-файла, по содержимому соответствующему нужному exe или dll.
ren имя.bin имя.exe (.dll) -- переименование файла
copy имя1.exe (.dll) имя2.exe (.dll) -- копирование файлов для создания FORTH-программ с тем же ядром, но приспособленных под другой текстовый довесок.

После исполнения командного файла в директории появятся несколько exe-файлов (все одинаковые, и, в принципе, достаточно одного) и dll-файлов (тоже все одинаковые). Если exe-файлы можно запускать как и не указывая имя txt-файла (т.е будет использован txt-файл того же директория с тем же именем), так и с явным указанием txt-файла (будет использован файл с указанным именем (путем) и расширением .txt), при использовании библиотек возможен только первый вариант.
***

Как с этим работать: найти в файле g2.txt нужный пример и раскомментировать в нем последнюю строчку. Запустить g2.exe.

ФАЙЛЫ - https://cloud.mail.ru/public/iqTp/9FU9DcbN5
коды exe-файла - g2bin.txt
коды dll-файла - g4bin.txt
все примеры - g2.txt
простое WIN-приложение для примера 14 - g3.txt
простая библиотека для примера 17 - g4.txt
hook-библиотека для примера 24 - g5.txt
splash-библиотека для примера 26 - g6.txt
подвисающее приложение для примера 29 - g7.txt
иконки для примера 19 - list.bmp
картинка для примера 25 - tweety78.bmp
заставка для примера 26 - JourneyStart.bmp
командный файл инсталляции - install.txt
ПРИЛОЖЕНИЕ
исходный текст exe-файла на языке ассемблера - g2asm.txt
исходный текст dll-файла на языке ассемблера - g4asm.txt
готовый g2.exe (и остальные g?.exe)
готовый g4.dll (и остальные g?.dll)
ISZELION'S WIN32 ASM TUTORIAL (англ.). Part I - masm32-1.txt
ISZELION'S WIN32 ASM TUTORIAL (англ.). Part II - masm32-2.txt
ISZELION'S WIN32 ASM TUTORIAL (англ.). Part III - masm32-3.txt

Лицензия GNU - http://www.gnu.org/licenses/gpl.html
avatar
Gudleifr
Admin

Сообщения : 932
Дата регистрации : 2017-03-29

Посмотреть профиль

Вернуться к началу Перейти вниз

Re: WIN-FORTH для минималистов (проект FOBOS)

Сообщение автор Спонсируемый контент


Спонсируемый контент


Вернуться к началу Перейти вниз

Вернуться к началу


 
Права доступа к этому форуму:
Вы не можете отвечать на сообщения