Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
MGMKLML
0 / 0 / 0
Регистрация: 25.10.2015
Сообщений: 11
1

Автоматическая смена раскладки клавиатуры не работает

09.07.2018, 12:52. Просмотров 379. Ответов 10

Здравствуйте!

Мне нужно сделать так, чтобы при запуске приложения автоматически менялась раскладка клавиатуры на английский язык. Создал простое консольное приложение, чтобы протестить работоспособность. И вот не получается.

Импортировал System.Windows.Forms (add reference).

Приложение состоит всего лишь из одной строки:
C#
1
InputLanguage.CurrentInputLanguage = InputLanguage.FromCulture(new CultureInfo("en-US"));
Однако в результате смена раскладки не происходит. Снизу как горело "РУС", так и горит.

Что я делаю не так?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.07.2018, 12:52
Ответы с готовыми решениями:

Смена раскладки клавиатуры
здравствуйте. подскажите пожалуйста можно ли с помощью С-шарп менять раскладки клавиатуры мне...

Смена раскладки клавиатуры
Нашел линк на киберфорум, но он оказался битым. Ни у кого нет кусочка кода с программным изменение...

Смена раскладки на русскую при установке фокуса на textbox
Добрый день! Подскажите, как принудительно менять раскладку на русскую каждый раз, когда...

Удаление раскладки клавиатуры
Сделал с помощю LoadKeyboardLayout("00000408", 1); греческую раскладку и она появляется и при...

Автоматический переключатель раскладки клавиатуры
нужно написать программу "автоматический переключатель раскладки клавиатуры" подскажите пожалуйста...

10
_REVOLUTION_
15 / 14 / 9
Регистрация: 21.11.2015
Сообщений: 86
09.07.2018, 19:09 2
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
using System.Runtime.InteropServices;
 
namespace ConsoleApp1
{
    class Program
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();
        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern bool PostMessage(IntPtr hWnd, uint Msg, Int32 wParam, Int32 lParam);
        static void Main(string[] args)
        {
            Console.ReadLine();
            PostMessage(GetForegroundWindow(), 0x0050, 2, 0);
            Console.ReadLine();
            PostMessage(GetForegroundWindow(), 0x0050, 2, 0);
        }
    }
}
0
MGMKLML
0 / 0 / 0
Регистрация: 25.10.2015
Сообщений: 11
09.07.2018, 20:21  [ТС] 3
_REVOLUTION_, Благодарю за ответ. Можно, пожалуйста, пояснить данный код, потому что я не совсем разбираюсь, что здесь происходит и каким образом собственно переключение клавиатуры происходит?
0
_REVOLUTION_
15 / 14 / 9
Регистрация: 21.11.2015
Сообщений: 86
10.07.2018, 06:06 4
Вообще дело в том, что в Винде как таковой "глобальной" смены раскладки клавиатуры не существует. Она у каждого приложения своя, а если быть точнее, то может быть своя у каждого потока. Свойство CurrentInputLanguage меняет раскладку клавиатуры в текущем потоке
Возвращает или задает язык ввода для текущего потока.
Цитата Сообщение от MGMKLML Посмотреть сообщение
в результате смена раскладки не происходит
и смена раскладки происходит, просто вы скорее всего не успеваете это заметить.
Функция 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.
Отправляет "сообщение" заданному приложению. Больше информации в документации.
Функция GetForegroundWindow получает хэндл активного в данный момент окна. Больше инфы все так же в документации.
0x0050 в данном случае соответствует константе "WM_INPUTLANGCHANGEREQUEST", это и есть отправляемое "сообщение". Посмотреть константы и их значения можно тут.
Третим параметром в PostMessage передаем, насколько я помню, параметр, который отвечает за выбор языков, определенных в системе.
И четвертым параметром передаем, насколько я помню, параметр, который отвечает за смену раскладки на следующую, которая определена в системе.
В документации к каждой функции можно найти все что необходимо, нужно лишь ее почитать

Добавлено через 2 минуты
И осторожней с GetForegroundWindow, она возвращает текущее активное окно, если вам нужно конкретно окно вашего приложения, то указывать нужно именно его
0
10.07.2018, 06:06
MGMKLML
0 / 0 / 0
Регистрация: 25.10.2015
Сообщений: 11
10.07.2018, 10:23  [ТС] 5
_REVOLUTION_, Хорошо, понял, спасибо за ответ. Буду разбираться.
0
ATop
103 / 9 / 6
Регистрация: 06.07.2013
Сообщений: 212
Завершенные тесты: 2
10.07.2018, 19:45 6
Решал подобную проблему, это код из одного моего проекта, с помощью него можно переключать раскладку клавиатуры передавая код Keybord Layout, т.е. не обязательно пользователю иметь в раскладках китайский чтобы на него переключить ввод (список всех кодов):

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
        #region SwitchKeyboardLayouts
 
        private enum KeyboardLayoutFlags : uint
        {
            KLF_ACTIVATE = 0x00000001,
            KLF_SETFORPROCESS = 0x00000100
        }
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern uint ActivateKeyboardLayout(uint hkl, KeyboardLayoutFlags Flags);
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr GetForegroundWindow();
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern ushort GetKeyboardLayout([In] int idThread);
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern int GetWindowThreadProcessId(
            [In] IntPtr hWnd,
            [Out] [Optional] IntPtr lpdwProcessId);
 
        private ushort GetKeyboardLayout()
        {
            return GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero));
        }
 
        #endregion SwitchKeyboardLayouts
Пример использования:

C#
1
2
3
4
    currentKeyboardLayout = GetKeyboardLayout();
    ActivateKeyboardLayout(1033, KeyboardLayoutFlags.KLF_SETFORPROCESS);
    //...
   ActivateKeyboardLayout(currentKeyboardLayout, KeyboardLayoutFlags.KLF_SETFORPROCESS);
0
MGMKLML
0 / 0 / 0
Регистрация: 25.10.2015
Сообщений: 11
10.07.2018, 23:34  [ТС] 7
Цитата Сообщение от ATop Посмотреть сообщение
[DllImport("user32.dll", SetLastError = true)]
А как мне правильно сделать DllImport? C# подчеркивает красным.
Вопрос снят - забыл добавить
C#
1
using System.Runtime.InteropServices;
Добавлено через 16 минут
А можно, пожалуйста, объяснить, что я делаю не так?

Я организовал это в простое консольное приложение:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
using System;
using System.Runtime.InteropServices;
 
namespace SwitchKbrdLayout
{
    class Program
    {
        #region SwitchKeyboardLayouts
        private enum KeyboardLayoutFlags : uint
        {
            KLF_ACTIVATE = 0x00000001,
            KLF_SETFORPROCESS = 0x00000100
        }
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern uint ActivateKeyboardLayout(uint hkl, KeyboardLayoutFlags Flags);
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr GetForegroundWindow();
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern ushort GetKeyboardLayout([In] int idThread);
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern int GetWindowThreadProcessId(
            [In] IntPtr hWnd,
            [Out] [Optional] IntPtr lpdwProcessId);
 
        private ushort GetKeyboardLayout()
        {
            return GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero));
        }
        #endregion SwitchKeyboardLayouts
 
        static void Main(string[] args)
        {
            ActivateKeyboardLayout(1049, KeyboardLayoutFlags.KLF_SETFORPROCESS);
            Console.ReadKey();
        }
    }
}
И тем не менее, если перед запуском у меня раскладка ENG, то после компиляции она в РУС не превращается

Добавлено через 3 минуты
Видимо, это как раз отсылка к тому, что нужно привязаться к процессу, чтобы изменить раскладку. Но тогда такой момент интересует. Как мне выполнить эту привязку? Вот я, допустим, сижу себе, открываю рабочий стол, приложения (не процессы) не запущены, просто нажимаю Shift + Alt, и раскладка меняется. К какому тогда процессу это привязка?
0
ATop
103 / 9 / 6
Регистрация: 06.07.2013
Сообщений: 212
Завершенные тесты: 2
10.07.2018, 23:54 8
Цитата Сообщение от MGMKLML Посмотреть сообщение
И тем не менее, если перед запуском у меня раскладка ENG, то после компиляции она в РУС не превращается
Вам ответил на это предыдущий каментатор. В Windows раскладка меняется на конкретное окно. Вы запускаете свое консольное приложение, оно становится активным, программа меняет раскладку в окне консоли и завершает работу.

