ツールバーのボタンを、既成のボタンにします。リッチエディットに付けます。
ファイルの読み書き2:コモンダイアログ - インコのWindowsSDK
で作成したソースを修正します。
ツールバー2: ボタンにビットマップを貼り付ける - インコのWindowsSDK
で作成したソースから流用します。
流れ
1.TBBUTTON(ツールバーボタン)型の配列を作成
ビットマップのインデックスは、既成のボタンにする場合は、次のようにする
ビットマップのインデックス | ビットマップ |
---|---|
STD_FILEOPEN | ファイルを開く |
STD_FILESAVE | ファイルを保存する |
STD_COPY | コピー |
STD_CUT | 切り取り |
STD_DELETE | 削除 |
STD_PASTE | 貼り付け |
STD_REDOW | やり直し |
STD_UNDO | 元に戻す |
2.TBADDBITMAP構造体に ツールバーに追加するためのビットマップの情報をセットする
typedef struct { HINSTANCE hInst; // モジュールのインスタンスハンドル UINT nID; // リソースIDまたはビットマップハンドル } TBADDBITMAP, *LPTBADDBITMAP;
WM_CREATE
1.1.メンバ hInstに、
システム定義のボタンのビットマップ[HINST_COMMCTRL]をセット。
1.2.メンバ nIDに、
システム標準ビットマップ(小)[IDB_STD_SMALL_COLOR]をセット。
2.TB_ADDBITMAPメッセージでツールバーに追加するための ビットマップの情報を格納
lResult = SendMessage( (HWND) hWndControl, // ツールバーのハンドル (UINT) TB_ADDBITMAP, (WPARAM) wParam, // ビットマップに含まれるボタンイメージの数 // システム定義のビットマップを指定した場合は無視 (LPARAM) lParam // TBADDBITMAP構造体 );
3.LoadString で、文字列リソース(IDC_BUTTON1など)をロードし、バッファ(szBuf)へコピーし、
TB_ADDSTRING で文字列のリストに文字列を追加。
(
ツールバー1: 文字だけのフラットツールバー
を参照。)
WM_SIZE
1.WM_SIZEで、ツールバーの高さだけ、リッチエディットのy座標を変えます。
※これを忘れると、ツールバーが表示されなくなります。
TB_AUTOSIZEメッセージを送信します。
※これを忘れると、ウインドウサイズを初期値よりも大きくした場合、大きくした箇所のツールバーが表示されなくなります。
WM_COMMAND
1.WM_COMMANDで、メニューを選択されたときの動作を入れます。
ソースコードの入力
ソースコードは下記のように入れてください。
#include <windows.h> #include <commctrl.h> #include <richedit.h> #include "resource.h" #define TEXTMAX 10000 #define TOOLBAR_BOTTON 8 #pragma comment(lib, "comctl32.lib") // ツールバーの作成に必要 // グローバル変数: HINSTANCE hInst; // 現在のインターフェイス HWND hToolBar; // ツールバーのウィンドウハンドル WNDPROC defProc; // TBBUTTON(ツールバーボタン)型の配列 TBBUTTON tbButton[] = { { STD_FILEOPEN, ID_BUTTON1, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0}, { STD_FILESAVE, ID_BUTTON2, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0}, { STD_COPY, ID_BUTTON3, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0}, { STD_CUT, ID_BUTTON4, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0}, { STD_DELETE, ID_BUTTON5, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0}, { STD_PASTE, ID_BUTTON6, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0}, { STD_REDOW, ID_BUTTON7, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0}, { STD_UNDO, ID_BUTTON8, TBSTATE_ENABLED, TBSTYLE_BUTTON | BTNS_AUTOSIZE, 0, 0, 0} }; TBBUTTON tbSPACE = {0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0L}; // リッチエディットの使用するために用いる変数宣言 TCHAR strPath[MAX_PATH + 1]; // DLLのパス HINSTANCE hRtLib; // インスタンスハンドル HWND hRichEdit; // ウィンドウハンドル // このコード モジュールに含まれる関数の宣言を転送します: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); DWORD CALLBACK MySaveProc(DWORD, LPBYTE, LONG, LONG *); DWORD CALLBACK MyReadProc(DWORD, LPBYTE, LONG, LONG *); LRESULT CALLBACK ToolbarProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 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; OPENFILENAME of; // OPENFILENAME構造体 TCHAR szText[TEXTMAX] = TEXT(""); static TCHAR szFile[MAX_PATH] = TEXT(""); HANDLE hFile; EDITSTREAM eds; // EDITSTREAM構造体 int wmax; int iString[TOOLBAR_BOTTON]; TCHAR szBuf[128]; static UINT uToolStyle; UINT i; TBADDBITMAP tb; switch (message) { case WM_CREATE: InitCommonControls(); wmax = GetSystemMetrics(SM_CXSCREEN); hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); hToolBar = CreateWindowEx( 0, // 拡張スタイルなし TOOLBARCLASSNAME, // クラスネーム NULL, // ウィンドウタイトル WS_CHILD | WS_VISIBLE, // ウィンドウスタイル 0, 0, // ウィンドウ位置 wmax, 40, // ウィンドウ幅、高さ hWnd, // 親ウィンドウ (HMENU)IDW_TOOL, // コントロール識別子 hInst, // インスタンスハンドル NULL); tb.hInst = HINST_COMMCTRL; // ボタンをシステム定義のビットマップ tb.nID = IDB_STD_SMALL_COLOR; // システム標準ビットマップ(小) SendMessage(hToolBar, TB_ADDBITMAP, 0, (LPARAM)&tb); SendMessage(hToolBar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); for(i = 0; i < TOOLBAR_BOTTON; i++) { LoadString(hInst, tbButton[i].idCommand, (LPTSTR)&szBuf, sizeof(szBuf) - 1); iString[i] = SendMessage(hToolBar, TB_ADDSTRING, 0, (LPARAM)szBuf); tbButton[i].iString = iString[i]; } /* ツールバーにボタンを挿入 */ SendMessage(hToolBar, TB_ADDBUTTONS, (WPARAM)TOOLBAR_BOTTON, (LPARAM)(LPTBBUTTON)&tbButton); // ボタンの区切りを挿入 SendMessage(hToolBar, TB_INSERTBUTTON, 2, (LPARAM)&tbSPACE); /* ツールバーサブクラス化 */ defProc = (WNDPROC)GetWindowLong(hToolBar, GWL_WNDPROC); SetWindowLong(hToolBar, GWL_WNDPROC, (LONG)ToolbarProc); SetWindowLong(hToolBar, GWL_USERDATA, (LONG)defProc); /* フラットツールバー */ uToolStyle = (UINT)GetWindowLong(hToolBar, GWL_STYLE); uToolStyle |= (TBSTYLE_FLAT); SetWindowLong(hToolBar, GWL_STYLE, (LONG)uToolStyle); SendMessage(hToolBar, TB_AUTOSIZE, 0, 0); InvalidateRect(hToolBar, NULL, TRUE); // 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_MULTILINE のときのみ有効) | ES_NOHIDESEL, // 選択されているテキストは、コントロールが... // フォーカス持っていない場合も反転表示 0, // ウィンドウの横方向の位置 0, // ウィンドウの縦方向の位置 0, // ウィンドウの幅 0, // ウィンドウの高さ hWnd, // 親ウィンドウまたはオーナーウィンドウのハンドル (HMENU)IDC_RICHEDIT, // メニューハンドルまたは子識別子 hInst, // アプリケーションインスタンスのハンドル NULL); // ウィンドウ作成データ break; case WM_SIZE: MoveWindow(hToolBar, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); MoveWindow(hRichEdit, 0, 40, LOWORD(lParam), HIWORD(lParam), TRUE); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 選択されたメニューの解析: switch (wmId) { case IDM_OPEN: case ID_BUTTON1: // OPENFILENAME構造体のサイズをセット memset(&of, 0, sizeof(OPENFILENAME)); of.lStructSize = sizeof(OPENFILENAME); // ダイアログボックスを所有するウィンドウへのハンドル of.hwndOwner = hRichEdit; of.lpstrFilter = TEXT("TEXT(*.txt)\0 *.txt\0RTF(*.rtf)\0 *.rtf\0\0"); // ファイル名を格納したバッファのアドレス of.lpstrFile = (LPTSTR)szFile; // lpstrFileメンバで指定されるバッファのサイズ of.nMaxFile = MAX_PATH; // ダイアログボックスの初期化に使用されるビットフラグ // OFN_PATHMUSTEXIST:ユーザーが有効なパス // およびファイル名のみを入力できるように指定 of.Flags = OFN_PATHMUSTEXIST; // デフォルトの拡張子を格納したバッファのアドレス of.lpstrDefExt = TEXT("txt"); // コモンダイアログの表示 GetOpenFileName( &of ); hFile = CreateFile(szFile, // ファイル名 GENERIC_READ, // アクセス指定 GENERIC_READ:読み取り 0, // 共有方法 0:共有しない NULL, // セキュリティ属性 0:デフォルト OPEN_EXISTING, // 動作指定 OPEN_EXISTING:ファイルをオープン。 // ファイルが存在していない場合、 // 関数が失敗 FILE_ATTRIBUTE_NORMAL, // フラグと属性 // FILE_ATTRIBUTE_NORMAL:属性設定なし NULL); // テンプレートファイル if (hFile != INVALID_HANDLE_VALUE) { eds.dwCookie = (DWORD)hFile; // ファイルハンドルを渡す eds.dwError = 0; // 読み込み操作の結果 0はエラーなし eds.pfnCallback = MyReadProc; // コールバック関数アドレス SendMessage(hRichEdit, EM_STREAMIN, // 読み込み SF_TEXT, // テキスト形式 (LPARAM)&eds); // EDITSTREAM 構造体のアドレス SendMessage(hRichEdit, EM_SETMODIFY, // エディットコントロールの変更フラグを設定または解除 (WPARAM)FALSE, // 解除 0); CloseHandle(hFile); // ウインドウタイトルをファイル名にする SetWindowText(hWnd, (LPCTSTR)szFile); // メニューの選択可 EnableMenuItem(GetMenu(hWnd), IDM_SAVE, MF_ENABLED); } break; case IDM_SAVE: case ID_BUTTON2: hFile = CreateFile(szFile, // ファイル名 GENERIC_WRITE, // アクセス指定 GENERIC_WRITE:書き込み 0, // 共有方法 0:共有しない NULL, // セキュリティ属性 0:デフォルト OPEN_ALWAYS, // 動作指定 OPEN_ALWAYS:ファイルをオープン。 // ファイルが存在していない場合、 // 新しいファイルを作成 FILE_ATTRIBUTE_NORMAL // フラグと属性 // FILE_ATTRIBUTE_NORMAL:属性設定なし | FILE_FLAG_WRITE_THROUGH,// データをそのまま直接ディスクに書き込む NULL); // テンプレートファイル eds.dwCookie = (DWORD)hFile; // ファイルハンドルを渡す eds.dwError = 0; // 書き込み操作の結果 0はエラーなし eds.pfnCallback = MySaveProc; // コールバック関数アドレス SendMessage(hRichEdit, EM_STREAMOUT, // 書き込み (WPARAM)SF_TEXT, // テキスト形式 (LPARAM)&eds); // EDITSTREAM 構造体のアドレス SendMessage(hRichEdit, EM_SETMODIFY, // エディットコントロールの変更フラグを設定または解除 (WPARAM)FALSE, // 解除 0); CloseHandle(hFile); break; case IDM_SAVE2: // OPENFILENAME構造体のサイズをセット memset(&of, 0, sizeof(OPENFILENAME)); of.lStructSize = sizeof(OPENFILENAME); // ダイアログボックスを所有するウィンドウへのハンドル of.hwndOwner = hRichEdit; of.lpstrFilter = TEXT("TEXT(*.txt)\0 *.txt\0RTF(*.rtf)\0 *.rtf\0\0"); // ファイル名を格納したバッファのアドレス of.lpstrFile = (LPTSTR)szFile; // lpstrFileメンバで指定されるバッファのサイズ of.nMaxFile = MAX_PATH; of.Flags = OFN_OVERWRITEPROMPT; // デフォルトの拡張子を格納したバッファのアドレス of.lpstrDefExt = TEXT("txt"); // コモンダイアログの表示 GetSaveFileName( &of ); hFile = CreateFile(szFile, // ファイル名 GENERIC_WRITE, // アクセス指定 GENERIC_WRITE:書き込み 0, // 共有方法 0:共有しない NULL, // セキュリティ属性 0:デフォルト OPEN_ALWAYS, // 動作指定 OPEN_ALWAYS:ファイルをオープン。 // ファイルが存在していない場合、 // 新しいファイルを作成 FILE_ATTRIBUTE_NORMAL // フラグと属性 // FILE_ATTRIBUTE_NORMAL:属性設定なし | FILE_FLAG_WRITE_THROUGH,// データをそのまま直接ディスクに書き込む NULL); // テンプレートファイル eds.dwCookie = (DWORD)hFile; // ファイルハンドルを渡す eds.dwError = 0; // 書き込み操作の結果 0はエラーなし eds.pfnCallback = MySaveProc; // コールバック関数アドレス SendMessage(hRichEdit, EM_STREAMOUT, // 書き込み (WPARAM)SF_TEXT, // テキスト形式 (LPARAM)&eds); // EDITSTREAM 構造体のアドレス SendMessage(hRichEdit, EM_SETMODIFY, // エディットコントロールの変更フラグを設定または解除 (WPARAM)FALSE, // 解除 0); CloseHandle(hFile); break; case ID_BUTTON3: SendMessage(hRichEdit, WM_COPY, 0, 0); break; case ID_BUTTON4: SendMessage(hRichEdit, WM_CUT, 0, 0); break; case ID_BUTTON5: SendMessage(hRichEdit, WM_CLEAR, 0, 0); break; case ID_BUTTON6: SendMessage(hRichEdit, WM_PASTE, 0, 0); break; case ID_BUTTON7: SendMessage(hRichEdit, EM_REDO, 0, 0); break; case ID_BUTTON8: SendMessage(hRichEdit, EM_UNDO, 0, 0); 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; } DWORD CALLBACK MySaveProc(DWORD dwCookie, LPBYTE pbbuf, LONG cb, LONG *pcb) { if (WriteFile((HANDLE)dwCookie, pbbuf, cb, (LPDWORD)pcb, NULL)) { return FALSE; } else { return TRUE; } } DWORD CALLBACK MyReadProc(DWORD dwCookie, LPBYTE pbBuf, LONG cb, LONG *pcb) { ReadFile((HANDLE)dwCookie, pbBuf, cb, (LPDWORD)pcb, NULL); return(FALSE); } /* ツールバーサブクラス */ LRESULT CALLBACK ToolbarProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_RBUTTONDOWN: case WM_RBUTTONUP: if (SendMessage(hWnd, TB_GETHOTITEM, 0, 0) >= 0) { ReleaseCapture(); } return 0; } return CallWindowProc(defProc, hWnd, msg, wParam, lParam); }
上記の太線で示している箇所は追加で、 文字で示している箇所は、 ツールバー2: ボタンにビットマップを貼り付ける - インコのWindowsSDK からの流用です。
#define IDM_ABOUT 104 #define IDM_EXIT 105 #define IDM_SAVE 110 #define IDM_SAVE2 112 #define IDM_OPEN 111 #define IDC_HP 109 #define IDC_RICHEDIT 101 #define IDW_TOOL 150 #define ID_BUTTON1 151 #define ID_BUTTON2 152 #define ID_BUTTON3 153 #define ID_BUTTON4 154 #define ID_BUTTON5 155 #define ID_BUTTON6 156 #define ID_BUTTON7 157 #define ID_BUTTON8 158
上記の太線で示している箇所は追加で、 文字で示している箇所は、 ツールバー2: ボタンにビットマップを貼り付ける - インコのWindowsSDK からの流用です。
#include "resource.h"
/////////////////////////////////////////////////////////////////////////////
//
// メニュー
//
IDC_HP MENU
BEGIN
POPUP "ファイル(&F)"
BEGIN
MENUITEM "開く(&O)", IDM_OPEN
MENUITEM "上書き保存(&S)", IDM_SAVE
MENUITEM "名前を付けて保存(&A)", IDM_SAVE2
MENUITEM "アプリケーションの終了(&X)", IDM_EXIT
END
POPUP "ヘルプ(&H)"
BEGIN
MENUITEM "バージョン情報(&A)...", IDM_ABOUT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// ストリング テーブル
//
STRINGTABLE
BEGIN
ID_BUTTON1 "開く"
ID_BUTTON2 "保存"
ID_BUTTON3 "コピー"
ID_BUTTON4 "切り取り"
ID_BUTTON5 "削除"
ID_BUTTON6 "貼り付け"
ID_BUTTON7 "やり直し"
ID_BUTTON8 "元に戻す"
END
上記の太線で示している箇所は追加で、 文字で示している箇所は、 ツールバー2: ボタンにビットマップを貼り付ける - インコのWindowsSDK からの流用です。