Как определить текущий язык в системе?

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Как определить текущий язык в системе?

Сообщение ger_kar » 09.02.2012 (Чт) 12:11

Хакер писал(а):Его даже не может быть, потому что большинству вещей в мире дают осмысленные названия, а это переводится как «надавить вверх».
Может, если кнопка будет на потолке :lol: ;) (шутка).
А вообще может имелось ввиду событие Form_KeyUp. Вообще нажатие определенных клавиш конечно отловить можно, и нажатие CAPS LOCk тоже, но вопрос стоял
АндрейБ писал(а):перехватить в форме изменение статуса CAPS LOCk или изменения языка
А как быть с настройками системы, в зависимости от которых для изменения языка, могут использоваться разные сочетания клавиш, да и поведение CAPS LOCk можно настроить. Предварительно считывать настройки из реестра, а потом от их результатов ловить соответствующие нажатия клавиш? А если языков не 2, а 3 и более будет, тогда как? Как мне кажется способ отлавливать нажатия клавиш для данной задачи будет довольно корявый.
Бороться и искать, найти и перепрятать

АндрейБ
Бывалый
Бывалый
 
Сообщения: 276
Зарегистрирован: 18.12.2004 (Сб) 17:00
Откуда: Санкт-Петербург

Re: Как определить текущий язык в системе?

Сообщение АндрейБ » 09.02.2012 (Чт) 13:58

key_press - соглсан.
но надо зрить в корень.
Кто ищет, тот всегда найдет ...

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Как определить текущий язык в системе?

Сообщение ger_kar » 09.02.2012 (Чт) 19:53

АндрейБ писал(а):но надо зрить в корень.
В какой корень не понял.
А вообще пришла такая идейка - отслеживать нажатия потенциальных клавиш, которые могут изменить язык, раскладку или же статус CapsLock. Для последнего это все две клавиши - сам CapsLock и Shift. И при обработке события если нажаты нужные клавиши проверять текущий язык, раскладку и статус CapsLock. Правда как проверить статус CapsLock я не в курсе, тут надо подумать.
Бороться и искать, найти и перепрятать

АндрейБ
Бывалый
Бывалый
 
Сообщения: 276
Зарегистрирован: 18.12.2004 (Сб) 17:00
Откуда: Санкт-Петербург

Re: Как определить текущий язык в системе?

Сообщение АндрейБ » 15.02.2012 (Ср) 17:21

KeyUp.
Кто ищет, тот всегда найдет ...

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Как определить текущий язык в системе?

Сообщение ger_kar » 15.02.2012 (Ср) 19:13

А что что-то не получается, вроде же уже все разрешилось. Или нет? Что обработка события key_press не дает нужного результата?
Бороться и искать, найти и перепрятать

coderx
Новичок
Новичок
 
Сообщения: 29
Зарегистрирован: 05.09.2005 (Пн) 10:44
Откуда: Узбекистан

Re: Как определить текущий язык в системе?

Сообщение coderx » 15.02.2012 (Ср) 22:17

Правда как проверить статус CapsLock я не в курсе, тут надо подумать.

На предыдущих постах были же показаны.

АндрейБ
Бывалый
Бывалый
 
Сообщения: 276
Зарегистрирован: 18.12.2004 (Сб) 17:00
Откуда: Санкт-Петербург

Re: Как определить текущий язык в системе?

Сообщение АндрейБ » 16.02.2012 (Чт) 8:22

все решено спасибо, не увидел второй странице ответов.
Кто ищет, тот всегда найдет ...

Teranas
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 224
Зарегистрирован: 13.12.2008 (Сб) 4:26
Откуда: Новосибирск

Re: Как определить текущий язык в системе?

Сообщение Teranas » 17.02.2012 (Пт) 19:19

Тут, пожалуй, всё, что вам надо...

:alien:

Код: Выделить всё
Option Explicit

Private Const HKL_PREV = 0
Private Const HKL_NEXT = 1

