1 (изменено: Malcev, 2012-01-31 22:58:19)

Тема: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Имеется программа удалённого доступа.
Всем хороша, скажем так единственна в своём роде, кроме одного.
Чтобы писать на удалённом компьютере на русском, на  локальном компьютере тоже должна стоять активная русская расскладка.
Тоже самое для английского.
То есть, если на локальном стоит En, а на удалённом Ru, то символы передаваться не будут.
Есть идея сделать скрипт, который отлавливал бы нажатие CTRL+SHIFT (смена языка) на удалённом компьютере и менял бы активную расскладку на локальном.
Возможно ли такое?
Так не получается.

#UseHook  ; Force the use of the hook for hotkeys after this point. 
#x::MsgBox, This hotkey will be implemented with the hook.

Какие ещё есть перехватчики?
http://forum.script-coding.com/viewtopic.php?id=5697
Этот тоже не работает.

2

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

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

3 (изменено: Malcev, 2012-02-01 00:58:15)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Вроде фурычит,
Но проблема в том, что когда нажимешь CTRL+SHIFT язык меняется только для активного окна.
Как этого избежать?

setTimer, timer, 500
#persistent
#usehook
return

1_key:
send, {CtrlDown}{ShiftDown}{CtrlUp}{ShiftUp}
PostMessage, 0x50, 0x02,0,, A
return

2_key:
send, {CtrlDown}{ShiftDown}{CtrlUp}{ShiftUp}
PostMessage, 0x50, 0x02,0,, A
return

timer:
ifwinactive 91.188.43.178 ahk_class QWidget
{
   hotkey LCtrl & LShift, 1_key, on
   hotkey LShift & LCtrl, 2_key, on
}
else
{
  hotkey LCtrl & LShift, 1_key, off
  hotkey LShift & LCtrl, 2_key, off
}
Return

4

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

Вроде фурычит,
Но проблема в том, что когда нажимешь CTRL+SHIFT язык меняется только для активного окна.
Как этого избежать?

Раскладка индивидуальна для каждого потока(не окна) в системе, поэтому я не понимаю чего вы добиваетесь.

5 (изменено: Malcev, 2012-02-01 02:19:20)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Вот скрипт переделал его, чтобы язык менялся на отжатие CTRL+SHIFT

setTimer, timer, 500
#persistent
#usehook
return

1_key:
send, {CtrlDown}{ShiftDown}{CtrlUp}{ShiftUp}
PostMessage, 0x50, 0x02,0,, A
return

2_key:
send, {CtrlDown}{ShiftDown}{CtrlUp}{ShiftUp}
PostMessage, 0x50, 0x02,0,, A
return

timer:
ifwinactive 91.188.43.178 ahk_class QWidget
{
   hotkey LCtrl & LShift up, 1_key, on
   hotkey LShift & LCtrl up, 2_key, on
}
else
{
  hotkey LCtrl & LShift up, 1_key, off
  hotkey LShift & LCtrl up, 2_key, off
}
Return

2 недостатка.
1) Блокируется шорткат CTRL+SHIFT+d - вместо него меняется язык
2) Если я в блокноте на удалённом компе поменяю язык, то у меня он соответственно поменяется и на локальном.
Но если я потом выйду из блокнота, т о язык на удалённом поменяется сам, а на локальном нет.
И что же с этим делать?

6

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

2 недостатка.
1) Блокируется шорткат CTRL+SHIFT+d - вместо него меняется язык
2) Если я в блокноте на удалённом компе поменяю язык, то у меня он соответственно поменяется и на локальном.
Но если я потом выйду из блокнота, т о язык на удалённом поменяется сам, а на локальном нет.
И что же с этим делать?

1) Групповой символ подойдёт?
2) Либо запускать второй скрипт на удалённом компьютере, либо пытаться отслеживать раскладку по картинке в окне.

7

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

1) Групповой символ подойдёт наверное, но я его никак не могу прилепить к

hotkey LCtrl & LShift up

В хелпе такой конструкции не нашёл, а так не проходит

*^+

2) По картинке не получится, так как экран на удалённом компе намного больше и поэтому она всё время в разных местах.
А какой вы имеете ввиду скрипт запускать на удалённом компе?
Типа такого?

F11:: MsgBox, % InputLayout()
 
InputLayout()
{
    ThreadID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
    HKL := DllCall("GetKeyboardLayout", "uint", ThreadID, "UShort")
    VarSetCapacity(sKbd, 260, 0)
    DllCall("GetLocaleInfo", "uint", HKL
                           , "uint", 0x1001
                           , "str",  sKbd
                           , "uint", 260)
    Return sKbd
}

Но как передать информацию на локальный компьютер?
Ведь локальный компьютер всего лишь клиент.
Или вы имеете ввиду задать координаты для окна сообщений и с этого окна прочитывать информацию?

8

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

Имеется программа удалённого доступа.

Всегда приводите конкретику. Что за программа?

9

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

HP Remote Graphics Software
http://h20331.www2.hp.com/hpsub/cache/2 … 5-121.html
Программа, специально созданная для ускоренной работы с 2-д и 3-д графикой удаленно

10

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

1) Групповой символ подойдёт наверное, но я его никак не могу прилепить к ...
В хелпе такой конструкции не нашёл, а так не проходит ...

Тогда можно разбить на два хоткея, пример:

LCtrl & LShift:: LCtrlLShift := 1
LCtrl & LShift up::
   LCtrlLShift := 0
   if(!LCtrlLShiftd)
      msgbox LCtrl & LShift up
   LCtrlLShiftd := 0
return
*d::
   if(LCtrlLShift)
   {
      LCtrlLShiftd := 1
      msgbox LCtrl & LShift & d
   }
return
Malcev пишет:

Но как передать информацию на локальный компьютер?

Через сеть . Через WSAAsyncSelect сокетами можно управлять через оконные сообщения.

11 (изменено: Malcev, 2012-02-01 10:39:58)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

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

SplashImage

А на локальном отслеживать цвет

12 (изменено: Malcev, 2012-02-01 12:26:21)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Вроде получилось!
Скрипт для удалённого компа


loop
{
If (InputLayout() = "Russian")
{
   Splashimage 3:,% "CW0EFFEF B W1 H1 Y" 525 "X" 840
sleep 100
}
If (InputLayout() = "Latvian")
{
   Splashimage 3:,% "CW00FFEF B W1 H1 Y" 525 "X" 840
sleep 100
}
If (InputLayout() = "English")
{
   Splashimage 3:,% "CW00FFFE B W1 H1 Y" 525 "X" 840
sleep 100
}
}
InputLayout()
{
    ThreadID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
    HKL := DllCall("GetKeyboardLayout", "uint", ThreadID, "UShort")
    VarSetCapacity(sKbd, 260, 0)
    DllCall("GetLocaleInfo", "uint", HKL
                           , "uint", 0x1001
                           , "str",  sKbd
                           , "uint", 260)
    Return sKbd
}

Скрипт для локального компьютера


