文件管理2

// FileControlExample.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "FileControlExample.h"
#include "FileControl.h"
#include <Commctrl.h>
#include <Shlobj.h> // 文件夹选择

#include <Uxtheme.h> // 扩展样式相关API
#pragma comment(lib,"UxTheme.lib")
#include <shlwapi.h> // 路径相关API
#pragma comment(lib,"shlwapi.lib")

typedef struct _TREE_ITEM 
{
    HTREEITEM hTreeItem;
    WCHAR     szFilePath[MAX_PATH];
}TREE_ITEM,*PTREE_ITEM;
typedef struct _LIST_ITEM 
{
    int   nItemIndex;
    WCHAR szFilePath[MAX_PATH];
}LIST_ITEM,*PLIST_ITEM;



#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst;                                // 当前实例
TCHAR szTitle[MAX_LOADSTRING];                    // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名


list<TREE_ITEM> g_lstTreeInfo;
list<LIST_ITEM> g_lstListInfo;

//HTREEITEM        g_hParent;


//TreeView_GetSelection

// 此代码模块中包含的函数的前向声明:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HTREEITEM AddItemToTree(HWND hTree, LPWSTR lpItemName, HTREEITEM hParent, BOOL bFolder);
BOOL      AddItemToList(HWND hWnd,FILE_INFO stcInfo, DWORD dwIndex);
VOID      UpdataControl(HWND hWnd, LPWSTR lpPath, HTREEITEM hParent);
VOID      DeleteTreeItemListNode(HTREEITEM hItem);
BOOL      SelectFolder(HWND hWnd, LPWSTR lpszFolder);

VOID      InitList(HWND hWnd);

VOID Tree_LButtonDown(HWND hWnd);
VOID List_RButtonDown(HWND hWnd);


int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPTSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    DialogBox(hInstance,LPTSTR(IDD_DIALOG),0,(DLGPROC)WndProc);

    return 0;
}



//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND    - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY    - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_INITDIALOG:{
        InitList(hWnd);
        break;}
    case WM_NOTIFY:
        {
            // 1. 判断是否为左键单击消息,并且消息消息来自树控件
            if (   NM_CLICK==((LPNMHDR)lParam)->code
                && IDC_TREE==((LPNMHDR)lParam)->idFrom )
            {
                Tree_LButtonDown(hWnd);
            }
            // 2. 判断是否为右键单击消息,并且消息消息来自列表框控件
            else if ( NM_RCLICK==((LPNMHDR)lParam)->code
                   && IDC_LIST==((LPNMHDR)lParam)->idFrom  )
            {
                List_RButtonDown(hWnd);
            }
            break;
        }
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // 分析菜单选择:
        switch (wmId)
        {
        case BTN_SELETE:
            WCHAR szPath[MAX_PATH];
            SelectFolder(hWnd, szPath);
            UpdataControl(hWnd, szPath, NULL);
            break;
        case ID__32771:
            {
                UINT nSeleteItem = ListView_GetSelectionMark(GetDlgItem(hWnd,IDC_LIST));
                for (list<LIST_ITEM>::iterator i=g_lstListInfo.begin(); 
                    i!=g_lstListInfo.end();
                    i++)
                {
                    if ( i->nItemIndex != nSeleteItem ) continue;
                    CFileControl obj;
                    obj.SetFileIsHidden(i->szFilePath);
                    break;
                }
                break;
            }
        case ID__32772:
            {
                UINT nSeleteItem = ListView_GetSelectionMark(GetDlgItem(hWnd,IDC_LIST));
                for (list<LIST_ITEM>::iterator i=g_lstListInfo.begin(); 
                    i!=g_lstListInfo.end();
                    i++)
                {
                    if ( i->nItemIndex != nSeleteItem ) continue;
                    CFileControl obj;
                    obj.SetFileIsOnlyRead(i->szFilePath);
                    break;
                }
                break;
            }
        case IDCANCEL:
            PostQuitMessage(0);
        default:
            return FALSE;
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: 在此添加任意绘图代码...
        EndPaint(hWnd, &ps);
        break;
    case WM_CLOSE: // 重点
        PostQuitMessage(0);
    default:
        return FALSE;
    }
    return TRUE;
}





