8

ユーザーがWindowsのフォントサイズを通常のフォントから特大のフォントに変更したときに検出する方法を決定しようとしています。フォントサイズは、WindowsXPマシンで次の手順を実行することによって選択されます。

  1. デスクトップを右クリックして、[プロパティ]を選択します。
  2. [外観]タブをクリックします。
  3. フォントサイズを選択します:通常/大きいフォント/特大フォント

フォントサイズを変更するとDPIが変更されると理解しているので、これまでに試したことは次のとおりです。


私の目標:

Windowsのフォントサイズが通常のフォントから大きいフォントまたは特大のフォントに変更されたことを検出し、そのフォントサイズの変更に基づいていくつかのアクションを実行したいと思います。Windowsのフォントサイズが変わると、DPIも変わると思います(特にサイズが特大フォントの場合)


私がこれまでに試したこと:

WM_SETTINGCHANGE、WM_NCCALCSIZE、WM_NCPAINTなどを含むいくつかのメッセージを受け取りますが、これらのメッセージはいずれも、フォントサイズが変更されたとき、つまり、何が変更されたかを知りたいWM_SETTINGSCHANGEメッセージを受け取ったときの状況に固有のものではありません。

理論的には、OnSettingChangeを定義し、Windowsがそれを呼び出すと、lpszSectionは変更セクションが何であるかを教えてくれますが、それは正常に機能しますが、SystemParametersInfoを呼び出して特定のセクションを確認し、アクションSPI_GETNONCLIENTMETRICSを渡します。デバッガーと私は、返されたNONCLIENTMETRICSのデータでフォントの変更がないかどうかを確認しますが、何も発生しません。

それがうまくいかなかったとしても、設定が変更されたときにDPIを確認できるはずです。他の詳細については気にしません。WM_SETTINGCHANGEメッセージを受け取るたびに、DPIを確認して、実行したいアクションを実行するだけですが、システムDPIも取得できません。

DCごとにGetSystemMetricsメソッドを呼び出して、DPIを取得しようとしました。

デスクトップDC->GetDeviceCapsLOGPIXELSX/LOGPIXELSYウィンドウDC->GetDeviceCapsLOGPIXELSX/LOGPIXELSY現在のDC->GetDeviceCapsLOGPIXELSX / LOGPIXELSY

グラフィックプロパティウィンドウでDPIを変更しても、これらの値は何も変わらず、常に96と表示されます。

誰かが私がこれを理解するのを手伝ってくれませんか?何を探すべきですか?どこを見ればいいの?

afx_msg void CMainFrame::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
{
    int windowDPI = 0;
    int deviceDPI = 0;
    int systemDPI = 0;
    int desktopDPI = 0;
    int dpi_00_X = 0;
    int dpi_01_X = 0;
    int dpi_02_X = 0;
    int dpi_03_X = 0;

    CDC* windowDC = CWnd::GetWindowDC(); // try with window DC
    HDC desktop = ::GetDC(NULL); // try with desktop DC
    CDC* device = CWnd::GetDC(); // try with current DC
    HDC hDC = *device; // try with HDC
    if( windowDC )
    {
        windowDPI = windowDC->GetDeviceCaps(LOGPIXELSY); 
        // always 96 regardless if I change the Font 
        // Size to Extra Large Fonts or keep it at Normal

        dpi_00_X = windowDC->GetDeviceCaps(LOGPIXELSX); // 96
    }

    if( desktop )
    {
        desktopDPI = ::GetDeviceCaps(desktop, LOGPIXELSY); // 96
        dpi_01_X = ::GetDeviceCaps(desktop, LOGPIXELSX); // 96
    }

    if( device )
    {
        deviceDPI = device->GetDeviceCaps(LOGPIXELSY); // 96
        dpi_02_X = device->GetDeviceCaps(LOGPIXELSX); // 96
    }

    systemDPI = ::GetDeviceCaps(hDC, LOGPIXELSY); // 96
    dpi_03_X = ::GetDeviceCaps(hDC, LOGPIXELSX); // 96

    CWnd::ReleaseDC(device);
    CWnd::ReleaseDC(windowDC);
    ::ReleaseDC(NULL, desktop);
    ::ReleaseDC(NULL, hDC);

    CWnd::OnWinSettingChange(uFlags, lpszSection);
}

DPIは常に96を返しますが、フォントサイズを特大フォントに変更した場合、またはDPIを(グラフィックスプロパティから)120に変更した場合、設定の変更は有効になります。

4

6 に答える 6

4

[再読後の編集] 「大きなフォント」に変更しても DPI が変化するのではなく、テーマの設定であることはほぼ確実です。「大きなフォント」の変更を適用し、DPI 設定が存在する高度な表示プロパティを開くことで確認できるはずです。96dpi のままである必要があります。


DPI の変更には、再起動が必要であると想定されています。GetDeviceCaps が取得できる場所に設定が反映されていない可能性がありますか?

再起動を必要としない設定 (おそらく解像度) を変更してみて、変更を検出できるかどうかを確認してください。可能であれば、再起動するまで DPI の変更を検出できないというのがおそらくあなたの答えです。

于 2008-10-17T12:46:58.527 に答える
3

デスクトップDCでGetDeviceCaps()を呼び出すとき、おそらくMFCによってキャッシュされている可能性があるために古い情報が含まれているDCを使用していますか?OnSettingsChangeハンドラー内から同期的にGetDeviceCaps()呼び出しを行っていますか?これらのいずれかまたは両方によって、DPIのバージョンが古くなる可能性があることがわかりました。

Raymond Chenはこれについて書き、彼のソリューションは次のようになりました(APIのMFCラッパーを呼び出さないように::演算子を追加したことに注意してください)。

int GetScreenDPI()
{
  HDC hdcScreen = ::GetDC(NULL);
  int iDPI = -1; // assume failure
  if (hdcScreen) {
    iDPI = ::GetDeviceCaps(hdcScreen, LOGPIXELSX);
    ::ReleaseDC(NULL, hdcScreen);
  }
  return iDPI;
}
于 2008-10-17T11:25:41.357 に答える
2

WM_THEMECHANGEDがあなたの面倒を見てくれます。ただし、何が変わったかについてのヒントはありません。OpenThemeDataを使用して初期設定をキャッシュし、メッセージを受信するたびに比較する必要があります。

おそらく何が変わったのか気にする必要はないでしょうが、すべてを考慮に入れて最初から始めることを想定してフォーム/ダイアログなどを調整する汎用のレイアウトルーチンはありませんか?

どのような問題を解決しようとしていますか?

于 2008-10-17T18:36:09.087 に答える
1

http://msdn.microsoft.com/en-us/library/ms701681(VS.85).aspxを参照してください。これについてはそこで説明されています (引用:「dpi スケーリングをキャンセルしない場合、この呼び出しはデフォルト値の 96 を返します。 dpi.")

于 2008-11-12T22:53:59.900 に答える
0

フォントサイズが変わってもディスプレイのDPIは変わらないと思います。Windows はおそらく、開いているすべてのウィンドウにWM_PAINTWM_NCPAINTメッセージを送信しているだけで、現在の (現在は大きい) システム フォントを使用して自分自身を再描画しています。

于 2008-10-17T18:47:37.330 に答える