1

Тема: AHK: edit

Добрый день. Мне нужно создать поле для ввода текста, но чтобы вводить туда можно было только шестнадцатеричные числа. Скажите пожалуйста как это сделать на AHK.

2

Re: AHK: edit

В каком формате, с префиксом "0xFF" или без него "FF"?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK: edit

teadrinker пишет:

В каком формате, с префиксом "0xFF" или без него "FF"?

Без, но это не принципиально.

4

Re: AHK: edit

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
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5

Re: AHK: edit

teadrinker, не стоит так делать, поскольку сообщение может идти напрямую контролу. Нужно сабклассить, тем более, что в справке кривой пример на эту тему . Кроме того стоит учесть WM_PASTE и WM_SETTEXT(возможно ещё какие-то есть), которые вообще не используют WM_CHAR.

6

Re: AHK: edit

М-м-м, не совсем понял, в коде как раз учитываются сообщения, идущие непосредственно в данный контрол. Что до 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 и остальное — это просто вряд ли пригодится в реальности. Но приведи и свой вариант, я убегаю сейчас.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK: edit

teadrinker пишет:

М-м-м, не совсем понял, в коде как раз учитываются сообщения, идущие непосредственно в данный контрол.

Нет, тут учитываются сообщения, которые проходят через DispatchMessage главного окна. Попробуй напрямую отправить символ:

SendMessage, 0x102, 0x77, , , ahk_id%hEdit%
teadrinker пишет:

А WM_SETTEXT и остальное — это просто вряд ли пригодится в реальности. Но приведи и свой вариант, я убегаю сейчас.

Чуть позже напишу, у меня острый приступ лени сейчас .

8

Re: AHK: edit

Сабклассинг- это изменение оконной процедуры окна на свою(обычно адрес старой оконной процедуры сохраняется и используется в новой). Пример есть в справке, но он кривой и не будет работать в 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

9

Re: AHK: edit

Александр_ пишет:

Нет, тут учитываются сообщения, которые проходят через 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? Она в любом варианте, вроде, работает?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

10 (изменено: Александр_, 2012-05-14 22:15:29)

Re: AHK: edit

teadrinker пишет:

В справке про это вот что написано:

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%

как всё мониторится.

Дык я это и сказал- сообщение можно отправлять контролу напрямую, минуя родительское окно. Понятно что можно и не напрямую отправлять, например передав фокус ввода и тыкнув по клавиатуре .

teadrinker пишет:

А разве нужно проверять битность интерпретатора для вызова SetWindowLongPtr? Она в любом варианте, вроде, работает?

Нет, в 32-битной версии этой функции вообще нет.

11

Re: AHK: edit

Александр_ пишет:

Нет, в 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
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

12

Re: AHK: edit

teadrinker пишет:

Таки есть.

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 */
teadrinker пишет:

Только что проверил в XP на 32-битном интерпретаторе.

Можно глянуть на user32.dll той системы?

teadrinker пишет:

но мой на практике вполне работоспособен

Не спорю, найти стуацию где бы он не сработал не так просто .

13

Re: AHK: edit

teadrinker пишет:

Только что проверил в XP на 32-битном интерпретаторе.

Ой, извиняюсь, плохо проверил, действительно не работает!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14

Re: AHK: edit

Может имеет смысл исправить тот пример в справке? Понятно, что это перевод, но всё-таки .

15

Re: AHK: edit

Не знаю, теоретически можно, но тогда уж по логике нужно будет всю переведённую справку исправлять, она ведь писана под AHK-basic. В новой тот пример исправлен.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AHK: edit

teadrinker пишет:

Не знаю, теоретически можно, но тогда уж по логике нужно будет всю переведённую справку исправлять, она ведь писана под AHK-basic. В новой тот пример исправлен.

А я и не в курсе, что для AHK_L есть отдельная справка . Этот пример ведь не использует никаких особенностей AHK_L и должен работать и на классической.

17

Re: AHK: edit

В AHK-basic нет типа "Ptr" и, соответственно, переменной A_PtrSize.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

18

Re: AHK: edit

teadrinker пишет:

В AHK-basic нет типа "Ptr" и, соответственно, переменной A_PtrSize.

Тогда там нет ошибок .