Войти

Показать полную графическую версию : [решено] Установка глобального HotKey


giv5dot26
03-02-2011, 06:35
Привет всем. Нужно: установить сочетания клавиш глобальное. Делаю так:

[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);

private const int MOD_ALT = 0x1;
private const int MOD_CONTROL = 0x2;
private const int MOD_SHIFT = 0x4;
private const int MOD_WIN = 0x8;
private const int WM_HOTKEY = 0x312;

public Form()
{
RegisterHotKey(this.Handle, 42, MOD_WIN, (int)Keys.Escape);
}

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_HOTKEY)
{
switch (m.WParam.ToInt32())
{
case 42:
if (this.Visible == false)
{
this.Show();
this.Tray.Visible = false;
this.ShowInTaskbar = true;
}
break;
}
}
}


Но ничего не происходит когда я нажимаю комбинацию клавишь. Ставлю точку останова на строке if (m.Msg == WM_HOTKEY) но программа туда даже не заходит. Что я сделал не так?

Delirium
03-02-2011, 08:24
Глобальная клавиша для чего нужна, для того, чтобы на форме в любом месте нажать, например, F3 и открылось какое то меню или действие? Если да, то все гораздо проще:
1. Выставляем у формы свойство KeyPreview=true;
2. Вставляем обработчик на KeyDown:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.F1)
{
//тут код после нажатия нужной клавиши
}
}

giv5dot26
03-02-2011, 08:39
Нет без привязки к форме. Все нужно чтобы вызывать свернутое окно.

Delirium
03-02-2011, 08:48
ну хотя бы на base.WndProc(ref m); он доходит? Или просто не заходит в функцию?

giv5dot26
03-02-2011, 08:57
Да доходит не срабатывает именно условие как будто клавишу и не нажимали вовсе. if (m.Msg == WM_HOTKEY) вот это место "пролетает".

Admiral
04-02-2011, 02:22
giv5dot26 приведённый код неполон. Но должен работать.
Первоначально хотел предложить вызов RegisterHotKey перенести из конструктора формы (подозрение на не валидный this.Handle) куда-нибудь в OnLoad (событие наступает сразу после первого отображения формы). Но нет, работать будет и там (this.Handle валидный в обоих случаях).
using System;
using System.Drawing;
using System.Windows.Forms;

using System.Runtime.InteropServices; //for DllImport

class Form1 : Form
{
[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);
private const int MOD_WIN = 0x8;
private const int WM_HOTKEY = 0x312;

public static void Main()
{
Application.Run(new Form1());
}
public Form1()
{
RegisterHotKey(this.Handle, 42, MOD_WIN, (int)Keys.Escape);
}
protected override void OnLoad(EventArgs ea)
{
base.OnLoad(ea);
//RegisterHotKey(this.Handle, 42, MOD_WIN, (int)Keys.Escape);
}
protected override void WndProc(ref Message msg)
{
base.WndProc(ref msg);
if (msg.Msg == WM_HOTKEY)
{
switch (msg.WParam.ToInt32())
{
case 42:
MessageBox.Show("Hello there");
break;
default:
MessageBox.Show("Hello stranger");
break;
}
}
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs cea)
{
base.OnClosing(cea);
UnregisterHotKey(this.Handle, 42);
}
}
Есть реакция на сочетание Win+Esc.
В примере название экземпляра класса Form1, а не Form (что бы не было путаницы с именем класса).

giv5dot26
04-02-2011, 05:28
В общем приведенный Вами код работает, но вот стоит форму свернуть в трей как реакция на нажатие прекращается и вот это уже не проходит
if (msg.Msg == WM_HOTKEY)
{
switch (msg.WParam.ToInt32())
{
case 42:
MessageBox.Show("Hello there");
break;
default:
MessageBox.Show("Hello stranger");
break;
}
}
Почему как считаете?

Admiral
05-02-2011, 15:48
giv5dot26, в предыдущем посте пропустил слово - приведённый выше код неполон. Иными словами, в первом посте приводится вполне рабочий код (на его основе полный вариант под споллером в 6 посте), однако не уточнен способ сворачивания в трей.
Что касается трея, то как-то не доводилось его программировать, но есть предположение создать две формы, первая (невидимая) пускай принимает сообщения, вторая получает их от первой, будучи свёрнута в трей.

Здесь WndProc doesn't receive hotkey message when minimized (http://www.dreamincode.net/forums/topic/189528-wndproc-doesnt-receive-hotkey-message-when-minimized/) человек пришёл к выводу, что виной всему this.ShowInTaskbar = false; после которого описатель приложения становится не валидным.

giv5dot26
11-02-2011, 07:33
Да так и есть. Если не использовать this.ShowInTaskbar = false то все работает как надо. Все нормально.




© OSzone.net 2001-2012