Hatena::ブログ(Diary)

hishidaのblog このページをアンテナに追加 RSSフィード

プロフィール

hishida

hishida

EB series support page 管理人 ブログ

2016-12-01 EBWin4 の高DPI化について このエントリーを含むブックマーク このエントリーのブックマークコメント

EBWin4の高DPI化を行ったので、忘備録として作業内容をまとめておこうと思う。

事の発端は、Macbook pro retina 13" Early2015を購入したこと(Macbook pro retina 13” Early 2015購入記 - hishidaのblog)。retinaディスプレイではVMWare Fusion上のWindowsの文字が極端に小さくなり、文字サイズを拡大しないと使用できなくなった。

Macbook pro retina 13"の実解像度は2560x1600だが、Mac OS Xでは擬似解像度1280x800にスケーリングされて表示される。だがVMWare 上のWindowsではドットバイドットで表示されるので、2560x1600の実解像度のまま表示され、文字が小さくなってしまう。

ディスプレイ設定」→「テキスト、アプリ、その他の項目のサイズを変更する:」で150%〜200%に拡大すると、DPIのスケーリングに従ってアプリも拡大されて表示される。だがEBWin4のように高DPIに対応していないアプリだと、下図のように文字がにじんで表示されてしまう。Surface Proなどの高解像度の端末では、以前から問題になっていたと思う。

図:高DPIに対応していない場合、文字サイズを拡大するとにじんで表示される:

f:id:hishida:20161202110628p:image

Windows Form アプリの高DPI化作業について

DPI化全般については、下記のマイクロソフト田中達彦氏のブログが詳しい。

アプリの高DPI(High DPI)対応について 第1回 ~ 高DPIとは ~ – 田中達彦のブログ

WPFで開発したソフトは自動的にdpiAwareになるが、昔ながらのWindows Formで開発したソフトは、デフォルトでは高DPIに非対応となる。

Windwos FormでアプリをdpiAwareにする方法は簡単で、前述のブログにあるように、app.manifestを追加してdpiAwareをtrueにすればいい。

app.manifestは、Visual Studio でプロジェクトで右クリック→追加(D)→新規項目(W)で簡単に追加できる。

ただしdpiAwareの雛型が作られるのはVisual Studio 2013以降なので(現行のVisual Studio Community 2015もOK)、Visual Studio 2010以前のバージョンを使用している場合は、記述を手動で追加する必要がある。

app.manifestに追加した記述:

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
  </application>

基本的には、これだけでdpiAwareになり、文字サイズを拡大しても文字がにじまなくなる。

ただEBWin4の場合はEPWINGの外字をビットマップイメージで表示しており、文字サイズを変えても外字ビットマップは小さいままなので、表示のバランスが非常に悪くなる。

つまり現在のWindowsの文字サイズの倍率を取得して、ビットマップ画像も拡大しなければならない。

様々なサイトを参考にして、現在のDPIを取得するサポートクラスを追加した:(100%なら96dpiを返す)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;


namespace EBWin4
{
    public static class ScreenExtensions
    {
        public static void GetDpi(this System.Windows.Forms.Screen screen, DpiType dpiType, 
                   out uint dpiX, out uint dpiY)
        {
            try
            {
                var pnt = new System.Drawing.Point(screen.Bounds.Left + 1, screen.Bounds.Top + 1);
                var mon = MonitorFromPoint(pnt, 2/*MONITOR_DEFAULTTONEAREST*/);
                GetDpiForMonitor(mon, dpiType, out dpiX, out dpiY);
            }
            catch
            {
                dpiX = 96;
                dpiY = 96;
            }
        }

        //https://msdn.microsoft.com/en-us/library/windows/desktop/dd145062(v=vs.85).aspx
        [DllImport("User32.dll")]
        private static extern IntPtr MonitorFromPoint([In]System.Drawing.Point pt, [In]uint dwFlags);

        //https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx
        [DllImport("Shcore.dll")]
        private static extern IntPtr GetDpiForMonitor([In]IntPtr hmonitor, [In]DpiType dpiType, [Out]out uint dpiX, [Out]out uint dpiY);
    }

    //https://msdn.microsoft.com/en-us/library/windows/desktop/dn280511(v=vs.85).aspx
    public enum DpiType
    {
        Effective = 0,
        Angular = 1,
        Raw = 2,
    }
}

上記クラスを使用して、現在の文字サイズのスケールを取得する関数

        /// <summary>
        /// ScreenのDPIスケールを得る
        /// </summary>
        /// <returns></returns>
        private double GetDPIScale()
        {
            double dpiScale = 1.0;
            try {
                //  現在フォームのあるスクリーンを得る
                System.Windows.Forms.Screen s =
                    System.Windows.Forms.Screen.FromControl(this);
                uint x, y;
                s.GetDpi(DpiType.Effective, out x, out y);
                dpiScale = ( x / 96.0);
            }
            catch {
            }
            return dpiScale;
        }

DPIスケールに合わせて画像を拡大する関数

      /// <summary>
        /// DPIに応じて拡大したImage画像を作成
        /// </summary>
        /// <param name="image"></param>
        /// <param name="dpiScale"></param>
        /// <returns></returns>
        private Image GetImageStretchedDPI(Image image, double dpiScale)
        {
            Size newSize = image.Size;
            newSize.Width = (int)(newSize.Width * dpiScale);
            newSize.Height = (int)(newSize.Height * dpiScale);

            Bitmap newBitmap = new Bitmap(image, newSize);

            image.Dispose();
            return newBitmap;

        }

これで高DPIで美しく文字が表示されるようになった。

図:高DPI化されたEBWin4

f:id:hishida:20161202110623p:image

DPI時代のEPWINGビューアとして、もうしばらく延命できることとなった。

2016-11-19 Macbook pro retina 13” Early 2015購入記 このエントリーを含むブックマーク このエントリーのブックマークコメント

Macbook proキーボードに落胆

およそ1年半ぶりのアップデートとなる新Macbook pro retina 13"/15"が発表された。新機能のTouch Barに注目が集まっているが、従来のAirの置き換えを狙ったと思われる TouchBar無しモデルも提供されている。

私のメインの開発機のMacbook pro 13" mid 2012は2.02kgもあり、持ち歩きに厳しさを感じていたので、新Macbook proが出たら買い換えるつもりでいた。ところが実際に店頭で触った結果、Macbook 12"と同じストロークの浅いキーボードにどうしても馴染めない。

「第二世代パンタグラフになって打鍵感が向上している」という触れ込みだったが、Macbook 12"と2台並べて打ち比べてみても、違いが全くわからない。軽量化されたボディと画面の明るさには魅力を感じるが、実際このキーボードプログラミングや文章作成を行うのは非常に厳しい。

また外部 I/FがUSB-Cだけというのも、現実問題としては不便である。将来的にUSB-Cが普及することは間違いないが、変換アダプタを持ち歩かないと何もできないのは困る。特にデジカメからSDで写真を取り込む機会が多いので、SDカードスロットは残してほしかった。また電源コードもUSB-Cになったので、力が加わった場合にMagSafeのように外れないので、破損しそうで怖い。(USBバッテリで充電できるというメリットはあるが)

あえて旧モデルの整備済品を購入

結局、新モデルの購入は見送り、Apple Storeで整備済品のMacbook Pro retine 13" Early 2015 (2.9GHz/core i5/8GB/512GB SSD)を購入することにした。為替レートが反映されたこともあって、税抜143,000円と大幅に安くなったし、性能的には新モデルと同等である。

整備済品は外箱が簡略化されているが、バッテリは新品に交換されていて一年保証もつき、Apple Careにも加入できる。実際上新品と同じでお買い得である。

これまで4年2ヶ月使用したMacbook pro 13" mid 2012は、中古ショップで42,000円で買い取ってもらえた。差額約10万で買い替えできたことになる。

追加アクセサリーとして、予備で持っていたMagsafe ACアダプタを活用するために、Magsafe-Magsafe2変換アダプタを購入した。

あとはThunderboltのポートが余っていて勿体無いので、Thunderbolt-Ethernet アダプタを購入しようと思う。

Macbook Pro retine 13" Early 2015 の感想

購入して2週間ほど使用してみたが、やはりretinaディスプレーの美しさは圧倒的で、満足度は高い。特にデジカメで撮影した写真の鑑賞には非常に向いている。

1.58Kgという重量は、新Macbook proよりは重いが、Macbook pro 13" mid 2012から比較すると420g軽いし、バッテリ駆動時間が長いのでACアダプタを持ち歩かなくていいことも合わせれば、実質的に650gの軽量化になる。これはミラーレス一眼のボディ+交換レンズ2本分ぐらいに相当する。

これであと最低3年は使用して、その後の買い替えはUSB-Cの普及を見てから考えようと思う。

Retinaディスプレーで一つ問題になったのは、VMWareWindowsを使用した時に、ドットバイドットで表示されるために文字が小さすぎるということ。

文字サイズを拡大すれば解決するが、ここで拙作のEBWin4が高DPIに対応していないという問題が明らかになってしまった。調べたところ、Windows Formで開発したアプリデフォルトでは高DPIに非対応だが、app.manifestの設定でDPIawareにできることがわかった。ということで、近日中に高DPIに対応したEBWin4を公開予定である。retinaディスプレーの思わぬ副産物である。(次のエントリに続く)

2016-11-18 EBPocket for iOSのバグ報告について このエントリーを含むブックマーク このエントリーのブックマークコメント

しばらく前から、AppStoreのレビューで、EBPocket for iOSが他のアプリから切り替えた時に落ちるという報告がリリース毎に投稿されている。

当方もレビューは読んでおり、手元のiPad mini2(iOS10)とiPod touch(iOS8)及びシミュレータで動作確認しているが、落ちるような致命的なバグは発見できない。

ご存知のようにAppSotreのレビューには作者からの応答はできないので、一方的なネガティブキャンペーンになっており、作者の開発意欲を非常に削ぐ状態になっている。

報告者の大半(もしかすると全て)が中国人なので、StarDictやMDictに限った話なのかもしれない。

誰でもいいですが、具体的に「落ちる」という状況の辞書とOSと機種を報告してくれませんか。

再現できないと直しようがないので。

2016-11-04 EBPocket for iOS の中華フォント現象 このエントリーを含むブックマーク このエントリーのブックマークコメント

「iOS10から、EBPocket for iOSの本文の日本語部分のフォント中国語繁体字になっている」というご指摘があった。iPad mini2で確認すると、英語フォントを指定した場合、確かに中国語の字形になっている。フォントの初期値をヒラギノではなく英語フォントのTimesNewRomanPSMTにしているのは、英和辞典などで文字のバランスがよいためだが、以前は日本語部分はヒラギノで表示されていた記憶がある。

調べてみると、最近のiOSでは中華フォント現象というのがあるらしい。

iOS で日本語文章に発生する中華フォント現象とは - Qiita

ただこのページで書いてある解決方法はSwiftの話で、EBPocketではObjective-CでUIWebViewを使用して本文を表示しているので、そのまま適用できない。

いろいろ試したところ、次のように、UIWebViewに表示するhtmlにlang="ja"をつければいいということがわかった。これでめでたく日本語部分がヒラギノで表示されるようになった。

<!DOCTYPE html>
<html lang='ja'>

言語の指定がないと標準で英語(lang='en')になり、iOSフォントの優先順位で中国語が日本語より先にあるために、フォールバックで中国語フォントが選ばれるらしい。

とりあえず中華フォント現象のみ対応したバージョンをAppStoreに提出した。iOSのバージョンが上がってから初めての提出なので、審査が通るかどうかちょっと不安。

やっぱりiOSのバージョンが上がると必ず何かしら問題が起きるなぁ。

P.S.

AppStoreの審査は1日で通過し、本日リリースされた。最近は審査がスピードアップされているらしい。

2016-11-03 読書尚友・EBPocketをマテリアルデザインに対応 このエントリーを含むブックマーク このエントリーのブックマークコメント

Androidアプリ読書尚友とEBPocketを、マテリアルデザインに対応してみた。

f:id:hishida:20161103094214p:image

f:id:hishida:20161103094210p:image

f:id:hishida:20161103094205p:image

マテリアルデザインはiOSなどのフラットデザインに似ているが、画面のパーツが現実世界の素材のメタファになっており、厚みや奥行き、重なり、質量を持つ。

GoogleGoogle I/O 2014でマテリアルデザインのガイドラインを出したが、当初はGoogle謹製のアプリのようなUIを実現するには開発者が自前でコードを書く必要があった。2015年にDesign Support Libraryが公開されたことで、マテリアルデザインに沿ったアプリを作りやすくなった。

個人的なAndroidの開発環境をEclipseからAndroid Studioに移行したことで、これらのライブラリの導入が簡単になった。もうEclipseには戻れないと思う。

Android Studio では新しいプロジェクトを作るときのテンプレートマテリアルデザインに沿ったアプリの雛形を生成できるので、自動生成されるレイアウトリソースを流用したほうが作業が早い。

今回のマテリアルデザイン化の作業をまとめてみると:

	Theme.AppCompat.Light.DarkActionBar
	Theme.AppCompat.Light.Dialog
  • 配色はマテリアルデザインガイドにあるものを使用する
  • 従来のFragmentActivityやActionBarActivityのかわりにAppCompatActivityを使う
  • ActionaBarのかわりにToolBarをつかう。(ただしAppCompatActivityで従来のActionaBarも使える)
  • Design Support Libraryの部品を使う。今回使用したクラスは、
android.support.design.widget.CoordinatorLayout
android.support.design.widget.AppBarLayout
android.support.design.widget.NavigationView
android.support.v7.widget.Toolbar
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support:design:23.4.0'
    compile 'com.android.support:support-v4:23.4.0'

EBPocketのほうはマテリアルデザインの導入を機にかなりUI見直したので、操作性が向上したと思う。

  • ActionBarメニューは本文に関するメニュー(共有、ブックマーク登録、ページ内検索)だけ残し、他はナビゲーションドロアに移動。
  • グループ選択とグループの編集がナビゲーションドロアでできるようにした。グループ切り替えが迅速にできるようなった。
  • ブックマーク、最近の項目、履歴を共有で外部アプリに渡せるようにした。
  • オーバースクロールによる前画面移動をオプションでオフにできるように。
  • SearchViewの検索履歴ポップアップをデフォルトでオフにした。

EBPocketの今後の課題

  • PDIC,MDict,StarDictでブックマークを保存できるようにする
  • App Indexngに対応する。Google検索にアプリ検索を表示する機能。従来は端末内検索という機能があったが、Kitkat以降削除され、App Indexingが推奨されるようになった。

ただしApp IndexngはWebサービスも必要で、アプリだけ登録する場合は申請フォームから申請の必要があるらしい(まだ十分に調べていない)

  • 要望の上がっているところではAnki連携。ただ私がまずAnkiになれないといけない。
  • あとは単語帳とか、英語学習的な機能を充実できれば。

読書尚友の今後の課題

  • 本棚をRecycleViewにして、カード形式とグリッド形式を切り替えられるようにする。
  • ファイルブラウザの機能向上