リストビューに変更するとなんとなく見栄えがします。
FTPの機能そのものは今までとまったく同じです。
では、どこをどのように変更すればよいのでしょうか。
ちょっと考えると面倒くさいようにも思えますが、意外に簡単です。
まず、リストボックスコントロールを作るところを、リストビューを
作るように変更します。このとき項目名(「ファイル名」「サイズ」「更新日時」)
も作っておきます。
また、リストビューからの通知メッセージはWM_NOTIFYの形でやってくるので この点も変更が必要です。
あとは、ListBox_*のマクロを探してListView_*に合うように適宜プログラムに 修正を加えます。さて、このときWIN32_FIND_DATA構造体からファイルの日時を 取得するにはどうすればよいのでしょうか。 第218章で示したようにWIN32_FIND_DATA構造体には ファイルに関連した日時を表す3つのメンバ(作成日時・アクセス日時・更新日時)がありました。 いずれもFILETIME構造体であらわされています。
ファイルタイムとは1601年1月1日からの0.1ミリ秒間隔の64ビット値です。typedef struct _FILETIME { // ft DWORD dwLowDateTime; DWORD dwHighDateTime; } FILETIME;
dwLowDateTimeは、ファイルタイムの下位32ビット値です。
dwHighDateTimeは、ファイルタイムの上位32ビット値です。
ファイルタイムを通常の日時に直すのはめんどうです。こういうのはたいてい 便利な関数とかマクロが用意されているはずです。
名前のとおりファイルタイムをシステムタイムに変換する関数です。BOOL FileTimeToSystemTime( CONST FILETIME *lpFileTime, LPSYSTEMTIME lpSystemTime );
lpFileTimeは変換するFILETIME構造体へのポインタです。
lpSystemTimeはシステムタイムを受け取るSYSTEMTIME構造体へのポインタです。
成功すると0以外を失敗すると0を返します。
世界標準時間(the Coordinated Universal Time (UTC))に基づくファイルタイムを ローカルファイルタイムに変換する関数です。BOOL FileTimeToLocalFileTime( CONST FILETIME *lpFileTime, LPFILETIME lpLocalFileTime );
lpFileTimeはUTCに基づくファイルタイムの入ったFILETIME構造体へのポインタです。
lpLocalFileTime変換結果が格納されるFILETIME構造体へのポインタです。
成功すると0以外が、失敗すると0が返されます。
さて、このくらいの予備知識があると日時付きのディレクトリ表示が可能です。
リソース・スクリプトは前章に比べ変更がありません。
コモンコントロールを取り扱うのでcommctrl.hをインクルードするのを忘れないで ください。その他の前準備(comctl32.libのリンク)も忘れないでください。// 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;//インターネットに接続しているかどうか
MakeMyList, InsertMyColumnという自作関数でリストビューをつくり列項目を 挿入します。
WinMain, InitApp, InitInstanceの各関数に変更はありません。
WM_CREATEが来たら、コモンコントロールを初期化します。//ウィンドウプロシージャ 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; }
MakeMyList, InsertMyColumn関数でリストビューを作ります。
さて、リストビューからの通知メッセージはWM_NOTIFYの形でやってくるので
書き換えが必要です。
ローカルのディレクトリを表示するリストビュー(hListL)からの
通知メッセージで、それがダブルクリックであれば、ListView_GetNextItem
マクロで選択されている項目のインデックスを取得します。
このマクロについてはすでに
第108章で解説しています。
さて、ダブルクリックをするのはカレントディレクトリを変更するときですから
選択されているのがファイルの時はその旨注意をして何もしません。
ディレクトリ名の時はカレントディレクトリを変更して、SetMyLocalDir関数を
呼んで表示しなおします。
FTPのディレクトリを表示するリストビュー(hList)からの通知メッセージで 、それがだぶるくりっくであるときも同じような処理をします。
MyConnect関数に変更はありません。
ListBox_GetCurSel, ListBox_GetTextのマクロを ListView_GetNextItem, ListView_GetItemTextに書き換えました。 ListView_GetItemTextマクロはすでに 第110章で解説しています。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; }
MyGetFNameProc, SetAccount, MyAccountProc, SetHost, MyFtpAddressProc の各関数に変更はありません。
FTPのカレントディレクトリをリストビューに表示する関数です。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; }
ListBox_ResetContentマクロがListView_DeleteAllItemsになりました。
リストビューからすべてのアイテムを削除します。成功したらTRUEを 失敗したらそれ以外を返します。BOOL ListView_DeleteAllItems( HWND hwnd );
WIN32_FIND_DATA構造体に取得したファイルのデータをListView_InsertItem, ListView_SetItemマクロでリストビューに表示します。 たいていのFTPソフトではFTPにあるファイルの日時をローカル時間に 変換しないでそのまま表示しているようです。したがって FileTimeToSystemTime関数でファイルタイムをそのままシステムタイムに 変換してリストビューに表示します。
ローカルのカレントディレクトリをリストビューに表示する関数です。 やっていることはGetAllFiles関数とほとんど同じです。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; }
WIN32_FIND_DATA構造体に取得したファイルタイムをそのまま使わずに FileTimeToLocalFileTime関数でローカルファイルタイムに変換してから 表示しています。
ChangeLocalDrive, MyDriveProc関数に変更はありません。
ListBox_GetCurSel, ListBox_GetTextマクロでローカルのファイル名を取得していたのを ListView_GetNextItem, ListView_GetItemTextマクロに書き換えました。あとは同じです。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; }
FTPのファイルを削除する関数です。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; }
これもListBox_GetCurSel, ListBox_GetTextマクロで削除するファイル名を 取得していたのをListView_GetNextItem, ListView_GetItemTextに書き直しただけです。
MyFtpCreatDir, MyCreateDirProc関数に変更はありません。
リストビューを作る関数です。新しいリストビューについては 第198章を参照してください。 ここでは、複数のアイテムが選択されてはまずいのでLVS_SINGLESELスタイルを 加えています。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; }
リストビューにカラムを挿入する関数です。特に説明は 不要でしょう。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; }
今回は今まで作ったプログラムのリストボックスの部分を リストビューに変更しただけです。やや面倒くさいところもありますが そんなに難しくはないですね。
このプログラムを動かしてまず、気の付くことは大変使いにくいことです。 それは、リストビューに表示されるファイル等が順不同だからです。 このへんを改良してみてください。
Update 15/Aug/1999 By Y.Kumei