Тема: AHK: edit
Добрый день. Мне нужно создать поле для ввода текста, но чтобы вводить туда можно было только шестнадцатеричные числа. Скажите пожалуйста как это сделать на AHK.
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Добрый день. Мне нужно создать поле для ввода текста, но чтобы вводить туда можно было только шестнадцатеричные числа. Скажите пожалуйста как это сделать на AHK.
В каком формате, с префиксом "0xFF" или без него "FF"?
В каком формате, с префиксом "0xFF" или без него "FF"?
Без, но это не принципиально.
Gui, Add, Edit, hwndhEdit
Gui, Show
OnMessage(0x102, "WM_CHAR")
return
GuiClose:
ExitApp
WM_CHAR(wp, lp, msg, hwnd)
{
global hEdit
if (hwnd != hEdit)
return
if wp in 3,8,24,26 ; обработка Ctrl+C, Backspace, Ctrl+X, Ctrl+Z
return
Chr := Chr(wp)
if Chr not in 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f
Return 0
}teadrinker, не стоит так делать, поскольку сообщение может идти напрямую контролу. Нужно сабклассить, тем более, что в справке кривой пример на эту тему
. Кроме того стоит учесть WM_PASTE и WM_SETTEXT(возможно ещё какие-то есть), которые вообще не используют WM_CHAR.
М-м-м, не совсем понял, в коде как раз учитываются сообщения, идущие непосредственно в данный контрол. Что до WM_PASTE, то да, нужно добавить в обработку.
Gui, Add, Edit, hwndhEdit
Gui, Show
OnMessage(0x102, "WM_CHAR")
return
GuiClose:
ExitApp
WM_CHAR(wp, lp, msg, hwnd)
{
global hEdit
if (hwnd != hEdit)
return
if wp in 3,8,22,24,26 ; обработка Ctrl+C, Backspace, Ctrl+V, Ctrl+X, Ctrl+Z
return
Chr := Chr(wp)
if Chr not in 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,x
Return 0
}А WM_SETTEXT и остальное — это просто вряд ли пригодится в реальности. Но приведи и свой вариант, я убегаю сейчас. ![]()
М-м-м, не совсем понял, в коде как раз учитываются сообщения, идущие непосредственно в данный контрол.
Нет, тут учитываются сообщения, которые проходят через DispatchMessage главного окна. Попробуй напрямую отправить символ:
SendMessage, 0x102, 0x77, , , ahk_id%hEdit%А WM_SETTEXT и остальное — это просто вряд ли пригодится в реальности. Но приведи и свой вариант, я убегаю сейчас.
Чуть позже напишу, у меня острый приступ лени сейчас
.
Сабклассинг- это изменение оконной процедуры окна на свою(обычно адрес старой оконной процедуры сохраняется и используется в новой). Пример есть в справке, но он кривой и не будет работать в 64-битной системе.
WindowProcNew := RegisterCallback("WindowProc", "", 4)
Gui, Add, edit, HWNDhWnd w200
WindowProcOld := DllCall("SetWindowLong" . (A_PtrSize==8?"Ptr":""), "ptr", hWnd, "int", -4, "ptr", WindowProcNew, "ptr")
Gui, Show
return
WindowProc(hwnd, uMsg, wParam, lParam)
{
Critical
global WindowProcOld
if (uMsg==0x0102) ;WM_CHAR
{
if((wParam>=0x30&&wParam<=0x39)||(wParam>=97&&wParam<=102)||(wParam>=65&&wParam<=70)||(wParam==0x08)||(wParam==3)||(wParam==26)||(wParam==24)||(wParam==22)) ;0-9, a-f, A-F, VK_BACK, ctr-c, ctrl-x, ctrl-v, ctrl-z
return DllCall("CallWindowProcW", "ptr", WindowProcOld, "ptr", hwnd, "uint", uMsg, "ptr", wParam, "ptr", lParam, "ptr")
else
return 0
}
else if(uMsg==0x0302) ;WM_PASTE
{
if(RegExMatch(Clipboard, "i)^[\da-f]*$"))
DllCall("CallWindowProcW", "ptr", WindowProcOld, "ptr", hwnd, "uint", uMsg, "ptr", wParam, "ptr", lParam, "ptr")
return 0
}
else if(uMsg==0x000C) ;WM_SETTEXT
{
if(RegExMatch(StrGet(lParam), "i)^[\da-f]*$"))
DllCall("CallWindowProcW", "ptr", WindowProcOld, "ptr", hwnd, "uint", uMsg, "ptr", wParam, "ptr", lParam, "ptr")
return 0
}
return DllCall("CallWindowProcW", "ptr", WindowProcOld, "ptr", hwnd, "uint", uMsg, "ptr", wParam, "ptr", lParam, "ptr")
}
Esc::
GuiClose:
ExitAppНет, тут учитываются сообщения, которые проходят через DispatchMessage главного окна. Попробуй напрямую отправить символ:
SendMessage, 0x102, 0x77, , , ahk_id%hEdit%.
В справке про это вот что написано:
Messages sent to a control (rather than being posted) are not monitored because the system routes them directly to the control behind the scenes. This is seldom an issue for system-generated messages because most of them are posted.
И действительно, стоит лишь попробовать
PostMessage, 0x102, 0x77, , , ahk_id%hEdit%как всё мониторится.
А разве нужно проверять битность интерпретатора для вызова SetWindowLongPtr? Она в любом варианте, вроде, работает?
В справке про это вот что написано:
Messages sent to a control (rather than being posted) are not monitored because the system routes them directly to the control behind the scenes. This is seldom an issue for system-generated messages because most of them are posted.
И действительно, стоит лишь попробовать
PostMessage, 0x102, 0x77, , , ahk_id%hEdit%как всё мониторится.
Дык я это и сказал- сообщение можно отправлять контролу напрямую, минуя родительское окно. Понятно что можно и не напрямую отправлять, например передав фокус ввода и тыкнув по клавиатуре
.
А разве нужно проверять битность интерпретатора для вызова SetWindowLongPtr? Она в любом варианте, вроде, работает?
Нет, в 32-битной версии этой функции вообще нет.
Нет, в 32-битной версии этой функции вообще нет.
Таки есть.
Note To write code that is compatible with both 32-bit and 64-bit versions of Windows, use SetWindowLongPtr.
Только что проверил в XP на 32-битном интерпретаторе.
В общем, по БОЛЬШОМУ счёту твой вариант более универсален, но мой на практике вполне работоспособен, если правильно обработать Ctrl+V:
Gui, Add, Edit, hwndhEdit
Gui, Show
OnMessage(0x102, "WM_CHAR")
return
GuiClose:
ExitApp
WM_CHAR(wp, lp, msg, hwnd)
{
global hEdit
if (hwnd != hEdit)
return
if (wp = 22 && RegExMatch(Clipboard, "i)[^\da-f]"))
Return 0
if wp in 3,8,22,24,26 ; обработка Ctrl+C, Backspace, Ctrl+V, Ctrl+X, Ctrl+Z
return
Chr := Chr(wp)
if Chr not in 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,x
Return 0
}Таки есть.
Note To write code that is compatible with both 32-bit and 64-bit versions of Windows, use SetWindowLongPtr.
Имеется ввиду, что в Visual Studio SetWindowLongPtr ссылается на SetWindowLong. Вот этот отрывок из заголовочного файла VS C++(я там пометил сабж):
#ifdef _WIN64
WINUSERAPI
LONG_PTR
WINAPI
GetWindowLongPtrA(
__in HWND hWnd,
__in int nIndex);
WINUSERAPI
LONG_PTR
WINAPI
GetWindowLongPtrW(
__in HWND hWnd,
__in int nIndex);
#ifdef UNICODE
#define GetWindowLongPtr GetWindowLongPtrW
#else
#define GetWindowLongPtr GetWindowLongPtrA
#endif // !UNICODE
WINUSERAPI
LONG_PTR
WINAPI
SetWindowLongPtrA(
__in HWND hWnd,
__in int nIndex,
__in LONG_PTR dwNewLong);
WINUSERAPI
LONG_PTR
WINAPI
SetWindowLongPtrW(
__in HWND hWnd,
__in int nIndex,
__in LONG_PTR dwNewLong);
#ifdef UNICODE
#define SetWindowLongPtr SetWindowLongPtrW
#else
#define SetWindowLongPtr SetWindowLongPtrA
#endif // !UNICODE
#else /* _WIN64 */
#define GetWindowLongPtrA GetWindowLongA //Вот здесь экшн :)
#define GetWindowLongPtrW GetWindowLongW
#ifdef UNICODE
#define GetWindowLongPtr GetWindowLongPtrW
#else
#define GetWindowLongPtr GetWindowLongPtrA
#endif // !UNICODE
#define SetWindowLongPtrA SetWindowLongA
#define SetWindowLongPtrW SetWindowLongW
#ifdef UNICODE
#define SetWindowLongPtr SetWindowLongPtrW
#else
#define SetWindowLongPtr SetWindowLongPtrA
#endif // !UNICODE
#endif /* _WIN64 */Только что проверил в XP на 32-битном интерпретаторе.
Можно глянуть на user32.dll той системы?
но мой на практике вполне работоспособен
Не спорю, найти стуацию где бы он не сработал не так просто
.
Только что проверил в XP на 32-битном интерпретаторе.
Ой, извиняюсь, плохо проверил, действительно не работает! ![]()
Может имеет смысл исправить тот пример в справке? Понятно, что это перевод, но всё-таки
.
Не знаю, теоретически можно, но тогда уж по логике нужно будет всю переведённую справку исправлять, она ведь писана под AHK-basic. В новой тот пример исправлен.
Не знаю, теоретически можно, но тогда уж по логике нужно будет всю переведённую справку исправлять, она ведь писана под AHK-basic. В новой тот пример исправлен.
А я и не в курсе, что для AHK_L есть отдельная справка
. Этот пример ведь не использует никаких особенностей AHK_L и должен работать и на классической.
В AHK-basic нет типа "Ptr" и, соответственно, переменной A_PtrSize.
В AHK-basic нет типа "Ptr" и, соответственно, переменной A_PtrSize.
Тогда там нет ошибок
.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться