<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 松本義弘

------------------------------------------------------------------------------------------------

デル4_120x60富士通ショッピングサイト WEB MART   NEC得選街   sotecロゴ88x31b   バナー 10000035