CFileViewer(文件浏览器)

 1 #pragma once
 2 #include <afxwin.h>
 3 #include <afxtempl.h>
 4 
 5 class CFileViewer : public CWnd
 6 {
 7     DECLARE_MESSAGE_MAP()
 8     DECLARE_DYNAMIC(CFileViewer)
 9 public:
10     struct FileItem
11     {
12         int type;        //0为File 1为 directory
13         CString name;    //
14         CString path;    //代表当前D:Download的路径,不包括名称
15         HICON hIcon;
16     };
17     CFileViewer();
18     ~CFileViewer();
19     /**
20      * 创建一个控件使其初始化
21      * @param pParent 父窗口对象指针
22      * @param dwStyle 控件样式
23      * @param rect 控件区域
24      * @param nId 控件的ID
25      */
26     void Create(CWnd* parent, DWORD style, RECT rect, UINT nId);
27     LPCTSTR GetClassName() {
28         return _T("CFileViewer");
29     }
30     LPCTSTR GetWindowName() {
31         return _T("CFileViewer");
32     }
33     /**
34      * 列举指定目录的文件
35      * @param dir 要列举的文件目录
36      */
37     void ListFile(CString dir);
38     virtual void SetDefaultVisualStyle();
39 private:
40     void AddFileViewer(FileItem* item)
41     {
42         m_arrItem.Add(item);
43     }
44     HICON GetFileIcon(SHFILEINFO strFileIcon, const CString& path);
45     /**
46      * 控件改变大小的时候会触发
47      * @param nType 是垂直还是水平大小
48      * @param cx x方向的偏移
49      * @param cy y方向的偏移
50      */
51     afx_msg void OnSize(UINT nType, int cx, int cy);
52     /**
53      * 重新绘制的时候触发
54      */
55     afx_msg void OnPaint();
56     afx_msg void OnVScroll(UINT, UINT, CScrollBar*);
57     afx_msg BOOL OnMouseWheel(UINT, short, CPoint);
58     afx_msg BOOL OnEraseBkgnd(CDC* pDC);
59 
60     void RegisterCtrl();
61     void DrawItem(const FileItem* item, CDC* pDC);
62     void DrawText(CDC* pDC, CRect cr, CString str);
63     void GetPosition(CPoint& p);
64     void GetLayoutInfo();
65     static LRESULT WndProc(HWND, UINT, WPARAM, LPARAM);
66 protected:
67     CArray<FileItem*> m_arrItem;
68     int curX;    ///< 每个item获取完位置后的X偏移
69     int curY;    ///< 每个item获取完位置后的Y偏移
70     CSize itemSize;        ///< 每个item的大小
71     CRect m_ctrlPadding;    ///< ctrl的内间距
72     CRect m_itemPadding;    ///< item的内间距
73     CRect m_itemMargin;        ///< item之间的间距
74     CScrollBar m_scVertical;    ///< 垂直滚动条
75     int m_nVertScrollPos;///< 垂直滚动的位置
76     int m_nRow;        ///< item画出来需要多少行
77     int m_nCol;        ///< item画出来需要多少列
78     bool m_bNeedGetLayout;    ///< 是否需要重新计算布局 如果为true则需要 
79     bool m_bFileMode; ///<  是否是文件模式 ,如果为否则为文件夹模式 
80 };
#include "pch.h"
#include "CFileViewer.h"
#include <Gdiplus.h>

IMPLEMENT_DYNAMIC(CFileViewer, CWnd)
BEGIN_MESSAGE_MAP(CFileViewer, CWnd)
    ON_WM_PAINT()
    ON_WM_ERASEBKGND()
    ON_WM_SIZE()
    ON_WM_VSCROLL()
    ON_WM_MOUSEWHEEL()
END_MESSAGE_MAP()


CFileViewer::CFileViewer()
{
    WNDCLASS windowclass;
    HINSTANCE hInst = AfxGetInstanceHandle();
    if (!::GetClassInfo(hInst, this->GetClassName(), &windowclass))
    {
        RegisterCtrl();
    }
    m_bNeedGetLayout = false;
}

