しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

UWP でアプリを作ってから 1 週間でやったことをまとめた

色々と苦労ばかりしてますが、何だかんだで UWP で作ったアプリの更新を頻繁に行っています。

情報が非常に少ないという点が苦労の原因なので、文句ばかり言わず調べた部分に関してはまとめます。実際にアプリに組み込んで試したことだけ書いてますが、間違っている可能性は高いです。

HockeyApp を有効化

Visual Studio から HockeyApp のクラッシュ分析を有効化すると、簡単にアカウント作ったりアプリの登録が出来ますが、AppId の設定は自分で行う必要があるみたいでした。

using Microsoft.HockeyApp;

public sealed partial class App
{
    public App()
    {
        HockeyClient.Current.Configure("APPID");

        InitializeComponent();

        Suspending += OnSuspending;
    }
}

公式のサンプルが InitializeComponent の前に呼び出していたので、同じようにしました。

f:id:shiba-yan:20160817214734p:plain

正しく設定が行えていると、HockeyApp のダッシュボードに情報が表示され始めます。最低でも Version が表示されていない場合は設定に失敗しているので、AppId を確認する必要があります。

課金処理を StoreContext API に変更

昔から存在している CurrentApp を使った課金処理は、Windows 10 Anniversary Update から新しく追加された StoreContext に置き換えられるようです。

https://msdn.microsoft.com/en-us/windows/uwp/monetize/in-app-purchases-and-trials

API が大きく変わっているのと、サンプルコードがいまいちでわかりにくかったので、実際に自分が書いたコードを参考までに載せておきます。正しいのかはわからないので自己責任で。

アドオンの購入は RequestPurchaseAsync メソッドに StoreId を渡すだけなので、これまでとあまり違いはないです。ProductId ではなく StoreId なので注意が必要です。

var context = StoreContext.GetDefault();

var result = await context.RequestPurchaseAsync(StoreId);

switch (result.Status)
{
    case StorePurchaseStatus.AlreadyPurchased:
        // 既に購入済み
        break;

    case StorePurchaseStatus.Succeeded:
        // 購入完了
        break;

    default:
        // エラー扱いにする
        return;
}

購入後は Status の値によってダイアログを出したりすることになると思います。

そして購入済みライセンスのチェックですが、新しい API では SKU という概念が追加されたみたいなので、これまでより少しめんどくさくなりました。

For a SKU, the Store ID has the format /xxxx, where xxxx is a 4-character alpha-numeric string that identifies a SKU for the product. For example, 9NBLGGH4R315/000N. This ID is returned by the StoreId property of a StoreSku object, and it is sometimes called the SKU Store ID.

In-app purchases and trials

情報自体は GetAppLicenseAsync メソッドで取得できますが、AddOnLicenses のキーは StoreSku から取得できる StoreId なので、単純にインデクサーで引くとエラーになります。

なので、LINQ を使って StartsWith で比較するか、StoreSku を先に調べて引っ張ってくるかの方法が必要になりそうです。挙動が不明だったので、私は後者を選びました。

// Durable なアドオンを取得する
var list = await context.GetAssociatedStoreProductsAsync(new[] { "Durable" });

// Skus は必ず 1 つ存在する
var skuStoreId = list.Products[StoreId].Skus[0].StoreId;

// ライセンス情報を取得
var license = await context.GetAppLicenseAsync();

// AddOnLicenses は KeyNotFoundException を投げる
if (license.AddOnLicenses.ContainsKey(skuStoreId) && license.AddOnLicenses[skuStoreId].IsActive)
{
    // アドオンを購入済み
}

ひとまず、これで StoreContext を使った IAP が動作するようになりました。

AdMediator が削除されたので変更

これまで Microsoft Store Engagement and Monetization SDK としてリリースされていた拡張が、先日新しく Microsoft Store Services SDK に変わりましたが、このタイミングで AdMediator が削除されました。

今後はサーバーサイドに切り替わっていくみたいですが、SDK がリリースされてもサーバー側がリリースされていないので、現状は Microsoft Advertising のみ利用可能です。

  • AdMediator is no longer being maintained as we shift to server side mediation.
    • For Windows 10 apps, an MSDN topic is coming out this week with prescriptive steps to refactor.
