[PowerRename] Fluent UX (#13678)

* PowerRename new UI

* Add scrollviewer

* Don't deploy PowerRenameUI_new

* Visual updates

* Visual updates

* Updates

* Update Resources.resw

* Added docs button

* Update MainWindow.xaml

* Wire Docs button

* RegEx -> regular expressions

* Update Show only renamed list on search/replace text changed

* Update Show only renamed list on search/replace text changed - proper fix
Set searchTerm to NULL when cleared - fix Show only renamed files on clear searchTerm

* Files/folders input error handling

* Fix renaming with keeping UI window opened

After renaming folder, all of it's children need path update.
Without path update, further renaming of children items would
fail.

* Update only children, not all items with greater depth

* Fix dictionary false positives

* Remove .NET dep

* Rename PowerRenameUI_new to PowerRenameUILib
Rename executable PowerRenameUIHost to PowerRename

Co-authored-by: Laute <Niels.Laute@philips.com>
This commit is contained in:
Stefan Markovic 2021-10-25 15:40:19 +02:00 committed by GitHub
parent ce942b0585
commit 5cfbd72fa8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
128 changed files with 5913 additions and 8281 deletions

View File

@ -7,6 +7,7 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ
abgr abgr
abi abi
ABlocked ABlocked
ABOUTBOX
Abug Abug
accctrl accctrl
Acceleratorkeys Acceleratorkeys
@ -1048,6 +1049,7 @@ IWeb
IWIC IWIC
IWindows IWindows
IWork IWork
IXaml
IXml IXml
ixx ixx
IYUV IYUV
@ -1157,6 +1159,7 @@ lmcons
LMEM LMEM
LMENU LMENU
lnk lnk
LOADSTRING
LOCALAPPDATA LOCALAPPDATA
LOCALDISPLAY LOCALDISPLAY
localhost localhost
@ -1178,6 +1181,7 @@ lowlevel
LOWORD LOWORD
lparam lparam
LPBYTE LPBYTE
LPCITEMIDLIST
LPCMINVOKECOMMANDINFO LPCMINVOKECOMMANDINFO
LPCREATESTRUCT LPCREATESTRUCT
LPCTSTR LPCTSTR
@ -1224,6 +1228,7 @@ LVS
LVSIL LVSIL
LWA LWA
lwin lwin
LZero
lzw lzw
mailto mailto
MAINICON MAINICON
@ -1579,6 +1584,7 @@ phwnd
pici pici
pid pid
pidl pidl
PIDLIST
PINDIR PINDIR
pinfo pinfo
pinvoke pinvoke
@ -1611,6 +1617,7 @@ powerlauncher
powerpreview powerpreview
powerrename powerrename
POWERRENAMETEST POWERRENAMETEST
POWERRENAMEUIHOST
powershell powershell
powertoy powertoy
powertoysinterop powertoysinterop

View File

@ -172,6 +172,8 @@ build:
- 'modules\launcher\Wox.Plugin.dll' - 'modules\launcher\Wox.Plugin.dll'
- 'modules\MouseUtils\FindMyMouse.dll' - 'modules\MouseUtils\FindMyMouse.dll'
- 'modules\PowerRename\PowerRenameExt.dll' - 'modules\PowerRename\PowerRenameExt.dll'
- 'modules\PowerRename\PowerRenameUILib.dll'
- 'modules\PowerRename\PowerRename.exe'
- 'modules\ShortcutGuide\ShortcutGuide\PowerToys.ShortcutGuide.exe' - 'modules\ShortcutGuide\ShortcutGuide\PowerToys.ShortcutGuide.exe'
- 'modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.dll' - 'modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.dll'
- 'modules\VideoConference\VideoConferenceModule.dll' - 'modules\VideoConference\VideoConferenceModule.dll'

View File

@ -76,7 +76,7 @@
<!-- Global props --> <!-- Global props -->
<PropertyGroup Label="Globals" Condition="'$(OverrideWindowsTargetPlatformVersion)'!='True'"> <PropertyGroup Label="Globals" Condition="'$(OverrideWindowsTargetPlatformVersion)'!='True'">
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<!-- Props that are constant for both Debug and Release configurations --> <!-- Props that are constant for both Debug and Release configurations -->
@ -84,7 +84,6 @@
<PlatformToolset Condition="'$(OverridePlatformToolset)'!='True'">v142</PlatformToolset> <PlatformToolset Condition="'$(OverridePlatformToolset)'!='True'">v142</PlatformToolset>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir> <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\</IntDir>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<SpectreMitigation>Spectre</SpectreMitigation>
</PropertyGroup> </PropertyGroup>
<!-- Debug/Release props --> <!-- Debug/Release props -->

View File

@ -5,7 +5,6 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runner", "src\runner\runner.vcxproj", "{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runner", "src\runner\runner.vcxproj", "{9412D5C6-2CF2-4FC2-A601-B55508EA9B27}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{217DF501-135C-4E38-BFC8-99D4821032EA} = {217DF501-135C-4E38-BFC8-99D4821032EA} {217DF501-135C-4E38-BFC8-99D4821032EA} = {217DF501-135C-4E38-BFC8-99D4821032EA}
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
{48804216-2A0E-4168-A6D8-9CD068D14227} = {48804216-2A0E-4168-A6D8-9CD068D14227} {48804216-2A0E-4168-A6D8-9CD068D14227} = {48804216-2A0E-4168-A6D8-9CD068D14227}
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2} {51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
{6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB} = {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB} {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB} = {6A71162E-FC4C-4A2C-B90F-3CF94F59A9BB}
@ -57,26 +56,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "powerrename", "powerrename"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameExt", "src\modules\powerrename\dll\PowerRenameExt.vcxproj", "{B25AC7A5-FB9F-4789-B392-D5C85E948670}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameExt", "src\modules\powerrename\dll\PowerRenameExt.vcxproj", "{B25AC7A5-FB9F-4789-B392-D5C85E948670}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2} {51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameLib", "src\modules\powerrename\lib\PowerRenameLib.vcxproj", "{51920F1F-C28C-4ADF-8660-4238766796C2}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameLib", "src\modules\powerrename\lib\PowerRenameLib.vcxproj", "{51920F1F-C28C-4ADF-8660-4238766796C2}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUI", "src\modules\powerrename\ui\PowerRenameUI.vcxproj", "{0E072714-D127-460B-AFAD-B4C40B412798}"
ProjectSection(ProjectDependencies) = postProject
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameTest", "src\modules\powerrename\testapp\PowerRenameTest.vcxproj", "{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameTest", "src\modules\powerrename\testapp\PowerRenameTest.vcxproj", "{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2} {51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUnitTests", "src\modules\powerrename\unittests\PowerRenameLibUnitTests.vcxproj", "{2151F984-E006-4A9F-92EF-C6DDE3DC8413}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUnitTests", "src\modules\powerrename\unittests\PowerRenameLibUnitTests.vcxproj", "{2151F984-E006-4A9F-92EF-C6DDE3DC8413}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2} {51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
{B25AC7A5-FB9F-4789-B392-D5C85E948670} = {B25AC7A5-FB9F-4789-B392-D5C85E948670} {B25AC7A5-FB9F-4789-B392-D5C85E948670} = {B25AC7A5-FB9F-4789-B392-D5C85E948670}
EndProjectSection EndProjectSection
@ -84,9 +75,6 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ModuleTemplateCompileTest", "tools\project_template\ModuleTemplate\ModuleTemplateCompileTest.vcxproj", "{64A80062-4D8B-4229-8A38-DFA1D7497749}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ModuleTemplateCompileTest", "tools\project_template\ModuleTemplate\ModuleTemplateCompileTest.vcxproj", "{64A80062-4D8B-4229-8A38-DFA1D7497749}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUWPUI", "src\modules\powerrename\UWPui\PowerRenameUWPUI.vcxproj", "{0485F45C-EA7A-4BB5-804B-3E8D14699387}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUWPUI", "src\modules\powerrename\UWPui\PowerRenameUWPUI.vcxproj", "{0485F45C-EA7A-4BB5-804B-3E8D14699387}"
ProjectSection(ProjectDependencies) = postProject
{0E072714-D127-460B-AFAD-B4C40B412798} = {0E072714-D127-460B-AFAD-B4C40B412798}
EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManager", "src\modules\keyboardmanager\dll\KeyboardManager.vcxproj", "{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManager", "src\modules\keyboardmanager\dll\KeyboardManager.vcxproj", "{89F34AF7-1C34-4A72-AA6E-534BCF972BD9}"
EndProject EndProject
@ -194,6 +182,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
src\.editorconfig = src\.editorconfig src\.editorconfig = src\.editorconfig
src\tests\win-app-driver\packages.config = src\tests\win-app-driver\packages.config src\tests\win-app-driver\packages.config = src\tests\win-app-driver\packages.config
Solution.props = Solution.props
EndProjectSection EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Settings.UI.Library", "src\settings-ui\Microsoft.PowerToys.Settings.UI.Library\Microsoft.PowerToys.Settings.UI.Library.csproj", "{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Settings.UI.Library", "src\settings-ui\Microsoft.PowerToys.Settings.UI.Library\Microsoft.PowerToys.Settings.UI.Library.csproj", "{B1BCC8C6-46B5-4BFA-8F22-20F32D99EC6A}"
@ -283,6 +272,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643
src\common\utils\EventLocker.h = src\common\utils\EventLocker.h src\common\utils\EventLocker.h = src\common\utils\EventLocker.h
src\common\utils\EventWaiter.h = src\common\utils\EventWaiter.h src\common\utils\EventWaiter.h = src\common\utils\EventWaiter.h
src\common\utils\exec.h = src\common\utils\exec.h src\common\utils\exec.h = src\common\utils\exec.h
src\common\utils\HDropIterator.h = src\common\utils\HDropIterator.h
src\common\utils\HttpClient.h = src\common\utils\HttpClient.h src\common\utils\HttpClient.h = src\common\utils\HttpClient.h
src\common\utils\json.h = src\common\utils\json.h src\common\utils\json.h = src\common\utils\json.h
src\common\utils\logger_helper.h = src\common\utils\logger_helper.h src\common\utils\logger_helper.h = src\common\utils\logger_helper.h
@ -372,6 +362,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plu
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests.csproj", "{4ED320BC-BA04-4D42-8D15-CBE62151F08B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.UnitTests.csproj", "{4ED320BC-BA04-4D42-8D15-CBE62151F08B}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUIHost", "src\modules\powerrename\PowerRenameUIHost\PowerRenameUIHost.vcxproj", "{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}"
ProjectSection(ProjectDependencies) = postProject
{4642D596-723F-4BFC-894C-46811219AC4A} = {4642D596-723F-4BFC-894C-46811219AC4A}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameUILib", "src\modules\powerrename\PowerRenameUILib\PowerRenameUILib.vcxproj", "{4642D596-723F-4BFC-894C-46811219AC4A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MouseUtils", "MouseUtils", "{322566EF-20DC-43A6-B9F8-616AF942579A}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MouseUtils", "MouseUtils", "{322566EF-20DC-43A6-B9F8-616AF942579A}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FindMyMouse", "src\modules\MouseUtils\FindMyMouse\FindMyMouse.vcxproj", "{E94FD11C-0591-456F-899F-EFC0CA548336}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FindMyMouse", "src\modules\MouseUtils\FindMyMouse\FindMyMouse.vcxproj", "{E94FD11C-0591-456F-899F-EFC0CA548336}"
@ -426,12 +423,6 @@ Global
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.ActiveCfg = Release|x64 {51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.ActiveCfg = Release|x64
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.Build.0 = Release|x64 {51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x64.Build.0 = Release|x64
{51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x86.ActiveCfg = Release|x64 {51920F1F-C28C-4ADF-8660-4238766796C2}.Release|x86.ActiveCfg = Release|x64
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x64.ActiveCfg = Debug|x64
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x64.Build.0 = Debug|x64
{0E072714-D127-460B-AFAD-B4C40B412798}.Debug|x86.ActiveCfg = Debug|x64
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x64.ActiveCfg = Release|x64
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x64.Build.0 = Release|x64
{0E072714-D127-460B-AFAD-B4C40B412798}.Release|x86.ActiveCfg = Release|x64
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.ActiveCfg = Debug|x64 {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.ActiveCfg = Debug|x64
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.Build.0 = Debug|x64 {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x64.Build.0 = Debug|x64
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x86.ActiveCfg = Debug|x64 {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}.Debug|x86.ActiveCfg = Debug|x64
@ -985,6 +976,18 @@ Global
{4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x64.Build.0 = Release|x64 {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x64.Build.0 = Release|x64
{4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x86.ActiveCfg = Release|Any CPU {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x86.ActiveCfg = Release|Any CPU
{4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x86.Build.0 = Release|Any CPU {4ED320BC-BA04-4D42-8D15-CBE62151F08B}.Release|x86.Build.0 = Release|Any CPU
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Debug|x64.ActiveCfg = Debug|x64
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Debug|x64.Build.0 = Debug|x64
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Debug|x86.ActiveCfg = Debug|x64
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Release|x64.ActiveCfg = Release|x64
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Release|x64.Build.0 = Release|x64
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63}.Release|x86.ActiveCfg = Release|x64
{4642D596-723F-4BFC-894C-46811219AC4A}.Debug|x64.ActiveCfg = Debug|x64
{4642D596-723F-4BFC-894C-46811219AC4A}.Debug|x64.Build.0 = Debug|x64
{4642D596-723F-4BFC-894C-46811219AC4A}.Debug|x86.ActiveCfg = Debug|x64
{4642D596-723F-4BFC-894C-46811219AC4A}.Release|x64.ActiveCfg = Release|x64
{4642D596-723F-4BFC-894C-46811219AC4A}.Release|x64.Build.0 = Release|x64
{4642D596-723F-4BFC-894C-46811219AC4A}.Release|x86.ActiveCfg = Release|x64
{E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x64.ActiveCfg = Debug|x64 {E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x64.ActiveCfg = Debug|x64
{E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x64.Build.0 = Debug|x64 {E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x64.Build.0 = Debug|x64
{E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x86.ActiveCfg = Debug|x64 {E94FD11C-0591-456F-899F-EFC0CA548336}.Debug|x86.ActiveCfg = Debug|x64
@ -1005,7 +1008,6 @@ Global
{89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{B25AC7A5-FB9F-4789-B392-D5C85E948670} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} {B25AC7A5-FB9F-4789-B392-D5C85E948670} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{51920F1F-C28C-4ADF-8660-4238766796C2} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} {51920F1F-C28C-4ADF-8660-4238766796C2} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{0E072714-D127-460B-AFAD-B4C40B412798} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} {A3935CF4-46C5-4A88-84D3-6B12E16E6BA2} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{2151F984-E006-4A9F-92EF-C6DDE3DC8413} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} {2151F984-E006-4A9F-92EF-C6DDE3DC8413} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{0485F45C-EA7A-4BB5-804B-3E8D14699387} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3} {0485F45C-EA7A-4BB5-804B-3E8D14699387} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
@ -1108,6 +1110,8 @@ Global
{F40C3397-1834-4530-B2D9-8F8B8456BCDF} = {2F305555-C296-497E-AC20-5FA1B237996A} {F40C3397-1834-4530-B2D9-8F8B8456BCDF} = {2F305555-C296-497E-AC20-5FA1B237996A}
{A2D583F0-B70C-4462-B1F0-8E81AFB7BA85} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {A2D583F0-B70C-4462-B1F0-8E81AFB7BA85} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{4ED320BC-BA04-4D42-8D15-CBE62151F08B} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {4ED320BC-BA04-4D42-8D15-CBE62151F08B} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{F7EC4E6C-19CA-4FBD-9918-B8AC5FEF4F63} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{4642D596-723F-4BFC-894C-46811219AC4A} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{322566EF-20DC-43A6-B9F8-616AF942579A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} {322566EF-20DC-43A6-B9F8-616AF942579A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{E94FD11C-0591-456F-899F-EFC0CA548336} = {322566EF-20DC-43A6-B9F8-616AF942579A} {E94FD11C-0591-456F-899F-EFC0CA548336} = {322566EF-20DC-43A6-B9F8-616AF942579A}
EndGlobalSection EndGlobalSection

6
Solution.props Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<GeneratedFilesDir>$(IntDir)Generated Files\</GeneratedFilesDir>
</PropertyGroup>
</Project>

View File

@ -21,6 +21,3 @@ TODO
#### [`trace.cpp`](/src/modules/powerrename/lib/trace.cpp) #### [`trace.cpp`](/src/modules/powerrename/lib/trace.cpp)
TODO TODO
#### [`PowerRenameUI.cpp`](/src/modules/powerrename/ui/PowerRenameUI.cpp)
TODO

View File

@ -236,7 +236,9 @@
<Directory Id="ToolsFolder" Name="Tools"/> <Directory Id="ToolsFolder" Name="Tools"/>
<Directory Id="ModulesInstallFolder" Name="modules"> <Directory Id="ModulesInstallFolder" Name="modules">
<Directory Id="ImageResizerInstallFolder" Name="$(var.ImageResizerProjectName)" /> <Directory Id="ImageResizerInstallFolder" Name="$(var.ImageResizerProjectName)" />
<Directory Id="PowerRenameInstallFolder" Name="$(var.PowerRenameProjectName)"/> <Directory Id="PowerRenameInstallFolder" Name="$(var.PowerRenameProjectName)">
<Directory Id="PowerRenameAssetsFolder" Name="Assets" />
</Directory>
<Directory Id="ShortcutGuideInstallFolder" Name="ShortcutGuide"> <Directory Id="ShortcutGuideInstallFolder" Name="ShortcutGuide">
<Directory Id="ShortcutGuideExecutableInstallFolder" Name="ShortcutGuide"> <Directory Id="ShortcutGuideExecutableInstallFolder" Name="ShortcutGuide">
<Directory Id="ShortcutGuideSvgsInstallFolder" Name="svgs"/> <Directory Id="ShortcutGuideSvgsInstallFolder" Name="svgs"/>
@ -694,6 +696,14 @@
<!-- PowerRename --> <!-- PowerRename -->
<DirectoryRef Id="PowerRenameInstallFolder" FileSource="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)"> <DirectoryRef Id="PowerRenameInstallFolder" FileSource="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)">
<Component Id="Module_PowerRename" Guid="E4401D08-27FE-4F96-BA17-0C61FD79E684" Win64="yes"> <Component Id="Module_PowerRename" Guid="E4401D08-27FE-4F96-BA17-0C61FD79E684" Win64="yes">
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\Microsoft.Toolkit.Win32.UI.XamlHost.dll" />
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\Microsoft.UI.Xaml.dll" />
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\msvcp140_app.dll" />
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\PowerRenameUILib.dll" />
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\PowerRename.exe" />
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\resources.pri" />
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\vcruntime140_1_app.dll" />
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\vcruntime140_app.dll" />
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\PowerRenameExt.dll" KeyPath="yes" /> <File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\PowerRenameExt.dll" KeyPath="yes" />
<RegistryKey Root="HKCR" Key="CLSID\{0440049F-D1DC-4E46-B27B-98393D79486B}"> <RegistryKey Root="HKCR" Key="CLSID\{0440049F-D1DC-4E46-B27B-98393D79486B}">
<RegistryValue Type="string" Value="PowerRename Shell Extension" /> <RegistryValue Type="string" Value="PowerRename Shell Extension" />
@ -707,6 +717,12 @@
</Component> </Component>
</DirectoryRef> </DirectoryRef>
<DirectoryRef Id="PowerRenameAssetsFolder" FileSource="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)">
<Component Id="Module_PowerRename_Assets" Guid="5976BEDF-64F5-4836-8674-EE7577C77508" Win64="yes">
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\Assets\file.png" />
<File Source="$(var.BinX64Dir)modules\$(var.PowerRenameProjectName)\Assets\folder.png" />
</Component>
</DirectoryRef>
<!-- MouseUtils --> <!-- MouseUtils -->
<DirectoryRef Id="MouseUtilsInstallFolder" FileSource="$(var.BinX64Dir)modules\$(var.MouseUtilsProjectName)"> <DirectoryRef Id="MouseUtilsInstallFolder" FileSource="$(var.BinX64Dir)modules\$(var.MouseUtilsProjectName)">
<Component Id="Module_FindMyMouse" Guid="60D0E4AE-188F-4403-BF06-1465AACC1BC5" Win64="yes"> <Component Id="Module_FindMyMouse" Guid="60D0E4AE-188F-4403-BF06-1465AACC1BC5" Win64="yes">
@ -1011,6 +1027,7 @@
<ComponentRef Id="Module_FancyZones" /> <ComponentRef Id="Module_FancyZones" />
<ComponentRef Id="DesktopShortcut" /> <ComponentRef Id="DesktopShortcut" />
<ComponentRef Id="Module_PowerRename" /> <ComponentRef Id="Module_PowerRename" />
<ComponentRef Id="Module_PowerRename_Assets" />
<ComponentRef Id="Module_ImageResizer" /> <ComponentRef Id="Module_ImageResizer" />
<ComponentRef Id="Module_ImageResizer_Registry" /> <ComponentRef Id="Module_ImageResizer_Registry" />
<ComponentRef Id="Module_PowerPreview" /> <ComponentRef Id="Module_PowerPreview" />

View File

@ -10,5 +10,6 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
// add headers that you want to pre-compile here // add headers that you want to pre-compile here
#include <Windows.h> #include <Windows.h>
#include <Endpointvolume.h>
#endif //PCH_H #endif //PCH_H

View File

@ -0,0 +1,58 @@
#pragma once
#include <shellapi.h>
class HDropIterator
{
public:
HDropIterator(IDataObject* pDataObject)
{
_current = 0;
FORMATETC formatetc = {
CF_HDROP,
NULL,
DVASPECT_CONTENT,
-1,
TYMED_HGLOBAL
};
pDataObject->GetData(&formatetc, &m_medium);
_listCount = DragQueryFile((HDROP)m_medium.hGlobal, 0xFFFFFFFF, NULL, 0);
}
~HDropIterator()
{
ReleaseStgMedium(&m_medium);
}
void First()
{
_current = 0;
}
void Next()
{
_current++;
}
bool IsDone() const
{
return _current >= _listCount;
}
LPTSTR CurrentItem() const
{
UINT cch = DragQueryFile((HDROP)m_medium.hGlobal, _current, NULL, 0) + 1;
LPTSTR pszPath = (LPTSTR)malloc(sizeof(TCHAR) * cch);
DragQueryFile((HDROP)m_medium.hGlobal, _current, pszPath, cch);
return pszPath;
}
private:
UINT _listCount;
STGMEDIUM m_medium;
UINT _current;
};

View File

@ -2,11 +2,11 @@
#include "pch.h" #include "pch.h"
#include "ContextMenuHandler.h" #include "ContextMenuHandler.h"
#include "HDropIterator.h"
#include "Settings.h" #include "Settings.h"
#include <common/themes/icon_helpers.h> #include <common/themes/icon_helpers.h>
#include <common/utils/process_path.h> #include <common/utils/process_path.h>
#include <common/utils/resources.h> #include <common/utils/resources.h>
#include <common/utils/HDropIterator.h>
#include "trace.h" #include "trace.h"

View File

@ -1,49 +0,0 @@
#include "pch.h"
#include "HDropIterator.h"
HDropIterator::HDropIterator(IDataObject* pdtobj)
{
_current = 0;
FORMATETC formatetc = {
CF_HDROP,
NULL,
DVASPECT_CONTENT,
-1,
TYMED_HGLOBAL
};
pdtobj->GetData(&formatetc, &m_medium);
_listCount = DragQueryFile((HDROP)m_medium.hGlobal, 0xFFFFFFFF, NULL, 0);
}
HDropIterator::~HDropIterator()
{
ReleaseStgMedium(&m_medium);
}
void HDropIterator::First()
{
_current = 0;
}
void HDropIterator::Next()
{
_current++;
}
bool HDropIterator::IsDone() const
{
return _current >= _listCount;
}
LPTSTR HDropIterator::CurrentItem() const
{
UINT cch = DragQueryFile((HDROP)m_medium.hGlobal, _current, NULL, 0) + 1;
LPTSTR pszPath = (LPTSTR)malloc(sizeof(TCHAR) * cch);
DragQueryFile((HDROP)m_medium.hGlobal, _current, pszPath, cch);
return pszPath;
}

View File

@ -1,17 +0,0 @@
#pragma once
class HDropIterator
{
public:
HDropIterator(IDataObject *pDataObject);
~HDropIterator();
void First();
void Next();
bool IsDone() const;
LPTSTR CurrentItem() const;
private:
UINT _listCount;
STGMEDIUM m_medium;
UINT _current;
};

View File

@ -77,7 +77,6 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="ContextMenuHandler.cpp" /> <ClCompile Include="ContextMenuHandler.cpp" />
<ClCompile Include="HDropIterator.cpp" />
<ClCompile Include="dllmain.cpp"> <ClCompile Include="dllmain.cpp">
<CompileAsManaged Condition="'$(CIBuild)'!='true'">false</CompileAsManaged> <CompileAsManaged Condition="'$(CIBuild)'!='true'">false</CompileAsManaged>
<PrecompiledHeader Condition="'$(CIBuild)'!='true'"> <PrecompiledHeader Condition="'$(CIBuild)'!='true'">
@ -97,7 +96,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="ContextMenuHandler.h" /> <ClInclude Include="ContextMenuHandler.h" />
<ClInclude Include="HDropIterator.h" />
<ClInclude Include="dllmain.h" /> <ClInclude Include="dllmain.h" />
<None Include="resource.base.h" /> <None Include="resource.base.h" />
<ClInclude Include="ImageResizerConstants.h" /> <ClInclude Include="ImageResizerConstants.h" />

View File

@ -28,9 +28,6 @@
<ClCompile Include="ContextMenuHandler.cpp"> <ClCompile Include="ContextMenuHandler.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="HDropIterator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Settings.cpp"> <ClCompile Include="Settings.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -57,9 +54,6 @@
<ClInclude Include="ContextMenuHandler.h"> <ClInclude Include="ContextMenuHandler.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="HDropIterator.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Settings.h"> <ClInclude Include="Settings.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>

View File

@ -0,0 +1,917 @@
// PowerRenameUIHost.cpp : Defines the entry point for the application.
//
#include "pch.h"
#include "PowerRenameUIHost.h"
#include <settings.h>
#include <trace.h>
#include <string>
#include <sstream>
#include <vector>
#include <common/utils/process_path.h>
#define MAX_LOADSTRING 100
const wchar_t c_WindowClass[] = L"PowerRename";
HINSTANCE g_hostHInst;
int AppWindow::Show(HINSTANCE hInstance, std::vector<std::wstring> files)
{
auto window = AppWindow(hInstance, files);
window.CreateAndShowWindow();
return window.MessageLoop(window.m_accelerators.get());
}
LRESULT AppWindow::MessageHandler(UINT message, WPARAM wParam, LPARAM lParam) noexcept
{
switch (message)
{
HANDLE_MSG(WindowHandle(), WM_CREATE, OnCreate);
HANDLE_MSG(WindowHandle(), WM_COMMAND, OnCommand);
HANDLE_MSG(WindowHandle(), WM_DESTROY, OnDestroy);
HANDLE_MSG(WindowHandle(), WM_SIZE, OnResize);
default:
return base_type::MessageHandler(message, wParam, lParam);
}
return base_type::MessageHandler(message, wParam, lParam);
}
AppWindow::AppWindow(HINSTANCE hInstance, std::vector<std::wstring> files) noexcept :
m_instance{ hInstance }, m_managerEvents{ this }
{
HRESULT hr = CPowerRenameManager::s_CreateInstance(&m_prManager);
// Create the factory for our items
CComPtr<IPowerRenameItemFactory> prItemFactory;
hr = CPowerRenameItem::s_CreateInstance(nullptr, IID_PPV_ARGS(&prItemFactory));
hr = m_prManager->PutRenameItemFactory(prItemFactory);
hr = m_prManager->Advise(&m_managerEvents, &m_cookie);
if (SUCCEEDED(hr))
{
CComPtr<IShellItemArray> shellItemArray;
// To test PowerRenameUIHost uncomment this line and update the path to
// your local (absolute or relative) path which you want to see in PowerRename
//files.push_back(L"<path>");
if (!files.empty())
{
hr = CreateShellItemArrayFromPaths(files, &shellItemArray);
if (SUCCEEDED(hr))
{
CComPtr<IEnumShellItems> enumShellItems;
hr = shellItemArray->EnumItems(&enumShellItems);
if (SUCCEEDED(hr))
{
EnumerateShellItems(enumShellItems);
}
}
}
}
}
void AppWindow::CreateAndShowWindow()
{
m_accelerators.reset(LoadAcceleratorsW(m_instance, MAKEINTRESOURCE(IDC_POWERRENAMEUIHOST)));
WNDCLASSEXW wcex = { sizeof(wcex) };
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = m_instance;
wcex.hIcon = LoadIconW(m_instance, MAKEINTRESOURCE(IDC_POWERRENAMEUIHOST));
wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
wcex.lpszClassName = c_WindowClass;
wcex.hIconSm = LoadIconW(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
RegisterClassExW(&wcex); // don't test result, handle error at CreateWindow
wchar_t title[64];
LoadStringW(m_instance, IDS_APP_TITLE, title, ARRAYSIZE(title));
m_window = CreateWindowW(c_WindowClass, title, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, m_instance, this);
THROW_LAST_ERROR_IF(!m_window);
ShowWindow(m_window, SW_SHOWNORMAL);
UpdateWindow(m_window);
SetFocus(m_window);
}
bool AppWindow::OnCreate(HWND, LPCREATESTRUCT) noexcept
{
m_mainUserControl = winrt::PowerRenameUILib::MainWindow();
m_xamlIsland = CreateDesktopWindowsXamlSource(WS_TABSTOP, m_mainUserControl);
PopulateExplorerItems();
SetHandlers();
ReadSettings();
m_mainUserControl.UIUpdatesItem().ButtonRenameEnabled(false);
InitAutoComplete();
SearchReplaceChanged();
return true;
}
void AppWindow::OnCommand(HWND, int id, HWND hwndControl, UINT codeNotify) noexcept
{
switch (id)
{
case IDM_ABOUT:
DialogBoxW(m_instance, MAKEINTRESOURCE(IDD_ABOUTBOX), WindowHandle(), [](HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) -> INT_PTR {
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL))
{
EndDialog(hDlg, LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
});
break;
case IDM_EXIT:
PostQuitMessage(0);
break;
}
}
void AppWindow::OnDestroy(HWND hwnd) noexcept
{
base_type::OnDestroy(hwnd);
}
void AppWindow::OnResize(HWND, UINT state, int cx, int cy) noexcept
{
SetWindowPos(m_xamlIsland, NULL, 0, 0, cx, cy, SWP_SHOWWINDOW);
}
HRESULT AppWindow::CreateShellItemArrayFromPaths(
std::vector<std::wstring> files,
IShellItemArray** shellItemArray)
{
*shellItemArray = nullptr;
PIDLIST_ABSOLUTE* itemList = nullptr;
itemList = new (std::nothrow) PIDLIST_ABSOLUTE[files.size()];
HRESULT hr = itemList ? S_OK : E_OUTOFMEMORY;
UINT itemsCnt = 0;
for (const auto& file : files)
{
const DWORD BUFSIZE = 4096;
TCHAR buffer[BUFSIZE] = TEXT("");
auto retval = GetFullPathName(file.c_str(), BUFSIZE, buffer, NULL);
if (retval != 0 && PathFileExists(buffer))
{
hr = SHParseDisplayName(buffer, nullptr, &itemList[itemsCnt], 0, nullptr);
++itemsCnt;
}
}
if (SUCCEEDED(hr) && itemsCnt > 0)
{
hr = SHCreateShellItemArrayFromIDLists(itemsCnt, const_cast<LPCITEMIDLIST*>(itemList), shellItemArray);
for (UINT i = 0; i < itemsCnt; i++)
{
CoTaskMemFree(itemList[i]);
}
}
else
{
hr = E_FAIL;
}
delete[] itemList;
return hr;
}
void AppWindow::PopulateExplorerItems()
{
UINT count = 0;
m_prManager->GetVisibleItemCount(&count);
UINT currDepth = 0;
std::stack<UINT> parents{};
UINT prevId = 0;
parents.push(0);
for (UINT i = 0; i < count; ++i)
{
CComPtr<IPowerRenameItem> renameItem;
if (SUCCEEDED(m_prManager->GetVisibleItemByIndex(i, &renameItem)))
{
int id = 0;
renameItem->GetId(&id);
PWSTR originalName = nullptr;
renameItem->GetOriginalName(&originalName);
PWSTR newName = nullptr;
renameItem->GetNewName(&newName);
bool selected;
renameItem->GetSelected(&selected);
UINT depth = 0;
renameItem->GetDepth(&depth);
bool isFolder = false;
bool isSubFolderContent = false;
winrt::check_hresult(renameItem->GetIsFolder(&isFolder));
if (depth > currDepth)
{
parents.push(prevId);
currDepth = depth;
}
else
{
while (currDepth > depth)
{
parents.pop();
currDepth--;
}
currDepth = depth;
}
m_mainUserControl.AddExplorerItem(
id, originalName, newName == nullptr ? hstring{} : hstring{ newName }, isFolder ? 0 : 1, parents.top(), selected);
prevId = id;
}
}
}
HRESULT AppWindow::InitAutoComplete()
{
HRESULT hr = S_OK;
if (CSettingsInstance().GetMRUEnabled())
{
hr = CPowerRenameMRU::CPowerRenameMRUSearch_CreateInstance(&m_searchMRU);
if (SUCCEEDED(hr))
{
for (const auto& item : m_searchMRU->GetMRUStrings())
{
if (!item.empty())
{
m_mainUserControl.AppendSearchMRU(item);
}
}
}
if (SUCCEEDED(hr))
{
hr = CPowerRenameMRU::CPowerRenameMRUReplace_CreateInstance(&m_replaceMRU);
if (SUCCEEDED(hr))
{
for (const auto& item : m_replaceMRU->GetMRUStrings())
{
if (!item.empty())
{
m_mainUserControl.AppendReplaceMRU(item);
}
}
}
}
}
return hr;
}
HRESULT AppWindow::EnumerateShellItems(_In_ IEnumShellItems* enumShellItems)
{
HRESULT hr = S_OK;
// Enumerate the data object and populate the manager
if (m_prManager)
{
m_disableCountUpdate = true;
// Ensure we re-create the enumerator
m_prEnum = nullptr;
hr = CPowerRenameEnum::s_CreateInstance(nullptr, m_prManager, IID_PPV_ARGS(&m_prEnum));
if (SUCCEEDED(hr))
{
hr = m_prEnum->Start(enumShellItems);
}
m_disableCountUpdate = false;
}
return hr;
}
void AppWindow::SearchReplaceChanged(bool forceRenaming)
{
// Pass updated search and replace terms to the IPowerRenameRegEx handler
CComPtr<IPowerRenameRegEx> prRegEx;
if (m_prManager && SUCCEEDED(m_prManager->GetRenameRegEx(&prRegEx)))
{
winrt::hstring searchTerm = m_mainUserControl.AutoSuggestBoxSearch().Text();
prRegEx->PutSearchTerm(searchTerm.c_str(), forceRenaming);
winrt::hstring replaceTerm = m_mainUserControl.AutoSuggestBoxReplace().Text();
prRegEx->PutReplaceTerm(replaceTerm.c_str(), forceRenaming);
}
}
void AppWindow::ValidateFlags(PowerRenameFlags flag)
{
if (flag == Uppercase)
{
if (m_mainUserControl.ToggleButtonUpperCase().IsChecked())
{
m_mainUserControl.ToggleButtonLowerCase().IsChecked(false);
m_mainUserControl.ToggleButtonTitleCase().IsChecked(false);
m_mainUserControl.ToggleButtonCapitalize().IsChecked(false);
}
}
else if (flag == Lowercase)
{
if (m_mainUserControl.ToggleButtonLowerCase().IsChecked())
{
m_mainUserControl.ToggleButtonUpperCase().IsChecked(false);
m_mainUserControl.ToggleButtonTitleCase().IsChecked(false);
m_mainUserControl.ToggleButtonCapitalize().IsChecked(false);
}
}
else if (flag == Titlecase)
{
if (m_mainUserControl.ToggleButtonTitleCase().IsChecked())
{
m_mainUserControl.ToggleButtonUpperCase().IsChecked(false);
m_mainUserControl.ToggleButtonLowerCase().IsChecked(false);
m_mainUserControl.ToggleButtonCapitalize().IsChecked(false);
}
}
else if (flag == Capitalized)
{
if (m_mainUserControl.ToggleButtonCapitalize().IsChecked())
{
m_mainUserControl.ToggleButtonUpperCase().IsChecked(false);
m_mainUserControl.ToggleButtonLowerCase().IsChecked(false);
m_mainUserControl.ToggleButtonTitleCase().IsChecked(false);
}
}
m_flagValidationInProgress = true;
}
void AppWindow::UpdateFlag(PowerRenameFlags flag, UpdateFlagCommand command)
{
DWORD flags{};
m_prManager->GetFlags(&flags);
if (command == UpdateFlagCommand::Set)
{
flags |= flag;
}
else if (command == UpdateFlagCommand::Reset)
{
flags &= ~flag;
}
// Ensure we update flags
if (m_prManager)
{
m_prManager->PutFlags(flags);
}
}
void AppWindow::SetHandlers()
{
m_mainUserControl.UIUpdatesItem().PropertyChanged([&](winrt::Windows::Foundation::IInspectable const& sender, Data::PropertyChangedEventArgs const& e) {
std::wstring property{ e.PropertyName() };
if (property == L"ShowAll")
{
SwitchView();
}
else if (property == L"ChangedItemId")
{
ToggleItem(m_mainUserControl.UIUpdatesItem().ChangedExplorerItemId(), m_mainUserControl.UIUpdatesItem().Checked());
}
else if (property == L"ToggleAll")
{
ToggleAll();
}
else if (property == L"Rename")
{
Rename(m_mainUserControl.UIUpdatesItem().CloseUIWindow());
}
});
// AutoSuggestBox Search
m_mainUserControl.AutoSuggestBoxSearch().TextChanged([&](winrt::Windows::Foundation::IInspectable const& sender, AutoSuggestBoxTextChangedEventArgs const&) {
SearchReplaceChanged();
});
// AutoSuggestBox Replace
m_mainUserControl.AutoSuggestBoxReplace().TextChanged([&](winrt::Windows::Foundation::IInspectable const& sender, AutoSuggestBoxTextChangedEventArgs const&) {
SearchReplaceChanged();
});
// ToggleButton UpperCase
m_mainUserControl.ToggleButtonUpperCase().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(Uppercase);
UpdateFlag(Uppercase, UpdateFlagCommand::Set);
});
m_mainUserControl.ToggleButtonUpperCase().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(Uppercase, UpdateFlagCommand::Reset);
});
// ToggleButton LowerCase
m_mainUserControl.ToggleButtonLowerCase().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(Lowercase);
UpdateFlag(Lowercase, UpdateFlagCommand::Set);
});
m_mainUserControl.ToggleButtonLowerCase().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(Lowercase, UpdateFlagCommand::Reset);
});
// ToggleButton TitleCase
m_mainUserControl.ToggleButtonTitleCase().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(Titlecase);
UpdateFlag(Titlecase, UpdateFlagCommand::Set);
});
m_mainUserControl.ToggleButtonTitleCase().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(Titlecase, UpdateFlagCommand::Reset);
});
// ToggleButton Capitalize
m_mainUserControl.ToggleButtonCapitalize().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(Capitalized);
UpdateFlag(Capitalized, UpdateFlagCommand::Set);
});
m_mainUserControl.ToggleButtonCapitalize().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(Capitalized, UpdateFlagCommand::Reset);
});
// CheckBox Regex
m_mainUserControl.CheckBoxRegex().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(UseRegularExpressions);
UpdateFlag(UseRegularExpressions, UpdateFlagCommand::Set);
});
m_mainUserControl.CheckBoxRegex().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(UseRegularExpressions, UpdateFlagCommand::Reset);
});
// CheckBox CaseSensitive
m_mainUserControl.CheckBoxCaseSensitive().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(CaseSensitive);
UpdateFlag(CaseSensitive, UpdateFlagCommand::Set);
});
m_mainUserControl.CheckBoxCaseSensitive().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(CaseSensitive, UpdateFlagCommand::Reset);
});
// ComboBox RenameParts
m_mainUserControl.ComboBoxRenameParts().SelectionChanged([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
if (m_mainUserControl.ComboBoxRenameParts().SelectedIndex() == 0)
{ // Filename + extension
UpdateFlag(NameOnly, UpdateFlagCommand::Reset);
UpdateFlag(ExtensionOnly, UpdateFlagCommand::Reset);
}
else if (m_mainUserControl.ComboBoxRenameParts().SelectedIndex() == 1) // Filename Only
{
ValidateFlags(NameOnly);
UpdateFlag(ExtensionOnly, UpdateFlagCommand::Reset);
UpdateFlag(NameOnly, UpdateFlagCommand::Set);
}
else if (m_mainUserControl.ComboBoxRenameParts().SelectedIndex() == 2) // Extension Only
{
ValidateFlags(ExtensionOnly);
UpdateFlag(NameOnly, UpdateFlagCommand::Reset);
UpdateFlag(ExtensionOnly, UpdateFlagCommand::Set);
}
});
// CheckBox MatchAllOccurences
m_mainUserControl.CheckBoxMatchAll().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(MatchAllOccurences);
UpdateFlag(MatchAllOccurences, UpdateFlagCommand::Set);
});
m_mainUserControl.CheckBoxMatchAll().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(MatchAllOccurences, UpdateFlagCommand::Reset);
});
// ToggleButton IncludeFiles
m_mainUserControl.ToggleButtonIncludeFiles().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(ExcludeFiles);
UpdateFlag(ExcludeFiles, UpdateFlagCommand::Reset);
});
m_mainUserControl.ToggleButtonIncludeFiles().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(ExcludeFiles, UpdateFlagCommand::Set);
});
// ToggleButton IncludeFolders
m_mainUserControl.ToggleButtonIncludeFolders().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(ExcludeFolders);
UpdateFlag(ExcludeFolders, UpdateFlagCommand::Reset);
});
m_mainUserControl.ToggleButtonIncludeFolders().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(ExcludeFolders, UpdateFlagCommand::Set);
});
// ToggleButton IncludeSubfolders
m_mainUserControl.ToggleButtonIncludeSubfolders().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(ExcludeSubfolders);
UpdateFlag(ExcludeSubfolders, UpdateFlagCommand::Reset);
});
m_mainUserControl.ToggleButtonIncludeSubfolders().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(ExcludeSubfolders, UpdateFlagCommand::Set);
});
// CheckBox EnumerateItems
m_mainUserControl.ToggleButtonEnumerateItems().Checked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
ValidateFlags(EnumerateItems);
UpdateFlag(EnumerateItems, UpdateFlagCommand::Set);
});
m_mainUserControl.ToggleButtonEnumerateItems().Unchecked([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
UpdateFlag(EnumerateItems, UpdateFlagCommand::Reset);
});
// ButtonSettings
m_mainUserControl.ButtonSettings().Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
OpenSettingsApp();
});
}
void AppWindow::ToggleItem(int32_t id, bool checked)
{
CComPtr<IPowerRenameItem> spItem;
m_prManager->GetItemById(id, &spItem);
spItem->PutSelected(checked);
UpdateCounts();
}
void AppWindow::ToggleAll()
{
UINT itemCount = 0;
m_prManager->GetItemCount(&itemCount);
bool selected = m_mainUserControl.CheckBoxSelectAll().IsChecked().GetBoolean();
for (UINT i = 0; i < itemCount; i++)
{
CComPtr<IPowerRenameItem> spItem;
if (SUCCEEDED(m_prManager->GetItemByIndex(i, &spItem)))
{
spItem->PutSelected(selected);
}
}
UpdateCounts();
}
void AppWindow::SwitchView()
{
m_prManager->SwitchFilter(0);
PopulateExplorerItems();
}
void AppWindow::Rename(bool closeWindow)
{
if (m_prManager)
{
m_prManager->Rename(m_window, closeWindow);
}
// Persist the current settings. We only do this when
// a rename is actually performed. Not when the user
// closes/cancels the dialog.
WriteSettings();
}
HRESULT AppWindow::ReadSettings()
{
// Check if we should read flags from settings
// or the defaults from the manager.
DWORD flags = 0;
if (CSettingsInstance().GetPersistState())
{
flags = CSettingsInstance().GetFlags();
m_mainUserControl.AutoSuggestBoxSearch().Text(CSettingsInstance().GetSearchText().c_str());
m_mainUserControl.AutoSuggestBoxReplace().Text(CSettingsInstance().GetReplaceText().c_str());
}
else
{
m_prManager->GetFlags(&flags);
}
m_prManager->PutFlags(flags);
SetCheckboxesFromFlags(flags);
return S_OK;
}
HRESULT AppWindow::WriteSettings()
{
// Check if we should store our settings
if (CSettingsInstance().GetPersistState())
{
DWORD flags = 0;
m_prManager->GetFlags(&flags);
CSettingsInstance().SetFlags(flags);
winrt::hstring searchTerm = m_mainUserControl.AutoSuggestBoxSearch().Text();
CSettingsInstance().SetSearchText(std::wstring{ searchTerm });
if (CSettingsInstance().GetMRUEnabled() && m_searchMRU)
{
CComPtr<IPowerRenameMRU> spSearchMRU;
if (SUCCEEDED(m_searchMRU->QueryInterface(IID_PPV_ARGS(&spSearchMRU))))
{
spSearchMRU->AddMRUString(searchTerm.c_str());
}
}
winrt::hstring replaceTerm = m_mainUserControl.AutoSuggestBoxReplace().Text();
CSettingsInstance().SetReplaceText(std::wstring{ replaceTerm });
if (CSettingsInstance().GetMRUEnabled() && m_replaceMRU)
{
CComPtr<IPowerRenameMRU> spReplaceMRU;
if (SUCCEEDED(m_replaceMRU->QueryInterface(IID_PPV_ARGS(&spReplaceMRU))))
{
spReplaceMRU->AddMRUString(replaceTerm.c_str());
}
}
Trace::SettingsChanged();
}
return S_OK;
}
HRESULT AppWindow::OpenSettingsApp()
{
std::wstring path = get_module_folderpath(g_hostHInst);
path += L"\\..\\..\\PowerToys.exe";
std::wstring openSettings = L"--open-settings=PowerRename";
CString commandLine;
commandLine.Format(_T("\"%s\""), path.c_str());
commandLine.AppendFormat(_T(" %s"), openSettings.c_str());
int nSize = commandLine.GetLength() + 1;
LPTSTR lpszCommandLine = new TCHAR[nSize];
_tcscpy_s(lpszCommandLine, nSize, commandLine);
STARTUPINFO startupInfo;
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
startupInfo.cb = sizeof(STARTUPINFO);
startupInfo.wShowWindow = SW_SHOWNORMAL;
PROCESS_INFORMATION processInformation;
// Start the resizer
CreateProcess(
NULL,
lpszCommandLine,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&startupInfo,
&processInformation);
delete[] lpszCommandLine;
if (!CloseHandle(processInformation.hProcess))
{
return HRESULT_FROM_WIN32(GetLastError());
}
if (!CloseHandle(processInformation.hThread))
{
return HRESULT_FROM_WIN32(GetLastError());
}
return S_OK;
}
void AppWindow::SetCheckboxesFromFlags(DWORD flags)
{
if (flags & CaseSensitive)
{
m_mainUserControl.CheckBoxCaseSensitive().IsChecked(true);
}
if (flags & MatchAllOccurences)
{
m_mainUserControl.CheckBoxMatchAll().IsChecked(true);
}
if (flags & UseRegularExpressions)
{
m_mainUserControl.CheckBoxRegex().IsChecked(true);
}
if (flags & EnumerateItems)
{
m_mainUserControl.ToggleButtonEnumerateItems().IsChecked(true);
}
if (flags & ExcludeFiles)
{
m_mainUserControl.ToggleButtonIncludeFiles().IsChecked(false);
}
if (flags & ExcludeFolders)
{
m_mainUserControl.ToggleButtonIncludeFolders().IsChecked(false);
}
if (flags & ExcludeSubfolders)
{
m_mainUserControl.ToggleButtonIncludeSubfolders().IsChecked(false);
}
if (flags & NameOnly)
{
m_mainUserControl.ComboBoxRenameParts().SelectedIndex(1);
}
else if (flags & ExtensionOnly)
{
m_mainUserControl.ComboBoxRenameParts().SelectedIndex(2);
}
if (flags & Uppercase)
{
m_mainUserControl.ToggleButtonUpperCase().IsChecked(true);
}
else if (flags & Lowercase)
{
m_mainUserControl.ToggleButtonLowerCase().IsChecked(true);
}
else if (flags & Titlecase)
{
m_mainUserControl.ToggleButtonTitleCase().IsChecked(true);
}
else if (flags & Capitalized)
{
m_mainUserControl.ToggleButtonCapitalize().IsChecked(true);
}
}
void AppWindow::UpdateCounts()
{
// This method is CPU intensive. We disable it during certain operations
// for performance reasons.
if (m_disableCountUpdate)
{
return;
}
UINT selectedCount = 0;
UINT renamingCount = 0;
if (m_prManager)
{
m_prManager->GetSelectedItemCount(&selectedCount);
m_prManager->GetRenameItemCount(&renamingCount);
}
if (m_selectedCount != selectedCount ||
m_renamingCount != renamingCount)
{
m_selectedCount = selectedCount;
m_renamingCount = renamingCount;
// Update counts UI elements if/when added
// Update Rename button state
m_mainUserControl.UIUpdatesItem().ButtonRenameEnabled(renamingCount > 0);
}
}
HRESULT AppWindow::OnItemAdded(_In_ IPowerRenameItem* renameItem)
{
return S_OK;
}
HRESULT AppWindow::OnUpdate(_In_ IPowerRenameItem* renameItem)
{
int id;
HRESULT hr = renameItem->GetId(&id);
if (SUCCEEDED(hr))
{
PWSTR newName = nullptr;
hr = renameItem->GetNewName(&newName);
if (SUCCEEDED(hr))
{
hstring newNameStr = newName == nullptr ? hstring{} : newName;
m_mainUserControl.UpdateExplorerItem(id, newNameStr);
}
}
UpdateCounts();
return S_OK;
}
HRESULT AppWindow::OnRename(_In_ IPowerRenameItem* renameItem)
{
int id;
HRESULT hr = renameItem->GetId(&id);
if (SUCCEEDED(hr))
{
PWSTR newName = nullptr;
hr = renameItem->GetOriginalName(&newName);
if (SUCCEEDED(hr))
{
hstring newNameStr = newName == nullptr ? hstring{} : newName;
m_mainUserControl.UpdateRenamedExplorerItem(id, newNameStr);
}
}
UpdateCounts();
return S_OK;
}
HRESULT AppWindow::OnError(_In_ IPowerRenameItem* renameItem)
{
return S_OK;
}
HRESULT AppWindow::OnRegExStarted(_In_ DWORD threadId)
{
return S_OK;
}
HRESULT AppWindow::OnRegExCanceled(_In_ DWORD threadId)
{
return S_OK;
}
HRESULT AppWindow::OnRegExCompleted(_In_ DWORD threadId)
{
if (m_flagValidationInProgress)
{
m_flagValidationInProgress = false;
}
else
{
DWORD filter = 0;
m_prManager->GetFilter(&filter);
if (filter == PowerRenameFilters::ShouldRename)
{
m_mainUserControl.ExplorerItems().Clear();
PopulateExplorerItems();
}
}
return S_OK;
}
HRESULT AppWindow::OnRenameStarted()
{
return S_OK;
}
HRESULT AppWindow::OnRenameCompleted(bool closeUIWindowAfterRenaming)
{
if (closeUIWindowAfterRenaming)
{
// Close the window
PostMessage(m_window, WM_CLOSE, (WPARAM)0, (LPARAM)0);
}
else
{
// Force renaming work to start so newly renamed items are processed right away
SearchReplaceChanged(true);
}
return S_OK;
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
#define BUFSIZE 4096 * 4
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
if (hStdin == INVALID_HANDLE_VALUE)
ExitProcess(1);
BOOL bSuccess;
WCHAR chBuf[BUFSIZE];
DWORD dwRead;
std::vector<std::wstring> files;
for (;;)
{
// Read from standard input and stop on error or no data.
bSuccess = ReadFile(hStdin, chBuf, BUFSIZE * sizeof(wchar_t), &dwRead, NULL);
if (!bSuccess || dwRead == 0)
break;
std::wstring inputBatch{ chBuf, dwRead / sizeof(wchar_t) };
std::wstringstream ss(inputBatch);
std::wstring item;
wchar_t delimiter = '?';
while (std::getline(ss, item, delimiter))
{
files.push_back(item);
}
if (!bSuccess)
break;
}
g_hostHInst = hInstance;
winrt::init_apartment(winrt::apartment_type::single_threaded);
winrt::PowerRenameUILib::App app;
const auto result = AppWindow::Show(hInstance, files);
app.Close();
}

