英語のフォント名
そこそこ調べたけど、結局使わなかったコードの断片を記録します。
症状
C++のプログラムで、フォント名(font face name)の英語表記を欲しかったのですが、日本語環境ではなかなか得ることができませんでした。つまり、下のような英語表記が欲しかったのです。
日本語 | 英語 |
---|---|
MS Pゴシック | MS PGothic |
メイリオ | Meiryo |
解決方法
.NETの FontFamily.GetName(1033) を使う。
経緯とサンプル
- サンプルは、VS2012Express、Win32コンソールアプリで作成しました。[空のプロジェクト]を作成して、プロジェクトのプロパティで、共通ランタイムサポート(/clr)を選択したものです。
サンプルソリューションのパック(ConsoleApplication7.zip)
- (記事の下の方にdll化してみたものも置いてます。)
- ちなみに、英語LCID(=1033)は、次のコードで得られます。
WORD langid =MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); DWORD lcid =MAKELCID( langid, SORT_DEFAULT );
- 識別子の一覧に関しては、サンプルコード中のコメントを参照してください。
- サンプルは
- .NETのフォントピッカーを開いて、
- マネージされた英語のフォント名をC++の文字列に変換して
- コンソールに表示するものです。
#pragma once #include <SDKDDKVer.h> // windows.hのインクルードに必要で、アーキテクチャや #include <Windows.h> // プラットフォームを限定するためのものです。 #include <stdio.h> #include <tchar.h> #include <iostream> #include <vcclr.h> // pin_ptrを使用するためのものです。 /* * オブジェクトの参照が必要です。ソリューションエクスプローラのプロジェクトを右クリして、 * [プロパティ][共通プロパティ][Frameworkと参照][新しい参照の追加(N)...] * でチェックすることで、有効化できます。コンパイラの/FUオプションになります。 * あるいは、#usingディレクティブを使って、コード中に埋め込むこともできます。 */ #using <System.dll> #using <System.Windows.Forms.dll> #using <System.Drawing.dll> int main(int argc, _TCHAR* argv[]) { std::locale::global(std::locale("japanese")); System::Windows::Forms::FontDialog^ fd=gcnew System::Windows::Forms::FontDialog(); fd->ShowDialog(); System::Drawing::FontFamily^ ff=fd->Font->FontFamily; /* * MAKELANGID, MAKELCID マクロや識別子に関しては、次のような文言でWeb検索すると * マイクロソフトの開発者用リファレンスが参照できます。 * 国際化に関係した識別子一覧があります。 * * ・National Language Support Reference * ・Language Identifier Constants and Strings * ・Sort Order Identifiers * */ WORD langid =MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); DWORD lcid =MAKELCID( langid, SORT_DEFAULT ); System::String^ strFFName_EN =ff->GetName(lcid); System::String^ strFFName_JP =ff->GetName(0); /* * pin_ptrを使って、String^をwchar_t*に変更することで、普通のC++のように記述できます。 * 次の文言でWeb検索すると、pin_ptr のサンプルが見れます。 * * ・方法: System::String を wchar_t* または char* に変換する */ pin_ptr<const wchar_t> wchFFName_EN = PtrToStringChars(strFFName_EN); pin_ptr<const wchar_t> wchFFName_JP = PtrToStringChars(strFFName_JP); std::wcout <<L"英語:" <<(const wchar_t*)wchFFName_EN <<std::endl; std::wcout <<L"日本語:" <<(const wchar_t*)wchFFName_JP <<std::endl; std::wcout <<L"Press ENTER to exit:"; std::cin.ignore(); return 0; }
- .NETを使用するために、/clrオプションを指定すること、
- #usingで適切な.dllを宣言することが必要です。
- あるいは、プロジェクトの[共通プロパティ][Frameworkと参照]にて、参照を参加させます。
- サンプル起動直後にフォントピッカーが開くので、フォントを選択します。
- コンソールにフォントの日本語と英語の表記が出力されます。
DLL化したサンプル
ふっと思いついて、.NET部分をDLLに封じ込めてみました。
DLL化したサンプル(ConsoleApplication7b.zip)
「メイリオ」を渡すと「Meiryo」を返すdll。「メイリオ」などと有効なフォント名でないと、何が起きるかわかりません。
メイン(ConsoleApplication.cpp)
#pragma once #include <stdio.h> #include <tchar.h> #include <iostream> #include "FontFamily\FontFamily.h" int main(int argc, _TCHAR* argv[]) { std::locale::global(std::locale("japanese")); const wchar_t* wchNameEn =GetName(L"メイリオ"); std::wcout <<L"英語:" <<(const wchar_t*)wchNameEn <<std::endl; std::wcout <<L"Press ENTER to exit:"; std::cin.ignore(); return 0; }
DLL(FontFamily.cpp)
#include "stdafx.h" #include "FontFamily.h" #include <vcclr.h> #using <System.Drawing.dll> FONTFAMILY_API const wchar_t* GetName( const wchar_t* nameJp ) { System::Drawing::FontFamily^ ff =gcnew System::Drawing::FontFamily( gcnew System::String(nameJp) ); WORD langid =MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); DWORD lcid =MAKELCID( langid, SORT_DEFAULT ); System::String^ strNameEn =ff->GetName(lcid); pin_ptr<const wchar_t> wchNameEn =PtrToStringChars(strNameEn); return (const wchar_t*)wchNameEn; }
- Dllの名前がFontFamilyだったり、エクスポート関数名がGetNameだったりと非実用的なネーミングです。
- 文字列のポインタ返しとか大丈夫なのか?とか今の僕にはわかりません。
- 記事書いて、ご飯食べたら、ふっと思いついただけなので...
- フォントピッカーは出ません。「メイリオ」決め打ちです。
- vcclr.hは、PtrToStringCharsを使うためのものですね。訂正します。
- 今思うと、なぜdll化したのだろう。単に関数化でもよかったかな?
- ご飯食べてて、ふっと思いついた勢いで作ったので...
- 思い出した、本体側で/clrしなくてもよいことになるからでした。
以上です。