Mario79
Пеинт
libGUI
Leency
Ну, в общем, то я и сам так представлял внешний вид.
И даже сделать такое не сложно, но вот как обмениваться с приложениями?... Пока не представляю.
Ну, в общем, то я и сам так представлял внешний вид.
И даже сделать такое не сложно, но вот как обмениваться с приложениями?... Пока не представляю.
По идее должен получить ошибку от ядра (или чего у вас там). Главное, чтобы вразумительную. Типа, "Уважаемый пользователь, вы выкинули GUI и стали сами себе дураком".erema wrote:Вот только если кто-то "выкинет" GUI...
Замечания по libGUI.
1. Что за странная модель передачи входных и выходных значений? Если это предназначено для ассемблерщиков, то проще всё передавать в регистрах, если рассматривается вариант для ЯВУ - то есть нормальная модель stdcall, когда входные параметры передаются в стеке, а возвращаемое значение в eax (а не заталкивается зачем-то в стек).
2. Пример editbox: запускаем, щёлкаем мышкой по полю ввода, нажимаем Backspace (в пустом поле ввода). Фокус ввода исчезает. Снова щёлкаем мышкой по полю ввода и нажимаем Backspace. Программа вылетает.
3. Почему нет средств программного управления фокусом ввода? Что ли, симулировать нажатия мышкой при необходимости?
4. Раз уж различные версии несовместимы, где средства контроля версий (как в библиотеках console и libini)?
5. Что за странные экспортируемые имена? "craete editbox" - заменить на "create_editbox" или "CreateEditBox" - по вкусу.
1. Что за странная модель передачи входных и выходных значений? Если это предназначено для ассемблерщиков, то проще всё передавать в регистрах, если рассматривается вариант для ЯВУ - то есть нормальная модель stdcall, когда входные параметры передаются в стеке, а возвращаемое значение в eax (а не заталкивается зачем-то в стек).
2. Пример editbox: запускаем, щёлкаем мышкой по полю ввода, нажимаем Backspace (в пустом поле ввода). Фокус ввода исчезает. Снова щёлкаем мышкой по полю ввода и нажимаем Backspace. Программа вылетает.
3. Почему нет средств программного управления фокусом ввода? Что ли, симулировать нажатия мышкой при необходимости?
4. Раз уж различные версии несовместимы, где средства контроля версий (как в библиотеках console и libini)?
5. Что за странные экспортируемые имена? "craete editbox" - заменить на "create_editbox" или "CreateEditBox" - по вкусу.
Ушёл к умным, знающим и культурным людям.
1) Как передавать параметры - обсуждалось в этой теме.Обсуждение было открытым. В результате обсуждения пришли к выводу, что параметры нужно передавать через стек.Конкретных вариантов НЕБЫЛО вообще. Я подумал как это можно сделать и реализовал в первой версии свой вариант передачи параметров. НИКТО НЕ ВЫСКАЗАЛСЯ НИ ЗА НИ ПРОТИВ этого варианта. И я стал использовать его дальше. Проверкой исходников занимаются в основном только авторы.
2)То, что editbox не работает, я писал. Я не автор этого компонента, я только пытался адаптировать его для библиотеки. Но так, как автору в это время было совершенно некогда заниматься этим компонентом, то один баг так и остался неисправленным.
3) В смысле чтобы некоторые компоненты(EditBox например ) автоматически активировались ? В принципе можно посылать свои координаты мыши, чтобы активировать компонент. А если делать автоматическую активацию, то надо добавлять новую функцию в библиотеку. Как её можно назвать ?
4)Когда будет время - добавлю. Я что-то не придавал внимания этому.
5)Какая разница, как называются имена, ведь главное получить указатель на начало функции, чтобы её вызвать ? В программе эти функции можно назвать по любому(желательно придерживаться одинаковых названий для разных программ разных авторов).
2)То, что editbox не работает, я писал. Я не автор этого компонента, я только пытался адаптировать его для библиотеки. Но так, как автору в это время было совершенно некогда заниматься этим компонентом, то один баг так и остался неисправленным.
3) В смысле чтобы некоторые компоненты(EditBox например ) автоматически активировались ? В принципе можно посылать свои координаты мыши, чтобы активировать компонент. А если делать автоматическую активацию, то надо добавлять новую функцию в библиотеку. Как её можно назвать ?
4)Когда будет время - добавлю. Я что-то не придавал внимания этому.
5)Какая разница, как называются имена, ведь главное получить указатель на начало функции, чтобы её вызвать ? В программе эти функции можно назвать по любому(желательно придерживаться одинаковых названий для разных программ разных авторов).
Вот именно потому, что в программе их можно назвать по-любому, и нужны эталонные названия - на горизонте маячит Kolibri SDK для языков высокого уровня.andrew_programmer wrote:В программе эти функции можно назвать по любому(желательно придерживаться одинаковых названий для разных программ разных авторов).
andrew_programmer
1. Конвенция вызова stdcall: входные параметры передаются в стеке (так, что на вершине стека оказывается первый из параметров), возвращаемое значение - в регистре eax (64-битное целое - в паре edx:eax), стек очищает вызываемая функция. Примерно так:
При использовании macros.inc:
Во втором случае параметры адресуются неявно через ebp, так что сама процедура не может использовать ebp.
Кстати, конвенция stdcall предписывает сохранять регистры ebx,esi,edi,ebp.
2. В приложениях, использующих editbox напрямую (run, kfm, rdsave), этого глюка нет.
3. В том то и дело, что неудобно рассчитывать координаты мыши, которые надо передавать, а также при таком подходе нужно два вызова функции - первый эмулирует нажатие, второй - отжатие.
5. Я смотрел используемую концепцию импорта. Она, конечно, работает, но идеологически неправильна. Дело в следующем. Формат таблицы экспорта на псевдо-Си:
Вариант импорта в libGUI (условно):
Вариант импорта, изначально предлагаемый автором подхода Serge и реализованный везде, кроме libGUI:
Подход libGUI работает, но только до тех пор, пока 2-й вход в таблице экспорта соответствует SendMessage. А что, если нужно добавить новую функцию? Добавлять её всегда в конец? А если какая-то из существующих функций в новой версии библиотеки не имеет смысла и должна быть удалена? Для справки: в Windows соответствующие подходы именуются импортом по ординалу и импортом по имени, и импорт из системных библиотек типа kernel32 должен осуществляться по имени. В *nix импорта по ординалу нет вообще.
И вот для импорта по имени нужны осмысленные корректные имена.
1. Конвенция вызова stdcall: входные параметры передаются в стеке (так, что на вершине стека оказывается первый из параметров), возвращаемое значение - в регистре eax (64-битное целое - в паре edx:eax), стек очищает вызываемая функция. Примерно так:
Code: Select all
; главная программа
...
push param4
push param3
push param2
push param1
call [Function]
mov [returnValue], eax
...
Code: Select all
; библиотека
Function:
mov eax, [esp+4] ; первый параметр
mov ecx, [esp+8] ; второй параметр
...
mov eax, returnValue
ret 4*4 ; выталкиваем 4 параметра
Code: Select all
; главная программа
invoke Function, param1,param2,param3,param4
mov [returnValue],eax
Code: Select all
; библиотека
proc Function stdcall, param1:dword, param2:dword, param3:dword, param4:dword
mov eax,[param1] ; первый параметр
...
mov eax,returnValue
ret
endp
Кстати, конвенция stdcall предписывает сохранять регистры ebx,esi,edi,ebp.
2. В приложениях, использующих editbox напрямую (run, kfm, rdsave), этого глюка нет.
3. В том то и дело, что неудобно рассчитывать координаты мыши, которые надо передавать, а также при таком подходе нужно два вызова функции - первый эмулирует нажатие, второй - отжатие.
5. Я смотрел используемую концепцию импорта. Она, конечно, работает, но идеологически неправильна. Дело в следующем. Формат таблицы экспорта на псевдо-Си:
Code: Select all
typedef struct
{
const char* FuncName;
const void* FuncAddr;
} item;
item EXPORTS[];
Code: Select all
SendMessage = EXPORTS[2].FuncAddr;
CreateEditBox = EXPORTS[3].FuncAddr;
Code: Select all
for (i пробегает таблицу импорта)
if (!strcmp(EXPORTS[i].FuncName,"SendMessage"))
{SendMessage = EXPORTS[i].FuncAddr;break;}
И вот для импорта по имени нужны осмысленные корректные имена.
Ушёл к умным, знающим и культурным людям.
andrew_programmer
3. Обычно такая функция называется SetFocus(control). В дополнение к ней пишутся обработчики OnSetFocus() и OnLostFocus() для событий получения и потери фокуса контролами или один общий обработчик OnChangeFocus()
3. Обычно такая функция называется SetFocus(control). В дополнение к ней пишутся обработчики OnSetFocus() и OnLostFocus() для событий получения и потери фокуса контролами или один общий обработчик OnChangeFocus()
diamond
Спасибо за советы.
Между обычным EditBox-ом(1) и EditBox-ом(2) встроенным в libGUI есть одно принципиальное
различие - у них разные методы получения координат мыши.(1) компонент получает координаты
мыши относительно левого верхнего угла экрана. Потом из процесса узнаются координаты окна, в
котором нарисован компонент, после берётся разность координат.Эта разность задаёт координаты
мыши внутри окна. Зачем это делается - мне непонятно. Рисовать за пределами окна непозволит
система, а координаты мыши внутри окна можно и так узнать.
В libGUI координаты мыши берутся относительно окна, потом эти координаты посылаются ввиде
сообщения и библиотека добавляет к координатам высоту скина и ширину боковой рамки.Я пытался
переделать компонент (1) для работы с координатами мыши рассчитанными относительно окна.
Переделать удалось, но вместе с переделкой я внёс какую-то ошибку в компонент.Это скорее всего
связано с ошибкой в работе со стеком.Хотя я потратил немало времени на поиск ошибки, найти
место,где происходит ошибка, мне неудалось.
Serge
Можно, пожалуйста, пример использования этих функций, чтобы я окончательно понял идею ?
Спасибо за советы.
Между обычным EditBox-ом(1) и EditBox-ом(2) встроенным в libGUI есть одно принципиальное
различие - у них разные методы получения координат мыши.(1) компонент получает координаты
мыши относительно левого верхнего угла экрана. Потом из процесса узнаются координаты окна, в
котором нарисован компонент, после берётся разность координат.Эта разность задаёт координаты
мыши внутри окна. Зачем это делается - мне непонятно. Рисовать за пределами окна непозволит
система, а координаты мыши внутри окна можно и так узнать.
В libGUI координаты мыши берутся относительно окна, потом эти координаты посылаются ввиде
сообщения и библиотека добавляет к координатам высоту скина и ширину боковой рамки.Я пытался
переделать компонент (1) для работы с координатами мыши рассчитанными относительно окна.
Переделать удалось, но вместе с переделкой я внёс какую-то ошибку в компонент.Это скорее всего
связано с ошибкой в работе со стеком.Хотя я потратил немало времени на поиск ошибки, найти
место,где происходит ошибка, мне неудалось.
Serge
Можно, пожалуйста, пример использования этих функций, чтобы я окончательно понял идею ?
andrew_programmer
SetFocus(control) назначает контролу фокус ввода т.е. все нажатые клавиши будут посылаться ему. Функция посылает сообщения kill_focus предыдущему контролу и set_focus новому. Это необходимо чтобы они могли отреагировать на изменения фокуса. Например в Win поля ввода прячут или устанавливают курсор ввода (caret) и меняют подсветку выделенного текста. В диалогах кнопки отрисовывают рамку при переборе по Tab и т.д. Возвращаемое значение - хендл предыдущего контрола имевшего фокус.
SetFocus(control) назначает контролу фокус ввода т.е. все нажатые клавиши будут посылаться ему. Функция посылает сообщения kill_focus предыдущему контролу и set_focus новому. Это необходимо чтобы они могли отреагировать на изменения фокуса. Например в Win поля ввода прячут или устанавливают курсор ввода (caret) и меняют подсветку выделенного текста. В диалогах кнопки отрисовывают рамку при переборе по Tab и т.д. Возвращаемое значение - хендл предыдущего контрола имевшего фокус.
Итак полетели камни в мой огород ). Объясню почему было сделано получение координат мышки таким странным образом в посленей ревизии EditBox. Дело в том, что есть разные стили оформления окна, при выводе окна нужно учитывать относительно чего считаются координаты, например, в разных программах KFM,Run используется по разному отсчет координат, для унификации и была придумана данная идея получения координат. Вот вырезка и исходного кода:
Итак в самом начале мы получили координаты мышки относительно верхнего левого угла экрана.
Далее получаем координаты нашего приложения, фунцией 9, от куда узнаем координаты нашего окна, далее вычиляем координаты, с учетом оформления, т.е. при сборке нужно указать ширину и высоту рамок оформления, или же не указывать их совсем. Данный метод, на мой взгляд является универсальным, т.к. он независим в будующем от типа оформления и других факторов.
В примере EditBox реализован код управления множеством или подгруппой EditBox, при переносе кода EditBox в библиотеку, необходимо переработать идею упраления EditBox. В библиотеке должен быть реализован демон обработки событий, фокуса, и т.д. Задача EditBox заключается в корректной обработке предоставляемых данных, а не самой обрабатывать события и реагировать на них. К тому же реализация для библиотеки должна быть выполнена с передачей в стеке, а не в регистрах, в духе С.
P.S. Забыл еще добавить, такая сложная обработки координат положения окна необходима для того что бы можно было выделять текст в Editbox, даже если курсор ушел за пределы активного окна приложения.
Code: Select all
;----------------------------------------------------------
;--- получаем координаты мыши относительно 0 т.е всей области экрана
;----------------------------------------------------------
@@: mcall 37,0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Функция обработки мышки получение координат и проверка их + выделения
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_work_mause scr_h,scr_w
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Общие функции обработки
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_general_func
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Функции для работы с key
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_key_func
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Функции для работы с mouse
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
use_mouse_func scr_w
Далее получаем координаты нашего приложения, фунцией 9, от куда узнаем координаты нашего окна, далее вычиляем координаты, с учетом оформления, т.е. при сборке нужно указать ширину и высоту рамок оформления, или же не указывать их совсем. Данный метод, на мой взгляд является универсальным, т.к. он независим в будующем от типа оформления и других факторов.
В примере EditBox реализован код управления множеством или подгруппой EditBox, при переносе кода EditBox в библиотеку, необходимо переработать идею упраления EditBox. В библиотеке должен быть реализован демон обработки событий, фокуса, и т.д. Задача EditBox заключается в корректной обработке предоставляемых данных, а не самой обрабатывать события и реагировать на них. К тому же реализация для библиотеки должна быть выполнена с передачей в стеке, а не в регистрах, в духе С.
P.S. Забыл еще добавить, такая сложная обработки координат положения окна необходима для того что бы можно было выделять текст в Editbox, даже если курсор ушел за пределы активного окна приложения.
На мой взгляд все сводиться к тому, что необходимо представить стандарт по архитектурной разработке библиотеки. Поправьте меня если я ошибусь.
Библиотеки можно разделить на два типа - это содержащие менеджер обработки событий т.е. нужно передавать события и обычные, которым нужно передавать данные к примеру в стеке и получать определенный результат.
1) Код библиотеки должен быть реентерантным.
2) Все пользовательские данные должны храниться в памяти у пользовательской программы.
3) Загрузка двух и более копий одной библиотеки не допускается
4) Предоставление одной копии DLL разным программам через системный драйвер.
Как все будет выглядеть:
Итак при первом обращении приложение через драйвер реализует загрузку библиотеки, по некоторому адресу. Если запускается еще одно приложение, и запрашивает ту же библиотеку, то получает
линки на загруженую библиотеку и может передавать управление на нее. Разработка драйверной модели позволит исключить загрузку лишнего кода, уменьшиться общее кол-во используемой памяти под загрузку библиотеки. Драйвер по сути будет являться менеджером по загрузки, выгрузке, предоставлению сервиса программам, которые будут обращаться к нему. расходы программы сократятся до выделения места только под данные, которые будут храниться в пользовательской программе. Драйверная модель загрузки библиотек нуждается в сервисе разграничения доступа к памяти куда загружены будут библиотеки.
Еще нужно разработать универсальный обработчик событий для компонентов, с обратной связью. Т.е. предлагаю всем принять участие в обсуждении данных тем.
Приведу пример. Для корректной обработки мышки у EDITBOX необходимо в определеннный момент предоствавить монопольный доступ к обработки сообщений от мышки. Этот момент выглядит так: при нажатии клавиши мышки и попадании курсора в активную область editbox, необходимо монопольно передавать перемещение мышке боксу т.к. в начале бокс поймал фокус, а затем можно выделить область ввода при помощи перемещения мышки, до тех пор, пока пользователь не отпустит кнопку мышки. Допускаю, что существуют более сложные комбинации для обработки сложных событий, следовательно, Общий обработчик событий должен уметь обрабатывать внешний код, представленный в коде вызывающей программы, т.к. на все случаи жизни не возможно предусмотреть и написать универсальный обработчик. Остановимся на событиях. событие от клавиатуры, события от мышки, события от IPC ...... События клавиатуры предоставляются объекту с фокусом, и он самостоятельно их обрабатывает. События от мышки то же стандартны - предоставление фокуса объекту, и передачу ему координат, пока не будет отжата клавиша.
Библиотеки можно разделить на два типа - это содержащие менеджер обработки событий т.е. нужно передавать события и обычные, которым нужно передавать данные к примеру в стеке и получать определенный результат.
1) Код библиотеки должен быть реентерантным.
2) Все пользовательские данные должны храниться в памяти у пользовательской программы.
3) Загрузка двух и более копий одной библиотеки не допускается
4) Предоставление одной копии DLL разным программам через системный драйвер.
Как все будет выглядеть:
Итак при первом обращении приложение через драйвер реализует загрузку библиотеки, по некоторому адресу. Если запускается еще одно приложение, и запрашивает ту же библиотеку, то получает
линки на загруженую библиотеку и может передавать управление на нее. Разработка драйверной модели позволит исключить загрузку лишнего кода, уменьшиться общее кол-во используемой памяти под загрузку библиотеки. Драйвер по сути будет являться менеджером по загрузки, выгрузке, предоставлению сервиса программам, которые будут обращаться к нему. расходы программы сократятся до выделения места только под данные, которые будут храниться в пользовательской программе. Драйверная модель загрузки библиотек нуждается в сервисе разграничения доступа к памяти куда загружены будут библиотеки.
Еще нужно разработать универсальный обработчик событий для компонентов, с обратной связью. Т.е. предлагаю всем принять участие в обсуждении данных тем.
Приведу пример. Для корректной обработки мышки у EDITBOX необходимо в определеннный момент предоствавить монопольный доступ к обработки сообщений от мышки. Этот момент выглядит так: при нажатии клавиши мышки и попадании курсора в активную область editbox, необходимо монопольно передавать перемещение мышке боксу т.к. в начале бокс поймал фокус, а затем можно выделить область ввода при помощи перемещения мышки, до тех пор, пока пользователь не отпустит кнопку мышки. Допускаю, что существуют более сложные комбинации для обработки сложных событий, следовательно, Общий обработчик событий должен уметь обрабатывать внешний код, представленный в коде вызывающей программы, т.к. на все случаи жизни не возможно предусмотреть и написать универсальный обработчик. Остановимся на событиях. событие от клавиатуры, события от мышки, события от IPC ...... События клавиатуры предоставляются объекту с фокусом, и он самостоятельно их обрабатывает. События от мышки то же стандартны - предоставление фокуса объекту, и передачу ему координат, пока не будет отжата клавиша.
Сделал набросок своей библиотеки, используется компонет editbox, исходники не выкладываю, т.к. сырые, и хочется добавить еще функциональности. Посмотреть пример можно, скачав прикрепленный файл.
Это экспортируемые данные.
Вот пример вызова функций:
Обновил файл
Code: Select all
;DATA данные
ini_file db 'box_lib.obj',0
myimport:
edit_box_draw dd aEdit_box_draw
edit_box_key dd aEdit_box_key
edit_box_mouse dd aEdit_box_mouse
version dd aVersion
dd 0
dd 0
aEdit_box_draw db 'edit_box',0
aEdit_box_key db 'edit_box_key',0
aEdit_box_mouse db 'edit_box_mouse',0
aVersion db 'version',0
Вот пример вызова функций:
Code: Select all
red_win:
call draw_window ;первоначально необходимо нарисовать окно
align 4
still: ;основной обработчик
mcall 10 ;Ожидать события
dec eax
jz red_win
dec eax
jz key
dec eax
jz button
push dword edit1
push 22
push 5
call [edit_box_mouse]
jmp still ;если ничего из перечисленного то снова в цикл
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
button:
mcall 17 ;получить идентификатор нажатой клавиши
test ah,ah ;если в ah 0, то перейти на обработчик событий still
jz still
exit: mcall -1
key:
mcall 2 ;загрузим значение 2 в регистор eax и получим код нажатой клавиши
push dword edit1
call [edit_box_key]
jmp still
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
align 4
draw_window: ;рисование окна приложения
mcall 12,1
mcall 0,(50*65536+390),(30*65536+200),0xb3AABBCC,0x805080DD,hed
push dword edit1
call [edit_box_draw]
mcall 12,2
ret
;Data
edit1 edit_box 250,5,30,0xffffff,0x6f9480,0,0xAABBCC,0,308,hed,ed_focus,43,43
hed db 'EDITBOX load from lib <Lrz> date 20.09.2007',0
rb 256
Обновил файл
- Attachments
-
-
EDITBOX_LIB.7z (18.52 KiB)Downloaded 242 times
-
Last edited by <Lrz> on Fri Sep 21, 2007 5:59 pm, edited 1 time in total.
Не хочет извлекать архив ни раром, ни 7-зипом((((
Хотя если открыть в Блокноте видно что файл 7зипа.
Хотя если открыть в Блокноте видно что файл 7зипа.
Из хаоса в космос
исходник залит на ftp в папке Lrz
Who is online
Users browsing this forum: No registered users and 5 guests