所需依赖库下载:

#NoEnv
#SingleInstance Force
SetBatchLines, -1
#Include <Gdip_All>
Gui, Add, ListView, Grid AltSubmit x10 y10 r20 w330 h400 vMyListView g列表被点击 hwndHLV, 文件名|拍摄日期| 💬
LV_ModifyCol(1, 150)
LV_ModifyCol(2, 130)
LV_ModifyCol(3, 30)
SetHeaderItemCheckBox(hLV, 1)
gui, font, s9, 微软雅黑
gui, Add, Text, x13 y+2 w150 v项目信息
gui, Add, Text, x280 y+-16 w200 v修改信息
gui, font, s12, 微软雅黑
gui, Add, text, x355 y10 w180 vname
gui, Add, Pic, y+10 vPic g打开图片
gui, font, s9, 微软雅黑
gui, Add, text, x+0 y165 , 拍摄日期:
gui, Add, text, y+5 , 创建日期:
gui, Add, text, y+5 , 修改日期:
gui, Add, text, c002b55 x420 y165 w130 v拍摄日期
gui, Add, text, c002b55 y+5 w130 v创建日期
gui, Add, text, c002b55 y+5 w130 v修改日期
gui, Add, Radio, Checked0 x355 y260 v指定时间单选 g单选按钮被点击, 指定日期:
gui, Add, DateTime, y+5 w180 v指定时间
gui, Add, Radio, Checked0 y+5 v匹配文件名单选 g单选按钮被点击, 匹配文件名:
gui, Add, Edit, y+5 w180 v匹配文件名编辑框
Gui, Add, Button, x355 y387 w50 g加载按钮被点击, 打 开
Gui, Add, Button, x+14 w50 +Disabled v移除按钮 g移除按钮被点击, 移 除
Gui, Add, Button, x+14 w50 +Disabled v修改按钮 g修改按钮被点击, 修 改
ImageListID1 := IL_Create(10) ; 创建图像列表, 这样 ListView 才可以显示图标:
LV_SetImageList(ImageListID1) ; 关联图像列表到 ListView, 然而它就可以显示图标了:
Gui, Show, , 相片拍摄时间修改
Folder := "D:\picture"
Gosub, 加载文件
return
加载按钮被点击:
Gui +OwnDialogs ; 强制用户解除此对话框后才可以操作主窗口.
FileSelectFolder, Folder,, 4, 选择要加载的目录
if not Folder ; 用户取消了对话框.
return
Else
{
LV_Delete()
Gosub, 加载文件
}
Return
加载文件:
global 加载文件 := 1
GDIPToken := Gdip_Startup()
; 检查文件夹名称的最后一个字符是否为反斜杠, 对于根目录则会如此,
; 例如 C:\. 如果是, 则移除这个反斜杠以避免之后出现两个反斜杠.
LastChar := SubStr(Folder, 0)
if (LastChar = "\")
Folder := SubStr(Folder, 1, -1) ; 移除尾随的反斜杠.
; 计算 SHFILEINFO 结构需要的缓存大小.
sfi_size := A_PtrSize + 8 + (A_IsUnicode ? 680 : 340)
VarSetCapacity(sfi, sfi_size)
; 获取所选择文件夹中的文件名列表并添加到 ListView:
Loop Files, %Folder%\*.*
{
; 建立唯一的扩展 ID 以避免变量名中的非法字符,
; 例如破折号. 这种使用唯一 ID 的方法也会执行地更好,
; 因为在数组中查找项目不需要进行搜索循环.
SplitPath, A_LoopFileFullPath,, Dir, FileExt ; 获取文件扩展名.
If A_LoopFileExt In bmp,jpg,png,tif
{
ExtID := 0 ; 进行初始化来处理比其他更短的扩展名.
Loop 7 ; 限制扩展名为 7 个字符, 这样之后计算的结果才能存放到 64 位值.
{
ExtChar := SubStr(FileExt, A_Index, 1)
if not ExtChar ; 没有更多字符了.
break
; 把每个字符与不同的位置进行运算来得到唯一 ID:
ExtID := ExtID | (Asc(ExtChar) << (8 * (A_Index - 1)))
}
; 检查此文件扩展名的图标是否已经在图像列表中. 如果是,
; 可以避免多次调用并极大提高性能,
; 尤其对于包含数以百计文件的文件夹而言:
IconNumber := IconArray%ExtID%
if not IconNumber ; 此扩展名还没有相应的图标, 所以进行加载.
{
; 获取与此文件扩展名关联的高质量小图标:
if not DllCall("Shell32\SHGetFileInfo" . (A_IsUnicode ? "W":"A"), "Str", A_LoopFileFullPath
, "UInt", 0, "Ptr", &sfi, "UInt", sfi_size, "UInt", 0x101) ; 0x101 为 SHGFI_ICON+SHGFI_SMALLICON
IconNumber := 9999999 ; 把它设置到范围外来显示空图标.
else ; 成功加载图标.
{
; 从结构中提取 hIcon 成员:
hIcon := NumGet(sfi, 0)
; 直接添加 HICON 到小图标和大图标列表.
; 下面加上 1 来把返回的索引从基于零转换到基于一:
IconNumber := DllCall("ImageList_ReplaceIcon", "Ptr", ImageListID1, "Int", -1, "Ptr", hIcon) + 1
DllCall("DestroyIcon", "Ptr", hIcon)
; 缓存图标来节省内存并提升加载性能:
IconArray%ExtID% := IconNumber
}
}
GDIPImage := Gdip_LoadImageFromFile(A_LoopFileLongPath)
PropItem := Gdip_GetPropertyItem(GDIPImage, 0x9003) ; ExifDTOrig - Date & time of original
Gdip_DisposeImage(GDIPImage)
Datetime := PropItem.Value
; 在 ListView 中创建新行并把它和上面的图标编号进行关联:
LV_Add("Icon" . IconNumber, A_LoopFileName, Datetime)
if (A_Index = 1)
显示图像(A_LoopFileName, A_LoopFileLongPath, datetime)
GuiControl,Text, 项目信息, % LV_GetCount() . " 个图像"
}
}
Gdip_Shutdown(GDIPToken)
加载文件 := 0
return
移除按钮被点击:
GuiControl, -Redraw, MyListView
起始行 := 0
RowNumber := 0 ; 这会使得首次循环从顶部开始搜索.
Loop
{
RowNumber := LV_GetNext(RowNumber - 1)
if !起始行
起始行 := RowNumber
if not RowNumber ; 上面返回零, 所以没有更多选择的行了.
break
LV_Delete(RowNumber) ; 从 ListView 中删除行.
}
起始行 := (起始行 > 1) ? 起始行-1 : 起始行
LV_GetText(FileName, 起始行, 1) ; 从首个字段中获取文本.
LV_GetText(Datetime, 起始行, 2)
Filepath := Dir "\" FileName
显示图像(FileName, FilePath, datetime)
GuiControl, +Redraw, MyListView
Return
单选按钮被点击:
if (A_GuiControl = "匹配文件名单选")
{
GuiControl,, 指定时间单选 , 0
GuiControl,, 匹配文件名单选 , 1
global 拍摄时间来源 := "匹配文件"
GuiControl, Enable, 修改按钮
tooltip % 拍摄时间
}
Else
{
GuiControl,, 指定时间单选 , 1
GuiControl,, 匹配文件名单选 , 0
global 拍摄时间来源 := "指定时间"
GuiControl, Enable, 修改按钮
}
Gui, Submit, NoHide
Return
修改按钮被点击:
GuiControl, -Redraw, MyListView
Loop % LV_GetCount()
LV_Modify(A_Index,,,, "")
GuiControl, +Redraw, MyListView
Gui, Submit, NoHide
GDIPToken := Gdip_Startup()
拍摄时间 := ""
global 修改数组 := {}
RowNumber := 0 ; 这样使得首次循环从列表的顶部开始搜索.
Loop
{
RowNumber := LV_GetNext(RowNumber) ; 在前一次找到的位置后继续搜索.
if not RowNumber ; 上面返回零, 所以选择的行已经都找到了.
break
LV_GetText(FileName, RowNumber, 1) ; 从首个字段中获取文本.
LV_GetText(Datetime, RowNumber, 2)
if (拍摄时间来源 = "指定时间")
FormatTime, 拍摄时间, %指定时间%, yyyy/MM/dd HH:mm:ss ;yyyy/MM/dd HH:mm:ss
Else
拍摄时间 := 匹配文件名(FileName)[1]
修改数组.insert(RowNumber "|" Dir . "\" . FileName "|" Datetime "|" 拍摄时间)
}
修改项 := []
for index, element in 修改数组 ; 在大多数情况下建议使用枚举的方式.
{
修改项 := StrSplit(element, "|")
sCmd := "D:\3m_script\exiftool.exe"
. " -P"
. " -ModifyDate=" """" 修改项[4] """"
. " -DateTimeOriginal=" """" 修改项[4] """"
. " -overwrite_original "
. 修改项[2]
ret:=CmdRet(sCmd)
LV_Modify(修改项[1], "Vis")
LV_Modify(修改项[1], "-Select")
GDIPImage := Gdip_LoadImageFromFile(修改项[2])
PropItem := Gdip_GetPropertyItem(GDIPImage, 0x9003)
Gdip_DisposeImage(GDIPImage)
Datetime := StrReplace(PropItem.Value, ":")
Datetime := StrReplace(Datetime, " ")
FormatTime, Datetime, %Datetime%, yyyy/MM/dd HH:mm:ss
if (Datetime = 修改项[4])
LV_Modify(修改项[1], , , Datetime, " ✔")
}
Gdip_Shutdown(GDIPToken)
Return
列表被点击:
Critical
if (A_GuiEvent = "i") ;修改动作会触发 i
{
选择 := 0
RowNumber := 0 ; 这样使得首次循环从列表的顶部开始搜索.
Loop
{
RowNumber := LV_GetNext(RowNumber) ; 在前一次找到的位置后继续搜索.
if not RowNumber ; 上面返回零, 所以选择的行已经都找到了.
break
选择++
}
GuiControl,Text, 项目信息, % LV_GetCount() . " 个图像 选择 " 选择 " 个"
if (选择 > 0)
GuiControl, Enable, 移除按钮
Else
GuiControl, Disable, 移除按钮
if (选择 > 0 and 拍摄时间来源 != "")
GuiControl, Enable, 修改按钮
Else
GuiControl, Disable, 修改按钮
if (LV_GetCount() = 0 and 选择 = 0)
{
GuiControl,Text, 拍摄日期
GuiControl,Text, 创建日期
GuiControl,Text, 修改日期
GuiControl,, 匹配文件名编辑框
GuiControl,Text, name, 文件名
}
}
if (A_GuiEvent = "Normal") ; 脚本还可以检查许多其他的可能值.
{
选择 := 0
RowNumber := 0 ; 这样使得首次循环从列表的顶部开始搜索.
Loop
{
RowNumber := LV_GetNext(RowNumber) ; 在前一次找到的位置后继续搜索.
if not RowNumber ; 上面返回零, 所以选择的行已经都找到了.
break
选择++
}
if A_EventInfo
{
LV_GetText(FileName, A_EventInfo, 1) ; 从首个字段中获取文本.
LV_GetText(Datetime, A_EventInfo, 2)
Filepath := Dir "\" FileName
显示图像(FileName, FilePath, datetime)
}
}
Return
显示图像(Filename, FilePath, datetime)
{
if !GDIPToken
GDIPToken := Gdip_Startup()
global picpath := FilePath ; 用于点击图片时 执行Run
GuiControl,Text, name, %Filename%
pBitmap := Gdip_CreateBitmapFromFile(FilePath)
Gdip_GetImageDimensions(pBitmap, Width, Height)
Gdip_DisposeImage(pBitmap)
if (Width > Height)
GuiControl,, Pic, % "*w200 *h-1 " FilePath
Else
GuiControl,, Pic, % "*w-1 *h150 " FilePath
if !datetime
拍摄时间 := ""
Else
{
Datetime := StrReplace(datetime, ":")
Datetime := StrReplace(Datetime, " ")
FormatTime, 拍摄时间, %Datetime%, yyyy/MM/dd HH:mm
}
GuiControl,Text, 拍摄日期, %拍摄时间%
if (拍摄时间来源 = "匹配文件")
{
匹配时间 := 匹配文件名(FileName)
if (匹配时间[2] = 0)
{
Gui, Font, cRed
GuiControl, Font, 匹配文件名编辑框
}
Else
{
Gui, Font, c000000
GuiControl, Font, 匹配文件名编辑框
}
GuiControl,, 匹配文件名编辑框, % 匹配时间[1]
}
FileGetTime, 创建时间, %FilePath%, C
FileGetTime, 修改时间, %FilePath%, M
FormatTime, 创建时间, %创建时间%, yyyy/MM/dd HH:mm
FormatTime, 修改时间, %修改时间%, yyyy/MM/dd HH:mm
GuiControl,Text, 创建日期, %创建时间%
GuiControl,Text, 修改日期, %修改时间%
if GDIPToken and (加载文件 = 0)
Gdip_Shutdown(GDIPToken)
}
匹配文件名(FileName)
{
匹配时间 := []
y := SubStr(FileName, 1, 4)
m := SubStr(FileName, 6, 2)
d := SubStr(FileName, 8, 2)
时间 := y "/" m "/" d " " A_Hour ":" A_Min ":" A_Sec
匹配时间.Insert(时间)
if !RegExMatch(时间, "(?:(?:(?:(?:1[8-9]|20)(?:04|08|[2468][048]|[13579][26]))|2000)([-/])02(?:\1)29|(?:(?:1[8-9]|20)\d\d)([-/])(?:(?:0[1-9]|1[0-2])(?:\2)(?:0[1-9]|1[0-9]|2[0-8])|(?:0(?:1|[3-9])|(?:1[0-2]))(?:\2)(?:29|30)|(?:0[13578]|1[02])(?:\2)31))")
匹配时间.Insert(0)
Else
匹配时间.Insert(1)
Return 匹配时间
}
CmdRet(sCmd, callBackFuncObj := "", encoding := "CP0")
{
static HANDLE_FLAG_INHERIT := 0x00000001, flags := HANDLE_FLAG_INHERIT
, STARTF_USESTDHANDLES := 0x100, CREATE_NO_WINDOW := 0x08000000
DllCall("CreatePipe", "PtrP", hPipeRead, "PtrP", hPipeWrite, "Ptr", 0, "UInt", 0)
DllCall("SetHandleInformation", "Ptr", hPipeWrite, "UInt", flags, "UInt", HANDLE_FLAG_INHERIT)
VarSetCapacity(STARTUPINFO , siSize := A_PtrSize*4 + 4*8 + A_PtrSize*5, 0)
NumPut(siSize , STARTUPINFO)
NumPut(STARTF_USESTDHANDLES, STARTUPINFO, A_PtrSize*4 + 4*7)
NumPut(hPipeWrite , STARTUPINFO, A_PtrSize*4 + 4*8 + A_PtrSize*3)
NumPut(hPipeWrite , STARTUPINFO, A_PtrSize*4 + 4*8 + A_PtrSize*4)
VarSetCapacity(PROCESS_INFORMATION, A_PtrSize*2 + 4*2, 0)
if !DllCall("CreateProcess", "Ptr", 0, "Str", sCmd, "Ptr", 0, "Ptr", 0, "UInt", true, "UInt", CREATE_NO_WINDOW
, "Ptr", 0, "Ptr", 0, "Ptr", &STARTUPINFO, "Ptr", &PROCESS_INFORMATION)
{
DllCall("CloseHandle", "Ptr", hPipeRead)
DllCall("CloseHandle", "Ptr", hPipeWrite)
throw Exception("CreateProcess is failed")
}
DllCall("CloseHandle", "Ptr", hPipeWrite)
VarSetCapacity(sTemp, 4096), nSize := 0
while DllCall("ReadFile", "Ptr", hPipeRead, "Ptr", &sTemp, "UInt", 4096, "UIntP", nSize, "UInt", 0)
{
stdOut := StrGet(&sTemp, nSize, encoding) ;返回当前信息
; sOutput .= stdOut := StrGet(&sTemp, nSize, encoding) ;返回累积信息
( callBackFuncObj && callBackFuncObj.Call(stdOut) )
}
DllCall("CloseHandle", "Ptr", NumGet(PROCESS_INFORMATION))
DllCall("CloseHandle", "Ptr", NumGet(PROCESS_INFORMATION, A_PtrSize))
DllCall("CloseHandle", "Ptr", hPipeRead)
Return sOutput
}
打开图片:
run, %picpath%
Return
GuiClose: ; 当窗口关闭时, 自动退出脚本:
ExitApp
;--------test-----------------改变LV样式,被选条目颜色改变
SetExplorerTheme(HCTL) { ; HCTL : handle of a ListView or TreeView control
If (DllCall("GetVersion", "UChar") > 5) {
VarSetCapacity(ClassName, 1024, 0)
If DllCall("GetClassName", "Ptr", HCTL, "Str", ClassName, "Int", 512, "Int")
If (ClassName = "SysListView32") || (ClassName = "SysTreeView32")
Return !DllCall("UxTheme.dll\SetWindowTheme", "Ptr", HCTL, "WStr", "Explorer", "Ptr", 0)
}
Return False
}
;---------------------------------------------------------
SetHeaderItemCheckBox(hListView, item) {
static LVM_GETHEADER := 0x101F, HDS_CHECKBOXES := 0x400, HDI_FORMAT := 0x4
, HDM_FIRST := 0x1200, HDM_GETITEM := HDM_FIRST + (A_IsUnicode ? 3 : 11)
, HDM_SETITEM := HDM_GETITEM + 1, HDF_CHECKBOX := 0x40
, HDITEM_SIZE := 4*6 + A_PtrSize*6, fmt_offset := 4*3 + A_PtrSize*2
SendMessage, LVM_GETHEADER,,,, ahk_id %hListView%
WinExist("ahk_id" header := ErrorLevel)
WinSet, Style, +%HDS_CHECKBOXES%
VarSetCapacity(HDITEM, HDITEM_SIZE, 0)
NumPut(HDI_FORMAT, HDITEM)
SendMessage, HDM_GETITEM, --item, &HDITEM
fmt := NumGet(HDITEM, fmt_offset, "Int")
NumPut(fmt|HDF_CHECKBOX, HDITEM, fmt_offset)
SendMessage, HDM_SETITEM, item, &HDITEM
}
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。

评论(0)