FreeBASIC в России

   

 Главная   Исходники   Русскоязычный форум   Полезные файлы   Пользователи   Поиск

 

 FB Wiki   Уроки   Скачать FreeBASIC   Проекты   Ссылки   Загрузить   Каталог ссылок

 
 

 Замечания и предложения по работе сайта оставляйте здесь.

Сейчас на сайте:

Вы вошли как: Guest   Регистрация   

Логин:     Пароль:     

Создай бесплатно WebMoney кошелёк на своём мобильном всего за 5 минут

 

Делаем dll своими руками

Хэндл окна

Графические средства языка

Точка пересечения отрезков

Окна без рамки

Физика поведения ядра

Win32 API Введение

►Урок 1 Win32 API

►Урок 2 Win32 API

►Урок 3 Win32 API

►Урок 4 Win32 API

►Урок 5 Win32 API

►Урок 6 Win32 API

►Урок 7 Win32 API

►Урок 8 Win32 API

►Урок 9 Win32 API

►Урок 10 Win32 API

►Урок 11 Win32 API

►Урок 12 Win32 API

►Урок 13 Win32 API

►Урок 14 Win32 API

►Урок 15 Win32 API

►Урок 16 Win32 API

►Урок 17 Win32 API

►Урок 18 Win32 API

►Урок 19 Win32 API

►Урок 20 Win32 API

►Урок 21 Win32 API

►Урок 22 Win32 API

►Урок 23 Win32 API

►Урок 24 Win32 API

Ассоциация файлов

Определить OS

Выводит имя компьютера

 

 

 

Win32 API. Урок 22.  Суперклассинг.

Опытом поделился и оптимизировал под FreeBASIC:   15.01.2011

 

 

Реклама:

Пушкина, 17 - Уссурийск;Полезные команды Linux в одном месте. Справочник по командам Linux.

В этом туториале мы изучим суперклассинг, что это такое и для чего он служит. Вы также узнаете, как реализовать навигацию с помощью клавиши 'Tab' в вашем окне.

Теория:

Во время вашей программной карьеры, вы наверняка встретитесь с ситуацией, когда вам потребуется несколько контролов с *несколько* отличным поведением. Например, вам могут потребоваться 10 edit control'ов, которые принимают только число. Есть несколько путей достигнуть цели:

• Создать собственный класс и написать контролы с нуля
• Создать эти edit control'ы и сабклассировать каждый из них
• Суперклассировать edit control

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

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

Ниже приведены шаги для суперклассинга:

• вызвать функцию GetClassInfoEx, чтобы получить информацию о классе окна, который вы хотите суперклассировать. GetClassInfoEx требует указатель на структуру WNDCLASSEX, которая будет заполнена информацией, если вызов пройдет успешно.
• Изменить требуемые параметры WNDCLASSEX. Тем не менее, есть два члена, которые вы должны обязательно изменить:

• hInstance - Вы должны поместить в это поле хэндл программы.
• lpszClassName - вы должны поместить сюда указатель на новое имя класса.
• Вы не обязаны изменять параметр lpfnWndProc, но обычно вам будет это нужно делать. Главное не забудьте сохранить старое значение lpfnWndproc, если вам надо будет его вызывать с помощью CallWindowproc.

• Зарегистрировать измененную структуру WNDCLASSEX. У вас будет новый класс окна, который будет обладать некоторыми характеристиками старого класса.
• Создать окна с помощью нового класса.

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

Пример:

Скопировать данный код в буфер обмена

Анализ:

Программа создаст простое окно с "измененными" edit control'ами в своей клиентской области. Edit control'ы будут принимать только шестнадцатиричные числа.
Фактически, я адаптировал пример с сабклассингом. программа стартует как обычно, а самое интересное происходит, когда создается основное окно:

case WM_CREATE
wc.cbSize = sizeof(WNDCLASSEX)
GetClassInfoEx _
(NULL, _
EditClass, _
@wc)

Сначала мы заполним данными класса, который мы хотим суперклассировать, в нашем случае это класс edit'а. Помните, что вы должны установить параметр структуры WNDCLASSEX, перед тем, как вызвать GetClassInfoEx, в противном случае она будет заполнена неверно. После вызова GetClassInfoEx у нас будет иметься вся
необходимая для создания нового класса информация.

OldWndproc = cPtr(LONG ,wc.lpfnWndproc)
wc.lpfnWndproc = @EditWndproc
wc.hInstance = hModule
wc.lpszClassName = @OurClass