Microsoft Store Services SDK extension

英語版のドキュメントは既に Store Services SDK 向けに更新されています。

https://msdn.microsoft.com/windows/uwp/monetize/microsoft-store-services-sdk

おそらく近日中にサーバー側がリリースされるんでしょう、足並み揃えろという感は拭えませんが。

Feedback Hub の起動コードを変更

Insider 向け機能として提供されている Feedback Hub を使ったフィードバック機能ですが、Store Services SDK の更新に従って微妙に API が更新されています。

まず StoreServicesFeedbackLauncher.IsSupported メソッドを使って、利用可能かチェックします。

if (StoreServicesFeedbackLauncher.IsSupported())
{
    feedbackButton.Visibility = Visibility.Visible;
}

何故か IsSupported はメソッドに変更されています。このあたりイマイチですね。

実際に Feedback Hub を開くためには StoreServicesFeedbackLauncher.GetDefault メソッドでインスタンスを取得した後、LaunchAsync メソッドを呼び出します。

private async void FeedbackButton_Click(object sender, RoutedEventArgs e)
{
    await StoreServicesFeedbackLauncher.GetDefault().LaunchAsync();
}

この修正はシンプルなのですぐ対応できます。

実際にフィードバックが送られるとどうなるのかはよくわかっていないですが、めんどくさい部分を Windows Store が受け持ってくれるのは便利ですね。

Windows Phone 8.1 向けに作ったアプリを Windows 10 Mobile 向けに作り直してみた

最後に更新してから 1 年ほど放置していたアプリが、実はダウンロード数が順調に伸びていたのと MADOSMA Q601 を買ったので Windows 10 Mobile に作り直してみました。

作り直したと言っても、WinRT から UWP への変更点としてはプロジェクトファイルぐらいみたいですが、project.json 周りで嫌な思いしたくなかったので新規にプロジェクトを作りました。

UWP プロジェクトに既存のコードをコピーして、ビルドすると大体移植は完了といった感じです。しかし、アイコンサイズが大きく変わっているため、UWP Logo Maker で作り直しました。

基本的には透過画像が好まれますが、StoreLogo 系だけは背景色を付けておかないと、ダッシュボードでの表示が残念なことになります。リリースするともっと悲惨になったかもしれません。

あと、今回は Mobile 向けなので Package.appxmanifest の TargetDeviceFamily を Windows.Mobile に変えておきました。これで Mobile をターゲットにしていることになるらしいです。

<Dependencies>
  <TargetDeviceFamily Name="Windows.Mobile" MinVersion="10.0.10240.0" MaxVersionTested="10.0.10586.0" />
</Dependencies>

ストアに出すときに嵌ったのが、デフォルトテンプレートでは MinVersion と MaxVersionTested が 10.0.0.0 になっていて、審査前にリジェクトされたことでした。

UWP なので Windows 10 Mobile 以外でも動作しますが、ストア側で Mobile のみ配布するようにしました。

f:id:shiba-yan:20160802234551p:plain

運悪く土日を挟んでいたため審査には時間がかかり、さらにストアへの情報反映までにはもっと時間がかかりましたが、何とか UWP 版のリリースまで行えました。

今後も Feedback Hub への対応や、IAP の実装などいい感じの実験アプリとしてリリースしていきます。

Windows Phone 8.1 への対応を打ち切って、UWP 版だけのリリースにしてしまいましたが、世界的に見ると Windows 10 Mobile のシェアは Windows Phone 8.1 の半分以下らしいので、かなり早まった感があります。

このスライドは AdDuplex が毎月公開しているものですが、今回は何故か日本のシェアについて特集されているので読んでみると面白いと思います。特に Lumia がシェア 1 位の部分とか突っ込みどころだと思います。

MADOSMA Q601 をヨドバシの深夜受け取りを利用して買ってみた話

今日 28 日は MADOSMA Q601 の発売日です。初代 MADOSMA も結局発売日に買っていた私ですが、今回の Q601 はちょっとタイミングをずらそうかなと思っていました。自転車盗まれたし。

しかし、ふとヨドバシの商品詳細ページを見ると、アキヨドでは MADOSMA Q601 を 30 分以内に用意してくれるみたいだったので、無理だろと思いつつ注文してみたら買えてしまった話です。

注文してから 7 分後には商品の準備が出来たので取りに来いメールが届いたので、タクシーを使ってアキヨドまで出向いて購入してきました。

シャッターを都度開けるとか、地味に凄い手間かかってるなと思いました。

経緯は割と謎ですが、TL 最速で MADOSMA Q601 を購入できたようです。アキバに近いとこういう芸当が出来るのが結構面白いですね、多分もう二度とやらないとは思いますが。

開封してみた

当然ながら Q501 より箱は全体的に大きいですが、それ以外はあまり変わっていない感じです。

f:id:shiba-yan:20160728022540j:plain

開けると、さっそく本体のお目見えです。実機は触ってましたが、それでもやっぱり 6 型はかなり大きく見えます。自分の手は割と大きい方ですが、割とギリギリです。

f:id:shiba-yan:20160728022603j:plain

今回は液晶保護シートが付いていない気がします。Gorilla Glass 3 だからでしょうか。

電源を入れてみた

起動画面は新しい mouse のロゴになっていて、ちょっとかわいいです。

f:id:shiba-yan:20160728022707j:plain

解像度が Full HD なので広々としてます。設定を弄るとタイルを 4 つ横並びに出来るらしいですが、今のところは 3 つで良いかなという気がしています。

f:id:shiba-yan:20160728024939p:plain:w450

そして事前情報の通り、すぐに新しいビルドが落ちてくるので、早々にアップデートを行っておくのが良さそうです。いつも通りですが、やっぱり結構時間がかかる感じです。

f:id:shiba-yan:20160728025013p:plain:w450

この記事を書いている間、ずっとアップデートの歯車が回っているので、朝まで放置する予定です。

Continuum を Android TV で試してみた

折角なので Continuum を手持ちの 4K BRAVIA のディスプレイミラーリング機能を使って試してみました。Continuum アプリを起動して無線接続すると、すぐにテレビが見つかりました。

f:id:shiba-yan:20160728025049p:plain:w450

昔は Miracast の接続が全く安定していなかったのですが、テレビ側のアップデートでじわじわと改善されてきたのかもしれないです。地味に喜ばしいことです。

しかし、予想通りレスポンスはあまりよくなく、解像度もなんだか狂っているようです。

f:id:shiba-yan:20160728024517j:plain

明らかに縦方向に潰れているように見えます。解像度の設定を Continuum アプリ側で出来るのかなと思いましたが、特にそういう設定もなかったので相性なのかもしれないです。

ちゃんと Windows 10 の Miracast 拡張に対応した機器を買ったほうが良さそうです。

Android TV が Amazon ビデオに対応した関係上、HDMI が一つ空いたので、そこに Microsoft の Miracast アダプタを刺そうかと考えています。

MADOSMA を Windows 10 Mobile へアップグレードしてきた

今朝、そろそろ起きて出社しようと思ったタイミングで、MADOSMA の Windows 10 Mobile アップグレードサービスが店頭なら即日で行えるという情報をゲットしたので、開店と同時に行ってきました。

アップグレードに伴い初期化しますよ、という同意書にサインをして端末を預けると、大体 30 分後ぐらいにはアップグレードが完了したという電話がかかってきました。アップグレードには 3240 円かかります。

受け取った端末は初期化された状態だったのでセットアップを行います。ロック画面は Windows 10 でもお馴染みのやつなので、何となく安心感があります。

スタート画面には Cortana や Office 系のアイコンが予め揃っています。Cortana がとても新鮮です。

OS のバージョンは 10586.11 となっていたので、PC 版と全く同じバージョンのようです。

Edge も PC 版と同じ Edge 13 です。html5test.com の結果もとても良くなりました。

やっと使えるようになった Cortana は PC 版と設定を自動的に同期してくれている感じがします。かずあきさんの年収とか、サービス残業時間を答えてくれると面白いのですが、まだそういった機能は無いようです。

8.1 ではダメダメだったマップは荒いですが、かなり良くなりました。解像度が低いのが気になります。

秋葉原のマウスコンピューターダイレクトショップは 19 時まで営業しているので、早く Windows 10 Mobile を入手したい人は仕事をさぼって走りましょう。

最初のリリースですが、完成度がとても高く感じました。これからも MADOSMA を応援していきたいです。

Windows 10 バージョン 1511 にアップデートすると iPad Air 2 も充電できる気がする

何故か手持ちの Windows 10 にはバージョン 1511 が Windows Update で落ちてこなかったので、直接 ISO を使ってアップグレードを行いました。メディア作成ツールでも出来るみたいです。

丸ごとアップデートになってるっぽいですが、40 分ぐらいでアップデート出来たので早く感じました。

Windows Update を待てない、堪え性のない人が思ったより多いみたいですね。

それはともかく、torne mobile でアニメを見るために iPad Air 2 をバージョン 1511 にアップデートした MacBook Pro に繋ぐと、充電中の表示になることに気が付きました。

これまでは MacBook Pro であっても Windows 10 で使っている場合には「充電していません」という表示になっていました。Apple のサポートには USB での給電が足りない場合に表示されるとあります。

一部の USB 2.0 ポートおよびアクセサリでは、iPad の充電に必要な電力が供給されない場合があります。このような状況では、ステータスバーのバッテリーアイコンの横に「充電していません」というメッセージが表示されます。

iPhone や iPod touch が充電されない場合 - Apple サポート (日本)

ビルド 10240 の時は「充電していません」表示になっていたと思いますが、恐らくアップデート後には iPad 側を見ても充電中表示になるようになった気がします。

ドライバーがアップデートされたなどの理由で、USB 周りの挙動が変わったのかも知れません。

ただし充電の速度はこれまでと同様に結構遅いです。10% 増えるのに 30 分はかかっていそうです。

WinQuickLook v1.0 を公開しました

Twitter では密かにバージョンアップを続けていましたが、個人的に満足できるレベルまで機能を追加できたので、一旦 v1.0 として公開してみることにしました。

ダウンロードは以下のリンクからどうぞ。

https://github.com/shibayan/WinQuickLook/releases/latest

Windows 10 専用の API を使っているので、それ以外のバージョンでは動きません。

ウィンドウの半透明化

WPF Window 周りの処理をガラッと変更したので、ついでに Windows 10 で追加された隠し API を使ってウィンドウ自体を半透明化しました。画像を表示する時、透過部分が分かりやすくなりました。

透明度やベースカラーは選べるようにした方が幸せかもしれませんね。将来的に考えます。

動画プレビュー時にコントロールを追加

動画プレビューをブログ公開バージョンに入れていたか覚えてないですが、これまでは途中で一時停止やシークといった基本操作が行えなかったので、簡単にコントロールを追加しました。

全体の再生時間の表示も付けています。再生時間もどこかに付けたいですね。

音楽ファイルのプレビューに対応

殆ど処理的には動画プレビューから持ってきただけですが、音楽ファイルの再生も行えるようになりました。

最近の Windows ではファイルに埋め込まれたアートワークをサムネイルにしてくれるので、個別に対応することなくアートワークを表示することが出来ます。

未対応ファイル、ディレクトリの表示改善

対応していないファイルやディレクトリはサムネイルを表示するだけだったのですが、Quick Look っぽくファイルの詳細な情報を表示するようにしました。

ディレクトリの場合は項目数が出ますが、これは第一階層にある項目数になります。

HTML プレビューのドキュメントモードを IE11 相当に

WebBrowser コントロールを使うと、デフォルトでドキュメントモードが Quirks になるみたいなので、レジストリの項目を使って IE11 相当のドキュメントモードになるようにしました。

Internet Feature Controls (B..C) (Internet Explorer) | Microsoft Learn

これで HTML5 や CSS3 を使ったページでも正しく表示されるようになります。

スタートアップへの自動登録

基本的に常駐するタイプのアプリケーションなので、スタートアップに追加するコマンドを付けました。

スタートメニューの Startup フォルダにリンクを作成するだけの簡単な方法です。

通知領域アイコンのクリックでアクティブ化

プレビューウィンドウがフォーカスを失っても表示されたままになるように変更したので、通知領域アイコンをクリックすることで一時的に最前面へ持ってくるようにしました。

複数起動ブロック

キーボードフックを使っているので Mutex を使って、複数起動させない処理を追加しました。

今後の予定など

  • マルチモニターへのちゃんとした対応
  • プレビューサイズの最適化
    • 動画の場合はサイズ計算が割と適当な感じ
    • IPreviewHandler はサイズ決め打ちなので何とかしたい
  • ちゃんとしたアイコンを付ける
  • 対応ファイル形式の拡充
    • C# などソースコードは色を付けて表示したい

GitHub にソースコードを置いて開発しているので、どっかのタイミングで公開したいです。

追記

準備が整った気がしたので、GitHub でソースの公開を始めました。AppVeyor を試しに使っています。

少しだけメモリ効率を改善したので v1.1.0 を出しました。Release からダウンロード出来ます。

オーストラリアで 3 キャリア分のプリペイド SIM を買って MADOSMA で使ってみた

オーストラリアに居る間に 3 キャリア分の SIM を買って、MADOSMA で試してみたのでまとめます。実際には 1 キャリア分だけ試せてませんが、SIM は買ったので含めておきます。

ちなみに MADOSMA でオーストラリアの LTE が使えるのかは既に書きました。

プリペイド SIM を販売しているキャリアは Optus / Vodafone AU / Telstra の 3 つになります。

空港では Optus や Vodafone AU のショップがあるので、割と簡単に入手出来るようです。Telstra に関しては市内のスーパーで売っていたので購入しました。基本的に $2 で買えます。

Optus

既に Optus に関しては書いたので割と省略しておきます。LTE のエリアはまあまあ広いですが HSPA に落ちることも度々ありました。特にタスマニアでは LTE は市内だけでした。

$10 単位でチャージ出来て、1 日に利用可能な最大データ通信料は $4 で 1GB です。この制限を超えると、その日は通信できなくなるので注意したいところです。

Vodafone AU

ケアンズで Vodafone AU の SIM を買い、$10 の Combo Plan でアクティベーションを行いました。

7 日間だけ使えるプランで 350MB しかデータ通信が付いていませんが、Vodafone AU は 1 日 $3 で 2GB 分データ通信量を追加できるので、大量に通信したい場合は Optus よりも便利です。

LTE のエリアは Optus と同じぐらいだと感じました。スピードもそれなり速いです。

ただし、グリーン島のビーチで試した時には全く繋がりませんでした。エリアは狭いのかもしれません。

Telstra

日本で言うところの docomo に相当するのが Telstra です。スーパーで SIM を買ってアクティベーションを行ったのですが、帰国するまでにアクティベーションが完了しませんでした。

少し先人を調べてみると、システム的な問題で 30 時間ぐらいかかることがあるらしいです。その場合は Telstra のお店に行けば良いみたいですが、ケアンズは駅にしかお店が無かったので行けませんでした。

今調べてみても、まだ完了していませんでした。短期滞在者が使うには向いていないようです。LTE のエリアは一番広いと聞いたので、試せなかったのが残念でなりません。

おまけ:電話番号が表示されない

あまり実害はないですが、Windows Phone の電話アプリを使って、現在の電話番号を確認することが何故か出来ませんでした。電話番号が表示されるべき場所自体が存在していません。

仕方ないので和歌山にいるかずあきさんの携帯にイタ電をして確認しましたが、後から思うと SMS に電話番号が毎回載っていたので、単なる国際イタ電になりました。

オーストラリアで MADOSMA を LTE で使ってみた

日本国内では SIM を入れずに、ほぼ Wi-Fi で検証用として使っていた MADOSMA ですが、今回オーストラリアに来ているので初めてプリペイド SIM を入れて使ってみました。

オーストラリアでは Optus / Telstra / Vodafone の 3 社が LTE でサービスを提供しているようですが、今回は Optus のプリペイド SIM をシドニー国際空港で購入して使ってみました。

国際線の出口を出てすぐに Optus の店舗があります。本当は向かい側に Vodafone があるみたいですが、今は改装中のようで閉まっていました。

Optus のプリペイド SIM は 3 種類ぐらいありますが、今回は 1 日 $2 で 500MB 使える Daily Plus を選んで、$20 チャージされているものを買いました。これで 1 週間は余裕で使えます。

ちなみに Optus が提供している LTE の周波数は公式サイトに書いてありました。

With 4G devices and a compatible plan, you can access our 3G network plus some or all of our 4G Plus network. Our 4G Plus network uses multiple frequencies (LTE 700 / 1800 / 2100 / 2300 / 2600 MHz) to provide coverage.

http://www.optus.com.au/shop/mobile/prepaid/plans

700 / 1800 / 2100 / 2600 が FD-LTE で、2300 は TD-LTE っぽいですね。

MADOSMA が対応している LTE の周波数は、こちらも公式サイトに書いてありました。


Band 1(2100MHz)/ Band 3 (1800MHz)/ Band 19 (800MHz)の3バンドによる高速通信LTEネットワークに対応しています。

パソコン(PC)通販のマウスコンピューター 公式サイト

MADOSMA は 1800 / 2100 を使った LTE には十分対応できるようです。日本と異なり LTE 1800 エリアの方が広いという噂ですし、日本だと docomo 向けの端末の方が有利かも知れません。

SIM のアクティベーションは店員さんがやってくれましたが、MADOSMA は APN を手動で設定しないと繋がらないみたいです。iPhone は何もせずに問題なくつながるようでした。

APN プロファイル一覧から Optus Internet を選択すると繋がるようになりました。ちゃんと LTE です。

通信速度

LTE での接続が上手くいったので、通信速度をメルボルンで計測してみました。1 回しか試していないので参考程度に考えてもらいたいですが、一般的な利用では十分な速度が出ていました。

下手なホテル Wi-Fi よりも速いみたいなので、500MB はあっという間に使い切ってしまいそうです。

テザリング

何の問題もなく、MADOSMA からインターネット共有を有効にするだけで使えるようになりました。

Monthly プランは分かりませんが Daily プランでは特に制限など掛かっていないようです。

Quick Look っぽく表示する WinQuickLook を更新しました

三連休の最終日は引きこもって、一昨日公開した Quick Look っぽく表示するアプリこと WinQuickLook を更新していました。名前は仮のつもりでしたが、新しく考えるのがめんどくさくなったのでこのままにします。

まだバージョニングしてませんが、多分これが v0.1 に相当するものだと思います。

http://shibayan.blob.core.windows.net/apps/WinQuickLook.zip
https://github.com/shibayan/WinQuickLook/releases

COM のリソースリークっぽい部分を修正したり、プレビュー可能ファイルの種類を増やしたり、プレビューのサイズがプライマリウィンドウからはみ出さないようにしたりと、細かい修正を行っています。

今日アップデートした中でも、分かりやすい部分だけ簡単に紹介しておきます。

テキスト、HTML ファイルのプレビュー

WPF の WebBrowser コントロールを使って、テキストや HTML のプレビューが出来るようになりました。

Markdown も一応表示できるようにしてますが、HTML へのレンダリングは行いません。

個人的には C# や C++ などのソースコードを色付けして表示まで出来ればいいと思っているので、良い感じに表示するライブラリがあれば考えます。

デスクトップでのプレビュー

これまではエクスプローラで表示していたファイルのみに対応していましたが、デスクトップ上のファイルに対してもプレビュー表示ができるようになりました。

ちなみにデスクトップの COM インスタンスを取得するには IShellWindows の FindWindowSW を使います。

更に GetForegroundWindow で取得したウィンドウがデスクトップなのか判別するために、以下のようなメソッドを作りました。ウィンドウクラス名で判別するようにします。

private static bool IsDesktopWindow(IntPtr hwnd)
{
    var classNameBuilder = new StringBuilder(Consts.MAX_PATH);

    NativeMethods.GetClassName(hwnd, classNameBuilder, Consts.MAX_PATH);

    var className = classNameBuilder.ToString();

    if (className != "Progman" && className != "WorkerW")
    {
        return false;
    }

    return NativeMethods.FindWindowEx(hwnd, IntPtr.Zero, "SHELLDLL_DefView", null) != IntPtr.Zero;
}

Space キーが押されたとき、このメソッドを使って FindWindowSW を使うのかコレクションから取得するのかを決めます。IWebBrowserApp を取得してしまえば、後の処理は全く同じなので共通化できます。

Windows 10 でも Quick Look っぽくファイルのプレビューが出来るアプリを作ってみた

先週の仕事中に Windows 10 でも Space キーを押すだけで、サクッとファイルをプレビューしたいという話になったので、少し調べてアプリを作ってみました。

実行ファイルは Azure Blob に置いてあります。Windows 10 x64 と .NET Framework 4.6 が恐らく必要になるというか、それ以外の環境では確認していませんし、確認する気もないです。

http://shibayan.blob.core.windows.net/apps/WinQuickLook.zip

通知領域に常駐するタイプのアプリなので、本当ならスタートアップ時に起動するようにしておくべきなのでしょうけど、まだ開発中なので zip での配布です。

エクスプローラでファイルを選択している状態で Space キーを押すと、以下の画像のようにプレビューがポップアップ表示されます。WPF が対応している画像なら、大きめの表示になります。

現時点では画像の DPI がおかしい場合に、表示が凄く小さくなることもあります。

Windows Vista から追加されたプレビューハンドラを使っているので、Word / Excel / PowerPoint などの対応アプリの場合には、そのままプレビュー表示できます。

表示中に Escape かもう一度 Space キーを押す、もしくはウィンドウがフォーカスを失えば消えます。

更に同じく Vista から追加されたサムネイルプロバイダーも使っているので、対応していないファイルやディレクトリの場合でも、何らかの画像は表示されます。

今後、ちゃんとファイル数やサイズなどを表示するようにしていきたいです。

久し振りに COM を使ったプログラムを書いたので、COM 周りのエラーハンドリングが出来ているか不安です。実装に必要だった要素について少しだけ紹介しておきます。

低レベルキーボードフックを仕込む

このアプリではプレビュー表示のトリガーとして、Space キーと Escape キーが押されたことを取得しないといけないので、C# から WH_KEYBOARD_LL フックを仕込みました。

http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx

9 年前の記事ですが、これがそのまま使えました。フックはちょっとめんどくさいです。

テキスト入力中か判別する

修飾キーを使わないタイプのショートカットだと、文字入力や変換中に誤爆する可能性があります。なので、現在入力中なのか判別する処理を入れます。

GetGUIThreadInfo function (Windows)

この API を使うと UI スレッドでキャレットが出ているかを判別できます。

選択されているアイテムを取得する

エクスプローラで選択されているアイテムを取得するには、COM を全力で使う必要があります。以下の記事がそのままの内容です。

Querying information from an Explorer window - The Old New Thing - Site Home - MSDN Blogs

これも 11 年前の記事ですが、Windows 10 でもそのまま使えました。

プレビューハンドラを使う

調べていたら、既にプレビューハンドラを Windows Forms で使っている記事が見つかったので、これを参考にして WPF に組み込みました。

処理の流れとしては、プレビューハンドラの CLSID をレジストリから取得し、インスタンスを作成して渡した HWND にレンダリングさせます。

IPreviewHandler interface (Windows)

IPreviewHandler インターフェースの仕様は MSDN に英語ですが存在しています。

アイテムのサムネイルを取得する

プレビューハンドラで対応していないファイルの場合には、IThumbnailProvider を使ってエクスプローラで表示されているアイコンを取得して表示します。

といっても、IShellItemImageFactory を使うと 特に意識することなく IThumbnailProvider に対応していない場合でも、古いインターフェースを使って取得してくれるみたいです。

IShellItemImageFactory interface (Windows)

IShellItem を作れば QueryInterface で簡単に取れるので、処理自体はとても単純でした。