山本ワールド
Windowsプログラミング
アルゴリズム Vitual C++ 2008/2013によるWin32/Win64 APIレベルのプログラム 基礎 Vitual C++ 2008/2013によるAPIレベルのプログラム(32/64bit) Wix3でインストーラーを作る Visual C++ 2008 Standard Editonによるフォームアプリケーションのプログラム(32/64bit) Vitual C++ 2008 Standard EditonによるAPIレベルのプログラム(32/64bit) Windows 7対応 Visual C++ 2008 ExpressによるAPIレベルのプログラム Visual C++ 2005 ExpressによるAPIレベルのプログラム Visual C++ Versiosn 5 BORLAND C++ Windowsプログラム全般 Excel VBA その他フォントの一覧を印刷
概要
横書きフォントの一覧を印刷します。
Windows 10 Version 1703以降の場合、高DPI環境で綺麗に表示されます。
以下に印刷により作成されたPDFファイルを表示結果を示します。
fonts.pdf
Windows 10 Version 1703以降の場合、高DPI環境で綺麗に表示されます。
以下に印刷により作成されたPDFファイルを表示結果を示します。
fonts.pdf
テスト環境
コンパイラ
Visual C++ 2013 Express 32/64bitプログラムソースの概要
_tWinMain関数
Windowsから最初に_tWinMain関数が呼び出されます。GetDC APIによりディスクトップのハンドルを取得しhdcに保存します。
LOGONT構造体に検索条件を設定してEnumFontFamiliesEx APIを呼び出します。
コールバック関数EnumFontFamProcがフォント1個に対して1回呼び出されますので、EnumFontFamProc関数側で可変長の配列であるvector
print2font関数でフォントの一覧を印刷します。
EnumFontFamProc関数
フォントが見つかるたびに呼び出されるので引数よりフォントの情報を可変長の配列であるvectorprint2font
以下の様な印刷のコモンダイアログボックスを表示してプリンタの選択をしてフォントの一覧を印刷します。PRINTDLG構造体を初期化してPrintDlg APIを呼び出します。なおページ数についてはわからないので1ページと仮定しています。このAPIが正常に終了するとTRUEを返します。
PrintDlg APIで取得されたデバイスコンテキストを使用してStartDoc APIを呼び出します。印刷の開始とDOCINFO構造体により文章名を設定しています。
GetDeviceCaps APIでLOGPIXELSXを指定してプリンタの解像度を取得し10㎜当たりのピクセル数を計算しfhに代入します。
GetDeviceCaps APIでVERTRESを指定してプリンタの縦方向の印刷可能領域のピクセル数を取得します。
GetDeviceCaps APIでLOGPIXELSXを指定して印刷領域の余白20㎜当たりのピクセル数を計算しmargeに代入します。
CreateFont APIによりフォント名と文字高さ10㎜に相当するピクセル数を指定してフォントを作成します。なお最初の呼び出し時には元のフォントのハンドルを保存しておきます。
SelectObj APIにより現在のフォントを作成されたフォントに変更します。
TextOut APIにより見つかったフォントの通し番号とフォント名を印刷します。
CreateFont APIによりフォント名と文字高さ3.5㎜に相当するピクセル数を指定してフォントを作成します。
SelectObj APIにより現在のフォントを作成されたフォントに変更します。
TextOut APIによりフォントの言語とフォントのタイプを印刷します。
なお、ページをはみ出す場合はEndPage APIにより今のページを終了させStartPageにより新しいページの開始を指定します。
全部のフォントを印刷したらEndDoc APIにより印刷ジョブが終了したことを指定します。
プログラムソース
// 印刷コモンダイアログボックスを使用してフォントの一覧を印刷する。
// Win32/64 Unicode/マルチバイト
#include <windows.h>
#include <vector>
#include <tchar.h>
using namespace std;
struct FONT_INFO{
TCHAR* elfFullName;
TCHAR* elfStyle;
TCHAR* elfScript;
DWORD FontType;
};
vector<FONT_INFO*> fonts;
// 横書きフォントの列挙
int CALLBACK EnumFontFamProc(const LOGFONT * lpelf, const TEXTMETRIC FAR* lpntm, DWORD FontType, LPARAM lParam);
// フォントの印刷
void print2font(void);
#ifndef _DPI_AWARENESS_CONTEXTS_
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
#endif
typedef HRESULT(_stdcall* SetThreadDpiAwarenessContextFunc)(DPI_AWARENESS_CONTEXT);
HMODULE hModUser32 = 0;
SetThreadDpiAwarenessContextFunc ThreadAwareFunc = 0;
#ifndef _DPI_AWARENESS_CONTEXTS_
typedef enum _DPI_AWARENESS {
DPI_AWARENESS_INVALID = -1,
DPI_AWARENESS_UNAWARE = 0,
DPI_AWARENESS_SYSTEM_AWARE = 1,
DPI_AWARENESS_PER_MONITOR_AWARE = 2
} DPI_AWARENESS;
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)
#endif
int win10ver2(void);
int WIN10VER;
int WINAPI _tWinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, TCHAR* lpsCmdLine, int nCmdShow){
LOGFONT lf;
WIN10VER = win10ver2();
hModUser32 = LoadLibrary(L"User32.dll");
if (hModUser32){
ThreadAwareFunc = (SetThreadDpiAwarenessContextFunc)GetProcAddress(hModUser32, "SetThreadDpiAwarenessContext");
if (ThreadAwareFunc){
if (1703 <= WIN10VER)
(*ThreadAwareFunc)(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
}
}
HDC hdc = GetDC(0);
lf.lfFaceName[0] = _T('¥0'); // 全てのフォント名
lf.lfPitchAndFamily = DEFAULT_PITCH;
lf.lfCharSet = SHIFTJIS_CHARSET;
EnumFontFamiliesEx(hdc, &lf, (FONTENUMPROC)EnumFontFamProc, (LONG_PTR)&lf, 0);
ReleaseDC(0, hdc);
print2font();
for (UINT n = 0; n < fonts.size(); n++){
free(fonts[n]->elfFullName);
free(fonts[n]->elfScript);
free(fonts[n]->elfStyle);
delete fonts[n];
}
fonts.clear();
if (hModUser32)
FreeLibrary(hModUser32);
return 0;
}
int CALLBACK EnumFontFamProc(const LOGFONT * lpelf, const TEXTMETRIC FAR* lpntm, DWORD FontType, LPARAM lParam){
ENUMLOGFONTEX *lpelfe = (ENUMLOGFONTEX *)lpelf;
if (lpelfe->elfFullName[0] != _T('@')){
FONT_INFO* fip = new FONT_INFO;
fip->elfFullName = _tcsdup(lpelfe->elfFullName);
fip->elfScript = _tcsdup(lpelfe->elfScript);
fip->elfStyle = _tcsdup(lpelfe->elfStyle);
fip->FontType = FontType;
fonts.push_back(fip);
}
return 1;
}
void print2font(void){
PRINTDLG pd;
DOCINFO di;
memset(&pd, 0, sizeof(PRINTDLG));
pd.lStructSize = sizeof(PRINTDLG);
pd.hwndOwner = NULL;
pd.hDevMode = NULL;
pd.hDevNames = NULL;
// pd.Flags = デバイスコンテキストを返す 「選択した部分」ラジオボタンを使用不可にします 「ファイルへ出力」チェックボックスを隠します。
pd.Flags = PD_RETURNDC |
PD_NOPAGENUMS | PD_NOSELECTION | PD_HIDEPRINTTOFILE;
pd.nCopies = 1; // 印刷部数1
pd.nFromPage = 1; // スタートページ1
pd.nToPage = 1; // 最後のページ1
pd.nMinPage = 1; // ページ範囲の最小値1
pd.nMaxPage = 1; // ページエディットコントロールの最大値1
memset(&di, 0, sizeof(DOCINFO));
di.cbSize = sizeof(DOCINFO);
di.lpszDocName = TEXT("fonts");
UINT n;
if (PrintDlg(&pd) == TRUE) { // ダイアログ表示
StartDoc(pd.hDC, &di);
int fh = int(10 * double(GetDeviceCaps(pd.hDC, LOGPIXELSX)) / 25.4); //10ミリの文字幅を計算(ピクセル)
// 印刷可能領域
int pheight = GetDeviceCaps(pd.hDC, VERTRES) - fh;
int marge = int(20 * double(GetDeviceCaps(pd.hDC, LOGPIXELSX)) / 25.4); //20ミリの余白を計算(ピクセル)
int y = marge;
StartPage(pd.hDC);
HFONT hOldFont = 0;
for (n = 0; fonts.size() > n; n++){
#ifdef UNICODE
HFONT hfont = CreateFont(fh, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fonts[n]->elfFullName);
#else
HFONT hfont = CreateFont(fh, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fonts[n]->elfFullName);
#endif
if (hOldFont == 0)
hOldFont = (HFONT)SelectObject(pd.hDC, hfont);
else
SelectObject(pd.hDC, hfont);
if (pheight - marge < y){ // 改ページ
StartPage(pd.hDC);
EndPage(pd.hDC);
y = marge;
}
TCHAR* ft = _TEXT("");
switch (fonts[n]->FontType){
case DEVICE_FONTTYPE:
ft = _TEXT("デバイスフォント");
break;
case RASTER_FONTTYPE:
ft = _TEXT("ラスターフォント");
break;
case TRUETYPE_FONTTYPE:
ft = _TEXT("TrueTypeフォント");
break;
}
TCHAR buf[64];
_stprintf_s(buf, sizeof(buf) / sizeof(buf[0]), TEXT("%03d %s"), n, fonts[n]->elfFullName);
TextOut(pd.hDC, marge, y, buf, _tcslen(buf));
SIZE size;
GetTextExtentPoint32(pd.hDC, buf, _tcslen(buf), &size);
int fh2 = int(3.5 * double(GetDeviceCaps(pd.hDC, LOGPIXELSX)) / 25.4); //3.5ミリの文字幅を計算(ピクセル)
#ifdef UNICODE
HFONT hfont2 = CreateFont(fh2, 0, 0, 0, 0, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fonts[n]->elfFullName);
#else
HFONT hfont2 = CreateFont(fh2, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, fonts[n]->elfFullName);
#endif
SelectObject(pd.hDC, hfont2);
_stprintf_s(buf, sizeof(buf) / sizeof(buf[0]), TEXT("%s %s"), fonts[n]->elfScript, ft);
TextOut(pd.hDC, marge + size.cx + fh2, y + fh - fh2, buf, _tcslen(buf));
SelectObject(pd.hDC, hOldFont);
DeleteObject(hfont);
DeleteObject(hfont2);
y += fh;
}
EndPage(pd.hDC);
EndDoc(pd.hDC);
DeleteDC(pd.hDC);
}
}
// DLL内の関数へのポインタ型を定義
typedef void (WINAPI *RtlGetVersion_FUNC)(OSVERSIONINFOEXW*);
int win10ver2(void){
int ver = 0;
HMODULE hMod;
OSVERSIONINFOEXW osw;
hMod = LoadLibrary(TEXT("ntdll.dll"));
RtlGetVersion_FUNC func;
if (hMod){
func = (RtlGetVersion_FUNC)GetProcAddress(hMod, "RtlGetVersion");
if (func == 0){
FreeLibrary(hMod);
return FALSE;
}
ZeroMemory(&osw, sizeof(osw));
osw.dwOSVersionInfoSize = sizeof(osw);
func(&osw);
FreeLibrary(hMod);
if (osw.dwMajorVersion == 10){
switch (osw.dwBuildNumber){
case 10240: ver = 1507; break;
case 10586: ver = 1511; break;
case 14393: ver = 1607; break;
case 15063: ver = 1703; break;
case 16299: ver = 1709; break;
case 17134: ver = 1803; break;
case 17763: ver = 1809; break;
default: ver = 1809; break;
}
return ver;
}
}
return -1;
}
ソースファイルと実行ファイルのダウンロード
Copyright (C) 2012 山本ワールド All Rights Reserved.