WindowsAPI

HSPで高DPI対応ソフトを作ろう

投稿日:


こんにちは!

久しぶりにHSPの記事を書きたいと思います!
今回は、HSPの高DPI対応です。


はじめに

高DPIとはなんぞや、という説明をします。

昔のディスプレイは、1ドットのサイズが細かくないため、
1ピクセル=1ドットのような設計がほとんどでした。
そして、1ピクセルの大きさも、どのディスプレイもだいたい同じようなサイズ(96dpi)でした。
従って、ソフトを作る際に、1ドット=1ピクセルの前提で、GUIの設計をしていました。

ただ5、6年前ぐらいから、スマホが高繊細化してきており、
ディスプレイもRatinaディスプレイや4kディスプレイなど、高繊細なものが登場してきました。

例をあげると、次のようなものがあります。
Apple MacBook Pro 解像度 2560×1600、227dpi
Microsoft Surface Pro 解像度 2736×1824 、267 dpi
iiyama 4Kディスプレイ B2875UHSU-B1A 解像度 3840×2160、157 dpi

このように、96dpiより大きなものを高DPI(High DPI)と呼びます。

高DPIに対応していないソフトの問題点

このような高密度なディスプレイで、
これまで作成したソフトを実行するとどうなるでしょう。

高DPIで動作することを考えていないソフトの場合は、
OSがソフトのGUIを自動的にスケーリングして表示することとなります。

しかし、このスケーリングが問題でして、
ASCII.jp Windows 10+高解像度ディスプレイでのアプリのボケはRS2で解消される」のように
文字や画像がボケてしまうのです。

高DPI化に対応する方法と問題点

まず前提として、アプリ自身が「高DPIに対応してますよ!」と宣言しないといけません。
この宣言方法は、2種類あり、マニフェストで宣言するか、
アプリ内で「SetProcessDPIAware」を呼び出す方法があります。
これらの宣言方法については、「SetProcessDPIAware function」に記載されています。

一見、上記の方法だけで対応できるなら簡単じゃないかと思えるかもしれません。
実際の問題点は、高DPI対応宣言後の処理となります。
具体的には、座標、サイズ、位置などについて、
高DPIを考慮した数値で設定する必要が出てきます。

これから作るソフトならまだよいですが、今まで作ったソフトで高DPI化させようとした場合、
ソースコード上の全ての位置やサイズ情報を書き直す必要があるのです。

現実的な解決策

実は、今までのソースコード書き直しせず、簡単に解決することが可能です。
それは、標準関数の置き換えです。

以下に、いくつかの標準関数を置き換えたモジュールの例をおきます。
HIGHDPI モジュール
(このモジュールは、実際に私が作ったツールで利用しています。)

このように、標準関数を置き換えたモジュールを
ソースコードの最初でincludeすることで、
全コードが高DPI対応用の命令で実行させるということです。

おわりに

これで、高DPI対応に関する記事は終わりです。
ありがとうございました。

ちなみに、高DPI対応を試験する際の注意点として
ディスプレイの設定から、「拡大縮小とレイアウト」で「100%」から変更させるという方法があるのですが、
一旦、サインアウト・サインインをやり直す必要があります。

サインアウト・サインインをしないと、
GetDeviceCaps の HIGHDPI_LOGPIXELSX / HIGHDPI_LOGPIXELSY
で取得できる数値が96のままになってしまいます。
気が付かずに、すこしはまってしまいました……。

広告

マップオンデマンドの地図更新でパスワードが入力できない

投稿日: 更新日:


車を購入時にカーナビとしてNSZT-W61Gを付けたのですが、
カーナビ購入してから3年間はマップ情報のバージョンアップが無料ということで、
バージョンアップをしようとしました。

バージョンアップ方法の流れ
1. 購入時についていた「マップオンデマンドセットアップディスク」のDVDでセットアップツールをインストール
2. GAZOO」を無料でユーザー登録(「TOYOTA Web Passport」と同一?)
追記「MOD専用G-BOOK ID」では数値のパスワード作れるらしく、本問題自体を解決できるようです!
下記の話はログイン、出来なかったときに書いたものなので無視していいと思います。
3. マップオンデマンドのサイトからログイン
4. 購入時についていた取説の一番後ろのページにある「G-BOOK用車載端末ID」を入力
5. マップをダウンロード
6. あとは、取説通りに進める

といった感じなのですが、重大な問題が発生します。
それは、「マップオンデマンドセットアップディスク」でインストールした
専用アプリケーションに問題がある点です。(恐らく新しいセットアップディスクだと問題は起きません)

マップオンデマンドのツールでは、
G-BOOKか、GAZOO のどちらかのユーザー情報をGUIで入力する必要があるのですが、
このパスワード入力欄が、数値しか受け付けてくれません。

マップオンデマンド」のサイトにはたしかに、

2013年06月11日
【販売店装着オプションでSDナビをご利用のお客様へ】TOYOTA Web PassportのID、パスワード(PW)をご利用の場合、パスワードを「数字のみ」で設定登録してください。SD地図更新アプリを利用する際、PW入力時にエラーメッセージが表示される場合があります(ログイン画面のPW欄が英数対応していないため)。PWを「英数」で設定登録された方は、「数字のみ」に変更し、SD地図更新アプリをご利用下さい。バージョンアップにて英数対応予定です(別途、ご案内します)。

とあるのですが、解決方法の「パスワードを「数字のみ」で設定登録」に関しては、
そもそもパスワードが数字と英字両方を含めないと登録できない制約があるため、不可能なのです。

password

そのため、バージョンアップを待つ必要があると思いますが、
どこでバージョンアップツールをダウンロードできるのか、ちょっとわかりませんでした。
恐らくG-BOOK様に連絡すれば、ダウンロードできるかもしれません。
トヨタ様のディーラーに聞いても、下記のサポートディスクへ聞かないとわからないとのことでした。

マップオンデマンド・サポートデスク
0561-57-6814. 受付時間 9:00∼18:00

更新期日があと1日しかなく聞く時間がなかったため、
結局聞いてはいないのですが、バージョンアップする方法が分かりました。
このツールのメニューバーのヘルプの「最新バージョンを確認」でバージョンアップしてください。
すると、恐らくツールがバージョンアップできるはずです。
新しいバージョンでは英数字が入力可能のため、バージョンアップ後は問題が発生しなくなります。

ただし、私自身後で気が付いたものなので、上の方法ではうまくいかないかもしれません。
「最新バージョンを確認」自体がログインしないとできないものかもしれないからです。


一応、私がとった方法を紹介します。解決方法の1つとしてみてください。
方法とは、パスワードの入力欄の設定の「数値しか受け付けない」を解除させます。

専門的な話になりますが、Windowsの表示は多くが共通の部品によってできています。
この共通の部品は使い方が公開されており、みんなが知ることができます。
今回は、文字の入力用の共通部品であるエディットボックスを使用しており、
このエディットボックスに「数値しか受け付けない」という設定がされているわけです。
共通部品なので、ほかのソフトからもその設定を設定したり、逆に解除することができます。
今回は、その設定を解除することを行います。

1. パスワード入力欄のウィンドウハンドルを調査
2. GetWindowLong でウィンドウハンドルから、スタイル(GWL_STYLE)を取得
3. ウィンドウ情報から ES_NUMBER (0x2000) をビットマスクで削除
4. SetWindowLong でスタイル(GWL_STYLE)を再設定

これで、パスワード入力欄に英数字を入力できるようになります。
ログインをすると、新しいツールの確認が始まり、
新しいマップオンデマンドツールのバージョンアップされます。

上の手順をHSPというプログラミングツールで実行ファイルにしたものです。

ソースコード
実行ファイル

上記の実行ファイルを実行したときに何か発生しても責任をとることはできません。
自己責任でお願いします。

ウィンドウハンドルは、毎回異なるため、
WindowFromPoint でカーソル下のハンドルを取得可能する関数を使用しました。


