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. Урок 20. Сабклассинг окна.

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

 

 

Реклама:

Расписание Таруса - Москва

Складская логистика обучение оптовая торговля. Курсы складской логистики, обучение логистике.

В этом туториале мы изучим сабклассинг окна, что это такое, и как это использовать нам на пользу.

Теория:

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

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

Теперь мы изучим как это сделать. Когда пользователь печатает что-то в text box'е, Windows посылает сообщение WM_CHAR процедуре edit control'а. Эта процедура окна находится внутри Windows, поэтому мы не можем модифицировать ее. Но мы можем перенаправить поток сообщений к нашей оконной процедуре. Поэтому наша процедура окна первой получит возможность обработать сообщение, которое Windows пошлет edit control'у. Если наша процедура решит обработать сообщение, она так и сделает. Но если она не захочет его обрабатывать, она может передать его оригинальной оконной процедуре. Таким образом, наша функция будет стоять между Windows и edit control'ом. Посмотрите на условную схему внизу.

До сабклассинга

Windows ==> процедура edit control'а

После сабклассинга

Windows ==> наша оконная процедура -----> процедура edit control'а

Теперь мы можем рассмотреть то, каким образом происходит сабклассинг окна. Заметьте, что сабклассинг не ограничивается контролами, он может использоваться с любым окном. Давайте подумаем о том, как Windows узнает, где находится процедура edit box'а. Ну?.. Поле lрfnWndproc в структуре WNDCLASSEX. Если мы сможем поменять значение этого поля на адрес собственной структуры, Windows пошлет сообщение нашей процедуре окна вместо этого. Мы можем сделать это, вызвав SetWindowLong.

function SetWindowLong _
(byval hWnd as HWND, _
byval nIndex as integer, _
byval dwNewLong as LONG) as LONG

hWnd = хэндл окна, чьи свойства мы хотим поменять.

nIndex = значение, которое нужно изменить.

GWL_EXSTYLE Установка нового расширенного стиля окна.
GWL_STYLE Установка нового стиля окна.
GWL_WNDPROC Установка нового адреса для процедуры окна.
GWL_HINSTANCE Установка нового хэндла приложения.
GWL_ID Установка нового идентификатора окна.
GWL_USERDATA Установка 32-битного значения, ассоциирующегося с окном.
У каждого окна есть ассоциированное с ним 32-битное значение, предназначенное для использования приложением в своих целях.

dwNewLong = новое значение.

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

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

function CallWindowProc _
(byval lpprevWndFunc as WNDPROC, _
byval hWnd as HWND, _
byval Msg as UINT, _
byval wparam as WPARAM, _
byval lparam as LPARAM) as LRESULT

lprevWndFunc = адрес оригинальной процедуры окна. Остальные четыре значения - это те, что передаются нашей процедуре окна. Мы передаем их CallWindowProc.

Пример:

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

Анализ:

OldWndproc = SetWindowLong _
(hwndEdit, _
GWL_WNDPROC, _
cPtr(long,@EditWndproc)

После того, как edit control создан, мы сабклассим его, вызываяSetWindowLong и замещая адрес оригинальной процедуры окна нашим собственным адресом. Заметьте, что мы сохраняем значение адреса оригинальной процедуры, чтобы впоследствии использовать его при вызовеCallWindowproc.Заметьте, что EditWndрroc - это обычная оконная процедура.

case WM_CHAR
if (ch >= 48 and _
ch <= 57) or _
(ch >= 65 and _
ch <= 70) or _
(ch >= 97 and _
ch <= 102) or _
ch = VK_BACK then
if (ch >= 97 and _
ch <= 102) then
ch =ch - &h20
end if
*cast(ubyte ptr,@wparam)=ch
function = CallWindowproc _
(cPtr(WNDPROC,OldWndproc), _
hEdit, _
uMsg, _
wparam, _ ' символ
lparam)
exit function
end if

Внутри EditWndProc, мы фильтруем сообщения WM_CHAR. Если введен символв диапазоне 0-9 или a-f, мы передаем его оригинальной процедуре окна.Если это символ нижнего регистра, мы конвертируем его в верхний, отнимая 20h. Заметьте, что если символ не тот, который мы ожидали, мы пропускаем его. Мы не передаем его оригинальной процедуре окна. Поэтому, когда пользователь печатает что-нибудь отличное от 0-9 или a-f, символ непоявляется в edit control'е.

case WM_KEYDOWN
if lobyte(wparam) = VK_RETURN then
MessageBox(hEdit,Message,AppName,MB_OK+MB_ICONINFORMATION)
SetFocus(hEdit)
else
function = CallWindowproc _
(cPtr(WNDPROC,OldWndproc), _
hEdit, _
uMsg, _
wparam, _
lparam)
exit function
end if

Я хочу продемонстрировать силу сабклассинга через перехват клавишиEnter. EditWndProc проверяет сообщение WM_KEYDOWN, не равно ли оно VK_RETURN(клавиша Enter).
Если это так, она отображает окно с сообщением "Youpressed the Enter key in the text box!". Если это не клавиша Enter, она передает сообщение оригинальной процедуре.

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

[C] Iczelion, пер. Aquila.

 

 

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

Ваше имя:  

Ваш e-mail:  

Сообщение:



Введите код: 

 

 

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

 

 

© 2010-2012

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

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

ICQ:279786014 или R549103331586   Z116647355686