<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関数です.
こんな感じでファイルに書き出せるんですね.
あ!これってメモ帳ですね!
立派なアプリケーションが一つできあがりました.
Menu/Top.png)
------------------------------------------------------------------------------------------------
当ページの一部または全部を転載、複写、複製することを禁じます。
また,当サイトを利用した結果に関するトラブル等は、一切関与いたしませんのでご容赦下さい。
Update 04/02/20 By 松本義弘
------------------------------------------------------------------------------------------------