View File

@ -0,0 +1,153 @@
#pragma once
#include "pch.h"
#include "resource.h"
#include "XamlBridge.h"
#include <PowerRenameEnum.h>
#include <PowerRenameItem.h>
#include <PowerRenameManager.h>
#include <PowerRenameInterfaces.h>
#include <PowerRenameMRU.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.system.h>
#pragma push_macro("GetCurrentTime")
#undef GetCurrentTime
#include <winrt/windows.ui.xaml.hosting.h>
#pragma pop_macro("GetCurrentTime")
#include <windows.ui.xaml.hosting.desktopwindowxamlsource.h>
#include <winrt/windows.ui.xaml.controls.h>
#include <winrt/windows.ui.xaml.controls.primitives.h>
#include <winrt/Windows.ui.xaml.media.h>
#include <winrt/Windows.ui.xaml.data.h>
#include <winrt/Windows.UI.Core.h>
#include <winrt/PowerRenameUILib.h>
using namespace winrt;
using namespace Windows::UI;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Composition;
using namespace Windows::UI::Xaml::Hosting;
using namespace Windows::Foundation::Numerics;
using namespace Windows::UI::Xaml::Controls;
class AppWindow : public DesktopWindowT<AppWindow>
{
public:
// Proxy class to Advise() PRManager, as AppWindow can't implement IPowerRenameManagerEvents
class UIHostPowerRenameManagerEvents : public IPowerRenameManagerEvents
{
public:
UIHostPowerRenameManagerEvents(AppWindow* app) :
m_refCount{ 1 }, m_app{ app }
{
}
IFACEMETHODIMP_(ULONG)
AddRef()
{
return InterlockedIncrement(&m_refCount);
}
IFACEMETHODIMP_(ULONG)
Release()
{
long refCount = InterlockedDecrement(&m_refCount);
if (refCount == 0)
{
delete this;
}
return refCount;
}
IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _Outptr_ void** ppv)
{
static const QITAB qit[] = {
QITABENT(UIHostPowerRenameManagerEvents, IPowerRenameManagerEvents),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
}
HRESULT OnItemAdded(_In_ IPowerRenameItem* renameItem) override { return m_app->OnItemAdded(renameItem); }
HRESULT OnUpdate(_In_ IPowerRenameItem* renameItem) override { return m_app->OnUpdate(renameItem); }
HRESULT OnRename(_In_ IPowerRenameItem* renameItem) override { return m_app->OnRename(renameItem); }
HRESULT OnError(_In_ IPowerRenameItem* renameItem) override { return m_app->OnError(renameItem); }
HRESULT OnRegExStarted(_In_ DWORD threadId) override { return m_app->OnRegExStarted(threadId); }
HRESULT OnRegExCanceled(_In_ DWORD threadId) override { return m_app->OnRegExCanceled(threadId); }
HRESULT OnRegExCompleted(_In_ DWORD threadId) override { return m_app->OnRegExCompleted(threadId); }
HRESULT OnRenameStarted() override { return m_app->OnRenameStarted(); }
HRESULT OnRenameCompleted(bool closeUIWindowAfterRenaming) override { return m_app->OnRenameCompleted(closeUIWindowAfterRenaming); }
private:
long m_refCount;
AppWindow* m_app;
};
static int Show(HINSTANCE hInstance, std::vector<std::wstring> files);
LRESULT MessageHandler(UINT message, WPARAM wParam, LPARAM lParam) noexcept;
private:
enum class UpdateFlagCommand
{
Set = 0,
Reset
};
AppWindow(HINSTANCE hInstance, std::vector<std::wstring> files) noexcept;
void CreateAndShowWindow();
bool OnCreate(HWND, LPCREATESTRUCT) noexcept;
void OnCommand(HWND, int id, HWND hwndControl, UINT codeNotify) noexcept;
void OnDestroy(HWND hwnd) noexcept;
void OnResize(HWND, UINT state, int cx, int cy) noexcept;
HRESULT CreateShellItemArrayFromPaths(std::vector<std::wstring> files, IShellItemArray** shellItemArray);
void PopulateExplorerItems();
HRESULT InitAutoComplete();
HRESULT EnumerateShellItems(_In_ IEnumShellItems* enumShellItems);
void SearchReplaceChanged(bool forceRenaming = false);
void ValidateFlags(PowerRenameFlags flag);
void UpdateFlag(PowerRenameFlags flag, UpdateFlagCommand command);
void SetHandlers();
void ToggleItem(int32_t id, bool checked);
void ToggleAll();
void SwitchView();
void Rename(bool closeWindow);
HRESULT ReadSettings();
HRESULT WriteSettings();
HRESULT OpenSettingsApp();
void SetCheckboxesFromFlags(DWORD flags);
void UpdateCounts();
HRESULT OnItemAdded(_In_ IPowerRenameItem* renameItem);
HRESULT OnUpdate(_In_ IPowerRenameItem* renameItem);
HRESULT OnRename(_In_ IPowerRenameItem* renameItem);
HRESULT OnError(_In_ IPowerRenameItem* renameItem);
HRESULT OnRegExStarted(_In_ DWORD threadId);
HRESULT OnRegExCanceled(_In_ DWORD threadId);
HRESULT OnRegExCompleted(_In_ DWORD threadId);
HRESULT OnRenameStarted();
HRESULT OnRenameCompleted(bool closeUIWindowAfterRenaming);
wil::unique_haccel m_accelerators;
const HINSTANCE m_instance;
HWND m_xamlIsland{};
HWND m_window{};
winrt::PowerRenameUILib::MainWindow m_mainUserControl{ nullptr };
bool m_disableCountUpdate = false;
CComPtr<IPowerRenameManager> m_prManager;
CComPtr<IUnknown> m_dataSource;
CComPtr<IPowerRenameEnum> m_prEnum;
UIHostPowerRenameManagerEvents m_managerEvents;
DWORD m_cookie = 0;
CComPtr<IPowerRenameMRU> m_searchMRU;
CComPtr<IPowerRenameMRU> m_replaceMRU;
UINT m_selectedCount = 0;
UINT m_renamingCount = 0;
bool m_flagValidationInProgress = false;
};

View File

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 115 KiB

View File

@ -0,0 +1,150 @@
//Microsoft Visual C++ generated resource script.
⼀⼀ഀ<EFBFBD>
⌀椀渀挀氀甀搀攀 ∀爀攀猀漀甀爀挀攀⸀栀∀ഀ<EFBFBD>
<EFBFBD>
⌀搀攀昀椀渀攀 䄀倀匀吀唀䐀䤀伀开刀䔀䄀䐀伀一䰀夀开匀夀䴀䈀伀䰀匀ഀ<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䜀攀渀攀爀愀琀攀搀 昀爀漀洀 琀栀攀 吀䔀堀吀䤀一䌀䰀唀䐀䔀 爀攀猀漀甀爀挀攀⸀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⌀椀昀渀搀攀昀 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
⌀椀渀挀氀甀搀攀 ∀琀愀爀最攀琀瘀攀爀⸀栀∀ഀ<EFBFBD>
⌀攀渀搀椀昀ഀ<EFBFBD>
⌀搀攀昀椀渀攀 䄀倀匀吀唀䐀䤀伀开䠀䤀䐀䐀䔀一开匀夀䴀䈀伀䰀匀ഀ<EFBFBD>
⌀椀渀挀氀甀搀攀 ∀眀椀渀搀漀眀猀⸀栀∀ഀ<EFBFBD>
⌀甀渀搀攀昀 䄀倀匀吀唀䐀䤀伀开䠀䤀䐀䐀䔀一开匀夀䴀䈀伀䰀匀ഀ<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⌀甀渀搀攀昀 䄀倀匀吀唀䐀䤀伀开刀䔀䄀䐀伀一䰀夀开匀夀䴀䈀伀䰀匀ഀ<EFBFBD>
<EFBFBD>
⌀椀昀 ℀搀攀昀椀渀攀搀䄀䘀堀开刀䔀匀伀唀刀䌀䔀开䐀䰀䰀⤀ 簀簀 搀攀昀椀渀攀搀䄀䘀堀开吀䄀刀䜀开䔀一唀⤀ഀ<EFBFBD>
䰀䄀一䜀唀䄀䜀䔀 㤀Ⰰ ㄀ഀ<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䤀挀漀渀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
<EFBFBD>
⼀⼀ 䤀挀漀渀 眀椀琀栀 氀漀眀攀猀琀 䤀䐀 瘀愀氀甀攀 瀀氀愀挀攀搀 昀椀爀猀琀 琀漀 攀渀猀甀爀攀 愀瀀瀀氀椀挀愀琀椀漀渀 椀挀漀渀ഀ<EFBFBD>
⼀⼀ 爀攀洀愀椀渀猀 挀漀渀猀椀猀琀攀渀琀 漀渀 愀氀氀 猀礀猀琀攀洀猀⸀ഀ<EFBFBD>
<EFBFBD>
䤀䐀䤀开倀伀圀䔀刀刀䔀一䄀䴀䔀唀䤀䠀伀匀吀       䤀䌀伀一         ∀倀漀眀攀爀刀攀渀愀洀攀唀䤀䠀漀猀琀⸀椀挀漀∀ഀ<EFBFBD>
䤀䐀䤀开匀䴀䄀䰀䰀                   䤀䌀伀一         ∀猀洀愀氀氀⸀椀挀漀∀ഀ<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䴀攀渀甀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
<EFBFBD>
䤀䐀䌀开倀伀圀䔀刀刀䔀一䄀䴀䔀唀䤀䠀伀匀吀 䴀䔀一唀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD>
    倀伀倀唀倀 ∀☀䘀椀氀攀∀ഀ<EFBFBD>
    䈀䔀䜀䤀一ഀ<EFBFBD>
        䴀䔀一唀䤀吀䔀䴀 ∀䔀☀砀椀琀∀Ⰰ                䤀䐀䴀开䔀堀䤀吀ഀ<EFBFBD>
    䔀一䐀ഀ<EFBFBD>
    倀伀倀唀倀 ∀☀䠀攀氀瀀∀ഀ<EFBFBD>
    䈀䔀䜀䤀一ഀ<EFBFBD>
        䴀䔀一唀䤀吀䔀䴀 ∀☀䄀戀漀甀琀 ⸀⸀⸀∀Ⰰ           䤀䐀䴀开䄀䈀伀唀吀ഀ<EFBFBD>
    䔀一䐀ഀ<EFBFBD>
䔀一䐀ഀ<EFBFBD>
<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䄀挀挀攀氀攀爀愀琀漀爀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
<EFBFBD>
䤀䐀䌀开倀伀圀䔀刀刀䔀一䄀䴀䔀唀䤀䠀伀匀吀 䄀䌀䌀䔀䰀䔀刀䄀吀伀刀匀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD>
    ∀㼀∀Ⰰ            䤀䐀䴀开䄀䈀伀唀吀Ⰰ              䄀匀䌀䤀䤀Ⰰ  䄀䰀吀ഀ<EFBFBD>
    ∀⼀∀Ⰰ            䤀䐀䴀开䄀䈀伀唀吀Ⰰ              䄀匀䌀䤀䤀Ⰰ  䄀䰀吀ഀ<EFBFBD>
䔀一䐀ഀ<EFBFBD>
<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䐀椀愀氀漀最ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
<EFBFBD>
䤀䐀䐀开䄀䈀伀唀吀䈀伀堀 䐀䤀䄀䰀伀䜀䔀堀     ㄀㜀  㘀㈀ഀ<EFBFBD>
匀吀夀䰀䔀 䐀匀开匀䔀吀䘀伀一吀  䐀匀开䴀伀䐀䄀䰀䘀刀䄀䴀䔀  䐀匀开䘀䤀堀䔀䐀匀夀匀  圀匀开倀伀倀唀倀  圀匀开䌀䄀倀吀䤀伀一  圀匀开匀夀匀䴀䔀一唀ഀ<EFBFBD>
䌀䄀倀吀䤀伀一 ∀䄀戀漀甀琀 倀漀眀攀爀刀攀渀愀洀攀唀䤀䠀漀猀琀∀ഀ<EFBFBD>
䘀伀一吀 㠀Ⰰ ∀䴀匀 匀栀攀氀氀 䐀氀最∀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD>
    䤀䌀伀一            䤀䐀刀开䴀䄀䤀一䘀刀䄀䴀䔀Ⰰ䤀䐀䌀开匀吀䄀吀䤀䌀Ⰰ㄀㐀Ⰰ㄀㐀Ⰰ㈀㄀Ⰰ㈀ <EFBFBD>
    䰀吀䔀堀吀           ∀倀漀眀攀爀刀攀渀愀洀攀唀䤀䠀漀猀琀Ⰰ 嘀攀爀猀椀漀渀 ㄀⸀ ∀Ⰰ䤀䐀䌀开匀吀䄀吀䤀䌀Ⰰ㐀㈀Ⰰ㄀㐀Ⰰ㄀㄀㐀Ⰰ㠀Ⰰ匀匀开一伀倀刀䔀䘀䤀堀ഀ<EFBFBD>
    䰀吀䔀堀吀           ∀䌀漀瀀礀爀椀最栀琀 挀⤀  ㈀㄀∀Ⰰ䤀䐀䌀开匀吀䄀吀䤀䌀Ⰰ㐀㈀Ⰰ㈀㘀Ⰰ㄀㄀㐀Ⰰ㠀ഀ<EFBFBD>
    䐀䔀䘀倀唀匀䠀䈀唀吀吀伀一   ∀伀䬀∀Ⰰ䤀䐀伀䬀Ⰰ㄀㄀㌀Ⰰ㐀㄀Ⰰ㔀 Ⰰ㄀㐀Ⰰ圀匀开䜀刀伀唀倀ഀ<EFBFBD>
䔀一䐀ഀ<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䐀䔀匀䤀䜀一䤀一䘀伀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
<EFBFBD>
⌀椀昀搀攀昀 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
䜀唀䤀䐀䔀䰀䤀一䔀匀 䐀䔀匀䤀䜀一䤀一䘀伀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD>
    䤀䐀䐀开䄀䈀伀唀吀䈀伀堀Ⰰ 䐀䤀䄀䰀伀䜀ഀ<EFBFBD>
    䈀䔀䜀䤀一ഀ<EFBFBD>
        䰀䔀䘀吀䴀䄀刀䜀䤀一Ⰰ 㜀ഀ<EFBFBD>
        刀䤀䜀䠀吀䴀䄀刀䜀䤀一Ⰰ ㄀㘀㌀ഀ<EFBFBD>
        吀伀倀䴀䄀刀䜀䤀一Ⰰ 㜀ഀ<EFBFBD>
        䈀伀吀吀伀䴀䴀䄀刀䜀䤀一Ⰰ 㔀㔀ഀ<EFBFBD>
    䔀一䐀ഀ<EFBFBD>
䔀一䐀ഀ<EFBFBD>
⌀攀渀搀椀昀    ⼀⼀ 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
<EFBFBD>
⌀椀昀搀攀昀 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 吀䔀堀吀䤀一䌀䰀唀䐀䔀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
 吀䔀堀吀䤀一䌀䰀唀䐀䔀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD>
    ∀爀攀猀漀甀爀挀攀⸀栀尀 ∀ഀ<EFBFBD>
䔀一䐀ഀ<EFBFBD>
<EFBFBD>
 吀䔀堀吀䤀一䌀䰀唀䐀䔀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD>
    ∀⌀椀昀渀搀攀昀 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀尀爀尀渀∀ഀ<EFBFBD>
    ∀⌀椀渀挀氀甀搀攀 ∀∀琀愀爀最攀琀瘀攀爀⸀栀∀∀尀爀尀渀∀ഀ<EFBFBD>
    ∀⌀攀渀搀椀昀尀爀尀渀∀ഀ<EFBFBD>
    ∀⌀搀攀昀椀渀攀 䄀倀匀吀唀䐀䤀伀开䠀䤀䐀䐀䔀一开匀夀䴀䈀伀䰀匀尀爀尀渀∀ഀ<EFBFBD>
    ∀⌀椀渀挀氀甀搀攀 ∀∀眀椀渀搀漀眀猀⸀栀∀∀尀爀尀渀∀ഀ<EFBFBD>
    ∀⌀甀渀搀攀昀 䄀倀匀吀唀䐀䤀伀开䠀䤀䐀䐀䔀一开匀夀䴀䈀伀䰀匀尀爀尀渀∀ഀ<EFBFBD>
    ∀尀 ∀ഀ<EFBFBD>
䔀一䐀ഀ<EFBFBD>
<EFBFBD>
 吀䔀堀吀䤀一䌀䰀唀䐀䔀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD>
    ∀尀爀尀渀∀ഀ<EFBFBD>
    ∀尀 ∀ഀ<EFBFBD>
䔀一䐀ഀ<EFBFBD>
<EFBFBD>
⌀攀渀搀椀昀    ⼀⼀ 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 匀琀爀椀渀最 吀愀戀氀攀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
<EFBFBD>
匀吀刀䤀一䜀吀䄀䈀䰀䔀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD>
   䤀䐀䌀开倀伀圀䔀刀刀䔀一䄀䴀䔀唀䤀䠀伀匀吀   ∀倀伀圀䔀刀刀䔀一䄀䴀䔀唀䤀䠀伀匀吀∀ഀ<EFBFBD>
   䤀䐀匀开䄀倀倀开吀䤀吀䰀䔀       ∀倀漀眀攀爀刀攀渀愀洀攀∀ഀ<EFBFBD>
䔀一䐀ഀ<EFBFBD>
<EFBFBD>
⌀攀渀搀椀昀ഀ<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
<EFBFBD>
<EFBFBD>
<EFBFBD>
⌀椀昀渀搀攀昀 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䜀攀渀攀爀愀琀攀搀 昀爀漀洀 琀栀攀 吀䔀堀吀䤀一䌀䰀唀䐀䔀 爀攀猀漀甀爀挀攀⸀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⌀攀渀搀椀昀    ⼀⼀ 渀漀琀 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
<EFBFBD>

View File

@ -0,0 +1,165 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.SDK.6.1.2\build\Microsoft.Toolkit.Win32.UI.SDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.SDK.6.1.2\build\Microsoft.Toolkit.Win32.UI.SDK.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{f7ec4e6c-19ca-4fbd-9918-b8ac5fef4f63}</ProjectGuid>
<RootNamespace>PowerRenameUIHost</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
<TargetPlatformMinVersion>$(WindowsTargetPlatformVersion)</TargetPlatformMinVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WindowsAppContainer>false</WindowsAppContainer>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<WindowsAppContainer>false</WindowsAppContainer>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"></ImportGroup>
<ImportGroup Label="Shared"></ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\Solution.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\..\..\Solution.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\PowerRename\</OutDir>
<TargetName>PowerRename</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\PowerRename\</OutDir>
<TargetName>PowerRename</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\;$(ProjectDir)..\..\..\common\Telemetry;$(ProjectDir)..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Manifest>
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<TreatWarningAsError>true</TreatWarningAsError>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\;$(ProjectDir)..\..\..\common\Telemetry;$(ProjectDir)..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<Manifest>
<EnableDpiAwareness>PerMonitorHighDPIAware</EnableDpiAwareness>
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="PowerRenameUIHost.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="XamlBridge.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="PowerRenameUIHost.cpp" />
<ClCompile Include="XamlBridge.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="PowerRenameUIHost.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="PowerRenameUIHost.ico" />
<Image Include="small.ico" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Manifest Include="app.manifest" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.SDK.6.1.2\build\Microsoft.Toolkit.Win32.UI.SDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.SDK.6.1.2\build\Microsoft.Toolkit.Win32.UI.SDK.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210803.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210803.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\..\packages\boost.1.72.0.0\build\boost.targets" Condition="Exists('..\..\..\..\packages\boost.1.72.0.0\build\boost.targets')" />
<Import Project="..\..\..\..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets" Condition="Exists('..\..\..\..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.SDK.6.1.2\build\Microsoft.Toolkit.Win32.UI.SDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.SDK.6.1.2\build\Microsoft.Toolkit.Win32.UI.SDK.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.SDK.6.1.2\build\Microsoft.Toolkit.Win32.UI.SDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.SDK.6.1.2\build\Microsoft.Toolkit.Win32.UI.SDK.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210803.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.210803.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\boost.1.72.0.0\build\boost.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost.1.72.0.0\build\boost.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\boost_regex-vc142.1.72.0.0\build\boost_regex-vc142.targets'))" />
</Target>
<PropertyGroup>
<AppProjectName>PowerRenameUILib</AppProjectName>
</PropertyGroup>
<PropertyGroup>
<AppIncludeDirectories>$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\;$(SolutionDir)$(Platform)\$(Configuration)\obj\$(ProjectName)\Generated Files\;</AppIncludeDirectories>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\$(AppProjectName)\$(AppProjectName).vcxproj" />
<ProjectReference Include="..\lib\PowerRenameLib.vcxproj">
<Project>{51920f1f-c28c-4adf-8660-4238766796c2}</Project>
</ProjectReference>
</ItemGroup>
</Project>

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PowerRenameUIHost.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="XamlBridge.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="PowerRenameUIHost.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="XamlBridge.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="PowerRenameUIHost.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="PowerRenameUIHost.ico">
<Filter>Resource Files</Filter>
</Image>
<Image Include="small.ico">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Manifest Include="app.manifest" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,30 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by PowerRenameUIHost.rc
#define IDS_APP_TITLE 103
#define IDR_MAINFRAME 128
#define IDD_POWERRENAMEUIHOST_DIALOG 102
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_POWERRENAMEUIHOST 107
#define IDI_SMALL 108
#define IDC_POWERRENAMEUIHOST 109
#define IDC_MYICON 2
#ifndef IDC_STATIC
#define IDC_STATIC -1
#endif
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 130
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif

View File

@ -0,0 +1,249 @@
#include "pch.h"
#include "XamlBridge.h"
#include "Resource.h"
#include <exception>
bool DesktopWindow::FilterMessage(const MSG* msg)
{
// When multiple child windows are present it is needed to pre dispatch messages to all
// DesktopWindowXamlSource instances so keyboard accelerators and
// keyboard focus work correctly.
for (auto& xamlSource : m_xamlSources)
{
BOOL xamlSourceProcessedMessage = FALSE;
winrt::check_hresult(xamlSource.as<IDesktopWindowXamlSourceNative2>()->PreTranslateMessage(msg, &xamlSourceProcessedMessage));
if (xamlSourceProcessedMessage != FALSE)
{
return true;
}
}
return false;
}
const auto static invalidReason = static_cast<winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason>(-1);
winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason GetReasonFromKey(WPARAM key)
{
auto reason = invalidReason;
if (key == VK_TAB)
{
byte keyboardState[256] = {};
WINRT_VERIFY(::GetKeyboardState(keyboardState));
reason = (keyboardState[VK_SHIFT] & 0x80) ?
winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Last :
winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::First;
}
else if (key == VK_LEFT)
{
reason = winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Left;
}
else if (key == VK_RIGHT)
{
reason = winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Right;
}
else if (key == VK_UP)
{
reason = winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Up;
}
else if (key == VK_DOWN)
{
reason = winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Down;
}
return reason;
}
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource DesktopWindow::GetNextFocusedIsland(const MSG* msg)
{
if (msg->message == WM_KEYDOWN)
{
const auto key = msg->wParam;
auto reason = GetReasonFromKey(key);
if (reason != invalidReason)
{
const BOOL previous =
(reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::First ||
reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Down ||
reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Right) ?
false :
true;
const auto currentFocusedWindow = ::GetFocus();
const auto nextElement = ::GetNextDlgTabItem(m_window.get(), currentFocusedWindow, previous);
for (auto& xamlSource : m_xamlSources)
{
HWND islandWnd{};
winrt::check_hresult(xamlSource.as<IDesktopWindowXamlSourceNative>()->get_WindowHandle(&islandWnd));
if (nextElement == islandWnd)
{
return xamlSource;
}
}
}
}
return nullptr;
}
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource DesktopWindow::GetFocusedIsland()
{
for (auto& xamlSource : m_xamlSources)
{
if (xamlSource.HasFocus())
{
return xamlSource;
}
}
return nullptr;
}
bool DesktopWindow::NavigateFocus(MSG* msg)
{
if (const auto nextFocusedIsland = GetNextFocusedIsland(msg))
{
const auto previousFocusedWindow = ::GetFocus();
RECT rect = {};
WINRT_VERIFY(::GetWindowRect(previousFocusedWindow, &rect));
const auto nativeIsland = nextFocusedIsland.as<IDesktopWindowXamlSourceNative>();
HWND islandWnd = nullptr;
winrt::check_hresult(nativeIsland->get_WindowHandle(&islandWnd));
POINT pt = { rect.left, rect.top };
SIZE size = { rect.right - rect.left, rect.bottom - rect.top };
::ScreenToClient(islandWnd, &pt);
const auto hintRect = winrt::Windows::Foundation::Rect({ static_cast<float>(pt.x), static_cast<float>(pt.y), static_cast<float>(size.cx), static_cast<float>(size.cy) });
const auto reason = GetReasonFromKey(msg->wParam);
const auto request = winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationRequest(reason, hintRect);
m_lastFocusRequestId = request.CorrelationId();
const auto result = nextFocusedIsland.NavigateFocus(request);
return result.WasFocusMoved();
}
else
{
const bool islandIsFocused = GetFocusedIsland() != nullptr;
byte keyboardState[256] = {};
WINRT_VERIFY(::GetKeyboardState(keyboardState));
const bool isMenuModifier = keyboardState[VK_MENU] & 0x80;
if (islandIsFocused && !isMenuModifier)
{
return false;
}
const bool isDialogMessage = !!IsDialogMessage(m_window.get(), msg);
return isDialogMessage;
}
}
int DesktopWindow::MessageLoop(HACCEL accelerators)
{
MSG msg = {};
while (GetMessage(&msg, nullptr, 0, 0))
{
const bool processedMessage = FilterMessage(&msg);
if (!processedMessage && !TranslateAcceleratorW(msg.hwnd, accelerators, &msg))
{
if (!NavigateFocus(&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return static_cast<int>(msg.wParam);
}
static const WPARAM invalidKey = (WPARAM)-1;
WPARAM GetKeyFromReason(winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason reason)
{
auto key = invalidKey;
if (reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Last || reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::First)
{
key = VK_TAB;
}
else if (reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Left)
{
key = VK_LEFT;
}
else if (reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Right)
{
key = VK_RIGHT;
}
else if (reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Up)
{
key = VK_UP;
}
else if (reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Down)
{
key = VK_DOWN;
}
return key;
}
void DesktopWindow::OnTakeFocusRequested(winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource const& sender, winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSourceTakeFocusRequestedEventArgs const& args)
{
if (args.Request().CorrelationId() != m_lastFocusRequestId)
{
const auto reason = args.Request().Reason();
const BOOL previous =
(reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::First ||
reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Down ||
reason == winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Right) ?
false :
true;
const auto nativeXamlSource = sender.as<IDesktopWindowXamlSourceNative>();
HWND senderHwnd = nullptr;
winrt::check_hresult(nativeXamlSource->get_WindowHandle(&senderHwnd));
MSG msg = {};
msg.hwnd = senderHwnd;
msg.message = WM_KEYDOWN;
msg.wParam = GetKeyFromReason(reason);
if (!NavigateFocus(&msg))
{
const auto nextElement = ::GetNextDlgTabItem(m_window.get(), senderHwnd, previous);
::SetFocus(nextElement);
}
}
else
{
const auto request = winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationRequest(winrt::Windows::UI::Xaml::Hosting::XamlSourceFocusNavigationReason::Restore);
m_lastFocusRequestId = request.CorrelationId();
sender.NavigateFocus(request);
}
}
HWND DesktopWindow::CreateDesktopWindowsXamlSource(DWORD extraWindowStyles, const winrt::Windows::UI::Xaml::UIElement& content)
{
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource desktopSource;
auto interop = desktopSource.as<IDesktopWindowXamlSourceNative>();
// Parent the DesktopWindowXamlSource object to current window
winrt::check_hresult(interop->AttachToWindow(m_window.get()));
HWND xamlSourceWindow{}; // Lifetime controlled desktopSource
winrt::check_hresult(interop->get_WindowHandle(&xamlSourceWindow));
const DWORD style = GetWindowLongW(xamlSourceWindow, GWL_STYLE) | extraWindowStyles;
SetWindowLongW(xamlSourceWindow, GWL_STYLE, style);
desktopSource.Content(content);
m_takeFocusEventRevokers.push_back(desktopSource.TakeFocusRequested(winrt::auto_revoke, { this, &DesktopWindow::OnTakeFocusRequested }));
m_xamlSources.push_back(desktopSource);
return xamlSourceWindow;
}
void DesktopWindow::ClearXamlIslands()
{
for (auto& takeFocusRevoker : m_takeFocusEventRevokers)
{
takeFocusRevoker.revoke();
}
m_takeFocusEventRevokers.clear();
for (auto& xamlSource : m_xamlSources)
{
xamlSource.Close();
}
m_xamlSources.clear();
}

View File

@ -0,0 +1,108 @@
#pragma once
#include <unknwn.h> // To enable support for non-WinRT interfaces, unknwn.h must be included before any C++/WinRT headers.
#include <winrt/Windows.System.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#pragma push_macro("GetCurrentTime")
#undef GetCurrentTime
#include <winrt/Windows.UI.Xaml.Hosting.h>
#pragma pop_macro("GetCurrentTime")
#include <winrt/Windows.UI.Xaml.Markup.h>
#include <windows.ui.xaml.hosting.desktopwindowxamlsource.h>
#include <windowsx.h>
#include <wil/resource.h>
class DesktopWindow
{
protected:
int MessageLoop(HACCEL accelerators);
HWND CreateDesktopWindowsXamlSource(DWORD extraStyles, const winrt::Windows::UI::Xaml::UIElement& content);
void ClearXamlIslands();
HWND WindowHandle() const
{
return m_window.get();
}
static void OnNCCreate(HWND window, LPARAM lparam) noexcept
{
auto cs = reinterpret_cast<CREATESTRUCT*>(lparam);
auto that = static_cast<DesktopWindow*>(cs->lpCreateParams);
that->m_window.reset(window); // take ownership of the window
SetWindowLongPtrW(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that));
}
private:
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource GetFocusedIsland();
bool FilterMessage(const MSG* msg);
void OnTakeFocusRequested(winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource const& sender, winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSourceTakeFocusRequestedEventArgs const& args);
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource GetNextFocusedIsland(const MSG* msg);
bool NavigateFocus(MSG* msg);
wil::unique_hwnd m_window;
winrt::guid m_lastFocusRequestId;
std::vector<winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource::TakeFocusRequested_revoker> m_takeFocusEventRevokers;
std::vector<winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource> m_xamlSources;
};
template<typename T>
struct DesktopWindowT : public DesktopWindow
{
protected:
using base_type = DesktopWindowT<T>;
static LRESULT __stdcall WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept
{
if (message == WM_NCCREATE)
{
OnNCCreate(window, lparam);
}
else if (message == WM_NCDESTROY)
{
SetWindowLongPtrW(window, GWLP_USERDATA, 0);
}
else if (auto that = reinterpret_cast<T*>(GetWindowLongPtrW(window, GWLP_USERDATA)))
{
return that->MessageHandler(message, wparam, lparam);
}
return DefWindowProcW(window, message, wparam, lparam);
}
LRESULT MessageHandler(UINT message, WPARAM wParam, LPARAM lParam) noexcept
{
switch (message)
{
HANDLE_MSG(WindowHandle(), WM_DESTROY, OnDestroy);
HANDLE_MSG(WindowHandle(), WM_ACTIVATE, OnActivate);
HANDLE_MSG(WindowHandle(), WM_SETFOCUS, OnSetFocus);
}
return DefWindowProcW(WindowHandle(), message, wParam, lParam);
}
void OnDestroy(HWND)
{
ClearXamlIslands();
PostQuitMessage(0);
}
private:
void OnActivate(HWND, UINT state, HWND hwndActDeact, BOOL fMinimized)
{
if (state == WA_INACTIVE)
{
m_hwndLastFocus = GetFocus();
}
}
void OnSetFocus(HWND, HWND hwndOldFocus)
{
if (m_hwndLastFocus)
{
SetFocus(m_hwndLastFocus);
}
}
HWND m_hwndLastFocus = nullptr;
};

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmV3="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0">
<asmV3:file name="PowerRenameUILib.dll">
<activatableClass name="PowerRenameUILib.App" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
<activatableClass name="PowerRenameUILib.XamlMetadataProvider" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
<activatableClass name="PowerRenameUILib.MainWindow" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1" />
</asmV3:file>
</assembly>

View File

@ -0,0 +1,15 @@
// header.h : include file for standard system include files,
// or project specific include files
//
#pragma once
#include "targetver.h"
// #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="boost" version="1.72.0.0" targetFramework="native" />
<package id="boost_regex-vc142" version="1.72.0.0" targetFramework="native" />
<package id="Microsoft.Toolkit.Win32.UI.SDK" version="6.1.2" targetFramework="native" />
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.7" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.210803.1" targetFramework="native" />
</packages>

View File

@ -0,0 +1,5 @@
#pragma once
#include "framework.h"
#include <atlstr.h>
#include <stack>

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

View File

@ -0,0 +1,18 @@
#include "pch.h"
#include "App.h"
#include "App.g.cpp"
using namespace winrt;
using namespace Windows::UI::Xaml;
namespace winrt::PowerRenameUILib::implementation
{
App::App()
{
Initialize();
AddRef();
m_inner.as<::IUnknown>()->Release();
}
App::~App()
{
Close();
}
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "App.g.h"
#include "App.base.h"
namespace winrt::PowerRenameUILib::implementation
{
class App : public AppT2<App>
{
public:
App();
~App();
};
}
namespace winrt::PowerRenameUILib::factory_implementation
{
class App : public AppT<App, implementation::App>
{
};
}

View File

@ -0,0 +1,7 @@
namespace PowerRenameUILib
{
[default_interface] runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
{
App();
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,105 @@
#include "pch.h"
#include "ExplorerItem.h"
#include "ExplorerItem.g.cpp"
namespace winrt::PowerRenameUILib::implementation
{
ExplorerItem::ExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, bool checked) :
m_id{ id }, m_idStr{ std::to_wstring(id) }, m_original{ original }, m_renamed{ renamed }, m_type{ type }, m_checked{ checked }
{
if (m_type == static_cast<UINT>(ExplorerItemType::Folder))
{
m_children = winrt::single_threaded_observable_vector<PowerRenameUILib::ExplorerItem>();
}
}
int32_t ExplorerItem::Id()
{
return m_id;
}
hstring ExplorerItem::IdStr()
{
return m_idStr;
}
hstring ExplorerItem::Original()
{
return m_original;
}
void ExplorerItem::Original(hstring const& value)
{
if (m_original != value)
{
m_original = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Original" });
}
}
hstring ExplorerItem::Renamed()
{
return m_renamed;
}
void ExplorerItem::Renamed(hstring const& value)
{
if (m_renamed != value)
{
m_renamed = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Renamed" });
}
}
int32_t ExplorerItem::Type()
{
return m_type;
}
void ExplorerItem::Type(int32_t value)
{
if (m_type != value)
{
m_type = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Type" });
}
}
bool ExplorerItem::Checked()
{
return m_checked;
}
void ExplorerItem::Checked(bool value)
{
if (m_checked != value)
{
m_checked = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Checked" });
}
}
winrt::Windows::Foundation::Collections::IObservableVector<winrt::PowerRenameUILib::ExplorerItem> ExplorerItem::Children()
{
return m_children;
}
void ExplorerItem::Children(Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::ExplorerItem> const& value)
{
if (m_children != value)
{
m_children = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Children" });
}
}
winrt::event_token ExplorerItem::PropertyChanged(winrt::Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
return m_propertyChanged.add(handler);
}
void ExplorerItem::PropertyChanged(winrt::event_token const& token) noexcept
{
m_propertyChanged.remove(token);
}
}

View File

@ -0,0 +1,48 @@
#pragma once
#include "ExplorerItem.g.h"
namespace winrt::PowerRenameUILib::implementation
{
struct ExplorerItem : ExplorerItemT<ExplorerItem>
{
enum class ExplorerItemType
{
Folder = 0,
File = 1
};
ExplorerItem() = delete;
ExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, bool checked);
int32_t Id();
hstring IdStr();
hstring Original();
void Original(hstring const& value);
hstring Renamed();
void Renamed(hstring const& value);
int32_t Type();
void Type(int32_t value);
bool Checked();
void Checked(bool value);
Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::ExplorerItem> Children();
void Children(Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::ExplorerItem> const& value);
winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
void PropertyChanged(winrt::event_token const& token) noexcept;
private:
int32_t m_id;
hstring m_idStr;
winrt::hstring m_original;
winrt::hstring m_renamed;
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::ExplorerItem> m_children;
int32_t m_type;
bool m_checked;
winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
};
}
namespace winrt::PowerRenameUILib::factory_implementation
{
struct ExplorerItem : ExplorerItemT<ExplorerItem, implementation::ExplorerItem>
{
};
}

View File

@ -0,0 +1,14 @@
namespace PowerRenameUILib
{
runtimeclass ExplorerItem : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
ExplorerItem(Int32 id, String original, String renamed, Int32 type, Boolean checked);
Int32 Id { get; };
String IdStr { get; };
String Original;
String Renamed;
Int32 Type;
Boolean Checked;
Windows.Foundation.Collections.IObservableVector<ExplorerItem> Children;
}
}

View File

@ -0,0 +1,37 @@
#include "pch.h"
#include "ExplorerItemTemplateSelector.h"
#include "ExplorerItemTemplateSelector.g.cpp"
namespace winrt::PowerRenameUILib::implementation
{
Windows::UI::Xaml::DataTemplate ExplorerItemTemplateSelector::SelectTemplateCore(IInspectable const& item)
{
ExplorerItem explorerItem = (ExplorerItem&)item;
return explorerItem.Type() == 0 ? m_folderTemplate : m_fileTemplate;
}
Windows::UI::Xaml::DataTemplate ExplorerItemTemplateSelector::SelectTemplateCore(IInspectable const&, Windows::UI::Xaml::DependencyObject const&)
{
return Windows::UI::Xaml::DataTemplate();
}
winrt::Windows::UI::Xaml::DataTemplate ExplorerItemTemplateSelector::FolderTemplate()
{
return m_folderTemplate;
}
void ExplorerItemTemplateSelector::FolderTemplate(winrt::Windows::UI::Xaml::DataTemplate const& value)
{
m_folderTemplate = value;
}
winrt::Windows::UI::Xaml::DataTemplate ExplorerItemTemplateSelector::FileTemplate()
{
return m_fileTemplate;
}
void ExplorerItemTemplateSelector::FileTemplate(winrt::Windows::UI::Xaml::DataTemplate const& value)
{
m_fileTemplate = value;
}
}

View File

@ -0,0 +1,28 @@
#pragma once
#include "ExplorerItemTemplateSelector.g.h"
namespace winrt::PowerRenameUILib::implementation
{
struct ExplorerItemTemplateSelector : ExplorerItemTemplateSelectorT<ExplorerItemTemplateSelector>
{
ExplorerItemTemplateSelector() = default;
Windows::UI::Xaml::DataTemplate SelectTemplateCore(IInspectable const&);
Windows::UI::Xaml::DataTemplate SelectTemplateCore(IInspectable const&, Windows::UI::Xaml::DependencyObject const&);
winrt::Windows::UI::Xaml::DataTemplate FolderTemplate();
void FolderTemplate(winrt::Windows::UI::Xaml::DataTemplate const& value);
winrt::Windows::UI::Xaml::DataTemplate FileTemplate();
void FileTemplate(winrt::Windows::UI::Xaml::DataTemplate const& value);
private:
Windows::UI::Xaml::DataTemplate m_folderTemplate{ nullptr };
Windows::UI::Xaml::DataTemplate m_fileTemplate{ nullptr };
};
}
namespace winrt::PowerRenameUILib::factory_implementation
{
struct ExplorerItemTemplateSelector : ExplorerItemTemplateSelectorT<ExplorerItemTemplateSelector, implementation::ExplorerItemTemplateSelector>
{
};
}

View File

@ -0,0 +1,11 @@
namespace PowerRenameUILib
{
[bindable]
[default_interface] runtimeclass ExplorerItemTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector
{
ExplorerItemTemplateSelector();
Windows.UI.Xaml.DataTemplate FolderTemplate;
Windows.UI.Xaml.DataTemplate FileTemplate;
}
}

View File

@ -4,9 +4,9 @@
"LanguageSet": "Azure_Languages", "LanguageSet": "Azure_Languages",
"LocItems": [ "LocItems": [
{ {
"SourceFile": "src\\modules\\powerrename\\ui\\Resources.resx", "SourceFile": "src\\modules\\powerrename\\PowerRenameUILib\\Strings\\en-us\\Resources.resw",
"CopyOption": "LangIDOnName", "CopyOption": "LangIDOnName",
"OutputPath": "src\\modules\\powerrename\\ui" "OutputPath": "src\\modules\\powerrename\\PowerRenameUILib\\Strings"
} }
] ]
} }

View File

@ -0,0 +1,326 @@
#include "pch.h"
#include "MainWindow.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif
using namespace winrt;
using namespace Windows::UI::Xaml;
namespace winrt::PowerRenameUILib::implementation
{
MainWindow::MainWindow() :
m_allSelected{ true }
{
m_searchMRU = winrt::single_threaded_observable_vector<hstring>();
m_replaceMRU = winrt::single_threaded_observable_vector<hstring>();
m_explorerItems = winrt::single_threaded_observable_vector<PowerRenameUILib::ExplorerItem>();
m_searchRegExShortcuts = winrt::single_threaded_observable_vector<PowerRenameUILib::PatternSnippet>();
auto resourceLoader{ Windows::ApplicationModel::Resources::ResourceLoader::GetForCurrentView() };
m_searchRegExShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"\\.", resourceLoader.GetString(L"RegExCheatSheet_MatchAny")));
m_searchRegExShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"\\d", resourceLoader.GetString(L"RegExCheatSheet_MatchDigit")));
m_searchRegExShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"\\D", resourceLoader.GetString(L"RegExCheatSheet_MatchNonDigit")));
m_searchRegExShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"\\w", resourceLoader.GetString(L"RegExCheatSheet_MatchNonWS")));
m_searchRegExShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"\\S", resourceLoader.GetString(L"RegExCheatSheet_MatchWordChar")));
m_searchRegExShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"\\S+", resourceLoader.GetString(L"RegExCheatSheet_MatchSeveralWS")));
m_searchRegExShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"\\b", resourceLoader.GetString(L"RegExCheatSheet_MatchWordBoundary")));
m_dateTimeShortcuts = winrt::single_threaded_observable_vector<PowerRenameUILib::PatternSnippet>();
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$YYYY", resourceLoader.GetString(L"DateTimeCheatSheet_FullYear")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$YY", resourceLoader.GetString(L"DateTimeCheatSheet_YearLastTwoDigits")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$Y", resourceLoader.GetString(L"DateTimeCheatSheet_YearLastDigit")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$MMMM", resourceLoader.GetString(L"DateTimeCheatSheet_MonthName")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$MMM", resourceLoader.GetString(L"DateTimeCheatSheet_MonthNameAbbr")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$MM", resourceLoader.GetString(L"DateTimeCheatSheet_MonthDigitLZero")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$M", resourceLoader.GetString(L"DateTimeCheatSheet_MonthDigit")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$DDDD", resourceLoader.GetString(L"DateTimeCheatSheet_DayName")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$DDD", resourceLoader.GetString(L"DateTimeCheatSheet_DayNameAbbr")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$DD", resourceLoader.GetString(L"DateTimeCheatSheet_DayDigitLZero")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$D", resourceLoader.GetString(L"DateTimeCheatSheet_DayDigit")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$hh", resourceLoader.GetString(L"DateTimeCheatSheet_HoursLZero")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$h", resourceLoader.GetString(L"DateTimeCheatSheet_Hours")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$mm", resourceLoader.GetString(L"DateTimeCheatSheet_MinutesLZero")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$m", resourceLoader.GetString(L"DateTimeCheatSheet_Minutes")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$ss", resourceLoader.GetString(L"DateTimeCheatSheet_SecondsLZero")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$s", resourceLoader.GetString(L"DateTimeCheatSheet_Seconds")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$fff", resourceLoader.GetString(L"DateTimeCheatSheet_MilliSeconds3D")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$ff", resourceLoader.GetString(L"DateTimeCheatSheet_MilliSeconds2D")));
m_dateTimeShortcuts.Append(winrt::make<PowerRenameUILib::implementation::PatternSnippet>(L"$f", resourceLoader.GetString(L"DateTimeCheatSheet_MilliSeconds1D")));
InitializeComponent();
}
Windows::Foundation::Collections::IObservableVector<hstring> MainWindow::SearchMRU()
{
return m_searchMRU;
}
Windows::Foundation::Collections::IObservableVector<hstring> MainWindow::ReplaceMRU()
{
return m_replaceMRU;
}
winrt::Windows::Foundation::Collections::IObservableVector<winrt::PowerRenameUILib::ExplorerItem> MainWindow::ExplorerItems()
{
return m_explorerItems;
}
winrt::Windows::Foundation::Collections::IObservableVector<winrt::PowerRenameUILib::PatternSnippet> MainWindow::SearchRegExShortcuts()
{
return m_searchRegExShortcuts;
}
winrt::Windows::Foundation::Collections::IObservableVector<winrt::PowerRenameUILib::PatternSnippet> MainWindow::DateTimeShortcuts()
{
return m_dateTimeShortcuts;
}
Windows::UI::Xaml::Controls::AutoSuggestBox MainWindow::AutoSuggestBoxSearch()
{
return textBox_search();
}
Windows::UI::Xaml::Controls::AutoSuggestBox MainWindow::AutoSuggestBoxReplace()
{
return textBox_replace();
}
Windows::UI::Xaml::Controls::CheckBox MainWindow::CheckBoxRegex()
{
return checkBox_regex();
}
Windows::UI::Xaml::Controls::CheckBox MainWindow::CheckBoxCaseSensitive()
{
return checkBox_case();
}
Windows::UI::Xaml::Controls::CheckBox MainWindow::CheckBoxMatchAll()
{
return checkBox_matchAll();
}
Windows::UI::Xaml::Controls::ComboBox MainWindow::ComboBoxRenameParts()
{
return comboBox_renameParts();
}
Windows::UI::Xaml::Controls::Primitives::ToggleButton MainWindow::ToggleButtonIncludeFiles()
{
return toggleButton_includeFiles();
}
Windows::UI::Xaml::Controls::Primitives::ToggleButton MainWindow::ToggleButtonIncludeFolders()
{
return toggleButton_includeFolders();
}
Windows::UI::Xaml::Controls::Primitives::ToggleButton MainWindow::ToggleButtonIncludeSubfolders()
{
return toggleButton_includeSubfolders();
}
Windows::UI::Xaml::Controls::Primitives::ToggleButton MainWindow::ToggleButtonEnumerateItems()
{
return toggleButton_enumItems();
}
Windows::UI::Xaml::Controls::Primitives::ToggleButton MainWindow::ToggleButtonUpperCase()
{
return toggleButton_upperCase();
}
Windows::UI::Xaml::Controls::Primitives::ToggleButton MainWindow::ToggleButtonLowerCase()
{
return toggleButton_lowerCase();
}
Windows::UI::Xaml::Controls::Primitives::ToggleButton MainWindow::ToggleButtonTitleCase()
{
return toggleButton_titleCase();
}
Windows::UI::Xaml::Controls::Primitives::ToggleButton MainWindow::ToggleButtonCapitalize()
{
return toggleButton_capitalize();
}
Windows::UI::Xaml::Controls::Button MainWindow::ButtonSettings()
{
return button_settings();
}
Windows::UI::Xaml::Controls::CheckBox MainWindow::CheckBoxSelectAll()
{
return checkBox_selectAll();
}
PowerRenameUILib::UIUpdates MainWindow::UIUpdatesItem()
{
return m_uiUpdatesItem;
}
void MainWindow::AddExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, int32_t parentId, bool checked)
{
auto newItem = winrt::make<PowerRenameUILib::implementation::ExplorerItem>(id, original, renamed, type, checked);
if (parentId == 0)
{
m_explorerItems.Append(newItem);
}
else
{
auto parent = FindById(parentId);
parent.Children().Append(newItem);
}
}
void MainWindow::UpdateExplorerItem(int32_t id, hstring const& newName)
{
auto itemToUpdate = FindById(id);
if (itemToUpdate != NULL)
{
itemToUpdate.Renamed(newName);
}
}
void MainWindow::UpdateRenamedExplorerItem(int32_t id, hstring const& newOriginalName)
{
auto itemToUpdate = FindById(id);
if (itemToUpdate != NULL)
{
itemToUpdate.Original(newOriginalName);
itemToUpdate.Renamed(L"");
}
}
void MainWindow::AppendSearchMRU(hstring const& value)
{
m_searchMRU.Append(value);
}
void MainWindow::AppendReplaceMRU(hstring const& value)
{
m_replaceMRU.Append(value);
}
PowerRenameUILib::ExplorerItem MainWindow::FindById(int32_t id)
{
auto fakeRoot = winrt::make<PowerRenameUILib::implementation::ExplorerItem>(0, L"Fake", L"", 0, false);
fakeRoot.Children(m_explorerItems);
return FindById(fakeRoot, id);
}
PowerRenameUILib::ExplorerItem MainWindow::FindById(PowerRenameUILib::ExplorerItem& root, int32_t id)
{
if (root.Id() == id)
return root;
if (root.Type() == static_cast<UINT>(ExplorerItem::ExplorerItemType::Folder))
{
for (auto c : root.Children())
{
auto result = FindById(c, id);
if (result != NULL)
return result;
}
}
return NULL;
}
void MainWindow::ToggleAll(PowerRenameUILib::ExplorerItem node, bool checked)
{
if (node == NULL)
return;
node.Checked(checked);
if (node.Type() == static_cast<UINT>(ExplorerItem::ExplorerItemType::Folder))
{
for (auto c : node.Children())
{
ToggleAll(c, checked);
}
}
}
void MainWindow::Checked_ids(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const&)
{
auto checkbox = sender.as<Windows::UI::Xaml::Controls::CheckBox>();
auto id = std::stoi(std::wstring{ checkbox.Name() });
auto item = FindById(id);
if (checkbox.IsChecked().GetBoolean() != item.Checked())
{
m_uiUpdatesItem.Checked(checkbox.IsChecked().GetBoolean());
m_uiUpdatesItem.ChangedExplorerItemId(id);
}
}
void MainWindow::SelectAll(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::RoutedEventArgs const&)
{
if (checkBox_selectAll().IsChecked().GetBoolean() != m_allSelected)
{
auto fakeRoot = winrt::make<PowerRenameUILib::implementation::ExplorerItem>(0, L"Fake", L"", 0, false);
fakeRoot.Children(m_explorerItems);
ToggleAll(fakeRoot, checkBox_selectAll().IsChecked().GetBoolean());
m_uiUpdatesItem.ToggleAll();
m_allSelected = !m_allSelected;
}
}
void MainWindow::ShowAll(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::RoutedEventArgs const&)
{
button_showAll().IsChecked(true);
button_showRenamed().IsChecked(false);
if (!m_uiUpdatesItem.ShowAll())
{
m_explorerItems.Clear();
m_uiUpdatesItem.ShowAll(true);
}
}
void MainWindow::ShowRenamed(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::RoutedEventArgs const&)
{
button_showRenamed().IsChecked(true);
button_showAll().IsChecked(false);
if (m_uiUpdatesItem.ShowAll())
{
m_explorerItems.Clear();
m_uiUpdatesItem.ShowAll(false);
}
}
void MainWindow::RegExItemClick(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::Controls::ItemClickEventArgs const& e)
{
auto s = e.ClickedItem().try_as<PatternSnippet>();
RegExFlyout().Hide();
textBox_search().Text(textBox_search().Text() + s->Code());
}
void MainWindow::DateTimeItemClick(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::Controls::ItemClickEventArgs const& e)
{
auto s = e.ClickedItem().try_as<PatternSnippet>();
DateTimeFlyout().Hide();
textBox_replace().Text(textBox_replace().Text() + s->Code());
}
void MainWindow::button_rename_Click(winrt::Microsoft::UI::Xaml::Controls::SplitButton const&, winrt::Microsoft::UI::Xaml::Controls::SplitButtonClickEventArgs const&)
{
m_uiUpdatesItem.CloseUIWindow(false);
m_uiUpdatesItem.Rename();
}
void MainWindow::MenuFlyoutItem_Click(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::RoutedEventArgs const&)
{
m_uiUpdatesItem.CloseUIWindow(true);
m_uiUpdatesItem.Rename();
}
void MainWindow::OpenDocs(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::RoutedEventArgs const&)
{
Windows::System::Launcher::LaunchUriAsync(winrt::Windows::Foundation::Uri{ L"https://aka.ms/PowerToysOverview_PowerRename" });
}
}

View File

@ -0,0 +1,88 @@
#pragma once
#include "winrt/Windows.UI.Xaml.h"
#include "winrt/Windows.UI.Xaml.Markup.h"
#include "winrt/Windows.UI.Xaml.Interop.h"
#include "winrt/Windows.UI.Xaml.Controls.Primitives.h"
#include "MainWindow.g.h"
#include "PatternSnippet.h"
#include "ExplorerItem.h"
#include "ExplorerItemTemplateSelector.h"
namespace winrt::PowerRenameUILib::implementation
{
struct MainWindow : MainWindowT<MainWindow>
{
MainWindow();
Windows::Foundation::Collections::IObservableVector<hstring> SearchMRU();
Windows::Foundation::Collections::IObservableVector<hstring> ReplaceMRU();
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::ExplorerItem> ExplorerItems();
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::PatternSnippet> SearchRegExShortcuts();
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::PatternSnippet> DateTimeShortcuts();
Windows::UI::Xaml::Controls::AutoSuggestBox AutoSuggestBoxSearch();
Windows::UI::Xaml::Controls::AutoSuggestBox AutoSuggestBoxReplace();
Windows::UI::Xaml::Controls::CheckBox CheckBoxRegex();
Windows::UI::Xaml::Controls::CheckBox CheckBoxCaseSensitive();
Windows::UI::Xaml::Controls::CheckBox CheckBoxMatchAll();
Windows::UI::Xaml::Controls::ComboBox ComboBoxRenameParts();
Windows::UI::Xaml::Controls::Primitives::ToggleButton ToggleButtonIncludeFiles();
Windows::UI::Xaml::Controls::Primitives::ToggleButton ToggleButtonIncludeFolders();
Windows::UI::Xaml::Controls::Primitives::ToggleButton ToggleButtonIncludeSubfolders();
Windows::UI::Xaml::Controls::Primitives::ToggleButton ToggleButtonUpperCase();
Windows::UI::Xaml::Controls::Primitives::ToggleButton ToggleButtonLowerCase();
Windows::UI::Xaml::Controls::Primitives::ToggleButton ToggleButtonTitleCase();
Windows::UI::Xaml::Controls::Primitives::ToggleButton ToggleButtonCapitalize();
Windows::UI::Xaml::Controls::Primitives::ToggleButton ToggleButtonEnumerateItems();
Windows::UI::Xaml::Controls::Button ButtonSettings();
Windows::UI::Xaml::Controls::CheckBox CheckBoxSelectAll();
PowerRenameUILib::UIUpdates UIUpdatesItem();
void AddExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, int32_t parentId, bool checked);
void UpdateExplorerItem(int32_t id, hstring const& newName);
void UpdateRenamedExplorerItem(int32_t id, hstring const& newOriginalName);
void AppendSearchMRU(hstring const& value);
void AppendReplaceMRU(hstring const& value);
void Checked_ids(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void SelectAll(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void ShowAll(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void ShowRenamed(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
private:
bool m_allSelected;
PowerRenameUILib::UIUpdates m_uiUpdatesItem;
PowerRenameUILib::ExplorerItem FindById(int32_t id);
PowerRenameUILib::ExplorerItem FindById(PowerRenameUILib::ExplorerItem& root, int32_t id);
void ToggleAll(PowerRenameUILib::ExplorerItem node, bool checked);
winrt::Windows::Foundation::Collections::IObservableVector<hstring> m_searchMRU;
winrt::Windows::Foundation::Collections::IObservableVector<hstring> m_replaceMRU;
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::ExplorerItem> m_explorerItems;
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::PatternSnippet> m_searchRegExShortcuts;
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::PatternSnippet> m_dateTimeShortcuts;
public:
void RegExItemClick(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::ItemClickEventArgs const& e);
void DateTimeItemClick(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::ItemClickEventArgs const& e);
void button_rename_Click(winrt::Microsoft::UI::Xaml::Controls::SplitButton const& sender, winrt::Microsoft::UI::Xaml::Controls::SplitButtonClickEventArgs const& args);
void MenuFlyoutItem_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void OpenDocs(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
};
}
namespace winrt::PowerRenameUILib::factory_implementation
{
struct MainWindow : MainWindowT<MainWindow, implementation::MainWindow>
{
};
}

View File

@ -0,0 +1,61 @@
import "ExplorerItem.idl";
import "PatternSnippet.idl";
namespace PowerRenameUILib
{
runtimeclass UIUpdates : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
UIUpdates();
Boolean ShowAll;
Int32 ChangedExplorerItemId;
Boolean Checked;
void ToggleAll();
Boolean CloseUIWindow();
void CloseUIWindow(Boolean closeUIWindow);
Boolean ButtonRenameEnabled;
void Rename();
}
[default_interface] runtimeclass MainWindow : Windows.UI.Xaml.Controls.UserControl
{
MainWindow();
Windows.Foundation.Collections.IObservableVector<String> SearchMRU { get; };
Windows.Foundation.Collections.IObservableVector<String> ReplaceMRU { get; };
Windows.Foundation.Collections.IObservableVector<ExplorerItem> ExplorerItems { get; };
Windows.Foundation.Collections.IObservableVector<PatternSnippet> SearchRegExShortcuts { get; };
Windows.Foundation.Collections.IObservableVector<PatternSnippet> DateTimeShortcuts { get; };
Windows.UI.Xaml.Controls.AutoSuggestBox AutoSuggestBoxSearch { get; };
Windows.UI.Xaml.Controls.AutoSuggestBox AutoSuggestBoxReplace { get; };
Windows.UI.Xaml.Controls.CheckBox CheckBoxRegex { get; };
Windows.UI.Xaml.Controls.CheckBox CheckBoxCaseSensitive { get; };
Windows.UI.Xaml.Controls.CheckBox CheckBoxMatchAll { get; };
Windows.UI.Xaml.Controls.Primitives.ToggleButton ToggleButtonEnumerateItems { get; };
Windows.UI.Xaml.Controls.ComboBox ComboBoxRenameParts { get; };
Windows.UI.Xaml.Controls.Primitives.ToggleButton ToggleButtonIncludeFiles { get; };
Windows.UI.Xaml.Controls.Primitives.ToggleButton ToggleButtonIncludeFolders { get; };
Windows.UI.Xaml.Controls.Primitives.ToggleButton ToggleButtonIncludeSubfolders { get; };
Windows.UI.Xaml.Controls.Button ButtonSettings { get; };
Windows.UI.Xaml.Controls.CheckBox CheckBoxSelectAll { get; };
Windows.UI.Xaml.Controls.Primitives.ToggleButton ToggleButtonUpperCase { get; };
Windows.UI.Xaml.Controls.Primitives.ToggleButton ToggleButtonLowerCase { get; };
Windows.UI.Xaml.Controls.Primitives.ToggleButton ToggleButtonTitleCase { get; };
Windows.UI.Xaml.Controls.Primitives.ToggleButton ToggleButtonCapitalize { get; };
void AddExplorerItem(Int32 id, String original, String renamed, Int32 type, Int32 parentId, Boolean checked);
void UpdateExplorerItem(Int32 id, String newName);
void UpdateRenamedExplorerItem(Int32 id, String newOriginalName);
void AppendSearchMRU(String value);
void AppendReplaceMRU(String value);
UIUpdates UIUpdatesItem { get; };
}
}

View File

@ -0,0 +1,326 @@
<UserControl x:Class="PowerRenameUILib.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:PowerRenameUILib" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="using:Microsoft.UI.Xaml.Controls" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" controls:BackdropMaterial.ApplyToRootOrPageBackground="True" xmlns:animatedVisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals" mc:Ignorable="d">
<UserControl.Resources>
<local:ExplorerItemTemplateSelector x:Key="ExplorerItemTemplateSelector" FolderTemplate="{StaticResource FolderTemplate}" FileTemplate="{StaticResource FileTemplate}" />
<local:ExplorerItemTemplateSelector x:Key="RenamedExplorerItemTemplateSelector" FolderTemplate="{StaticResource RenamedFolderTemplate}" FileTemplate="{StaticResource RenamedFileTemplate}" />
<DataTemplate x:Key="FileTemplate" x:DataType="local:ExplorerItem">
<Grid Height="24" Margin="0,4,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="36" />
<ColumnDefinition Width="36" />
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<CheckBox TabIndex="0" Grid.Column="0" XYFocusKeyboardNavigation="Enabled" Checked="Checked_ids" IsTabStop="True" Unchecked="Checked_ids" Content="" Name="{x:Bind IdStr}" AutomationProperties.Name="{x:Bind Original}" AutomationProperties.HelpText="{x:Bind Renamed}" IsChecked="{x:Bind Checked, Mode=TwoWay}" />
<Image Width="16" Source="ms-appx:///Assets/file.png" HorizontalAlignment="Left" Grid.Column="1" />
<TextBlock Text="{x:Bind Original, Mode=OneWay}" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" FontSize="12" Grid.Column="2" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="FolderTemplate" x:DataType="local:ExplorerItem">
<Grid Margin="0,4,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="36" />
<ColumnDefinition Width="36" />
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="24" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<CheckBox TabIndex="0" IsTabStop="True" XYFocusKeyboardNavigation="Enabled" Grid.Row="0" Grid.Column="0" Checked="Checked_ids" Unchecked="Checked_ids" Content="" Name="{x:Bind IdStr}" AutomationProperties.Name="{x:Bind Original}" AutomationProperties.HelpText="{x:Bind Renamed}" IsChecked="{x:Bind Checked, Mode=TwoWay}" />
<Image Width="16" Source="ms-appx:///Assets/folder.png" HorizontalAlignment="Left" Grid.Column="1" />
<TextBlock Text="{x:Bind Original, Mode=OneWay}" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" FontSize="12" Grid.Column="2" />
<ListView Grid.ColumnSpan="3" IsTabStop="false" XYFocusKeyboardNavigation="Enabled" SelectionMode="None" IsItemClickEnabled="False" ItemsSource="{x:Bind Children}" Grid.Row="1" ItemTemplateSelector="{StaticResource ExplorerItemTemplateSelector}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</DataTemplate>
<DataTemplate x:Key="RenamedFileTemplate" x:DataType="local:ExplorerItem">
<Grid Height="24" Margin="0,4,0,0">
<TextBlock Text="{x:Bind Renamed, Mode=OneWay}" FontWeight="SemiBold" VerticalAlignment="Center" FontSize="14" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="RenamedFolderTemplate" x:DataType="local:ExplorerItem">
<Grid Margin="0,4,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="24" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="{x:Bind Renamed, Mode=OneWay}" FontWeight="Bold" VerticalAlignment="Center" FontSize="14" />
<ListView IsTabStop="false" Margin="-12,0,0,0" SelectionMode="None" IsItemClickEnabled="False" ItemsSource="{x:Bind Children}" Grid.Row="1" ItemTemplateSelector="{StaticResource RenamedExplorerItemTemplateSelector}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Padding="20">
<Grid.RowDefinitions>
<RowDefinition Height="0" /> <!-- 48 if we need to draw the title bar ourself -->
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="1" Grid.Column="1" Background="{ThemeResource LayerFillColorDefaultBrush}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" CornerRadius="8" BorderThickness="1" BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="36" />
<ColumnDefinition Width="48" />
<ColumnDefinition Width="Auto" MinWidth="324" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="48" />
</Grid.ColumnDefinitions>
<CheckBox x:Name="checkBox_selectAll" IsChecked="True" Content="" x:Uid="SelectAllCheckBox" Margin="16,0,0,0" Checked="SelectAll" Unchecked="SelectAll" />
<Image Width="16" Grid.Column="1" Source="ms-appx:///Assets/file.png" HorizontalAlignment="Center" />
<TextBlock x:Uid="TxtBlock_Original" Grid.Column="2" FontWeight="Medium" Margin="2,-2,0,0" VerticalAlignment="Center" />
<AppBarSeparator Grid.Column="3" Margin="-6,4,0,4" HorizontalAlignment="Left" />
<TextBlock x:Uid="TxtBlock_Renamed" FontWeight="Medium" Grid.Column="3" Margin="4,-2,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" />
<Button Content="&#xE16E;" Background="Transparent" FontFamily="{ThemeResource SymbolThemeFontFamily}" Height="32" x:Uid="FilterButton" Grid.Column="4" BorderThickness="0" HorizontalAlignment="Right" Margin="0,0,8,0">
<Button.Flyout>
<MenuBarItemFlyout Placement="Bottom">
<controls:RadioMenuFlyoutItem x:Name="button_showAll" Click="ShowAll" x:Uid="ShowAll" IsChecked="True" GroupName="Filter" />
<controls:RadioMenuFlyoutItem x:Name="button_showRenamed" Click="ShowRenamed" x:Uid="ShowOnly" GroupName="Filter" />
</MenuBarItemFlyout>
</Button.Flyout>
</Button>
<Rectangle Height="1" Grid.ColumnSpan="5" Fill="{ThemeResource CardStrokeColorDefaultBrush}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" />
<ScrollViewer Grid.ColumnSpan="6" HorizontalScrollMode="Enabled" Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="286" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListView IsTabStop="false" SelectionMode="None" XYFocusKeyboardNavigation="Enabled" IsItemClickEnabled="False" ItemsSource="{x:Bind ExplorerItems, Mode=OneWay}" Margin="4,0,0,0" ItemTemplateSelector="{StaticResource ExplorerItemTemplateSelector}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
<!--<controls:ItemsRepeater ItemsSource="{x:Bind ExplorerItems, Mode=OneWay}"
Margin="16,0,0,0"
ItemTemplate="{StaticResource ExplorerItemTemplateSelector}" />-->
<ListView Grid.Column="1" IsTabStop="false" SelectionMode="None" IsItemClickEnabled="False" ItemsSource="{x:Bind ExplorerItems, Mode=OneWay}" ItemTemplateSelector="{StaticResource RenamedExplorerItemTemplateSelector}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
<!--<controls:ItemsRepeater ItemsSource="{x:Bind ExplorerItems, Mode=OneWay}"
Grid.Column="1"
ItemTemplate="{StaticResource RenamedExplorerItemTemplateSelector}" />-->
</Grid>
</ScrollViewer>
</Grid>
<Grid Grid.Column="0" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="48" />
</Grid.RowDefinitions>
<ScrollViewer>
<StackPanel Orientation="Vertical" Padding="0,0,0,16" Margin="0,0,20,0">
<Grid>
<AutoSuggestBox x:Name="textBox_search" x:Uid="SearchBox" Height="48" VerticalContentAlignment="Center" ItemsSource="{x:Bind SearchMRU}" />
<Button FontFamily="{ThemeResource SymbolThemeFontFamily}" VerticalAlignment="Center" Visibility="{Binding ElementName=checkBox_regex, Path=IsChecked}" MinHeight="32" Margin="4" x:Uid="RegExButton" Background="Transparent" BorderBrush="Transparent" Content="&#xE946;" HorizontalAlignment="Right">
<Button.Flyout>
<Flyout x:Name="RegExFlyout">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="*" />
<RowDefinition Height="48" />
</Grid.RowDefinitions>
<TextBlock x:Uid="RegExCheatSheet_Title" FontWeight="SemiBold" />
<ListView ItemsSource="{x:Bind SearchRegExShortcuts}" Grid.Row="1" IsItemClickEnabled="True" Margin="-4,12,0,0" ItemClick="RegExItemClick">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:PatternSnippet">
<Grid ColumnSpacing="8" Margin="-10,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border CornerRadius="4" Padding="8" HorizontalAlignment="Left" BorderThickness="1" BorderBrush="{ThemeResource ButtonBorderBrush}" Background="{ThemeResource ButtonBackground}">
<TextBlock FontFamily="Consolas" Foreground="{ThemeResource ButtonForeground}" Text="{x:Bind Code}" />
</Border>
<TextBlock Text="{x:Bind Description}" FontSize="12" Grid.Column="1" Margin="0,0,0,0" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<HyperlinkButton Grid.Row="2" VerticalAlignment="Bottom">
<TextBlock x:Uid="RegExCheatSheet_LearnMore" />
</HyperlinkButton>
</Grid>
</Flyout>
</Button.Flyout>
</Button>
</Grid>
<CheckBox x:Name="checkBox_regex" x:Uid="CheckBox_RegEx" Margin="2,12,0,0" />
<CheckBox x:Name="checkBox_matchAll" x:Uid="CheckBox_MatchAll" Margin="2,4,0,0" />
<CheckBox x:Name="checkBox_case" x:Uid="CheckBox_Case" Margin="2,4,0,0" />
<Rectangle Height="1" Fill="{ThemeResource CardStrokeColorDefaultBrush}" HorizontalAlignment="Stretch" Margin="0,16,0,20" />
<Grid>
<AutoSuggestBox x:Name="textBox_replace" Margin="0,0,0,0" x:Uid="ReplaceBox" Height="48" VerticalContentAlignment="Center" Padding="12,12,0,0" ItemsSource="{x:Bind ReplaceMRU}" />
<Button FontFamily="{ThemeResource SymbolThemeFontFamily}" VerticalAlignment="Center" MinHeight="32" Margin="4" x:Uid="FileCreationButton" Background="Transparent" BorderBrush="Transparent" Content="&#xE946;" HorizontalAlignment="Right">
<Button.Flyout>
<Flyout x:Name="DateTimeFlyout" ShouldConstrainToRootBounds="False">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock x:Uid="DateTimeCheatSheet_Title" FontWeight="SemiBold" />
<ListView ItemsSource="{x:Bind DateTimeShortcuts}" Grid.Row="1" IsItemClickEnabled="True" Margin="-4,12,0,0" ItemClick="DateTimeItemClick">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:PatternSnippet">
<Grid ColumnSpacing="8" Margin="-10,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="56" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border CornerRadius="4" Padding="8" HorizontalAlignment="Left" BorderThickness="1" BorderBrush="{ThemeResource ButtonBorderBrush}" Background="{ThemeResource ButtonBackground}">
<TextBlock FontFamily="Consolas" Foreground="{ThemeResource ButtonForeground}" Text="{x:Bind Code}" />
</Border>
<TextBlock Text="{x:Bind Description}" FontSize="12" Grid.Column="1" Margin="0,0,0,0" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Flyout>
</Button.Flyout>
</Button>
</Grid>
<TextBlock x:Uid="TextBox_ApplyTo" x:Name="ApplyToLabel" FontSize="12" Margin="0,20,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<StackPanel Orientation="Horizontal" Grid.Column="1" Spacing="4" Grid.Row="1">
<ComboBox x:Name="comboBox_renameParts" SelectedIndex="0" Width="200" AutomationProperties.LabeledBy="{Binding ElementName=ApplyToLabel}" HorizontalAlignment="Stretch" Grid.Column="0" Grid.Row="1">
<x:String>Filename + extension</x:String>
<x:String>Filename only</x:String>
<x:String>Extension only</x:String>
</ComboBox>
<AppBarSeparator Margin="5,0,5,0" />
<ToggleButton x:Name="toggleButton_includeFiles" Content="&#xE160;" MinHeight="32" IsChecked="True" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="ToggleButton_IncludeFiles" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_includeFolders" Content="&#xE8B7;" MinHeight="32" IsChecked="True" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="ToggleButton_IncludeFolders" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_includeSubfolders" Content="&#xE12F;" MinHeight="32" IsChecked="True" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="ToggleButton_IncludeSubFolders" Style="{StaticResource CustomToggleButtonStyle}" />
</StackPanel>
<TextBlock x:Uid="TextBlock_TextFormatting" FontSize="12" Foreground="{ThemeResource TextFillColorSecondaryBrush}" Margin="0,20,0,8" />
<StackPanel Orientation="Horizontal" Spacing="4">
<ToggleButton x:Name="toggleButton_lowerCase" Content="aa" FontWeight="Medium" MinHeight="32" x:Uid="ToggleButton_Lowercase" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_upperCase" Content="AA" FontWeight="Medium" MinHeight="32" x:Uid="ToggleButton_Uppercase" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_titleCase" Content="Aa" FontWeight="Medium" MinHeight="32" x:Uid="ToggleButton_TitleCase" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_capitalize" Content="Aa Aa" FontWeight="Medium" MinHeight="32" x:Uid="ToggleButton_Capitalize" Style="{StaticResource CustomToggleButtonStyle}" />
<AppBarSeparator Margin="5,0,5,0" />
<ToggleButton x:Name="toggleButton_enumItems" Content="&#xEA40;" FontFamily="{ThemeResource SymbolThemeFontFamily}" MinHeight="32" x:Uid="ToggleButton_EnumItems" Style="{StaticResource CustomToggleButtonStyle}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
<Rectangle Height="1" Fill="{ThemeResource CardStrokeColorDefaultBrush}" HorizontalAlignment="Stretch" Margin="0,0,20,0" VerticalAlignment="Top" Grid.Row="1" />
<StackPanel Orientation="Horizontal" Grid.Row="1" Spacing="8" Margin="0" Grid.Column="1" VerticalAlignment="Bottom" HorizontalAlignment="Left">
<Button x:Name="button_settings" Height="32" x:Uid="TxtBlock_ButtonSettings" FontFamily="{ThemeResource SymbolThemeFontFamily}" Grid.Row="5" Padding="6" Background="Transparent" BorderBrush="Transparent" Grid.Column="1">
<Button.Content>
<controls:AnimatedIcon x:Name="SearchAnimatedIcon">
<controls:AnimatedIcon.Source>
<animatedVisuals:AnimatedSettingsVisualSource />
</controls:AnimatedIcon.Source>
<controls:AnimatedIcon.FallbackIconSource>
<controls:SymbolIconSource Symbol="Setting" />
</controls:AnimatedIcon.FallbackIconSource>
</controls:AnimatedIcon>
</Button.Content>
</Button>
<Button x:Name="button_docs" Content="&#xE11B;" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="DocsButton" Background="Transparent" BorderBrush="Transparent" Grid.Row="1" Height="32" VerticalAlignment="Bottom" HorizontalAlignment="Left" Click="OpenDocs" />
<!--<Button Content="&#xE728;"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
ToolTipService.ToolTip="Presets"
Background="Transparent"
BorderBrush="Transparent"
Grid.Row="1"
Height="36"
VerticalAlignment="Bottom"
HorizontalAlignment="Left">
<Button.Flyout>
<MenuFlyout>
<MenuFlyoutItem Text="Photo rule 1" />
<MenuFlyoutItem Text="Date time rule" />
<MenuFlyoutItem Text="And another rule" />
</MenuFlyout>
</Button.Flyout>
</Button>-->
</StackPanel>
<muxc:SplitButton Grid.Row="1" Style="{StaticResource SplitAccentButtonStyle}" x:Name="button_rename" Margin="0,0,20,0" x:Uid="ButtonApply" Click="button_rename_Click" HorizontalAlignment="Right" VerticalAlignment="Bottom" IsEnabled="{x:Bind UIUpdatesItem.ButtonRenameEnabled, Mode=OneWay}">
<muxc:SplitButton.Content>
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE13E;" FontSize="14" VerticalAlignment="Center" Margin="0,2,10,0" />
<TextBlock x:Uid="TxtBlock_ButtonApply" />
</StackPanel>
</muxc:SplitButton.Content>
<muxc:SplitButton.Flyout>
<MenuFlyout>
<MenuFlyoutItem x:Uid="TxtBlock_ButtonApplyAndClose" Click="MenuFlyoutItem_Click" />
</MenuFlyout>
</muxc:SplitButton.Flyout>
</muxc:SplitButton>
</Grid>
<!--<StackPanel x:Name="TitleBar" Orientation="Horizontal">
<Image Source="Assets/PowerRename.png" Width="16" Height="16" VerticalAlignment="Top" Margin="20,9,0,0"/>
<TextBlock Text="PowerRename" Style="{StaticResource CaptionTextBlockStyle}" Margin="18,8,8,0" VerticalAlignment="Top" />
</StackPanel>-->
</Grid>
</UserControl>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
<Identity Name="661b0d33-8cab-4599-adca-0976e0346f63" Publisher="CN=ms" Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="661b0d33-8cab-4599-adca-0976e0346f63" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
<Properties>
<DisplayName>PowerRenameUILib</DisplayName>
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="App" Executable="placeholder.exe" EntryPoint="PowerRenameUILib.App">
<uap:VisualElements DisplayName="PowerRenameUILib" Description="Project for a single page C++/WinRT Universal Windows Platform (UWP) app with no predefined layout" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"></uap:DefaultTile>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
</Package>

View File

@ -0,0 +1,49 @@
#include "pch.h"
#include "PatternSnippet.h"
#include "PatternSnippet.g.cpp"
namespace winrt::PowerRenameUILib::implementation
{
PatternSnippet::PatternSnippet(hstring const& code, hstring const& description) :
m_code{ code }, m_description{ description }
{
}
hstring PatternSnippet::Code()
{
return m_code;
}
void PatternSnippet::Code(hstring const& value)
{
if (m_code != value)
{
m_code = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Code" });
}
}
hstring PatternSnippet::Description()
{
return m_description;
}
void PatternSnippet::Description(hstring const& value)
{
if (m_description != value)
{
m_description = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Description" });
}
}
winrt::event_token PatternSnippet::PropertyChanged(winrt::Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
return m_propertyChanged.add(handler);
}
void PatternSnippet::PropertyChanged(winrt::event_token const& token) noexcept
{
m_propertyChanged.remove(token);
}
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "PatternSnippet.g.h"
namespace winrt::PowerRenameUILib::implementation
{
struct PatternSnippet : PatternSnippetT<PatternSnippet>
{
PatternSnippet() = delete;
PatternSnippet(hstring const& code, hstring const& description);
hstring Code();
void Code(hstring const& value);
hstring Description();
void Description(hstring const& value);
winrt::event_token PropertyChanged(winrt::Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
void PropertyChanged(winrt::event_token const& token) noexcept;
private:
winrt::hstring m_code;
winrt::hstring m_description;
winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
};
}
namespace winrt::PowerRenameUILib::factory_implementation
{
struct PatternSnippet : PatternSnippetT<PatternSnippet, implementation::PatternSnippet>
{
};
}

View File

@ -0,0 +1,9 @@
namespace PowerRenameUILib
{
runtimeclass PatternSnippet : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
PatternSnippet(String code, String description);
String Code;
String Description;
}
}

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ApplicationDefinition Include="App.xaml" />
</ItemGroup>
<ItemGroup>
<Page Include="MainWindow.xaml" />
</ItemGroup>
<ItemGroup>
<Midl Include="App.idl" />
<Midl Include="PatternSnippet.idl" />
<Midl Include="ExplorerItem.idl" />
<Midl Include="ExplorerItemTemplateSelector.idl" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp" />
<ClCompile Include="App.cpp" />
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="PatternSnippet.cpp" />
<ClCompile Include="ExplorerItem.cpp" />
<ClCompile Include="ExplorerItemTemplateSelector.cpp" />
<ClCompile Include="UIUpdates.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="app.base.h" />
<ClInclude Include="PatternSnippet.h" />
<ClInclude Include="ExplorerItem.h" />
<ClInclude Include="ExplorerItemTemplateSelector.h" />
<ClInclude Include="UIUpdates.h" />
</ItemGroup>
<ItemGroup>
<Image Include="Assets\Wide310x150Logo.scale-200.png">
<Filter>Assets</Filter>
</Image>
<Image Include="Assets\StoreLogo.png">
<Filter>Assets</Filter>
</Image>
<Image Include="Assets\Square150x150Logo.scale-200.png">
<Filter>Assets</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png">
<Filter>Assets</Filter>
</Image>
<Image Include="Assets\Square44x44Logo.scale-200.png">
<Filter>Assets</Filter>
</Image>
<Image Include="Assets\SplashScreen.scale-200.png">
<Filter>Assets</Filter>
</Image>
<Image Include="Assets\LockScreenLogo.scale-200.png">
<Filter>Assets</Filter>
</Image>
<Image Include="Assets\file.png">
<Filter>Assets</Filter>
</Image>
<Image Include="Assets\folder.png">
<Filter>Assets</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest" />
</ItemGroup>
<ItemGroup>
<Filter Include="Assets">
<UniqueIdentifier>{e48dc53e-40b1-40cb-970a-f89935452892}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="PropertySheet.props" />
<None Include="packages.config" />
<None Include="placeholder.exe" />
</ItemGroup>
<ItemGroup>
<Text Include="readme.txt" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,210 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.210922.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.210922.5\build\native\Microsoft.Windows.CppWinRT.props')" />
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
<CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata>
<MinimalCoreWin>true</MinimalCoreWin>
<ProjectGuid>{4642d596-723f-4bfc-894c-46811219ac4a}</ProjectGuid>
<ProjectName>PowerRenameUILib</ProjectName>
<RootNamespace>PowerRenameUILib</RootNamespace>
<DefaultLanguage>en-US</DefaultLanguage>
<MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
<AppContainerApplication>true</AppContainerApplication>
<ApplicationType>Windows Store</ApplicationType>
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.18362.0</WindowsTargetPlatformMinVersion>
<CppWinRTVerbosity>normal</CppWinRTVerbosity>
</PropertyGroup>
<PropertyGroup Label="Globals">
<WindowsAppContainer>true</WindowsAppContainer>
<AppxGeneratePriEnabled>true</AppxGeneratePriEnabled>
<ProjectPriIndexName>App</ProjectPriIndexName>
<AppxPackage>true</AppxPackage>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v143</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
<PlatformToolset Condition="'$(VisualStudioVersion)' == '14.0'">v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"></ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="PropertySheet.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="..\..\..\..\Solution.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="..\..\..\..\Solution.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\PowerRename\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\PowerRename\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
<WarningLevel>Level4</WarningLevel>
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
<!--Temporarily disable cppwinrt heap enforcement to work around xaml compiler generated std::shared_ptr use -->
<AdditionalOptions Condition="'$(CppWinRTHeapEnforcement)'==''">/DWINRT_NO_MAKE_DETECTION %(AdditionalOptions)</AdditionalOptions>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MultiThreadedDLL</RuntimeLibrary>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="app.base.h" />
<ClInclude Include="ExplorerItem.h" />
<ClInclude Include="ExplorerItemTemplateSelector.h" />
<ClInclude Include="MainWindow.h">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="pch.h" />
<ClInclude Include="App.h">
<DependentUpon>App.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="PatternSnippet.h" />
<ClInclude Include="UIUpdates.h" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
</ItemGroup>
<ItemGroup>
<Image Include="Assets\file.png" />
<Image Include="Assets\folder.png" />
<Image Include="Assets\LockScreenLogo.scale-200.png" />
<Image Include="Assets\SplashScreen.scale-200.png" />
<Image Include="Assets\Square150x150Logo.scale-200.png" />
<Image Include="Assets\Square44x44Logo.scale-200.png" />
<Image Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Image Include="Assets\StoreLogo.png" />
<Image Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="ExplorerItem.cpp" />
<ClCompile Include="ExplorerItemTemplateSelector.cpp" />
<ClCompile Include="MainWindow.cpp">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</ClCompile>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="App.cpp">
<DependentUpon>App.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<ClCompile Include="PatternSnippet.cpp" />
<ClCompile Include="UIUpdates.cpp" />
</ItemGroup>
<ItemGroup>
<Midl Include="App.idl">
<DependentUpon>App.xaml</DependentUpon>
</Midl>
<Midl Include="ExplorerItem.idl" />
<Midl Include="ExplorerItemTemplateSelector.idl" />
<Midl Include="MainWindow.idl">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<Midl Include="PatternSnippet.idl" />
</ItemGroup>
<ItemGroup>
<_WildCardPRIResource Include="Strings\*\Resources.resw" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="placeholder.exe">
<DeploymentContent>true</DeploymentContent>
</None>
<None Include="PropertySheet.props" />
<Text Include="readme.txt">
<DeploymentContent>false</DeploymentContent>
</Text>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.210922.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.210922.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
<Import Project="..\..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.210922.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.210922.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.210922.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.210922.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.UI.Xaml.2.7.0-prerelease.210913003\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
<Target Name="AddWildCardItems" AfterTargets="BuildGenerateSources">
<ItemGroup>
<PRIResource Include="@(_WildCardPRIResource)" />
</ItemGroup>
</Target>
</Project>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<!--
To customize common C++/WinRT project properties:
* right-click the project node
* expand the Common Properties item
* select the C++/WinRT property page
For more advanced scenarios, and complete documentation, please see:
https://github.com/Microsoft/cppwinrt/tree/master/nuget
-->
<PropertyGroup />
<ItemDefinitionGroup />
</Project>

View File

@ -0,0 +1,335 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="SearchBox.PlaceholderText" xml:space="preserve">
<value>Search for</value>
</data>
<data name="RegExCheatSheet_Title.Text" xml:space="preserve">
<value>RegEx help</value>
</data>
<data name="RegExCheatSheet_MatchAny" xml:space="preserve">
<value>Matches any character</value>
</data>
<data name="RegExCheatSheet_MatchDigit" xml:space="preserve">
<value>Any digit, short for [0-9]</value>
</data>
<data name="RegExCheatSheet_MatchNonDigit" xml:space="preserve">
<value>A non-digit, short for [^0-9]</value>
</data>
<data name="RegExCheatSheet_MatchNonWS" xml:space="preserve">
<value>A non-whitespace character, short for [^\\s]</value>
</data>
<data name="RegExCheatSheet_MatchWordChar" xml:space="preserve">
<value>A word character, short for [a-zA-Z_0-9]</value>
</data>
<data name="RegExCheatSheet_MatchSeveralWS" xml:space="preserve">
<value>Several non-whitespace characters</value>
</data>
<data name="RegExCheatSheet_MatchWordBoundary" xml:space="preserve">
<value>Matches a word boundary where a word character is [a-zA-Z0-9_].</value>
</data>
<data name="RegExCheatSheet_LearnMore.Text" xml:space="preserve">
<value>Learn more about RegEx</value>
</data>
<data name="ReplaceBox.PlaceholderText" xml:space="preserve">
<value>Replace with</value>
</data>
<data name="DateTimeCheatSheet_Title.Text" xml:space="preserve">
<value>Replace using file creation date and time</value>
</data>
<data name="DateTimeCheatSheet_FullYear" xml:space="preserve">
<value>Year represented by a full four or five digits, depending on the calendar used.</value>
</data>
<data name="DateTimeCheatSheet_YearLastTwoDigits" xml:space="preserve">
<value>Year represented only by the last two digits. A leading zero is added for single-digit years.</value>
</data>
<data name="DateTimeCheatSheet_YearLastDigit" xml:space="preserve">
<value>Year represented only by the last digit.</value>
</data>
<data name="DateTimeCheatSheet_MonthName" xml:space="preserve">
<value>Name of the month.</value>
</data>
<data name="DateTimeCheatSheet_MonthNameAbbr" xml:space="preserve">
<value>Abbreviated name of the month.</value>
</data>
<data name="DateTimeCheatSheet_MonthDigitLZero" xml:space="preserve">
<value>Month as digits with leading zeros for single-digit months.</value>
</data>
<data name="DateTimeCheatSheet_MonthDigit" xml:space="preserve">
<value>Month as digits without leading zeros for single-digit months.</value>
</data>
<data name="DateTimeCheatSheet_DayName" xml:space="preserve">
<value>Name of the day of the week.</value>
</data>
<data name="DateTimeCheatSheet_DayNameAbbr" xml:space="preserve">
<value>Abbreviated name of the day of the week.</value>
</data>
<data name="DateTimeCheatSheet_DayDigitLZero" xml:space="preserve">
<value>Day of the month as digits with leading zeros for single-digit days.</value>
</data>
<data name="DateTimeCheatSheet_DayDigit" xml:space="preserve">
<value>Day of the month as digits without leading zeros for single-digit days.</value>
</data>
<data name="DateTimeCheatSheet_HoursLZero" xml:space="preserve">
<value>Hours with leading zeros for single-digit hours.</value>
</data>
<data name="DateTimeCheatSheet_Hours" xml:space="preserve">
<value>Hours without leading zeros for single-digit hours.</value>
</data>
<data name="DateTimeCheatSheet_MinutesLZero" xml:space="preserve">
<value>Minutes with leading zeros for single-digit minutes.</value>
</data>
<data name="DateTimeCheatSheet_Minutes" xml:space="preserve">
<value>Minutes without leading zeros for single-digit minutes.</value>
</data>
<data name="DateTimeCheatSheet_SecondsLZero" xml:space="preserve">
<value>Seconds with leading zeros for single-digit seconds.</value>
</data>
<data name="DateTimeCheatSheet_Seconds" xml:space="preserve">
<value>Seconds without leading zeros for single-digit seconds.</value>
</data>
<data name="DateTimeCheatSheet_MilliSeconds3D" xml:space="preserve">
<value>Milliseconds represented by full three digits.</value>
</data>
<data name="DateTimeCheatSheet_MilliSeconds2D" xml:space="preserve">
<value>Milliseconds represented only by the first two digit.</value>
</data>
<data name="DateTimeCheatSheet_MilliSeconds1D" xml:space="preserve">
<value>Milliseconds represented only by the first digit.</value>
</data>
<data name="CheckBox_RegEx.Content" xml:space="preserve">
<value>Use regular expressions</value>
</data>
<data name="CheckBox_MatchAll.Content" xml:space="preserve">
<value>Match all occurences</value>
</data>
<data name="CheckBox_Case.Content" xml:space="preserve">
<value>Case sensitive</value>
</data>
<data name="TextBox_ApplyTo.Text" xml:space="preserve">
<value>Apply to</value>
</data>
<data name="DocsButton.ToolTipService.ToolTip" xml:space="preserve">
<value>Documentation</value>
</data>
<data name="DocsButton.AutomationProperties.Name" xml:space="preserve">
<value>Documentation</value>
</data>
<data name="ToggleButton_IncludeFiles.ToolTipService.ToolTip" xml:space="preserve">
<value>Include files</value>
</data>
<data name="ToggleButton_IncludeFiles.AutomationProperties.Name" xml:space="preserve">
<value>Include files</value>
</data>
<data name="ToggleButton_IncludeFolders.ToolTipService.ToolTip" xml:space="preserve">
<value>Include folders</value>
</data>
<data name="ToggleButton_IncludeFolders.AutomationProperties.Name" xml:space="preserve">
<value>Include folders</value>
</data>
<data name="ToggleButton_IncludeSubFolders.ToolTipService.ToolTip" xml:space="preserve">
<value>Include subfolders</value>
</data>
<data name="ToggleButton_IncludeSubFolders.AutomationProperties.Name" xml:space="preserve">
<value>Include subfolders</value>
</data>
<data name="TextBlock_TextFormatting.Text" xml:space="preserve">
<value>Text formatting</value>
</data>
<data name="ToggleButton_Lowercase.ToolTipService.ToolTip" xml:space="preserve">
<value>lowercase</value>
</data>
<data name="ToggleButton_Lowercase.AutomationProperties.Name" xml:space="preserve">
<value>Lowercase</value>
</data>
<data name="ToggleButton_Uppercase.ToolTipService.ToolTip" xml:space="preserve">
<value>UPPERCASE</value>
</data>
<data name="ToggleButton_Uppercase.AutomationProperties.Name" xml:space="preserve">
<value>Uppercase</value>
</data>
<data name="ToggleButton_Titlecase.ToolTipService.ToolTip" xml:space="preserve">
<value>Title case</value>
</data>
<data name="ToggleButton_Titlecase.AutomationProperties.Name" xml:space="preserve">
<value>Title case</value>
</data>
<data name="ToggleButton_Capitalize.ToolTipService.ToolTip" xml:space="preserve">
<value>Capitalize Each Word</value>
</data>
<data name="ToggleButton_Capitalize.AutomationProperties.Name" xml:space="preserve">
<value>Capitalize each word</value>
</data>
<data name="ToggleButton_EnumItems.ToolTipService.ToolTip" xml:space="preserve">
<value>Enumerate items</value>
</data>
<data name="ToggleButton_EnumItems.AutomationProperties.Name" xml:space="preserve">
<value>Enumerate items</value>
</data>
<data name="SelectAllCheckBox.AutomationProperties.Name" xml:space="preserve">
<value>Select or deselect all</value>
</data>
<data name="FilterButton.AutomationProperties.Name" xml:space="preserve">
<value>Filter</value>
</data>
<data name="FilterButton.ToolTipService.ToolTip" xml:space="preserve">
<value>Filter</value>
</data>
<data name="ShowAll.Text" xml:space="preserve">
<value>Show all files</value>
</data>
<data name="ShowOnly.Text" xml:space="preserve">
<value>Only show files that will be renamed</value>
</data>
<data name="TxtBlock_Original.Text" xml:space="preserve">
<value>Original</value>
</data>
<data name="TxtBlock_Renamed.Text" xml:space="preserve">
<value>Renamed</value>
</data>
<data name="TxtBlock_ButtonSettings.ToolTipService.ToolTip" xml:space="preserve">
<value>Settings</value>
</data>
<data name="TxtBlock_ButtonSettings.AutomationProperties.Name" xml:space="preserve">
<value>Settings</value>
</data>
<data name="TxtBlock_ButtonApply.Text" xml:space="preserve">
<value>Apply</value>
</data>
<data name="ButtonApply.AutomationProperties.Name" xml:space="preserve">
<value>Apply</value>
</data>
<data name="TxtBlock_ButtonApplyAndClose.Text" xml:space="preserve">
<value>Apply and close</value>
</data>
<data name="RegExButton.AutomationProperties.Name" xml:space="preserve">
<value>RegEx help</value>
</data>
<data name="RegExButton.ToolTipService.ToolTip" xml:space="preserve">
<value>RegEx help</value>
</data>
<data name="FileCreationButton.AutomationProperties.Name" xml:space="preserve">
<value>File creation date and time help</value>
</data>
<data name="FileCreationButton.ToolTipService.ToolTip" xml:space="preserve">
<value>File creation date and time help</value>
</data>
</root>

View File

@ -0,0 +1,90 @@
#include "pch.h"
#include "UIUpdates.h"
#include "UIUpdates.g.cpp"
namespace winrt::PowerRenameUILib::implementation
{
UIUpdates::UIUpdates() :
m_showAll{ true }, m_changedItemId{ -1 }, m_checked{ true }, m_closeUIWindow{ false }, m_buttonRenameEnabled{ false }
{
}
bool UIUpdates::ShowAll()
{
return m_showAll;
}
void UIUpdates::ShowAll(bool value)
{
if (m_showAll != value)
{
m_showAll = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"ShowAll" });
}
}
int32_t UIUpdates::ChangedExplorerItemId()
{
return m_changedItemId;
}
void UIUpdates::ChangedExplorerItemId(int32_t value)
{
m_changedItemId = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"ChangedItemId" });
}
bool UIUpdates::Checked()
{
return m_checked;
}
void UIUpdates::Checked(bool value)
{
m_checked = value;
}
winrt::event_token UIUpdates::PropertyChanged(winrt::Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
return m_propertyChanged.add(handler);
}
void UIUpdates::PropertyChanged(winrt::event_token const& token) noexcept
{
m_propertyChanged.remove(token);
}
void UIUpdates::ToggleAll()
{
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"ToggleAll" });
}
void UIUpdates::Rename()
{
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Rename" });
}
bool UIUpdates::CloseUIWindow()
{
return m_closeUIWindow;
}
void UIUpdates::CloseUIWindow(bool closeUIWindow)
{
m_closeUIWindow = closeUIWindow;
}
bool UIUpdates::ButtonRenameEnabled()
{
return m_buttonRenameEnabled;
}
void UIUpdates::ButtonRenameEnabled(bool value)
{
if (m_buttonRenameEnabled != value)
{
m_buttonRenameEnabled = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"ButtonRenameEnabled" });
}
}
}

View File

@ -0,0 +1,39 @@
#pragma once
#include "UIUpdates.g.h"
namespace winrt::PowerRenameUILib::implementation
{
struct UIUpdates : UIUpdatesT<UIUpdates>
{
UIUpdates();
bool ShowAll();
void ShowAll(bool value);
int32_t ChangedExplorerItemId();
void ChangedExplorerItemId(int32_t value);
bool Checked();
void Checked(bool value);
winrt::event_token PropertyChanged(winrt::Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
void PropertyChanged(winrt::event_token const& token) noexcept;
void ToggleAll();
bool CloseUIWindow();
void CloseUIWindow(bool closeUIWindow);
bool ButtonRenameEnabled();
void ButtonRenameEnabled(bool value);
void Rename();
private:
bool m_showAll;
int32_t m_changedItemId;
bool m_checked;
bool m_closeUIWindow;
bool m_buttonRenameEnabled;
winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
};
}
namespace winrt::PowerRenameUILib::factory_implementation
{
struct UIUpdates : UIUpdatesT<UIUpdates, implementation::UIUpdates>
{
};
}

View File

@ -0,0 +1,35 @@
#pragma once
namespace winrt::PowerRenameUILib::implementation
{
template<typename D, typename... I>
struct App_baseWithProvider : public App_base<D, ::winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider>
{
using IXamlType = ::winrt::Windows::UI::Xaml::Markup::IXamlType;
IXamlType GetXamlType(::winrt::Windows::UI::Xaml::Interop::TypeName const& type)
{
return AppProvider()->GetXamlType(type);
}
IXamlType GetXamlType(::winrt::hstring const& fullName)
{
return AppProvider()->GetXamlType(fullName);
}
::winrt::com_array<::winrt::Windows::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions()
{
return AppProvider()->GetXmlnsDefinitions();
}
private:
bool _contentLoaded{ false };
winrt::com_ptr<XamlMetaDataProvider> _appProvider;
winrt::com_ptr<XamlMetaDataProvider> AppProvider()
{
if (!_appProvider)
{
_appProvider = winrt::make_self<XamlMetaDataProvider>();
}
return _appProvider;
}
};
template<typename D, typename... I>
using AppT2 = App_baseWithProvider<D, I...>;
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.7.0-prerelease.210913003" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.210922.5" targetFramework="native" />
</packages>

View File

@ -0,0 +1 @@
#include "pch.h"

View File

@ -0,0 +1,27 @@
#pragma once
#include <windows.h>
#include <unknwn.h>
#include <RestrictedErrorInfo.h>
#include <hstring.h>
#include <WinUser.h>
#include <winrt/Windows.ApplicationModel.Activation.h>
#include <winrt/Windows.ApplicationModel.Resources.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.System.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.UI.Xaml.Automation.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
#include <winrt/Windows.UI.Xaml.Data.h>
#include <winrt/Windows.UI.Xaml.Interop.h>
#include <winrt/Windows.UI.Xaml.Markup.h>
#include <winrt/Windows.UI.Xaml.Navigation.h>
#include "winrt/Microsoft.UI.Xaml.Automation.Peers.h"
#include "winrt/Microsoft.UI.Xaml.Controls.Primitives.h"
#include "winrt/Microsoft.UI.Xaml.Controls.AnimatedVisuals.h"
#include "winrt/Microsoft.UI.Xaml.Media.h"
#include "winrt/Microsoft.UI.Xaml.XamlTypeInfo.h"

View File

@ -0,0 +1,23 @@
========================================================================
C++/WinRT PowerRenameUILib Project Overview
========================================================================
This project demonstrates how to get started writing XAML apps directly
with standard C++, using the C++/WinRT SDK component and XAML compiler
support to generate implementation headers from interface (IDL) files.
These headers can then be used to implement the local Windows Runtime
classes referenced in the app's XAML pages.
Steps:
1. Create an interface (IDL) file to define any local Windows Runtime
classes referenced in the app's XAML pages.
2. Build the project once to generate implementation templates under
the "Generated Files" folder, as well as skeleton class definitions
under "Generated Files\sources".
3. Use the skeleton class definitions for reference to implement your
Windows Runtime classes.
========================================================================
Learn more about C++/WinRT here:
http://aka.ms/cppwinrt/
========================================================================

View File

@ -5,7 +5,6 @@
// We need both DLL and UI resource files for UWP UI. // We need both DLL and UI resource files for UWP UI.
#include "../dll/Generated Files/PowerRenameExt.rc" #include "../dll/Generated Files/PowerRenameExt.rc"
#undef IDC_STATIC #undef IDC_STATIC
#include "../ui/Generated Files/PowerRenameUI.rc"
2 VERSIONINFO 2 VERSIONINFO
FILEVERSION FILE_VERSION FILEVERSION FILE_VERSION

View File

@ -63,9 +63,6 @@
<ProjectReference Include="..\lib\PowerRenameLib.vcxproj"> <ProjectReference Include="..\lib\PowerRenameLib.vcxproj">
<Project>{51920f1f-c28c-4adf-8660-4238766796c2}</Project> <Project>{51920f1f-c28c-4adf-8660-4238766796c2}</Project>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\ui\PowerRenameUI.vcxproj">
<Project>{0e072714-d127-460b-afad-b4c40b412798}</Project>
</ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="..\ui\PowerRename.ico" /> <Image Include="..\ui\PowerRename.ico" />

View File

@ -60,4 +60,8 @@
// Non-localizable // Non-localizable
////////////////////////////// //////////////////////////////
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_RENAME ICON "..\PowerRenameUIHost\PowerRenameUIHost.ico"

View File

@ -1,8 +1,5 @@
#include "pch.h" #include "pch.h"
#include "PowerRenameExt.h" #include "PowerRenameExt.h"
#include <PowerRenameUI.h>
#include <PowerRenameItem.h>
#include <PowerRenameManager.h>
#include <trace.h> #include <trace.h>
#include <Helpers.h> #include <Helpers.h>
#include <common/themes/icon_helpers.h> #include <common/themes/icon_helpers.h>
@ -11,6 +8,7 @@
#include <common/utils/resources.h> #include <common/utils/resources.h>
#include <common/utils/process_path.h> #include <common/utils/process_path.h>
#include <common/utils/HDropIterator.h>
extern HINSTANCE g_hInst; extern HINSTANCE g_hInst;
@ -116,6 +114,11 @@ HRESULT CPowerRenameMenu::QueryContextMenu(HMENU hMenu, UINT index, UINT uIDFirs
} }
HRESULT CPowerRenameMenu::InvokeCommand(_In_ LPCMINVOKECOMMANDINFO pici) HRESULT CPowerRenameMenu::InvokeCommand(_In_ LPCMINVOKECOMMANDINFO pici)
{
return RunPowerRename(pici, nullptr);
}
HRESULT CPowerRenameMenu::RunPowerRename(CMINVOKECOMMANDINFO* pici, IShellItemArray* psiItemArray)
{ {
HRESULT hr = E_FAIL; HRESULT hr = E_FAIL;
@ -124,82 +127,117 @@ HRESULT CPowerRenameMenu::InvokeCommand(_In_ LPCMINVOKECOMMANDINFO pici)
(LOWORD(pici->lpVerb) == 0)) (LOWORD(pici->lpVerb) == 0))
{ {
Trace::Invoked(); Trace::Invoked();
InvokeStruct* pInvokeData = new (std::nothrow) InvokeStruct; // Set the application path based on the location of the dll
hr = E_OUTOFMEMORY; std::wstring path = get_module_folderpath(g_hInst);
if (pInvokeData) path = path + L"\\PowerRename.exe";
LPTSTR lpApplicationName = (LPTSTR)path.c_str();
// Create an anonymous pipe to stream filenames
SECURITY_ATTRIBUTES sa;
HANDLE hReadPipe;
HANDLE hWritePipe;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0))
{ {
pInvokeData->hwndParent = pici->hwnd; hr = HRESULT_FROM_WIN32(GetLastError());
hr = CoMarshalInterThreadInterfaceInStream(__uuidof(m_spdo), m_spdo, &(pInvokeData->pstrm)); return hr;
if (SUCCEEDED(hr))
{
hr = SHCreateThread(s_PowerRenameUIThreadProc, pInvokeData, CTF_COINIT | CTF_PROCESS_REF, nullptr) ? S_OK : E_FAIL;
if (FAILED(hr))
{
pInvokeData->pstrm->Release(); // if we failed to create the thread, then we must release the stream
} }
if (!SetHandleInformation(hWritePipe, HANDLE_FLAG_INHERIT, 0))
{
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
CAtlFile writePipe(hWritePipe);
CString commandLine;
commandLine.Format(_T("\"%s\""), lpApplicationName);
int nSize = commandLine.GetLength() + 1;
LPTSTR lpszCommandLine = new TCHAR[nSize];
_tcscpy_s(lpszCommandLine, nSize, commandLine);
STARTUPINFO startupInfo;
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
startupInfo.cb = sizeof(STARTUPINFO);
startupInfo.hStdInput = hReadPipe;
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
if (pici)
{
startupInfo.wShowWindow = pici->nShow;
}
else
{
startupInfo.wShowWindow = SW_SHOWNORMAL;
} }
if (FAILED(hr)) PROCESS_INFORMATION processInformation;
{
delete pInvokeData;
}
}
Trace::InvokedRet(hr);
}
// Start the resizer
CreateProcess(
NULL,
lpszCommandLine,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&startupInfo,
&processInformation);
delete[] lpszCommandLine;
if (!CloseHandle(processInformation.hProcess))
{
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
if (!CloseHandle(processInformation.hThread))
{
hr = HRESULT_FROM_WIN32(GetLastError());
return hr; return hr;
} }
DWORD WINAPI CPowerRenameMenu::s_PowerRenameUIThreadProc(_In_ void* pData) // psiItemArray is NULL if called from InvokeCommand. This part is used for the MSI installer. It is not NULL if it is called from Invoke (MSIX).
if (!psiItemArray)
{ {
InvokeStruct* pInvokeData = static_cast<InvokeStruct*>(pData); // Stream the input files
CComPtr<IUnknown> dataSource; HDropIterator i(m_spdo);
HRESULT hr = CoGetInterfaceAndReleaseStream(pInvokeData->pstrm, IID_PPV_ARGS(&dataSource)); for (i.First(); !i.IsDone(); i.Next())
if (SUCCEEDED(hr))
{ {
// Create the rename manager CString fileName(i.CurrentItem());
CComPtr<IPowerRenameManager> spsrm; // File name can't contain '?'
hr = CPowerRenameManager::s_CreateInstance(&spsrm); fileName.Append(_T("?"));
if (SUCCEEDED(hr))
{
// Create the factory for our items
CComPtr<IPowerRenameItemFactory> spsrif;
hr = CPowerRenameItem::s_CreateInstance(nullptr, IID_PPV_ARGS(&spsrif));
if (SUCCEEDED(hr))
{
// Pass the factory to the manager
hr = spsrm->PutRenameItemFactory(spsrif);
if (SUCCEEDED(hr))
{
// Create the rename UI instance and pass the rename manager
CComPtr<IPowerRenameUI> spsrui;
hr = CPowerRenameUI::s_CreateInstance(spsrm, dataSource, false, &spsrui);
if (SUCCEEDED(hr)) writePipe.Write(fileName, fileName.GetLength() * sizeof(TCHAR));
{
IDataObject* dummy;
// If we're running on a local COM server, we need to decrement module refcount, which was previously incremented in CPowerRenameMenu::Invoke.
if (SUCCEEDED(dataSource->QueryInterface(IID_IShellItemArray, reinterpret_cast<void**>(&dummy))))
{
ModuleRelease();
} }
// Call blocks until we are done
spsrui->Show(pInvokeData->hwndParent);
spsrui->Close();
} }
else
{
//m_pdtobj will be NULL when invoked from the MSIX build as Initialize is never called (IShellExtInit functions aren't called in case of MSIX).
DWORD fileCount = 0;
// Gets the list of files currently selected using the IShellItemArray
psiItemArray->GetCount(&fileCount);
// Iterate over the list of files
for (DWORD i = 0; i < fileCount; i++)
{
IShellItem* shellItem;
psiItemArray->GetItemAt(i, &shellItem);
LPWSTR itemName;
// Retrieves the entire file system path of the file from its shell item
shellItem->GetDisplayName(SIGDN_FILESYSPATH, &itemName);
CString fileName(itemName);
// File name can't contain '?'
fileName.Append(_T("?"));
// Write the file path into the input stream for image resizer
writePipe.Write(fileName, fileName.GetLength() * sizeof(TCHAR));
} }
} }
// Need to call shutdown to break circular dependencies writePipe.Close();
spsrm->Shutdown();
}
} }
Trace::InvokedRet(hr);
delete pInvokeData; return hr;
Trace::UIShownRet(hr);
return 0;
} }
HRESULT __stdcall CPowerRenameMenu::GetTitle(IShellItemArray* /*psiItemArray*/, LPWSTR* ppszName) HRESULT __stdcall CPowerRenameMenu::GetTitle(IShellItemArray* /*psiItemArray*/, LPWSTR* ppszName)
@ -261,7 +299,7 @@ HRESULT __stdcall CPowerRenameMenu::Invoke(IShellItemArray* psiItemArray, IBindC
} }
// Prevent Shutting down before PowerRenameUI is created // Prevent Shutting down before PowerRenameUI is created
ModuleAddRef(); ModuleAddRef();
hr = SHCreateThread(s_PowerRenameUIThreadProc, pInvokeData, CTF_COINIT | CTF_PROCESS_REF, nullptr) ? S_OK : E_FAIL; hr = RunPowerRename(nullptr, psiItemArray);
} }
Trace::InvokedRet(hr); Trace::InvokedRet(hr);
return S_OK; return S_OK;

View File

@ -49,6 +49,8 @@ public:
return E_NOTIMPL; return E_NOTIMPL;
} }
HRESULT RunPowerRename(CMINVOKECOMMANDINFO* pici, IShellItemArray* psiItemArray);
// Inherited via IExplorerCommand // Inherited via IExplorerCommand
virtual HRESULT __stdcall GetTitle(IShellItemArray* psiItemArray, LPWSTR* ppszName) override; virtual HRESULT __stdcall GetTitle(IShellItemArray* psiItemArray, LPWSTR* ppszName) override;
virtual HRESULT __stdcall GetIcon(IShellItemArray* psiItemArray, LPWSTR* ppszIcon) override; virtual HRESULT __stdcall GetIcon(IShellItemArray* psiItemArray, LPWSTR* ppszIcon) override;
@ -60,7 +62,6 @@ public:
virtual HRESULT __stdcall EnumSubCommands(IEnumExplorerCommand** ppEnum) override; virtual HRESULT __stdcall EnumSubCommands(IEnumExplorerCommand** ppEnum) override;
static HRESULT s_CreateInstance(_In_opt_ IUnknown* punkOuter, _In_ REFIID riid, _Outptr_ void** ppv); static HRESULT s_CreateInstance(_In_opt_ IUnknown* punkOuter, _In_ REFIID riid, _Outptr_ void** ppv);
static DWORD WINAPI s_PowerRenameUIThreadProc(_In_ void* pData);
static bool SetEnabled(_In_ bool enabled); static bool SetEnabled(_In_ bool enabled);
static bool IsEnabled(); static bool IsEnabled();

View File

@ -21,7 +21,7 @@
<AdditionalIncludeDirectories>..\lib\;..\ui\;..\;..\..\..\;..\..\..\common\telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\lib\;..\ui\;..\;..\..\..\;..\..\..\common\telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>Pathcch.lib;comctl32.lib;$(SolutionDir)$(Platform)\$(Configuration)\obj\PowerRenameUI\PowerRenameUI.res;shcore.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>Pathcch.lib;comctl32.lib;shcore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>PowerRenameExt.def</ModuleDefinitionFile> <ModuleDefinitionFile>PowerRenameExt.def</ModuleDefinitionFile>
<DelayLoadDLLs>gdi32.dll;shell32.dll;ole32.dll;shlwapi.dll;oleaut32.dll;%(DelayLoadDLLs)</DelayLoadDLLs> <DelayLoadDLLs>gdi32.dll;shell32.dll;ole32.dll;shlwapi.dll;oleaut32.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
</Link> </Link>
@ -60,9 +60,6 @@
<ProjectReference Include="..\lib\PowerRenameLib.vcxproj"> <ProjectReference Include="..\lib\PowerRenameLib.vcxproj">
<Project>{51920f1f-c28c-4adf-8660-4238766796c2}</Project> <Project>{51920f1f-c28c-4adf-8660-4238766796c2}</Project>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\ui\PowerRenameUI.vcxproj">
<Project>{0e072714-d127-460b-afad-b4c40b412798}</Project>
</ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Resources.resx" /> <None Include="Resources.resx" />

View File

@ -10,6 +10,9 @@
#include <unknwn.h> #include <unknwn.h>
#include <shlwapi.h> #include <shlwapi.h>
#include <atlbase.h> #include <atlbase.h>
#include <atlcom.h>
#include <atlfile.h>
#include <atlstr.h>
#include <Shobjidl.h> #include <Shobjidl.h>
#include <Shlobj.h> #include <Shlobj.h>
#include "CLSID.h" #include "CLSID.h"

View File

@ -7,6 +7,13 @@
namespace fs = std::filesystem; namespace fs = std::filesystem;
namespace
{
const int MAX_INPUT_STRING_LEN = 1024;
const wchar_t c_rootRegPath[] = L"Software\\Microsoft\\PowerRename";
}
HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source) HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source)
{ {
HRESULT hr = E_INVALIDARG; HRESULT hr = E_INVALIDARG;
@ -545,3 +552,56 @@ HWND CreateMsgWindow(_In_ HINSTANCE hInst, _In_ WNDPROC pfnWndProc, _In_ void* p
return hwnd; return hwnd;
} }
std::wstring GetRegString(const std::wstring& valueName, const std::wstring& subPath)
{
wchar_t value[MAX_INPUT_STRING_LEN];
value[0] = L'\0';
DWORD type = REG_SZ;
DWORD size = MAX_INPUT_STRING_LEN * sizeof(wchar_t);
std::wstring completePath = std::wstring(c_rootRegPath) + subPath;
if (SHGetValue(HKEY_CURRENT_USER, completePath.c_str(), valueName.c_str(), &type, value, &size) == ERROR_SUCCESS)
{
return std::wstring(value);
}
return std::wstring{};
}
unsigned int GetRegNumber(const std::wstring& valueName, unsigned int defaultValue)
{
DWORD type = REG_DWORD;
DWORD data = 0;
DWORD size = sizeof(DWORD);
if (SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), &type, &data, &size) == ERROR_SUCCESS)
{
return data;
}
return defaultValue;
}
void SetRegNumber(const std::wstring& valueName, unsigned int value)
{
SHSetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), REG_DWORD, &value, sizeof(value));
}
bool GetRegBoolean(const std::wstring& valueName, bool defaultValue)
{
DWORD value = GetRegNumber(valueName.c_str(), defaultValue ? 1 : 0);
return (value == 0) ? false : true;
}
void SetRegBoolean(const std::wstring& valueName, bool value)
{
SetRegNumber(valueName, value ? 1 : 0);
}
bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime)
{
WIN32_FILE_ATTRIBUTE_DATA attr{};
if (GetFileAttributesExW(filePath.c_str(), GetFileExInfoStandard, &attr))
{
*lpFileTime = attr.ftLastWriteTime;
return true;
}
return false;
}

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <lib/PowerRenameInterfaces.h> #include "PowerRenameInterfaces.h"
#include <string>
HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source); HRESULT GetTrimmedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source);
HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags); HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, DWORD flags);
@ -16,3 +18,10 @@ BOOL GetEnumeratedFileName(
unsigned long ulMinLong, unsigned long ulMinLong,
__inout unsigned long* pulNumUsed); __inout unsigned long* pulNumUsed);
HWND CreateMsgWindow(_In_ HINSTANCE hInst, _In_ WNDPROC pfnWndProc, _In_ void* p); HWND CreateMsgWindow(_In_ HINSTANCE hInst, _In_ WNDPROC pfnWndProc, _In_ void* p);
std::wstring GetRegString(const std::wstring& valueName, const std::wstring& subPath);
unsigned int GetRegNumber(const std::wstring& valueName, unsigned int defaultValue);
void SetRegNumber(const std::wstring& valueName, unsigned int value);
bool GetRegBoolean(const std::wstring& valueName, bool defaultValue);
void SetRegBoolean(const std::wstring& valueName, bool value);
bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime);

View File

@ -0,0 +1,181 @@
#include "pch.h"
#include "MRUListHandler.h"
#include "Helpers.h"
#include <dll/PowerRenameConstants.h>
#include <common/SettingsAPI/settings_helpers.h>
namespace
{
const wchar_t c_mruList[] = L"MRUList";
const wchar_t c_insertionIdx[] = L"InsertionIdx";
const wchar_t c_maxMRUSize[] = L"MaxMRUSize";
}
MRUListHandler::MRUListHandler(unsigned int size, const std::wstring& filePath, const std::wstring& regPath) :
pushIdx(0),
nextIdx(1),
size(size),
jsonFilePath(PTSettingsHelper::get_module_save_folder_location(PowerRenameConstants::ModuleKey) + filePath),
registryFilePath(regPath)
{
items.resize(size);
Load();
}
void MRUListHandler::Push(const std::wstring& data)
{
if (Exists(data))
{
// TODO: Already existing item should be put on top of MRU list.
return;
}
items[pushIdx] = data;
pushIdx = (pushIdx + 1) % size;
Save();
}
bool MRUListHandler::Next(std::wstring& data)
{
if (nextIdx == size + 1)
{
Reset();
return false;
}
// Go backwards to consume latest items first.
unsigned int idx = (pushIdx + size - nextIdx) % size;
if (items[idx].empty())
{
Reset();
return false;
}
data = items[idx];
++nextIdx;
return true;
}
void MRUListHandler::Reset()
{
nextIdx = 1;
}
const std::vector<std::wstring>& MRUListHandler::GetItems()
{
return items;
}
void MRUListHandler::Load()
{
if (!std::filesystem::exists(jsonFilePath))
{
MigrateFromRegistry();
Save();
}
else
{
ParseJson();
}
}
void MRUListHandler::Save()
{
json::JsonObject jsonData;
jsonData.SetNamedValue(c_maxMRUSize, json::value(size));
jsonData.SetNamedValue(c_insertionIdx, json::value(pushIdx));
jsonData.SetNamedValue(c_mruList, Serialize());
json::to_file(jsonFilePath, jsonData);
}
json::JsonArray MRUListHandler::Serialize()
{
json::JsonArray searchMRU{};
std::wstring data{};
for (const std::wstring& item : items)
{
searchMRU.Append(json::value(item));
}
return searchMRU;
}
void MRUListHandler::MigrateFromRegistry()
{
std::wstring searchListKeys = GetRegString(c_mruList, registryFilePath);
std::sort(std::begin(searchListKeys), std::end(searchListKeys));
for (const wchar_t& key : searchListKeys)
{
Push(GetRegString(std::wstring(1, key), registryFilePath));
}
}
void MRUListHandler::ParseJson()
{
auto json = json::from_file(jsonFilePath);
if (json)
{
const json::JsonObject& jsonObject = json.value();
try
{
unsigned int oldSize{ size };
if (json::has(jsonObject, c_maxMRUSize, json::JsonValueType::Number))
{
oldSize = (unsigned int)jsonObject.GetNamedNumber(c_maxMRUSize);
}
unsigned int oldPushIdx{ 0 };
if (json::has(jsonObject, c_insertionIdx, json::JsonValueType::Number))
{
oldPushIdx = (unsigned int)jsonObject.GetNamedNumber(c_insertionIdx);
if (oldPushIdx < 0 || oldPushIdx >= oldSize)
{
oldPushIdx = 0;
}
}
if (json::has(jsonObject, c_mruList, json::JsonValueType::Array))
{
auto jsonArray = jsonObject.GetNamedArray(c_mruList);
if (oldSize == size)
{
for (uint32_t i = 0; i < jsonArray.Size(); ++i)
{
items[i] = std::wstring(jsonArray.GetStringAt(i));
}
pushIdx = oldPushIdx;
}
else
{
std::vector<std::wstring> temp;
for (unsigned int i = 0; i < min(jsonArray.Size(), size); ++i)
{
int idx = (oldPushIdx + oldSize - (i + 1)) % oldSize;
temp.push_back(std::wstring(jsonArray.GetStringAt(idx)));
}
if (size > oldSize)
{
std::reverse(std::begin(temp), std::end(temp));
pushIdx = (unsigned int)temp.size();
temp.resize(size);
}
else
{
temp.resize(size);
std::reverse(std::begin(temp), std::end(temp));
}
items = std::move(temp);
Save();
}
}
}
catch (const winrt::hresult_error&)
{
}
}
}
bool MRUListHandler::Exists(const std::wstring& data)
{
return std::find(std::begin(items), std::end(items), data) != std::end(items);
}

View File

@ -0,0 +1,35 @@
#pragma once
#include "pch.h"
#include <filesystem>
#include <string>
#include <common/utils/json.h>
class MRUListHandler
{
public:
MRUListHandler(unsigned int size, const std::wstring& filePath, const std::wstring& regPath);
void Push(const std::wstring& data);
bool Next(std::wstring& data);
void Reset();
const std::vector<std::wstring>& GetItems();
private:
void Load();
void Save();
void MigrateFromRegistry();
json::JsonArray Serialize();
void ParseJson();
bool Exists(const std::wstring& data);
std::vector<std::wstring> items;
unsigned int pushIdx;
unsigned int nextIdx;
unsigned int size;
const std::wstring jsonFilePath;
const std::wstring registryFilePath;
};

View File

@ -28,20 +28,10 @@ IFACEMETHODIMP CPowerRenameEnum::QueryInterface(_In_ REFIID riid, _Outptr_ void*
return QISearch(this, qit, riid, ppv); return QISearch(this, qit, riid, ppv);
} }
IFACEMETHODIMP CPowerRenameEnum::Start() IFACEMETHODIMP CPowerRenameEnum::Start(_In_ IEnumShellItems* enumShellItems)
{ {
m_canceled = false; m_canceled = false;
CComPtr<IShellItemArray> spsia; HRESULT hr = _ParseEnumItems(enumShellItems);
HRESULT hr = GetShellItemArrayFromDataObject(m_spdo, &spsia);
if (SUCCEEDED(hr))
{
CComPtr<IEnumShellItems> spesi;
hr = spsia->EnumItems(&spesi);
if (SUCCEEDED(hr))
{
hr = _ParseEnumItems(spesi);
}
}
return hr; return hr;
} }

View File

@ -14,7 +14,7 @@ public:
IFACEMETHODIMP_(ULONG) Release(); IFACEMETHODIMP_(ULONG) Release();
// ISmartRenameEnum // ISmartRenameEnum
IFACEMETHODIMP Start(); IFACEMETHODIMP Start(_In_ IEnumShellItems* enumShellItems);
IFACEMETHODIMP Cancel(); IFACEMETHODIMP Cancel();
public: public:

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include "pch.h" #include "pch.h"
#include <string>
#include <vector>
enum PowerRenameFlags enum PowerRenameFlags
{ {
@ -41,9 +43,9 @@ public:
IFACEMETHOD(Advise)(_In_ IPowerRenameRegExEvents* regExEvents, _Out_ DWORD* cookie) = 0; IFACEMETHOD(Advise)(_In_ IPowerRenameRegExEvents* regExEvents, _Out_ DWORD* cookie) = 0;
IFACEMETHOD(UnAdvise)(_In_ DWORD cookie) = 0; IFACEMETHOD(UnAdvise)(_In_ DWORD cookie) = 0;
IFACEMETHOD(GetSearchTerm)(_Outptr_ PWSTR* searchTerm) = 0; IFACEMETHOD(GetSearchTerm)(_Outptr_ PWSTR* searchTerm) = 0;
IFACEMETHOD(PutSearchTerm)(_In_ PCWSTR searchTerm) = 0; IFACEMETHOD(PutSearchTerm)(_In_ PCWSTR searchTerm, bool forceRenaming = false) = 0;
IFACEMETHOD(GetReplaceTerm)(_Outptr_ PWSTR* replaceTerm) = 0; IFACEMETHOD(GetReplaceTerm)(_Outptr_ PWSTR* replaceTerm) = 0;
IFACEMETHOD(PutReplaceTerm)(_In_ PCWSTR replaceTerm) = 0; IFACEMETHOD(PutReplaceTerm)(_In_ PCWSTR replaceTerm, bool forceRenaming = false) = 0;
IFACEMETHOD(GetFlags)(_Out_ DWORD* flags) = 0; IFACEMETHOD(GetFlags)(_Out_ DWORD* flags) = 0;
IFACEMETHOD(PutFlags)(_In_ DWORD flags) = 0; IFACEMETHOD(PutFlags)(_In_ DWORD flags) = 0;
IFACEMETHOD(PutFileTime)(_In_ SYSTEMTIME fileTime) = 0; IFACEMETHOD(PutFileTime)(_In_ SYSTEMTIME fileTime) = 0;
@ -54,10 +56,12 @@ public:
interface __declspec(uuid("C7F59201-4DE1-4855-A3A2-26FC3279C8A5")) IPowerRenameItem : public IUnknown interface __declspec(uuid("C7F59201-4DE1-4855-A3A2-26FC3279C8A5")) IPowerRenameItem : public IUnknown
{ {
public: public:
IFACEMETHOD(PutPath)(_In_opt_ PCWSTR newPath) = 0;
IFACEMETHOD(GetPath)(_Outptr_ PWSTR * path) = 0; IFACEMETHOD(GetPath)(_Outptr_ PWSTR * path) = 0;
IFACEMETHOD(GetTime)(_Outptr_ SYSTEMTIME* time) = 0; IFACEMETHOD(GetTime)(_Outptr_ SYSTEMTIME* time) = 0;
IFACEMETHOD(GetShellItem)(_Outptr_ IShellItem** ppsi) = 0; IFACEMETHOD(GetShellItem)(_Outptr_ IShellItem** ppsi) = 0;
IFACEMETHOD(GetOriginalName)(_Outptr_ PWSTR * originalName) = 0; IFACEMETHOD(GetOriginalName)(_Outptr_ PWSTR * originalName) = 0;
IFACEMETHOD(PutOriginalName)(_In_opt_ PCWSTR originalName) = 0;
IFACEMETHOD(GetNewName)(_Outptr_ PWSTR * newName) = 0; IFACEMETHOD(GetNewName)(_Outptr_ PWSTR * newName) = 0;
IFACEMETHOD(PutNewName)(_In_opt_ PCWSTR newName) = 0; IFACEMETHOD(PutNewName)(_In_opt_ PCWSTR newName) = 0;
IFACEMETHOD(GetIsFolder)(_Out_ bool* isFolder) = 0; IFACEMETHOD(GetIsFolder)(_Out_ bool* isFolder) = 0;
@ -84,12 +88,13 @@ interface __declspec(uuid("87FC43F9-7634-43D9-99A5-20876AFCE4AD")) IPowerRenameM
public: public:
IFACEMETHOD(OnItemAdded)(_In_ IPowerRenameItem* renameItem) = 0; IFACEMETHOD(OnItemAdded)(_In_ IPowerRenameItem* renameItem) = 0;
IFACEMETHOD(OnUpdate)(_In_ IPowerRenameItem * renameItem) = 0; IFACEMETHOD(OnUpdate)(_In_ IPowerRenameItem * renameItem) = 0;
IFACEMETHOD(OnRename)(_In_ IPowerRenameItem * renameItem) = 0;
IFACEMETHOD(OnError)(_In_ IPowerRenameItem * renameItem) = 0; IFACEMETHOD(OnError)(_In_ IPowerRenameItem * renameItem) = 0;
IFACEMETHOD(OnRegExStarted)(_In_ DWORD threadId) = 0; IFACEMETHOD(OnRegExStarted)(_In_ DWORD threadId) = 0;
IFACEMETHOD(OnRegExCanceled)(_In_ DWORD threadId) = 0; IFACEMETHOD(OnRegExCanceled)(_In_ DWORD threadId) = 0;
IFACEMETHOD(OnRegExCompleted)(_In_ DWORD threadId) = 0; IFACEMETHOD(OnRegExCompleted)(_In_ DWORD threadId) = 0;
IFACEMETHOD(OnRenameStarted)() = 0; IFACEMETHOD(OnRenameStarted)() = 0;
IFACEMETHOD(OnRenameCompleted)() = 0; IFACEMETHOD(OnRenameCompleted)(_In_ bool closeUIWindowAfterRenaming) = 0;
}; };
interface __declspec(uuid("001BBD88-53D2-4FA6-95D2-F9A9FA4F9F70")) IPowerRenameManager : public IUnknown interface __declspec(uuid("001BBD88-53D2-4FA6-95D2-F9A9FA4F9F70")) IPowerRenameManager : public IUnknown
@ -101,7 +106,9 @@ public:
IFACEMETHOD(Stop)() = 0; IFACEMETHOD(Stop)() = 0;
IFACEMETHOD(Reset)() = 0; IFACEMETHOD(Reset)() = 0;
IFACEMETHOD(Shutdown)() = 0; IFACEMETHOD(Shutdown)() = 0;
IFACEMETHOD(Rename)(_In_ HWND hwndParent) = 0; IFACEMETHOD(Rename)(_In_ HWND hwndParent, _In_ bool closeWindow) = 0;
IFACEMETHOD(UpdateChildrenPath)(_In_ int parentId, _In_ size_t oldParentPathSize) = 0;
IFACEMETHOD(GetCloseUIWindowAfterRenaming)(_Out_ bool* closeUIWindowAfterRenaming) = 0;
IFACEMETHOD(AddItem)(_In_ IPowerRenameItem * pItem) = 0; IFACEMETHOD(AddItem)(_In_ IPowerRenameItem * pItem) = 0;
IFACEMETHOD(GetItemByIndex)(_In_ UINT index, _COM_Outptr_ IPowerRenameItem** ppItem) = 0; IFACEMETHOD(GetItemByIndex)(_In_ UINT index, _COM_Outptr_ IPowerRenameItem** ppItem) = 0;
IFACEMETHOD(GetVisibleItemByIndex)(_In_ UINT index, _COM_Outptr_ IPowerRenameItem ** ppItem) = 0; IFACEMETHOD(GetVisibleItemByIndex)(_In_ UINT index, _COM_Outptr_ IPowerRenameItem ** ppItem) = 0;
@ -121,23 +128,17 @@ public:
IFACEMETHOD(PutRenameItemFactory)(_In_ IPowerRenameItemFactory* pItemFactory) = 0; IFACEMETHOD(PutRenameItemFactory)(_In_ IPowerRenameItemFactory* pItemFactory) = 0;
}; };
interface __declspec(uuid("E6679DEB-460D-42C1-A7A8-E25897061C99")) IPowerRenameUI : public IUnknown
{
public:
IFACEMETHOD(Show)(_In_opt_ HWND hwndParent) = 0;
IFACEMETHOD(Close)() = 0;
IFACEMETHOD(Update)() = 0;
};
interface __declspec(uuid("04AAFABE-B76E-4E13-993A-B5941F52B139")) IPowerRenameMRU : public IUnknown interface __declspec(uuid("04AAFABE-B76E-4E13-993A-B5941F52B139")) IPowerRenameMRU : public IUnknown
{ {
public: public:
IFACEMETHOD(AddMRUString)(_In_ PCWSTR entry) = 0; IFACEMETHOD(AddMRUString)(_In_ PCWSTR entry) = 0;
IFACEMETHOD_(const std::vector<std::wstring>&, GetMRUStrings)() = 0;
}; };
interface __declspec(uuid("CE8C8616-C1A8-457A-9601-10570F5B9F1F")) IPowerRenameEnum : public IUnknown interface __declspec(uuid("CE8C8616-C1A8-457A-9601-10570F5B9F1F")) IPowerRenameEnum : public IUnknown
{ {
public: public:
IFACEMETHOD(Start)() = 0; IFACEMETHOD(Start)
(_In_ IEnumShellItems * enumShellItems) = 0;
IFACEMETHOD(Cancel)() = 0; IFACEMETHOD(Cancel)() = 0;
}; };

View File