Private Declare Function GetSystemDefaultLangID Lib "kernel32" () As Integer
Private Declare Function VerLanguageName Lib "kernel32" Alias "VerLanguageNameA" (ByVal wLang As Long, ByVal szLang As String, ByVal nSize As Long) As Long
Private Declare Function GetKeyboardLayoutName Lib "user32" Alias "GetKeyboardLayoutNameA" (ByVal pwszKLID As String) As Long
Private Declare Function LoadKeyboardLayout Lib "user32" Alias "LoadKeyboardLayoutA" (ByVal pwszKLID As String, ByVal Flags As Long) As Long
Private Declare Function ActivateKeyboardLayout Lib "user32" (ByVal HKL As Long, ByVal Flags As Long) As Long

Private Declare Function GetAsyncKeyState Lib "user32" (ByVal vKey As Long) As Integer
' Контролирует нажатие и отжатие клавиши (-127)Нажата (1)Отжата
'Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer

Public Function SetDefaultLang() As String
' Установить раскладку по системному языку
Dim L1 As Long, L2 As Long
  L1 = GetSystemDefaultLangID() ' Системный язык по умолчанию
  'MsgBox Str$(L1) & vbCrLf & Str$(GetNumLangAN)
  While (L1 <> GetNumLangAN) And (L2 < 100)
    Call SetLangNEXT
    DoEvents
    L2 = L2 + 1
  Wend
  SetDefaultLang = GetNameLangAN(GetNumLangAN())
End Function

Public Function GetNameLangAN(NumLang As Long) As String
' Получить имя языка раскладки по номеру
Dim sBuff1 As String * 128
  VerLanguageName NumLang, sBuff1, 128
  GetNameLangAN = Lsn1(sBuff1)
End Function

Public Function GetNumLangAN() As Long
' Получить номер текущей раскладки
Dim s1 As String, L1 As Long
  s1 = String$(9, 0)
  GetKeyboardLayoutName s1
  'MsgBox s1
  GetNumLangAN = Val("&H" & s1)
End Function

Public Function SetLangAN(NumLang As Long) As Long
' Установить раскладку
  LoadKeyboardLayout StrCharPlus(Hex$(NumLang), "0", 9, 1), 1
End Function

Public Function SetLangNEXT() As Long
' Сменить раскладку на следующую
  ActivateKeyboardLayout HKL_NEXT, 0
End Function

Public Function SetLangPREV() As Long
' Сменить раскладку на предыдущую
  ActivateKeyboardLayout HKL_PREV, 0
End Function

Private Function StrCharPlus(String1 As String, Char1 As String, LenStr1 As Integer, LeftRightCenter As Integer) As String
' Добавление символов Char1 к строке
  Dim sTempSCP As String, i As Integer
  If (LenStr1 - Len(String1)) < 1 Then
    StrCharPlus = Left$(String1, LenStr1): Exit Function
  End If
  Select Case LeftRightCenter
  Case 0 ' Строка(String1) + Символы(Char1)
    StrCharPlus = String1 & String$(LenStr1 - Len(String1), Char1)
  Case 1 ' Символы(Char1) + Строка(String1)
    StrCharPlus = String$(LenStr1 - Len(String1), Char1) & String1
  Case 2 ' Символы(Char1) + Строка(String1) + Символы(Char1)
    i = (LenStr1 - Len(String1)) \ 2
    sTempSCP = String$(i, Char1) & String1 & String$(i, Char1)
    If Len(sTempSCP) < LenStr1 Then sTempSCP = Char1 & sTempSCP
    StrCharPlus = sTempSCP
  End Select
End Function
С уважением, Андрей.

АндрейБ
Бывалый
Бывалый
 
Сообщения: 276
Зарегистрирован: 18.12.2004 (Сб) 17:00
Откуда: Санкт-Петербург

Re: Как определить текущий язык в системе?

Сообщение АндрейБ » 10.05.2012 (Чт) 10:52

Твистеру спасибо, но есть глюк:
'Переключаем Caps
keybd_event vbKeyCapital, 0, KEYEVENTF_KEYDOWN, 0
keybd_event vbKeyCapital, 0, KEYEVENTF_KEYUP, 0

Все переключается, толь в Windows 7 все работает безупречно, а в Wibdows XP фокус прыгает по контролами формы.
В чем причина и как ее побороть?
Кто ищет, тот всегда найдет ...

