События на нажатие клавиш

Viktor Bartel
Дата: 09.05.2006 16:36:28
Добрый день,

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

Заранее вам благодарен.

--
Cordialement
Victor Bartel
darkSql
Дата: 10.05.2006 10:33:16
notify icon - трей
public sealed class HotKeyHelper: IMessageFilter
	{
		//....................for hot key.............................................
		const string USER32_DLL = "User32.dll";
		const string KERNEL32_DLL = "Kernel32.dll";
		const int WM_HOTKEY = 0x0312;
		[DllImport(USER32_DLL, SetLastError = true)]
		static extern bool RegisterHotKey(IntPtr hWnd, int id, ModifierKey fsModifiers, Keys vk);
		[DllImport(USER32_DLL, SetLastError = true)]
		static extern bool UnregisterHotKey(IntPtr hWnd, int id);
		[DllImport(KERNEL32_DLL, SetLastError = true)]
		static extern ushort GlobalAddAtom(string lpString);
		[DllImport(KERNEL32_DLL)]
		static extern ushort GlobalDeleteAtom(ushort nAtom);
		//.....................................................

		const string MSG_REGISTERED = "Горячие клавиши уже зарегистрированы, вызовите UnRegister для отмены регистрации.";
		const string MSG_UNREGISTERED = "Горячие клавиши не зарегистрированы, вызовите Register для регистрации.";
		//Делаем из нашего класса singleton
		private HotKeyHelper()
		{
		}
		public static readonly HotKeyHelper Instance = new HotKeyHelper();
		bool isRegistered;
		ushort atom;
		ModifierKey modifiers;
		Keys keyCode;
		public void Register(ModifierKey modifiers, Keys keyCode)
		{
			//Эти значения нам будут нужны в PreFilterMessage
			this.modifiers = modifiers;
			this.keyCode = keyCode;
			//Не выполнена ли уже регистрация?
			if (isRegistered)
				throw new InvalidOperationException(MSG_REGISTERED);
			//Сохраняем atom, для последующей отмены регистрации
			atom = GlobalAddAtom(Guid.NewGuid().ToString());
			if (atom == 0)
				ThrowWin32Exception();
			if (!RegisterHotKey(IntPtr.Zero, atom, modifiers, keyCode))
				ThrowWin32Exception();
			//Добавляем себя в цепочку фильтров сообщений
			Application.AddMessageFilter(this);
			isRegistered = true;
		}
		public void UnRegister()
		{
			//Не отменена ли уже регистрация?
			if (!isRegistered)
				throw new InvalidOperationException(MSG_UNREGISTERED);
			if (!UnregisterHotKey(IntPtr.Zero, atom))
				ThrowWin32Exception();
			GlobalDeleteAtom(atom);
			//Удаляем себя из цепочки фильтров сообщений
			Application.RemoveMessageFilter(this);
			isRegistered = false;
		}
		//Генерирует Win32Exception в ответ на неудачный вызов импортируемой Win32 функции
		void ThrowWin32Exception()
		{
			throw new Win32Exception(Marshal.GetLastWin32Error());
		}
		//Событие, инициируемое при обнаружении нажатия HotKeys
		public event EventHandler HotKeyPressed;
		public bool PreFilterMessage(ref Message m)
		{
			//Проверка на сообщение WM_HOTKEY
			if (m.Msg == WM_HOTKEY && 
				//Проверка на окно
				m.HWnd == IntPtr.Zero &&
				//Проверка virtual key code
				m.LParam.ToInt32() >> 16 == (int)keyCode &&
				//Проверка кнопок модификаторов
				(m.LParam.ToInt32() & 0x0000FFFF) == (int)modifiers &&
				//Проверка на наличие подписчиков сообщения
				HotKeyPressed != null)
			{
				HotKeyPressed(this, EventArgs.Empty);
			}
			return false;
		}

	}
в конструкторе окна
const ModifierKey MODIFIER_CNTL = ModifierKey.MOD_CONTROL ;

const Keys VIRTUAL_KEY_F = Keys.F;
блин нормальную ссылку не помню, но тут в принципе разберешся ,у меня работает
darkSql
Дата: 10.05.2006 10:34:48
да и незабудь прописать реакции на нажатие, если кнопок больше то и определений больше
darkSql
Дата: 10.05.2006 10:40:51
HotKeyHelper.Instance.Register(MODIFIER_CNTL, VIRTUAL_KEY_F);
HotKeyHelper.Instance.HotKeyPressed += new EventHandler(OnHotKeyPressed_Open)


....
у меня например отображение окна из трея
void OnHotKeyPressed_Open(object sender, EventArgs e)
		{
			ShowDialog();
		}
а чтоб окно не появлялось при запуске можно так
static void Main() 
		{
// это необязательно			
bool createdNew;
			_syncObject = new Mutex(true, _syncObjectName, out createdNew);
			if (!createdNew) 
			{
				MessageBox.Show("Копия программы уже запущена");
				return;
			}
			else	
//вот так. можно.
				new Form1();
			
			Application.Run();			
	
		}
Viktor Bartel
Дата: 10.05.2006 11:04:03
Спасибо вам,

Скажите а как сделать что бы программа "реагировала" на нажатие цифр, например при нажатии на 1 показывалал мессадж "Вы нажали 1"?

--
Cordialement
Victor Bartel
Viktor Bartel
Дата: 12.05.2006 17:57:12
Я немного неточно сформулировал вопрос, как сделать что бы приложение находилось в трее(вроде сделанно) и реагировало на все нажатия клавиш, как перехватывать и обрабатывать системные сообшения о нажатых клавишах из C# (нажали 1 получили 9)?

Спасибо...

--
Cordialement
Victor Bartel
Лиман Артём
Дата: 12.05.2006 20:34:19
если я не ошибась, то тебе необходимо зарегестрировать глобальный хук на события клавиатуры. Есть и плохие новости - насколько мне изветсно .net 1.1 не поддерживает глобальных хуков (возможно что в 2.0 это не так).
_______________________________________________________
Never ask users what they want, or they'll tell you.
Картинка с другого сайта.
Bodom
Дата: 16.05.2006 12:46:54
Использовать Win32API
в частности
SetWindowsHookEx
UnhookWindowsHookEx

И естесственно если глобальный хук - то только в Длл.