CFileViewer::~CFileViewer()
{
    for (int i = 0; i < m_arrItem.GetSize(); i++)
    {
        delete m_arrItem[i];
    }
}

void CFileViewer::Create(CWnd* pParent, DWORD dwStyle, RECT rect, UINT nId)
{
    WNDCLASS windowclass;
    HINSTANCE hInst = AfxGetInstanceHandle();

    if (!::GetClassInfo(hInst, this->GetClassName(), &windowclass))
    {
        RegisterCtrl();
    }
    CWnd::Create(GetClassName(), GetWindowName(), dwStyle, rect, pParent, nId);
    SetDefaultVisualStyle();
    rect.left = rect.right - 10;
    m_scVertical.Create(WS_CHILD | WS_CLIPCHILDREN | SBS_VERT, rect, this, AFX_IDW_VSCROLL_FIRST);
    m_scVertical.EnableScrollBar(ESB_ENABLE_BOTH);
    m_scVertical.SetScrollRange(0, 100, TRUE);
}
void CFileViewer::GetPosition(CPoint& p)
{
    //p点作为右上角的点
    //默许从左到右排序,然后依次换行
    CRect rectClient;
    GetClientRect(&rectClient);
    if (curX == 0)
        curX += m_ctrlPadding.left;
    else
        curX += m_itemMargin.right + itemSize.cx + m_itemMargin.left;
    if (curY == 0)
        curY += m_ctrlPadding.top;

    if (curX >= rectClient.Width() - m_ctrlPadding.right)
    {
        //超过范围 开始下一行
        curX = m_ctrlPadding.left;
        curY += m_itemMargin.bottom + m_itemMargin.top + itemSize.cy;
    }
    p.SetPoint(curX, curY);
}

void CFileViewer::GetLayoutInfo()
{
    if (m_bNeedGetLayout) return;
    CRect rectClient;
    GetClientRect(&rectClient);
    int size = m_arrItem.GetSize();
    //计算col列row行

    m_nCol = (rectClient.Width() - m_ctrlPadding.left - m_ctrlPadding.right) / (itemSize.cx + m_itemMargin.left + m_itemMargin.top);
    m_nRow = size / m_nCol + 1;
    double dbTotalHeight = m_nRow * (itemSize.cy + m_itemMargin.top + m_itemMargin.bottom)
        + m_ctrlPadding.top + m_ctrlPadding.bottom;
    float range = dbTotalHeight / (double)rectClient.Height() * 100.0;
    if (range > 100)
    {
        m_scVertical.ShowScrollBar();
        //set range
        m_scVertical.SetScrollRange(0, range);
    }
    m_bNeedGetLayout = true;
}

void CFileViewer::OnSize(UINT nType, int cx, int cy)
{
    //Invalidate();
}


