Mac App Store対策シリーズ その1. スクリーンサイズの変更に対応する

Mac App Storeに最近やってるチームで作ったアプリをサブミットしました。
そんなわけでひさびさにCocoaをやっていました。

これからMacアプリを作る、もしくはMacな頭への切り替えが必要な方のために
自分のリハビリも含め、ぼちぼちMacのことを書いていきます。

さて、iOSアプリではなくて、Macのアプリの場合、特有の考えなくてはいけないことが結構あります。

ぱっと思いつく単純なところでは次の2つです。
・Menu
・Window (Screen)

#逆に言うと、この辺が無いiOSが非常にシンプルなわけです。
#画面に1アプリだし、メニューなんかありません。

この中から今回はWindowについて。
Document-Basedなアプリケーションの場合、たぶん自動でやってくれたりする気がしますが
Windowの位置なんかを自分でなんとかしないといけない場合があります。

なんとかしないといけない場合は
・スクリーンサイズが変更になった(解像度を変更した)
・新しいスクリーンが追加された、外された(つまりモニターをつないだ、外した)
の二つです。

まず、NSApplicationDidChangeScreenParametersNotificationというキーがあって
これでスクリーンの何かが変わったら通知を受けとることができます。
通知がきたら、スクリーンサイズの変更だったら、変更に合わせてWindowの位置を移動させるなどすればよいでしょう。
以前の位置を比率で覚えておいて、新しいスクリーンサイズで計算し直すと、同じ位置に表示されますね。

しかし、新しいスクリーンが追加された(されている)場合、そうも単純にはいきません
モニターが二つある場合、メインじゃない方のスクリーンは以下のように
かなりいろいろな場所に移動できてしまうからです。

(これは「いびつな形のスクリーンサイズへ変更された」状態ととらえるといいと思います。)

これだけの自由度に対応するのはどう考えてもめんどくさそうです。
また、対応を完璧に実装したとして、何人の人がDualモニター環境で使うか分かりません。
おそらくかなり少ないはずです。
が、しかし、無視するわけにもいかないのです。
これらの変更があることを無視すると、モニターを外したら以前あったスクリーン領域がなくなったりしますので
Windowが表示されない…ということもあり得ます。
これは困ります。Windowが見えないとアプリが使えないからです。

そんなときは、次のコードでひとまずなんとかなります。

    //windowはNSWindowのインスタンス
    //1
    NSScreen* screen = [window screen];
    if(screen == nil){
        //2
        [window center];
    }

やっていることは単純で
1. NSWindowのscreenメソッドは、Windowが属するNSScreenのインスタンスを返すが
所属している(表示されている)Screenがなければnilを返すので

2. その場合はcenterメソッドでメインスクリーンのセンターに表示する

です。

これでWindowが見えないところに行ってしまって操作できない、という最悪の状態は防げます。
センターに表示するのは、screenがnil、つまり、以前は表示できていたんだけど、見えなくなってしまった
という場合だけなので、あまり問題ないでしょう。

この処理を最後に行うようにして、その前にスクリーンの状態の変更前に応じた移動の処理を入れてやればいいと思います。

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

Leave a Reply

You must be logged in to post a comment.