Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > глобальные горячие клавиши


Автор: AGENTxXx 2.2.2010, 17:53
Добрый день! Задача: создать глобальные горячие клавиши для моей программы, т.е. чтобы работая в другой проге и нажимая сочитание клавишь, моя прога отвечала на это (если конечно они зарезервированы). Я думаю что все это реализуется с помщью хуков (хотя очень надеюсь что это гораздо проще). Хотел бы чтобы подсказали оптимальный алгоритм по решению этой задачи. Сам это реализовать могу, но не считаю свой алгоритм минимальным (к процессору будет обращение частое). Кто ни будь может подсказать как это сделать оптимально?

Автор: AGENTxXx 2.2.2010, 23:22
Для тех, кому это интересно:
Код

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace GlobalHotKeysExperiments
{
    
    public partial class Form1 : Form
    {

        public const int MOD_ALT = 0x1;
        public const int MOD_CONTROL = 0x2;
        public const int MOD_SHIFT = 0x4;
        public const int MOD_WIN = 0x8;
        
        [DllImport("User32.dll")]
        public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);

        [DllImport("User32.dll")]
        public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

        [DllImport("kernel32.dll")]
        public static extern Int16 GlobalAddAtom(string name);

        [DllImport("kernel32.dll")]
        public static extern Int16 GlobalDeleteAtom(Int16 nAtom);

        Int16 atom = GlobalAddAtom("PFight");

        public Form1()
        {
            bool state = RegisterHotKey(this.Handle, atom, MOD_SHIFT|MOD_ALT, (uint)Keys.R);
            InitializeComponent();
            this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);

        }

        void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnregisterHotKey(this.Handle, atom);
            GlobalDeleteAtom(atom);
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x0312 && m.WParam.ToString() == atom.ToString())
            {
                MessageBox.Show("Yahooo!");
            }
            base.WndProc(ref m);
        }
    }
}

Автор: WolfTheGrey 4.2.2010, 16:10
А эти горячие клавищи возможно реализовать в среде WPF не прибегая к интеграции с WinForms ????

Автор: AGENTxXx 4.2.2010, 18:46
Знаю что можно их использовать и в консольных приложениях. С WPF как то не сталкивался. Да и не знаю для чего это, но думаю наверное что то с глобальными сетями связанно

Автор: AGENTxXx 7.2.2010, 16:38
Ребят, может кто то сталкивался с такой проблемой: реализовал и глобальные клавиши (как видите выше код). Загвоздка в том, чтобы теперь пользователь непосредственно смог реализовать и назначить их на свой вкус. т.е. есть у меня контрол специальный, нажимаешь там нужные клавиши и он выдает например такую строку: Control, Shift + W. а код установки:
Код

public const int MOD_ALT = 0x1;
        public const int MOD_CONTROL = 0x2;
        public const int MOD_SHIFT = 0x4;
        public const int MOD_WIN = 0x8;
        
        [DllImport("User32.dll")]
        public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);

Проблема в обращении к функции RegisterHotKey. Например, я преобразовал Control, Shift + W, в "MOD_CONTROL | MOD_SHIFT", т.е как бы все выглядит нормально:
Код

 bool state = RegisterHotKey(this.Handle, atom, "MOD_ALT | MOD_SHIFT", (uint)Keys.W);

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

public void hotkey()
        {
            str = hkControl1.Text;
            strarray = str.Split(new char(), ',');
            r = strarray.Length;
            if (r==1)
            {
                strarray = null;
                strarray = str.Split(new char(), ' ');
                switch (strarray[0])
                {
                    case "Shift":
                        m[0] = 0x4;
                        break;
                    case "Control":
                        m[0] = 0x2;
                        break;
                    case "Alt":
                        m[0] = 0x1;
                        break;
                }
            }

а использовать какие ни будь встроенные возможности. Например, в php и ActionScript 2.0 (кто не слышал этого - язык Flash) есть функция eval() которая дает это сделать. Есть ли в C# что либо подобное?

Автор: Ceiceron 7.2.2010, 19:13
Если контрол регистрации дает только текстовое представление, то парсить придется в любом случае.
Константы мдификаторов клавиш я б преобразовал в перечисление, тогда в конечную функцию и будет передавать проще.
Цитата
т.е. есть у меня контрол специальный, нажимаешь там нужные клавиши и он выдает например такую строку: Control, Shift + W

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

Автор: AGENTxXx 7.2.2010, 19:50
Контрол самодельный но не мной... он в библиотеке лежит. Так что что и как там - не знаю. А в ildasm.exe еще не умею работать, чтобы вытащить эту инфу. Фленову еще по этому поводу написал. Может он че путное скажет

Автор: nmn 7.2.2010, 20:11
Цитата(AGENTxXx @ 7.2.2010,  19:50)
А в ildasm.exe еще не умею работать, чтобы вытащить эту инфу.

RedGate Reflector

Автор: AGENTxXx 7.2.2010, 21:41
Спасибо! буду разбираться)))

Автор: CasperSC 9.9.2010, 10:44
Ну и как, решил проблему? Мне тоже нужно с горячими клавишами разобраться. Код есть, но в WPF (незнаю с этим ли связанно) он вызывает жуткие лаги при срабатывании кода запукаемого горячей клавишей.

Автор: 6atoh 9.9.2010, 12:26
Цитата(AGENTxXx @  7.2.2010,  15:38 Найти цитируемый пост)
а использовать какие ни будь встроенные возможности. Например, в php и ActionScript 2.0 (кто не слышал этого - язык Flash) есть функция eval() которая дает это сделать. Есть ли в C# что либо подобное? 


Создайте перечисление, которое будет содержать все возможные строковые значения, которые возвращает элемент управления:
Код

public enum ModKeys
{
    Alt = 0x1,
    Control = 0x2,
    Shift = 0x4,
    Win = 0x8
}


Теперь вы можете можете получить значение элемента перечисления (int) по его названию:
Код

m[0] = (int)Enum.Parse(typeof(ModKeys), strarray[0]);

Автор: starostin 27.12.2010, 22:33
Объясните мне тупом, что за Dispose в дизайнере форма1.цс? Что она делать должна и почему компилятор говорит что для неё нет соответствующего переопределения?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)