loop
{
PixelSearch, Px, Py, 0, 0, 1680, 1050, 0xEFFF0E, 0, Fast
 If ErrorLevel = 0
    {
  SendMessage, 0x50,, 0x4190419,, A ; русский
    }
PixelSearch, Px, Py, 0, 0, 1680, 1050, 0xEFFF00, 0, Fast
 If ErrorLevel = 0
    {
   SendMessage, 0x50,, 0xF0150426,, A ; латышский
    }
PixelSearch, Px, Py, 0, 0, 1680, 1050, 0xFEFF00, 0, Fast
 If ErrorLevel = 0
    {
   SendMessage, 0x50,, 0x4090409,, A ; английский
    }
}

Вопрос, что вот здесь прописать,

Splashimage 3:,% "CW0EFFEF B W1 H1 Y" 525 "X" 840

чтобы картинка появлялась в левом верхнем углу видимого экрана, при условии, что на удалённом компьютере экран больше?
Решил переделать скрипт и сразу он перестал работать.
Почему?


loop
{
If (InputLayout() = "Russian") & (InputLayout() != InputLayout_old())
{
   Splashimage 3:,% "CW0EFFEF B W1 H1 Y" 525 "X" 840
sleep 100
}
If (InputLayout() = "Latvian") & (InputLayout() != InputLayout_old())
{
   Splashimage 3:,% "CW00FFEF B W1 H1 Y" 525 "X" 840
sleep 100
}
If (InputLayout() = "English") & (InputLayout() != InputLayout_old())
{
   Splashimage 3:,% "CW00FFFE B W1 H1 Y" 525 "X" 840
sleep 100
}
InputLayout() := InputLayout_old()
}
InputLayout()
{
    ThreadID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
    HKL := DllCall("GetKeyboardLayout", "uint", ThreadID, "UShort")
    VarSetCapacity(sKbd, 260, 0)
    DllCall("GetLocaleInfo", "uint", HKL
                           , "uint", 0x1001
                           , "str",  sKbd
                           , "uint", 260)
    Return sKbd
}

.

13

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

InputLayout() := InputLayout_old()

Интересная конструкция. Что в данном случае происходит?

14

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Ну я хочу присвоить значение переменной InputLayout()  значению переменной InputLayout_old().
Чтобы потом его сравнить с новым значением. Так как если язык не изменяется, то зачем этой точке мигать?

15

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

Ну я хочу присвоить значение переменной InputLayout()  значению переменной InputLayout_old().
Чтобы потом его сравнить с новым значением. Так как если язык не изменяется, то зачем этой точке мигать?

Т.е. InputLayout_old и InputLayout это таки переменные, тогда () не нужны.
А каково значение переменной InputLayout_old в момент присваивания?

16

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Очевидно нулю.
То есть надо так?

InputLayout_old = 0
InputLayout := InputLayout_old

17 (изменено: creature.ws, 2012-02-01 13:20:14)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

К сожалению, не смогу в объёме ответить на этот вопрос
Если цель — присвоить InputLayout и InputLayout_old "0", то сделать это можно и в одну строку.

18

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev
InputLayout() — это вызов функции, ему нельзя ничего присвоить. Можно присвоить его результат какой-нибудь переменной.

InputLayout_old := InputLayout()

Можно сравнить его результат с какой-нибудь переменной.

If (InputLayout() = InputLayout_old)

19 (изменено: Malcev, 2012-02-01 14:01:12)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

И всё-равно постоянно точка горит

loop
{
If (InputLayout() = "Russian") & (InputLayout() != InputLayout_old)
{
   Splashimage 3:,% "CW0EFFEF B W1 H1 Y" 525 "X" 840
   sleep 100
   Splashimage, off
   InputLayout_old := InputLayout()
}
If (InputLayout() = "Latvian") & (InputLayout() != InputLayout_old)
{
   Splashimage 3:,% "CW00FFEF B W1 H1 Y" 525 "X" 840
   sleep 100
   Splashimage, off
   InputLayout_old := InputLayout()
}
If (InputLayout() = "English") & (InputLayout() != InputLayout_old)
{
   Splashimage 3:,% "CW00FFFE B W1 H1 Y" 525 "X" 840
   sleep 100
   Splashimage, off
   InputLayout_old := InputLayout()
}
}

InputLayout()
{
    ThreadID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
    HKL := DllCall("GetKeyboardLayout", "uint", ThreadID, "UShort")
    VarSetCapacity(sKbd, 260, 0)
    DllCall("GetLocaleInfo", "uint", HKL
                           , "uint", 0x1001
                           , "str",  sKbd
                           , "uint", 260)
    Return sKbd
}

20

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

А что она должна делать? Опишите свою задумку детально.

21 (изменено: Malcev, 2012-02-01 14:26:50)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Ну я бы хотел бы что бы она на одну десятую сукунды загоралась и пропадала.
То есть появлялась только во время смены языков.
Для этого я и вписал    Splashimage, off.
И самое главное, что прописать в координаты чтобы картинка появлялась в левом верхнем углу видимого экрана, при условии, что на удалённом компьютере экран больше?
Тогда пускай себе горит не мигая.

22

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Верхний левый угол — начало координат, т.е. 0,0.
Вот так мигает.

loop
{
    If (InputLayout() = "Russian" and InputLayout() != InputLayout_old)
    {
        Splashimage, 1:, CW0EFFEF B W10 H10 Y10 X10
        sleep 100
        Splashimage, off
        InputLayout_old := InputLayout()
    }
    Else If (InputLayout() = "Latvian" and InputLayout() != InputLayout_old)
    {
        Splashimage, 1:, CW00FFEF B W10 H10 Y10 X10
        sleep 100
        Splashimage, off
        InputLayout_old := InputLayout()
    }
    Else If (InputLayout() = "English" and InputLayout() != InputLayout_old)
    {
        Splashimage, 1:, CW00FFFE B W10 H10 Y10 X10
        sleep 100
        Splashimage, off
        InputLayout_old := InputLayout()
    }
}
 

InputLayout()
{
    ThreadID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
    HKL := DllCall("GetKeyboardLayout", "uint", ThreadID, "UShort")
    VarSetCapacity(sKbd, 260, 0)
    DllCall("GetLocaleInfo", "uint", HKL
                           , "uint", 0x1001
                           , "str",  sKbd
                           , "uint", 260)
    Return sKbd
}

23

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

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

24

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Я глубоко не вникал в описание, но тройка — это вроде номер сплэшимиджа. У Вас же он один.
Что значит "передать разрешение"? Поместите точку там, где её будет видно.

25

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Кстати, этот Ваш цикл заметно процессор грузит.

26

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Поместите точку там, где её будет видно.

Там экран в 2 с половиной раза больше, поэтому когда его прокручиваешь, точку не всегда увидеть
Наверное придётся 2 точки посылать.

Кстати, этот Ваш цикл заметно процессор грузит.

А есть варианты получше?

27 (изменено: Irbis, 2012-02-01 16:04:53)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

...А есть варианты получше?

У программы Punto Switcher есть опция в настройках - показывать плавающий индикатор.
При этом появляется мальнький флажок страны, точь-в-точь как в трее. При этом Window Spy отлично определяет как его AHK_class (Afx:013C0000:8), так и координаты на экране.
Так что PixelGetColor вам в руки, надеюсь это поможет.

Upd: Если же не хочется доверять переключение раскладки PS по каким-либо соображениям, всегда можно выключить эту опцию, индикатор от этого не пострадает.