Rody66
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 183
Зарегистрирован: 16.01.2011 (Вс) 17:03

Re: Как определить текущий язык в системе?

Сообщение Rody66 » 10.05.2012 (Чт) 21:34

АндрейБ
На первый взгляд вроде элементарная задача, а на деле все оказалось куда интереснее.
Раз уж ты гоовришь, что keybd_event не канает, то его я пропустил и сразу начал с SendKeys "{CAPSLOCK}", который как выяснилось вообще не работает, вопреки тому, что клавишу {CAPSLOCK} он поддерживает (http://msdn.microsoft.com/ru-ru/library/system.windows.forms.sendkeys.aspx).
Далее перешел на SendMessage. Посмотрел, что за параметры приходят вместе с сообщениями WM_KEYDOWN и WM_KEYUP при нажатии CapsLock на клавиатуре, выяснилось следующее: WM_KEYDOWN ::: wParam=20 (vbKeyCapital), lParam=3801089; WM_KEYUP ::: wParam=20 (vbKeyCapital), lParam=-1069940735. Сформировал следующие сообщения:
Код: Выделить всё
SendMessage Me.hwnd, WM_KEYDOWN, vbKeyCapital, ByVal 3801089
SendMessage Me.hwnd, WM_KEYUP, vbKeyCapital, ByVal -1069940735

Хоть Spy++ и утверждает, что мое сообщение и физическое нажатие CapsLock для программы идентичны, тем не менее, регистр не переключается.
И последнее, на что хватило терпения - это SendInput. На семерке регистр меняется. На XP - нет.
То есть, все использованные мною методы - фейл. Осталось лишь DirectInput попробовать (и, возможно, есть еще какие-то ф-ции эмуляции клавиш). Но и нельзя исключать тот факт, что для переключения регистра вполне себе может существовать соответствующая апи ф-ция.

АндрейБ
Бывалый
Бывалый
 
Сообщения: 276
Зарегистрирован: 18.12.2004 (Сб) 17:00
Откуда: Санкт-Петербург

Re: Как определить текущий язык в системе?

Сообщение АндрейБ » 23.05.2012 (Ср) 14:33

Я понимаю что для Windows XP проще не делать автоматическую смену CAPS LOCK, прыгает фокус как ему вздумается?
Кто ищет, тот всегда найдет ...

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Как определить текущий язык в системе?

Сообщение ger_kar » 23.05.2012 (Ср) 18:04

Rody66 писал(а):Далее перешел на SendMessage.
Вообще по идее здесь не SendMessage нужен, а PostMessage, т.е. сообщения должны не просто быть отправлены окну, а помещены в очередь сообщений потока, затем уже поток их оттуда выудит и далее после трансляции и диспетчера они должны попасть в нужное окно.
Бороться и искать, найти и перепрятать

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Как определить текущий язык в системе?

Сообщение Хакер » 23.05.2012 (Ср) 18:08

ger_kar писал(а):Вообще по идее здесь не SendMessage нужен, а PostMessage, т.е. сообщения должны не просто быть отправлены окну, а помещены в очередь сообщений потока,

Интересно, по твоему надо SendMessage не помещает сообщение в очередь?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Как определить текущий язык в системе?

Сообщение ger_kar » 23.05.2012 (Ср) 18:59

Я вообще опирался на ту информацию, которую прочитал, а прочитал я следующее:
MSDN писал(а):PostMessage
Places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.

Помещает (вставляет) сообщение в очередь сообщений, связанную с потоком, который создал заданное окно и возвращает значение без ожидания потока, который обрабатывает сообщение.

SendMessage
Sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.

To send a message and return immediately, use the SendMessageCallback or SendNotifyMessage function. To post a message to a thread's message queue and return immediately, use the PostMessage or PostThreadMessage function.

Отправляет заданное сообщение окну или окнам. Функция вызывает оконную процедуру для заданного окна и не возвращает значение до тех пор, пока оконная процедура не обработает сообщение.

Чтобы отправить сообщение и возвратить немедленно значение, используйте функцию SendMessageCallback или SendNotifyMessage. Чтобы поместить сообщение в очередь сообщений потока и возвратить немедленно значение, используйте функцию PostMessage или PostThreadMessage.
Бороться и искать, найти и перепрятать

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.05.2012 (Ср) 19:31

Не "возвратить немедленно значение", а "вернуться немедленно".

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Как определить текущий язык в системе?

Сообщение ger_kar » 23.05.2012 (Ср) 19:46

НУ и значение функция тоже возвращает :) , хотя замечание правильное :)
Бороться и искать, найти и перепрятать

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 23.05.2012 (Ср) 19:55

SendMessage возвращает то значение, которое вернула ей оконная процедура, насколько я помню.
Что возвращают эти, понятия не имею.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Как определить текущий язык в системе?

Сообщение Хакер » 23.05.2012 (Ср) 21:08

ger_kar, как насчёт того, чтобы пропустить написанное не только через автоматический переводчик, но и через призму собственной логики и здравого смысла?

Описанное в документации поведение актуально только для того случая, когда поток, вызывающий SendMessage, и поток, владеющий окном, которому предназначено сообщение — один и тот же поток.

Вот если задействовать логику и привлечь здравый смысл то сразу напрашивается два вывода:
  • Если вызывает SendMessage один поток, а окно-получатель сообщения принадлежит другому потоку, то SendMessage не имеет права взывать напрямую WindowProc этого окна, потому что WindowProc должен быть вызван в контексте другого потока. А если эти два разных потока принадлежат ещё и разным процессам, то такой прямой вызов вообще невозможен.
  • В случае же, когда отправляющий сообщение поток и получающий сообщение поток — один и тот же, у SendMessage вообще нет никакого другого варианта, кроме как вызывать WindowProc окна-получателя напрямую. Если SendMessage в этом случае не вызовет WindowProc напрямую, а поместит сообщение в очередь и заморозится до тех пор, пока сообщение не обработают, то просто некому будет обработать сообщение, потому что поток, который должен его обработать — то есть текущий поток — заморожен, спит и ждёт внутри SendMessage.

Поэтому SendMessage вызывает WindowProc напрямую только если окно-получатель принадлежит текущему потоку.
Во всех остальных случаях SendMessage кладёт сообщение в очередь и ждёт его обработки.

Причём в рамках потока-получателя такое сообщение обрабатывает не обычным образом: GetMessage никогда не вернёт его вам и не даст вам его пропустить через TranslateMessage->DispatchMessage, потому что нет гарантии, что вы это сделаете, и потому что в этом случае программисту придётся расчитывать и нацеливаться на целых два варианта обработки сообщений, посланных через SendMessage: в одном случае WP бы вызывался напрямую, а в других — через цепочку GetMessage...TranslateMessage...DispatchMessage.

Вместо этого GetMessage (когда её вызывают) при обнаружении сообщений, посланных в очередь с помощью SendMessage, не возвращает такие сообщения вызывающий стороне. Она их обрабатывает сама. И с точки программиста складывается полная иллюзия того, что такое сообщение вообще не попадало в очередь — поскольку GetMessage его никогда не вернёт.

И если вы попытаетесь внутри цикла обработки сообщений между вызовами GetMessage и DispatchMessage с помощью if-а попробовать отследить посланное текущему потоку с помощью SendMessage сообщение — вы его никогда в принципе не отследите. Потому что такое сообщение не проходит через итерацию цикла прокачки сообщений.

Зато попробуйте не вызывать в цикле GetMessage — тогда сообщение, посланное вашему окну с помощью SendMessage, никогда не будет обработано.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Как определить текущий язык в системе?

Сообщение ger_kar » 23.05.2012 (Ср) 23:01

Хакер писал(а):Описанное в документации поведение актуально только для того случая, когда поток, вызывающий SendMessage, и поток, владеющий окном, которому предназначено сообщение — один и тот же поток.
А вот составляющим такую документацию, что шибко лень было сделать подобные уточнения, что-бы не вводить в заблуждения? А когда не знал, да еще и забыл, никакая логика это восстановит :) Получается что в документации одно пишут, а другое в уме. Попробуй догадайся.
Бороться и искать, найти и перепрятать

Пред.

Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 71

    TopList