今回はドラッグ・アンド・ドロップで、ファイルの読み込みをします。
ファイルの読み書き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