Добавлено через 2 минуты
Цитата Сообщение от MGMKLML Посмотреть сообщение
просто нажимаю Shift + Alt, и раскладка меняется
На сколько я знаю эту раскладку программно изменить нельзя. Если вам нужно именно это, можете переключать раскладку эмулируя нажатие сочетания клавиш, к примеру при помощи библиотеки AutoitX.

Добавлено через 13 минут
Да и кстати, в консоли нельзя переключить раскладку этим способом. У консоли нет окна, из-за этого способ работать не будит. Создайте WPF приложение или WinForms и проверьте что все работает если хотите.
0
ATop
103 / 9 / 6
Регистрация: 06.07.2013
Сообщений: 212
Завершенные тесты: 2
11.07.2018, 00:02 9
Скриншот и код примера:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;
using System.Runtime.InteropServices;
using System.Windows;
 
namespace WpfApp1
{
    /// <summary>
    ///     Логика взаимодействия для MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
 
        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            var currentKeyboardLayout = GetKeyboardLayout();
 
            ActivateKeyboardLayout(1033, KeyboardLayoutFlags.KLF_SETFORPROCESS);
            Console.WriteLine(currentKeyboardLayout);
        }
 
        #region SwitchKeyboardLayouts
 
        private enum KeyboardLayoutFlags : uint
        {
            KLF_ACTIVATE = 0x00000001,
            KLF_SETFORPROCESS = 0x00000100
        }
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern uint ActivateKeyboardLayout(uint hkl, KeyboardLayoutFlags Flags);
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr GetForegroundWindow();
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern ushort GetKeyboardLayout([In] int idThread);
 
        private static ushort GetKeyboardLayout()
        {
            return GetKeyboardLayout(GetWindowThreadProcessId(GetForegroundWindow(), IntPtr.Zero));
        }
 
        [DllImport("user32.dll", SetLastError = true)]
        private static extern int GetWindowThreadProcessId(
            [In] IntPtr hWnd,
            [Out] [Optional] IntPtr lpdwProcessId);
 
        #endregion SwitchKeyboardLayouts
    }
}
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="242.069" Width="436.897">
    <Grid>
        <StackPanel>
            <TextBox Name="tb" Height="159" FontSize="20"></TextBox>
            <Button Name="Button1" Height="50" Click="Button1_Click">Нажми меня</Button>
        </StackPanel>
    </Grid>
</Window>
0
Миниатюры
Автоматическая смена раскладки клавиатуры не работает  
ATop
103 / 9 / 6
Регистрация: 06.07.2013
Сообщений: 212
Завершенные тесты: 2
11.07.2018, 00:06 10
Цитата Сообщение от MGMKLML Посмотреть сообщение
Как мне выполнить эту привязку?
Вам нужно найти нужный процесс и сделать его главное окно активным, на форуме это уже обсуждали. Через Post сообщение думаю можно менять раскладку и в не активных окнах, пример вам уже давали.
0
MGMKLML
0 / 0 / 0
Регистрация: 25.10.2015
Сообщений: 11
11.07.2018, 01:33  [ТС] 11
Да, спасибо большое, теперь мне понятно все. Я просто думал, что нажатие shift + alt можно эмулировать не конкретно эмуляцией сочетания клавиш, а просто переключив какую-то системную настройку. Оказалось, я был неправ.

Пример с формами видел в интернете, это и насторожило сначала. Теперь же все ясно, почему

Всем спасибо за комментарии и объяснения.
0
11.07.2018, 01:33
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.07.2018, 01:33

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

Как отловить смену раскладки клавиатуры?
Нужно на форме вывести значок с текущей раскладкой клавиатуры. В Net есть событие...

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


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru