Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.91/22: Рейтинг темы: голосов - 22, средняя оценка - 4.91
 Аватар для DimanRu
721 / 712 / 168
Регистрация: 15.06.2011
Сообщений: 1,704

Отлов нажатия NumLock и управление им

28.05.2012, 11:43. Показов 4645. Ответов 27
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здраствуйте! Недавно написал программу - калькулятор. Хотел осуществить включение\выключение по нажатию NumLock. Нашел даже какой-то
способ


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern short GetAsyncKeyState(int vkey);
 
...
 
private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
    while (true)
    {
        short key2 = GetAsyncKeyState(0x90); // А этот клавиши NumLock 
 
        if (key2 != 0)
        {
            if (this.Visible)
            {
                this.Invoke(new MethodInvoker(() => this.Visible = false));
                this.Invoke(new MethodInvoker(() => this.TopMost = true));
            }
            else
                this.Invoke(new MethodInvoker(() => this.Visible = true));
        }
    }
}
. Однако данный способ во-первых, через раз отрывает программу, и при показе она прорисовывается несколько раз, во-вторых, при показанной программе NumLock может оказаться выключенным, и набрать что-либо в поле калькулятора использую доп. цифровую клавиатуру становиться невозможным, а именно на это программа и ореинтирована.

Подскажите как осуществить такое, или где можно почитать?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
28.05.2012, 11:43
Ответы с готовыми решениями:

Отлов нажатия кнопки submit и блокировка последующего нажатия
Привет всем! Нужен код, который способствует блокировке нажатия кнопки после одного нажатия на нее. Спасибо. Добавлено через 54...

Управление клавишами и индикаторами CapsLock, ScrLock, NumLock
Добрый всем день. Возникла необходимость программно управлять режимами клавиатуры (имеется ввиду капслок, намлок и скроллок). Грубо говоря...

Программное управление NumLock \ CapsLock \ Sroll Lock
Проблема следующая - есть устройство которое эмитируется под клавиатуру и управляется оно с помощью сигналов о включении светодиодов ...

27
13 / 13 / 4
Регистрация: 14.04.2010
Сообщений: 52
28.05.2012, 14:08
эм... Глупый вопрос, может, но это Windows Forms?..
0
 Аватар для DimanRu
721 / 712 / 168
Регистрация: 15.06.2011
Сообщений: 1,704
28.05.2012, 14:09  [ТС]
Да, это WinForm.
0
13 / 13 / 4
Регистрация: 14.04.2010
Сообщений: 52
28.05.2012, 14:11
Form Events => PreviewKeyDown..
e.Keys = Key.NumLock.. мб что-то такое будет)
0
 Аватар для DimanRu
721 / 712 / 168
Регистрация: 15.06.2011
Сообщений: 1,704
28.05.2012, 14:13  [ТС]
Нет-нет вы не поняли. Отлавливать нажатие клавиши нужно независимо от отго, какя форма в данный момент активна. Например я работаю в Excel'e vyt понадобилось что-то посчитать. Я нажал NumLock - появился мой калькулятор, ввел выражение нажал Enter - он посчитал. Нажал NumLock ещё раз - калькулятор скрылся.

P.S. Нужно что-то вроде глобального хука клавиатуры.
0
Футболист
 Аватар для Goal
533 / 435 / 142
Регистрация: 31.10.2011
Сообщений: 1,010
28.05.2012, 14:42
challenge accepted^^

Добавлено через 1 минуту
Вот работающий пример, сам для себя делал, работает 100%, ща изменю что б ты понял, где что и как

Добавлено через 1 минуту
Код(Program.cs)
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
static class Program
    {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;
 
        [STAThread]
        static void Main()
        {
            _hookID = SetHook(_proc);
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
            UnhookWindowsHookEx(_hookID);
        }
 
        private static IntPtr SetHook(LowLevelKeyboardProc proc)//hook
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
            }
        }
 
        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
        static public String DopBtn = "null";
        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
 
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                //MessageBox.Show(( (Keys)vkCode ).ToString(), "Goalchts.at.ua"); // Вот сними комментарии к етой сроке, нажми на кепс лук, и увидиш какая клавиша была нажата!
                #region press
                    #region dop
                    if (vkCode == 162)
                    {
                        DopBtn = "LControlKey";
                    }
                    if (vkCode == 160)
                    {
                        DopBtn = "LShiftKey";
                    }
                    #endregion
                    if (TestKeys.Form1.DoMas.Length > 1)//activate macro
                        for (int i = 0; i < TestKeys.Form1.DoMas.Length-1; i++)
                            if (((Keys)vkCode).ToString() == TestKeys.Form1.DoMas[i].StartKey2 && DopBtn.Equals(TestKeys.Form1.DoMas[i].StartKey1))
                            {
                                DopBtn = "end";
                                TestKeys.Form1.DoMas[i].PerformKeys(TestKeys.Form1.DoMas[i]);
                                DopBtn = "end";
                            }
                    #region clear_dopBtn
                    if (!((DopBtn.Equals("LControlKey") && !DopBtn.Equals("LShiftKey")) || (!DopBtn.Equals("LControlKey") && DopBtn.Equals("LShiftKey"))))
                    {
                        DopBtn = "xxx";
                    }
                    #endregion
 
                #endregion
 
 
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
 
        #region DLLimport
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
            IntPtr wParam, IntPtr lParam);
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
        #endregion
    }


Добавлено через 56 секунд
Сори что со не переделал, стало лень
если еще не разобрался тут идет имитация нажатия сочетания клавиш(к примеру шифт+ф1)
1
 Аватар для DimanRu
721 / 712 / 168
Регистрация: 15.06.2011
Сообщений: 1,704
28.05.2012, 14:42  [ТС]
Goal, Спасибо за пример, но не могли бы вы прокомментровать код, хоят ы в главных, основных местах?
0
Футболист
 Аватар для Goal
533 / 435 / 142
Регистрация: 31.10.2011
Сообщений: 1,010
28.05.2012, 14:43
я сейчас иду в футбол играть, вечером если подождеш, хорошо?
1
 Аватар для DimanRu
721 / 712 / 168
Регистрация: 15.06.2011
Сообщений: 1,704
28.05.2012, 14:44  [ТС]
Хорошо, заранее спасибо! Удачной игры!
1
Футболист
 Аватар для Goal
533 / 435 / 142
Регистрация: 31.10.2011
Сообщений: 1,010
28.05.2012, 14:45
советую пока что почитать документацию в интернете о тех функциях, что находяться в DLL import.
1
 Аватар для DimanRu
721 / 712 / 168
Регистрация: 15.06.2011
Сообщений: 1,704
28.05.2012, 14:46  [ТС]
Спасибо, почитаю.
0
Футболист
 Аватар для Goal
533 / 435 / 142
Регистрация: 31.10.2011
Сообщений: 1,010
28.05.2012, 15:03
Цитата Сообщение от DimanRu Посмотреть сообщение
Хорошо, заранее спасибо! Удачной игры!
спасибо..

Добавлено через 16 минут
по сути, весь код вне метода HookCallback
предназначен для правильного функционирования етого метода.
соответственно.
Метод
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
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
 
             if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)//проверка на правильность(что б потом ошибка не вылетела, такое бывает)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                MessageBox.Show(( (Keys)vkCode ).ToString(), "Goalchts.at.ua");//каждый раз будет выскакивать окно с названием нажатой клавишы(закомментировать)
                #region press
                    #region dop//установка дополнительных клавиш(контрл и шифт)
                    if (vkCode == 162)
                    {
                        DopBtn = "LControlKey";
                    }
                    if (vkCode == 160)
                    {
                        DopBtn = "LShiftKey";
                    }
                    #endregion
                    if (TestKeys.Form1.DoMas.Length > 1)//activate macro(увы ето уже мое, в каждом екземпляре класса есть переменные старта макро)
                        for (int i = 0; i < TestKeys.Form1.DoMas.Length-1; i++)
                            if (((Keys)vkCode).ToString() == TestKeys.Form1.DoMas[i].StartKey2 && DopBtn.Equals(TestKeys.Form1.DoMas[i].StartKey1))
                            {
                                DopBtn = "end";
                                TestKeys.Form1.DoMas[i].PerformKeys(TestKeys.Form1.DoMas[i]);
                                DopBtn = "end";
                            }
                    #region clear_dopBtn
                    if (!((DopBtn.Equals("LControlKey") && !DopBtn.Equals("LShiftKey")) || (!DopBtn.Equals("LControlKey") && DopBtn.Equals("LShiftKey"))))
                    {
                        DopBtn = "xxx";//очистка дополнительных клавиш
                    }
                    #endregion
 
                #endregion
 
 
            }
              return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
1
123 / 121 / 6
Регистрация: 21.12.2011
Сообщений: 348
28.05.2012, 18:39
Вот пример готовой программы для глобального хука Num Lock.
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
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
namespace TestHook {
  class Program {
    static void Main( string[] args ) {
      Application.Run( new TestHooks() );
 
      Hooks.UnHook();
    }
  }
 
  public class TestHooks : ApplicationContext {
    public TestHooks() {
      Hooks.SetHook();
    }
  }
 
  public static class Hooks {
    #region Declare WinAPI functions
      [DllImport("kernel32.dll")]
      private static extern IntPtr LoadLibrary(string lpFileName);
 
      [DllImport("user32.dll")]
      private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc callback, IntPtr hInstance, uint threadId);
      [DllImport("user32.dll")]
      private static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);
      [DllImport("user32.dll")]
      private static extern bool   UnhookWindowsHookEx(IntPtr hInstance);
    #endregion
    #region Constants
      private const int WH_KEYBOARD_LL = 13;
      private const int WH_KEYDOWN     = 0x0100;
      // код клавиши на которую ставим хук
      private const int KBD_NUM_LOCK      = 0x90;
    #endregion
 
    private delegate IntPtr KeyboardHookProc(int code, IntPtr wParam, IntPtr lParam);
    private static readonly KeyboardHookProc Proc = HookProc;
 
    private static IntPtr _hhook = IntPtr.Zero;
 
    public static void SetHook() {
      var hInstance = LoadLibrary("User32");
      _hhook = SetWindowsHookEx(WH_KEYBOARD_LL, Proc, hInstance, 0);
    }
 
    public static void UnHook() {
      UnhookWindowsHookEx(_hhook);
    }
 
    private static IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam) {
      if( (code >= 0 && wParam == (IntPtr)WH_KEYDOWN) && Marshal.ReadInt32(lParam) == KBD_NUM_LOCK ) {
        // обрабатываем нажатие нужной клавиши
        MessageBox.Show("NumLock");
      }
    
      // пробрасываем дальше
      return CallNextHookEx(_hhook, code, (int)wParam, lParam);
    }
  }
}
1
 Аватар для DimanRu
721 / 712 / 168
Регистрация: 15.06.2011
Сообщений: 1,704
29.05.2012, 12:09  [ТС]
Savvy, Спасибо. Работает, но в отдельном проекте. Как добавить это к совоему незнаю. Если вставлять это в Program.cs, то в методе Main не получается вызвать главную форму. Иначе же, незнаю как запустить Хук.

Добавлено через 11 минут
Так'c разобрался куда вставить, теперь неполучается изменять состояние формы(((
Вот код, посмотрите что не так?
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Runtime.InteropServices;
 
namespace Num__
{
    static class Program
    {
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Hooks.SetHook(); //Ставлю Хук
            Application.Run(new Form1()); //Открываю форму
        }
    }
 
    public static class Hooks
    {
        #region Declare WinAPI functions
        [DllImport("kernel32.dll")]
        private static extern IntPtr LoadLibrary(string lpFileName);
 
        [DllImport("user32.dll")]
        private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc callback, IntPtr hInstance, uint threadId);
        [DllImport("user32.dll")]
        private static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);
        [DllImport("user32.dll")]
        private static extern bool UnhookWindowsHookEx(IntPtr hInstance);
        #endregion
        #region Constants
        private const int WH_KEYBOARD_LL = 13;
        private const int WH_KEYDOWN = 0x0100;
        // код клавиши на которую ставим хук
        private const int KBD_NUM_LOCK = 0x90;
        #endregion
 
        private delegate IntPtr KeyboardHookProc(int code, IntPtr wParam, IntPtr lParam);
        private static readonly KeyboardHookProc Proc = HookProc;
 
        private static IntPtr _hhook = IntPtr.Zero;
 
        public static void SetHook()
        {
            var hInstance = LoadLibrary("User32");
            _hhook = SetWindowsHookEx(WH_KEYBOARD_LL, Proc, hInstance, 0);
        }
 
        public static void UnHook()
        {
            UnhookWindowsHookEx(_hhook);
        }
 
        private static IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam)
        {
            if ((code >= 0 && wParam == (IntPtr)WH_KEYDOWN) && Marshal.ReadInt32(lParam) == KBD_NUM_LOCK)
            {
                // обрабатываем нажатие нужной клавиши
                MessageBox.Show("NumLock");
                Form1.State(); //Пытаюсь менять состояние формы
            }
 
            // пробрасываем дальше
            return CallNextHookEx(_hhook, code, (int)wParam, lParam);
        }
    }
}
 
...
 
        static public void State() //В метоже ругается на "this", но если убрать "static" - то метод вообще не вызывается
        {
            if (this.WindowState == FormWindowState.Normal)
                this.WindowState = FormWindowState.Minimized;
            if (this.WindowState == FormWindowState.Minimized)
                this.WindowState = FormWindowState.Normal;
        }
0
123 / 121 / 6
Регистрация: 21.12.2011
Сообщений: 348
29.05.2012, 12:21
DimanRu, всё что тебе нужно это:
1. скопировать код класса Hooks и вставить его в свой проект на уровне класса формы (ну или как тебе угодно)
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
  public static class Hooks {
    #region Declare WinAPI functions
      [DllImport("kernel32.dll")]
      private static extern IntPtr LoadLibrary(string lpFileName);
 
      [DllImport("user32.dll")]
      private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc callback, IntPtr hInstance, uint threadId);
      [DllImport("user32.dll")]
      private static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);
      [DllImport("user32.dll")]
      private static extern bool   UnhookWindowsHookEx(IntPtr hInstance);
    #endregion
    #region Constants
      private const int WH_KEYBOARD_LL = 13;
      private const int WH_KEYDOWN     = 0x0100;
      // код клавиши на которую ставим хук
      private const int KBD_NUM_LOCK      = 0x90;
    #endregion
 
    private delegate IntPtr KeyboardHookProc(int code, IntPtr wParam, IntPtr lParam);
    private static readonly KeyboardHookProc Proc = HookProc;
 
    private static IntPtr _hhook = IntPtr.Zero;
 
    public static void SetHook() {
      var hInstance = LoadLibrary("User32");
      _hhook = SetWindowsHookEx(WH_KEYBOARD_LL, Proc, hInstance, 0);
    }
 
    public static void UnHook() {
      UnhookWindowsHookEx(_hhook);
    }
 
    private static IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam) {
      if( (code >= 0 && wParam == (IntPtr)WH_KEYDOWN) && Marshal.ReadInt32(lParam) == KBD_NUM_LOCK ) {
        // обрабатываем нажатие нужной клавиши
        MessageBox.Show("NumLock");
      }
    
      // пробрасываем дальше
      return CallNextHookEx(_hhook, code, (int)wParam, lParam);
    }
  }