void CFileViewer::ListFile(CString srcFile)
{
    m_arrItem.RemoveAll();
    //HICON hIcon = GetFileIcon(sfile, srcFile);
    //逐个列举文件夹内所有txt文件
    CString strFileName, strFileTemp, strSuffixTemp;
    CFileFind findFile;
    if (srcFile.Right(1) != '\')
        srcFile = srcFile += '\';
    else
    {
        srcFile.Right(1) = '\';
        srcFile = srcFile;
    }

    strFileTemp = srcFile + _T("*.*");
    int nIsFind = findFile.FindFile(strFileTemp);          //执行文件搜索

    while (nIsFind)
    {
        nIsFind = findFile.FindNextFile();          //查找下一个文件
        if (findFile.IsDirectory())           //若为目录,结束本次循环
            continue;
        strFileName = findFile.GetFileName();         //获取文件名称,包括后缀
        FileItem* fitem = new FileItem();
        SHFILEINFO sfile{ 0 };
        fitem->hIcon = GetFileIcon(sfile, srcFile + strFileName);
        fitem->name = strFileName;
        fitem->path = srcFile;
        //if (strFileName == ".." || strFileName == ".")
        //    continue;
        //strSuffixTemp = strFileName.Mid(strFileName.GetLength() - 3, 3);
        strFileName = srcFile + strFileName;
        AddFileViewer(fitem);
        //对文件进行后续处理
        Invalidate();
    }
}

HICON CFileViewer::GetFileIcon(SHFILEINFO stFileInfo, const CString& path)
{
    // 同时将 ENM_CHANGE 标志“或”运算到掩码中。
    ::SHGetFileInfo(path, 0, &stFileInfo, sizeof(stFileInfo), SHGFI_ICON);
    return stFileInfo.hIcon;
}

void CFileViewer::OnPaint()
{
    CClientDC client(this);

    //CDC& client = *GetDC();

    PAINTSTRUCT ps;
    this->BeginPaint(&ps);
    CRect rectClient;
    GetClientRect(&rectClient);
    //bufferMemBitmap.CreateCompatibleBitmap(&client, rectClient.Width(), rectClient.Height());

    //计算滚动
    int size = m_arrItem.GetSize();
    ////计算col列row行
    //int nCol = (rectClient.Width() - m_ctrlPadding.left - m_ctrlPadding.right) / (itemSize.cx + m_itemMargin.left + m_itemMargin.top);
    //int nRow = size / nCol + 1;
    //double dbTotalHeight = nRow * (itemSize.cy + m_itemMargin.top + m_itemMargin.bottom)
    //    + m_ctrlPadding.top + m_ctrlPadding.bottom;
    //float range = dbTotalHeight /(double) rectClient.Height() * 100.0;
    ////set range
    //m_scVertical.SetScrollRange(0,range);
    //重新计算布局,
    curX = 0;
    curY = 0;
    for (int i = 0; i < size; i++)
    {
        FileItem* fi = m_arrItem.GetAt(i);
        DrawItem(fi, &client);
    }

    /*client.BitBlt(rectClient.left, rectClient.top, rectClient.Width(), rectClient.Height(),
        &memDC, 0, 0, SRCCOPY);*/
        //bufferMemBitmap.DeleteObject();
        //memDC.DeleteDC();
    EndPaint(&ps);

    ::SwapBuffers(client.GetSafeHdc());
    /*LPITEMIDLIST pidl = NULL;
    int hr = SHGetFolderLocation(NULL, CSIDL_BITBUCKET, NULL, 0, &pidl);*/
    //SHFILEINFO    shfi = { 0 }; //文件信息结构变量用于存放函数调用的结果
    ////memset(&shfi, 0, sizeof(shfi));
    //DWORD dwError = GetLastError();
    //SHGetFileInfo(_T("E:\"), 0, &shfi, sizeof(SHFILEINFO), SHGFI_LARGEICON);
    ////SHGetFileInfo((LPCTSTR)pidl, -1, &shfi, sizeof(SHFILEINFO), SHGFI_ATTRIBUTES | SHGFI_TYPENAME);
    //dwError = GetLastError();
    //HICON hIcon = shfi.hIcon;
    //client.DrawIcon(200, 20, hIcon);
}

void CFileViewer::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* scroll)
{
    int TempPos = m_scVertical.GetScrollPos();
    //SCROLLINFO si;
    //GetScrollInfo(SB_HORZ, &si, SIF_ALL);
    //m_ImgVScrollPos = si.nPos;
    //dbHScroll = si.nPos;
    m_nVertScrollPos = nPos;
    GetLayoutInfo();
    //switch (nSBCode)
    //{
    //case SB_THUMBPOSITION://拖动滑块
    //    m_scVertical.SetScrollPos(nPos);
    //    break;
    //case SB_TOP://点击左边的箭头
    //    if (TempPos > 1)
    //    {
    //        TempPos--;
    //    }
    //    m_scVertical.SetScrollPos(TempPos);
    //    break;
    //case SB_BOTTOM://点击右边的箭头
    //    if (TempPos < 100)
    //    {
    //        TempPos++;
    //    }
    //    m_scVertical.SetScrollPos(TempPos);
    //    break;
    //}
    //m_scVertical.Invalidate();
    Invalidate(TRUE);

}