28

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Спасибо, но так как на удалённом компе экран в разы больше, то посередине этот флажок сильно раздражает глаз - как мишень.

29

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev
Чтобы не грузило, вставьте ещё один Sleep, 100 в конец цикла (вне всех If).

30

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Супер, заработало!!!!

31

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

Вообщем, не хочу чтобы с удалённого компа могли зайти на локальный

Обратное реализовать сложнее .

Malcev пишет:

плюс там такие дебри, что не один год программить надо. Я там вообще ничего не понимаю

Ничего там страшного, всего пара функций, вызываемых по простому шаблону.
WSAStartup - инициалтзация
socket - создание сокета
WSAAsyncSelect - привязка к окну
bind - привязка к порту
listen - приём соединений
connect - установка соединений
send/recv - отправка/приём данных
closesocket и WSACleanup - предназначения очевидны.
WSAGetLastError - получение кодов ошибок, аналог GetLastError(она же встроенная переменная A_LastError).
пример позже приведу, сейчас времени нет.

32

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Обещанный пример, сервер:

;объявление констант
AF_INET := 2
SOCK_STREAM := 1
IPPROTO_TCP := 6
WSA_FLAG_OVERLAPPED := 1
WM_USER := 0x400
WM_SOCKET := WM_USER + 1
FD_READ := 0x01 
FD_WRITE := 0x02
FD_OOB := 0x04
FD_ACCEPT := 0x08
FD_CONNECT := 0x10
FD_CLOSE := 0x20
;объявление переменных
VarSetCapacity(WSAData, 108, 0) ;для x86 хватит и 100
Socket := -1
AcceptSocket := -1
VarSetCapacity(SockAddr, 16, 0)
VarSetCapacity(buf, 1024, 0)
;код
Gui, Add, ListView, w480 h240, сокет|сообщение
Gui, Show
Gui, +LastFound
hWnd := WinExist()
OnMessage(WM_SOCKET, "DlgProc", 5)
DllCall("LoadLibrary", "str", "Ws2_32.dll")
if(DllCall("Ws2_32.dll\WSAStartup", "ushort", 0x0202, "ptr", &WSAData))
{
   msgbox WSAStartup
   goto Clear
}
Socket := DllCall("Ws2_32.dll\socket", "int", AF_INET, "int", SOCK_STREAM, "int", IPPROTO_TCP, "ptr")
if(Socket=-1)
{
   msgbox Socket
   goto Clear
}
NumPut(AF_INET, &SockAddr, 0, "short")
NumPut(htons(5676), &SockAddr, 2, "ushort")
NumPut(inet_addr("127.0.0.1"), &SockAddr, 4, "uint")
if(DllCall("Ws2_32.dll\WSAAsyncSelect", "ptr", Socket, "ptr", hWnd, "uint", WM_SOCKET, "int", FD_ACCEPT|FD_CLOSE, "int")=-1)
{
   msgbox % "WSAAsyncSelect " . DllCall("Ws2_32.dll\WSAGetLastError")
   goto Clear
}
if(DllCall("Ws2_32.dll\bind", "ptr", Socket, "ptr", &SockAddr, "int", 16, "int")=-1)
{
   msgbox % "bind " . DllCall("Ws2_32.dll\WSAGetLastError")
   goto Clear
}
if(DllCall("Ws2_32.dll\listen", "ptr", Socket, "int", 5, "int")=-1)
{
   msgbox % "listen " . DllCall("Ws2_32.dll\WSAGetLastError")
   goto Clear
}
return
Clear:
if(Socket)
   DllCall("Ws2_32.dll\closesocket", "ptr", Socket)
DllCall("Ws2_32.dll\WSACleanup")
return

DlgProc(wParam, lParam, msg, hwnd)
{
   global
   local fd, ClientSocket, r
   if(msg=WM_SOCKET)
   {
      fd := lParam&0xFFFF
	  if(fd=FD_ACCEPT)
	  {
	     LV_Add("", wParam, "FD_ACCEPT")
	     ClientSocket := DllCall("Ws2_32.dll\accept", "ptr", wParam, "ptr", 0, "int", 0, "ptr")
		 DllCall("Ws2_32.dll\WSAAsyncSelect", "ptr", ClientSocket, "ptr", hWnd, "uint", WM_SOCKET, "int", FD_READ|FD_WRITE|FD_CLOSE, "int")
	  }
	  else if(fd=FD_READ)
	  {
	     LV_Add("", wParam, "FD_READ")
	     x:=DllCall("Ws2_32.dll\recv", "ptr", wParam, "ptr", &buf, "int", 1024, "int", 0)
		 LV_Add("", wParam, StrGet(&buf, x, "utf-16"))
	  }
	  else if(fd=FD_WRITE)
	  {
	     LV_Add("", wParam, "FD_WRITE")
	  }
	  else if(fd=FD_CLOSE)
	  {
	     LV_Add("", wParam, "FD_CLOSE")
	     DllCall("Ws2_32.dll\closesocket", "ptr", wParam)
	  }
	  else
	  {
	     LV_Add("", wParam, "???")
	  }
   }
}

inet_addr(StringWithIP)
{
   ret := RegExMatch(StringWithIP, "^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$", ArrayWithIP)
   if((ret="")||(ret=0))
      return ""
   if((ArrayWithIP1>127)||(ArrayWithIP2>127)||(ArrayWithIP3>127)||(ArrayWithIP4>127))
      return ""
   VarSetCapacity(ip, 4, 0)
   NumPut(ArrayWithIP1, &ip, 0, "uchar")
   NumPut(ArrayWithIP2, &ip, 1, "uchar")
   NumPut(ArrayWithIP3, &ip, 2, "uchar")
   NumPut(ArrayWithIP4, &ip, 3, "uchar")
   return NumGet(&ip, 0, "uint")
}

htons(port)
{
   if((port<0)||(port>0xFFFF))
      return ""
   return ((port&0xFF)<<8)|(port>>8)
}

GuiClose:
   ExitApp

Клиент:

AF_INET := 2
SOCK_STREAM := 1
IPPROTO_TCP := 6
WSA_FLAG_OVERLAPPED := 1
WM_USER := 0x400
WM_SOCKET := WM_USER + 1
FD_READ := 0x01 
FD_WRITE := 0x02
FD_OOB := 0x04
FD_ACCEPT := 0x08
FD_CONNECT := 0x10
FD_CLOSE := 0x20
WSAEWOULDBLOCK := 10035
;объявление переменных
VarSetCapacity(WSAData, 108, 0) ;для x86 хватит и 100
Socket := -1
AcceptSocket := -1
VarSetCapacity(SockAddr, 16, 0)
VarSetCapacity(buf, 1024, 0)
;код
Gui, Add, ListView, w480 h240, сокет|сообщение
Gui, Add, Button, default, Ping1
Gui, Add, Button, default, Ping2
Gui, Show
Gui, +LastFound
hWnd := WinExist()
OnMessage(WM_SOCKET, "DlgProc", 5)
DllCall("LoadLibrary", "str", "Ws2_32.dll")
if(DllCall("Ws2_32.dll\WSAStartup", "ushort", 0x0202, "ptr", &WSAData))
{
   msgbox WSAStartup
   goto Clear
}
Socket := DllCall("Ws2_32.dll\socket", "int", AF_INET, "int", SOCK_STREAM, "int", IPPROTO_TCP, "ptr")
if(Socket=-1)
{
   msgbox Socket
   goto Clear
}
if(DllCall("Ws2_32.dll\WSAAsyncSelect", "ptr", Socket, "ptr", hWnd, "uint", WM_SOCKET, "int", FD_READ|FD_WRITE|FD_CLOSE, "int")=-1)
{
   msgbox % "WSAAsyncSelect " . DllCall("Ws2_32.dll\WSAGetLastError")
   goto Clear
}
NumPut(AF_INET, &SockAddr, 0, "short")
NumPut(htons(5676), &SockAddr, 2, "ushort")
NumPut(inet_addr("127.0.0.1"), &SockAddr, 4, "uint")
if(DllCall("Ws2_32.dll\connect", "ptr", Socket, "ptr", &SockAddr, "int", 16)=-1)
{
   if(DllCall("Ws2_32.dll\WSAGetLastError")!=WSAEWOULDBLOCK)
   {
      msgbox connect
	  goto Clear
   }
}
return
Clear:
if(Socket)
   DllCall("Ws2_32.dll\closesocket", "ptr", Socket)
