今回は図のようなコモンダイアログを出して、書式の変更をします。
上の図はWindows 8のコモンダイアログで、下はWindows XPの場合です。
リッチエディット2:書式の変更 - インコのWindowsSDK で作成したソースを修正します。
流れ
1.メニューに「フォントの設定」を追加
●追加したメニューが実行されたときの動作
2.現状のフォントの設定(CHARFORMAT構造体)を取得して、 CHOOSEFONT構造体にセット
typedef struct { DWORD lStructSize; // 構造体サイズ HWND hwndOwner; // オーナーウィンドウハンドル HDC hDC; // プリンタのデバイスハンドル LPLOGFONT lpLogFont; // LOGFONT構造体のアドレス INT iPointSize; // サイズ(ポイント数) DWORD Flags; // フラグ DWORD rgbColors; // 文字色 LPARAM lCustData; // アプリケーション定義値 LPCFHOOKPROC lpfnHook; // フックプロシージャアドレス LPTCSTR lpTemplateName; // テンプレートリソース名 HINSTANCE hInstance; // モジュールインスタンス LPTSTR lpszStyle; // スタイルデータ WORD nFontType; // フォントタイプ WORD ___MISSING_ALIGNMENT__; INT nSizeMin; // サイズ最小値 INT nSizeMax; // サイズ最大値 } CHOOSEFONT, *LPCHOOSEFONT;
lStructSize | CHOOSEFONT構造体のサイズ | |
hwndOwner | オーナーウィンドウのハンドル | |
hDC | プリンタのデバイスのハンドル | |
lpLogFont | LOGFONT構造体のアドレス | |
iPointSize | フォントサイズを1/10ポイント単位で指定 | |
Flags | フラグ (後述の表を参照) | |
rgbColors | FlagsメンバでCF_EFFECTSを指定した場合は、文字色の初期値をRGB (COLORREF) 値で指定します。 | |
lCustData | lpfnHookメンバで指定されたフックプロシージャに渡すアプリケーション定義の値を指定 | |
lpfnHook | CFHookProcフックプロシージャのアドレスを指定 FlagsメンバにCF_ENABLEHOOKフラグを指定しているときのみ有効 |
|
lpTemplateName | hInstanceメンバで指定されたモジュールに含まれるダイアログボックスのテンプレートリソースの名前を表す文字列のアドレスを指定 FlagsメンバでCF_ENABLETEMPLATEが指定されているときのみ有効 |
|
hInstance | ● FlagsメンバにCF_ENABLETEMPLATEHANDLEを指定した場合・・・ ダイアログボックスのテンプレートリソースを含むメモリオブジェクトのハンドルを指定 ● FlagsメンバにCF_ENABLETEMPLATEを指定した場合・・・ lpTemplateNameメンバで指定された名前のダイアログボックスのテンプレートリソースを含むモジュールのハンドルを指定 ● 上記以外の場合・・・ 無視される |
|
lpszStyle | スタイルデータを含むバッファのアドレス | |
nFontType | フォントのタイプ | |
BOLD_FONTTYPE | 太字 | |
ITALIC_FONTTYPE | イタリック | |
REGULAR_FONTTYPE | 通常の太さ | |
SCREEN_FONTTYPE | スクリーンフォント | |
PRINTER_FONTTYPE | プリンタフォント | |
nSizeMin |
ユーザーが選択可能なフォントサイズ(ポイント数)の最小値を指定 FlagsメンバにCF_LIMITSIZEを指定した場合にのみ有効 |
|
nSizeMax |
ユーザーが選択可能なフォントサイズ(ポイント数)の最大値を指定 FlagsメンバにCF_LIMITSIZEを指定した場合にのみ有効 |
上の表にあるFlags (フラグ)は下記を指定できます。
CF_SCREENFONTS | スクリーンフォントのみを表示 |
CF_PRINTERFONTS | hDCメンバで指定されたデバイスコンテキスト(または情報コンテキスト)に関連付けられているプリンタがサポートするフォントのみが表示 |
CF_BOTH | CF_SCREENFONTSとCF_PRINTERFONTSの両方 |
CF_SHOWHELP | ヘルプボタンを表示 |
CF_ENABLEHOOK |
lpfnHookメンバで指定されたフックプロシージャを有効 フック・・・ 本来のプロシージャに届くはずのメッセージを、横取りする プロシージャ・・・ プログラム内で繰り返し出現する処理を行なうために、一連の命令を一つの手順としてまとめたもの |
CF_ENABLETEMPLATE | hInstanceメンバとlpTemplateNameメンバで指定されたダイアログボックステンプレートをデフォルトテンプレートの代わりに使用 |
CF_ENABLETEMPLATEHANDLE | hInstanceメンバで指定されたメモリブロックに含まれるダイアログボックステンプレートを使用 |
CF_INITTOLOGFONTSTRUCT | ダイアログボックスをlpLogFontメンバが指し示すLOGFONT構造体で指定されたフォントが選択された状態に初期化 |
CF_USESTYLE | フォントスタイルコンボボックスをlpszStyleメンバが指し示すバッファで指定されたスタイルデータで初期化 |
CF_EFFECTS |
打ち消し線・下線・文字色を指定できるようにします。 このフラグが指定されると、rgbColorsに初期の文字色を指定することができます。 lpLogFontメンバが指し示すLOGFONT構造体のlfStrikeOutメンバとlfUnderlineメンバに初期の設定を指定することができます。 |
CF_APPLY |
ダイアログボックスに 「適用」ボタンを表示 フックプロシージャ中でWM_COMMANDメッセージを処理する必要があります。 フックプロシージャは、ダイアログボックスにWM_CHOOSEFONT_GETLOGFONTメッセージを送信して、 現在選択されているフォント情報が格納されたLOGFONT構造体を取得することができます。 |
CF_SCRIPTSONLY CF_NOOEMFONTS |
非OEM文字セットやシンボル文字セットを選択可に |
CF_NOVECTORFONTS CF_ANSIONLY |
ベクトルフォントを選択不可に |
CF_LIMITSIZE | nSizeMinメンバおよびnSizeMaxメンバで、フォントサイズの範囲を制限 |
CF_FIXEDPITCHONLY | 固定ピッチフォントのみを選択可に |
CF_FORCEFONTEXIST | 存在しないフォントやスタイルをユーザーが選択しようした場合には、関数がエラーを返すようにします。 |
CF_SCALABLEONLY | スケーリング可能なフォント(ベクトルフォント、TrueTypeフォントなど)のみを選択可に |
CF_TTONLY | TrueTypeフォントのみを選択可に |
CF_NOFACESEL | ダイアログボックスの初期状態を設定するのにLOGFONT構造体の情報を使用する場合、 初期状態でフォント名のコンボボックスに何も選択されていないようにします。 |
CF_NOSTYLESEL | ダイアログボックスの初期状態を設定するのにLOGFONT構造体の情報を使用する場合、 初期状態でフォントスタイルのコンボボックスに何も選択されていないようにします。 |
CF_NOSIZESEL | ダイアログボックスの初期状態を設定するのにLOGFONT構造体の情報を使用する場合、 初期状態でフォントサイズのコンボボックスに何も選択されていないようにします。 |
CF_SELECTSCRIPT | LOGFONT構造体のlfCharSetメンバで指定された文字セットを持つフォントのみが表示されます。 文字セットコンボボックスで指定される文字セットをユーザーが変更することができないようになります。 |
CF_NOSCRIPTSEL | 文字セットのコンボボックスを無効にします。 |
CF_NOVERTFONTS | 水平方向のフォントのみがリスト表示されます。 |
typedef struct tagLOGFONT { LONG lfHeight; // 文字セルまたは文字の高さ LONG lfWidth; // 平均文字幅 LONG lfEscapement; // 文字送りの方向とX軸との角度 LONG lfOrientation; // ベースラインとX軸との角度 LONG lfWeight; // フォントの太さ BYTE lfItalic; // イタリック体指定 BYTE lfUnderline; // 下線付き指定 BYTE lfStrikeOut; // 打ち消し線付き指定 BYTE lfCharSet; // キャラクタセット BYTE lfOutPrecision; // 出力精度 BYTE lfClipPrecision; // クリッピングの精度 BYTE lfQuality; // 出力品質 BYTE lfPitchAndFamily; // ピッチとファミリ TCHAR lfFaceName[LF_FACESIZE]; // フォント名 } LOGFONT *PLOGFONT, NEAR *NPLOGFONT, FAR *LPLOGFONT;
lfHeight | フォントの文字セルまたは文字の高さを論理単位で指定 正の数・・・文字セルの高さ 0・・・デフォルトの高さ 負の数・・・その絶対値が文字の高さ |
|
lfWidth | フォントの平均文字幅を論理単位で指定 0・・・自動 |
|
lfEscapement | 文字送りの方向とX軸との角度を、10分の1度単位で指定 | |
lfOrientation | 各文字のベースラインとX軸との角度を、10分の1度単位で指定 | |
lfWeight | フォントの太さを、0から1000までの値で指定 | |
lfItalic | 1 (TRUE):イタリック体 | |
lfUnderline | 1 (TRUE):下線つき | |
lfStrikeOut | 1 (TRUE):打ち消し線つき | |
lfCharSet | 文字セット | |
ANSI_CHARSET | ANSI | |
SHIFTJIS_CHARSET | シフトJIS | |
lfOutPrecision | 出力精度 | |
OUT_DEFAULT_PRECIS | デフォルト | |
lfFaceName | フォント名 |
3.ChooseFont()で、フォント選択ダイアログを出す
BOOL ChooseFont( LPCHOOSEFONT lpcf // 初期化データ(構造体へのポインタ) );
ソースコードの入力
ソースコードは下記のように入れてください。
test.cpp
#include <windows.h> #include <richedit.h> // CHARFORMAT構造体を使うためにインクルード #include "resource.h" // グローバル変数: HINSTANCE hInst; // 現在のインターフェイス // リッチエディットの使用するために用いる変数宣言 TCHAR strPath[MAX_PATH + 1]; // DLLのパス HINSTANCE hRtLib; // インスタンスハンドル HWND hRichEdit; // ウィンドウハンドル DWORD dwChMask; // CHARFORMAT構造体で使うマスク値 // このコード モジュールに含まれる関数の宣言を転送します: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); void SetFont(); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG msg; MyRegisterClass(hInstance); // アプリケーションの初期化を実行します: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } // メイン メッセージ ループ: while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; } // // 関数: MyRegisterClass() // // 目的: ウィンドウ クラスを登録します。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(NULL , IDI_APPLICATION); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_HP); wcex.lpszClassName = TEXT("HP"); wcex.hIconSm = LoadIcon(NULL , IDI_APPLICATION); return RegisterClassEx(&wcex); } // // 関数: InitInstance(HINSTANCE, int) // // 目的: メイン ウィンドウを作成します。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // グローバル変数にインスタンス処理を格納します。 hWnd = CreateWindow(TEXT("HP"), TEXT("HP"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 関数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: メイン ウィンドウのメッセージを処理します。 // // WM_CREATE - ウインドウ作成時の処理 // WM_SIZE - ウインドウサイズ変更時の処理 // WM_COMMAND - アプリケーション メニューの処理 // WM_DESTROY - 中止メッセージを表示して戻る // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; DWORD dwLangOptions; CHARFORMAT cfm; // CHARFORMAT構造体 switch (message) { case WM_CREATE: // DLLのロード GetSystemDirectory(strPath , MAX_PATH + 1); wsprintf(strPath, TEXT("%s\\%s"), strPath, TEXT("RICHED20.DLL")); hRtLib = LoadLibrary((LPCTSTR)strPath); hRichEdit = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("RichEdit20A"), TEXT(""), WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | WS_HSCROLL | WS_VSCROLL | ES_AUTOVSCROLL | ES_NOHIDESEL, 0, 0, 0, 0, hWnd, (HMENU)IDC_RICHEDIT, hInst, NULL); // デュアルフォントモードを無効にする // 下記3行がないと、半角文字のフォントが変更できない dwLangOptions = SendMessage(hRichEdit, EM_GETLANGOPTIONS, 0, 0); dwLangOptions &= ~IMF_DUALFONT; SendMessage(hRichEdit, EM_SETLANGOPTIONS, 0, (LPARAM)dwLangOptions); memset(&cfm, 0, sizeof(CHARFORMAT)); cfm.cbSize = sizeof(CHARFORMAT); // CHARFORMAT構造体のサイズを渡す cfm.dwMask = CFM_BOLD | CFM_ITALIC | CFM_UNDERLINE | CFM_STRIKEOUT | CFM_CHARSET | CFM_FACE | CFM_COLOR | CFM_SIZE; dwChMask = cfm.dwMask; cfm.yHeight = 20 * 12; cfm.crTextColor = 0x000000; cfm.bCharSet = SHIFTJIS_CHARSET; //文字コード(ShiftJIS) lstrcpy(cfm.szFaceName, TEXT("MS ゴシック")); SendMessage(hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cfm); break; case WM_SIZE: MoveWindow(hRichEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 選択されたメニューの解析: switch (wmId) { case IDM_FONT: SetFont(); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // フォント選択ダイアログ void SetFont() { CHARFORMAT cfm; CHOOSEFONT cf; LOGFONT lf; HDC hDC; memset(&cf, 0, sizeof(CHOOSEFONT)); memset(&lf, 0, sizeof(LOGFONT)); cfm.cbSize = sizeof(CHARFORMAT); //今までの設定を取得してそれをCHOOSEFONT構造体に渡す SendMessage(hRichEdit, EM_GETCHARFORMAT, TRUE, (LPARAM)&cfm); hDC = GetDC(hRichEdit); lf.lfHeight = cfm.yHeight * GetDeviceCaps(hDC, LOGPIXELSY) / (-72 * 20); ReleaseDC(hRichEdit, hDC); cfm.dwMask = dwChMask; if (cfm.dwEffects & CFE_BOLD) { lf.lfWeight = FW_BOLD; } else { lf.lfWeight = FW_NORMAL; } if (cfm.dwEffects & CFE_ITALIC) { lf.lfItalic = 1; } if (cfm.dwEffects & CFE_UNDERLINE) { lf.lfUnderline = 1; } if (cfm.dwEffects & CFE_STRIKEOUT) { lf.lfStrikeOut = 1; } lf.lfCharSet = cfm.bCharSet; lstrcpy(lf.lfFaceName, cfm.szFaceName); cf.rgbColors = cfm.crTextColor; cf.lStructSize = sizeof(CHOOSEFONT); cf.hwndOwner = hRichEdit; cf.lpLogFont = &lf; cf.Flags = CF_SCREENFONTS | CF_EFFECTS | CF_INITTOLOGFONTSTRUCT; // フォント選択ダイアログを出す if(ChooseFont(&cf)) { // フォント選択ダイアログから新しい設定を取得する cfm.cbSize = sizeof(CHARFORMAT); cfm.dwMask = dwChMask; cfm.yHeight = 2 * cf.iPointSize; cfm.dwEffects = 0; if (lf.lfWeight >= FW_BOLD) { cfm.dwEffects |= CFE_BOLD; } if (lf.lfItalic) { cfm.dwEffects |= CFE_ITALIC; } if (lf.lfUnderline) { cfm.dwEffects |= CFE_UNDERLINE; } if (lf.lfStrikeOut) { cfm.dwEffects |= CFE_STRIKEOUT; } cfm.crTextColor = (COLORREF)cf.rgbColors; cfm.bCharSet = lf.lfCharSet; lstrcpy(cfm.szFaceName, lf.lfFaceName); SendMessage(hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cfm); } SetFocus(hRichEdit); }
上記の太線で示している箇所のみ追加です。
resource.h
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDM_FONT 170
#define IDC_HP 109
#define IDC_RICHEDIT 101
上記の太線で示している箇所のみ追加です。
test.rc リソースファイル
#include "resource.h"
/////////////////////////////////////////////////////////////////////////////
//
// メニュー
//
IDC_HP MENU
BEGIN
POPUP "ファイル(&F)"
BEGIN
MENUITEM "アプリケーションの終了(&X)", IDM_EXIT
END
POPUP "書式(&O)"
BEGIN
MENUITEM "フォント(&F)...", IDM_FONT
END
POPUP "ヘルプ(&H)"
BEGIN
MENUITEM "バージョン情報(&A)...", IDM_ABOUT
END
END
上記の太線で示している箇所のみ追加です。