; ============================================================== ; 名称: ExifMove ; 用途: 把图片移动到拍照时间目录 ; -------------------------------------------------------------- ; 作者: tmplinshi ; AHK 版本: AHK_L ; 操作系统: >= WIN_XP ; ============================================================== #NoTrayIcon #NoEnv #SingleInstance Force SetWorkingDir %A_ScriptDir% SetBatchLines -1 ListLines Off gui_title := "ExifMove v1.90 by tmplinshi" arg1 = %1% ; ################################# ; 界面 ; ################################# ; Gui, +hwndhMainGui Gui, Color, White ; /////////////////////////////////// Gui, Font, s12 bold cFF8000 Gui, Add, GroupBox, w550 h80 vbox1, 源文件夹 Gui, Font Gui, Font, s12 Gui, Add, Edit, xp+10 yp+25 w420 Section h20 vdir_source gModify_destRoot, % GetDir(arg1) Gui, Add, Button, ys h20 gbtn_browseDir_source, ... Gui, Font Gui, Add, Button, ys h20 gOpenDir vOpen_dir_source, 打开 Gui, Font, s12 Gui, Add, Checkbox, xs vRecurse, 包括子文件夹 ; /////////////////////////////////// Gui_Add_Picture("move.png", "x210 Section w24 h24", "hImgArrow") Gui, Add, Radio, ys+5 gChangePic vIsCopyImg, 复制 Gui, Add, Radio, ys+5 gChangePic vIsMoveImg Checked, 移动 ; /////////////////////////////////// Gui, Font, s12 bold cFF8000 Gui, Add, GroupBox, xm w550 h140 vbox2 , 目标 Gui, Font Gui, Add, Text, xp+10 yp+25 Section c8AAAED, (如果目标根目录为空,则默认与源文件夹相同。) Gui, Font, s12 Gui, Add, Text, xs Section, 根目录: Gui, Add, Edit, ys w350 h20 vdir_destRoot, % GetDir(arg1) Gui, Add, Button, ys h20 gbtn_browseDir_Dest, ... Gui, Font Gui, Add, Button, ys h20 gOpenDir vOpen_dir_destRoot, 打开 Gui, Font, s12 Gui_Add_BoldText("xs Section cBlack", "输入") Gui, Add, Text, x+0, 或选择子目录: Gui, Add, ComboBox, x+5 w230 vdir_destSub gUpdateExample HwndHCB1, YYYYMMDD|YYYYMM_DD|YYYY|YYYYMM|YYYYMMDD|YYYY_MM|YYYY_MM_DD|YYYYMM-DD|YYYY-MM|YYYY-MM-DD|ExtYYYYMMDD||ExtYYYYMM_DD|ExtYYYY|ExtYYYYMM|ExtYYYYMMDD|ExtYYYY_MM|ExtYYYY_MM_DD|ExtYYYYMM-DD|ExtYYYY-MM|ExtYYYY-MM-DD Gui, Font ; Gui, Add, Text, ys+8 c8AAAED, 示例: Gui, Add, Text, x+5 hp 0x200 c8AAAED vExample_SubDir w155, % __UpdateExample("dir_destSub") Gui, Font, s12 Gui_Add_BoldText("xs Section cBlack", "输入") Gui, Add, Text, x+0, 或选择文件名: Gui, Add, ComboBox, x+5 w230 vdestName gUpdateExample HwndHCB2, YYYYMMDD_hhmm_FileName.Ext|YYYYMMDDhhmm_FileName.Ext|FileName.Ext||hhmm_FileName.Ext|FileName_YYYYMMDD_hhmm.Ext|FileName_YYYYMMDDhhmm.Ext|FileName.Ext|FileName_hhmm.Ext|FileName_YYYYMMDD.Ext|YYYYMMDD.Ext|YYYYMMDD_FileName.Ext Gui, Font ; Gui, Add, Text, ys+8 c8AAAED, 示例: Gui, Add, Text, x+5 hp 0x200 c8AAAED vExample_FileName w155, % __UpdateExample("destName") Gui, Font, s12 ; /////////////////////////////////// Gui, Font, s12 bold cFF8000 Gui, Add, GroupBox, xm w550 h197 vbox3, 筛选 Gui, Font Gui, Font, s12 Gui, Add, Checkbox, xp+10 yp+25 Section vEnable_DateRange gEnable_DateRange, 日期: Gui, Add, DateTime, ys w160 vdate_start Gui, Add, Text, ys vtxt_1, 到 Gui, Add, DateTime, ys w160 vdate_end, Gui, Add, Text, xs Section, 后缀: Gui, Add, Checkbox, ys vsearch_jpeg h20 Checked, jpeg Gui, Add, Checkbox, ys vsearch_jpg h20 Checked, jpg Gui, Add, Checkbox, ys vsearch_tif h20 Checked, tif Gui, Add, Checkbox, ys vsearch_png h20 gPrompt, png Gui, Add, Checkbox, ys vsearch_gif h20 gPrompt, gif Gui, Add, Checkbox, ys vsearch_bmp h20 gPrompt, bmp Gui, Add, Checkbox, ys vsearch_ico h20 gPrompt, ico GuiControlGet, search_jpeg, Pos Gui, Add, Checkbox, xs x%search_jpegX% vEnable_CustomExt gEnable_CustomExt, 自定义后缀: Gui, Add, Edit, xp+120 w330 h20 vCustomExt, mp4,mp3,avi,png,gif,bmp,ico,amr,wav,mov Gui, Add, Checkbox, xs Section vSearchNoExifFile, 包括无 Exif 文件 Gui, Font Gui, Add, Text, ys+3 xp+155 c8AAAED, (用修改日期代替拍照日期,对mp4,jpg等文件修改日期就是拍摄日期) ;但本程序使用函数可以更准确地获取系统中的拍摄日期 Gui, Font Gui, Font, s12 Gui, Add, Text, xs 0x10 w530 h1 ; 横线 Gui, Add, Text, xs 0x10 w530 h1 ; 横线 Gui, Add, Text, xs h27 0x200, 过滤:排除 Gui, Add, DropDownList, x+5 w60 vDX, 小于||大于 Gui, Add, Edit, x+5 w90 Center hp vMaxSize, Gui, Add, DropDownList, x+5 w50 vDW, KB||MB Gui, Add, Text, x+5 hp 0x200, 的文件 Gui, Font, s12 ; /////////////////////////////////// Gui, Add, Button, x120 yp+50 w150 Section h40 vbtn_start gbtn_start, 开始 Gui, Add, Button, xp+200 w150 h40 Disabled vbtn_stop gbtn_stop, 停止 ; /////////////////////////////////// Gui, Font Gui, Add, Progress, xm Section w490 h10 vMyProgress Hidden Gui, Add, Text, ys-2 w30 h10 vPercent Hidden, 100`% ; /////////////////////////////////// Gui, Add, StatusBar,, %A_Space% SB_SetParts(450) _dis_en("Enable_DateRange", "date_start txt_1 date_end") _dis_en("Enable_CustomExt", "CustomExt") ; ------------ 获取三个 GroupBox 的坐标 GuiControlGet, box1, Pos GuiControlGet, box2, Pos GuiControlGet, box3, Pos ; ------------ 创建透明遮罩窗口 Gui, Trans: +ToolWindow +LastFound +hwndhTrans -Caption +Owner1 Gui, Trans: Color, 00FF00 WinSet, Transparent, 50 WinSet, ExStyle, +0x20 ; 鼠标穿透 SetTimer, _CoverBox, 100 Gui, Show,, %gui_title% Return _CoverBox: CoverBox() Return Modify_destRoot: GuiControlGet, dir_source GuiControl,, dir_destRoot, %dir_source% Return Prompt: GuiControlGet, SearchNoExifFile if SearchNoExifFile Return GuiControlGet, IsChecked,, %A_GuiControl% if !IsChecked Return MsgBox2("是否勾选“包括无 Exif 文件”", "提示", 36) IfMsgBox, Yes GuiControl,, SearchNoExifFile, 1 Return OpenDir: GuiControlGet, dir_source SetWorkingDir %dir_source% GuiControlGet, TargetPath,, % SubStr(A_GuiControl, 6) TargetPath := Trim(TargetPath, " `t/") Run, %TargetPath%,, UseErrorLevel Return ChangePic: if !hBitmap_copy { hBitmap_copy := Create_copy_png() hBitmap_move := Create_move_png() } Gui, Submit, NoHide SendMessage, 0x172, 0x0, (IsCopyImg ? hBitmap_copy : hBitmap_move),, ahk_id %hImgArrow% Return UpdateExample: __UpdateExample(A_GuiControl) Return Enable_DateRange: _dis_en("Enable_DateRange", "date_start txt_1 date_end") Return Enable_CustomExt: _dis_en("Enable_CustomExt", "CustomExt") Goto, Prompt Return ; ################################# ; ... ; ################################# ; btn_browseDir_source: FileSelectFolder, Dir, *%A_Desktop%,, 选择源文件夹 if (Dir = "") Return GuiControl,, dir_source, % Dir GuiControl,, dir_destRoot, % Dir return btn_browseDir_dest: FileSelectFolder, Dir, *%A_Desktop%,, 选择目标根目录 if (Dir = "") Return GuiControl,, dir_destRoot, % Dir Return ; ################################# ; 停止 ; ################################# ; btn_stop: GuiControl, Disable, btn_stop IsStop := True Return stop_run: GuiControl, Enable, btn_start GuiControl, Disable, btn_stop GuiControl, Hide, MyProgress GuiControl, Hide, Percent GuiControl,, MyProgress GuiControl,, Percent SB_SetText("") SB_SetText("", 2) Return ; ################################# ; 开始 ; ################################# ; btn_start: Gui, Submit, NoHide ; ------------ 检查【原文件夹】 if (dir_source = "") { MsgBox2("请先设置原文件夹", "提示", 48) Return } If !FileExist(dir_source) { MsgBox2("原文件夹不存在,请重新设置", "提示", 48) Return } ; ------------ 检查【后缀】 ExtList := "jpeg|jpg|tif|png|gif|bmp|ico", SearchExt := "" Loop, Parse, ExtList, | if search_%A_LoopField% SearchExt .= A_LoopField "," if !( SearchExt := Trim(SearchExt, ",") ) { MsgBox2("请先勾选至少一个图片后缀", "提示", 48) Return } if Enable_CustomExt { CustomExt := RegExReplace(CustomExt, "[, t]+", ",") CustomExt := Trim(CustomExt, ",") SearchExt .= "," CustomExt } ; ------------ 判断“排除”设置 MaxSize := RegExReplace(MaxSize, "[^d.]") If (MaxSize != "") MaxSize := (DW = "KB") ? MaxSize * 1024 : MaxSize * 1024 * 1024 ; ------------ 确认操作 MsgBox2("确定要" (IsCopyImg ? "复制" : "移动") "吗?", "确认", 36) IfMsgBox, No Return ; ------------------------------------------------------------------------------------ GuiControl, Disabled, btn_start GuiControl, Enable, btn_stop IsStop := False SetWorkingDir %dir_source% ; ------------ 格式化“开始日期”和“结束日期” if Enable_DateRange { date_start := SubStr(date_start, 1, 8) date_end := SubStr(date_end, 1, 8) } ; ------------ 目标根目录 if (dir_destRoot = "") dir_destRoot := dir_source dir_destRoot := Trim(dir_destRoot, " `t/") SB_SetText("正在统计文件数量...") FileTotal := 0, FileList := "" Loop, %dir_source%*,, %Recurse% { if IsStop Goto, stop_run if A_LoopFileExt in %SearchExt% { If (MaxSize != "") { FileGetSize, size, %A_LoopFileFullPath% If (size > MaxSize && DX = "大于") || (size 0 ; 超过了最大日期 Continue } ; 获取原文件名 SplitPath, A_LoopField, SourceFileName,, SourceExt, SourceFileNameNoExt ; 替换字符 _SubDir_And_Filename := dir_destSub "" destName _SubDir_And_Filename := RegExReplace(_SubDir_And_Filename, "MM", a2) _SubDir_And_Filename := RegExReplace(_SubDir_And_Filename, "mm", a5 "00") StringReplace, _SubDir_And_Filename, _SubDir_And_Filename, YYYY, %a1%, All StringReplace, _SubDir_And_Filename, _SubDir_And_Filename, DD, %a3%, All StringReplace, _SubDir_And_Filename, _SubDir_And_Filename, hh, %a4%, All StringReplace, _SubDir_And_Filename, _SubDir_And_Filename, Filename, %SourceFileNameNoExt%, All StringReplace, _SubDir_And_Filename, _SubDir_And_Filename, Ext, %SourceExt%, All ; ------------ _destFile := dir_destRoot "" _SubDir_And_Filename ; 目标文件 SplitPath, _destFile,, _destDir ; 分解出目标文件夹名称 ; 创建目标文件夹 IfNotExist, %_destDir% FileCreateDir, %_destDir% ; 重命名重名文件 _destFile := CheckDupFile(_destFile) ; 复制/移动文件 if IsCopyImg FileCopy, %A_LoopField%, %_destFile%, 1 else FileMove, %A_LoopField%, %_destFile%, 1 SuccessCount ++ } CancelLoop: FileList := "" Str_CopyOrMove := IsCopyImg ? "复制" : "移动" MsgBox2("已" Str_CopyOrMove " " SuccessCount " 个文件", IsStop ? "处理结果" : "完毕") Goto, stop_run Return GuiDropFiles: Gui, Trans:Cancel if (ctrl = "box1") Control := "dir_source" else if (ctrl = "box2") Control := "dir_destRoot" else Return GuiControl,, %Control%, % GetDir(A_GuiEvent) ; 设置目标根目录 if (Control = "dir_source") { GuiControl,, dir_destRoot, % GetDir(A_GuiEvent) GuiControl, Enable, Open_dir_source GuiControl, Enable, Open_dir_destRoot } Else GuiControl, Enable, Open_dir_destRoot Return GuiClose: ExitApp ; ====================================== 以下是函数 ====================================== GetImgDate(FileName, dateType = "date_exif") ; date_exif=相片拍照日期, date_create=修改日期 { static objShell := ComObjCreate("Shell.Application") static date_exif := InStr(A_OSVersion, "WIN_7") ? 12 : 25 static date_create := InStr(A_OSVersion, "WIN_7") ? 3 : 3 ;win7或xp上使用创建日期是4:4 ,修改日期是:3:3 ;本来想用创建日期, 但是mp4等文件的修改日期就是拍摄日期,所以上面语句改为3:3 SplitPath, FileName, sFileName, sFileDir objFolder := objShell.Namespace(sFileDir . "") objFilename := objFolder.Parsename(sFileName) iValue := objFolder.GetDetailsOf(objFilename, %dateType%) Return iValue } Gui_Add_Picture(file, Options, hWnd) { global StringReplace, name, file, ., _, a Gui, Add, Picture, 0xE %Options% hWnd%hWnd% SendMessage, 0x172, 0x0, % ( Create_%name%() ), , % "ahk_id " %hWnd% } MsgBox2(Text, Title = "", Options = "") { gui, +OwnDialogs MsgBox, % Options, %Title%, %Text% } ; _dis_en("send_email", "_smtp _from _pwd _to", "gui2:") ; _dis_en(checkbox_var, control_list, gui_name = "") { control_list := RegExReplace(control_list, "s+", " ") control_list := Trim(control_list) GuiControlGet, checkbox_value, % gui_name, % checkbox_var action := checkbox_value ? "Enable" : "Disable" Loop, Parse, control_list, %A_Space% GuiControl, %gui_name%%action%, % A_LoopField } GetFullPathName( SPath ) { VarSetCapacity(lPath,260,0), DllCall("GetLongPathName", Str,SPath, Str,lPath, UInt,260 ) Return lPath } GetDir(InPath) { SplitPath, InPath,, OutDir, OutExtension if (OutExtension != "lnk") Return GetFullPathName( FileExist(InPath "") ? InPath : OutDir ) FileGetShortcut, %InPath%, OutTarget, OutDir Return GetFullPathName( (OutDir = "") ? RegExReplace(OutTarget, "\[^\]*$") : OutDir ) } __UpdateExample(ctrl) { GuiControlGet, ExampleStr,, %ctrl% StringReplace, ExampleStr, ExampleStr, YYYY, %A_YYYY% StringReplace, ExampleStr, ExampleStr, DD, %A_DD% StringReplace, ExampleStr, ExampleStr, hh, %A_Hour% ExampleStr := RegExReplace(ExampleStr, "MM", A_MM) ExampleStr := RegExReplace(ExampleStr, "mm", A_Min) ExmapleControl := (ctrl = "dir_destSub" ? "Example_SubDir" : "Example_FileName") GuiControl,, %ExmapleControl%, %ExampleStr% Return ExampleStr } Gui_Add_BoldText(Options="", Text="", NewFont="s12", OldFont="s12") { global Gui, Font Gui, Font, %NewFont% bold Gui, Add, Text, %Options%, %Text% Gui, Font Gui, Font, %OldFont% } CheckDupFile(fPath) { IfNotExist, % fPath Return fPath SplitPath, fPath, fName, fDir, fExt, fNameNoExt Loop IfNotExist, % fDir "" fNameNoExt " (" A_Index+1 ")." fExt Return fDir "" fNameNoExt " (" A_Index+1 ")." fExt } ; -------------- 覆盖鼠标下的控件 CoverBox() { global static pre_ctrl MouseGetPos, x, y, WinId If !( (A_Cursor = "Unknown") AND GetKeyState("LButton", "P") AND (WinId = hMainGui) ) Return else IfWinNotActive, ahk_id %hMainGui% WinActivate, ahk_id %hMainGui% if ( (x >= box1X && x = box1Y && y = box2X && x = box2Y && y http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257 hData := DllCall("Kernel32.dllGlobalAlloc", "UInt", 2, "UPtr", DecLen, "UPtr") pData := DllCall("Kernel32.dllGlobalLock", "Ptr", hData, "UPtr") DllCall("Kernel32.dllRtlMoveMemory", "Ptr", pData, "Ptr", &Dec, "UPtr", DecLen) DllCall("Kernel32.dllGlobalUnlock", "Ptr", hData) DllCall("Ole32.dllCreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream) hGdip := DllCall("Kernel32.dllLoadLibrary", "Str", "Gdiplus.dll", "UPtr") VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar") DllCall("Gdiplus.dllGdiplusStartup", "PtrP", pToken, "Ptr", &SI, "Ptr", 0) DllCall("Gdiplus.dllGdipCreateBitmapFromStream", "Ptr", pStream, "PtrP", pBitmap) DllCall("Gdiplus.dllGdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0) DllCall("Gdiplus.dllGdipDisposeImage", "Ptr", pBitmap) DllCall("Gdiplus.dllGdiplusShutdown", "Ptr", pToken) DllCall("Kernel32.dllFreeLibrary", "Ptr", hGdip) DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream) Return hBitmap } ; ################################################################################## ; # This #Include file was generated by Image2Include.ahk, you must not change it! # ; ################################################################################## Create_move_png(NewHandle := False) { Static hBitmap := 0 If (NewHandle) hBitmap := 0 If (hBitmap) Return hBitmap VarSetCapacity(B64, 1544 http://www.autohotkey.com/board/topic/21213-how-to-convert-image-data-jpegpnggif-to-hbitmap/?p=139257 hData := DllCall("Kernel32.dllGlobalAlloc", "UInt", 2, "UPtr", DecLen, "UPtr") pData := DllCall("Kernel32.dllGlobalLock", "Ptr", hData, "UPtr") DllCall("Kernel32.dllRtlMoveMemory", "Ptr", pData, "Ptr", &Dec, "UPtr", DecLen) DllCall("Kernel32.dllGlobalUnlock", "Ptr", hData) DllCall("Ole32.dllCreateStreamOnHGlobal", "Ptr", hData, "Int", True, "PtrP", pStream) hGdip := DllCall("Kernel32.dllLoadLibrary", "Str", "Gdiplus.dll", "UPtr") VarSetCapacity(SI, 16, 0), NumPut(1, SI, 0, "UChar") DllCall("Gdiplus.dllGdiplusStartup", "PtrP", pToken, "Ptr", &SI, "Ptr", 0) DllCall("Gdiplus.dllGdipCreateBitmapFromStream", "Ptr", pStream, "PtrP", pBitmap) DllCall("Gdiplus.dllGdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "PtrP", hBitmap, "UInt", 0) DllCall("Gdiplus.dllGdipDisposeImage", "Ptr", pBitmap) DllCall("Gdiplus.dllGdiplusShutdown", "Ptr", pToken) DllCall("Kernel32.dllFreeLibrary", "Ptr", hGdip) DllCall(NumGet(NumGet(pStream + 0, 0, "UPtr") + (A_PtrSize * 2), 0, "UPtr"), "Ptr", pStream) Return hBitmap }