DllCall("Ws2_32.dll\WSACleanup")
return

DlgProc(wParam, lParam, msg, hwnd)
{
   global
   local fd
   if(msg=WM_SOCKET)
   {
      fd := lParam&0xFFFF
	  if(fd=FD_READ)
	  {
	     LV_Add("", wParam, "FD_READ")
	  }
	  else if(fd=FD_WRITE)
	  {
	     LV_Add("", wParam, "FD_WRITE")
	  }
	  else if(fd=FD_CLOSE)
	  {
	     LV_Add("", wParam, "FD_CLOSE")
	     DllCall("Ws2_32.dll\closesocket", "ptr", wParam)
	  }
	  else
	  {
	     LV_Add("", wParam, "???")
	  }
   }
}

inet_addr(StringWithIP)
{
   ret := RegExMatch(StringWithIP, "^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$", ArrayWithIP)
   if((ret="")||(ret=0))
      return ""
   if((ArrayWithIP1>255)||(ArrayWithIP2>255)||(ArrayWithIP3>255)||(ArrayWithIP4>255))
      return ""
   VarSetCapacity(ip, 4, 0)
   NumPut(ArrayWithIP1, &ip, 0, "uchar")
   NumPut(ArrayWithIP2, &ip, 1, "uchar")
   NumPut(ArrayWithIP3, &ip, 2, "uchar")
   NumPut(ArrayWithIP4, &ip, 3, "uchar")
   return NumGet(&ip, 0, "uint")
}

htons(port)
{
   if((port<0)||(port>0xFFFF))
      return ""
   return ((port&0xFF)<<8)|(port>>8)
}

ButtonPing1:
   StrPut("pg|1", &buf, 8, "utf-16")
   DllCall("Ws2_32.dll\send", "ptr", Socket, "ptr", &buf, "int", 16, "int", 0)
return
ButtonPing2:
   StrPut("pg|2", &buf, 8, "utf-16")
   DllCall("Ws2_32.dll\send", "ptr", Socket, "ptr", &buf, "int", 16, "int", 0)
return

GuiClose:
   ExitApp

Очень много кода совпадает, поэтому можно вынести его в отдельный файл. htons и inet_addr аналоги стандартных функций- первая преобразует порт(меняет байты местами), а вторая преобразует строку с ip-адресом в число(двойное слово, uint).
Ещё стоит обратить внимание на то, что в используемом режиме функция "connect" почти всегда возвращает ошибку с кодом WSAEWOULDBLOCK, поэтому нельзя сразу точно сказать установлена связь или нет. Если установлена, то придёт сообщение FD_WRITE(т.е. можно писАть). Как только сервер получает данные, приходит сообщение FD_WRITE, FD_CLOSE приходит если кто-то закрыл соединение.
Тут довольно много кода, поэтому всё я описывать не буду, лучше отвечу на вопросы, если таковые найдутся.
Кстати можно посмотреть книгу "Программирование в сетях Microsoft Windows"(легко найти в сети), там в 8-ой главе есть описание моделей ввода-вывода, в том числе и этой.

33 (изменено: Malcev, 2012-02-02 08:05:36)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

На WinXp 32 бит если запустить клиент и сервер, то работает.
А вот на висте 64 уже нет.
И зачем нужно 2 пинга?
И непонятно, обращение к какой функции прописывать в скрипты чтобы передавать сообщения на клиентскую зону?
И я ещё почитал вот это
http://www.autohotkey.com/forum/topic58183.html
Это тоже самое, что у вас?
Или другое?

Модернизировал свой скрипт.
Есть ли какие-то недочёты?
Серверная часть


loop
{
   MouseGetPos, xpos, ypos
   PixelSearch, Px, Py, % xpos - 10, % ypos - 10, % xpos + 10, % ypos + 10, 0xEFFF0E, 0, Fast
   If ErrorLevel = 0
   {
       SendMessage, 0x50,, 0x4190419,, A ; русский
   }
   MouseGetPos, xpos, ypos
   PixelSearch, Px, Py, % xpos - 10, % ypos - 10, % xpos + 10, % ypos + 10, 0xEFFF00, 0, Fast
   If ErrorLevel = 0
   {
       SendMessage, 0x50,, 0xF0150426,, A ; латышский
   }
   MouseGetPos, xpos, ypos
   PixelSearch, Px, Py, % xpos - 10, % ypos - 10, % xpos + 10, % ypos + 10, 0xFEFF00, 0, Fast
   If ErrorLevel = 0
   {
       SendMessage, 0x50,, 0x4090409,, A ; английский
   }
   sleep 100
}

Клиентская часть


loop
{   
    If (InputLayout() = "Russian" and InputLayout() != InputLayout_old)
    {   
        CoordMode, Mouse
        MouseGetPos, xpos, ypos
        Splashimage, 1:, CW0EFFEF B W5 H5 Y%ypos% X%xpos%
        sleep 100
        Splashimage, off
        InputLayout_old := InputLayout()
    }
    Else If (InputLayout() = "Latvian" and InputLayout() != InputLayout_old)
    {   
        CoordMode, Mouse
        MouseGetPos, xpos, ypos
        Splashimage, 1:, CW00FFEF B W5 H5 Y%ypos% X%xpos%
        sleep 100
        Splashimage, off
        InputLayout_old := InputLayout()
    }
    Else If (InputLayout() = "English" and InputLayout() != InputLayout_old)
    {   
        CoordMode, Mouse
        MouseGetPos, xpos, ypos
        Splashimage, 1:, CW00FFFE B W5 H5 Y%ypos% X%xpos%
        sleep 100
        Splashimage, off
        InputLayout_old := InputLayout()
    }
    sleep 100
}

InputLayout()
{
    ThreadID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
    HKL := DllCall("GetKeyboardLayout", "uint", ThreadID, "UShort")
    VarSetCapacity(sKbd, 260, 0)
    DllCall("GetLocaleInfo", "uint", HKL
                           , "uint", 0x1001
                           , "str",  sKbd
                           , "uint", 260)
    Return sKbd
}

34 (изменено: Александр_, 2012-02-02 11:56:51)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

На WinXp 32 бит если запустить клиент и сервер, то работает.
А вот на висте 64 уже нет.

Какую-нибудь ошибку выдаёт? Я всё на Win7 x64 тестировал.

Malcev пишет:

И непонятно, обращение к какой функции прописывать в скрипты чтобы передавать сообщения на клиентскую зону?

StrPut("pg|1", &buf, 8, "utf-16")
DllCall("Ws2_32.dll\send", "ptr", Socket, "ptr", &buf, "int", 16, "int", 0)

В буфер(buf), выделенный в начале скрипта(1024 байта) записывается строка в кодировке UTF-16(2 байта на символ). Затем этот буфер отправляется на сервер(третьим параметром функции send должна быть восьмёрка, это размер передаваемых данных). Необязательно передавать строки, можно выбрать любой формат.

Malcev пишет:

И я ещё почитал вот это
http://www.autohotkey.com/forum/topic58183.html
Это тоже самое, что у вас?
Или другое?

То же самое, можно в такую же библиотеку оформить.

Malcev пишет:

Есть ли какие-то недочёты?

Фатальных нет .

35 (изменено: Malcev, 2012-02-03 00:03:00)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Извините, всё работает.
Я просто не те айпи вписал.
Но всё-равно не понимаю как мне передать эту команду

SendMessage, 0x50,, 0x4190419,, A ; русский

Как я понял, мне это значение

0x50,, 0x4190419,, A ; русский

надо скопировать в буфер обмена, после чего нажать на Ping1.
Тогда оно появится в окошке на сервере и мне его оттуда надо как-то взять и запустить

SendMessage, 0x50,, 0x4190419,, A ; русский

А нельзя это всё поставить автоматом +убрать Gui, типа

Gui, Hide

36 (изменено: Александр_, 2012-02-03 23:54:34)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Ну вот в сообщении #33 есть код, который отслеживает смену раскладки(к сожалению сейчас нет времени разбираться с TSF). Вся система выглядит так:
1) Запускаем первый скрипт(сервер)
2) Запускаем программу удалённого управления и подключаемся к нужному компьютеру.
3) Запускаем на удалённом компьютере второй скрипт(клиент)
Значит сервер после запуска должен только ждать соединения, а затем команд о смене раскладки от клиента. Это уже реализовано в посте #32, разве что можно убрать обработку FD_WRITE(раз сервер у нас ничего не отправляет) и ждать только одного соединения, а при его разрыве закрываться самому. Теперь протокол, я предлагаю следующий формат: 2 байта занимает команда, а дальше по обстоятельствам . В частности команда "1" будет означать смену раскладки на ту, которая передаётся следующими четырьмя байтами(см. функцию ReadData).

;объявление констант
AF_INET := 2
SOCK_STREAM := 1
IPPROTO_TCP := 6
WSA_FLAG_OVERLAPPED := 1
WM_USER := 0x400
WM_SOCKET := WM_USER + 1
FD_READ := 0x01 
FD_WRITE := 0x02
FD_OOB := 0x04
FD_ACCEPT := 0x08
FD_CONNECT := 0x10
FD_CLOSE := 0x20
;объявление переменных
VarSetCapacity(WSAData, 108, 0) ;для x86 хватит и 100
Socket := -1
AcceptSocket := -1
VarSetCapacity(SockAddr, 16, 0)
VarSetCapacity(buf, 1024, 0)
;код
DetectHiddenWindows, On
WinGet, hWnd, ID, % "ahk_classAutoHotkey ahk_pid" DllCall("GetCurrentProcessId", "uint")
OnMessage(WM_SOCKET, "DlgProc", 5)
DllCall("LoadLibrary", "str", "Ws2_32.dll")
if(DllCall("Ws2_32.dll\WSAStartup", "ushort", 0x0202, "ptr", &WSAData))
{
   msgbox WSAStartup
   goto Clear
}
Socket := DllCall("Ws2_32.dll\socket", "int", AF_INET, "int", SOCK_STREAM, "int", IPPROTO_TCP, "ptr")
if(Socket=-1)
{
   msgbox Socket
   goto Clear
}
NumPut(AF_INET, &SockAddr, 0, "short")
NumPut(htons(5676), &SockAddr, 2, "ushort")
NumPut(inet_addr("127.0.0.1"), &SockAddr, 4, "uint")
if(DllCall("Ws2_32.dll\WSAAsyncSelect", "ptr", Socket, "ptr", hWnd, "uint", WM_SOCKET, "int", FD_ACCEPT|FD_CLOSE, "int")=-1)
{
   msgbox % "WSAAsyncSelect " . DllCall("Ws2_32.dll\WSAGetLastError")
   goto Clear
}
if(DllCall("Ws2_32.dll\bind", "ptr", Socket, "ptr", &SockAddr, "int", 16, "int")=-1)
{
   msgbox % "bind " . DllCall("Ws2_32.dll\WSAGetLastError")
   goto Clear
}
if(DllCall("Ws2_32.dll\listen", "ptr", Socket, "int", 1, "int")=-1)
{
   msgbox % "listen " . DllCall("Ws2_32.dll\WSAGetLastError")
   goto Clear
}
return
Clear:
if(Socket)
   DllCall("Ws2_32.dll\closesocket", "ptr", Socket)
DllCall("Ws2_32.dll\WSACleanup")
return
 
DlgProc(wParam, lParam, msg, hwnd)
{
   global
   local fd, ClientSocket
   if(msg=WM_SOCKET)
   {
      fd := lParam&0xFFFF
      if(fd=FD_ACCEPT)
      {
         ClientSocket := DllCall("Ws2_32.dll\accept", "ptr", wParam, "ptr", 0, "int", 0, "ptr")
         DllCall("Ws2_32.dll\WSAAsyncSelect", "ptr", ClientSocket, "ptr", hWnd, "uint", WM_SOCKET, "int", FD_READ|FD_CLOSE, "int")
		 DllCall("Ws2_32.dll\closesocket", "ptr", wParam)
      }
      else if(fd=FD_READ)
      {
	     ReadData(wParam)
      }
      else if(fd=FD_CLOSE)
      {
         DllCall("Ws2_32.dll\closesocket", "ptr", wParam)
		 if(Socket!=wParam)
		 {
		    DllCall("Ws2_32.dll\WSACleanup")
		    ExitApp
		 }
      }
   }
}
 
inet_addr(StringWithIP)
{
   ret := RegExMatch(StringWithIP, "^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$", ArrayWithIP)
   if((ret="")||(ret=0))
      return ""
   if((ArrayWithIP1>127)||(ArrayWithIP2>127)||(ArrayWithIP3>127)||(ArrayWithIP4>127))
      return ""
   VarSetCapacity(ip, 4, 0)
   NumPut(ArrayWithIP1, &ip, 0, "uchar")
   NumPut(ArrayWithIP2, &ip, 1, "uchar")
   NumPut(ArrayWithIP3, &ip, 2, "uchar")
   NumPut(ArrayWithIP4, &ip, 3, "uchar")
   return NumGet(&ip, 0, "uint")
}
 
htons(port)
{
   if((port<0)||(port>0xFFFF))
      return ""
   return ((port&0xFF)<<8)|(port>>8)
}

ReadData(Socket)
{
   global buf
   x:=DllCall("Ws2_32.dll\recv", "ptr", Socket, "ptr", &buf, "int", 1024, "int", 0)
   if(x>=2) ;2 байта обязательно должны быть, т.к. это размер команды
   {
      com := NumGet(&buf, 0, "ushort") ;получаем команду
	  if(com=1) ;если смена раскладки
	  {
	     SendMessage, 0x50,, NumGet(&buf, 2, "uint"),, A ;меняем раскладку
	  }
   }
}

Теперь клиент. Там по аналогии, убираем gui, убираем обработку FD_READ и закрываемся после разрыва соединения. Функция ChangeLayout(id) посылает серверу команду о смене раскладки на id. В примере смена раскладки производится по нажатию клавиш "1" и "2", а нужно на место "SplashImage":

AF_INET := 2
SOCK_STREAM := 1
IPPROTO_TCP := 6
WSA_FLAG_OVERLAPPED := 1
WM_USER := 0x400
WM_SOCKET := WM_USER + 1
FD_READ := 0x01 
FD_WRITE := 0x02
FD_OOB := 0x04
FD_ACCEPT := 0x08
FD_CONNECT := 0x10
FD_CLOSE := 0x20
WSAEWOULDBLOCK := 10035
;объявление переменных
VarSetCapacity(WSAData, 108, 0) ;для x86 хватит и 100
Socket := -1
AcceptSocket := -1
VarSetCapacity(SockAddr, 16, 0)
VarSetCapacity(buf, 1024, 0)
;код
DetectHiddenWindows, On
WinGet, hWnd, ID, % "ahk_classAutoHotkey ahk_pid" DllCall("GetCurrentProcessId", "uint")
OnMessage(WM_SOCKET, "DlgProc", 5)
DllCall("LoadLibrary", "str", "Ws2_32.dll")
if(DllCall("Ws2_32.dll\WSAStartup", "ushort", 0x0202, "ptr", &WSAData))
{
   msgbox WSAStartup
   goto Clear
}
Socket := DllCall("Ws2_32.dll\socket", "int", AF_INET, "int", SOCK_STREAM, "int", IPPROTO_TCP, "ptr")
if(Socket=-1)
{
   msgbox Socket
   goto Clear
}
if(DllCall("Ws2_32.dll\WSAAsyncSelect", "ptr", Socket, "ptr", hWnd, "uint", WM_SOCKET, "int", FD_WRITE|FD_CLOSE, "int")=-1)
{
   msgbox % "WSAAsyncSelect " . DllCall("Ws2_32.dll\WSAGetLastError")
   goto Clear
}
NumPut(AF_INET, &SockAddr, 0, "short")
NumPut(htons(5676), &SockAddr, 2, "ushort")
NumPut(inet_addr("127.0.0.1"), &SockAddr, 4, "uint")
if(DllCall("Ws2_32.dll\connect", "ptr", Socket, "ptr", &SockAddr, "int", 16)=-1)
{
   if(DllCall("Ws2_32.dll\WSAGetLastError")!=WSAEWOULDBLOCK)
   {
      msgbox connect
	  goto Clear
   }
}
return
Clear:
if(Socket)
   DllCall("Ws2_32.dll\closesocket", "ptr", Socket)
DllCall("Ws2_32.dll\WSACleanup")
return

DlgProc(wParam, lParam, msg, hwnd)
{
   global
   local fd
   if(msg=WM_SOCKET)
   {
      fd := lParam&0xFFFF
	  if(fd=FD_WRITE)
	  {
	     ;можно отправлять, в данном примере проверка этого сообщения опускается
	  }
	  else if(fd=FD_CLOSE)
	  {
	     LV_Add("", wParam, "FD_CLOSE")
	     DllCall("Ws2_32.dll\closesocket", "ptr", wParam)
		 DllCall("Ws2_32.dll\WSACleanup")
		 ExitApp
	  }
   }
}

inet_addr(StringWithIP)
{
   ret := RegExMatch(StringWithIP, "^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$", ArrayWithIP)
   if((ret="")||(ret=0))
      return ""
   if((ArrayWithIP1>255)||(ArrayWithIP2>255)||(ArrayWithIP3>255)||(ArrayWithIP4>255))
      return ""
   VarSetCapacity(ip, 4, 0)
   NumPut(ArrayWithIP1, &ip, 0, "uchar")
   NumPut(ArrayWithIP2, &ip, 1, "uchar")
   NumPut(ArrayWithIP3, &ip, 2, "uchar")
   NumPut(ArrayWithIP4, &ip, 3, "uchar")
   return NumGet(&ip, 0, "uint")
}

htons(port)
{
   if((port<0)||(port>0xFFFF))
      return ""
   return ((port&0xFF)<<8)|(port>>8)
}

ChangeLayout(id)
{
   global buf, Socket
   NumPut(1, &buf, 0, "ushort")
   NumPut(id, &buf, 2, "uint")
   DllCall("Ws2_32.dll\send", "ptr", Socket, "ptr", &buf, "int", 6, "int", 0)
}

1::ChangeLayout(0x4090409)
2::ChangeLayout(0x4190419)

Только ip нужно везде сменить .

37 (изменено: Malcev, 2012-02-04 05:56:57)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Александр_, чувствую эти заморочки с  айпи никогда не закончатся.
Вчера я ваш скрипт проверял в локалке, а сейчас проверил действительно на удалённом компе и как оказалось скрипт  не может пробиться с удалённого котмпьютера через рутер, который установлен на локальном компьютере.
Хотя в рутере я открыл и перенаправил порт 3389, и через Remote desktop связь есть.
А тут я вписываю ip adress:port и не пингуется.
Проверял первый вариант вашего скрипта с GUI.
Как я понимаю, я не там вписываю порт, в смысле в вашем скрипте.
Как тут быть?

к сожалению сейчас нет времени разбираться с TSF

А это что такое?
Вот это?
http://en.wikipedia.org/wiki/Text_Services_Framework
И как с ним надо разбираться?

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

#SingleInstance force
OnExit, ExitSub

cD = 32   ; bits (quality) - you can change to suit your requirments
sW = 1668 ; pixels - you can change to suit your requirments
sH = 1002  ; pixels - you can change to suit your requirments
rR = 60   ; Hz (frequency) - you can change to suit your requirments 
 
ChangeDisplaySettings( cD, sW, sH, rR )
 
ChangeDisplaySettings( cD, sW, sH, rR )
{
  VarSetCapacity(dM,156,0), NumPut(156,dM,36)
  DllCall( "EnumDisplaySettingsA", UInt,0, UInt,-1, UInt,&dM ), NumPut(0x5c0000,dM,40)
  NumPut(cD,dM,104),  NumPut(sW,dM,108),  NumPut(sH,dM,112),  NumPut(rR,dM,120)
  Return DllCall( "ChangeDisplaySettingsA", UInt,&dM, UInt,0 )
}

Color = 0x00000C 
Color1 = 0x0C0000
Color2 = 0x000C00
x = 500
y = 500
w = 1 
h = 1
loop
{   
    If (InputLayout() = "Russian")
    {   
	Gui, +AlwaysOnTop -Caption +ToolWindow +LastFound
	Gui, Color, % Color
	Gui, Show, x%x% y%y% w%w% h%h% NA
    }
    Else If (InputLayout() = "Latvian")
    {   
	Gui, +AlwaysOnTop -Caption +ToolWindow +LastFound
	Gui, Color, % Color1
	Gui, Show, x%x% y%y% w%w% h%h% NA
    }
    Else If (InputLayout() = "English")
    {   
	Gui, +AlwaysOnTop -Caption +ToolWindow +LastFound
	Gui, Color, % Color2
	Gui, Show, x%x% y%y% w%w% h%h% NA
    }  
    sleep, 50 
}
 
InputLayout()
{
    ThreadID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
    HKL := DllCall("GetKeyboardLayout", "uint", ThreadID, "UShort")
    VarSetCapacity(sKbd, 260, 0)
    DllCall("GetLocaleInfo", "uint", HKL
                           , "uint", 0x1001
                           , "str",  sKbd
                           , "uint", 260)
    Return sKbd
}


ExitSub:
if A_ExitReason not in Reload,Single,Error  ; Avoid spaces around the comma in this line.
{
    cD1 = 32   ; bits (quality) - you can change to suit your requirments
    sW1 = 1920 ; pixels - you can change to suit your requirments
    sH1 = 1080  ; pixels - you can change to suit your requirments
    rR1 = 60   ; Hz (frequency) - you can change to suit your requirments 

    ChangeDisplaySettings( cD1, sW1, sH1, rR1 )

    ChangeDisplaySettings1( cD1, sW1, sH1, rR1 )
    {
	VarSetCapacity(dM,156,0), NumPut(156,dM,36)
        DllCall( "EnumDisplaySettingsA", UInt,0, UInt,-1, UInt,&dM ), NumPut(0x5c0000,dM,40)
	NumPut(cD1,dM,104),  NumPut(sW1,dM,108),  NumPut(sH1,dM,112),  NumPut(rR1,dM,120)
	Return DllCall( "ChangeDisplaySettingsA", UInt,&dM, UInt,0 )
    }
}
ExitApp

38 (изменено: Александр_, 2012-02-04 13:11:56)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

А тут я вписываю ip adress:port и не пингуется.
Проверял первый вариант вашего скрипта с GUI.
Как я понимаю, я не там вписываю порт, в смысле в вашем скрипте.
Как тут быть?

порт задаётся вторым параметром в структуре SockAddr(NumPut(htons(5676), &SockAddr, 2, "ushort")).

Malcev пишет:

А это что такое?
Вот это?
http://en.wikipedia.org/wiki/Text_Services_Framework
И как с ним надо разбираться?

Читать документацию и проверять её на практике . Раньше при смене раскладки приходили оконные сообщения, а в WinXP всё через COM сделали.

39

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

При запуске в серверной части выходит ошибка bind 10048
А в клиентской части при попытке пинга пишет 460 FD_CLOSE

40

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

При запуске в серверной части выходит ошибка bind 10048

Скорее всего порт используется другой программой. Полное описание ошибки тут.

41

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Да точно - перенаправил порт, всё заработало.
Сейчас привяжу это всё к изменению языка.
Спасибо большое!

42

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Я всё правильно вписал?
Что-то не переключает

ChangeLayout(id)
{
   global buf, Socket
   NumPut(1, &buf, 0, "ushort")
   NumPut(id, &buf, 2, "uint")
   DllCall("Ws2_32.dll\send", "ptr", Socket, "ptr", &buf, "int", 6, "int", 0)
}

loop
{   
If (InputLayout() = "Russian")
{
   ChangeLayout(0x4090409)
}

Else If (InputLayout() = "English")
{
   ChangeLayout(0x4190419)
}

Else If (InputLayout() = "Latvian")
{
   ChangeLayout(0xF0150426)
}
}

InputLayout()
{
    ThreadID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
    HKL := DllCall("GetKeyboardLayout", "uint", ThreadID, "UShort")
    VarSetCapacity(sKbd, 260, 0)
    DllCall("GetLocaleInfo", "uint", HKL
                           , "uint", 0x1001
                           , "str",  sKbd
                           , "uint", 260)
    Return sKbd
}

43

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

Я всё правильно вписал?
Что-то не переключает

Этого фрагмента недостаточно. Посылать данные нужно только при смене раскладки, а тут они постоянно отправляются.

44

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

А так?
Но так тоже не посылает.

ChangeLayout(id)
{
   global buf, Socket
   NumPut(1, &buf, 0, "ushort")
   NumPut(id, &buf, 2, "uint")
   DllCall("Ws2_32.dll\send", "ptr", Socket, "ptr", &buf, "int", 6, "int", 0)
}

loop
{   
 
 If (InputLayout() = "Russian" and InputLayout() != InputLayout_old)
{
   ChangeLayout(0x4090409)
   InputLayout_old := InputLayout()
}

Else If (InputLayout() = "English" and InputLayout() != InputLayout_old)
{
   ChangeLayout(0x4190419)
   InputLayout_old := InputLayout()
}

Else If (InputLayout() = "Latvian" and InputLayout() != InputLayout_old)
{
   ChangeLayout(0xF0150426)
   InputLayout_old := InputLayout()
}
}

InputLayout()
{
    ThreadID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
    HKL := DllCall("GetKeyboardLayout", "uint", ThreadID, "UShort")
    VarSetCapacity(sKbd, 260, 0)
    DllCall("GetLocaleInfo", "uint", HKL
                           , "uint", 0x1001
                           , "str",  sKbd
                           , "uint", 260)
    Return sKbd
}

45

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

А так?

Нормально, но лучше так:

OldLayout := DllCall("GetKeyboardLayout", "uint", DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0, "ushort"), "ptr")
loop
{
   NewLayout := DllCall("GetKeyboardLayout", "uint", DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0, "ushort"), "ptr")
   if(OldLayout!=NewLayout)
   {
      OldLayout := NewLayout
      ChangeLayout(NewLayout)
   }
}
Malcev пишет:

Но так тоже не посылает.

Это понятно, но причина не в этом фрагменте. Нужен весь скрипт.

46

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

А чем лучше?
Вот весь код.

