第274章 自己解凍書庫を作る


今回はLHAの自己解凍書庫を作ります。作り方は簡単です。



もっとも簡単なコマンドラインは「s LZHファイル名」です。 おまけで、ツールバー、レバーコントロール、ツールチップを 付けてみました。



では、プログラムを見てみましょう。

// unlha03.rcの一部 ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "書庫の新規作成(&N)...", IDM_NEW MENUITEM "書庫を開く(&O)...", IDM_OPEN MENUITEM SEPARATOR MENUITEM "書庫にファイルを追加(&A)...", IDM_ADD MENUITEM "書庫からファイルを削除(&D)...", IDM_DEL MENUITEM SEPARATOR MENUITEM "解凍(&E)...", IDM_EXTRACT MENUITEM SEPARATOR MENUITEM "自己解凍書庫の作成(&S)...", IDM_SFX MENUITEM SEPARATOR MENUITEM "終了(&X)...", IDM_END END POPUP "表示(&V)" BEGIN MENUITEM "ツールバー(&T)", IDM_TOOL, CHECKED END END ///////////////////////////////////////////////////////////////////////////// // // Dialog // MYDIRDLG DIALOG DISCARDABLE 0, 0, 141, 151 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "ディレクトリ指定" FONT 9, "MS Pゴシック" BEGIN DEFPUSHBUTTON "OK",IDOK,7,130,50,14 PUSHBUTTON "キャンセル",IDCANCEL,84,130,50,14 LISTBOX IDC_LIST1,7,31,126,90,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP LTEXT "Static",IDC_STATIC1,7,7,127,19 END ///////////////////////////////////////////////////////////////////////////// // // Toolbar // MYTOOLBAR TOOLBAR DISCARDABLE 16, 15 BEGIN BUTTON IDM_ADD BUTTON IDM_EXTRACT BUTTON IDM_SFX END ///////////////////////////////////////////////////////////////////////////// // // Bitmap // MYTOOLBAR BITMAP DISCARDABLE "bmp00001.bmp" ///////////////////////////////////////////////////////////////////////////// // // String Table // STRINGTABLE DISCARDABLE BEGIN IDS_NEW "新規の書庫を作ります" IDS_OPEN "書庫を開きます" IDS_DELETE "書庫からファイルを削除します" IDS_ADD "書庫にファイルを追加します" IDS_EXTRACT "書庫からファイルを解凍します" IDS_SFX "自己解凍書庫を作ります" END

メニューに「自己解凍書庫の作成」「ツールバー」が増えました。

ツールバー、ビットマップ、ストリングテーブル(ツールチップ用)が増えました。

// unlha03.cpp #ifndef STRICT #define STRICT #endif #define ID_LISTVIEW 100 #define ID_TOOLBAR 101 #define ID_REBAR 102 #define ID_STATIC 103 #define ID_TOOLMENU 104 // unlha32.hでtime_tを使うためtime.hが必要です #include <time.h> // sprintf()を使う関係上stdio.hが必要です #include <stdio.h> #include <windows.h> #include <windowsx.h> #include <commctrl.h> #include "unlha32.h" #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDirProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); BOOL MyAdd(HWND, int); BOOL MyOpen(HWND, int); BOOL MySetColumn(HWND); BOOL MyExtract(HWND); BOOL MyDel(HWND hWnd); BOOL MySFX(HWND hWnd); char szClassName[] = "unlha03"; //ウィンドウクラス char szWindowTitle[] = "猫でもわかるアーカイバ [%s]"; HINSTANCE hInst; char szCmdLine[1024]; char szLZHFile[MAX_PATH], szOrgFile[MAX_PATH], szTitle[MAX_PATH]; char szDir[MAX_PATH]; HWND hList, hTool, hRb; BOOL bTool = TRUE; //Toolbarを表示するかどうか TBBUTTON tbBtn[] = { {STD_FILENEW, IDM_NEW, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}, {STD_FILEOPEN, IDM_OPEN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}, {STD_DELETE, IDM_DEL, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0} }; TBBUTTON tbLHA[] = { {0, IDM_ADD, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}, {1, IDM_EXTRACT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}, {2, IDM_SFX, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0} };

コモンコントロール関係のID、ツールバー関連の変数などが増えました。

WinMain, InitApp, InitInstanceの各関数に変更はありません。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; INITCOMMONCONTROLSEX ic; static HWND hStatic1, hStatic2; RECT rc; static int nRbH; REBARINFO ri; REBARBANDINFO rbi; TBADDBITMAP ta; int nStdID; MENUITEMINFO mi; static HMENU hMenu; LPARAM mylp; LPTOOLTIPTEXT lptip; LPNMHDR lpnmhdr; switch (msg) { case WM_CREATE: hMenu = GetMenu(hWnd); ic.dwSize = sizeof(INITCOMMONCONTROLSEX); ic.dwICC = ICC_LISTVIEW_CLASSES | ICC_BAR_CLASSES | ICC_COOL_CLASSES; InitCommonControlsEx(&ic); hStatic1 = CreateWindow("static", "", WS_CHILD | WS_VISIBLE | SS_SUNKEN, 0, 0, 0, 0, hWnd, (HMENU)ID_STATIC, hInst, NULL); hStatic2 = CreateWindow("static", "", WS_CHILD | WS_VISIBLE | SS_SUNKEN, 0, 0, 0, 0, hWnd, (HMENU)ID_STATIC, hInst, NULL); hRb = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, "", WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | RBS_VARHEIGHT | RBS_BANDBORDERS, 0, 0, 0, 0, hWnd, (HMENU)ID_REBAR, hInst, NULL); hTool = CreateToolbarEx(hRb, WS_CHILD | WS_VISIBLE | CCS_NORESIZE | CCS_NODIVIDER | CCS_NOMOVEY | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS, ID_TOOLBAR, 3, HINST_COMMCTRL, IDB_STD_SMALL_COLOR, tbBtn, 3, 0, 0, 0, 0, sizeof(TBBUTTON)); ta.hInst = NULL; ta.nID = (UINT)LoadBitmap(hInst, "MYTOOLBAR"); nStdID = SendMessage(hTool, TB_ADDBITMAP, (WPARAM)3, (LPARAM)&ta); tbLHA[0].iBitmap += nStdID; tbLHA[1].iBitmap += nStdID; tbLHA[2].iBitmap += nStdID; SendMessage(hTool, TB_ADDBUTTONS, (WPARAM)3, (LPARAM)tbLHA); memset(&ri, 0, sizeof(REBARINFO)); ri.cbSize = sizeof(REBARINFO); SendMessage(hRb, RB_SETBARINFO, 0, (LPARAM)&ri); memset(&rbi, 0, sizeof(REBARBANDINFO)); rbi.cbSize = sizeof(REBARBANDINFO); rbi.fMask = RBBIM_TEXT | RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE; rbi.fStyle = RBBS_CHILDEDGE | RBBS_GRIPPERALWAYS; rbi.lpText = "ファイル"; rbi.hwndChild = hTool; rbi.cxMinChild = 0; rbi.cyMinChild = 23; rbi.cx = 120; SendMessage(hRb, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbi); hList = CreateWindowEx(0, WC_LISTVIEW, "", WS_CHILD | WS_VISIBLE | LVS_REPORT, 0, 0, 0, 0, hWnd, (HMENU)ID_LISTVIEW, hInst, NULL); ListView_SetExtendedListViewStyle(hList, LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP); MySetColumn(hList); break; case WM_SIZE: if (bTool) { MoveWindow(hStatic1, 0, 0, LOWORD(lp), 2, TRUE); SendMessage(hRb, WM_SIZE, wp, lp); GetWindowRect(hRb, &rc); nRbH = rc.bottom - rc.top; MoveWindow(hStatic2, 0, nRbH + 2, LOWORD(lp), 2, TRUE); MoveWindow(hList, 0, nRbH + 4, LOWORD(lp), HIWORD(lp) - nRbH - 4, TRUE); } else { MoveWindow(hList, 0, 0, LOWORD(lp), HIWORD(lp), TRUE); } break; case WM_NOTIFY: lpnmhdr = (LPNMHDR)lp; switch (lpnmhdr->code) { case TTN_NEEDTEXT: lptip = (LPTOOLTIPTEXT)lp; lptip->hinst = hInst; switch (lptip->hdr.idFrom) { case IDM_NEW: lptip->lpszText = MAKEINTRESOURCE(IDS_NEW); break; case IDM_OPEN: lptip->lpszText = MAKEINTRESOURCE(IDS_OPEN); break; case IDM_DEL: lptip->lpszText = MAKEINTRESOURCE(IDS_DELETE); break; case IDM_ADD: lptip->lpszText = MAKEINTRESOURCE(IDS_ADD); break; case IDM_EXTRACT: lptip->lpszText = MAKEINTRESOURCE(IDS_EXTRACT); break; case IDM_SFX: lptip->lpszText = MAKEINTRESOURCE(IDS_SFX); break; default: return DefWindowProc(hWnd, msg, wp, lp); } default: return DefWindowProc(hWnd, msg, wp, lp); } break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_ADD: //iOpt 1..追加 //iOpt 0..新規 MyAdd(hWnd, 1); break; case IDM_NEW: MyAdd(hWnd, 0); break; case IDM_OPEN: //iOpt 0...新規オープン MyOpen(hWnd, 0); break; case IDM_EXTRACT: MyExtract(hWnd); break; case IDM_DEL: MyDel(hWnd); break; case IDM_SFX: MySFX(hWnd); break; case IDM_TOOL: memset(&mi, 0, sizeof(MENUITEMINFO)); mi.cbSize = sizeof(MENUITEMINFO); mi.fMask = MIIM_STATE; if (bTool) { mi.fState = MFS_UNCHECKED; SetMenuItemInfo(hMenu, IDM_TOOL, FALSE, &mi); bTool = FALSE; ShowWindow(hRb, SW_HIDE); } else { mi.fState = MFS_CHECKED; SetMenuItemInfo(hMenu, IDM_TOOL, FALSE, &mi); bTool = TRUE; ShowWindow(hRb, SW_NORMAL); } GetClientRect(hWnd, &rc); mylp = MAKELPARAM(rc.right - rc.left, rc.bottom - rc.top); SendMessage(hWnd, WM_SIZE, (WPARAM)SIZE_RESTORED, mylp); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hStatic1); DestroyWindow(hStatic2); DestroyWindow(hTool); DestroyWindow(hRb); DestroyWindow(hList); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

