今回はドラッグ・アンド・ドロップで、ファイルの読み込みをします。
ファイルの読み書き2:コモンダイアログ - インコのWindowsSDK で作成したソースを修正します。
流れ
WM_CREATE
1.WM_DROPFILESメッセージを処理するようにする[DragAcceptFiles()]
VOID DragAcceptFiles(
HWND hWnd, // ウィンドウのハンドル
BOOL fAccept // 受け入れの有無
);
fAcceptがtrueのときは、ファイルがドロップされたときにWM_DROPFILESメッセージが送られてくるようになります。
WM_DROPFILES
2.WndProc()にファイルをドロップされたときの処理[WM_DROPFILES]を追加
3.DragQueryFile()で、ドロップされたファイル数を取得。
UINT DragQueryFile(
HDROP hDrop, // ファイル名構造体のハンドル
UINT iFile, // 取得するファイルのインデックス番号
LPTSTR lpszFile, // 取得したファイル名を格納するバッファ
UINT cch // 取得したファイル名を格納するバッファのサイズ
);
・hDrop:WM_DROPFILES メッセージ発生時の wParam パラメータ[WndProc()の第3引数]。
・iFileを-1にすることにより、戻り値がドロップされたファイル数になります。
4.ファイル数が2以上のときは、エラー表示をして、以下5と6の処理はしない。
5.DragQueryFile()で、ドロップされたファイル名を取得。
6. ファイルの読み書き1 - インコのWindowsSDK で行ったように、ファイルを開く処理をする。
7.ファイル名を転送するためにシステムが割り当てたメモリを解放[DragFinish()]
VOID DragFinish(
HDROP hDrop // ファイル名構造体のハンドル
);
ソースコードの入力
ソースコードは下記のように入れてください。
#include <windows.h>
#include <richedit.h>
#include "resource.h"
#define TEXTMAX 10000
// グローバル変数:
HINSTANCE hInst; // 現在のインターフェイス
// リッチエディットの使用するために用いる変数宣言
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 *);
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_DROPFILES - ファイルをドロップされたときの処理
// WM_COMMAND - アプリケーション メニューの処理
// WM_DESTROY - 中止メッセージを表示して戻る
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
HDROP hDrop;
UINT uFileNo;
OPENFILENAME of; // OPENFILENAME構造体
TCHAR szText[TEXTMAX] = TEXT("");
static TCHAR szFile[MAX_PATH] = TEXT("");
HANDLE hFile;
EDITSTREAM eds; // EDITSTREAM構造体
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_MULTILINE のときのみ有効)
| ES_NOHIDESEL, // 選択されているテキストは、コントロールが...
// フォーカス持っていない場合も反転表示
0, // ウィンドウの横方向の位置
0, // ウィンドウの縦方向の位置
0, // ウィンドウの幅
0, // ウィンドウの高さ
hWnd, // 親ウィンドウまたはオーナーウィンドウのハンドル
(HMENU)IDC_RICHEDIT, // メニューハンドルまたは子識別子
hInst, // アプリケーションインスタンスのハンドル
NULL); // ウィンドウ作成データ
// WM_DROPFILESメッセージを処理するようにする
DragAcceptFiles(hWnd, TRUE);
break;
case WM_SIZE:
MoveWindow(hRichEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
break;
case WM_DROPFILES:
hDrop = (HDROP)wParam;
// ドロップされたファイル数を取得
uFileNo = DragQueryFile((HDROP)wParam, -1, NULL, 0);
if(uFileNo > 1)
{
MessageBox(hWnd, TEXT("ファイルを開けませんでした"), TEXT("失敗"), MB_OK);
}
else
{
DragQueryFile(hDrop, 0, szFile, sizeof(szFile));
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);
}
}
DragFinish(hDrop);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// 選択されたメニューの解析:
switch (wmId)
{
case IDM_OPEN:
// 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:
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 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);
}
上記の太線で示している箇所のみ追加です。
#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
#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