⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dlapi.c

📁 C语言编程中算法数据结构中的树行代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************
*
*
* Notepad2
*
* Dlapi.c
*   Directory Listing APIs used in Notepad2
*
* See Readme.txt for more information about this source code.
* Please send me your comments to this work.
*
* See License.txt for details about distribution and modification.
*
*                                              (c) Florian Balmer 1996-2008
*                                                  florian.balmer@gmail.com
*                                               http://www.flos-freeware.ch
*
*
******************************************************************************/
#include <windows.h>
#include <commctrl.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <string.h>
#include "dlapi.h"



//==== Global LPMALLOC instance ===============================================
extern LPMALLOC g_lpMalloc;



//==== DirList ================================================================

//==== DLDATA Structure =======================================================

typedef struct tagDLDATA // dl
{

  HWND hwnd;                 // HWND of ListView Control
  UINT cbidl;                // Size of pidl
  LPITEMIDLIST  pidl;        // Directory Id
  LPSHELLFOLDER lpsf;        // IShellFolder Interface to pidl
  char szPath[MAX_PATH];     // Pathname to Directory Id
  int iDefIconFolder;        // Default Folder Icon
  int iDefIconFile;          // Default File Icon
  BOOL bNoFadeHidden;        // Flag passed from GetDispInfo()
  HANDLE hExitThread;        // Flag is set when Icon Thread should terminate
  HANDLE hTerminatedThread;  // Flag is set when Icon Thread has terminated

} DLDATA, *LPDLDATA;


//==== Property Name ==========================================================
static const char *pDirListProp = "DirListData";



//=============================================================================
//
//  DirList_Init()
//
//  Initializes the DLDATA structure and sets up the listview control
//
BOOL DirList_Init(HWND hwnd,LPCSTR pszHeader)
{

  HIMAGELIST hil;
  SHFILEINFO shfi;
  LV_COLUMN  lvc;

  // Allocate DirListData Property
  LPDLDATA lpdl = (LPVOID)GlobalAlloc(GPTR,sizeof(DLDATA));
  SetProp(hwnd,pDirListProp,(HANDLE)lpdl);

  // Setup dl
  lpdl->hwnd = hwnd;
  lpdl->cbidl = 0;
  lpdl->pidl = NULL;
  lpdl->lpsf = NULL;
  lstrcpy(lpdl->szPath,"");

  // Add Imagelists
  hil = (HIMAGELIST)SHGetFileInfo("C:\\",0,&shfi,sizeof(SHFILEINFO),
                    SHGFI_SMALLICON | SHGFI_SYSICONINDEX);

  ListView_SetImageList(hwnd,hil,LVSIL_SMALL);

  hil = (HIMAGELIST)SHGetFileInfo("C:\\",0,&shfi,sizeof(SHFILEINFO),
                    SHGFI_LARGEICON | SHGFI_SYSICONINDEX);

  ListView_SetImageList(hwnd,hil,LVSIL_NORMAL);

  // Initialize default icons - done in DirList_Fill()
  //SHGetFileInfo("Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
  //  SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  //lpdl->iDefIconFolder = shfi.iIcon;

  //SHGetFileInfo("Icon",FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
  //  SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  //lpdl->iDefIconFile = shfi.iIcon;

  lpdl->iDefIconFolder = 0;
  lpdl->iDefIconFile = 0;

  // Icon thread control
  lpdl->hExitThread = CreateEvent(NULL,TRUE,FALSE,NULL);
  lpdl->hTerminatedThread = CreateEvent(NULL,TRUE,TRUE,NULL);

  lvc;
  pszHeader;

  return TRUE;

}


//=============================================================================
//
//  DirList_Destroy()
//
//  Free memory used by dl structure
//
BOOL DirList_Destroy(HWND hwnd)
{

  //LPMALLOC lpMalloc;

  LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);

  // Release multithreading objects
  DirList_TerminateIconThread(hwnd);
  CloseHandle(lpdl->hExitThread);
  CloseHandle(lpdl->hTerminatedThread);

  //if (NOERROR == SHGetMalloc(&lpMalloc))
  //{

    if (lpdl->pidl)
      g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdl->pidl);

    //lpMalloc->lpVtbl->Release(lpMalloc);

    if (lpdl->lpsf)
      lpdl->lpsf->lpVtbl->Release(lpdl->lpsf);

  //}

  // Free DirListData Property
  RemoveProp(hwnd,pDirListProp);
  GlobalFree(lpdl);

  return FALSE;

}