WM_CREATEメッセージが来たら、スタティックコントロール2つ(境界線用)、レバーコントロール、 ツールバー、リストビューを作ります。

WM_SIZEメッセージが来た時の処理は場合分けされています。 レバーコントロールを表示する時と、非表示の場合です。それぞれのコントロールの 位置、大きさ等を調整します。

WM_NOTIFYの処理はツールチップ用です。この方法が一番簡単なようです。 忘れてしまった方は第65章を参照してください。

メニューからIDM_SFXが選択されたら、MySFX関数を呼びます。

IDM_TOOLが選択されたら、レバーコントロールの表示・非表示を切り替えます。 表示・非表示の切り替えはShowWindow関数で行っていますが、これだけでは 各コントロールの位置関係がおかしくなります。それで親ウィンドウにWM_SIZE メッセージを送って、位置・大きさを調整します。もっと姑息な方法としては 非表示になったときに親ウィンドウの縦方向のサイズを1縮めて、表示になったときに 1延ばす、というのがあります。これでもWM_SIZEメッセージが送られるので 同じことです。親ウィンドウが1ピクセル程度伸び縮みしてもユーザーには全く 気づかれません。

プログラム終了時には各コントロールを破棄しておきます。

MyAdd, MyOpen, MyOpen, MySetColumn, MyExtract, MyDel, MyDirProc の各関数に変更はありません。

BOOL MySFX(HWND hWnd) { char szBuf[1024]; if (strcmp(szLZHFile, "") == 0) { MessageBox(hWnd, "書庫ファイルが開かれていません", "Error", MB_OK); return FALSE; } wsprintf(szBuf, "%sから自動解凍書庫を作りますかよろしいですか", szLZHFile); if (MessageBox(hWnd, szBuf, "自動解凍書庫", MB_YESNO | MB_ICONQUESTION) == IDNO) return FALSE; strcpy(szCmdLine, "s -gw "); strcat(szCmdLine, "\""); strcat(szCmdLine, szLZHFile); strcat(szCmdLine, "\""); if (Unlha(hWnd, szCmdLine, szBuf, sizeof(szBuf))) { MessageBox(hWnd, szBuf, "Error", MB_OK); return FALSE; } return TRUE; }

自己解凍書庫を作る関数です。ここでは32ビット版ウィンドウズでの 使用を想定しているので-gwスイッチを付けました。

Unlha関数はパラメータ関係が大変複雑なので、添付のテキストをよく読んでおいてください。


[SDK第3部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 06/Jun/2000 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。