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); }