<Previous> <Next> <SDK Top> <Top>
2章.3節.リッチエディットコントロールに打たれた文章を保存する
リッチエディットコントロールに打たれた文章をテキストファイルとして保存してみましょう. 左上の図がリッチエディットコントロールに"Hello SDK Programing!!"と打たれた図です. そして,その文字をsample.txtというファイルに保存します. さらに,そのファイルをメモ帳で開いたのが右上の図です! 今回のポイントは,どうやってリッチエディットコントロールの文字列を取得し, どうやってファイルに書き込むかというところですね. ここで,「別章.1節.メニューバーを編集してみよう」を参照して,「ファイルを保存する」ボタンを作成しましょう.
メニューボタンの配置場所 | ID |
[ファイル]-[上書き保存] | IDM_SAVE |
今回はこのように設定して,プログラムを組んでみましょう. ------------------------------------------------------------------------------------------------------------------------ #include "stdafx.h" #include <richedit.h> #include "resource.h" #define MAX_LOADSTRING 100 #define IDC_RICHEDIT (101) // グローバル変数: HINSTANCE hInst; // 現在のインスタンス TCHAR szTitle[MAX_LOADSTRING]; // タイトル バー テキスト TCHAR szWindowClass[MAX_LOADSTRING]; // タイトル バー テキスト // このコード モジュールに含まれる関数の前宣言: ATOM MyRegisterClass( HINSTANCE hInstance ); BOOL InitInstance( HINSTANCE, int ); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); BOOL SetCharFormats(HWND hWnd, char szFont[], COLORREF crColor, DWORD dwPoint, char* pszEffects); DWORD GetText(HWND hWnd, char* pszText); HANDLE OpenFile_Write( char* pszFilename ); BOOL CloseFile(HANDLE hFile); //リッチエディットの使用するために用いる変数 HINSTANCE hRtLib; HWND hRichEdit; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { MSG msg; HACCEL hAccelTable; // グローバル ストリングを初期化します LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_SAMPLE, szWindowClass, MAX_LOADSTRING); MyRegisterClass( hInstance ); // アプリケーションの初期化を行います: if( !InitInstance( hInstance, nCmdShow ) ) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SAMPLE); // メイン メッセージ ループ: while( GetMessage(&msg, NULL, 0, 0) ) { if( !TranslateAccelerator (msg.hwnd, hAccelTable, &msg) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } } return msg.wParam; } ATOM MyRegisterClass( HINSTANCE hInstance ) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SAMPLE); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCSTR)IDC_SAMPLE; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx( &wcex ); } BOOL InitInstance( HINSTANCE hInstance, int nCmdShow ) { HWND hWnd; hInst = hInstance; // グローバル変数にインスタンス ハンドルを保存します hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if( !hWnd ) { return FALSE; } ShowWindow( hWnd, nCmdShow ); UpdateWindow( hWnd ); return TRUE; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; DWORD dwSize; char szText[1024], szFile[]="sample.txt"; HANDLE hFile; DWORD dwNumberOfBytesToRead; switch( message ) { case WM_CREATE: hRtLib = LoadLibrary("RICHED32.DLL"); hRichEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "RICHEDIT", "", 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); SetCharFormats(hRichEdit, "MS ゴシック", 0x00FF00, 18, "B"); 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_SAVE: dwSize = GetText(hRichEdit, szText); hFile = OpenFile_Write( szFile ); WriteFile(hFile, szText, dwSize, &dwNumberOfBytesToRead, NULL ); CloseFile(hFile); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } BOOL SetCharFormats(HWND hWnd, char szFont[], COLORREF crColor, DWORD dwPoint, char* pszEffects) { DWORD dwCount; CHARFORMAT cfm; memset(&cfm, 0, sizeof(CHARFORMAT)); cfm.cbSize = sizeof(CHARFORMAT); cfm.dwMask = CFM_BOLD | CFM_CHARSET | CFM_COLOR | CFM_FACE | CFM_ITALIC | CFM_SIZE | CFM_STRIKEOUT | CFM_UNDERLINE; //エフェクト(効果).ボールド(太字)とか,イタリック(斜体)とか if( pszEffects != NULL ) { for( dwCount = 0; pszEffects[dwCount] != '\0'; dwCount++ ) { switch( pszEffects[dwCount] ) { case 'B': cfm.dwEffects = cfm.dwEffects | CFE_BOLD ; break; case 'I': cfm.dwEffects = cfm.dwEffects | CFE_ITALIC ; break; case 'S': cfm.dwEffects = cfm.dwEffects | CFE_STRIKEOUT ; break; } } } cfm.yHeight = (20)* dwPoint; //ポイント(文字の高さを twip 単位で指定します( 1 point=20 twip ) cfm.crTextColor = crColor; //カラー cfm.bCharSet = SHIFTJIS_CHARSET; //文字コード(WindowsならShiftJIS) lstrcpy(cfm.szFaceName, szFont); //フォント if (SendMessage(hWnd, EM_SETCHARFORMAT, SCF_SELECTION | SCF_WORD, (LPARAM)&cfm) == 0) { MessageBox(hWnd, "EM_SETCHARFORMAT失敗です", "Error", MB_OK); return FALSE; } return TRUE; } DWORD GetText(HWND hWnd, char* pszText) { DWORD dwSize; dwSize = GetWindowTextLength(hWnd); GetWindowText(hWnd, pszText, dwSize); return dwSize; } HANDLE OpenFile_Write( char* pszFilename ) { HANDLE hFile; hFile = CreateFile(pszFilename, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return INVALID_HANDLE_VALUE; } return hFile; } BOOL CloseFile(HANDLE hFile) { return CloseHandle( hFile ); } ------------------------------------------------------------------------------------------------------------------------ まずプロシージャー内のWM_COMMANDの処理から見ていきましょう. case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); switch( wmId ) { case IDM_SAVE: dwSize = GetText(hRichEdit, szText); hFile = OpenFile_Write( szFile ); WriteFile(hFile, szText, dwSize, &dwNumberOfBytesToRead, NULL ); CloseFile(hFile); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } break; WM_COMMANDはメニューバーのボタンが押されると飛んでくるメッセージです. IDM_SAVEはメニューバーの[ファイル]-[上書き保存]ボタンに対応するID(識別子)でしたね. [上書き保存]ボタンが押されると,case IDM_SAVEの処理が実行されます. 次はそのcase文内の関数を順に見ていきましょう. DWORD GetText(HWND hWnd, char* pszText) { DWORD dwSize; dwSize = GetWindowTextLength(hWnd); GetWindowText(hWnd, pszText, dwSize); return dwSize; } GetText関数は内部でGetWindowTextLengthという関数を呼んでいます. これはAPI(Application Program Interface)という関数群の一つです. このAPIは,Windowsが提供しており, 「この関数達を使ってアプリケーションを開発してください!」 っていうものです. その下のGetWindowTextもAPIです.リッチエディットコントロールを作ったCreateWindowEx関数もAPIです. で,この関数では何をしているかというと, GetWindowTextLength関数で,リッチエディットに打たれた文字列のバイト数を取得し, GetWindowText関数で,その文字数分だけリッチエディットから文字列を取得しています. HANDLE OpenFile_Write( char* pszFilename ) { HANDLE hFile; hFile = CreateFile(pszFilename, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return INVALID_HANDLE_VALUE; } return hFile; } では,書き込み専用でファイルを開いています. ファイルを開くAPIはCreateFile関数ですね.引数が多いですが,覚える必要なんてないです. WriteFile(hFile, szText, dwSize, &dwNumberOfBytesToRead, NULL ); WriteFile関数はAPIであり,szTextという配列に書き込まれた文字をファイルに書き出しています. BOOL CloseFile(HANDLE hFile) { return CloseHandle( hFile ); } そして,開いたファイルはちゃんと閉じないといけません. その役目をしているのが,CloseFile関数です. こんな感じでファイルに書き出せるんですね. あ!これってメモ帳ですね! 立派なアプリケーションが一つできあがりました.![]()
![]()
![]()
------------------------------------------------------------------------------------------------
当ページの一部または全部を転載、複写、複製することを禁じます。
また,当サイトを利用した結果に関するトラブル等は、一切関与いたしませんのでご容赦下さい。
Update 04/02/20 By 松本義弘
------------------------------------------------------------------------------------------------