第221章 ディレクトリをリストビュー表示する


前章までのFTPはなんとなくみすぼらしい感じがしました。 今回はリストボックスをリストビュー表示に変えてみます。 そして、ファイル名だけではなく、ファイルサイ、ファイル更新日時 も表示するようにします。



リストビューに変更するとなんとなく見栄えがします。 FTPの機能そのものは今までとまったく同じです。



では、どこをどのように変更すればよいのでしょうか。 ちょっと考えると面倒くさいようにも思えますが、意外に簡単です。 まず、リストボックスコントロールを作るところを、リストビューを 作るように変更します。このとき項目名(「ファイル名」「サイズ」「更新日時」) も作っておきます。

また、リストビューからの通知メッセージはWM_NOTIFYの形でやってくるので この点も変更が必要です。

あとは、ListBox_*のマクロを探してListView_*に合うように適宜プログラムに 修正を加えます。さて、このときWIN32_FIND_DATA構造体からファイルの日時を 取得するにはどうすればよいのでしょうか。 第218章で示したようにWIN32_FIND_DATA構造体には ファイルに関連した日時を表す3つのメンバ(作成日時・アクセス日時・更新日時)がありました。 いずれもFILETIME構造体であらわされています。

typedef struct _FILETIME { // ft DWORD dwLowDateTime; DWORD dwHighDateTime; } FILETIME;

ファイルタイムとは1601年1月1日からの0.1ミリ秒間隔の64ビット値です。

dwLowDateTimeは、ファイルタイムの下位32ビット値です。
dwHighDateTimeは、ファイルタイムの上位32ビット値です。

ファイルタイムを通常の日時に直すのはめんどうです。こういうのはたいてい 便利な関数とかマクロが用意されているはずです。

BOOL FileTimeToSystemTime( CONST FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime );

名前のとおりファイルタイムをシステムタイムに変換する関数です。

lpFileTimeは変換するFILETIME構造体へのポインタです。
lpSystemTimeはシステムタイムを受け取るSYSTEMTIME構造体へのポインタです。

成功すると0以外を失敗すると0を返します。

BOOL FileTimeToLocalFileTime( CONST FILETIME *lpFileTime, LPFILETIME lpLocalFileTime );

世界標準時間(the Coordinated Universal Time (UTC))に基づくファイルタイムを ローカルファイルタイムに変換する関数です。

lpFileTimeはUTCに基づくファイルタイムの入ったFILETIME構造体へのポインタです。
lpLocalFileTime変換結果が格納されるFILETIME構造体へのポインタです。

成功すると0以外が、失敗すると0が返されます。

さて、このくらいの予備知識があると日時付きのディレクトリ表示が可能です。

リソース・スクリプトは前章に比べ変更がありません。

// myftp05.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <wininet.h> #include <windowsx.h> #include <commctrl.h> #include "resource.h" #define ID_LIST 100 #define ID_STATIC 101 #define ID_LISTL 102 #define ID_STATICL 103 typedef struct _tagAccount{ char szUserName[64]; char szPassWord[64]; } ACCOUNT; typedef struct _tagFTPAddress{ char szHost[64]; char szBaseDir[64]; } FTPADDRESS; typedef struct _tagINETHANDLE{ HINTERNET hInternet; HINTERNET hHost; } INETHANDLE; typedef struct _tagFNAME{ char szFName[MAX_PATH]; char szLocalFileName[MAX_PATH]; } FNAME; typedef struct _tagHWNDSET{ HWND hwnd1; HWND hwnd2; } HWNDSET; LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyAccountProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyFtpAddressProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyGetFNameProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyDriveProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyCreateDirProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); BOOL MyConnect(HWND, INETHANDLE *, ACCOUNT, FTPADDRESS, HWND, HWND); void MyDown(HWND, INETHANDLE, FTPADDRESS, FNAME *, HWND, HWND, HWND); void SetAccount(HWND, ACCOUNT *); void SetHost(HWND, FTPADDRESS *); void GetAllFiles(HWND, HWND, HWND, INETHANDLE *); void SetMyLocalDir(HWND, HWND, HWND); void ChangeLocalDrive(HWND, HWND, HWND); void MyUp(HWND, INETHANDLE, HWND, HWND, HWND, HWND); void MyFtpDelFile(HWND, INETHANDLE, HWND, HWND); void MyFtpCreatDir(HWND, INETHANDLE, HWND, HWND); HWND MakeMyList(HWND); void InsertMyColumn(HWND); const char szWindowTitle[] = "猫でもわかるFTP"; char szClassName[] = "myftp05"; //ウィンドウクラス BOOL bConnect = FALSE;//インターネットに接続しているかどうか

コモンコントロールを取り扱うのでcommctrl.hをインクルードするのを忘れないで ください。その他の前準備(comctl32.libのリンク)も忘れないでください。

MakeMyList, InsertMyColumnという自作関数でリストビューをつくり列項目を 挿入します。

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

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id, i, iIndex; static ACCOUNT myaccount; static FNAME myfname; static FTPADDRESS myftpaddress; static INETHANDLE inet; static HWND hList, hStatic, hListL, hStaticL; static HINSTANCE hInst; RECT rc; HDWP hDwp; char szDir[MAX_PATH], szBuf[MAX_PATH]; INITCOMMONCONTROLSEX icc; LPNMHDR lpnmhdr; switch (msg) { case WM_CREATE: icc.dwSize = sizeof(INITCOMMONCONTROLSEX); icc.dwICC = ICC_LISTVIEW_CLASSES; InitCommonControlsEx(&icc); hInst = ((LPCREATESTRUCT)lp)->hInstance; GetClientRect(hWnd, &rc); hList = MakeMyList(hWnd); InsertMyColumn(hList); hListL = MakeMyList(hWnd); InsertMyColumn(hListL); hStatic = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 0, 0, hWnd, (HMENU)ID_STATIC, hInst, NULL); hStaticL = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE | WS_BORDER, 0, 0, 0, 0, hWnd, (HMENU)ID_STATICL, hInst, NULL); SetMyLocalDir(hWnd, hListL, hStaticL); break; case WM_SIZE: hDwp = BeginDeferWindowPos(4); hDwp = DeferWindowPos(hDwp, hStaticL, HWND_TOP, 10, 5, LOWORD(lp) / 2 - 15, 30, SWP_SHOWWINDOW); hDwp = DeferWindowPos(hDwp, hStatic, HWND_TOP, LOWORD(lp) / 2 + 5, 5, LOWORD(lp) / 2 - 15, 30, SWP_SHOWWINDOW); hDwp = DeferWindowPos(hDwp, hListL, HWND_TOP, 10, 40, LOWORD(lp) / 2 - 15, HIWORD(lp) - 50, SWP_SHOWWINDOW); hDwp = DeferWindowPos(hDwp, hList, HWND_TOP, LOWORD(lp) / 2 + 5, 40, LOWORD(lp) / 2 - 15, HIWORD(lp) - 50, SWP_SHOWWINDOW); EndDeferWindowPos(hDwp); break; case WM_NOTIFY: lpnmhdr = (LPNMHDR)lp; if (lpnmhdr->hwndFrom == hListL) { switch (lpnmhdr->code) { case NM_DBLCLK: iIndex = ListView_GetNextItem(hListL, -1, LVNI_SELECTED); ListView_GetItemText(hListL, iIndex, 0, szDir, sizeof(szDir)); if (strstr(szDir, "<dir> ") != szDir) { MessageBox(hWnd, "ディレクトリではありません", "注意", MB_OK); break; } for (i =0; i <= lstrlen(szDir) - 5; i++) { szBuf[i] = szDir[i + 6]; } SetCurrentDirectory(szBuf); SetMyLocalDir(hWnd, hListL, hStaticL); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } } if (lpnmhdr->hwndFrom == hList) { switch (lpnmhdr->code) { case NM_DBLCLK: iIndex = ListView_GetNextItem(hList, -1, LVNI_SELECTED); ListView_GetItemText(hList, iIndex, 0, szDir, sizeof(szDir)); if (strstr(szDir, "<dir> ") != szDir) { MessageBox(hWnd, "ディレクトリではありません", "注意", MB_OK); break; } for (i =0; i <= lstrlen(szDir) - 5; i++) { szBuf[i] = szDir[i + 6]; } FtpSetCurrentDirectory(inet.hHost, szBuf); GetAllFiles(hWnd, hList, hStatic, &inet); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } } break; case WM_COMMAND: switch (LOWORD(wp)) { case IDM_LOCALDRIVE: ChangeLocalDrive(hWnd, hListL, hStaticL); break; case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_CONNECT: bConnect = MyConnect(hWnd, &inet, myaccount, myftpaddress, hList, hStatic); break; case IDM_DOWNLOAD: MyDown(hWnd, inet, myftpaddress, &myfname, hList, hListL, hStaticL); break; case IDM_UPLOAD: MyUp(hWnd, inet, hList, hStatic, hListL, hStaticL); break; case IDM_DELFILE: MyFtpDelFile(hWnd, inet, hList, hStatic); break; case IDM_CREATEDIR: MyFtpCreatDir(hWnd, inet, hList, hStatic); break; case IDM_ACCOUNT: SetAccount(hWnd, &myaccount); break; case IDM_GETHOST: SetHost(hWnd, &myftpaddress); break; case IDM_DISCONNECT: if (!bConnect) { MessageBox(hWnd, "インターネットに接続されていません", "失敗", MB_OK); break; } if (InternetCloseHandle(inet.hHost)) MessageBox(hWnd, "FTPをクローズしました", "OK", MB_OK); if (InternetCloseHandle(inet.hInternet)) MessageBox(hWnd, "インターネットから切り離しました", "OK", MB_OK); bConnect = FALSE; SetWindowText(hWnd, szWindowTitle); break; } break; case WM_CLOSE: if (bConnect) { MessageBox(hWnd, "インターネットの接続を切ってから終了してください", "注意", MB_OK); break; } id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hList); DestroyWindow(hStatic); DestroyWindow(hListL); DestroyWindow(hStaticL); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