AF_INET := 2
SOCK_STREAM := 1
IPPROTO_TCP := 6
WSA_FLAG_OVERLAPPED := 1
WM_USER := 0x400
WM_SOCKET := WM_USER + 1
FD_READ := 0x01 
FD_WRITE := 0x02
FD_OOB := 0x04
FD_ACCEPT := 0x08
FD_CONNECT := 0x10
FD_CLOSE := 0x20
WSAEWOULDBLOCK := 10035
;объявление переменных
VarSetCapacity(WSAData, 108, 0) ;для x86 хватит и 100
Socket := -1
AcceptSocket := -1
VarSetCapacity(SockAddr, 16, 0)
VarSetCapacity(buf, 1024, 0)
;код
DetectHiddenWindows, On
WinGet, hWnd, ID, % "ahk_classAutoHotkey ahk_pid" DllCall("GetCurrentProcessId", "uint")
OnMessage(WM_SOCKET, "DlgProc", 5)
DllCall("LoadLibrary", "str", "Ws2_32.dll")
if(DllCall("Ws2_32.dll\WSAStartup", "ushort", 0x0202, "ptr", &WSAData))
{
   msgbox WSAStartup
   goto Clear
}
Socket := DllCall("Ws2_32.dll\socket", "int", AF_INET, "int", SOCK_STREAM, "int", IPPROTO_TCP, "ptr")
if(Socket=-1)
{
   msgbox Socket
   goto Clear
}
if(DllCall("Ws2_32.dll\WSAAsyncSelect", "ptr", Socket, "ptr", hWnd, "uint", WM_SOCKET, "int", FD_WRITE|FD_CLOSE, "int")=-1)
{
   msgbox % "WSAAsyncSelect " . DllCall("Ws2_32.dll\WSAGetLastError")
   goto Clear
}
NumPut(AF_INET, &SockAddr, 0, "short")
NumPut(htons(666), &SockAddr, 2, "ushort")
NumPut(inet_addr("192.168.123.254"), &SockAddr, 4, "uint")
if(DllCall("Ws2_32.dll\connect", "ptr", Socket, "ptr", &SockAddr, "int", 16)=-1)
{
   if(DllCall("Ws2_32.dll\WSAGetLastError")!=WSAEWOULDBLOCK)
   {
      msgbox connect
      goto Clear
   }
}
return
Clear:
if(Socket)
   DllCall("Ws2_32.dll\closesocket", "ptr", Socket)
DllCall("Ws2_32.dll\WSACleanup")
return
 
DlgProc(wParam, lParam, msg, hwnd)
{
   global
   local fd
   if(msg=WM_SOCKET)
   {
      fd := lParam&0xFFFF
      if(fd=FD_WRITE)
      {
         ;можно отправлять, в данном примере проверка этого сообщения опускается
      }
      else if(fd=FD_CLOSE)
      {
         LV_Add("", wParam, "FD_CLOSE")
         DllCall("Ws2_32.dll\closesocket", "ptr", wParam)
         DllCall("Ws2_32.dll\WSACleanup")
         ExitApp
      }
   }
}
 
inet_addr(StringWithIP)
{
   ret := RegExMatch(StringWithIP, "^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$", ArrayWithIP)
   if((ret="")||(ret=0))
      return ""
   if((ArrayWithIP1>255)||(ArrayWithIP2>255)||(ArrayWithIP3>255)||(ArrayWithIP4>255))
      return ""
   VarSetCapacity(ip, 4, 0)
   NumPut(ArrayWithIP1, &ip, 0, "uchar")
   NumPut(ArrayWithIP2, &ip, 1, "uchar")
   NumPut(ArrayWithIP3, &ip, 2, "uchar")
   NumPut(ArrayWithIP4, &ip, 3, "uchar")
   return NumGet(&ip, 0, "uint")
}
 
htons(port)
{
   if((port<0)||(port>0xFFFF))
      return ""
   return ((port&0xFF)<<8)|(port>>8)
}
 
ChangeLayout(id)
{
   global buf, Socket
   NumPut(1, &buf, 0, "ushort")
   NumPut(id, &buf, 2, "uint")
   DllCall("Ws2_32.dll\send", "ptr", Socket, "ptr", &buf, "int", 6, "int", 0)
}

loop
{   
 
 If (InputLayout() = "Russian" and InputLayout() != InputLayout_old)
{
   ChangeLayout(0x4090409)
   InputLayout_old := InputLayout()
}

Else If (InputLayout() = "English" and InputLayout() != InputLayout_old)
{
   ChangeLayout(0x4190419)
   InputLayout_old := InputLayout()
}

Else If (InputLayout() = "Latvian" and InputLayout() != InputLayout_old)
{
   ChangeLayout(0xF0150426)
   InputLayout_old := InputLayout()
}
}

InputLayout()
{
    ThreadID := DllCall("GetWindowThreadProcessId", "Int", WinExist("A"), "Int", 0)
    HKL := DllCall("GetKeyboardLayout", "uint", ThreadID, "UShort")
    VarSetCapacity(sKbd, 260, 0)
    DllCall("GetLocaleInfo", "uint", HKL
                           , "uint", 0x1001
                           , "str",  sKbd
                           , "uint", 260)
    Return sKbd
}

47

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

А чем лучше?

Ну у тебя следующая цепочка- "узнать HKL->узнать язык по HKL->узнать HKL по языку", а у меня только "узнать HKL" . Плюс проверка на смену языка идёт в каждом условии, хотя достаточно один раз проверить.
И лучше задержку(Sleep) вставить, какие-нибудь пол секунды погоды не сделают, а процессору работы на порядок меньше.

Malcev пишет:

Вот весь код.

дык этот цикл вообще управления не получает.

if(DllCall("Ws2_32.dll\connect", "ptr", Socket, "ptr", &SockAddr, "int", 16)=-1)
{
   if(DllCall("Ws2_32.dll\WSAGetLastError")!=WSAEWOULDBLOCK)
   {
      msgbox connect
      goto Clear
   }
}
;если мы сюда попали, то скорее всего всё хорошо.
;точно можно будет сказать когда придёт сообщение с кодом FD_WRITE
;тут и должен выполнятся цикл, следящий за сменой языка
return
Clear:
;сюда мы попадаем если случился косяк.
if(Socket)
   DllCall("Ws2_32.dll\closesocket", "ptr", Socket)
DllCall("Ws2_32.dll\WSACleanup")
return

48

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Да, всё сейчас заработало!!!
Наконец-то!!!
Это что-то невероятное!
Спасибо за возню со мной!

49 (изменено: Александр_, 2012-02-04 16:21:13)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Malcev пишет:

Да, всё сейчас заработало!!!
Наконец-то!!!
Это что-то невероятное!

Эта проблема тоже решена?

50

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Да, спасибо за внимание  к моей проблеме.
Копирую через Ultra Vnc.
Так как делать это надо редко, то всё устраивает.
Александр_, если тебе несложно, намекнул бы куда вот здесь копать?
http://forum.script-coding.com/viewtopic.php?id=6767
А насчёт этого топика, то у меня есть целых 2 рабочих решения.
Скрипт который определяет по цвету, какой язык выбран, оставлю как запасной.
Вдруг выйдет ситуация при которой нельзя будет раскрыть порты.

51 (изменено: unKn0wn, 2017-06-21 15:06:37)

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

Добрый день.
Попробовал пример из сообщения №32 и даже с моими "руками" получилось. Подскажите, реализация клиента с возможностью принимать ответы от компьютеров с сервером -то в этом случае уже не обойтись на стороне клиента без кода серверной части?
Просто если в сети появился новый РС(скажем, в сети больше 400 машин), установив на него сервер, то без внесения в список адреса этого компьютера на клиенте -клиентская машина (машина админа) знать не будет о новом сервере. Потому, возник вопрос: как автоматически получать список машин? Подумал, что очень удобно будет если машины "серверы" будут отправлять что-то вроде эхо запроса на админскую машину и уже админская машина будет генерировать список РС, на которых стоит сервер. Мне думается здесь и второго зайца убить можно -мы будем знать какие машины живые а какие нет.

Может кто-то уже реализовал подобное?

52

Re: AHK: Синхронизация посылания клавиш на удалённом и локальном компьютер

http://forum.script-coding.com/viewtopic.php?id=12367