ページ

2008年4月6日日曜日

ホットキー

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

「ホットキー」とは、アプリケーションが非アクティブでも処理できるキー(イベント)のこと。今作っている画面キャプチャキーで使いたいので調べてみた。

2つほど参考になるページが見つかった。Carbonイベントを使うようだ。
ホットキーを登録する(HDMT)
Program Global Hotkeys in Cocoa Easily (Dustin Bachrach Blog)

HDMT木下さんのページでは Cocoaで扱いやすいようにアレンジしてある。


情報が揃ったのでこれらを参考に自分で試してみた。

ソース:Shortcutkey.zip

実行すると右上のステータスバーに "SAMPLE MENU"が現れる。


この状態で Option + Command + スペースキー を押すとウィンドウがポップアップする。


別のアプリが前面に出てアクティブになっていてもこのキーは有効に働く(だからホットキー)。


ホットキーの使い方のポイントは3つ。
1. ホットキーの登録
2. ホットキーのハンドリング
3. ホットキーの解除


まずはホットキーの登録。サンプルではアプリケーション起動時にこれを行っている。
MyController.m

- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
  :
EventTypeSpec eventTypeSpecList[] ={
{ kEventClassKeyboard, kEventHotKeyPressed }
};

InstallApplicationEventHandler(&hotKeyHandler, GetEventTypeCount(eventTypeSpecList),
eventTypeSpecList, self, NULL);
EventHotKeyID hotKeyID;
hotKeyID.id = 0;
hotKeyID.signature = 'htky';
UInt32 hotKeyCode = 49;
UInt32 hotKeyModifier = cmdKey + optionKey;

OSStatus status = RegisterEventHotKey(hotKeyCode, hotKeyModifier, hotKeyID,
GetApplicationEventTarget(), 0, &_hotKeyRef);
  :
}


InstallApplicationEventHandler() でイベントハンドラを登録し、RegisterEventHotKey() でホットキーを登録する。
イベントハンドラでコントローラのインスタンスを使いたいので、InstallApplicationEventHandler() の第四引数に selfを渡しておく(この引数は void* userData)。


続いてホットキーが押された時に呼出されるイベントハンドラ。
OSStatus hotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
{
EventHotKeyID hotKeyID;
GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, NULL,
sizeof(hotKeyID), NULL, &hotKeyID);

if (hotKeyID.signature == 'htky') {

switch (hotKeyID.id) {
case 0:
NSLog(@"The hotkey was pressed.");
[(id)userData openWindow:nil];
break;
}
}

return noErr;
}


hotKeyID でキーの種類を判別する。ここでは先ほど指定しておいた userData(self)を使ってインスタンスメソッド openWindow: を呼出している。これでウィンドウがポップアップする。

-(IBAction)openWindow:(id)sender
{
NSLog(@"openWindow: was called.");
[NSApp activateIgnoringOtherApps:YES];
[_window makeKeyAndOrderFront:self];
}



最後のホットキー解除。
- (void)applicationWillTerminate:(NSNotification *)notification
{
OSStatus status = UnregisterEventHotKey(_hotKeyRef);
   :
}


登録時にとっておいた EventHotKeyRef _hotKeyRef を UnregisterEventHotKey() へ渡してやる。


実行時のログはこんな感じ。



なおビルドには Carbon Frameworkを加えてやる必要がある。

無いとエラー。


これを加えてやる。



- - - -
前出の情報を参考にしたら簡単にできた。Cocoaで使う場合は木下さんのコードのような使い方が楽かもしれない(インスタンスの参照が必須なので)。