2. Использовать метод
C#
1
      Hooks.SetHook();
в том месте где тебе необходимо (по сути если твое приложение будет висеть в трее, то SetHook нужно вызывать в конструкторе формы).

З.Ы.: если хук нужно снимать\ставить (по нажатию button например) то используй в паре SetHook и UnHook. Если недостаточно понятно объяснил, кинь свой код я помогу встроить. Кстати, я этот класс сейчас переписываю.

Добавлено через 11 минут
DimanRu, чисто логическая ошибка.
ты проверяешь если форма развернута - то свернуть, НО дальше сразу проверяешь если форма СВЕРНУТА - то развернуть)
лучше сделать так
C#
1
2
3
4
5
6
7
8
switch( WindowState ) {
    case FormWindowState.Normal:
        WindowState = FormWindowState.Minimized;
        break;
    case FormWindowState.Minimized:
        WindowState = FormWindowState.Normal;
        break;
}
и да, статический метод делать действительно не надо.
1
 Аватар для DimanRu
721 / 712 / 168
Регистрация: 15.06.2011
Сообщений: 1,704
29.05.2012, 12:22  [ТС]
Очень было бы неплохо, если бы вы прокомментировали код, яхочу понять как все работает, что бы потом самому ставить хуки, а не лезть опять на форум. Вставил как вы сказали в файл формы, но опять таже ошибка.
Тут
C#
1
2
3
4
5
6
7
8
9
10
11
12
        private static IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam)
        {
            if ((code >= 0 && wParam == (IntPtr)WH_KEYDOWN) && Marshal.ReadInt32(lParam) == KBD_NUM_LOCK)
            {
                // обрабатываем нажатие нужной клавиши
                MessageBox.Show("NumLock");
                Form1.State(); //Вот тут!
            }
 
            // пробрасываем дальше
            return CallNextHookEx(_hhook, code, (int)wParam, lParam);
        }
, по нажатию NumLock я вызываю
метод
C#
1
2
3
4
5
6
7
8
9
10
11
12
        public void State()
        {
            switch( WindowState ) 
            { //Изменил - не помогает, нужна ссылка на нестатический...
                case FormWindowState.Normal:
                    WindowState = FormWindowState.Minimized;
                    break;
                case FormWindowState.Minimized:
                    WindowState = FormWindowState.Normal;
                    break;
            }
        }
, который изменяем текущее состояние моей формы. 2 ошибки: либо нужна ссылка на нестатический метод, либо, если добавить статик - ругается на this в методе.
0
123 / 121 / 6
Регистрация: 21.12.2011
Сообщений: 348
29.05.2012, 12:28
DimanRu, смотри в чем проблема. this - указатель на ТЕКУЩИЙ экземпляр класса. Иначе говоря, метод State вообще не должен находится в классе Hooks, т.к. этот метод напрямую зависит от состояния формы. В таком варианте тебе статический класс не подходит, т.к. ты хочешь обратной связи от хука, соответственно надо допилить этот класс с событиями, на которое ты сможешь подписаться и реагировать на нажатие как захочешь. Я в данное время как раз переписываю класс который будет не статическим но более дружелюбным и прозрачным в плане его использования. Если тебе не срочно, то подожди часа 2-3 я выложу новую версию)
1
 Аватар для DimanRu
721 / 712 / 168
Регистрация: 15.06.2011
Сообщений: 1,704
29.05.2012, 12:29  [ТС]
Метод State у мея находится в классе формы. Поэтому и спрашиваю)

Вот
код

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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;
 
namespace Num__
{
    public partial class Form1 : Form
    {
        double c;
        bool status = false;
        bool stat = true;
 
        public Form1()
        {
            InitializeComponent();
 
            Hooks.SetHook();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            string inString = textBox1.Text;
            if (Checked(inString))
            {
                string outStr = GetExp(inString);
                textBox1.Text += " = " + Reshenie(outStr);
                status = true;
            }
        }
 
        static private bool Checked(string str)
        {
            int sum = 0;
 
            foreach (char ch in str)
            {
                if (ch == '(')
                    sum++;
                if (ch == ')')
                    sum--;
            }
 
            if (sum != 0 || IsOperator(str[0]) || IsOperator(str[str.Length - 1]))
            {
                MessageBox.Show("Error!");
                return false;
            }
            return true;
        }
 
        private double Reshenie(string str)
        {
            Stack<double> resh = new Stack<double>();
 
            for (int i = 0; i < str.Length; i++)
            {
                if (Char.IsDigit(str[i]))
                {
                    string a = "";
 
                    while (!IsDelimetr(str[i])) //Пока не разделитель
                    {
                        a += str[i]; //Добаляем
                        i++;
                        if (i == str.Length) break;
                    }
                    resh.Push(double.Parse(a));
                    i--;
                    continue;
                }
                else if (IsOperator(str[i]))
                {
                    double a = resh.Pop();
                    double b = resh.Pop();
                    switch (str[i])
                    {
 
                        case '+': c = b + a; break;
                        case '-': c = b - a; break;
                        case '*': c = b * a; break;
                        case '/': c = b / a; break;
                        case '^': c = double.Parse(Math.Pow(double.Parse(b.ToString()), double.Parse(a.ToString())).ToString()); break;
                    }
                    resh.Push(c);
                }
            }
 
            return resh.Peek();
        }
 
        private string GetExp(string str)
        {
            string outString = "";
            Stack<char> operStack = new Stack<char>();
 
            for (int i = 0; i < str.Length; i++)
            {
                if (str[i] == ' ') //Если пробел
                    continue; //пропускаем
 
                if (Char.IsDigit(str[i])) //Если число
                {
                    while (!IsDelimetr(str[i])) //Пока не разделитель
                    {
                        outString += str[i]; //Добаляем
                        i++;
                        if (i == str.Length) break;
                    }
                    outString += " ";
                    i--;
                    continue;
                }
 
                if (IsOperator(str[i]))
                {
                    if (operStack.Count > 0)
                        if (GetPriority(str[i]) <= GetPriority(operStack.Peek()))
                            outString += operStack.Pop().ToString() + " ";
 
                    operStack.Push(char.Parse(str[i].ToString()));
                }
 
                if (str[i] == '(')
                    operStack.Push(str[i]);
 
                if (str[i] == ')')
                {
                    char s = operStack.Pop();
 
                    while (s != '(')
                    {
                        outString += s.ToString() + ' '; //Тут была ошибка, вместо операторов добавлялась цифра (75)
                        s = operStack.Pop();
                    }
                }
            }
 
            while (operStack.Count > 0)
                outString += operStack.Pop() + " ";
 
            return outString;
        }
 
        static private bool IsOperator(char с)
        {
            if (("+-/*^".IndexOf(с) != -1))
                return true;
            return false;
        }
 
        private byte GetPriority(char s)
        {
            switch (s)
            {
                case '(':
                    return 0;
                case ')':
                    return 1;
                case '+':
                    return 2;
                case '-':
                    return 3;
                case '*':
                    return 4;
                case '/':
                    return 4;
                case '^':
                    return 5;
                default:
                    return 6;
            }
        }
 
