Windowsには,GDIベースのアプリケーションが高解像度ディスプレイでも鮮明に表示されるようにするための表示スケールという仕組みがあります。GDIは,Windowsネイティブアプリで2Dグラフィックを描画するための標準的なAPIのひとつで,高解像度ディスプレイ以前から存在し,テキスト・アイコン・図形・画像といった2Dグラフィックを常に96 DPIで描画するように設計されています。GDIで描画した画面が高解像度ディスプレイで縮小されないようにするためには,実際のDPIに合わせて画像を拡大する必要があります。画面がぼやけて表示されるのはそのためです。
Creators Update(Windows 10 1703)では,この現象を改善するため,GDIスケーリングという仕組みが導入されました。アプリの表示スケールの修正で表示がぼやける可能性があるといわれている一部のデスクトップアプリは,GDIで画面を描画しているアプリのことを指しています。4Dは,GDIとDirect2D(高解像度ディスプレイに対応したAPI)を併用しているので,これに該当します。
高解像度ディスプレイ(4Kなど)を搭載したノートパソコンに標準的な外部モニター(1080pなど)を接続し,デスクトップを拡大しているユーザーは少なくありません。その場合,ノートパソコンは解像度を200%(192 DPI)に設定し,外部モニターは100%(96 DPI)のまま使用する,といったことができます。従来のスケーリングでは,物理的なサイズを再現するため,画面の解像度に合わせて画像を引き伸ばしていました。そのように拡大された画像は,96 DPIのデータしか持ち合わせていないため,おおきなピクセルで表示されたり,ぼやけて表示されたりします。
ディスプレイ毎のDPIを考慮し,場面に合わせて動的に画像データを差し替えるようにアプリが設計されていれば良いのですが,高解像度ディスプレイ以前から存在するGDIアプリは,そのような仕組みを持っていません。GDIスケーリングは,アプリの代わりにシステムがスケーリングするので,DPIを意識したプログラミングをしなくても良い,というメリットがあります。特にテキストの表示が改善されます。
GDIに限らず,Windowsアプリには,下記のDPIモードが用意されています。
DPIを気にしない。100%(96 DPI)を前提に描画します。その他の解像度は想定されていません。
システムDPIに合わせる。ユーザーがログインした時点におけるメイン画面のDPIを前提に描画します。メイン画面は鮮明に描画されますが,その他のモニターは表示がぼやける可能性があります。
モニター毎のDPIに合わせる。モニターのDPIに合わせて描画します。正しく開発されていれば,モニター間でウィンドウを移動しても,鮮明に画面が表示されます。
ウィンドウ別にDPIを管理する。上述したモードを組み合わせてアプリを開発することができます。
High DPI Desktop Application Development on Windows
GDIスケーリングは,実際のDPIと同等以上(x2, x3, x4など)の解像度でテキストやベクトル図形をレンダリングした後,Desktop Window Manager (DWM) が合成したビットマップを画面に表示するというものです。画面の解像度96の倍数であれば,DWMは使用されません。いずれにしても,単純な拡大よりも鮮明な表示が期待できます。96 DPIのデータしか持ち合わせていないビットマップ画像は,引き延ばされてレンダリングされるため,ぼやけて表示されます。また,実際のDPIが96の倍数でなかった場合,単純な拡大ほどではありませんが,テキストやベクトル図形であっても,ぼやけて表示されるという限界があります。
GDIスケーリングは,おもにテキストの表示を鮮明にすることを意図した仕組みですが,一部の文字は端のピクセルが欠落されて表示されないことがあります。たとえば,10ptのフォントを200%の画面に表示する場合,20ptのフォントが2倍の領域にレンダリングされますが,フォントや文字の種別により,テキストの線が「太く」なれば,表示領域の幅が200%を超えることがあるためです。
前述したモードとGDIスケーリングの関係は,下記のとおりです。
DPIを気にしない: GDIスケーリングは適用されません。
システムDPIに合わせる: システムDPIよりも高解像度の外部モニターであっても,GDIスケーリングが適用されることにより,図形とテキストの表示が改善されます。システムDPIは,ユーザーがログインした時点におけるメイン画面のDPIなので,途中でメイン画面を別のディスプレイに切り替えたり,メイン画面の解像度を変更した場合,従来のスケーリングは再ログインするまで表示がぼやけたままになりました。GDIスケーリングが有効であれば,システムがDPIの変更を検出するので,自動的に表示が調整されます。
モニター毎のDPIに合わせる: すでに高解像度ディスプレイを意識したアプリであれば,GDIスケーリングを使用する必要はないはずです。テキストや図形はもちろんのこと,ビットマップ画像もDPIに合わせたものを使用しているので,GDIスケーリングよりも鮮明に画面が描画されます。これには,チェックボックスやポップアップメニューのキャレット(実際にはビットマップ画像)も含まれます。カーニング(隣接する文字の距離の計算)も係数を掛けるのではなく,実際のフォントサイズに基づいて計算されるため,GDIスケーリングよりも自然になります。このようなアプリでは,GDIスケーリングを無効にしたいと思うでしょう。判断の材料として,それぞれのモードでアプリを実行して詳細な点を比較することができます。
アプリには,開発者が設定したデフォルトの表示モードがありますが,「プロパティ>互換性>高 DPI 設定の変更」で上書きすることもできます。「システム(拡張)」がGDIスケーリングです。4D v18は,このモードに設定されています。「アプリケーション」に設定した場合,スケーリングが無効となります。「システム」は,Creators Update(Windows 10 1703)以前のスケーリングです。
ユーザーは,プロパティで自由にスケーリングの設定を変更することができます。,IT管理者は,System Center Configuration Manager (SCCM) やMicrosoft IntuneでGDIスケーリングのポリシーを設定することにより,これを制御したいと考えるかもしれません。
参考資料
Improving the high-DPI experience in GDI based Desktop Apps
前述したように,4DはGDIとDirect2Dを併用しています。GDIスケーリングを無効にした場合,Direct2Dで描画されている部分は鮮明に表示され,そうでない部分は96 DPIの位置とサイズにレンダリングされます。「システムスタイルシート」は自動的に調整されますが,その他のフォントサイズは絶対値で計算されるので,文字が小さくなります。スケーリングが適用されないため,画面のレイアウトは変わりますが,すべて鮮明に表示されるというメリットがあります。
MDIウィンドウの「閉じるボタン」上でマウスポインターを移動すると,ボタンが高速で点滅するという現象が報告されています。これはGDIスケーリングの不具合であることがわかっています。「高 DPI 設定」を「アプリケーション」に変更した場合,あるいは96 DPIの画面であれば,問題は発生しません。
具体的には,GDIスケーリングで描画されているウィンドウのウィンドウプロセスマネージャーで,WM_NCMOUSEMOVE
メッセージ処理中にWindowFromPoint
を呼び出した場合,ボタンのハイライト表示がリセットされることがわかっています。
Mac/Windowsの違いを吸収し,過去のバージョンでデザインされたフォーム等を高解像度ディスプレイで同じように表示するためには,WindowsのGDIスケーリングを利用するのが,現状,最良のソリューションであるように思われます。4D側でこの現象を解消することは困難かもしれません。
コレクション型に対し,文字列のTrue
またはFalse
でクエリを実行した場合,ブール値はヒットしません。これは仕様です。
$entitySelection.query("value = False")
パラメーターを使用せずにリテラル値で検索文字列を記述した場合,ブール型同士ではなく,ブール型と文字列の比較演算となり,大文字と小文字が区別されることになります。エンティティセレクションであれば,フィールド型が決まっているため,文字列をブール型に変換して検索を実行することができます。しかし,コレクション型の場合,そのような「ヒント」が利用できません。リテラル値はtrue
またはfalse
と記述する必要があります。
同一マシンに4D Serverのライセンスをインストールし,複数のインスタンスを同時に起動した場合,サーバーはクライアント接続ライセンスを分け合うことになります。つまり,一方のサーバーにクライアントが接続するたびに,他方のクライアントに接続できるクライアント数が減少します。ただし,他のサーバーが使用しているライセンスは,サーバー管理画面に表示される接続ユーザー数の計算に含まれません。これは仕様です。Get license info
から返されるusedCount
も同様です。
Write Proの標準アクションprint
は,プレビューを表示してからページビューモードで印刷を実行します。つまり,ヘッダーやフッターが非表示に設定されていれば,印刷はされません。
コマンドのWP PRINT
をすれば,プレビューを省略することができますが,印刷されるのはドキュメント全体なので,ヘッダーやフッターも印刷されることになります。これは仕様です。
Write Proのwk decimal
タブ(小数点の位置で数値を揃える)は,ピリオドとカンマのいずれかを小数点として認識します。地域と言語の設定は考慮されませんので,桁区切りと併用することはできません。これは仕様です。
ツールボックスのメニューエディターには「イベントを発生させない」というプロパティが存在します。このイベントとはOn Data Change
のことです。
編集メニューの「ペースト」標準アクションに「イベントを発生させない」プロパティが設定されていない場合,アプリケーションモードでは,ペーストの直前にOn Data Change
イベントが発生します。
これは,通常のタイミング(入力を確定した時点)よりも早く,値が変更される前のことなので,奇妙に感じるかもしれません。編集メニューの標準アクションは,原則的に「イベントを発生させない」設定にしたほうが良いでしょう。これには「取り消し」「やり直し」「カット」「ペースト」アクションが含まれます。
ビルド253159
(18r4)以降,プロジェクトメソッド呼び出しのトークナイズが変更されています。メソッド名とカッコ((
)の間にスペースは挿入されなくなりました。たとえば「デザインモード検索」を実行する場合,新しいトークナイズをサーチフレーズに入力する必要があります。
ビルド252873
(18r5)以降,コメント文のトークナイズが変更されています。シングルラインコメント(//
)の前に2
個のスペースは挿入されなくなりました。METHOD GET CODE
で取得したメソッドのメタ情報(//%attributes...
)も同じように「スペース無し」で返されます。
4Dでは,日付リテラル(定数)をメソッドエディターに記述することができます。
$日付:=!1920-06-30!
ドキュメントに記述されているように,日付リテラルのフォーマットはv15で改定されました。
-
)YYYY-MM-DD
00-00-00
過去のバージョンでは,区切り文字と年月日の順序はシステムのロケール(地域と言語)設定に左右されました。世界的にみて,もっとも一般的なフォーマットは「日月年」または「月日年」,区切り文字はピリオド(.
)またはスラッシュ(/
)記号というものです。
メソッドに入力された日付リテラルは,トークナイズされ,内部的に「年・月・日」に分解されて保存されます。システムのロケールが違う環境でメソッドを開いた場合,日付リテラルのフォーマットは自動的に変換されますが,コピー&ペーストをしたり,メソッドのソースコードをテキスト形式でインポートした場合は,別の値になってしまう恐れがあります。
日本のように「年月日」という順序を採用しているロケールはあまり多くありません。また,区切り文字にハイフン記号を使用しているロケールも,スウェーデン語など,ごく少数です。大抵の地域では,日付リテラルの仕様がv15で変更されたことにすぐに気づきましたが,日本の場合,以前の仕様がISOフォーマットに似ているため,変更に気づかなかったかもしれません。
メソッドエディターにピリオド(.
)またはスラッシュ(/
)区切りで日付リテラルを入力した場合,トークナイズにより,区切り文字が自動的に変換されてハイフン(-
)になります。同時に,2
桁で入力された年は自動的に4
桁に変換されます。
!20/6/30!
→ !2020-06-30!
!20.6.30!
→ !2020-06-30!
SET DEFAULT CENTURY
でデフォルト世紀を変更しない限り,29
年以前の日付は21世紀,30
年以降の日付は20世紀,とみなされます。
両方の区切り文字にハイフン(-
)を入力した場合,2
桁で入力された年はトークナイズで4
桁に変換されません。下記の例では,1世紀の日付を入力したことになります。
!20-6-30!
→ !20-06-30!
当然,この日付で検索を実行した場合,1920年あるいは2020年のレコードはヒットしません。
メソッド日付リテラルを記述する場合,下記いずれかの方法で入力するように注意してください。
.
)またはスラッシュ(/
)を使用する(4
桁に変換されます)-
)を使用するのであれば,年を4
桁で入力する