ページ

2008年11月30日日曜日

範囲指定の履歴をコンテキストメニューへ

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

以前、範囲指定の履歴を左下の三角ボタンで呼びだせるようにしたが、これをコンテキストメニューへ統合することにした。こんな感じ。


上がユーザ設定の範囲、下が履歴となる。

- - - -
三角ボタンがどうも気になっていたがこれですっきりした。

2008年11月29日土曜日

範囲選択・ユーザ設定(2)

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

プリファレンスの設定値をユーザデフォルトと同期する。汎用的に作ろうとすると面倒そうだったのでベタに値毎にキーを用意して保存することにした。キーの数は 15個(WIDTH, HEIGHT, NAMEの3種類 × 5設定)。


ここは数が増えるにしても対応の手作業はそんなに大変ではないのでまあいいだろう(手抜き)。


さて選び方だがコンテキストメニューで選べるようにする。こんな感じ。


- - - -
ちょっと前までにコンテキストメニューは、画像形式や出力オプションの設定ができる用途に使う実装を行ったがこれはやめた。便利ではあるが、使ってみるとそこまで便利ではないし、本来のコンテキストメニューの意味から外れていると思ったため。

2008年11月28日金曜日

範囲選択・ユーザ設定

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

範囲選択であらかじめユーザが設定しておいたサイズを選べる様にする。設定はプリファレンスで行う。まずはその設定用のインターフェイスから。
イメージはこんな感じ。



特に工夫もなく、入力欄を並べただけ。

2008年11月27日木曜日

simpleCapへコンテキストメニューを追加 (2)

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

昨日の続き。コンテキストメニューで3種類の画像フォーマットを選択する個所の実装について。


これら3つのメニューは排他的で1つを選ぶと他の二つのチェックを外さなければならない。最初は Cocoa Bindings で簡単にできるだろうと高をくくっていたが、結局複数のパス(Model Key Path)が必要だったり、既にチェック済みの状態で選ぶとチェックが外れてしまうなど、どうもうまくいかなかった。結局いい方法が思い浮かばず IBOutletとIBActionを3つのメニューそれぞれに接続して、ベタに制御することにした。

AppController


@interface AppController : NSObject {
IBOutlet NSMenuItem* _menu_png;
IBOutlet NSMenuItem* _menu_gif;
IBOutlet NSMenuItem* _menu_jpeg;
:

@implements
- (void)setImageFormat:(int)image_format
{
[_menu_png setState:0];
[_menu_gif setState:0];
[_menu_jpeg setState:0];

switch (image_format) {
case 0:
[_menu_png setState:1];
break;
case 1:
[_menu_gif setState:1];
break;
case 2:
[_menu_jpeg setState:1];
break;
}
[UserDefaults setValue:[NSNumber numberWithFloat:image_format]
forKey:UDKEY_IMAGE_FORMAT];
[UserDefaults save];
}

- (IBAction)setImageFormatPNG:(id)sender
{
[self setImageFormat:0];
}
- (IBAction)setImageFormatGIF:(id)sender
{
[self setImageFormat:1];
}
- (IBAction)setImageFormatJPEG:(id)sender
{
[self setImageFormat:2];
}


これらを InterfaceBuilderで接続する。



あまりにもベタな実装になってしまった。。

2008年11月26日水曜日

SimpleCapへコンテキストメニューを追加

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

SimpleCapへコンテキストメニューを追加する。画像形式や出力オプションをその場で変更したい場合、プリファレンスを開くのが面倒な時がある。現在のボタンの横に設定用のコントロールオブジェクトを追加することも考えたが、ごちゃごちゃしてわかりづらくなりそう。色々と考えたあげくコンテキストメニューで実現することにした。

SimpleCapで表示する範囲指定枠などの上で右クリックすると表示される。こんな感じ。


モデル(NSUserDefaults)との紐付けは簡単で、InterfaceBuilderでパスを指定するだけ。コーディング0。あいかわらずよくできている。


バインド先(Bind to)に"Shared User Defaults Controller" を選び、パス(Model Key Path)にユーザでフォルトで使っているキーを指定するだけ。

- - - -
今回バインディングで簡単に紐付けができたのはON/OFFを持つ単純な値だけ(例えば、QuickLookを使う/使わない)。画像形式(PNG, JPEG, GIF)はそうは行かない。これはどうやればいいのだろうか。

2008年11月25日火曜日

SimpleCapヘホットキー追加

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

SimpleCapへホットキーを追加する。
こういったツールの場合、すべての機能に一つ一つホットキーを割り当てるのが普通だが、いちいち覚えていられないのと元々ホットキーに割り当てられるキーの数が少ないので、1つだけ割り当てることにする。

具体的にはホットキーが押されたら特定の機能を実行するのではなく、SimpleCapのメニューを開く動作とする。その上で各メニューに割り当てられたキーを押す事で目的の操作をキーだけで行える様にする。

ホットキーには OPTION + COMMAND + 0 (数字の0)を割当てみた。メニュー内はよく使われる機能を数字に置き換えてみた。


利用イメージは次の様になる。
(1) OPTION + COMMAND + 0 でSimpleCapのメニューが開く
(2) '2' キーを押して範囲選択を実行

キーストロークが2回になってしまうが、覚えるホットキーは一つだけになるのはメリットだと思う。

さて実装だがホットキー自体の検証は以前済んでいでいたのでハンドリング個所の実装は既に終わっていた。
Cocoaの日々 - ホットキー

残るはキーが押された時にどうやってステータスバーのメニューを開くかだ。ADCのマニュアルを眺めているとNSStatusItem#popUpStatusItemMenu:というメソッドが見つかった。ホットキーハンドラ内でこれを呼出して見ると意図通りの動作となった。

コードはこんな感じ。

- (void)openMenu
{
[_status_item popUpStatusItemMenu:_status_menu];
}

//=========================
// Hot key handler
//=========================
OSStatus hotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData)
{
EventHotKeyID hotKeyID;
GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, NULL,
sizeof(hotKeyID), NULL, &hotKeyID);

if (hotKeyID.signature == SC_HOTKEY_SIGNATURE) {

NSLog(@"The hotkey was pressed.%@", userData);
[(AppController*)userData openMenu];
}
}



ただこの方法だとステータスバーのアイコンが選択されていない状態なので少し違和感がある。

(上の2つの画像を見比べると左側のカメラアイコンが反転していないことがわかる)

実用上問題ないのでまあいいか。

2008年11月24日月曜日

Quick Look APIs(その10)複数の画像

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

QuickLook パネルを表示する APIはNSURLを配列で受け取る。試しに複数の画像のNSURLを渡してみた。
コードはこんな感じ。

 NSMutableArray* list = [NSMutableArray array];
NSBundle* bundle = [NSBundle mainBundle];
[list addObject:[NSURL fileURLWithPath:[bundle pathForImageResource:@"image"]]];
[list addObject:[NSURL fileURLWithPath:[bundle pathForImageResource:@"buzz"]]];
[list addObject:[NSURL fileURLWithPath:[bundle pathForImageResource:@"081123-0009"]]];
[list addObject:[NSURL fileURLWithPath:[bundle pathForImageResource:@"pro"]]];

[[QLPreviewPanel sharedPreviewPanel] setURLs:list
currentIndex:0
preservingDisplayState:YES];


自動的にスライドショー用のアイコンが付く。左下はプログラムで付けたカスタムボタン。


インデックス表示も標準で動く。


サンプル:QuickLook-5.zip

2008年11月23日日曜日

直前のキャプチャ画像をゴミ箱へ捨てる

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

QuickLookパネルへアイコンを一つ追加する。表示しているキャプチャ画像を削除する目的で使うのでゴミ箱のアイコンを作ってみた。


ThinButtonBarクラスを使いこれを QuickLookパネルへ貼付ける。 こんな感じ。


次にボタンが押された時に表示中のキャプチャ画像ファイルをゴミ箱へ捨てる処理を実装する。

ファイルをゴミ箱へ捨てる(=移動する)操作は NSWorkspace#performFileOperation:source:destination:files:tag:を使う。

こんな感じ。

[[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation
source:dir
destination:@""
files:files
tag:nil];


source: にディレクトリパス、filesに移動対象のファイルリストを渡してやる。

- - - -
前から欲しかった機能がこれで1つ片付いた。

2008年11月22日土曜日

SimpleCapへQuickLookパネルを組み込む

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

さて QuickLookの検証が一通りできたので SimpleCapへ組み込むことにする。

新たに QuickLookController クラスを追加し、ここで QuickLookパネルや今後追加するカスタムボタンの処理をさせる。

QuickLookController.h

@interface QuickLookController : NSObject {

BOOL _is_available;
NSRect _start_frame;
}

+(QuickLookController*)sharedController;
-(void)showWithURLs:(NSArray*)urls;
-(void)showWithURL:(NSURL*)url startFrame:(NSRect)start_frame;
-(void)showWithURLs:(NSArray*)urls startFrame:(NSRect)start_frame;
-(BOOL)isAvailable;
-(void)close;

@end


このクラスのインスタンスを一つ作っておき(シングルトン)、#sharedController でこれを取得して利用する。SimpleCapでは全ての種類のキャプチャの制御を CaptureControllerで行っているので、この中のキャプチャ終了時のタイミングで QuickLookパネルを呼出すようにした。

これでキャプチャ終了時に QuickLookパネルが開く様になった。


また QuickLookパネルの利用の有無をプリファレンスで設定できるようにしておいた。


QuckLookパネルの呼出しは簡単にできたのだが、表示する時の拡大アニメーションに対応する為のキャプチャ位置を算出するのが少し手間がかかった。

- - - -
表示ができたので次はカスタムボタンを加えていく。まずはキャプチャ画像を削除(ゴミ箱へ移動)するボタンを加えてみよう。

2008年11月21日金曜日

Quick Look APIs(その9)非アクティブで表示

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

QuickLook パネル は NSPanel から派生しており、デフォルトではアプリケーションが非アクティブになると隠れてしまう。そこで試しに NSWindow#setHidesOnDeactive: を使ってみたところ、非アクティブになってもウィンドウを表示させることができた。

[[QLPreviewPanel sharedPreviewPanel] setHidesOnDeactivate:NO];


前回のサンプルへ上の1行を加えて実行し、ファインダ上の画像ファイルのQuickLookと同時に表示させてみた。



いろいろと触ってみたが簡易ビューアとして自分で作るよりは手っ取り早く利用できそうなのがわかった。SimpleCapで採用しよう。

2008年11月20日木曜日

Quick Look APIs(その8)カスタムボタン

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

SimpleCapで使っているボタンクラス ThinButtonBar を QuickLookパネルへ付けてみた。



問題なく動く。

標準のボタンを表示させないと下の黒いエリアの高さが縮まる。



サンプル:QuickLook-4.zip

2008年11月19日水曜日

Quick Look APIs(その7)カスタムボタン

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

試しに新規にビューを加えてみる。

まず赤色の矩形を描くビューを用意する。

@implementation View
- (void)drawRect:(NSRect)rect {
// Drawing code here.
NSLog(@"drawRect:%@", NSStringFromRect(rect));
[[NSColor redColor] set];
NSRectFill(rect);
}


これを QuickLookパネルのサブビューへ追加する。

NSView* content_view = [[QLPreviewPanel sharedPreviewPanel] contentView];
View* view = [[[View alloc] initWithFrame:NSMakeRect(10, 10, 100, 100)] autorelease];
[content_view addSubview:view];



できた。


おお意外と簡単。

2008年11月18日火曜日

Quick Look APIs(その6)カスタムボタン

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

QuickLookパネルは NSPanel から派生しているので、#sharedPreviewPanelで取得したインスタンスからいろいろと情報が取り出せる。先ずは Content View を取り出してみよう。

 NSView* content_view = [[QLPreviewPanel sharedPreviewPanel] contentView];
for(NSView* v in [content_view subviews]) {
NSLog(@"%@: %@", v, NSStringFromRect([v frame]));




上の画像を表示させた結果はこんな感じ。
2008-11-16 12:57:49.251 QuickLook[44826:10b] : {{0, 45}, {322, 427}}
2008-11-16 12:57:49.263 QuickLook[44826:10b] : {{0, 3}, {322, 39}}


Content View のサブビューは2つある。サイズからみて恐らくこんな感じだろう。


APIが見つからないので自分でこれらのビューをカスタイマイズするか、新たにビューを加えるかの方法を取る事になる。
どっちにしてもビューのインスタンスが手に入れば後は力任せ?で何でもできる。

サンプル:QuickLook-3.zip

2008年11月17日月曜日

Quick Look APIs(その5)カスタムボタン

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

QuickLookパネルにカスタムのボタンを付けたい。

標準のボタンはこんな感じ。


これらのいくつかはメソッドで制御できる。例えばフルスクリーンボタンの表示は下記メソッドが使える。

- (void)setShowsFullscreenButton:(BOOL)fp8;



QuickLookにカスタムボタンをつける情報はほとんどみつからなかった。公開APIではないので仕方はないが。
CocoaDevでほんの少しだけボタンについて触れた書き込みがあったぐらい。
CocoaDev: QuickLook (このページの一番下)。


さてどうするか。

2008年11月16日日曜日

Quick Look APIs(その4)

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

Quick Look のメモ

・QuickLookのパネルはアプリケーションプロセス毎に1つ割当られている(シングルトン)。
・パネルはそのアプリケーションがアクティブな時だけ表示される。

つまり言い換えると MacOSX上で表示できる QuickLookパネルは常に1つだけということ。

例えばファインダである画像をQuickLookパネルで表示させる。


この状態で他の画像を選択すると画像が入れ替わる。新しいパネルは開かれない。


この状態で他のアプリケーションを選択するとパネルは消える。


あるいは別のアプリがQuickLookパネルを表示させていた場合はそちらのパネルが表示される。

2008年11月15日土曜日

Quick Look APIs(その3)

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

引き続き QuickLook。
delegateメソッド #previewPanel:frameForURL:を実装すると、表示する時と閉じる時に拡大(縮小)のアニメーションがつく。こんな感じ。


このアニメーションを使うには最初にまず delegateを指定し、

[[[QLPreviewPanel sharedPreviewPanel] windowController] setDelegate:self];


#previewPanel:frameForURL:を実装する。
- (NSRect)previewPanel:(NSPanel*)panel frameForURL:(NSURL*)URL
{
return NSMakeRect(0,0,100,100);
}


戻り値の NSRect が最初の位置とサイズを決める。上の例の場合、起点が(0,0)で大きさが (100,100)の画像が拡大(縮小)アニメーションの初期状態となる。

サンプル:QuickLook-2.zip

2008年11月14日金曜日

Quick Look APIs(その2)

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

前回紹介したページを参考にサンプルを作ってみる。簡単にできた。



QuickLookのパネルを表示するのに最低限必要なのは3つ。

(1) ライブラリのロード

[[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load];


(2) 表示対象のURLを設定
 [[QLPreviewPanel sharedPreviewPanel] setURLs:list
currentIndex:0
preservingDisplayState:YES];

setURLs に NSURLの配列(NSArray)を渡す。

(3) パネルの表示
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFrontWithEffect:2];


サンプルはこんな感じ。
#import "AppController.h"
#import "QuickLook.h"

#define QLPreviewPanel NSClassFromString(@"QLPreviewPanel")

@implementation AppController
- (void)awakeFromNib
{
[[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load];
}

- (IBAction)look:(id)sender
{
NSMutableArray* list = [NSMutableArray array];
NSBundle* bundle = [NSBundle mainBundle];
NSURL* url = [NSURL fileURLWithPath:[bundle pathForImageResource:@"image"]];
[list addObject:url];

[[QLPreviewPanel sharedPreviewPanel] setURLs:list
currentIndex:0
preservingDisplayState:YES];
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFrontWithEffect:2];
}

@end



サンプル:QuickLook-1.zip

2008年11月13日木曜日

Quick Look APIs(その1)

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

Quick Lookが SimpleCapでビューアとして利用できないかと考えている。
そこでまず調べてみた。どちらかというと(特に日本語情報は)利用よりもプラグインを使う情報が多い。
調べる内に目的の情報が載っているページが見つかった。

Ciaran Walsh's Blog
Quick Look APIs


このページには使い方の解説とサンプルのソースコードがついていてかなり参考になる。
試しにサンプルをビルドして実行してみた。



実行するとディレクトリツリーが現れる。画像などを選びスペースバーを押すと QuickLookのウィンドウ(パネル?)が現れる。


複数の画像も普通に扱える。

2008年11月12日水曜日

範囲選択試行錯誤中

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

範囲選択のUIをいろいろいじっている。

現行のデフォルト状態とタイマー状態。




タイマー状態では大きさが変更できるようになったが移動ができない。


試しに枠をつけてみた。両状態とも同じインターフェイスになった。




ただこれだと選択範囲がどこまでなのか(透明部分だけなのか?)、また影の部分がドラッグ対象なのかがわかりづらい。

結局元に戻す。

なおタイマーをキャンセルした時に通常の選択モードへ戻るようにした。今まではキャプチャ操作を完全にキャンセルしていた。この変更で位置が気に入らなければ通常モードへ移動し、再びタイマーを起動できるようになった。これで十分かもしれない。

2008年11月11日火曜日

ボタンの簡易アニメーション

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

SimpleCapを初めて使った時にボタンに気がつかないという意見が以前あった。


点滅させたり、横に流れるようなフラッシュをさせたりといろいろ試した結果、透明(alpha=0)から徐々に不透明(alpha=1.0)に変えていくのが雰囲気が良くて飽きがこない?ので、この方法を取る事にした。

静止画ではわかりにくいが徐々にボタンが明るくなっていく。



実装はボタンを管理する ThinBunttonクラスに startFlasher メソッドを追加し、各Handler起動時にこれを呼出すようにした。メソッドはこんな感じ。

//-----------------
// Flasher
//-----------------
#define FLASHER_INTERVAL 0.05
#define FLASHER_FRAMES 10.0
- (void)flasherAnimate:(NSTimer*)timer
{
// do it
[self setNeedsDisplay:YES];
_flasher_alpha += 1.0/FLASHER_FRAMES;

if (_flasher_alpha > 1.65) {
[timer invalidate];
_while_flasher = NO;
}
}

- (void)startFlasher
{
if (_while_flasher) {
return;
}
_flasher_alpha = 0.0;
_while_flasher = YES;
NSTimer* timer = [NSTimer timerWithTimeInterval:FLASHER_INTERVAL
target:self
selector:@selector(flasherAnimate:)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
}


drawRect: 内の描画処理で _flasher_alphaを使っている。_flasher_alphaを 1.65まで増やしている。alpha値は 1.0が最大値なのでこれを超えても透明度は変わらないのだがこうすることで1.0状態の表示を簡単な方法で長めに表示させることができる。

2008年11月10日月曜日

SimpleCap α3リリース

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

遅くなりました。SimpleCap α3をリリースします。

SimpleCap-a3.zip
※再配布不可

α2から追加・変更された機能
・環境設定追加(Preferences..)
・JPEG/GIF/PNGの選択可能
・マウスカーソルキャプチャ
・キャプチャ後アプリ起動
・影、角丸、白縁、背景などの加工機能
・Widgetキャプチャ(実験的)

標準ではマウスカーソルは矢印Onlyです。Preferences内の "Use private functions for cursor"を使うと実際のカーソルの形でキャプチャしますが、プライベート関数利用のせいもあってPowerBookG4などでは色がおかしくなっていました。この為、非デフォルト扱いです。
波紋エフェクトは今回見合わせ。


Tipsなど
・Windowsではシフトキーを押しながらマウスクリックすると、複数のウィンドウを選択できます
・Selectionではキーが使えます
   矢印キー:1px移動
   矢印+コマンド:5px移動
   矢印+シフトキー:拡大、縮小
   コマンド+Z:アンドゥ
   コマンド+シフト+Z:リドゥ



意見、感想、要望、バグ、なんでも歓迎します。
コメントに書き込んでください。
参考にさせてもらいます。


- - - -
年内にあともう一回α版(α4)を出します。

α4での対応予定
 ・マルチスクリーン対応
 ・アイコン、キャプチャ音の用意
 ・ホットキー
 ・Nibの多言語化
 ・QuickLook(実験的)

この後は機能Fixし、β版、正式版と仕上げる予定です。

2008年11月9日日曜日

範囲選択の変更

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

範囲選択(Selection)の仕様を変更した。

以前は下のように範囲の外が黒くなって、範囲選択以外の操作は何もできなかった。


これをやめて範囲選択中も他のウィンドウの操作ができるようにした。


またタイマー起動時はサイズを変更できるようにした。移動ができた方が良さそうだがどういう方法が良いのか今のところアイディアが無い。


真ん中のところは下のウィンドウが操作できた方が良いので、例えば線の部分をドラッグしてもらう方法が考えられる。現在試行錯誤中。

- - - -
これらを反映したα版バージョン3(α3)を近日公開する予定です。

2008年11月8日土曜日

非アクティブなウィンドウで最初のクリックイベントを拾う

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

普通に NSView を作ると、そのビューが載るウィンドウが非アクティブな場合は最初のクリックイベントを拾わない。この為、まず(1)ウィンドウをクリックしてアクティブにし、(2)ビューをクリックする、と2回クリックすることでようやくイベントが拾える。

ビューでクリックイベントを拾う

(1) ウィンドウをクリック(アクティブにする)
(2) ビューをクリックする(イベントが拾える)


これを非アクティブのウィンドウであってもワンクリックでビューがイベントを拾えるようにしたい。
NSButtonの動作を見ると、非アクティブのウィンドウであってもワンクリックでイベントを拾っているようにみえる。

そこで NSViewのリファレンスを調べたところ該当するメソッドがあった。

NSView#acceptsFirstMouse:

ビューでこのメソッドをオーバーライドして YESを返すようにすればよい。
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
return YES;
}


検証用にサンプルを作ってみたところ、うまくいった。

サンプル:WindowSample-1.zip



サンプルは画面最上位レベルに赤枠を表示する。このウィンドウが非アクティブな場合でも、赤枠をクリックするとイベントに反応する(デバッグコンソールに NSEventの内容がダンプされる)。

- - - -
おおこれはいい。SimpleCapで使おう。

2008年11月7日金曜日

透明なウィンドウ(3)SimpleCapでの実装

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

さて、SimpleCapではどう実装するか。もともと NSWindow#setIgnoresMouseEvents: を使った経緯は範囲選択モードで、真ん中の透明部分をつかんで選択範囲をドラッグできるようにするのが目的だった。コードを見直したところ、それ以外の目的では使っていない。

ということは、ここだけ何か対応ができれば NSWindow#setIgnoresMouseEvents: を使わなくても良いということになる。前回 NSWindow#setIgnoresMouseEvents: を使った場合でも、透明部分へのクリックイベントをスルーさせることができることがわかったが、今後 MacOSX10.6, 7, 8...とバージョンアップ後も動作させたいので、できればプライベート関数を使うのは避けたい。

で、結局今回は完全な透明ではなく、透明度を限りなく上げた不透明な色を使うことにした。

[[NSColor colorWithDeviceRed:1.0 green:1.0 blue:1.0 alpha:0.05] set];


見た目は透明で全然支障が無い。


alpha値は 0.05がぎりぎりで、それより小さくなるとイベントが拾えなかった。

これで NSWindow#setIgnoresMouseEvents: とプライベート関数を使わずに対応できた。

2008年11月6日木曜日

透明なウィンドウ(2)非公開関数

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

CGSClearWindowTags( )関数を使うと setIgnoresMouseEvents: の問題が解決できるらしい(掲示板:196)。

CGSClearWindowTags( )を調べてみると、これはプライベート関数らしい(またか。。)。
CocoaDev: CoreGraphicsPrivate

Fixing an annoying Exposé bug with NSWindows を参考にサンプルを作ってみた。

サンプル:TransparentWindow-2.zip


追加コードはこんな感じ。

typedef int CGSConnection;
typedef int CGSWindow;
typedef enum {
CGSTagNone = 0, // No tags
CGSTagExposeFade = 0x0002, // Fade out when Expose activates.
CGSTagNoShadow = 0x0008, // No window shadow.
CGSTagTransparent = 0x0200, // Transparent to mouse clicks.
CGSTagSticky = 0x0800, // Appears on all workspaces.
} CGSWindowTag;
extern CGSConnection _CGSDefaultConnection(void);
extern CGError CGSClearWindowTags(const CGSConnection cid, const CGSWindow wid, CGSWindowTag *tags, int thirtyTwo);

@implementation TransparentWindow

- (void)clearWindowTag
{
CGSConnection connectionID = _CGSDefaultConnection();
CGSWindow winNumber = [self windowNumber];
CGSWindowTag tags[2] = {0x0200, 0};
CGSClearWindowTags(connectionID, winNumber, tags, 32);
}


上記 clearWindowTag を setIgnoresMouseEvents:YES の後に呼出してみた。

  [self setIgnoresMouseEvents:YES];
[self clearWindowTag];


すると赤枠がイベントを拾い、それ以外の透明部分はイベントを拾わなくなった。



おお。いい感じだ。

だがマウスカーソルに続いてまたしてもプライベート関数か。うーむ。

- - - -
その他参考情報
Cocoa Wiki >> Expse しないウィンドウ

2008年11月5日水曜日

透明なウィンドウ(1)非透明部分でイベントを拾い、透明部分は拾わない

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

SimpleCapの範囲選択にタイマー機能がある。このタイマー機能、使っているともの足りない点に気がついた。タイマー起動中に範囲の大きさが変更できない。これを変更できる様にしよう。ただ調べていくうちに問題に突き当たった。ラバーバンドはイベントを拾いたいが、それ以外の透明部分はイベントを拾わないようにしたいがこれがうまく行かない。どうも NSWindow#setIgnoresMouseEvents: を使うとウィンドウの透明部分がイベントを拾う様になってしまうようだ。

このあたりを調べるためにサンプルアプリを作ってみた。

サンプル:TransparentWindow-1.zip

実行すると透明なウィンドウが作られ、そこへ赤い四角枠が描かれる。赤い枠のみイベントを拾い、真ん中の透明部分はイベントを拾わないようにしたい。


このサンプルで次のことがわかった。

(1) NSWindow#setIgnoresMouseEvents: を使わないと意図通りに動作する。つまり赤枠のみイベントを拾い、真ん中の透明部分はイベントを拾わない(下のウィンドウが反応する)。

(2) setIgnoresMouseEvents:NO を投げると赤枠だけでなく、透明部分もイベントを拾う様になる

(3) setIgnoresMouseEvents:YES を投げると全てがイベントを拾わなくなる。その後に setIgnoresMouseEvents:NO を投げると (2)と同じになる。


つまり setIgnoresMouseEvents: を1度でも使うと (1)の状態へ戻せない。

うーむ。

2008年11月4日火曜日

アプリケーションを開く(7)SimpleCapへの組み込み

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

さてお膳立てが整ったのでいよいよ SimpleCapへ組み込む。前回まで作ったモデルクラス PreferredApplicationsをSimpleCapのプロジェクトへ追加して必要なコードを書く。

環境設定にプルダウンが表示される。


プルダウンの中身。


キャプチャを実行すると最後に指定したアプリケーションでオープされる。下図は Safariで開いている。


上のチェックボックス(Open with application:)と Bindingsで連携していて、チェックを外すとディゼーブルになる。