实现方法:按下快捷键,弹出一个包含当前目录下所有文件夹的列表,输入几个字母就可以快速定位特定文件夹。
用途:下载控整理下载文件夹,或者有很多文献、电子书需要归类整理,甚至于整理桌面都可以用得到。
代码:
Code: Select all
; Script function: move file(s) to a folder under current dir
; the destination folder can be located with a few keystroks by real-time filtering
; AutoHotkey Version: 1.0.48.05
; Language: English
; Platform: Win8.1 64 bit
; Author: Valuex
; Note:this script is a modification version of YONKEN's work:
; 根据输入实时更新过滤文件列表
; http://www.cnblogs.com/yonken/archive/2010/05/10/Smart_Open_Files_Update_File_List_On_Pattern_Changed.html
; Use at your own risk.
;
#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.
SetBatchLines, -1 ; Never sleep
WM_NOTIFY := 0x004E
LVN_FIRST := -100
LVN_GETDISPINFOA := (LVN_FIRST-50) ; For ANSI version
LVN_GETDISPINFOW := (LVN_FIRST-77) ; For unicode version
LVN_GETDISPINFO := LVN_GETDISPINFOW
LVM_FIRST := 0x1000
LVM_SETITEMCOUNT := (LVM_FIRST + 47)
LVM_REDRAWITEMS := (LVM_FIRST + 21)
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
pRtlFillMemory := GetProcAddressInModule("RtlFillMemory")
pWideCharToMultiByte := GetProcAddressInModule("WideCharToMultiByte")
pMultiByteToWideChar := GetProcAddressInModule("MultiByteToWideChar")
pStrCpy := GetProcAddressInModule("strcpy", "msvcrt")
g_strAppName := "Smart Open File"
g_strVersion := "2010.5.10"
g_strTitle := g_strAppName A_Space g_strVersion
g_hMainWnd := 0
g_nFilesCount := 0
g_nMatchCount := 0
g_MatchIndices = -1
ColNum :=5
; Allow the user to maximize or drag-resize the window:
Gui +Resize +Owner ; +Owner avoids a taskbar button.
; Create some buttons:
;Gui, Add, Button, Default vBtnLoadFolder gButtonLoadFolder, &Load a folder
; Create the ListView with two columns, Name and Size:
Gui, Add, ListView, Grid xm r20 w700 vMyListView Hwndg_hMyListView +%LVS_OWNERDATA%, Name|In Folder|Modified|Size (KB)|Type
; Create an ImageList so that the ListView can display some icons:
ImageListID1 := IL_Create(10)
ImageListID2 := IL_Create(10, 10, true) ; A list of large icons to go with the small ones.
; Attach the ImageLists to the ListView so that it can later display the icons:
LV_SetImageList(ImageListID1)
LV_SetImageList(ImageListID2)
ListView_SetItemCount(g_hMyListView, g_nMatchCount)
Gui, Add, Button, Hidden Default, OK
Gui, Add, Text,vSourceFile , SourceFile:
Gui, Add, Edit, vEditSearchString gOnChangeSearchString
F1::
Gosub, lblGetSourcePath
MsgBox,, ,OK,0.01
Gosub, ButtonLoadFolder
LV_ModifyCol(1,250)
LV_ModifyCol(2,250)
LV_ModifyCol(3,50)
LV_ModifyCol(4,50)
LV_ModifyCol(5,50)
GuiControl, text, SourceFile ,% GetFileNameByPath(SourceFileArr1)
Gui, Show, , %g_strTitle% [0 of 0]
OnMessage(WM_NOTIFY, "OnNotify")
Gui, +LastFound
WinSet, ReDraw ; Invalidate the list-view
g_hMainWnd := WinExist()
return
GuiEscape:
;GuiClose: ; Indicate that the script should exit automatically when the window is closed.
Reload
Return
GuiSize: ; Expand or shrink the ListView in response to the user's resizing of the window.
if A_EventInfo = 1 ; The window has been minimized. No action needed.
return
; Otherwise, the window has been resized or maximized. Resize the ListView to match.
GuiControl, Move, MyListView, % "W" . (A_GuiWidth - 20) . " H" . (A_GuiHeight - 70)
GuiControl, Move, SourceFile, % "W" . (A_GuiWidth - 20) . " H" . (A_GuiHeight - 40)
GuiControl, Move, EditSearchString, % "W" . (A_GuiWidth - 20) . " Y" . (A_GuiHeight - 30)
return
ButtonOK:
Gosub, lblGetListViewInfo
IfExist, %FileDestDir%
Gosub, lblMoveFile
Reload
return
lblGetListViewInfo:
;get dest dir by combining cell1 and cell2 in focused row
GuiControlGet, FocusedControl, FocusV
;get content of cell 1 and cell 2
if FocusedControl <> MyListView
{
LV_GetText(RowText11, 1,1)
LV_GetText(RowText12, 1,2)
}
Else
{
FocusRow:=LV_GetNext(0, "Focused")
LV_GetText(RowText11, FocusRow,1)
LV_GetText(RowText12, FocusRow,2)
}
FileDestDir:=RowText12 . "\" . RowText11
Return
lblGetSourcePath:
; get path of current dir by copying under-cursor file(s)
Clipboard=
Send, ^C
ClipWait, 2
If(ErrorLevel)
{
MsgBox, , Alert, clip fail, 1
Reload
}
SourceFilePath=%Clipboard%
IfInString, SourceFilePath, `n ;selectec more than one file
{
StringSplit, SourceFileArr, SourceFilePath , `n, `r
SourceFileNum:=SourceFileArr0
}
Else
{
SourceFileNum:=1
SourceFileArr1:=SourceFilePath
}
SourceFileDir:=GetFileDirByPath(SourceFileArr1)
Return
GetFileDirByPath(FileFullPath)
{
StringGetPos, LastSlashPos, FileFullPath, \ ,R
StringLeft, FileDir, FileFullPath, LastSlashPos
return,FileDir
}
Return
GetFileNameByPath(FileFullPath)
{
StringGetPos, LastSlashPos, FileFullPath, \ ,R
StringRight, FileName, FileFullPath, strLen(FileFullPath)-LastSlashPos-1
return,FileName
}
Return
lblMoveFile:
loop, %SourceFileNum%
{
SourceFilePath:=SourceFileArr%A_Index%
FileMove, %SourceFilePath%, %FileDestDir%, 1
}
Return
lblGetActive_TC_Path:
ControlGetText, TC_Path_R, TPathPanel2, ahk_class TTOTAL_CMD
ControlGetText, TC_Path_L, TPathPanel1, ahk_class TTOTAL_CMD
Return
ButtonLoadFolder:
Folder:=SourceFileDir
g_nMatchCount := 0
WinSetTitle, , , %g_strTitle% [%g_nMatchCount% of %g_nFilesCount%]
GuiControl, Disable, BtnLoadFolder
SetTimer, FileLoadProgressTimer, 100
g_arrResult := ; Free the memory
g_nFilesCount := GenList(Folder, "g_arrResult")
Gosub, OnChangeSearchString
Gui +LastFound
GuiControl, Enable, BtnLoadFolder
SetTimer, FileLoadProgressTimer, Off
return
OnChangeSearchString:
GuiControl, -Redraw, MyListView ; Improve performance by disabling redrawing during load.
nMatchCount := g_nFilesCount
bNeedSetFocus := false
If (g_nFilesCount > 0)
{
GuiControlGet, strSearchPattern, , EditSearchString
strSearchPattern := RegExReplace(strSearchPattern, "S)[\s]+", "|") ; Replace multiple whitespaces with a single character
if(strSearchPattern = "" || strSearchPattern = "|")
{
; Nothing is entered, select the first one
g_MatchIndices = -1
bNeedSetFocus := true
}
Else
{
If ( SubStr(strSearchPattern, StrLen(strSearchPattern)) == "|")
strSearchPattern := SubStr(strSearchPattern, 1, StrLen(strSearchPattern)-1)
StringSplit, arrSearchPatterns, strSearchPattern, |
g_MatchIndices =
VarSetCapacity(g_MatchIndices, g_nFilesCount * 4)
nMatchCount := 0
Loop, %g_nFilesCount%
{
strName := g_arrResult%A_Index%_1
bMatch := true
Loop %arrSearchPatterns0%
{
if ( !IsMatch(strName, arrSearchPatterns%A_Index%) )
{
bMatch := false
Break
}
}
if (bMatch)
{
NumPut(A_Index, g_MatchIndices, nMatchCount * 4)
++nMatchCount
}
}
}
}
Else
{
g_MatchIndices = -1
}
g_nMatchCount := nMatchCount
ListView_SetItemCount(g_hMyListView, g_nMatchCount)
ListView_RedrawItems(g_hMyListView, 0, -1)
;ToolTip, Done searching %strSearchPattern%
LV_ModifyCol() ; Auto-size each column to fit its contents.
GuiControl, +Redraw, MyListView ; Re-enable redrawing (it was disabled above).
If (bNeedSetFocus)
{
GuiControl, Focus, SysListView321,
Send, {Home}
GuiControl, Focus, EditSearchString,
}
WinSetTitle, , , %g_strTitle% [%g_nMatchCount% of %g_nFilesCount%]
Return
IsMatch(ByRef strFileName, strSubPattern)
{
chChar1 := SubStr(strSubPattern, 1, 1)
chChar2 := SubStr(strSubPattern, 2, 1)
bIsExclude := chChar1 == "-" || chChar2 == "-"
strSubPattern := RegExReplace(strSubPattern, "S)^[-\\]+")
If (strSubPattern = "")
return true
bMatch := InStr(strFileName, strSubPattern)
if (bIsExclude)
bMatch := !bMatch
return bMatch
}
FileLoadProgressTimer:
Gui +LastFound
WinSetTitle, , , %g_strTitle% [%g_nMatchCount% of %g_nFilesCount%]
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
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)
{
global
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)
If (g_MatchIndices = -1)
nIndex := iItem + 1
else
nIndex := NumGet(g_MatchIndices, iItem * 4)
;ToolTip, Row %iItem% Index in list %nIndex%
pstrText := 0
iSubItem := iSubItem+1
Loop, %ColNum%
{
if (A_Index == iSubItem)
pstrText := &g_arrResult%nIndex%%A_Index%
}
EncodeInteger( pstrText, 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 )
}
}
GenList(ByRef strFolder, arrResultName, ByRef strExtInclude = "", ByRef strExtExclude = "", bRecursive = true)
{
global ; This is important for creating/accessing array
nTotalFiles := 0
nIndex := g_nFilesCount+1
; Check if the last character of the folder name is a backslash, which happens for root
; directories such as C:\. If it is, remove it to prevent a double-backslash later on.
StringRight, LastChar, strFolder, 1
if LastChar = \
StringTrimRight, strFolder, strFolder, 1 ; Remove the trailing backslash.
; Ensure the variable has enough capacity to hold the longest file path. This is done
; because ExtractAssociatedIconA() needs to be able to store a new filename in it.
;VarSetCapacity(Filename, 260)
sfi_size = 352
VarSetCapacity(sfi, sfi_size)
; Gather a list of file names from the folder
;Loop %strFolder%\*.*, 0, %bRecursive%
Loop, %strFolder%\*.*, 2 ; %bRecursive%
{
; Name|In Folder|Modified|Size (KB)|Type
FormatTime, FileTimeModified, %A_LoopFileTimeModified% LSys R D1 ;, MM/dd/yyyy HH:mm
EntryInfo1:=A_LoopFileName
EntryInfo2:=A_LoopFileDir
EntryInfo3:=FileTimeModified
EntryInfo4:=A_LoopFileSizeKB
EntryInfo5:=A_LoopFileExt
Loop, %ColNum%
ToWideChar(EntryInfo%A_Index%, %arrResultName%%nIndex%%A_Index%)
; We need this for pattern matching
%arrResultName%%nIndex%_1 := A_LoopFileName
++nIndex
++nTotalFiles
++g_nFilesCount
}
return nTotalFiles
}
#IfWinActive ahk_class AutoHotkeyGUI
~Up::
~+Up::
IfWinNotActive, ahk_id %g_hMainWnd%,
{
Send, {Up}
Return
}
GuiControl, Focus, SysListView321,
;ControlSend, SysListView321, {Up}, %g_hMainWnd%
Return
~Down::
~+Down::
IfWinNotActive, ahk_id %g_hMainWnd%,
{
Send, {Down}
Return
}
GuiControl, Focus, SysListView321,
;ControlSend, SysListView321, {Down}, %g_hMainWnd%
Return
#IfWinActive
;;;;;;;;;;;;;;;;;;; Helper Functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ListView_RedrawItems(hwndLV, iFirst, iLast)
{
global LVM_REDRAWITEMS
SendMessage, LVM_REDRAWITEMS, iFirst, iLast, , ahk_id %hwndLV%
return %ErrorLevel%
}
ListView_SetItemCount(hwndLV, cItems)
{
global LVM_SETITEMCOUNT, LVSICF_NOINVALIDATEALL
SendMessage, LVM_SETITEMCOUNT, cItems, LVSICF_NOINVALIDATEALL, , ahk_id %hwndLV%
return %ErrorLevel%
}
TransformWideCharToMultiByte(pWideChar, nWideCharNumber)
{
Global CP_ACP
nRequiredSize := WideCharToMultiByte(CP_ACP, 0, pWideChar, nWideCharNumber, 0, 0, 0, 0)
if(nRequiredSize > 0)
{
VarSetCapacity( pMultiByteBuffer, nRequiredSize, 0 )
nBytesWritten := WideCharToMultiByte(CP_ACP, 0, pWideChar, nWideCharNumber, &pMultiByteBuffer, nRequiredSize, 0, 0)
return pMultiByteBuffer
}
return 0
}
TransformMultiByteToWideChar(pMultiByte, ByRef pWideCharBuffer)
{
Global CP_ACP
nRequiredSize := MultiByteToWideChar(CP_ACP, 0, pMultiByte, -1, 0, 0)
if(nRequiredSize > 0)
{
VarSetCapacity( pWideCharBuffer, nRequiredSize<<1, 0 )
nBytesWritten := MultiByteToWideChar(CP_ACP, 0, pMultiByte, -1, &pWideCharBuffer, nRequiredSize)
return nBytesWritten
}
return -1
}
ToWideChar(strAnsiText, ByRef strUnicodeText)
{
nStrLen := StrLen(strAnsiText)
VarSetCapacity(strUnicodeText, (nStrLen+1)*2, 0)
TransformMultiByteToWideChar(&strAnsiText, strUnicodeText)
Return strUnicodeText
}
WideCharToMultiByte(CodePage, dwFlags, lpWideCharStr, cchWideChar, lpMultiByteStr, cbMultiByte, lpDefaultChar, lpUsedDefaultChar)
{
global pWideCharToMultiByte
return DllCall(pWideCharToMultiByte, "UInt", CodePage, "UInt", dwFlags, "UInt", lpWideCharStr, "Int", cchWideChar, "UInt",lpMultiByteStr, "Int", cbMultiByte, "UInt", lpDefaultChar, "UInt", lpUsedDefaultChar)
}
MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, lpWideCharStr, cchWideChar)
{
global pMultiByteToWideChar
return DllCall(pMultiByteToWideChar, "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 pRtlFillMemory
loop, %p_size%
DllCall( pRtlFillMemory, "uint", p_address+p_offset+A_Index-1, "uint", 1, "uchar", p_value >> ( 8*( A_Index-1 ) ) )
}
GetProcAddressInModule(strFuncName, strModuleName = "kernel32")
{
return DllCall("GetProcAddress", uint, DllCall("GetModuleHandle", str, strModuleName), str, strFuncName)
}