//=============================================================================
//
//  DirList_StartIconThread()
//
//  Start thread to extract file icons in the background
//
BOOL DirList_StartIconThread(HWND hwnd)
{

  DWORD dwtid;
  LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);

  DirList_TerminateIconThread(hwnd);

  ResetEvent(lpdl->hExitThread);
  //ResetEvent(lpdl->hTerminatedThread);

  CreateThread(NULL,0,DirList_IconThread,(LPVOID)lpdl,0,&dwtid);

  return TRUE;

}


//=============================================================================
//
//  DirList_TerminateIconThread()
//
//  Terminate Icon Thread and reset multithreading control structures
//
BOOL DirList_TerminateIconThread(HWND hwnd)
{

  LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);

  SetEvent(lpdl->hExitThread);

  //WaitForSingleObject(lpdl->hTerminatedThread,INFINITE);
  while (WaitForSingleObject(lpdl->hTerminatedThread,0) != WAIT_OBJECT_0)
  {
    MSG msg;
    if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }

  ResetEvent(lpdl->hExitThread);
  SetEvent(lpdl->hTerminatedThread);

  return TRUE;

}


//=============================================================================
//
//  DirList_Fill()
//
//  Snapshots a directory and displays the items in the listview control
//
int DirList_Fill(HWND hwnd,LPCSTR lpszDir,DWORD grfFlags,LPCSTR lpszFileSpec,
                 BOOL bExcludeFilter,BOOL bNoFadeHidden,
                 int iSortFlags,BOOL fSortRev)
{

  WCHAR wszDir[MAX_PATH];

  //LPMALLOC lpMalloc = NULL;

  LPSHELLFOLDER lpsfDesktop = NULL;
  LPSHELLFOLDER lpsf = NULL;

  LPITEMIDLIST  pidl = NULL;
  LPITEMIDLIST  pidlEntry = NULL;

  LPENUMIDLIST  lpe = NULL;

  LV_ITEM       lvi;
  LPLV_ITEMDATA lplvid;

  ULONG chParsed = 0;
  ULONG dwAttributes = 0;

  DL_FILTER dlf;
  SHFILEINFO shfi;

  LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);

  // Initialize default icons
  SHGetFileInfo("Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
    SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  lpdl->iDefIconFolder = shfi.iIcon;

  SHGetFileInfo("Icon",FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
    SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  lpdl->iDefIconFile = shfi.iIcon;

  // First of all terminate running icon thread
  DirList_TerminateIconThread(hwnd);

  // A Directory is strongly required
  if (!lpszDir || !*lpszDir)
    return(-1);

  lstrcpy(lpdl->szPath,lpszDir);

  // Init ListView
  SendMessage(hwnd,WM_SETREDRAW,0,0);
  ListView_DeleteAllItems(hwnd);

  // Init Filter
  DirList_CreateFilter(&dlf,lpszFileSpec,bExcludeFilter);

  // Init lvi
  lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  lvi.iItem = 0;
  lvi.iSubItem = 0;
  lvi.pszText = LPSTR_TEXTCALLBACK;
  lvi.cchTextMax = MAX_PATH;
  lvi.iImage = I_IMAGECALLBACK;

  // Convert Directory to a UNICODE string
  MultiByteToWideChar(CP_ACP,
                      MB_PRECOMPOSED,
                      lpszDir,
                      -1,
                      wszDir,
                      MAX_PATH);


  // Get Shell's IMalloc Interface
  //if (NOERROR == SHGetMalloc(&lpMalloc))
  //{

    // Get Desktop Folder
    if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
    {

      // Convert wszDir into a pidl
      if (NOERROR == lpsfDesktop->lpVtbl->ParseDisplayName(
                                            lpsfDesktop,
                                            hwnd,
                                            NULL,
                                            wszDir,
                                            &chParsed,
                                            &pidl,
                                            &dwAttributes))

      {

        // Bind pidl to IShellFolder
        if (NOERROR == lpsfDesktop->lpVtbl->BindToObject(
                                              lpsfDesktop,
                                              pidl,
                                              NULL,
                                              &IID_IShellFolder,
                                              &lpsf))

        {

          // Create an Enumeration object for lpsf
          if (NOERROR == lpsf->lpVtbl->EnumObjects(
                                         lpsf,
                                         hwnd,
                                         grfFlags,
                                         &lpe))

          {

            // Enumerate the contents of lpsf
            while (NOERROR == lpe->lpVtbl->Next(
                                             lpe,
                                             1,
                                             &pidlEntry,
                                             NULL))

            {

              // Add found item to the List
              // Check if it's part of the Filesystem
              dwAttributes = SFGAO_FILESYSTEM | SFGAO_FOLDER;

              lpsf->lpVtbl->GetAttributesOf(
                              lpsf,
                              1,
                              &pidlEntry,
                              &dwAttributes);

              if (dwAttributes & SFGAO_FILESYSTEM)
              {

                // Check if item matches specified filter
                if (DirList_MatchFilter(lpsf,pidlEntry,&dlf))
                {

                  lplvid = g_lpMalloc->lpVtbl->Alloc(
                                                g_lpMalloc,
                                                sizeof(LV_ITEMDATA));

                  lplvid->pidl = pidlEntry;
                  lplvid->lpsf = lpsf;

                  lpsf->lpVtbl->AddRef(lpsf);

                  lvi.lParam = (LPARAM)lplvid;

                  // Setup default Icon - Folder or File
                  lvi.iImage = (dwAttributes & SFGAO_FOLDER) ?
                    lpdl->iDefIconFolder : lpdl->iDefIconFile;

                  ListView_InsertItem(hwnd,&lvi);

                  lvi.iItem++;

                }

              }

              //lpMalloc->lpVtbl->Free(lpMalloc,pidlEntry);

            } // IEnumIDList::Next()

            lpe->lpVtbl->Release(lpe);

          } // IShellFolder::EnumObjects()

        } // IShellFolder::BindToObject()

      } // IShellFolder::ParseDisplayName()

      lpsfDesktop->lpVtbl->Release(lpsfDesktop);

    } // SHGetDesktopFolder()

    if (lpdl->pidl)
      g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdl->pidl);

    if (lpdl->lpsf && lpdl->lpsf->lpVtbl)
      lpdl->lpsf->lpVtbl->Release(lpdl->lpsf);

    //lpMalloc->lpVtbl->Release(lpMalloc);

  //} // SHGetMalloc()

  // Set lpdl
  lpdl->cbidl = IL_GetSize(pidl);
  lpdl->pidl = pidl;
  lpdl->lpsf = lpsf;
  lpdl->bNoFadeHidden = bNoFadeHidden;

  // Set column width to fit window
  ListView_SetColumnWidth(hwnd,0,LVSCW_AUTOSIZE_USEHEADER);

  // Sort before display is updated
  DirList_Sort(hwnd,iSortFlags,fSortRev);

  // Redraw Listview
  SendMessage(hwnd,WM_SETREDRAW,1,0);

  // Return number of items in the control
  return (ListView_GetItemCount(hwnd));

}