Теперь мы можем изменить некоторые члены wc. Первый из них - это указатель на процедуру окна. Так как нам нужно будет соединить вызовы новой и старой процедуры в цепь, нам необходимо сохранить старое значение в переменную, чтобы потом воспользоваться функцией CallWindowproc. Эта техника идентична с сабклассингом, не считая того, что вы напрямую изменяете структуру WNDCLASSEX не вызывая SetWindowLong. Следующие два поля должны быть изменены, иначе вам не удастся
зарегистрировать ваш новый класс окна, hInstance и lpszClassName. Вы должны заменить старое значение hInstance на хэндл вашей програмы, а также выбрать имя для нового класса.

RegisterClassEx _
(@wc)

Когда все готово, регистрируйте новый класс. Вы получите новый класс, обладающий некоторыми характеристиками старого.

y = 20
for countWin = 0 to 5
hwndEdit(countWin) = CreateWindowEx _
(WS_EX_CLIENTEDGE, _
OurClass, _
0, _
WS_CHILD+WS_VISIBLE+WS_BORDER, _
20, _
y, _
300, _
25, _
hWnd, _
cptr(HMENU,countWin), _
hModule, _
NULL)
y = y + 25
next
SetFocus(hwndEdit(0))

Теперь, когда мы зарегистрировали класс, мы можем создать основанные на нем окна. в вышеприведенном куске кода, я использовал countWin в качестве счетчика созданных
окон. y, используется как y-координата левого верхнего угла окна. Когда окно создано, его хэндл сохраняется в массиве хэндлов. Когда все окна созданы, устанавливаем фокус на первое окно. К этому моменту у вас есть 6 edit control'ов, которые принимают только шестнадцатиричные числа. Новая процедура окна,
заменившая старую, выполняет роль фильтра. Фактически, это работает точно также, как и в примере с сабклассингом, только вам не нужно выполнять лишнюю работу.

Я вставил кусок кода, который обрабатывает нажатия на Tab, чтобы сделать пример более полезным для вас. Обычно, если вы помещаете контролы на диалоговое окно, его внутренний менеджер сам обрабатывает нажатия на клавиши навигации. Увы, но это недоступно, когда вы помещаете контролы на обычное окно. Вам следует сабклассировать их, чтобы нажатия на Tab обрабатывались. В нашем примере нам нет нужды сабклассировать контролы по одному, так как мы уже суперклассировали, поэтому можем реализовать "центральный менеджер навигации контролов".

case VK_TAB
if GetKeyState(VK_SHIFT) and &h80000000 then
focus = GetWindow _
(hEdit, _
GW_HWNDPREV)
if focus = NULL then
focus = GetWindow _
(hEdit, _
GW_HWNDLAST)
end if
else
focus = GetWindow _
(hEdit, _
GW_HWNDNEXT)
if focus = NULL then
focus = GetWindow _
(hEdit, _
GW_HWNDFIRST)
end if
end if
SetFocus(focus)
exit function

Вышеприведенный код взят из процедуры EditWndClass. Он проверяет, нажал ли пользователь клавишу tab, если да, он вызывает GetKeyState, чтобы узнать, нажата ли также клавиша Shift. GetKeyState возвращает значение , которое определяет, нажата ли указанная клавиша или нет. Если клавиша нажата, верхний бит будет установлен. Если нет, он будет очищен. Поэтому мы проверяем полученное значение &H80000000. Если верхний бит установлен, это будет означать, что пользователь нажал shift и tab одновременно, и должны обработать это отдельно.

Если пользователь нажал клавишу Tab, мы вызываем GetWindow, чтобы получить хэндл следующего контрола. Мы используем флаг GW_HWNDNEXT, чтобы указать GetWindow получить хэндл следующего окна относительно текущего hEdit. Если эта функция возвращает NULL, то такого окна нет и мы устанавливаем фокус на первое окно,
вызвав GetWindow с флагом GW_HWNDFIRST. Shift-Tab работает так же, как и обычно нажатие на Tab, только передвигает фокус окна назад.

[C] Iczelion, пер. Aquila.

 

 

Прокомментировать

Ваше имя:  

Ваш e-mail:  

Сообщение:



Введите код: 

 

 

19.01.2011 22:31
DEPOzit
Так в чем проблема? Пришли свой визуальный пример. Мы же не против.
 
19.01.2011 15:03
Pavel
Всё хорошо, но побольше бы визуальных примеров. Скучно как-то одни коды та слова...
 

   Спасибо можно сказать, посетив любую ссылку:

 

 

© 2010-2012

DEPOzit (Попов Денис Владимирович)

WebMoney кошелёк: WMID#302963000004

ICQ:279786014 или R549103331586   Z116647355686