HTREEITEM AddItemToTree(HWND hTree, LPWSTR lpItemName, HTREEITEM hParent, BOOL bFolder)
{
    TVITEM            tvi   = {0};    // 树节点项属性信息
    TVINSERTSTRUCT    tvins = {0};    // 树形控件的节点信息
    tvi.mask = TVIF_TEXT|TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_PARAM;
    tvi.pszText = lpItemName;
    tvi.cchTextMax = wcslen(lpItemName)+sizeof(TCHAR);
    if ( bFolder )
    {
        tvi.iImage = 1;
        tvi.iSelectedImage = 2;
        tvi.cChildren = I_CHILDRENCALLBACK;
    }
    else
    {
        tvi.iImage = 3;
        tvi.iSelectedImage = 3;
        tvi.cChildren = 0;
    }
    tvins.item = tvi;               // 插入点的属性信息
    tvins.hInsertAfter = TVI_SORT;    // 插入位置
    if ( NULL == hParent )          // 父节点的句柄
        tvins.hParent = TVI_ROOT;
    else
        tvins.hParent = hParent;
    return TreeView_InsertItem(hTree,&tvins);
}

VOID UpdataControl(HWND hWnd, LPWSTR lpPath, HTREEITEM hParent)
{
    HWND hTreeWnd = GetDlgItem(hWnd,IDC_TREE);

    // 1. 清空Tree的子节点
    if ( hParent )
    {
        // 1.1 获取其子节点,如果有的话则循环删除其子节点,否则跳过此步骤
        HTREEITEM hNext_A = TreeView_GetNextItem(hTreeWnd,hParent,TVGN_CHILD);
        if ( hNext_A )
        {
            // 1.1.1 获取其子节点的下一个节点
            HTREEITEM hNext_B = TreeView_GetNextItem(hTreeWnd,hNext_A,TVGN_NEXT);
            // 1.1.2 删除第一个子节点
            TreeView_DeleteItem(hTreeWnd,hNext_A);
            DeleteTreeItemListNode(hNext_A);
            // 1.1.3 将第二个节点hNext_B的句柄值赋值给第一个节点hNext_A
            hNext_A = hNext_B;
            // 1.1.4 如此往复删除剩余节点
            while ( hNext_B = TreeView_GetNextItem(hTreeWnd,hNext_A,TVGN_NEXT) )
            {
                TreeView_DeleteItem(hTreeWnd,hNext_A);
                DeleteTreeItemListNode(hNext_A);
                hNext_A = hNext_B;
            }
            // 1.1.5 删除最后一个节点
            if ( hNext_A )
            {
                TreeView_DeleteItem(hTreeWnd,hNext_A);
                DeleteTreeItemListNode(hNext_A);
            }
        }
    }
    
    // 2. 获取此目录下的所有文件列表,并清除列表框中的所有内容
    CFileControl objFile;
    list<FILE_INFO>  lstFileInfo;
    objFile.GetFileList(lpPath,lstFileInfo);
    ListView_DeleteAllItems(GetDlgItem(hWnd,IDC_LIST)); // 清空列表框
    g_lstListInfo.clear();                              // 情况列表框信息链表

    // 3. 将目录添加到Tree控件中
    DWORD dwIndex = 0;
    for (list<FILE_INFO>::iterator i=lstFileInfo.begin(); i!=lstFileInfo.end(); i++)
    {
        TREE_ITEM strTreeItem = {0};
        if ( i->bIsFolder )
        {
            // 3.1 将目录添加到Tree控件中,并将此节点信息加入链表
            strTreeItem.hTreeItem = AddItemToTree(hTreeWnd, i->szFilePath, hParent, TRUE);
            StringCbPrintf(strTreeItem.szFilePath, MAX_PATH, L"%s\\%s", lpPath, i->szFilePath);
            g_lstTreeInfo.push_back(strTreeItem);
            continue;
        }
        // 3.2 将文件添加到List控件中并将此节点信息加入链表
        AddItemToList(hWnd,*i,dwIndex);
        LIST_ITEM stcListItem = {0};
        stcListItem.nItemIndex = dwIndex;
        StringCbCopy(stcListItem.szFilePath,MAX_PATH,i->szFilePath);
        g_lstListInfo.push_back(stcListItem);
        dwIndex++;
    }

    lstFileInfo.clear();
}