@ -32,6 +32,19 @@ IFACEMETHODIMP CPowerRenameItem::QueryInterface(_In_ REFIID riid, _Outptr_ void*
return QISearch(this, qit, riid, ppv); return QISearch(this, qit, riid, ppv);
} }
IFACEMETHODIMP CPowerRenameItem::PutPath(_In_opt_ PCWSTR newPath)
{
CSRWSharedAutoLock lock(&m_lock);
CoTaskMemFree(m_path);
m_path = nullptr;
HRESULT hr = S_OK;
if (newPath != nullptr)
{
hr = SHStrDup(newPath, &m_path);
}
return hr;
}
IFACEMETHODIMP CPowerRenameItem::GetPath(_Outptr_ PWSTR* path) IFACEMETHODIMP CPowerRenameItem::GetPath(_Outptr_ PWSTR* path)
{ {
*path = nullptr; *path = nullptr;
@ -84,6 +97,19 @@ IFACEMETHODIMP CPowerRenameItem::GetShellItem(_Outptr_ IShellItem** ppsi)
return SHCreateItemFromParsingName(m_path, nullptr, IID_PPV_ARGS(ppsi)); return SHCreateItemFromParsingName(m_path, nullptr, IID_PPV_ARGS(ppsi));
} }
IFACEMETHODIMP CPowerRenameItem::PutOriginalName(_In_opt_ PCWSTR originalName)
{
CSRWSharedAutoLock lock(&m_lock);
CoTaskMemFree(m_originalName);
m_originalName = nullptr;
HRESULT hr = S_OK;
if (originalName != nullptr)
{
hr = SHStrDup(originalName, &m_originalName);
}
return hr;
}
IFACEMETHODIMP CPowerRenameItem::GetOriginalName(_Outptr_ PWSTR* originalName) IFACEMETHODIMP CPowerRenameItem::GetOriginalName(_Outptr_ PWSTR* originalName)
{ {
CSRWSharedAutoLock lock(&m_lock); CSRWSharedAutoLock lock(&m_lock);

View File

@ -14,9 +14,11 @@ public:
IFACEMETHODIMP_(ULONG) Release(); IFACEMETHODIMP_(ULONG) Release();
// IPowerRenameItem // IPowerRenameItem
IFACEMETHODIMP PutPath(_In_opt_ PCWSTR newPath);
IFACEMETHODIMP GetPath(_Outptr_ PWSTR* path); IFACEMETHODIMP GetPath(_Outptr_ PWSTR* path);
IFACEMETHODIMP GetTime(_Outptr_ SYSTEMTIME* time); IFACEMETHODIMP GetTime(_Outptr_ SYSTEMTIME* time);
IFACEMETHODIMP GetShellItem(_Outptr_ IShellItem** ppsi); IFACEMETHODIMP GetShellItem(_Outptr_ IShellItem** ppsi);
IFACEMETHODIMP PutOriginalName(_In_opt_ PCWSTR originalName);
IFACEMETHODIMP GetOriginalName(_Outptr_ PWSTR* originalName); IFACEMETHODIMP GetOriginalName(_Outptr_ PWSTR* originalName);
IFACEMETHODIMP PutNewName(_In_opt_ PCWSTR newName); IFACEMETHODIMP PutNewName(_In_opt_ PCWSTR newName);
IFACEMETHODIMP GetNewName(_Outptr_ PWSTR* newName); IFACEMETHODIMP GetNewName(_Outptr_ PWSTR* newName);

View File

@ -40,10 +40,12 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Helpers.h" /> <ClInclude Include="Helpers.h" />
<ClInclude Include="MRUListHandler.h" />
<ClInclude Include="PowerRenameEnum.h" /> <ClInclude Include="PowerRenameEnum.h" />
<ClInclude Include="PowerRenameItem.h" /> <ClInclude Include="PowerRenameItem.h" />
<ClInclude Include="PowerRenameInterfaces.h" /> <ClInclude Include="PowerRenameInterfaces.h" />
<ClInclude Include="PowerRenameManager.h" /> <ClInclude Include="PowerRenameManager.h" />
<ClInclude Include="PowerRenameMRU.h" />
<ClInclude Include="PowerRenameRegEx.h" /> <ClInclude Include="PowerRenameRegEx.h" />
<ClInclude Include="Settings.h" /> <ClInclude Include="Settings.h" />
<ClInclude Include="srwlock.h" /> <ClInclude Include="srwlock.h" />
@ -53,9 +55,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Helpers.cpp" /> <ClCompile Include="Helpers.cpp" />
<ClCompile Include="MRUListHandler.cpp" />
<ClCompile Include="PowerRenameEnum.cpp" /> <ClCompile Include="PowerRenameEnum.cpp" />
<ClCompile Include="PowerRenameItem.cpp" /> <ClCompile Include="PowerRenameItem.cpp" />
<ClCompile Include="PowerRenameManager.cpp" /> <ClCompile Include="PowerRenameManager.cpp" />
<ClCompile Include="PowerRenameMRU.cpp" />
<ClCompile Include="PowerRenameRegEx.cpp" /> <ClCompile Include="PowerRenameRegEx.cpp" />
<ClCompile Include="Settings.cpp" /> <ClCompile Include="Settings.cpp" />
<ClCompile Include="pch.cpp"> <ClCompile Include="pch.cpp">
@ -70,6 +74,9 @@
<ProjectReference Include="..\..\..\common\SettingsAPI\SetttingsAPI.vcxproj"> <ProjectReference Include="..\..\..\common\SettingsAPI\SetttingsAPI.vcxproj">
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project> <Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\..\..\common\Themes\Themes.vcxproj">
<Project>{98537082-0fdb-40de-abd8-0dc5a4269bab}</Project>
</ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -0,0 +1,87 @@
#include "pch.h"
#include "PowerRenameMRU.h"
#include "Settings.h"
namespace
{
const wchar_t c_searchMRUListFilePath[] = L"\\search-mru.json";
const wchar_t c_replaceMRUListFilePath[] = L"\\replace-mru.json";
const wchar_t c_mruSearchRegPath[] = L"\\SearchMRU";
const wchar_t c_mruReplaceRegPath[] = L"\\ReplaceMRU";
}
CPowerRenameMRU::CPowerRenameMRU(int size, const std::wstring& filePath, const std::wstring& regPath) :
refCount(1)
{
mruList = std::make_unique<MRUListHandler>(size, filePath, regPath);
}
HRESULT CPowerRenameMRU::CreateInstance(_In_ const std::wstring& filePath, _In_ const std::wstring& regPath, _In_ REFIID iid, _Outptr_ void** resultInterface)
{
*resultInterface = nullptr;
unsigned int maxMRUSize = CSettingsInstance().GetMaxMRUSize();
HRESULT hr = E_FAIL;
if (maxMRUSize > 0)
{
CPowerRenameMRU* renameMRU = new CPowerRenameMRU(maxMRUSize, filePath, regPath);
hr = E_OUTOFMEMORY;
if (renameMRU)
{
renameMRU->QueryInterface(iid, resultInterface);
renameMRU->Release();
hr = S_OK;
}
}
return hr;
}
IFACEMETHODIMP_(ULONG)
CPowerRenameMRU::AddRef()
{
return InterlockedIncrement(&refCount);
}
IFACEMETHODIMP_(ULONG)
CPowerRenameMRU::Release()
{
unsigned int cnt = InterlockedDecrement(&refCount);
if (cnt == 0)
{
delete this;
}
return cnt;
}
IFACEMETHODIMP CPowerRenameMRU::QueryInterface(_In_ REFIID riid, _Outptr_ void** ppv)
{
static const QITAB qit[] = {
QITABENT(CPowerRenameMRU, IEnumString),
QITABENT(CPowerRenameMRU, IPowerRenameMRU),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
}
IFACEMETHODIMP_(const std::vector<std::wstring>&) CPowerRenameMRU::GetMRUStrings()
{
return mruList->GetItems();
}
IFACEMETHODIMP CPowerRenameMRU::AddMRUString(_In_ PCWSTR entry)
{
mruList->Push(entry);
return S_OK;
}
HRESULT CPowerRenameMRU::CPowerRenameMRUSearch_CreateInstance(_Outptr_ IPowerRenameMRU** ppUnk)
{
return CPowerRenameMRU::CreateInstance(c_searchMRUListFilePath, c_mruSearchRegPath, IID_PPV_ARGS(ppUnk));
}
HRESULT CPowerRenameMRU::CPowerRenameMRUReplace_CreateInstance(_Outptr_ IPowerRenameMRU** ppUnk)
{
return CPowerRenameMRU::CreateInstance(c_replaceMRUListFilePath, c_mruReplaceRegPath, IID_PPV_ARGS(ppUnk));
}

View File

@ -0,0 +1,34 @@
#pragma once
#include "pch.h"
#include "PowerRenameInterfaces.h"
#include "MRUListHandler.h"
#include <string>
#include <memory>
#include <vector>
class CPowerRenameMRU :
public IPowerRenameMRU
{
public:
// IUnknown
IFACEMETHODIMP_(ULONG)
AddRef();
IFACEMETHODIMP_(ULONG)
Release();
IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _Outptr_ void** ppv);
// IPowerRenameMRU
IFACEMETHODIMP AddMRUString(_In_ PCWSTR entry);
IFACEMETHODIMP_(const std::vector<std::wstring>&) GetMRUStrings();
static HRESULT CPowerRenameMRUSearch_CreateInstance(_Outptr_ IPowerRenameMRU** ppUnk);
static HRESULT CPowerRenameMRUReplace_CreateInstance(_Outptr_ IPowerRenameMRU** ppUnk);
private:
static HRESULT CreateInstance(_In_ const std::wstring& filePath, _In_ const std::wstring& regPath, _In_ REFIID iid, _Outptr_ void** resultInterface);
CPowerRenameMRU(int size, const std::wstring& filePath, const std::wstring& regPath);
std::unique_ptr<MRUListHandler> mruList;
unsigned int refCount = 0;
};

View File

@ -11,7 +11,7 @@
namespace fs = std::filesystem; namespace fs = std::filesystem;
extern HINSTANCE g_hInst; extern HINSTANCE g_hostHInst;
// The default FOF flags to use in the rename operations // The default FOF flags to use in the rename operations
#define FOF_DEFAULTFLAGS (FOF_ALLOWUNDO | FOFX_ADDUNDORECORD | FOFX_SHOWELEVATIONPROMPT | FOF_RENAMEONCOLLISION) #define FOF_DEFAULTFLAGS (FOF_ALLOWUNDO | FOFX_ADDUNDORECORD | FOFX_SHOWELEVATIONPROMPT | FOF_RENAMEONCOLLISION)
@ -92,12 +92,56 @@ IFACEMETHODIMP CPowerRenameManager::Stop()
return E_NOTIMPL; return E_NOTIMPL;
} }
IFACEMETHODIMP CPowerRenameManager::Rename(_In_ HWND hwndParent) IFACEMETHODIMP CPowerRenameManager::Rename(_In_ HWND hwndParent, bool closeWindow)
{ {
m_hwndParent = hwndParent; m_hwndParent = hwndParent;
m_closeUIWindowAfterRenaming = closeWindow;
return _PerformFileOperation(); return _PerformFileOperation();
} }
IFACEMETHODIMP CPowerRenameManager::UpdateChildrenPath(_In_ int parentId, _In_ size_t oldParentPathSize)
{
auto parentIt = m_renameItems.find(parentId);
if (parentIt != m_renameItems.end())
{
UINT depth = 0;
winrt::check_hresult(parentIt->second->GetDepth(&depth));
PWSTR renamedPath = nullptr;
winrt::check_hresult(parentIt->second->GetPath(&renamedPath));
std::wstring renamedPathStr{ renamedPath };
for (auto it = ++parentIt; it != m_renameItems.end(); ++it)
{
UINT nextDepth = 0;
winrt::check_hresult(it->second->GetDepth(&nextDepth));
if (nextDepth > depth)
{
// This is child, update path
PWSTR path = nullptr;
winrt::check_hresult(it->second->GetPath(&path));
std::wstring pathStr{ path };
std::wstring newPath = pathStr.replace(0, oldParentPathSize, renamedPath);
it->second->PutPath(newPath.c_str());
}
else
{
break;
}
}
}
return S_OK;
}
IFACEMETHODIMP CPowerRenameManager::GetCloseUIWindowAfterRenaming(_Out_ bool* closeUIWindowAfterRenaming)
{
*closeUIWindowAfterRenaming = m_closeUIWindowAfterRenaming;
return S_OK;
}
IFACEMETHODIMP CPowerRenameManager::Reset() IFACEMETHODIMP CPowerRenameManager::Reset()
{ {
// Stop all threads and wait // Stop all threads and wait
@ -338,21 +382,15 @@ IFACEMETHODIMP CPowerRenameManager::GetFilter(_Out_ DWORD* filter)
return S_OK; return S_OK;
} }
IFACEMETHODIMP CPowerRenameManager::SwitchFilter(_In_ int columnNumber) IFACEMETHODIMP CPowerRenameManager::SwitchFilter(_In_ int)
{ {
switch (m_filter) switch (m_filter)
{ {
case PowerRenameFilters::None: case PowerRenameFilters::None:
m_filter = (columnNumber == 0) ? PowerRenameFilters::Selected : PowerRenameFilters::ShouldRename; m_filter = PowerRenameFilters::ShouldRename;
break;
case PowerRenameFilters::Selected:
m_filter = (columnNumber == 0) ? PowerRenameFilters::FlagsApplicable : PowerRenameFilters::ShouldRename;
break;
case PowerRenameFilters::FlagsApplicable:
m_filter = (columnNumber == 0) ? PowerRenameFilters::None : PowerRenameFilters::ShouldRename;
break; break;
case PowerRenameFilters::ShouldRename: case PowerRenameFilters::ShouldRename:
m_filter = (columnNumber == 0) ? PowerRenameFilters::Selected : PowerRenameFilters::None; m_filter = PowerRenameFilters::None;
break; break;
} }
@ -458,7 +496,7 @@ HRESULT CPowerRenameManager::_Init()
m_startRegExWorkerEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); m_startRegExWorkerEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
m_cancelRegExWorkerEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); m_cancelRegExWorkerEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
m_hwndMessage = CreateMsgWindow(g_hInst, s_msgWndProc, this); m_hwndMessage = CreateMsgWindow(g_hostHInst, s_msgWndProc, this);
return S_OK; return S_OK;
} }
@ -467,6 +505,7 @@ HRESULT CPowerRenameManager::_Init()
enum enum
{ {
SRM_REGEX_ITEM_UPDATED = (WM_APP + 1), // Single rename item processed by regex worker thread SRM_REGEX_ITEM_UPDATED = (WM_APP + 1), // Single rename item processed by regex worker thread
SRM_REGEX_ITEM_RENAMED_KEEP_UI, // Single rename item processed by rename worker thread in case UI remains opened
SRM_REGEX_STARTED, // RegEx operation was started SRM_REGEX_STARTED, // RegEx operation was started
SRM_REGEX_CANCELED, // Regex operation was canceled SRM_REGEX_CANCELED, // Regex operation was canceled
SRM_REGEX_COMPLETE, // Regex worker thread completed SRM_REGEX_COMPLETE, // Regex worker thread completed
@ -523,6 +562,16 @@ LRESULT CPowerRenameManager::_WndProc(_In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM
} }
break; break;
} }
case SRM_REGEX_ITEM_RENAMED_KEEP_UI:
{
int id = static_cast<int>(lParam);
CComPtr<IPowerRenameItem> spItem;
if (SUCCEEDED(GetItemById(id, &spItem)))
{
_OnRename(spItem);
}
break;
}
case SRM_REGEX_STARTED: case SRM_REGEX_STARTED:
_OnRegExStarted(static_cast<DWORD>(wParam)); _OnRegExStarted(static_cast<DWORD>(wParam));
break; break;
@ -681,6 +730,9 @@ DWORD WINAPI CPowerRenameManager::s_fileOpWorkerThread(_In_ void* pv)
WorkerThreadData* pwtd = reinterpret_cast<WorkerThreadData*>(pv); WorkerThreadData* pwtd = reinterpret_cast<WorkerThreadData*>(pv);
if (pwtd) if (pwtd)
{ {
bool closeUIWindowAfterRenaming = true;
pwtd->spsrm->GetCloseUIWindowAfterRenaming(&closeUIWindowAfterRenaming);
// Wait to be told we can begin // Wait to be told we can begin
if (WaitForSingleObject(pwtd->startEvent, INFINITE) == WAIT_OBJECT_0) if (WaitForSingleObject(pwtd->startEvent, INFINITE) == WAIT_OBJECT_0)
{ {
@ -732,6 +784,38 @@ DWORD WINAPI CPowerRenameManager::s_fileOpWorkerThread(_In_ void* pv)
if (SUCCEEDED(spItem->GetShellItem(&spShellItem))) if (SUCCEEDED(spItem->GetShellItem(&spShellItem)))
{ {
spFileOp->RenameItem(spShellItem, newName, nullptr); spFileOp->RenameItem(spShellItem, newName, nullptr);
if (!closeUIWindowAfterRenaming)
{
// Update item data
PWSTR originalName = nullptr;
winrt::check_hresult(spItem->GetOriginalName(&originalName));
std::wstring originalNameStr{ originalName };
PWSTR path = nullptr;
winrt::check_hresult(spItem->GetPath(&path));
std::wstring pathStr{ path };
size_t oldPathSize = pathStr.size();
auto fileNamePos = pathStr.find_last_of(L"\\");
pathStr.replace(fileNamePos + 1, originalNameStr.length(), std::wstring{ newName });
spItem->PutPath(pathStr.c_str());
spItem->PutOriginalName(newName);
spItem->PutNewName(nullptr);
// if folder, update children path
bool isFolder = false;
winrt::check_hresult(spItem->GetIsFolder(&isFolder));
if (isFolder)
{
int id = -1;
winrt::check_hresult(spItem->GetId(&id));
pwtd->spsrm->UpdateChildrenPath(id, oldPathSize);
}
int id = -1;
winrt::check_hresult(spItem->GetId(&id));
PostMessage(pwtd->hwndManager, SRM_REGEX_ITEM_RENAMED_KEEP_UI, GetCurrentThreadId(), id);
}
} }
CoTaskMemFree(newName); CoTaskMemFree(newName);
} }
@ -1137,6 +1221,19 @@ void CPowerRenameManager::_OnUpdate(_In_ IPowerRenameItem* renameItem)
} }
} }
void CPowerRenameManager::_OnRename(_In_ IPowerRenameItem* renameItem)
{
CSRWSharedAutoLock lock(&m_lockEvents);
for (auto it : m_powerRenameManagerEvents)
{
if (it.pEvents)
{
it.pEvents->OnRename(renameItem);
}
}
}
void CPowerRenameManager::_OnError(_In_ IPowerRenameItem* renameItem) void CPowerRenameManager::_OnError(_In_ IPowerRenameItem* renameItem)
{ {
CSRWSharedAutoLock lock(&m_lockEvents); CSRWSharedAutoLock lock(&m_lockEvents);
@ -1210,7 +1307,7 @@ void CPowerRenameManager::_OnRenameCompleted()
{ {
if (it.pEvents) if (it.pEvents)
{ {
it.pEvents->OnRenameCompleted(); it.pEvents->OnRenameCompleted(m_closeUIWindowAfterRenaming);
} }
} }
} }

View File

@ -3,8 +3,7 @@
#include <map> #include <map>
#include "srwlock.h" #include "srwlock.h"
#include <lib/PowerRenameManager.h> #include <PowerRenameInterfaces.h>
#include <lib/PowerRenameInterfaces.h>
class CPowerRenameManager : class CPowerRenameManager :
public IPowerRenameManager, public IPowerRenameManager,
@ -23,7 +22,9 @@ public:
IFACEMETHODIMP Stop(); IFACEMETHODIMP Stop();
IFACEMETHODIMP Reset(); IFACEMETHODIMP Reset();
IFACEMETHODIMP Shutdown(); IFACEMETHODIMP Shutdown();
IFACEMETHODIMP Rename(_In_ HWND hwndParent); IFACEMETHODIMP Rename(_In_ HWND hwndParent, bool closeWindow);
IFACEMETHODIMP UpdateChildrenPath(_In_ int parentId, _In_ size_t oldParentPathSize);
IFACEMETHODIMP GetCloseUIWindowAfterRenaming(_Out_ bool* closeUIWindowAfterRenaming);
IFACEMETHODIMP AddItem(_In_ IPowerRenameItem* pItem); IFACEMETHODIMP AddItem(_In_ IPowerRenameItem* pItem);
IFACEMETHODIMP GetItemByIndex(_In_ UINT index, _COM_Outptr_ IPowerRenameItem** ppItem); IFACEMETHODIMP GetItemByIndex(_In_ UINT index, _COM_Outptr_ IPowerRenameItem** ppItem);
IFACEMETHODIMP GetVisibleItemByIndex(_In_ UINT index, _COM_Outptr_ IPowerRenameItem** ppItem); IFACEMETHODIMP GetVisibleItemByIndex(_In_ UINT index, _COM_Outptr_ IPowerRenameItem** ppItem);
@ -61,6 +62,7 @@ protected:
void _OnItemAdded(_In_ IPowerRenameItem* renameItem); void _OnItemAdded(_In_ IPowerRenameItem* renameItem);
void _OnUpdate(_In_ IPowerRenameItem* renameItem); void _OnUpdate(_In_ IPowerRenameItem* renameItem);
void _OnRename(_In_ IPowerRenameItem* renameItem);
void _OnError(_In_ IPowerRenameItem* renameItem); void _OnError(_In_ IPowerRenameItem* renameItem);
void _OnRegExStarted(_In_ DWORD threadId); void _OnRegExStarted(_In_ DWORD threadId);
void _OnRegExCanceled(_In_ DWORD threadId); void _OnRegExCanceled(_In_ DWORD threadId);
@ -125,6 +127,7 @@ protected:
// Parent HWND used by IFileOperation // Parent HWND used by IFileOperation
HWND m_hwndParent = nullptr; HWND m_hwndParent = nullptr;
bool m_closeUIWindowAfterRenaming = true;
HWND m_hwndMessage = nullptr; HWND m_hwndMessage = nullptr;

View File

