アクティベーションコンテキストのときのコードでは、SystemParametersInfo(SPI_GETNONCLIENTMETRICSでメッセージボックスの表示に使うフォントを取得していました。何のためと言えば、日本語Vistaでメイリオを使うためです(日本語XP以前ではMS UI Gothicが得られます、特に設定をいじっていなければ)。直接メイリオと指定するよりは、設定の値を読み取るほうがスマートです。XPでもメイリオを入れて設定している人もいれば、私みたいにそれ以外の人、日本語以外の人、いろんな人がいるというのが言い訳理由です。

それに関連して、今日は.NET Frameworkではどうやるという話です。

といっても、ずばりSystem.Drawing名前空間のSystemFonts.MessageBoxFontを読み取るだけです。これでFontインスタンスが得られます。これで話は終わってしまいました。

いえいえ、ここからが本題。さらにそこからLOGFONT構造体を取り出します。

それすらも簡単そうに思いました。何せ、ToLogFontメソッドを呼ぶだけです。ただし、引数がObjectなのが問題だったのです。.NET Frameworkの中でLogFont構造体でも用意すればよかったのにと思いますが、技術的に難しいのかもしれません。

ではどうするかというと、まず小さな改善とコンパイラの新機能、そして3.0への展望(連載:C# 2.0入門 最終回 - @IT)のように、自分で値型構造体を宣言するという手法もあります。しかし、C++/CLIなら<windows.h>のLOGFONTの宣言を使いまわしたい、というわけでやってみたのです。

結局、こうなりました。

#define WIN32_LEAN_AND_MEAN
#define _WIN32_IE 0x0501
#include <windows.h>
#include <shlwapi.h>
#using <System.Drawing.dll>
 
int main()
{
  namespace dr = System::Drawing;
 
  dr::Font^ f = dr::SystemFonts::MessageBoxFont;
  if (IsOS(OS_WINDOWS)) //9xか否か
  {
    array<BYTE>^ a = gcnew array<BYTE>(sizeof (LOGFONTA));
    f->ToLogFont(a);
    pin_ptr<LOGFONTA> plf = reinterpret_cast<interior_ptr<LOGFONTA> >(&a[0]);
    ::MessageBoxA(0, plf->lfFaceName, "", MB_OK);
  }
  else
  {
    array<BYTE>^ a = gcnew array<BYTE>(sizeof (LOGFONTW));
    f->ToLogFont(a);
    pin_ptr<LOGFONTW> plf = reinterpret_cast<interior_ptr<LOGFONTW> >(&a[0]);
    ::MessageBoxW(0, plf->lfFaceName, L"", MB_OK);
  }
  return 0;
}

BYTEに違和感のある方は、unsigned charやSystem::Byteに読み変えるといいです。また、pin_ptr<logfontw> plf = reinterpret_cast<interior_ptr<LOGFONTW> >(&a[0]);は、C++/CLIに不慣れなら次のように読み変えるとよいかもしれません。

interior_ptr<LOGFONTW> iplf = reinterpret_cast<interior_ptr<LOGFONTW> >(&a[0]);
pin_ptr<LOGFONTW> plf = iplf;

マネージヒープにバイト配列を作って、それをToLogFontに渡し、それをLOGFONTにreinterpret_castしてpinしている、コードを読み上げるとそうなります。直接LOGFONT^ hlf = gcnew LOGFONT;とかけたらすごいのにと思いましたが、さすがに無理でした。

あと、9xだとLOGFONTAになるというのが盲点で、Windows 98で試しておいて正解でした。その判別に使ったIsOSはIE 5.01以上が必要です。ただし、.NET Framework [1.0/1.1/2.0]自体がIE 5.01以上を必要とするので、入っていないという心配は要りません。

それでも、判別処理は面倒のもとでしょうから、なるべくFontからLOGFONTへの変換は避けた方が楽だと思います。情報取得はFontのプロパティ、HFONTへはToHfontメソッドが使えます。もっとも、それで済むならこんなことするわけないですよね。


2011年9月11日:HTMLに一部誤りがあったので修正しました。


スポンサード リンク

この記事のカテゴリ

  • ⇒ Font.ToLogFontを使う
  • ⇒ Font.ToLogFontを使う