VOID DeleteTreeItemListNode(HTREEITEM hItem)
{
    for ( list<TREE_ITEM>::iterator i = g_lstTreeInfo.begin();
        i != g_lstTreeInfo.end();
        i++)
    {
        if ( i->hTreeItem != hItem )  continue;
        g_lstTreeInfo.erase(i);
        break;
    }
}



BOOL AddItemToList(HWND hWnd,FILE_INFO stcInfo, DWORD dwIndex)
{
    HWND hListWnd = GetDlgItem(hWnd,IDC_LIST);

    LVITEM lvItem = {0};
    lvItem.mask    = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
    lvItem.state     = 0; // 子项的状态
    lvItem.stateMask = 0; // 状态有效的屏蔽位
    lvItem.iImage     = 0; // 与列表框关联的指定图像的索引值
    lvItem.iSubItem  = 0; // 子项的索引值(可以视为列号)

    WCHAR szInfo[64] = {0};
    lvItem.iItem    = dwIndex;
    lvItem.pszText  = PathFindFileName(stcInfo.szFilePath);
    lvItem.cchTextMax = wcslen(lvItem.pszText)+sizeof(TCHAR);
    ListView_InsertItem(hListWnd, &lvItem);

    wsprintf(szInfo,L"%I64d KB",stcInfo.qwFileSize/1024);
    ListView_SetItemText(hListWnd, lvItem.iItem, 1, szInfo);
    wsprintf(szInfo,L"%4d年%.2d月%#02d日,%.2d:%.2d:%.2d",
        stcInfo.stcCreatTime.wYear,
        stcInfo.stcCreatTime.wMonth,
        stcInfo.stcCreatTime.wDay,
        stcInfo.stcCreatTime.wHour,
        stcInfo.stcCreatTime.wMinute,
        stcInfo.stcCreatTime.wSecond);
    ListView_SetItemText(hListWnd, lvItem.iItem, 2, szInfo);
    wsprintf(szInfo,L"%4d年%.2d月%#02d日,%.2d:%.2d:%.2d",
        stcInfo.stcLastWriteTime.wYear,
        stcInfo.stcLastWriteTime.wMonth,
        stcInfo.stcLastWriteTime.wDay,
        stcInfo.stcLastWriteTime.wHour,
        stcInfo.stcLastWriteTime.wMinute,
        stcInfo.stcLastWriteTime.wSecond);
    ListView_SetItemText(hListWnd, lvItem.iItem, 3, szInfo);
    wsprintf(szInfo,L"%4d年%.2d月%#02d日,%.2d:%.2d:%.2d",
        stcInfo.stcLastAccessTime.wYear,
        stcInfo.stcLastAccessTime.wMonth,
        stcInfo.stcLastAccessTime.wDay,
        stcInfo.stcLastAccessTime.wHour,
        stcInfo.stcLastAccessTime.wMinute,
        stcInfo.stcLastAccessTime.wSecond);
    ListView_SetItemText(hListWnd, lvItem.iItem, 4, szInfo);

    return TRUE;
}





BOOL SelectFolder(HWND hWnd, LPWSTR lpszFolder)
{
    BROWSEINFO  bi = {0}; 
    ITEMIDLIST *pidl; 
    TCHAR       szPath[MAX_PATH];

    bi.hwndOwner      = hWnd; 
    bi.pszDisplayName = szPath; 
    bi.lpszTitle      = TEXT("Please select a folder"); 
    bi.ulFlags        = BIF_RETURNONLYFSDIRS; 

    if( pidl=SHBrowseForFolder(&bi) )
    {
        SHGetPathFromIDList( pidl, lpszFolder );
        return TRUE;
    }

    return FALSE;    
}






VOID InitList(HWND hWnd)
{
    // 1. 设置列表框样式为“可整行选择”、“有网格”
    ListView_SetExtendedListViewStyle( GetDlgItem(hWnd,IDC_LIST),
        LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_AUTOCHECKSELECT );

    // 2. 初始化列表框内容
    LVCOLUMN lvc = {0};
    lvc.mask   = LVCF_WIDTH|LVCF_TEXT;  // 列表框样式
    lvc.iImage = 1;                     // 与列表框关联的指定图像的索引值
    lvc.fmt    = LVCFMT_LEFT;            // 列的对齐方式

    lvc.pszText  = L"文件名";
    lvc.cx       = 128;
    lvc.iSubItem = 0;
    ListView_InsertColumn(GetDlgItem(hWnd,IDC_LIST), lvc.iSubItem, &lvc);
    lvc.pszText  = L"文件大小";
    lvc.cx       = 88;
    lvc.iSubItem = 1;
    ListView_InsertColumn(GetDlgItem(hWnd,IDC_LIST), lvc.iSubItem, &lvc);
    lvc.pszText  = L"创建时间";
    lvc.cx       = 88;
    lvc.iSubItem = 2;
    ListView_InsertColumn(GetDlgItem(hWnd,IDC_LIST), lvc.iSubItem, &lvc);
    lvc.pszText  = L"修改时间";
    lvc.cx       = 88;
    lvc.iSubItem = 3;
    ListView_InsertColumn(GetDlgItem(hWnd,IDC_LIST), lvc.iSubItem, &lvc);
    lvc.pszText  = L"访问时间";
    lvc.cx       = 88;
    lvc.iSubItem = 4;
    ListView_InsertColumn(GetDlgItem(hWnd,IDC_LIST), lvc.iSubItem, &lvc);

}




VOID Tree_LButtonDown(HWND hWnd)
{
    // 1. 初始化必要的信息
    POINT stcPoint = {0};                       // 发生此消息时的鼠标坐标
    HWND  hTreeWnd = GetDlgItem(hWnd,IDC_TREE); // 树形控件HEND
    GetCursorPos(&stcPoint);

    // 2. 将鼠标位置转换为相对坐标
    HTREEITEM     hTreeItem;
    TVHITTESTINFO thti;
    ScreenToClient(hTreeWnd,&stcPoint);
    thti.pt    = stcPoint;
    thti.flags = LVHT_EX_GROUP_BACKGROUND;

    // 3. 如果选中的列表框中的某一项,则更新树控件内容
    if ( hTreeItem  = TreeView_HitTest(hTreeWnd,&thti) )
    {
        for ( list<TREE_ITEM>::iterator i = g_lstTreeInfo.begin();
            i != g_lstTreeInfo.end();
            i++)
        {
            if ( i->hTreeItem != hTreeItem )
                continue;
            UpdataControl(hWnd,i->szFilePath,hTreeItem);
            break;
        }
    }
}




VOID List_RButtonDown(HWND hWnd)
{
    POINT stcPoint = {0};                       // 发生此消息时的鼠标坐标
    HWND  hListWnd = GetDlgItem(hWnd,IDC_LIST); // 列表框的HWND

    // 1. 将鼠标位置转换为相对坐标,然后测试是否选中的列表框中的某一项
    int           nListItemIndex;
    LVHITTESTINFO thti;
    GetCursorPos(&stcPoint);

    // 2. 判断是否点击了列表项的头结点
    ScreenToClient(hListWnd,&stcPoint);
    thti.pt        = stcPoint;
    thti.flags     = LVHT_EX_GROUP_HEADER;
    nListItemIndex = ListView_HitTestEx(hListWnd,&thti);
    if ( -1 != nListItemIndex )
    {
        // 2.1 加载菜单资源
        HMENU hMenu  = LoadMenu(NULL, MAKEINTRESOURCE(IDR_MENU1));
        HMENU hPopup = GetSubMenu(hMenu, 0);
        if ( !hMenu || !hPopup )  return;
        // 2.2 将相对坐标转换为原鼠标位置
        ClientToScreen(hListWnd,&stcPoint);
        // 2.3 弹出菜单
        TrackPopupMenuEx(hPopup, TPM_LEFTALIGN|TPM_RIGHTBUTTON, stcPoint.x, stcPoint.y, hWnd, NULL); 
        // 2.4 释放相关资源
        DestroyMenu(hMenu);
    }
}

 

posted @ 2016-03-16 15:46  天还是那么蓝  阅读(241)  评论(0编辑  收藏  举报