@ -85,9 +85,9 @@ IFACEMETHODIMP CPowerRenameRegEx::GetSearchTerm(_Outptr_ PWSTR* searchTerm)
return hr; return hr;
} }
IFACEMETHODIMP CPowerRenameRegEx::PutSearchTerm(_In_ PCWSTR searchTerm) IFACEMETHODIMP CPowerRenameRegEx::PutSearchTerm(_In_ PCWSTR searchTerm, bool forceRenaming)
{ {
bool changed = false; bool changed = false || forceRenaming;
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (searchTerm) if (searchTerm)
{ {
@ -96,9 +96,16 @@ IFACEMETHODIMP CPowerRenameRegEx::PutSearchTerm(_In_ PCWSTR searchTerm)
{ {
changed = true; changed = true;
CoTaskMemFree(m_searchTerm); CoTaskMemFree(m_searchTerm);
if (lstrcmp(searchTerm, L"") == 0)
{
m_searchTerm = NULL;
}
else
{
hr = SHStrDup(searchTerm, &m_searchTerm); hr = SHStrDup(searchTerm, &m_searchTerm);
} }
} }
}
if (SUCCEEDED(hr) && changed) if (SUCCEEDED(hr) && changed)
{ {
@ -120,9 +127,9 @@ IFACEMETHODIMP CPowerRenameRegEx::GetReplaceTerm(_Outptr_ PWSTR* replaceTerm)
return hr; return hr;
} }
IFACEMETHODIMP CPowerRenameRegEx::PutReplaceTerm(_In_ PCWSTR replaceTerm) IFACEMETHODIMP CPowerRenameRegEx::PutReplaceTerm(_In_ PCWSTR replaceTerm, bool forceRenaming)
{ {
bool changed = false; bool changed = false || forceRenaming;
HRESULT hr = S_OK; HRESULT hr = S_OK;
if (replaceTerm) if (replaceTerm)
{ {

View File

@ -20,9 +20,9 @@ public:
IFACEMETHODIMP Advise(_In_ IPowerRenameRegExEvents* regExEvents, _Out_ DWORD* cookie); IFACEMETHODIMP Advise(_In_ IPowerRenameRegExEvents* regExEvents, _Out_ DWORD* cookie);
IFACEMETHODIMP UnAdvise(_In_ DWORD cookie); IFACEMETHODIMP UnAdvise(_In_ DWORD cookie);
IFACEMETHODIMP GetSearchTerm(_Outptr_ PWSTR* searchTerm); IFACEMETHODIMP GetSearchTerm(_Outptr_ PWSTR* searchTerm);
IFACEMETHODIMP PutSearchTerm(_In_ PCWSTR searchTerm); IFACEMETHODIMP PutSearchTerm(_In_ PCWSTR searchTerm, bool forceRenaming);
IFACEMETHODIMP GetReplaceTerm(_Outptr_ PWSTR* replaceTerm); IFACEMETHODIMP GetReplaceTerm(_Outptr_ PWSTR* replaceTerm);
IFACEMETHODIMP PutReplaceTerm(_In_ PCWSTR replaceTerm); IFACEMETHODIMP PutReplaceTerm(_In_ PCWSTR replaceTerm, bool forceRenaming);
IFACEMETHODIMP GetFlags(_Out_ DWORD* flags); IFACEMETHODIMP GetFlags(_Out_ DWORD* flags);
IFACEMETHODIMP PutFlags(_In_ DWORD flags); IFACEMETHODIMP PutFlags(_In_ DWORD flags);
IFACEMETHODIMP PutFileTime(_In_ SYSTEMTIME fileTime); IFACEMETHODIMP PutFileTime(_In_ SYSTEMTIME fileTime);

View File

@ -1,6 +1,7 @@
#include "pch.h" #include "pch.h"
#include "Settings.h" #include "Settings.h"
#include "PowerRenameInterfaces.h" #include "PowerRenameInterfaces.h"
#include "Helpers.h"
#include <common/SettingsAPI/settings_helpers.h> #include <common/SettingsAPI/settings_helpers.h>
#include <filesystem> #include <filesystem>
@ -13,12 +14,6 @@ namespace
{ {
const wchar_t c_powerRenameDataFilePath[] = L"\\power-rename-settings.json"; const wchar_t c_powerRenameDataFilePath[] = L"\\power-rename-settings.json";
const wchar_t c_powerRenameUIFlagsFilePath[] = L"\\power-rename-ui-flags"; const wchar_t c_powerRenameUIFlagsFilePath[] = L"\\power-rename-ui-flags";
const wchar_t c_searchMRUListFilePath[] = L"\\search-mru.json";
const wchar_t c_replaceMRUListFilePath[] = L"\\replace-mru.json";
const wchar_t c_rootRegPath[] = L"Software\\Microsoft\\PowerRename";
const wchar_t c_mruSearchRegPath[] = L"\\SearchMRU";
const wchar_t c_mruReplaceRegPath[] = L"\\ReplaceMRU";
const wchar_t c_enabled[] = L"Enabled"; const wchar_t c_enabled[] = L"Enabled";
const wchar_t c_showIconOnMenu[] = L"ShowIcon"; const wchar_t c_showIconOnMenu[] = L"ShowIcon";
@ -29,380 +24,8 @@ namespace
const wchar_t c_searchText[] = L"SearchText"; const wchar_t c_searchText[] = L"SearchText";
const wchar_t c_replaceText[] = L"ReplaceText"; const wchar_t c_replaceText[] = L"ReplaceText";
const wchar_t c_mruEnabled[] = L"MRUEnabled"; const wchar_t c_mruEnabled[] = L"MRUEnabled";
const wchar_t c_mruList[] = L"MRUList";
const wchar_t c_insertionIdx[] = L"InsertionIdx";
const wchar_t c_useBoostLib[] = L"UseBoostLib"; const wchar_t c_useBoostLib[] = L"UseBoostLib";
unsigned int GetRegNumber(const std::wstring& valueName, unsigned int defaultValue)
{
DWORD type = REG_DWORD;
DWORD data = 0;
DWORD size = sizeof(DWORD);
if (SHGetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), &type, &data, &size) == ERROR_SUCCESS)
{
return data;
}
return defaultValue;
}
void SetRegNumber(const std::wstring& valueName, unsigned int value)
{
SHSetValue(HKEY_CURRENT_USER, c_rootRegPath, valueName.c_str(), REG_DWORD, &value, sizeof(value));
}
bool GetRegBoolean(const std::wstring& valueName, bool defaultValue)
{
DWORD value = GetRegNumber(valueName.c_str(), defaultValue ? 1 : 0);
return (value == 0) ? false : true;
}
void SetRegBoolean(const std::wstring& valueName, bool value)
{
SetRegNumber(valueName, value ? 1 : 0);
}
std::wstring GetRegString(const std::wstring& valueName, const std::wstring& subPath)
{
wchar_t value[CSettings::MAX_INPUT_STRING_LEN];
value[0] = L'\0';
DWORD type = REG_SZ;
DWORD size = CSettings::MAX_INPUT_STRING_LEN * sizeof(wchar_t);
std::wstring completePath = std::wstring(c_rootRegPath) + subPath;
if (SHGetValue(HKEY_CURRENT_USER, completePath.c_str(), valueName.c_str(), &type, value, &size) == ERROR_SUCCESS)
{
return std::wstring(value);
}
return std::wstring{};
}
bool LastModifiedTime(const std::wstring& filePath, FILETIME* lpFileTime)
{
WIN32_FILE_ATTRIBUTE_DATA attr{};
if (GetFileAttributesExW(filePath.c_str(), GetFileExInfoStandard, &attr))
{
*lpFileTime = attr.ftLastWriteTime;
return true;
}
return false;
}
}
class MRUListHandler
{
public:
MRUListHandler(unsigned int size, const std::wstring& filePath, const std::wstring& regPath) :
pushIdx(0),
nextIdx(1),
size(size),
jsonFilePath(PTSettingsHelper::get_module_save_folder_location(PowerRenameConstants::ModuleKey) + filePath),
registryFilePath(regPath)
{
items.resize(size);
Load();
}
void Push(const std::wstring& data);
bool Next(std::wstring& data);
void Reset();
private:
void Load();
void Save();
void MigrateFromRegistry();
json::JsonArray Serialize();
void ParseJson();
bool Exists(const std::wstring& data);
std::vector<std::wstring> items;
unsigned int pushIdx;
unsigned int nextIdx;
unsigned int size;
const std::wstring jsonFilePath;
const std::wstring registryFilePath;
};
void MRUListHandler::Push(const std::wstring& data)
{
if (Exists(data))
{
// TODO: Already existing item should be put on top of MRU list.
return;
}
items[pushIdx] = data;
pushIdx = (pushIdx + 1) % size;
Save();
}
bool MRUListHandler::Next(std::wstring& data)
{
if (nextIdx == size + 1)
{
Reset();
return false;
}
// Go backwards to consume latest items first.
unsigned int idx = (pushIdx + size - nextIdx) % size;
if (items[idx].empty())
{
Reset();
return false;
}
data = items[idx];
++nextIdx;
return true;
}
void MRUListHandler::Reset()
{
nextIdx = 1;
}
void MRUListHandler::Load()
{
if (!std::filesystem::exists(jsonFilePath))
{
MigrateFromRegistry();
Save();
}
else
{
ParseJson();
}
}
void MRUListHandler::Save()
{
json::JsonObject jsonData;
jsonData.SetNamedValue(c_maxMRUSize, json::value(size));
jsonData.SetNamedValue(c_insertionIdx, json::value(pushIdx));
jsonData.SetNamedValue(c_mruList, Serialize());
json::to_file(jsonFilePath, jsonData);
}
json::JsonArray MRUListHandler::Serialize()
{
json::JsonArray searchMRU{};
std::wstring data{};
for (const std::wstring& item : items)
{
searchMRU.Append(json::value(item));
}
return searchMRU;
}
void MRUListHandler::MigrateFromRegistry()
{
std::wstring searchListKeys = GetRegString(c_mruList, registryFilePath);
std::sort(std::begin(searchListKeys), std::end(searchListKeys));
for (const wchar_t& key : searchListKeys)
{
Push(GetRegString(std::wstring(1, key), registryFilePath));
}
}
void MRUListHandler::ParseJson()
{
auto json = json::from_file(jsonFilePath);
if (json)
{
const json::JsonObject& jsonObject = json.value();
try
{
unsigned int oldSize{ size };
if (json::has(jsonObject, c_maxMRUSize, json::JsonValueType::Number))
{
oldSize = (unsigned int)jsonObject.GetNamedNumber(c_maxMRUSize);
}
unsigned int oldPushIdx{ 0 };
if (json::has(jsonObject, c_insertionIdx, json::JsonValueType::Number))
{
oldPushIdx = (unsigned int)jsonObject.GetNamedNumber(c_insertionIdx);
if (oldPushIdx < 0 || oldPushIdx >= oldSize)
{
oldPushIdx = 0;
}
}
if (json::has(jsonObject, c_mruList, json::JsonValueType::Array))
{
auto jsonArray = jsonObject.GetNamedArray(c_mruList);
if (oldSize == size)
{
for (uint32_t i = 0; i < jsonArray.Size(); ++i)
{
items[i] = std::wstring(jsonArray.GetStringAt(i));
}
pushIdx = oldPushIdx;
}
else
{
std::vector<std::wstring> temp;
for (unsigned int i = 0; i < min(jsonArray.Size(), size); ++i)
{
int idx = (oldPushIdx + oldSize - (i + 1)) % oldSize;
temp.push_back(std::wstring(jsonArray.GetStringAt(idx)));
}
if (size > oldSize)
{
std::reverse(std::begin(temp), std::end(temp));
pushIdx = (unsigned int)temp.size();
temp.resize(size);
}
else
{
temp.resize(size);
std::reverse(std::begin(temp), std::end(temp));
}
items = std::move(temp);
Save();
}
}
}
catch (const winrt::hresult_error&)
{
}
}
}
bool MRUListHandler::Exists(const std::wstring& data)
{
return std::find(std::begin(items), std::end(items), data) != std::end(items);
}
class CRenameMRU :
public IEnumString,
public IPowerRenameMRU
{
public:
// IUnknown
IFACEMETHODIMP_(ULONG)
AddRef();
IFACEMETHODIMP_(ULONG)
Release();
IFACEMETHODIMP QueryInterface(_In_ REFIID riid, _Outptr_ void** ppv);
// IEnumString
IFACEMETHODIMP Next(__in ULONG celt, __out_ecount_part(celt, *pceltFetched) LPOLESTR* rgelt, __out_opt ULONG* pceltFetched);
IFACEMETHODIMP Skip(__in ULONG) { return E_NOTIMPL; }
IFACEMETHODIMP Reset();
IFACEMETHODIMP Clone(__deref_out IEnumString** ppenum)
{
*ppenum = nullptr;
return E_NOTIMPL;
}
// IPowerRenameMRU
IFACEMETHODIMP AddMRUString(_In_ PCWSTR entry);
static HRESULT CreateInstance(_In_ const std::wstring& filePath, _In_ const std::wstring& regPath, _Outptr_ IUnknown** ppUnk);
private:
CRenameMRU(int size, const std::wstring& filePath, const std::wstring& regPath);
std::unique_ptr<MRUListHandler> mruList;
unsigned int refCount = 0;
};
CRenameMRU::CRenameMRU(int size, const std::wstring& filePath, const std::wstring& regPath) :
refCount(1)
{
mruList = std::make_unique<MRUListHandler>(size, filePath, regPath);
}
HRESULT CRenameMRU::CreateInstance(_In_ const std::wstring& filePath, _In_ const std::wstring& regPath, _Outptr_ IUnknown** ppUnk)
{
*ppUnk = nullptr;
unsigned int maxMRUSize = CSettingsInstance().GetMaxMRUSize();
HRESULT hr = E_FAIL;
if (maxMRUSize > 0)
{
CRenameMRU* renameMRU = new CRenameMRU(maxMRUSize, filePath, regPath);
hr = E_OUTOFMEMORY;
if (renameMRU)
{
renameMRU->QueryInterface(IID_PPV_ARGS(ppUnk));
renameMRU->Release();
hr = S_OK;
}
}
return hr;
}
IFACEMETHODIMP_(ULONG)
CRenameMRU::AddRef()
{
return InterlockedIncrement(&refCount);
}
IFACEMETHODIMP_(ULONG)
CRenameMRU::Release()
{
unsigned int cnt = InterlockedDecrement(&refCount);
if (cnt == 0)
{
delete this;
}
return cnt;
}
IFACEMETHODIMP CRenameMRU::QueryInterface(_In_ REFIID riid, _Outptr_ void** ppv)
{
static const QITAB qit[] = {
QITABENT(CRenameMRU, IEnumString),
QITABENT(CRenameMRU, IPowerRenameMRU),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
}
IFACEMETHODIMP CRenameMRU::Next(__in ULONG celt, __out_ecount_part(celt, *pceltFetched) LPOLESTR* rgelt, __out_opt ULONG* pceltFetched)
{
if (pceltFetched)
{
*pceltFetched = 0;
}
if (!celt)
{
return S_OK;
}
if (!rgelt)
{
return S_FALSE;
}
HRESULT hr = S_FALSE;
if (std::wstring data{}; mruList->Next(data))
{
hr = SHStrDup(data.c_str(), rgelt);
if (SUCCEEDED(hr) && pceltFetched != nullptr)
{
*pceltFetched = 1;
}
}
return hr;
}
IFACEMETHODIMP CRenameMRU::Reset()
{
mruList->Reset();
return S_OK;
}
IFACEMETHODIMP CRenameMRU::AddMRUString(_In_ PCWSTR entry)
{
mruList->Push(entry);
return S_OK;
} }
CSettings::CSettings() CSettings::CSettings()
@ -547,13 +170,3 @@ CSettings& CSettingsInstance()
static CSettings instance; static CSettings instance;
return instance; return instance;
} }
HRESULT CRenameMRUSearch_CreateInstance(_Outptr_ IUnknown** ppUnk)
{
return CRenameMRU::CreateInstance(c_searchMRUListFilePath, c_mruSearchRegPath, ppUnk);
}
HRESULT CRenameMRUReplace_CreateInstance(_Outptr_ IUnknown** ppUnk)
{
return CRenameMRU::CreateInstance(c_replaceMRUListFilePath, c_mruReplaceRegPath, ppUnk);
}

View File

@ -5,8 +5,6 @@
class CSettings class CSettings
{ {
public: public:
static const int MAX_INPUT_STRING_LEN = 1024;
CSettings(); CSettings();
inline bool GetEnabled() inline bool GetEnabled()
@ -146,6 +144,3 @@ private:
}; };
CSettings& CSettingsInstance(); CSettings& CSettingsInstance();
HRESULT CRenameMRUSearch_CreateInstance(_Outptr_ IUnknown** ppUnk);
HRESULT CRenameMRUReplace_CreateInstance(_Outptr_ IUnknown** ppUnk);

View File

@ -5,13 +5,16 @@
#include "PowerRenameTest.h" #include "PowerRenameTest.h"
#include <PowerRenameInterfaces.h> #include <PowerRenameInterfaces.h>
#include <PowerRenameItem.h> #include <PowerRenameItem.h>
#include <PowerRenameUI.h>
#include <PowerRenameManager.h> #include <PowerRenameManager.h>
#include <Shobjidl.h> #include <Shobjidl.h>
#include <atlfile.h>
#include <atlstr.h>
#include <common/utils/process_path.h>
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
HINSTANCE g_hInst; HINSTANCE g_hostHInst;
void ModuleAddRef() {} void ModuleAddRef() {}
void ModuleRelease() {} void ModuleRelease() {}
@ -29,34 +32,52 @@ int APIENTRY wWinMain(
_In_ PWSTR lpCmdLine, _In_ PWSTR lpCmdLine,
_In_ int nCmdShow) _In_ int nCmdShow)
{ {
g_hInst = hInstance; g_hostHInst = hInstance;
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
// Create the rename manager // Set the application path based on the location of the dll
CComPtr<IPowerRenameManager> spsrm; std::wstring path = get_module_folderpath(g_hostHInst);
if (SUCCEEDED(CPowerRenameManager::s_CreateInstance(&spsrm))) path = path + L"\\PowerRename.exe";
{ LPTSTR lpApplicationName = (LPTSTR)path.c_str();
// Create the factory for our items
CComPtr<IPowerRenameItemFactory> spsrif;
if (SUCCEEDED(CPowerRenameItem::s_CreateInstance(nullptr, IID_PPV_ARGS(&spsrif))))
{
// Pass the factory to the manager
if (SUCCEEDED(spsrm->PutRenameItemFactory(spsrif)))
{
// Create the rename UI instance and pass the manager
CComPtr<IPowerRenameUI> spsrui;
if (SUCCEEDED(CPowerRenameUI::s_CreateInstance(spsrm, nullptr, true, &spsrui)))
{
// Call blocks until we are done
spsrui->Show(NULL);
spsrui->Close();
// Need to call shutdown to break circular dependencies CString commandLine;
spsrm->Shutdown(); commandLine.Format(_T("\"%s\""), lpApplicationName);
}
} int nSize = commandLine.GetLength() + 1;
LPTSTR lpszCommandLine = new TCHAR[nSize];
_tcscpy_s(lpszCommandLine, nSize, commandLine);
STARTUPINFO startupInfo;
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
startupInfo.cb = sizeof(STARTUPINFO);
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
startupInfo.wShowWindow = SW_SHOWNORMAL;
PROCESS_INFORMATION processInformation;
// Start the resizer
CreateProcess(
NULL,
lpszCommandLine,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&startupInfo,
&processInformation);
delete[] lpszCommandLine;
if (!CloseHandle(processInformation.hProcess))
{
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
} }
if (!CloseHandle(processInformation.hThread))
{
hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
} }
CoUninitialize(); CoUninitialize();
} }

View File

@ -38,7 +38,7 @@
<PreprocessorDefinitions>WIN32;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>$(OutDir)PowerRenameLib.lib;$(OutDir)PowerRenameUI.lib;Pathcch.lib;comctl32.lib;$(SolutionDir)$(Platform)\$(Configuration)\obj\PowerRenameUI\PowerRenameUI.res;shlwapi.lib;shcore.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>$(OutDir)PowerRenameLib.lib;Pathcch.lib;comctl32.lib;shlwapi.lib;shcore.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>

View File

@ -1,85 +0,0 @@
// Microsoft Visual C++ generated resource script.
⼀⼀ഀ<EFBFBD>
⌀椀渀挀氀甀搀攀 ∀爀攀猀漀甀爀挀攀⸀栀∀ഀ<EFBFBD>
<EFBFBD>
⌀搀攀昀椀渀攀 䄀倀匀吀唀䐀䤀伀开刀䔀䄀䐀伀一䰀夀开匀夀䴀䈀伀䰀匀ഀ<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䜀攀渀攀爀愀琀攀搀 昀爀漀洀 琀栀攀 吀䔀堀吀䤀一䌀䰀唀䐀䔀  爀攀猀漀甀爀挀攀⸀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⌀椀昀渀搀攀昀 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
⌀椀渀挀氀甀搀攀 ∀琀愀爀最攀琀瘀攀爀⸀栀∀ഀ<EFBFBD>
⌀攀渀搀椀昀ഀ<EFBFBD>
⌀搀攀昀椀渀攀 䄀倀匀吀唀䐀䤀伀开䠀䤀䐀䐀䔀一开匀夀䴀䈀伀䰀匀ഀ<EFBFBD>
⌀椀渀挀氀甀搀攀 ∀眀椀渀搀漀眀猀⸀栀∀ഀ<EFBFBD>
⌀甀渀搀攀昀 䄀倀匀吀唀䐀䤀伀开䠀䤀䐀䐀䔀一开匀夀䴀䈀伀䰀匀ഀ<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⌀甀渀搀攀昀 䄀倀匀吀唀䐀䤀伀开刀䔀䄀䐀伀一䰀夀开匀夀䴀䈀伀䰀匀ഀ<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䤀挀漀渀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
<EFBFBD>
⼀⼀ 䤀挀漀渀 眀椀琀栀 氀漀眀攀猀琀 䤀䐀 瘀愀氀甀攀 瀀氀愀挀攀搀 昀椀爀猀琀 琀漀 攀渀猀甀爀攀 愀瀀瀀氀椀挀愀琀椀漀渀 椀挀漀渀ഀ<EFBFBD>
⼀⼀ 爀攀洀愀椀渀猀 挀漀渀猀椀猀琀攀渀琀 漀渀 愀氀氀 猀礀猀琀攀洀猀⸀ഀ<EFBFBD>
䤀䐀䤀开刀䔀一䄀䴀䔀              䤀䌀伀一                    ∀倀漀眀攀爀刀攀渀愀洀攀⸀椀挀漀∀ഀ<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䐀椀愀氀漀最ഀ<EFBFBD>
⼀⼀ 堀倀伀匀 夀倀伀匀 圀䤀䐀吀䠀 䠀䔀䤀䜀䠀吀ഀ<EFBFBD>
<EFBFBD>
䤀䐀䐀开䴀䄀䤀一 䐀䤀䄀䰀伀䜀䔀堀     ㌀㘀㐀Ⰰ ㌀㔀㤀ഀ<EFBFBD>
匀吀夀䰀䔀 䐀匀开匀䔀吀䘀伀一吀  䐀匀开䘀䤀堀䔀䐀匀夀匀  䐀匀开䌀䔀一吀䔀刀  圀匀开䴀䤀一䤀䴀䤀娀䔀䈀伀堀  圀匀开䴀䄀堀䤀䴀䤀娀䔀䈀伀堀  圀匀开倀伀倀唀倀  圀匀开䌀䄀倀吀䤀伀一  圀匀开匀夀匀䴀䔀一唀  圀匀开吀䠀䤀䌀䬀䘀刀䄀䴀䔀ഀ<EFBFBD>
䌀䄀倀吀䤀伀一 ∀∀ഀ<EFBFBD>
䘀伀一吀 㠀Ⰰ ∀䴀匀 匀栀攀氀氀 䐀氀最∀Ⰰ       砀㄀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD>
    䔀䐀䤀吀吀䔀堀吀        䤀䐀䌀开䔀䐀䤀吀开匀䔀䄀刀䌀䠀䘀伀刀Ⰰ㄀ ㄀Ⰰ㈀ Ⰰ㈀㈀㤀Ⰰ㄀㌀Ⰰ䔀匀开䄀唀吀伀䠀匀䌀刀伀䰀䰀ഀ<EFBFBD>
    䔀䐀䤀吀吀䔀堀吀        䤀䐀䌀开䔀䐀䤀吀开刀䔀倀䰀䄀䌀䔀圀䤀吀䠀Ⰰ㄀ ㄀Ⰰ㌀㠀Ⰰ㈀㈀㤀Ⰰ㄀㌀Ⰰ䔀匀开䄀唀吀伀䠀匀䌀刀伀䰀䰀 <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开䌀䠀䔀䌀䬀开唀匀䔀刀䔀䜀䔀堀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㈀㄀Ⰰ 㠀㌀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开䌀䠀䔀䌀䬀开䴀䄀吀䌀䠀䄀䰀䰀伀䌀䌀唀刀䔀一䌀䔀匀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㈀㄀Ⰰ 㤀㔀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开䌀䠀䔀䌀䬀开䌀䄀匀䔀匀䔀一匀䤀吀䤀嘀䔀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㈀㄀Ⰰ  㜀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开䌀䠀䔀䌀䬀开䔀一唀䴀䤀吀䔀䴀匀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㈀㄀Ⰰ ㄀㄀㤀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开䌀䠀䔀䌀䬀开一䄀䴀䔀伀一䰀夀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㈀㄀Ⰰ ㄀㌀㄀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开䌀䠀䔀䌀䬀开䔀堀吀䔀一匀䤀伀一伀一䰀夀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㈀㄀Ⰰ ㄀㐀㌀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开䌀䠀䔀䌀䬀开䔀堀䌀䰀唀䐀䔀䘀伀䰀䐀䔀刀匀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㈀㄀Ⰰ ㄀㔀㔀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开䌀䠀䔀䌀䬀开䔀堀䌀䰀唀䐀䔀䘀䤀䰀䔀匀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㄀㠀㄀Ⰰ 㠀㌀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开䌀䠀䔀䌀䬀开䔀堀䌀䰀唀䐀䔀匀唀䈀䘀伀䰀䐀䔀刀匀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㄀㠀㄀Ⰰ 㤀㔀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开吀刀䄀一匀䘀伀刀䴀开唀倀倀䔀刀䌀䄀匀䔀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㄀㠀㄀Ⰰ  㜀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开吀刀䄀一匀䘀伀刀䴀开䰀伀圀䔀刀䌀䄀匀䔀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㄀㠀㄀Ⰰ ㄀㄀㤀Ⰰ ㄀㔀    <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开吀刀䄀一匀䘀伀刀䴀开吀䤀吀䰀䔀䌀䄀匀䔀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㄀㠀㄀Ⰰ ㄀㌀㄀Ⰰ ㄀㔀   <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开吀刀䄀一匀䘀伀刀䴀开䌀䄀倀䤀吀䄀䰀䤀娀䔀䐀Ⰰ ∀䈀甀琀琀漀渀∀Ⰰ 䈀匀开䄀唀吀伀䌀䠀䔀䌀䬀䈀伀堀  圀匀开吀䄀䈀匀吀伀倀Ⰰ ㄀㠀㄀Ⰰ ㄀㐀㌀Ⰰ ㄀㔀   <EFBFBD>
    䌀伀一吀刀伀䰀         ∀∀Ⰰ䤀䐀䌀开䰀䤀匀吀开倀刀䔀嘀䤀䔀圀Ⰰ∀匀礀猀䰀椀猀琀嘀椀攀眀㌀㈀∀Ⰰ䰀嘀匀开刀䔀倀伀刀吀  䰀嘀匀开䄀䰀䤀䜀一䰀䔀䘀吀  䰀嘀匀开伀圀一䔀刀䐀䄀吀䄀  圀匀开䈀伀刀䐀䔀刀  圀匀开吀䄀䈀匀吀伀倀Ⰰ㈀㈀Ⰰ㈀ ㈀Ⰰ㌀ 㠀Ⰰ㄀㄀㘀 <EFBFBD>
    䐀䔀䘀倀唀匀䠀䈀唀吀吀伀一   ∀∀Ⰰ䤀䐀开刀䔀一䄀䴀䔀Ⰰ㄀㜀㠀Ⰰ㌀㌀㜀Ⰰ㔀 Ⰰ㄀㐀ഀ<EFBFBD>
    倀唀匀䠀䈀唀吀吀伀一      ∀∀Ⰰ䤀䐀开䄀䈀伀唀吀Ⰰ㈀㌀㐀Ⰰ㌀㌀㜀Ⰰ㔀 Ⰰ㄀㐀ഀ<EFBFBD>
    倀唀匀䠀䈀唀吀吀伀一      ∀∀Ⰰ䤀䐀䌀䄀一䌀䔀䰀Ⰰ㈀㤀 Ⰰ㌀㌀㜀Ⰰ㔀 Ⰰ㄀㐀ഀ<EFBFBD>
    刀吀䔀堀吀           ∀∀Ⰰ䤀䐀䌀开匀䔀䄀刀䌀䠀开䘀伀刀Ⰰ㈀㄀Ⰰ㈀㌀Ⰰ㜀㔀Ⰰ㠀ഀ<EFBFBD>
    刀吀䔀堀吀           ∀∀Ⰰ䤀䐀䌀开刀䔀倀䰀䄀䌀䔀开圀䤀吀䠀Ⰰ㈀㄀Ⰰ㐀 Ⰰ㜀㔀Ⰰ㠀ഀ<EFBFBD>
    䰀吀䔀堀吀           ∀∀Ⰰ䤀䐀䌀开匀吀䄀吀唀匀开䴀䔀匀匀䄀䜀䔀开匀䔀䰀䔀䌀吀䔀䐀Ⰰ ㄀㄀Ⰰ ㌀㌀㔀Ⰰ ㄀㌀㜀Ⰰ ㄀㌀ <EFBFBD>
    䰀吀䔀堀吀           ∀∀Ⰰ䤀䐀䌀开匀吀䄀吀唀匀开䴀䔀匀匀䄀䜀䔀开刀䔀一䄀䴀䤀一䜀Ⰰ ㄀㄀Ⰰ ㌀㐀㔀Ⰰ ㄀㌀㜀Ⰰ ㄀㌀ഀ<EFBFBD>
    䜀刀伀唀倀䈀伀堀        ∀∀Ⰰ䤀䐀䌀开伀倀吀䤀伀一匀䜀刀伀唀倀Ⰰ㄀㄀Ⰰ㘀㠀Ⰰ㌀㈀㤀Ⰰ㄀ 㘀ഀ<EFBFBD>
    䜀刀伀唀倀䈀伀堀        ∀∀Ⰰ䤀䐀䌀开倀刀䔀嘀䤀䔀圀䜀刀伀唀倀Ⰰ㄀㄀Ⰰ㄀㠀㜀Ⰰ㌀㈀㤀Ⰰ㄀㐀㈀ഀ<EFBFBD>
    䜀刀伀唀倀䈀伀堀        ∀∀Ⰰ䤀䐀䌀开匀䔀䄀刀䌀䠀刀䔀倀䰀䄀䌀䔀䜀刀伀唀倀Ⰰ㄀㄀Ⰰ㜀Ⰰ㌀㈀㤀Ⰰ㔀㔀ഀ<EFBFBD>
䔀一䐀ഀ<EFBFBD>
<EFBFBD>
<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
⼀⼀ 䐀䔀匀䤀䜀一䤀一䘀伀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
<EFBFBD>
⌀椀昀搀攀昀 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
䜀唀䤀䐀䔀䰀䤀一䔀匀 䐀䔀匀䤀䜀一䤀一䘀伀ഀ<EFBFBD>
䈀䔀䜀䤀一ഀ<EFBFBD>
    䤀䐀䐀开䴀䄀䤀一Ⰰ 䐀䤀䄀䰀伀䜀ഀ<EFBFBD>
    䈀䔀䜀䤀一ഀ<EFBFBD>
        䰀䔀䘀吀䴀䄀刀䜀䤀一Ⰰ ㄀㄀ഀ<EFBFBD>
        刀䤀䜀䠀吀䴀䄀刀䜀䤀一Ⰰ ㌀㐀 <EFBFBD>
        吀伀倀䴀䄀刀䜀䤀一Ⰰ 㜀ഀ<EFBFBD>
        䈀伀吀吀伀䴀䴀䄀刀䜀䤀一Ⰰ ㈀㤀㜀ഀ<EFBFBD>
    䔀一䐀ഀ<EFBFBD>
䔀一䐀ഀ<EFBFBD>
⌀攀渀搀椀昀    ⼀⼀ 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
<EFBFBD>

File diff suppressed because it is too large Load Diff

View File

@ -1,215 +0,0 @@
#pragma once
#include <PowerRenameInterfaces.h>
#include <settings.h>
#include <shldisp.h>
void ModuleAddRef();
void ModuleRelease();
class CPowerRenameListView
{
public:
CPowerRenameListView() = default;
~CPowerRenameListView() = default;
void Init(_In_ HWND hwndLV);
void ToggleAll(_In_ IPowerRenameManager* psrm, _In_ bool selected);
void ToggleItem(_In_ IPowerRenameManager* psrm, _In_ int item);
void UpdateItemCheckState(_In_ IPowerRenameManager* psrm, _In_ int iItem);
void RedrawItems(_In_ int first, _In_ int last);
void SetItemCount(_In_ UINT itemCount);
void OnKeyDown(_In_ IPowerRenameManager* psrm, _In_ LV_KEYDOWN* lvKeyDown);
void OnClickList(_In_ IPowerRenameManager* psrm, NM_LISTVIEW* pnmListView);
void OnColumnClick(_In_ IPowerRenameManager* psrm, _In_ int pnmListView);
void GetDisplayInfo(_In_ IPowerRenameManager* psrm, _Inout_ LV_DISPINFO* plvdi);
void OnSize();
HWND GetHWND() { return m_hwndLV; }
private:
void _UpdateColumns();
void _UpdateColumnSizes();
void _UpdateHeaderCheckState(_In_ bool check);
void _UpdateHeaderFilterState(_In_ DWORD filter);
UINT m_itemCount = 0;
HWND m_hwndLV = nullptr;
};
class CPowerRenameProgressUI :
public IUnknown
{
public:
CPowerRenameProgressUI() :
m_refCount(1)
{
}
~CPowerRenameProgressUI() = default;
// IUnknown
IFACEMETHODIMP QueryInterface(__in REFIID riid, __deref_out void** ppv);
IFACEMETHODIMP_(ULONG)
AddRef();
IFACEMETHODIMP_(ULONG)
Release();
HRESULT Start();
HRESULT Stop();
bool IsCanceled() { return m_canceled; }
private:
static LRESULT CALLBACK s_msgWndProc(_In_ HWND hwnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam);
LRESULT _WndProc(_In_ HWND hwnd, _In_ UINT msg, _In_ WPARAM wParam, _In_ LPARAM lParam);
static DWORD WINAPI s_workerThread(_In_ void* pv);
void _UpdateCancelState();
void _Cleanup();
long m_refCount = 0;
bool m_canceled = false;
std::atomic<bool> m_loadingThread{ false };
HANDLE m_workerThreadHandle = nullptr;
CComPtr<IProgressDialog> m_sppd;
};
class CPowerRenameUI :
public IDropTarget,
public IPowerRenameUI,
public IPowerRenameManagerEvents
{
public:
CPowerRenameUI();
// IUnknown
IFACEMETHODIMP QueryInterface(__in REFIID riid, __deref_out void** ppv);
IFACEMETHODIMP_(ULONG)
AddRef();
IFACEMETHODIMP_(ULONG)
Release();
// IPowerRenameUI
IFACEMETHODIMP Show(_In_opt_ HWND hwndParent);
IFACEMETHODIMP Close();
IFACEMETHODIMP Update();
IFACEMETHODIMP GetHwnd(_Out_ HWND* hwnd);
IFACEMETHODIMP GetShowUI(_Out_ bool* showUI);
// IPowerRenameManagerEvents
IFACEMETHODIMP OnItemAdded(_In_ IPowerRenameItem* renameItem);
IFACEMETHODIMP OnUpdate(_In_ IPowerRenameItem* renameItem);
IFACEMETHODIMP OnError(_In_ IPowerRenameItem* renameItem);
IFACEMETHODIMP OnRegExStarted(_In_ DWORD threadId);
IFACEMETHODIMP OnRegExCanceled(_In_ DWORD threadId);
IFACEMETHODIMP OnRegExCompleted(_In_ DWORD threadId);
IFACEMETHODIMP OnRenameStarted();
IFACEMETHODIMP OnRenameCompleted();
// IDropTarget
IFACEMETHODIMP DragEnter(_In_ IDataObject* pdtobj, DWORD grfKeyState, POINTL pt, _Inout_ DWORD* pdwEffect);
IFACEMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, _Inout_ DWORD* pdwEffect);
IFACEMETHODIMP DragLeave();
IFACEMETHODIMP Drop(_In_ IDataObject* pdtobj, DWORD grfKeyState, POINTL pt, _Inout_ DWORD* pdwEffect);
static HRESULT s_CreateInstance(_In_ IPowerRenameManager* psrm, _In_opt_ IUnknown* dataSource, _In_ bool enableDragDrop, _Outptr_ IPowerRenameUI** ppsrui);
private:
struct DialogItemsPositioning
{
int groupsWidthDiff;
int previewGroupHeightDiff;
int searchReplaceWidthDiff;
int listPreviewWidthDiff;
int listPreviewHeightDiff;
int statusMessageSelectedYDiff;
int statusMessageRenamingYDiff;
int renameButtonXDiff;
int renameButtonYDiff;
int helpButtonXDiff;
int helpButtonYDiff;
int cancelButtonXDiff;
int cancelButtonYDiff;
};
~CPowerRenameUI()
{
DeleteObject(m_iconMain);
OleUninitialize();
ModuleRelease();
}
HRESULT _DoModal(__in_opt HWND hwnd);
HRESULT _DoModeless(__in_opt HWND hwnd);
void BecomeForegroundWindow();
static INT_PTR CALLBACK s_DlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CPowerRenameUI* pDlg = reinterpret_cast<CPowerRenameUI*>(GetWindowLongPtr(hdlg, DWLP_USER));
if (uMsg == WM_INITDIALOG)
{
pDlg = reinterpret_cast<CPowerRenameUI*>(lParam);
pDlg->m_hwnd = hdlg;
SetWindowLongPtr(hdlg, DWLP_USER, reinterpret_cast<LONG_PTR>(pDlg));
}
return pDlg ? pDlg->_DlgProc(uMsg, wParam, lParam) : FALSE;
}
HRESULT _Initialize(_In_ IPowerRenameManager* psrm, _In_opt_ IUnknown* dataSource, _In_ bool enableDragDrop);
HRESULT _InitAutoComplete();
void _Cleanup();
INT_PTR _DlgProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
void _OnCommand(_In_ WPARAM wParam, _In_ LPARAM lParam);
BOOL _OnNotify(_In_ WPARAM wParam, _In_ LPARAM lParam);
void _OnSize(_In_ WPARAM wParam);
void _OnGetMinMaxInfo(_In_ LPARAM lParam);
void _OnInitDlg();
void _InitDlgText();
void _OnRename();
void _OnAbout();
void _OnCloseDlg();
void _OnDestroyDlg();
void _OnSearchReplaceChanged();
void _MoveControl(_In_ DWORD id, _In_ DWORD repositionFlags);
HRESULT _ReadSettings();
HRESULT _WriteSettings();
DWORD _GetFlagsFromCheckboxes();
void _SetCheckboxesFromFlags(_In_ DWORD flags);
void _ValidateFlagCheckbox(_In_ DWORD checkBoxId);
HRESULT _EnumerateItems(_In_ IUnknown* pdtobj);
void _UpdateCounts();
void _CollectItemPosition(_In_ DWORD id);
long m_refCount = 0;
bool m_initialized = false;
bool m_enableDragDrop = false;
bool m_disableCountUpdate = false;
bool m_modeless = true;
HWND m_hwnd = nullptr;
HWND m_hwndLV = nullptr;
HICON m_iconMain = nullptr;
DWORD m_cookie = 0;
DWORD m_currentRegExId = 0;
UINT m_selectedCount = 0;
UINT m_renamingCount = 0;
UINT m_initialDPI = 0;
DialogItemsPositioning m_itemsPositioning {};
int m_initialWidth = 0;
int m_initialHeight = 0;
int m_lastWidth = 0;
int m_lastHeight = 0;
CPowerRenameProgressUI m_prpui;
CComPtr<IPowerRenameManager> m_spsrm;
CComPtr<IUnknown> m_dataSource;
CComPtr<IPowerRenameEnum> m_sppre;
CComPtr<IDropTargetHelper> m_spdth;
CComPtr<IAutoComplete2> m_spSearchAC;
CComPtr<IUnknown> m_spSearchACL;
CComPtr<IAutoComplete2> m_spReplaceAC;
CComPtr<IUnknown> m_spReplaceACL;
CPowerRenameListView m_listview;
};

Some files were not shown because too many files have changed in this diff Show More