WM_CREATEが来たら、コモンコントロールを初期化します。

MakeMyList, InsertMyColumn関数でリストビューを作ります。

さて、リストビューからの通知メッセージはWM_NOTIFYの形でやってくるので 書き換えが必要です。
ローカルのディレクトリを表示するリストビュー(hListL)からの 通知メッセージで、それがダブルクリックであれば、ListView_GetNextItem マクロで選択されている項目のインデックスを取得します。 このマクロについてはすでに 第108章で解説しています。 さて、ダブルクリックをするのはカレントディレクトリを変更するときですから 選択されているのがファイルの時はその旨注意をして何もしません。 ディレクトリ名の時はカレントディレクトリを変更して、SetMyLocalDir関数を 呼んで表示しなおします。

FTPのディレクトリを表示するリストビュー(hList)からの通知メッセージで 、それがだぶるくりっくであるときも同じような処理をします。

MyConnect関数に変更はありません。

void MyDown(HWND hWnd, INETHANDLE inet, FTPADDRESS ftpadr, FNAME *lpfname, HWND hList, HWND hListL, HWND hStaticL) { HINSTANCE hInst; int iIndex; if (!bConnect) { MessageBox(hWnd, "インターネットに接続されていません", "失敗", MB_OK); return; } iIndex = ListView_GetNextItem(hList, -1, LVNI_SELECTED); ListView_GetItemText(hList, iIndex, 0, lpfname->szFName, MAX_PATH); GetWindowText(hStaticL, lpfname->szLocalFileName, sizeof(lpfname->szLocalFileName)); strcat(lpfname->szLocalFileName, "\\"); strcat(lpfname->szLocalFileName, lpfname->szFName); hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); if (DialogBoxParam(hInst, "MYGETFNAME", hWnd, (DLGPROC)MyGetFNameProc, (LPARAM)lpfname) == IDCANCEL) return; if (!FtpGetFile(inet.hHost, //FTPのインターネットハンドル lpfname->szFName, //ダウンロードするファイル lpfname->szLocalFileName, //ダウンロード先のパス付ファイル名 TRUE, //ダウンロード先に同名のファイルがあるときエラーにする(上書き防止) FILE_ATTRIBUTE_NORMAL, //ダウンロード先に作られるファイルのアトリビュート FTP_TRANSFER_TYPE_BINARY, //バイナリファイルとしてダウンロード 0 )) { MessageBox(hWnd, "ダウンロードに失敗しました。", "失敗", MB_OK); return; } SetMyLocalDir(hWnd, hListL, hStaticL); MessageBox(hWnd, "無事ダウンロードできました", "OK", MB_OK); return; }

ListBox_GetCurSel, ListBox_GetTextのマクロを ListView_GetNextItem, ListView_GetItemTextに書き換えました。 ListView_GetItemTextマクロはすでに 第110章で解説しています。

MyGetFNameProc, SetAccount, MyAccountProc, SetHost, MyFtpAddressProc の各関数に変更はありません。

void GetAllFiles(HWND hWnd, HWND hList, HWND hStatic, INETHANDLE *lpinet) { WIN32_FIND_DATA FindFileData; HINTERNET hFindHandle; char fname[MAX_PATH + 5]; char szStr[MAX_PATH]; DWORD dwCD = MAX_PATH; LVITEM li; int iItemNo = 0; SYSTEMTIME st; if (FtpGetCurrentDirectory(lpinet->hHost, szStr, &dwCD) == TRUE) SetWindowText(hStatic, szStr); else { MessageBox(hWnd, "現在のディレクトリを取得できません", "失敗", MB_OK); return; } ListView_DeleteAllItems(hList); hFindHandle = FtpFindFirstFile(lpinet->hHost, "*.*", &FindFileData, INTERNET_FLAG_RELOAD, 0); if (hFindHandle == NULL) { if (GetLastError() == ERROR_NO_MORE_FILES) { MessageBox(hWnd, "ファイルはありません", "Error", MB_OK); return; } else { MessageBox(hWnd, "深刻なエラーが発生しました", "Error", MB_OK); InternetCloseHandle(lpinet->hHost); InternetCloseHandle(lpinet->hInternet); bConnect = FALSE; SetWindowText(hWnd, szWindowTitle); return; } } else { if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { strcpy(fname, "<dir> "); strcat(fname, FindFileData.cFileName); } else { strcpy(fname, FindFileData.cFileName); } li.mask = LVIF_TEXT; li.pszText = fname; li.iItem = iItemNo; li.iSubItem = 0; ListView_InsertItem(hList, &li); itoa(FindFileData.nFileSizeLow, li.pszText, 10); li.iSubItem = 1; ListView_SetItem(hList, &li); FileTimeToSystemTime(&FindFileData.ftLastWriteTime, &st); wsprintf(li.pszText, "%02d/%02d/%02d %02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute); li.iSubItem = 2; ListView_SetItem(hList, &li); iItemNo++; } while (InternetFindNextFile(hFindHandle, &FindFileData)) { if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { strcpy(fname, "<dir> "); strcat(fname, FindFileData.cFileName); } else { strcpy(fname, FindFileData.cFileName); } li.mask = LVIF_TEXT; li.pszText = fname; li.iItem = iItemNo; li.iSubItem = 0; ListView_InsertItem(hList, &li); itoa(FindFileData.nFileSizeLow, li.pszText, 10); li.iSubItem = 1; ListView_SetItem(hList, &li); FileTimeToSystemTime(&FindFileData.ftLastWriteTime, &st); wsprintf(li.pszText, "%02d/%02d/%02d %02d:%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute); li.iSubItem = 2; ListView_SetItem(hList, &li); iItemNo++; } InternetCloseHandle(hFindHandle); return; }

FTPのカレントディレクトリをリストビューに表示する関数です。
LV_ITEM構造体はLVITEM構造体に名前が変わりました。LV_*という名前の 構造体はみなアンダスコアがとれました。

ListBox_ResetContentマクロがListView_DeleteAllItemsになりました。

BOOL ListView_DeleteAllItems( HWND hwnd );

リストビューからすべてのアイテムを削除します。成功したらTRUEを 失敗したらそれ以外を返します。

WIN32_FIND_DATA構造体に取得したファイルのデータをListView_InsertItem, ListView_SetItemマクロでリストビューに表示します。 たいていのFTPソフトではFTPにあるファイルの日時をローカル時間に 変換しないでそのまま表示しているようです。したがって FileTimeToSystemTime関数でファイルタイムをそのままシステムタイムに 変換してリストビューに表示します。

void SetMyLocalDir(HWND hWnd, HWND hListL, HWND hStaticL) { char szfname[MAX_PATH + 5]; WIN32_FIND_DATA wfd; HANDLE hFind; int iItemNo = 0; LVITEM li; SYSTEMTIME localtm; FILETIME localft; ListView_DeleteAllItems(hListL); GetCurrentDirectory(MAX_PATH, szfname); SetWindowText(hStaticL, szfname); hFind = FindFirstFile("*.*", &wfd); if (hFind == INVALID_HANDLE_VALUE) { MessageBox(hWnd, "エラーです", "Error", MB_OK); FindClose(hFind); return; } else { if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { strcpy(szfname, "<dir> "); strcat(szfname, wfd.cFileName); } else { strcpy(szfname, wfd.cFileName); } li.mask = LVIF_TEXT; li.pszText = szfname; li.iItem = iItemNo; li.iSubItem = 0; ListView_InsertItem(hListL, &li); itoa(wfd.nFileSizeLow, li.pszText, 10); li.iSubItem = 1; ListView_SetItem(hListL, &li); FileTimeToLocalFileTime(&wfd.ftLastWriteTime, &localft); FileTimeToSystemTime(&localft, &localtm); wsprintf(li.pszText, "%02d/%02d/%02d %02d:%02d", localtm.wYear, localtm.wMonth, localtm.wDay, localtm.wHour, localtm.wMinute); li.iSubItem = 2; ListView_SetItem(hListL, &li); iItemNo++; } while (FindNextFile(hFind, &wfd)) { if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { strcpy(szfname, "<dir> "); strcat(szfname, wfd.cFileName); } else { strcpy(szfname, wfd.cFileName); } li.mask = LVIF_TEXT; li.pszText = szfname; li.iItem = iItemNo; li.iSubItem = 0; ListView_InsertItem(hListL, &li); itoa(wfd.nFileSizeLow, li.pszText, 10); li.iSubItem = 1; ListView_SetItem(hListL, &li); FileTimeToLocalFileTime(&wfd.ftLastWriteTime, &localft); FileTimeToSystemTime(&localft, &localtm); wsprintf(li.pszText, "%02d/%02d/%02d %02d:%02d", localtm.wYear, localtm.wMonth, localtm.wDay, localtm.wHour, localtm.wMinute); li.iSubItem = 2; ListView_SetItem(hListL, &li); iItemNo++; } FindClose(hFind); return; }

ローカルのカレントディレクトリをリストビューに表示する関数です。 やっていることはGetAllFiles関数とほとんど同じです。

WIN32_FIND_DATA構造体に取得したファイルタイムをそのまま使わずに FileTimeToLocalFileTime関数でローカルファイルタイムに変換してから 表示しています。

ChangeLocalDrive, MyDriveProc関数に変更はありません。

void MyUp(HWND hWnd, INETHANDLE ih, HWND hList, HWND hStatic, HWND hListL, HWND hStaticL) { int iIndex; DWORD dwSize; char szMsg[512], szFile[MAX_PATH], szFTPPath[MAX_PATH]; if (bConnect == FALSE) { MessageBox(hWnd, "インターネットに接続されていません", "失敗", MB_OK); return; } dwSize = sizeof(szFTPPath); iIndex = ListView_GetNextItem(hListL, -1, LVNI_SELECTED); ListView_GetItemText(hListL, iIndex, 0, szFile, sizeof(szFile)); FtpGetCurrentDirectory(ih.hHost, szFTPPath, &dwSize); wsprintf(szMsg, "「%s」を「%s」にアップロードします。\nよろしいですか。", szFile, szFTPPath); iIndex = MessageBox(hWnd, szMsg, "アップロード", MB_YESNO | MB_ICONQUESTION); if (iIndex == IDNO) return; if (!FtpPutFile(ih.hHost, szFile, szFile, INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD, 0)) { MessageBox(hWnd, "アップロードに失敗しました", "失敗", MB_OK); return; } MessageBox(hWnd, "無事アップロードできました", "成功", MB_OK); GetAllFiles(hWnd, hList, hStatic, &ih);//ftpカレントディレクトリ再表示 return; }

ListBox_GetCurSel, ListBox_GetTextマクロでローカルのファイル名を取得していたのを ListView_GetNextItem, ListView_GetItemTextマクロに書き換えました。あとは同じです。

void MyFtpDelFile(HWND hWnd, INETHANDLE inet, HWND hList, HWND hStatic) { int iIndex; char szFile[MAX_PATH], szStr[MAX_PATH], szFTPPATH[MAX_PATH]; DWORD dwSize; if (bConnect == FALSE) { MessageBox(hWnd, "インターネットに接続されていません", "失敗", MB_OK); return; } iIndex = ListView_GetNextItem(hList, -1, LVNI_SELECTED); ListView_GetItemText(hList, iIndex, 0, szFile, sizeof(szFile)); dwSize = sizeof(szFTPPATH); FtpGetCurrentDirectory(inet.hHost, szFTPPATH, &dwSize); wsprintf(szStr, "「%s」から「%s」を削除してもよろしいですか", szFTPPATH, szFile); iIndex = MessageBox(hWnd, szStr, "ファイル削除", MB_YESNO | MB_ICONQUESTION); if (iIndex == IDNO) return; FtpDeleteFile(inet.hHost, szFile); GetAllFiles(hWnd, hList, hStatic, &inet);//ftpカレントディレクトリ再表示 return; }

FTPのファイルを削除する関数です。

これもListBox_GetCurSel, ListBox_GetTextマクロで削除するファイル名を 取得していたのをListView_GetNextItem, ListView_GetItemTextに書き直しただけです。

MyFtpCreatDir, MyCreateDirProc関数に変更はありません。

HWND MakeMyList(HWND hWnd) { HWND hList; DWORD dwStyle; HINSTANCE hInst; hInst = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE); hList = CreateWindowEx(0, WC_LISTVIEW, "", WS_CHILD | WS_VISIBLE | LVS_REPORT | WS_BORDER | LVS_SINGLESEL, 0, 0, 0, 0, hWnd, (HMENU)100, hInst, NULL); dwStyle = ListView_GetExtendedListViewStyle(hList); dwStyle |= LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_HEADERDRAGDROP; ListView_SetExtendedListViewStyle(hList, dwStyle); return hList; }

リストビューを作る関数です。新しいリストビューについては 第198章を参照してください。 ここでは、複数のアイテムが選択されてはまずいのでLVS_SINGLESELスタイルを 加えています。

void InsertMyColumn(HWND hList) { LVCOLUMN lc; lc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lc.fmt = LVCFMT_LEFT; lc.cx = 100; lc.pszText = "ファイル名"; lc.iSubItem = 0; ListView_InsertColumn(hList, 0, &lc); lc.cx = 75; lc.pszText = "サイズ"; lc.iSubItem = 1; ListView_InsertColumn(hList, 1, &lc); lc.cx = 110; lc.pszText = "更新日時"; lc.iSubItem = 2; ListView_InsertColumn(hList, 2, &lc); return; }

リストビューにカラムを挿入する関数です。特に説明は 不要でしょう。

今回は今まで作ったプログラムのリストボックスの部分を リストビューに変更しただけです。やや面倒くさいところもありますが そんなに難しくはないですね。

このプログラムを動かしてまず、気の付くことは大変使いにくいことです。 それは、リストビューに表示されるファイル等が順不同だからです。 このへんを改良してみてください。


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

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