追記
Yahoo知恵袋 「トヨタ純正カーナビで、データ更新をしようと思い、マップオンデマンドソフトを添…
fukushun1994様による解決方法の回答がありました。
MOD専用G-BOOK ID」というものをとるといいとのことです。


関連するブログ
MapOnDemandでちょいイラ‐(NSZT-W61G編)カッパっぱ、るっパッパ
ナビの地図データ更新&Gracenoteメディアデータベース更新*YOU*のページ

立て続けに…

投稿日: 更新日:


ここ立て続けに、「オンラインゲーム」と「システムのチェック」を公開したのですが
修正したいのが後から後から出てくる。

 修正したいの一覧

オンラインゲーム

 ・サーバーの状態で時間別の接続人数が、過去最大の接続人数になってる。
 1日以上サーバー付けっぱなしはなかったので気づかなかった

 ・サーバーを監視するプログラム
 サーバーは友人のを借りているので、
問題があった場合すぐさま再起動出来ない。
 また、サーバーはGUIでのみ操作するように作っちゃったので
なんか、その辺をどうにかしたい

 「システムのチェック

・多分64ビット版Vistaで終了できない
国産の言語HSPのバグ。対処方法はある。

そもそも窓の手がVistaで動かないらしいので
これ自体が動かない可能性も。 Vistaでテストする必要あるみたい

 ・タスクバーに表示される。

ダイアログっぽいウィンドウを目指してるので
ここに表示されたら雰囲気が……。)
でも、これ消したら、Win+Dとかどうなるんだろう。

ああ。いろいろ大変なことに。
 仕事も大変な時期なので、
ここら辺が完成したら、
しばらくゲーム作りとか休止したい。
 といっても、なんだかんだで更新続けそうですが。


7月2日追記
サーバー監視ソフト1つを残して全て解決しました。

レイヤードウィンドウ

投稿日: 更新日:


以前、アルファ値付きのウィンドウを作りたくて、
リージョンではなくレイヤードウィンドウについて色々調べてたのですが、
なんかうまくいかずに、結局HSPは32bitのウィンドウではなくて24bitのウィンドウのために、
アルファ値付きは不可能なんだと勝手に決めつけ断念していました。
で、昨日あたりからまた調べだして、UpdateLayeredWindowを使えばいいことが判明。
駄目もとで、一度HSPで作ってみようと頑張ったら完成しましたヾ(*ΦωΦ)ノ ヒャッホゥ
32bitのDIBとかは、すぽいと君のBITMAPのコピー処理の時に勉強してたので、そこらへんを流用。
何とか動いたんだけど、プログラム的にはちょっと心配(゜-゜*;)
しかしゲームとかと違って、Windowsプログラムはソース自体は短いのに理解するまでが大変ですね。(;´▽`A“
ちなみに、ただ単に透過色指定のSetLayeredWindowAttributesを利用したレイヤードウィンドウや、リージョンウィンドウと比べると
やっぱり、半透明の値をしっかりもっているので、UpdateLayeredWindowで作ったウィンドウはめっちゃきれい。v(‘▽^*)♪
↑下の方は、ディザリング処理と言うか、灰色の中間色が透過されないためギザギザしている。L(゜□゜)」オーマイガ!
とりあえず、モジュール化して公開してみたのでよかったら使ってください(^o^)丿
placearkモジュールレイヤードウィンドウ総合モジュールね^^ ~( ̄△ ̄~)(~ ̄△ ̄)~勝手にこんな大それた名前を^^;
ところでWindows2000にGetLayeredWindowAttributesがないのはちょっと・・・。

ファイルの順番が常に降順になってしまうときは

投稿日: 更新日:


以前、インターネット上で何かファイルを保存しようとするたびに、
表示されるダイアログ形式のエクスプローラにて、毎回ファイルが昇順ではなく降順に表示されてしまうという事件が起きました^^
右クリックから並び替えすれば元に戻るのですが、エクスプローラでファイルを開くたびにまたアイコンが降順に並べ替えられてしまうという呪い。
「すべてのフォルダに適用」もきかなかったような気がする。
それから、数ヶ月後に、直す方法をようやく見つけて、まあその場限りで直せたのですが
なぜ直ったか、いまいちよく分からなかったので、もう一度調べてみようと思いました。
で、問題はエクスプローラの設定が保存されているレジストリ
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\ShellState“です。
中は36byteのバイナリで記述されているのですが、この中には一体なにが書きこまれているのか、調べてみました。
typedef struct {
BOOL fShowAllObjects:1; 全てのファイルを表示する
BOOL fShowExtensions:1; 拡張子を表示する
BOOL fNoConfirmRecycle:1;  削除するときに確認を表示する
BOOL fShowSysFiles:1; システムファイルを表示する
BOOL fShowCompColor:1; 暗号化や圧縮されたNTFS圧縮ファイルをカラーで表示する
BOOL fDoubleClickInWebView:1; ダブルクリックでウェブ上に表示する
BOOL fDesktopHTML:1; アクティブデスクトップを使用する
BOOL fWin95Classic:1; enforce Microsoft Windows 95 Shell behavior and restrictions. 訳すの面倒
BOOL fDontPrettyPath:1; prevent the conversion of the path to all lowercase characters. 訳すの面倒
BOOL fShowAttribCol:1; 使用されていない
BOOL fMapNetDrvBtn:1; NetworkDriveを表示する
BOOL fShowInfoTip:1; ファイルやフォルダでポップアップで説明を表示する
BOOL fHideIcons:1; デスクトップのアイコンを隠す
BOOL fWebView:1; ウェブページとして表示する
BOOL fFilter:1; 使用されていない
BOOL fShowSuperHidden:1; OSのファイルを表示する
BOOL fNoNetCrawling:1; 自動で無効なネットワークドライブやプリンタを調べる
DWORD dwWin95Unused; 使用されていない
UINT uWin95Unused; 使用されていない
LONG lParamSort; アイコンを並び替える
int iSortDirection; アイコンの名前でアルファベットにおいて、1で昇順ソート・-1で降順ソートを行う
UINT version; 使用されていない
UINT uNotUsed; 使用されていない
BOOL fSepProcess:1; ウィンドウズのフォルダを個別のプロセスで起動する
BOOL fStartPanelOn:1; スタートメニューをクラシックスタイルではなく、XP風にする(XPのみ)
BOOL fShowStartPage:1; 使用されていない
BOOL fAutoCheckSelect:1; フォルダをクラシックスタイルではなく、Vista風にする(Vistaのみ)
BOOL fIconsOnly:1; サムネイルを利用せずに、一般的なアイコンのみ表示する(Vistaのみ)
BOOL fShowTypeOverlay:1; 実行ファイルのアイコン?サムネイルのこと?なんたらかんたら(Vistaのみ
UINT fSpareFlags:13; 字あまり
} SHELLSTATE, *LPSHSHELLSTATE;

SHELLSTATE Structure ()より

話し変わるけど、「UINT fSpareFlags:13;」このビットフィールドのデータがどのようになっているのかよく分からない^;
うん、でこの中のソート関係の設定、「lParamSort」と「iSortDirection」が、その変なことを起こさせる原因になると思う。
一応この2つの設定は4byteだから、簡単に目でなおせそうな気がする。
0でデフォルトだから、治したい人は、この2つの項目を両方とも0にしてみるといいかもしれないです。
あと上の方と下の方のBOOL型のパラメータは、ビットフィールド使ってるので、レジストリエディタから直すの激しく面倒。
時間あったから、HSPでこのレジストリを読み込んだり書き込んだり内容を表示するのを書いてみた。
そしたら、実際は拡張子は表示させているのに「fShowExtensions」がFALSEになっていたり、
未使用のはずの「dwWin95Unused」や「fSpareFlags」になぞの数字が書き込まれていた^^;
まだ先月にWindowsインストールしたからレジストリはあんまり汚れていないと思うんだけど。なんでだろう。
関連なページ