        static private bool IsDelimetr(char c)
        {
            if ((" +-/*^()=".IndexOf(c) != -1))
                return true;
            return false;
        }
 
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (status)
            {
                textBox1.Clear();
                status = false;
            }
        }
 
        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (this.Visible)
            {
                this.Visible = false;
            }
            else 
            {
                this.Visible = true;
            }
        }
 
        private void exitButton_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
 
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            notifyIcon1.Dispose();
        }
 
        public void State()
        {
            switch (WindowsState)
            {
                case FormWindowState.Normal:
                    WindowState = FormWindowState.Minimized;
                    break;
                case FormWindowState.Minimized:
                    WindowState = FormWindowState.Normal;
                    break;
            }
        }
    }
 
    #region Hook
    public static class Hooks
    {
        #region Declare WinAPI functions
        [DllImport("kernel32.dll")]
        private static extern IntPtr LoadLibrary(string lpFileName);
 
        [DllImport("user32.dll")]
        private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardHookProc callback, IntPtr hInstance, uint threadId);
        [DllImport("user32.dll")]
        private static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);
        [DllImport("user32.dll")]
        private static extern bool UnhookWindowsHookEx(IntPtr hInstance);
        #endregion
        #region Constants
        private const int WH_KEYBOARD_LL = 13;
        private const int WH_KEYDOWN = 0x0100;
        // код клавиши на которую ставим хук
        private const int KBD_NUM_LOCK = 0x90;
        #endregion
 
        private delegate IntPtr KeyboardHookProc(int code, IntPtr wParam, IntPtr lParam);
        private static readonly KeyboardHookProc Proc = HookProc;
 
        private static IntPtr _hhook = IntPtr.Zero;
 
        public static void SetHook()
        {
            var hInstance = LoadLibrary("User32");
            _hhook = SetWindowsHookEx(WH_KEYBOARD_LL, Proc, hInstance, 0);
        }
 
        public static void UnHook()
        {
            UnhookWindowsHookEx(_hhook);
        }
 
        private static IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam)
        {
            if ((code >= 0 && wParam == (IntPtr)WH_KEYDOWN) && Marshal.ReadInt32(lParam) == KBD_NUM_LOCK)
            {
                // обрабатываем нажатие нужной клавиши
                MessageBox.Show("NumLock");
                Form1.State();
            }
 
            // пробрасываем дальше
            return CallNextHookEx(_hhook, code, (int)wParam, lParam);
        }
    }
 
    #endregion Hook 
 
}
, на всякий случай.

Я тут кстати подумал, может прошлое мое решение, с woker'om неработало из-зи неправильной логики при свертывании?! И ещё вспомнил что мне ещё нужно будет включать NumLock, если он выключен.
0
123 / 121 / 6
Регистрация: 21.12.2011
Сообщений: 348
29.05.2012, 12:34
DimanRu, я понял в чем проблема. Тут можно намудрить, но оно того не стоит. В новой версии класса будет намного проще с обработкой нажатий "хукнутой" клавиши. Так что лучше подожди.
1
 Аватар для DimanRu
721 / 712 / 168
Регистрация: 15.06.2011
Сообщений: 1,704
29.05.2012, 12:35  [ТС]
Спасибо, подожду. Вот нашел на форуме:
C#
1
2
3
4
5
6
7
private void butNumLock_Click(object sender, EventArgs e) 
{ 
// Включаем или выключаем индикатор Num Lock 
keybd_event(VK_NUMLOCK, 0x45, KEYEVENTF_EXTENDEDKEY, (UlntPtrH); 
keybd_event(VK_NUMLOCK, 0x45, 
KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UlntPtrH); 
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
29.05.2012, 12:35
Помогаю со студенческими работами здесь

Имитация нажатия клавиши (цифры) не работает, если включен NumLock
Всем привет, прошу помочь, необходимо чтобы программа сама имитировала нажатие клавиши 9 без всякого вмешательства, если включен Num Lock,...

Отлов нажатия клавиш
Доброго времени суток! Стоит задача при нажатии оперделенной клавиши выполнить действие. Код: #include &lt;windows.h&gt; ...

Отлов нажатия клавиш
Хочу создать класс, который будет мне говорить, какая клавиша нажата в данный момент. Как это сделать?

Отлов нажатия кнопки
Приветствую, идея такая. Из базы данных запрашивается содержимое таблицы и выводится на экран. Для каждой строчки создается кнопка с...

Отлов нажатия кнопки
Интересует такой вопрос. На устройстве под win CE 6.0 есть кнопка, и нужно отлавливать момент, когда она нажата. То есть пока мы жмем...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru