Что нового

ISubclass - обработка всех сообщений окна или контрола

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
AutoIt: 3
Версия: 1.0

Категория: Вспомогательные функции, Окна и диалоги, Элементы GUI

Описание: Позволяет обработать все сообщения окна или контрола в одной зарегистрированной функции.

Код/Пример:
Код:
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <WinAPIEx.au3>
#include 'ISubclass.au3'

If (Not ISubclassStartup()) Then
    Exit
EndIf

$tProc = DllCallbackRegister('Subclass', 'ptr', 'hwnd;ulong;wparam;lparam')
$hForm = GUICreate('', 400, 300, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS))
$iSubclass = ISubclassRegister($hForm, DllCallbackGetPtr($tProc))
$iButton1 = GUICtrlCreateButton('1', 0, 0, 0, 0)
$iButton2 = GUICtrlCreateButton('2', 0, 0, 0, 0)
$iButton3 = GUICtrlCreateButton('3', 0, 0, 0, 0)
$iButton4 = GUICtrlCreateButton('4', 0, 0, 0, 0)
$iButton5 = GUICtrlCreateButton('5', 0, 0, 0, 0)
$iButton6 = GUICtrlCreateButton('6', 0, 0, 0, 0)
$iButton7 = GUICtrlCreateButton('7', 0, 0, 0, 0)
$iButton8 = GUICtrlCreateButton('8', 0, 0, 0, 0)
$iButton9 = GUICtrlCreateButton('9', 0, 0, 0, 0)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case -3
			ExitLoop
	EndSwitch
Wend

ISubclassUnregister($iSubclass)
DllCallbackFree($tProc)
ISubclassShutdown()

Func Subclass($hWnd, $iMsg, $wParam, $lParam)
	Switch $hWnd
		Case $hForm
			Switch $iMsg
				Case $WM_COMMAND
					Switch _WinAPI_LoWord($wParam)
						Case $iButton1
							Switch _WinAPI_HiWord($wParam)
								Case $BN_CLICKED
									MsgBox(0, '', 'Button 1')
							EndSwitch
						Case $iButton2
							Switch _WinAPI_HiWord($wParam)
								Case $BN_CLICKED
									MsgBox(0, '', 'Button 2')
							EndSwitch
						Case $iButton3
							Switch _WinAPI_HiWord($wParam)
								Case $BN_CLICKED
									MsgBox(0, '', 'Button 3')
							EndSwitch
						Case $iButton4
							Switch _WinAPI_HiWord($wParam)
								Case $BN_CLICKED
									MsgBox(0, '', 'Button 4')
							EndSwitch
						Case $iButton5
							Switch _WinAPI_HiWord($wParam)
								Case $BN_CLICKED
									MsgBox(0, '', 'Button 5')
							EndSwitch
						Case $iButton6
							Switch _WinAPI_HiWord($wParam)
								Case $BN_CLICKED
									MsgBox(0, '', 'Button 6')
							EndSwitch
						Case $iButton7
							Switch _WinAPI_HiWord($wParam)
								Case $BN_CLICKED
									MsgBox(0, '', 'Button 7')
							EndSwitch
						Case $iButton8
							Switch _WinAPI_HiWord($wParam)
								Case $BN_CLICKED
									MsgBox(0, '', 'Button 8')
							EndSwitch
						Case $iButton9
							Switch _WinAPI_HiWord($wParam)
								Case $BN_CLICKED
									MsgBox(0, '', 'Button 9')
							EndSwitch
					EndSwitch
				Case $WM_ACTIVATE, $WM_SIZING, $WM_SIZE
					Local $iPos = _WinAPI_GetPosFromRect(_WinAPI_GetClientRect($hWnd))
					GUICtrlSetPos($iButton1, 0, 0, 80, 20)
					GUICtrlSetPos($iButton2, 0, 20, 80, $iPos[3] - 40)
					GUICtrlSetPos($iButton3, 0, $iPos[3] - 20, 80, 20)
                    GUICtrlSetPos($iButton4, 80, 0, $iPos[2] - 160, 20)
					GUICtrlSetPos($iButton5, 80, 20, $iPos[2] - 160, $iPos[3] - 40)
					GUICtrlSetPos($iButton6, 80, $iPos[3] - 20, $iPos[2] - 160, 20)
					GUICtrlSetPos($iButton7, $iPos[2] - 80, 0, 80, 20)
					GUICtrlSetPos($iButton8, $iPos[2] - 80, 20, 80, $iPos[3] - 40)
					GUICtrlSetPos($iButton9, $iPos[2] - 80, $iPos[3] - 20, 80, 20)
			EndSwitch
	EndSwitch
EndFunc

Файл: ISubclass.rar

Снимок:

История версий:
1.0

Список функций:
ISubclassStartup - Открывает Dll
ISubclassRegister - Регистрирует функцию для обработки сообщений окна
ISubclassRegisterEx - Регистрирует функцию для обработки сообщений контрола
ISubclassUnregister - Закрывает зарегистрированную функцию
ISubclassShutdown - Закрывает Dll

Источник: autoit-script.ru
Автор(ы): Viktor1703
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Почему бы не упростить это дело, чтобы нужно было делать только регистрацию, а уже обрабатывать в самой UDF?

Типа этого:

Код:
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>

#include 'ISubclass.au3'

$hForm = GUICreate('', 400, 300, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX, $WS_CLIPCHILDREN, $WS_CLIPSIBLINGS))

$iButton1 = GUICtrlCreateButton('1', 0, 0, 0, 0)

ISubclassRegister($hForm, 'MySubclassFunc')
GUISetState()

While 1
    Switch GUIGetMsg()
        Case -3
            ExitLoop
    EndSwitch
Wend

Func MySubclassFunc($iID, $iEvent)
    Switch $iEvent
        Case $BN_CLICKED
            Switch $iID
                Case $iButton1
                    MsgBox(0, '', 'Button 1')
            EndSwitch
    EndSwitch
EndFunc


инициализацию делать при первом запуске ISubclassRegister, а выгрузку по завершению скрипта (OnAutoItExitRegister).
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Viktor1703
ISubclass.dll сам делал? :smile:
смотрю что в ней всего лишь три функции
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
а зачем в библиотеку спрятал? я бы воспользовался твоей полезняшкой, но таскать с собой библиотеку из трех функция как то неудобно . твое дело, конечно. ты автор ты и ставишь условия :smile:
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
joiner [?]
а зачем в библиотеку спрятал?
я полагаю, потому что библиотека написана на другом языке, переписывание которой на AutoIt либо невозможно, либо неоправдано, либо неэффективно.
таскать с собой библиотеку из трех функция как то неудобно
чем в плане неудобности отличается таскание с собой библиотеки из трех функций от таскания библиотеки с 100500 функциями? :smile:
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
ну сразу так зачем? я ж спросил ради интереса.

Kaster [?]
я полагаю, потому что библиотека написана на другом языке,
Kaster, этого ответа мне достаточно. я подозревал подобное :smile:. но лучше ж просто спросить. а?
Kaster [?]
либо неоправдано, либо неэффективно.
почему то мне кажется ,что в данном случае это одно и то же :smile:
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
joiner
я без понятия, чем руководствовался Viktor1703, я просто предположил, потому что помню что он любитель побаловаться созданием библиотек на PureBasic :smile:
joiner [?]
почему то мне кажется ,что в данном случае это одно и то же
ну, не совсем. неоправдано в плане трудозатрат на создание, а на выходе получить тот же функционал, которые можно получить другими менее затратными способами. а неэффективным может быть например, если полученная библиотека будет уступать в разы по скорости работы своему аналогу на PureBasic
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Хорошая работа, но немного критики. По сути, эта библиотека заменяет лишь несколько вызовов GUIRegisterMsg(). Все остальное можно и так реализовать в одной функции. А минус здесь в том, что из быстрого машинного кода ты вызываешь медленный код AutoIt. А так как сообщений окну приходит море, и все они перенаправляютсяются в AutoIt, то рано или поздно это приведет к ошибкам и тормозам. Думаю это неизбежно случится, например, с ListView или TreeView. Чем хороша GUIRegisterMsg()? Тем, что мы вмешиваемся только туда, куда необходимо. Логичнее было бы сделать триггер на собщения, но в этом случае смысл в библиотеке пропадает. И еще, в примере ты возвращаешь $GUI_RUNDEFMSG, но это строковое значение...

PS

Хорошо бы добавить еще 64-битную dll.
 
Автор
V

Viktor1703

AutoIT Гуру
Сообщения
1,535
Репутация
413
$GUI_RUNDEFMSG я забыл убрать, просто был пример WM_NOTIFY и я его переделал под Subclass

то рано или поздно это приведет к ошибкам и тормозам

Были такие мысли, я её сделал для себя... мне удобно было обрабатывать все сообщения в одной функции а не раскидывать их, так как я мало чего знаю про Callback'и, прошу совета, как лучше сделать... стоит ли её тогда вообще использовать?

Хорошо бы добавить еще 64-битную dll.

Если в этом будет смысл, то конечно нужно будет написать :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Viktor1703 сказал(а):
мне удобно было обрабатывать все сообщения в одной функции а не раскидывать их...

А что мешает зарегистрировать с помощью GUIRegisterMsg() все необходимые сообщения на одну функцию?

Viktor1703 сказал(а):
стоит ли её тогда вообще использовать?

Я не советую. В данном виде это ничем не отличается от примера к функции _WinAPI_SetWindowSubclass(), где к тому же не используется dll. Вот пример, где действительно возникла необходимость писать dll. Но там обработка соответствующего сообщения происходит в самой dll.
 
Верх