BOOL CFileViewer::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
    if (m_nVertScrollPos < 0)
    {
        m_nVertScrollPos = 0;
        return TRUE;
    }
    m_nVertScrollPos -= zDelta / 100.0;
    INT min, max;
    m_scVertical.GetScrollRange(&min, &max);
    m_scVertical.SetScrollPos(m_nVertScrollPos);
    GetLayoutInfo();
    CRect rectClient;
    GetWindowRect(&rectClient);
    rectClient.right -= 60;
    //InvalidateRect(&rectClient);
    Invalidate();
    //    m_scVertical.Invalidate();
    return TRUE;
}

BOOL CFileViewer::OnEraseBkgnd(CDC* pDC)
{
    CRect rect;
    GetClientRect(&rect);
    //rect.right -= 60;
    pDC->FillSolidRect(&rect, RGB(255, 255, 255));
    //pDC->FillSolidRect(0, 0, 320, 240, RGB(255,255,255));
    return TRUE;
}

void CFileViewer::SetDefaultVisualStyle()
{
    itemSize.SetSize(100, 80);
    m_itemPadding = { 1,1,1,1 };    //item内部
    m_itemMargin = { 2,2,2,2 };    //margin间距
    m_ctrlPadding = { 2,2,2,2 };    //控件内部padding
    //m_arrItem.SetSize(3);
}
void CFileViewer::RegisterCtrl()
{
    WNDCLASS w;
    memset(&w, 0, sizeof(WNDCLASS));   // start with NULL defaults
    w.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
    w.lpszClassName = GetClassName();
    w.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
    w.hIcon = NULL;//GetIcon(FALSE);
    w.hInstance = AfxGetInstanceHandle();
    w.lpszMenuName = NULL;//_T("Menu");
    w.cbClsExtra = w.cbWndExtra = 0;
    w.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);//::GetSysColor(COLOR_WINDOW);
    w.lpfnWndProc = (WNDPROC)AfxWndProc; //::DefWindowProc;//(WNDPROC)CGridCtrl::GridCtrlProc;
    if (!AfxRegisterClass(&w))
    {
        AfxThrowResourceException();
        return;
    }
}
void CFileViewer::DrawItem(const FileItem* item, CDC* pDC)
{
    CPoint p;
    GetPosition(p);
    p.y -= m_nVertScrollPos;

    //p.Offset(itemSize.cx / 2, itemSize.cy / 2);
    //pDC->Ellipse(p.x, p.y, p.x + itemSize.cx, p.y + itemSize.cy);
    pDC->Rectangle(p.x, p.y, p.x + itemSize.cx, p.y + itemSize.cy);
    CRect rect{ p.x, p.y, p.x + itemSize.cx, p.y + itemSize.cy };
    CBrush brush(RGB(125, 125, 125));
    pDC->FillRect(&rect, &brush);
    pDC->DrawIcon(p.x + 40, p.y + 10, item->hIcon);
    rect.DeflateRect(10, 50, 10, 10);
    //pDC->TextOut(p.x, p.y, item->name);
    //pDC->DrawText(item->name, rect,  ES_MULTILINE|  DT_TOP);
    DrawText(pDC, rect, item->name);


}

void CFileViewer::DrawText(CDC* pDC, CRect cr, CString text)
{
    CSize size;
    GetTextExtentPoint(pDC->GetSafeHdc(), text, text.GetLength(), &size);
    //BOOL B = this->SetCaretPos(nStartX, nStartY);
    int cx = cr.left;
    int cy = cr.top;
    CString cstr;
    for (int i = 0; i < text.GetLength(); i++)
    {
        cstr = text.GetAt(i);
        GetTextExtentPoint(pDC->GetSafeHdc(), cstr, 1, &size);
        //cr.SetRect(0, 0, size.cx, size.cy);

        if (cx >= cr.right)
        {
            cx = cr.left;
            cy += size.cy;
        }
        //cr.MoveToX(size.cx);
        //pDC->DrawText(cstr, &cr, DT_CENTER);
        pDC->TextOut(cx, cy, cstr);
        cx += size.cx;
    }

}

LRESULT CFileViewer::WndProc(HWND hWnd, UINT msgType, WPARAM wParam, LPARAM lParam)
{
    return AfxWndProc(hWnd, msgType, wParam, lParam);
}
原文地址:https://www.cnblogs.com/yang131/p/14372442.html