前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >显示文件和文件夹的关联图标和说明

显示文件和文件夹的关联图标和说明

作者头像
加菲猫的VFP
发布2023-08-21 17:26:49
1510
发布2023-08-21 17:26:49
举报
文章被收录于专栏:加菲猫的VFP加菲猫的VFP
代码语言:javascript
复制
PUBLIC oForm As Explorer
oForm = CREATEOBJECT("Explorer")
oForm.Visible=.T.
* end of main

DEFINE CLASS Explorer As Form
#DEFINE LVM_FIRST 0x1000
#DEFINE LVM_GETIMAGELIST (LVM_FIRST + 2)
#DEFINE LVM_SETIMAGELIST (LVM_FIRST + 3)
#DEFINE LVM_SETITEM (LVM_FIRST + 6)
#DEFINE LVIF_IMAGE 0x0002

#DEFINE LVSIL_SMALL 1
#DEFINE LVS_SHAREIMAGELISTS 0x0040
#DEFINE GWL_STYLE -16
#DEFINE MAX_PATH 260

#DEFINE SHGFI_SYSICONINDEX 0x000004000
#DEFINE SHGFI_SMALLICON 0x000000001
#DEFINE SHGFI_ICON 0x000000100
#DEFINE SHGFI_TYPENAME 0x000000400
#DEFINE SHGFI_USEFILEATTRIBUTES 0x000000010

#DEFINE FILE_ATTRIBUTE_NORMAL 0x00000080
#DEFINE FILE_ATTRIBUTE_DIRECTORY 0x00000010

  Width=560
  Height=370
  MaxButton=.F.
  BorderStyle=2
  AutoCenter=.T.
  Caption="File Explorer"
  ShowWindow=2

  ADD OBJECT lst As TListViewFiles WITH;
  Left=5, Top=35, Width=550, Height=310

  ADD OBJECT Label1 As Label WITH Autosize=.T.,;
  BackStyle=0, Left=7, Top=7, Caption="Address:"
  
  ADD OBJECT txtFolder As TextBox WITH;
  Left=64, Top=5, Width=466,;
  ControlSource="THIS.Parent.lst.defaultpath"

  ADD OBJECT cmdFolder As CommandButton WITH;
  Left=530, Top=4, Width=24, Height=24, Caption=".."

PROCEDURE Init
  = BINDEVENT(THIS.cmdFolder, "Click", THIS, "GetFolder")
  THIS.lst.populatelist

PROCEDURE GotFocus
  THIS.lst.SwitchToSystemList

PROCEDURE GetFolder
  LOCAL cStoredPath, cPath
  cStoredPath = SYS(5) + SYS(2003)
  cPath = GETDIR(THIS.lst.defaultpath,;
    "Folders:", "Select Folder")
  SET DEFAULT TO (m.cStoredPath)
  IF NOT EMPTY(m.cPath)
    THIS.lst.defaultpath = LOWER(m.cPath)
    THIS.Refresh
  ENDIF

ENDDEFINE

DEFINE CLASS TListViewFiles As OleControl
  OleClass="MSComctlLib.ListViewCtrl"
  defaultpath=JUSTPATH(_vfp.ServerName)

PROCEDURE Init
  THIS.declare
  WITH THIS
    .View=3
    .LabelEdit=1
    .AddColumnHeader("Name", 200)
    .AddColumnHeader("Size", 80)
    .AddColumnHeader("Type", 110)
    .AddColumnHeader("Date Modified", 130)
    
    LOCAL oMsgFont As SystemMessageFont
    oMsgFont=CREATEOBJECT("SystemMessageFont")
    .Font.Name=oMsgFont.lfFaceName &&"Segoe UI"
    .Font.Size=oMsgFont.GetFontSize()  &&9
  ENDWITH

PROCEDURE defaultpath_ASSIGN(cPath As String)
  cPath=LOWER(ALLTRIM(JUSTPATH(m.cPath)))
  IF RIGHT(m.cPath,1)="\" AND LEN(m.cPath) > 3
    cPath=SUBSTR(m.cPath,1,LEN(m.cPath)-1)
  ENDIF
  THIS.defaultpath=m.cPath
  THIS.PopulateList

PROCEDURE ColumnClick
LPARAMETERS columnheader
  THIS.PopulateList

PROCEDURE AddColumnHeader(cCaption, nWidth)
  WITH THIS.ColumnHeaders.Add()
    .Text=cCaption
    .Width=nWidth
  ENDWITH

PROCEDURE SwitchToSystemList
  LOCAL nWStyle, hSysImageList, nResult, cBuffer

  * check if the list is already assigned
  IF SendMessage(THIS.HWND, LVM_GETIMAGELIST,;
    LVSIL_SMALL, 0) <> 0
    RETURN
  ENDIF

  WITH THIS
    nWStyle = GetWindowLong(.HWND, GWL_STYLE)
    nWStyle = BITOR(m.nWStyle, LVS_SHAREIMAGELISTS)
    SetWindowLong(.HWND, GWL_STYLE, nWStyle)

    cBuffer = REPLICATE(CHR(0), 1024)
    hSysImageList = SHGetFileInfo("", FILE_ATTRIBUTE_NORMAL,;
      @cBuffer, LEN(cBuffer),;
      BITOR(SHGFI_SYSICONINDEX, SHGFI_SMALLICON,;
        SHGFI_ICON, SHGFI_TYPENAME,;
        SHGFI_USEFILEATTRIBUTES))

    = SendMessage(.HWND, LVM_SETIMAGELIST, LVSIL_SMALL, 0)
    = INKEY(0.1)
    = SendMessage(.HWND, LVM_SETIMAGELIST, LVSIL_SMALL, hSysImageList)

  ENDWITH

PROCEDURE PopulateList
* scans current directory and populates the ListView
  THIS.ListItems.Clear
  
  LOCAL nCount, nIndex

  nCount = ADIR(arrListOfFiles,;
    THIS.defaultpath + "\*.*", "D", 1)

  FOR nIndex=1 TO nCount
    IF arrListOfFiles[nIndex, 1] = "."
      LOOP
    ENDIF
    IF DIRECTORY(THIS.defaultpath + "\" +;
      arrListOfFiles[nIndex, 1])
      THIS.AddLstItem(@arrListOfFiles, nIndex, .T.)
    ENDIF
  NEXT

  nCount = ADIR(arrListOfFiles,;
    THIS.defaultpath + "\*.*", "A", 1)

  FOR nIndex=1 TO nCount
    IF NOT DIRECTORY(THIS.defaultpath + "\" +;
      arrListOfFiles[nIndex, 1])
      THIS.AddLstItem(@arrListOfFiles, nIndex, .F.)
    ENDIF
  NEXT
  RELEASE arrListOfFiles

PROCEDURE AddLstItem(arr, nIndex, lDirectory)
* adds new ListItem to the ListView control
  LOCAL cFilename, nTypeIndex, cFiletype, oItem

  cFilename = arr[nIndex, 1]
  nTypeIndex=0
  cFiletype=""
  
  THIS.GetFileTypeInfo(THIS.defaultpath+"\"+m.cFilename,;
    @nTypeIndex, @cFiletype,;
    IIF(lDirectory, FILE_ATTRIBUTE_DIRECTORY,;
      FILE_ATTRIBUTE_NORMAL))
  
  oItem = THIS.ListItems.Add(,,cFilename)
  THIS.SetIcon(oItem.Index, m.nTypeIndex)

  WITH oItem
    IF NOT lDirectory
      .Subitems(1) = THIS.FormatFilesize(arr[nIndex, 2])
    ENDIF
    .Subitems(2) = m.cFiletype
    .Subitems(3) = THIS.FormatDT(arr[nIndex, 3], arr[nIndex, 4])
  ENDWITH

PROCEDURE SetIcon(nItemIndex, nImageIndex)
* sets the icon for the specified ListItem
    LOCAL cItemBuffer  && LVITEM structure

    cItemBuffer = num2dword(LVIF_IMAGE) +;
      num2dword(nItemIndex-1) + num2dword(0) + num2dword(0) +;
      num2dword(0) + num2dword(0) + num2dword(0) +;
      num2dword(nImageIndex) + num2dword(0)

    = SendMessageS(THIS.hWnd , LVM_SETITEM, 0, @cItemBuffer)

FUNCTION FormatDT(dDate, cTime) As String
  LOCAL cResult
  cResult = DTOC(dDate) + " " + cTime
RETURN m.cResult

FUNCTION FormatFilesize(nSize) As String
  LOCAL cBuffer
  cBuffer = REPLICATE(CHR(0), 128)
  = StrFormatByteSizeA(m.nSize, @cBuffer, LEN(m.cBuffer))
RETURN STRTRAN(m.cBuffer, CHR(0), "")

PROCEDURE GetFileTypeInfo(cFilename, nTypeIndex,;
  cFileType, nFileAttr)
* obtains the icon and description associated
* with the specified file type
  LOCAL nBufsize, cBuffer, nFlags, hIcon, nTypeIndex

  nBufsize=0x200
  cBuffer = REPLICATE(CHR(0), nBufsize)

  nFlags = BITOR(SHGFI_SYSICONINDEX,;
    SHGFI_SMALLICON, SHGFI_ICON, SHGFI_TYPENAME,;
    SHGFI_USEFILEATTRIBUTES)

  = SHGetFileInfo(m.cFilename, m.nFileAttr,;
    @cBuffer, nBufsize, nFlags)
  
  hIcon = buf2dword(SUBSTR(cBuffer, 1, 4))
  nTypeIndex = buf2dword(SUBSTR(cBuffer,5, 4))
  cFileType = STRTRAN(SUBSTR(m.cBuffer,13+MAX_PATH), CHR(0),"")

  IF hIcon <> 0
    = DestroyIcon(hIcon)
  ENDIF

PROCEDURE declare
  DECLARE INTEGER DestroyIcon IN user32 INTEGER hIcon

  DECLARE STRING StrFormatByteSizeA IN Shlwapi;
    INTEGER dw, STRING @pszBuf, INTEGER cchBuf

  DECLARE INTEGER SHGetFileInfo IN shell32;
    STRING pszPath, LONG dwFileAttributes,;
    STRING @psfi, LONG cbFileInfo, LONG uFlags

  DECLARE INTEGER SendMessage IN user32;
    INTEGER hWindow, INTEGER Msg,;
    INTEGER wParam, INTEGER lParam

  DECLARE INTEGER SendMessage IN user32 AS SendMessageS;
    INTEGER hWindow, INTEGER Msg,;
    INTEGER wParam, STRING @lParam

  DECLARE INTEGER SetWindowLong IN user32;
    INTEGER hWindow, INTEGER nIndex, INTEGER dwNewLong

  DECLARE INTEGER GetWindowLong IN user32;
    INTEGER hWindow, INTEGER nIndex

  DECLARE INTEGER GetWindowDC IN user32 INTEGER hWindow

  DECLARE INTEGER SystemParametersInfo IN user32;
    INTEGER uiAction, INTEGER uiParam,;
    STRING @pvParam, INTEGER fWinIni

  DECLARE INTEGER GetDeviceCaps IN gdi32;
    INTEGER hdc, INTEGER nIndex

  DECLARE INTEGER ReleaseDC IN user32;
    INTEGER hWindow, INTEGER hDC

ENDDEFINE

DEFINE CLASS SystemMessageFont As Custom
#DEFINE SPI_GETNONCLIENTMETRICS 0x0029
#DEFINE NONCLIENTMETRICS_SIZE 0x0154
#DEFINE LOGFONT_SIZE 0x003c
#DEFINE LOGPIXELSY 0x005a
  lfHeight=12
  lfFaceName="Arial"

PROCEDURE Init
  LOCAL cNonClientMetrics, cBuffer
  cNonClientMetrics=num2dword(NONCLIENTMETRICS_SIZE)
  cNonClientMetrics=PADR(cNonClientMetrics,;
    NONCLIENTMETRICS_SIZE, CHR(0))

  IF SystemParametersInfo(SPI_GETNONCLIENTMETRICS,;
    NONCLIENTMETRICS_SIZE, @cNonClientMetrics, 0) <> 0
    cBuffer=SUBSTR(cNonClientMetrics, 281, LOGFONT_SIZE)
    WITH THIS
      .lfHeight=buf2dword(SUBSTR(cBuffer,1,4))
      .lfFaceName=STRTRAN(SUBSTR(cBuffer,29,32), CHR(0),"")
    ENDWITH
  ENDIF

FUNCTION GetFontSize() As Number
  LOCAL hWindow, hDC, nPxPerInchY
  hWindow=_screen.HWnd
  hDC=GetWindowDC(hWindow)
  nPxPerInchY = GetDeviceCaps(hDC, LOGPIXELSY)
  ReleaseDC(hWindow, hDC)
RETURN ROUND((ABS(THIS.lfHeight) * 72) / nPxPerInchY, 0)

ENDDEFINE

FUNCTION buf2dword(lcBuffer)
RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ;
  BitLShift(Asc(SUBSTR(lcBuffer, 2,1)),  8) +;
  BitLShift(Asc(SUBSTR(lcBuffer, 3,1)), 16) +;
  BitLShift(Asc(SUBSTR(lcBuffer, 4,1)), 24)

FUNCTION num2dword(lnValue)
#DEFINE m0 256
#DEFINE m1 65536
#DEFINE m2 16777216
  IF lnValue < 0
    lnValue = 0x100000000 + lnValue
  ENDIF
  LOCAL b0, b1, b2, b3
  b3 = Int(lnValue/m2)
  b2 = Int((lnValue - b3*m2)/m1)
  b1 = Int((lnValue - b3*m2 - b2*m1)/m0)
  b0 = Mod(lnValue, m0)
RETURN Chr(b0)+Chr(b1)+Chr(b2)+Chr(b3)  

每种文件类型的关联图标和说明存储在注册表中。

例如,若要获取 DBF 文件的这些关联,第一步是找到“HKEY_CLASSES_ROOT.dbf”注册表项。此项的默认值为“Visual.FoxPro.Table”。这意味着“HKEY_CLASSES_ROOT\Visual.FoxPro.Table”键必须位于下一个。

后者具有默认值“Microsoft Visual FoxPro Table”,这是操作系统坚持DBF文件类型的实际描述。

此项的“DefaultIcon”子项的值为“C:\Program Files\Microsoft Visual FoxPro 9\vfp9.exe,-103”。这意味着组图标 #103 资源存在于 VFP9 可执行文件中。

此资源包含操作系统在需要时用于表示视觉 FoxPro DBF 文件的几个图标;例如,在资源管理器窗口中显示文件列表时。

资源查看器显示此资源以及存储在 VFP9 可执行文件中的其他资源。

以类似的方式,任何其他文件类型(读取“文件扩展名”)都可以追溯到图标+描述对。

没有单一的规则,寻找关联的方法即使不是混乱,也是棘手的。走这条路需要相当广泛的编码。幸运的是,MS费心在SHGetFileInfo API调用中隐藏了该过程的复杂性。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-06-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 加菲猫的VFP 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档