//=============================================================================
//
//  DirList_IconThread()
//
//  Thread to extract file icons in the background
//
DWORD WINAPI DirList_IconThread(LPVOID lpParam)
{

  HWND hwnd;

  LPDLDATA lpdl;
  LV_ITEM lvi;
  LPLV_ITEMDATA lplvid;

  LPMALLOC lpMalloc;
  LPSHELLICON lpshi;

  int iItem = 0;
  int iMaxItem;

  lpdl = (LPDLDATA)lpParam;
  ResetEvent(lpdl->hTerminatedThread);

  // Exit immediately if DirList_Fill() hasn't been called
  if (!lpdl->lpsf) {
    SetEvent(lpdl->hTerminatedThread);
    ExitThread(0);
    return(0);
  }

  hwnd = lpdl->hwnd;
  iMaxItem = ListView_GetItemCount(hwnd);

  CoInitialize(NULL);
  SHGetMalloc(&lpMalloc);

  // Get IShellIcon
  lpdl->lpsf->lpVtbl->QueryInterface(lpdl->lpsf,&IID_IShellIcon,&lpshi);

  while (iItem < iMaxItem && WaitForSingleObject(lpdl->hExitThread,0) != WAIT_OBJECT_0) {

    lvi.iItem = iItem;
    lvi.mask  = LVIF_PARAM;
    if (ListView_GetItem(hwnd,&lvi)) {

      SHFILEINFO shfi;
      LPITEMIDLIST pidl;
      DWORD dwAttributes = SFGAO_LINK | SFGAO_SHARE;

      lplvid = (LPLV_ITEMDATA)lvi.lParam;

      lvi.mask = LVIF_IMAGE;

      if (!lpshi || NOERROR != lpshi->lpVtbl->GetIconOf(lpshi,lplvid->pidl,GIL_FORSHELL,&lvi.iImage))
      {
        pidl = IL_Create(lpMalloc,lpdl->pidl,lpdl->cbidl,lplvid->pidl,0);
        SHGetFileInfo((LPCSTR)pidl,0,&shfi,sizeof(SHFILEINFO),SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
        lpMalloc->lpVtbl->Free(lpMalloc,pidl);
        lvi.iImage = shfi.iIcon;
      }

      // It proved necessary to reset the state bits...
      lvi.stateMask = 0;
      lvi.state = 0;

      // Link and Share Overlay
      lplvid->lpsf->lpVtbl->GetAttributesOf(
                              lplvid->lpsf,
                              1,&lplvid->pidl,
                              &dwAttributes);

      if (dwAttributes & SFGAO_LINK)
      {
        lvi.mask |= LVIF_STATE;
        lvi.stateMask |= LVIS_OVERLAYMASK;
        lvi.state |= INDEXTOOVERLAYMASK(2);
      }

      if (dwAttributes & SFGAO_SHARE)
      {
        lvi.mask |= LVIF_STATE;
        lvi.stateMask |= LVIS_OVERLAYMASK;
        lvi.state |= INDEXTOOVERLAYMASK(1);
      }

      // Fade hidden/system files
      if (!lpdl->bNoFadeHidden)
      {
        WIN32_FIND_DATA fd;
        if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,lplvid->pidl,
                        SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA)))
        {
          if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
              (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
          {
            lvi.mask |= LVIF_STATE;
            lvi.stateMask |= LVIS_CUT;
            lvi.state |= LVIS_CUT;
          }
        }
      }
      //MessageBox(NULL,NULL,NULL,MB_ICONWARNING);
      lvi.iSubItem = 0;
      ListView_SetItem(hwnd,&lvi);
    }
    iItem++;
  }

  if (lpshi)
    lpshi->lpVtbl->Release(lpshi);

  lpMalloc->lpVtbl->Release(lpMalloc);
  CoUninitialize();

  SetEvent(lpdl->hTerminatedThread);
  ExitThread(0);
  return(0);

}


//=============================================================================
//
//  DirList_GetDispInfo()
//
//  Must be called in response to a WM_NOTIFY/LVN_GETDISPINFO message from
//  the listview control
//
BOOL DirList_GetDispInfo(HWND hwnd,LPARAM lParam,BOOL bNoFadeHidden)
{

  LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);

  LV_DISPINFO *lpdi = (LPVOID)lParam;

  LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lpdi->item.lParam;

  // SubItem 0 is handled only
  if (lpdi->item.iSubItem != 0)
    return FALSE;

  // Text
  if (lpdi->item.mask & LVIF_TEXT)
    IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_INFOLDER,
                      lpdi->item.pszText,lpdi->item.cchTextMax);

  // Image
  //if (lpdi->item.mask & LVIF_IMAGE)
  //{

  //  //LPMALLOC lpMalloc;
  //  SHFILEINFO shfi;
  //  LPITEMIDLIST pidl;
  //  DWORD dwAttributes = SFGAO_LINK | SFGAO_SHARE;

  //  //if (NOERROR == SHGetMalloc(&lpMalloc))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -