Coding Life

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

    一直想做个这样的小工具:指定某个/几个文件夹,并且指定文件后缀过滤(包括是否遍历子文件夹等),然后程序在一个列表控件上显示所有的结果(文件),还要有个编辑框供输入文件名(全部或部分,就像搜索引擎),在这个编辑框打字的同时立即根据所输入的关键字更新前面提到的列表控件的结果。这样的小工具若用VC来做恐怕比较繁琐,又要纠缠于界面设计和实现以及编译调试的各种琐细问题,如果用脚本来做可能会方便些。后来发现原来已经有人用 AHK 做了个 叫 nDroid (前身为320MPH)的类似工具,在 AutoHotkey 的论坛上找到它的代码运行了一下,感觉刷新有点延迟(但到它的作者的主页上找的新版本反应速度倒是还不错)。

    其实类似这样的工具还有更强大的,比如说那个搜索速度惊人的 Everything,但它主要是全盘搜索,虽然速度惊人但有点杀鸡用牛刀的味道了,而且它仅支持NTFS。

    如果想自己做一个看的话,首先得分析实现的可能性。由于文件遍历的结果可能非常多,在超过2K的情况下如果使用 Windows 标准的 listview 控件同时还要进行频繁的插入/删除(在搜索框的内容改变的时候)操作,更新速度必然不如人意,于是就得考虑用 virtual listview 来实现了。

    virtual listview(虚拟列表控件)主要用于显示庞大数据内容,于是就先试着用AHK写了一下看看它实现的效果,感觉 virtual listview 的刷新不是很好,等有时间再继续研究吧。

 

 

  #NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
  SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
  SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
 
  WM_NOTIFY               := 0x004E
  LVN_FIRST               := -100
 
  LVN_GETDISPINFOA        := (LVN_FIRST-50)
  LVN_GETDISPINFOW        := (LVN_FIRST-77)
  LVN_GETDISPINFO         := LVN_GETDISPINFOW ; For unicode version
 
  LVM_FIRST               := 0x1000
  LVM_SETITEMCOUNT        := (LVM_FIRST + 47)
 
  LVS_OWNERDATA           := 0x1000
 
  LPSTR_TEXTCALLBACKA     := -1
 
  sizeofNMHDR             := 12
  sizeofLVITEM            := 40
 
  LVSICF_NOINVALIDATEALL  := 0x00000001
 
  LVIF_TEXT               := 0x0001
  LVIF_IMAGE              := 0x0002
  LVIF_STATE              := 0x0008
 
  CP_ACP                  := 0           ; default to ANSI code page
 
  RtlFillMemory := DllCall("GetProcAddress", uint, DllCall("GetModuleHandle", str, "kernel32"), str, "RtlFillMemory")
 
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  g_nMatchCount           := 10
 
  VarSetCapacity(g_strText, 20, 0)
  DllCall("msvcrt\strcpy", str, g_strText, str, "Hello", "Cdecl Str")
 
  VarSetCapacity(g_unistrText, 50, 0)
 
  TransformMultiByteToWideChar(&g_strText, g_unistrText)
 
  VarSetCapacity(g_strText2, 20, 0)
  DllCall("msvcrt\strcpy", str, g_strText2, str, "World", "Cdecl Str")
 
  VarSetCapacity(g_unistrText2, 50, 0)
 
  TransformMultiByteToWideChar(&g_strText2, g_unistrText2)
 
 
  ; Create the ListView with two columns, Name and Size:
  Gui, Add, ListView, r20 w700 vMyListView Hwndg_hMyListView +%LVS_OWNERDATA%, Name|Size (KB)
 
  ListView_SetItemCount(g_hMyListView, g_nMatchCount)
 
  LV_ModifyCol(1, "Text")
  LV_ModifyCol(2, "Text")
 
  loop, %g_nMatchCount%
      LV_Add("", LPSTR_TEXTCALLBACKA, 123)
  
  OnMessage(WM_NOTIFY, "OnNotify")
  Gui, Show
 
  return
 
  GuiEscape:
  GuiClose:  ; Indicate that the script should exit automatically when the window is closed.
  ExitApp
  Return
 
- /*
  typedef struct tagNMHDR
  {
      HWND  hwndFrom;
      UINT  idFrom;
      UINT  code;         // NM_ code
  }   NMHDR;
 
   NMHDR *pnm
  */
  OnNotify(idCtrl, pnmh)
- {
      global g_hMyListView, LVN_GETDISPINFO
      hwndFrom := DecodeInteger( "uint4", pnmh, 0 )
      if ( hwndFrom == g_hMyListView )
-     {
          idFrom := DecodeInteger( "uint4", pnmh, 4)
          code := DecodeInteger( "uint4", pnmh, 8)
          nCode := code > 0x7FFFFFFF ? -(~code) - 1 : code
          ;TrayTip, OnNotify, idCtrl`t= %idCtrl%`nhwndFrom`t= %hwndFrom%`nidFrom`t=%idFrom%`ncode`t= %nCode%, 10, 1
          if ( nCode == LVN_GETDISPINFO )
-         {
              OnGetDispInfo(pnmh)
          }
      }
  }
 
- /*
  NMLVDISPINFO* pnmv
 
  typedef struct tagNMLVDISPINFO {
      NMHDR hdr;
      LVITEM item;
  } NMLVDISPINFO;
 
  typedef struct _LVITEM {
      UINT mask;     0
      int iItem;     4
      int iSubItem;  8
      UINT state;    12
      UINT stateMask; 16
      LPTSTR pszText; 20
      int cchTextMax; 24
      int iImage;     28
      LPARAM lParam;
  #if (_WIN32_IE >= 0x0300)
      int iIndent;
  #endif
  #if (_WIN32_WINNT >= 0x560)
      int iGroupId;
      UINT cColumns; // tile view columns
      PUINT puColumns;
  #endif
  #if (_WIN32_WINNT >= 0x0600)
      int* piColFmt;
      int iGroup;
  #endif
  } LVITEM, *LPLVITEM;
 
  */
  OnGetDispInfo(pnmv)
- {
      Critical
      ;TrayTip, OnGetDispInfo, yes!!!, 10, 1
      global sizeofNMHDR, LVIF_TEXT, LVIF_STATE, LVIF_IMAGE, g_nMatchCount, g_unistrText, g_unistrText2
      iItemOffset     := sizeofNMHDR + 4
      iItem           := DecodeInteger( "uint4", pnmv, iItemOffset)
     
      if (iItem < 0 || iItem > g_nMatchCount)
          return  ; requesting invalid item
     
      maskOffset      := sizeofNMHDR + 0
      mask            := DecodeInteger( "uint4", pnmv, maskOffset)
     
      if (mask & LVIF_TEXT)
-     {
          iSubItemOffset  := sizeofNMHDR + 8
          iSubItem        := DecodeInteger( "uint4", pnmv, iSubItemOffset)
         
          pszTextOffset   := sizeofNMHDR + 20
          pszText         := DecodeInteger( "uint4", pnmv, pszTextOffset)
         
          ;TrayTip, OnGetDispInfo, iItem = %iItem%`nmask = %mask%`niSubItem = %iSubItem%, 10, 1
         
          pg_strText := 0
          if (0 == iSubItem)
-         {
              pg_strText := &g_unistrText
          }
          Else
-         {
              pg_strText := &g_unistrText2
          }
          EncodeInteger( pg_strText, 4, pnmv, pszTextOffset )
      }
      if (mask & LVIF_STATE)
-     {
          stateOffset := sizeofNMHDR + 12
          EncodeInteger( 0, 4, pnmv, stateOffset )
      }
      if (mask & LVIF_IMAGE)
-     {
          iImageOffset := sizeofNMHDR + 28
          EncodeInteger( -1, 4, pnmv, iImageOffset )
      }
  }
 
  ListView_SetItemCount(hwndLV, cItems)
- {
      global LVM_SETITEMCOUNT, LVSICF_NOINVALIDATEALL
      SendMessage, LVM_SETITEMCOUNT, cItems, LVSICF_NOINVALIDATEALL, , ahk_id %hwndLV%
      return %ErrorLevel%
  }
 
  TransformWideCharToMultiByte(pWideChar, nWideCharNumber)
- {
      Global
      Local nRequiredSize := WideCharToMultiByte(CP_ACP, 0, pWideChar, nWideCharNumber, 0, 0, 0, 0)
      if(nRequiredSize > 0)
-     {
          Local pMultiByteBuffer
          VarSetCapacity( pMultiByteBuffer, nRequiredSize, 0 )
          Local nBytesWritten := WideCharToMultiByte(CP_ACP, 0, pWideChar, nWideCharNumber, &pMultiByteBuffer, nRequiredSize, 0, 0)
          return pMultiByteBuffer
      }
      return 0
  }
 
  TransformMultiByteToWideChar(pMultiByte, ByRef pWideCharBuffer)
- {
      Global
      Local nRequiredSize := MultiByteToWideChar(CP_ACP, 0, pMultiByte, -1, 0, 0)
      if(nRequiredSize > 0)
-     {
          VarSetCapacity( pWideCharBuffer, nRequiredSize<<1, 0 )
          Local nBytesWritten := MultiByteToWideChar(CP_ACP, 0, pMultiByte, -1, &pWideCharBuffer, nRequiredSize)
          return nBytesWritten
      }
      return -1
  }
 
  WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar)
- {
      return DllCall("WideCharToMultiByte", "UInt", CodePage, "UInt", dwFlags, "UInt", lpWideCharStr, "Int", cchWideChar, "UInt", lpMultiByteStr, "Int", cbMultiByte, "UInt", lpDefaultChar, "UInt", lpUsedDefaultChar)
  }
 
  MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar)
- {
      return DllCall("MultiByteToWideChar", "UInt", CodePage, "UInt", dwFlags, "UInt", lpMultiByteStr, "Int", cbMultiByte, "UInt", lpWideCharStr, "Int", cchWideChar)
  }
 
  DecodeInteger( p_type, p_address, p_offset, p_hex=true )
- {
    old_FormatInteger := A_FormatInteger
    ifEqual, p_hex, 1, SetFormat, Integer, hex
    else, SetFormat, Integer, dec
    StringRight, size, p_type, 1
    loop, %size%
        value += *( ( p_address+p_offset )+( A_Index-1 ) ) << ( 8*( A_Index-1 ) )
    if ( size <= 4 and InStr( p_type, "u" ) != 1 and *( p_address+p_offset+( size-1 ) ) & 0x80 )
        value := -( ( ~value+1 ) & ( ( 2**( 8*size ) )-1 ) )
    SetFormat, Integer, %old_FormatInteger%
    return, value
  }
 
  EncodeInteger( p_value, p_size, p_address, p_offset )
- {
      global RtlFillMemory
    loop, %p_size%
      DllCall( RtlFillMemory, "uint", p_address+p_offset+A_Index-1, "uint", 1, "uchar", p_value >> ( 8*( A_Index-1 ) ) )
  }

posted on 2010-05-09 21:18  yonken  阅读(2945)  评论(0编辑  收藏  举报