Integrate thmviewer.exe and thmviewer.msi
Cannot build MSI until a few fixes are made to WixToolset.Core. Will enable this later.
This commit is contained in:
Родитель
28779cbbaa
Коммит
e8d9c70934
42
Tools.sln
42
Tools.sln
|
@ -24,44 +24,86 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Tools.Core", "sr
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.WixCop", "src\test\WixToolsetTest.WixCop\WixToolsetTest.WixCop.csproj", "{F1A8112B-95A1-4AF7-81CB-523BE7DB8E5C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "thmviewer", "src\thmviewer\thmviewer.vcxproj", "{95228C13-97F5-484A-B4A2-ECF4618B0881}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4B0098A4-B581-4D04-BA1E-6DC2370A7D43}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DA5CA026-6165-48C4-BDA5-BB4B17D56A18}.Release|x86.Build.0 = Release|Any CPU
|
||||
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{65141CE1-0BDD-41EF-8043-35B96C423CB6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{938BCA04-610B-4B99-9CB7-02BF7397A972}.Release|x86.Build.0 = Release|Any CPU
|
||||
{0DF5D4CF-8457-469D-8288-13775E984F70}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0DF5D4CF-8457-469D-8288-13775E984F70}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0DF5D4CF-8457-469D-8288-13775E984F70}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{0DF5D4CF-8457-469D-8288-13775E984F70}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{0DF5D4CF-8457-469D-8288-13775E984F70}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0DF5D4CF-8457-469D-8288-13775E984F70}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0DF5D4CF-8457-469D-8288-13775E984F70}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{0DF5D4CF-8457-469D-8288-13775E984F70}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2E54120B-8958-40B1-A7FC-851446994CD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2E54120B-8958-40B1-A7FC-851446994CD8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2E54120B-8958-40B1-A7FC-851446994CD8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2E54120B-8958-40B1-A7FC-851446994CD8}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2E54120B-8958-40B1-A7FC-851446994CD8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2E54120B-8958-40B1-A7FC-851446994CD8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2E54120B-8958-40B1-A7FC-851446994CD8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2E54120B-8958-40B1-A7FC-851446994CD8}.Release|x86.Build.0 = Release|Any CPU
|
||||
{9C3B486F-AE0E-43BA-823A-30808B73C6B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9C3B486F-AE0E-43BA-823A-30808B73C6B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9C3B486F-AE0E-43BA-823A-30808B73C6B4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9C3B486F-AE0E-43BA-823A-30808B73C6B4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9C3B486F-AE0E-43BA-823A-30808B73C6B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9C3B486F-AE0E-43BA-823A-30808B73C6B4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9C3B486F-AE0E-43BA-823A-30808B73C6B4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9C3B486F-AE0E-43BA-823A-30808B73C6B4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F1A8112B-95A1-4AF7-81CB-523BE7DB8E5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F1A8112B-95A1-4AF7-81CB-523BE7DB8E5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F1A8112B-95A1-4AF7-81CB-523BE7DB8E5C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F1A8112B-95A1-4AF7-81CB-523BE7DB8E5C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{F1A8112B-95A1-4AF7-81CB-523BE7DB8E5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F1A8112B-95A1-4AF7-81CB-523BE7DB8E5C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F1A8112B-95A1-4AF7-81CB-523BE7DB8E5C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F1A8112B-95A1-4AF7-81CB-523BE7DB8E5C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{95228C13-97F5-484A-B4A2-ECF4618B0881}.Debug|Any CPU.ActiveCfg = Debug|Win32
|
||||
{95228C13-97F5-484A-B4A2-ECF4618B0881}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{95228C13-97F5-484A-B4A2-ECF4618B0881}.Debug|x86.Build.0 = Debug|Win32
|
||||
{95228C13-97F5-484A-B4A2-ECF4618B0881}.Release|Any CPU.ActiveCfg = Release|Win32
|
||||
{95228C13-97F5-484A-B4A2-ECF4618B0881}.Release|x86.ActiveCfg = Release|Win32
|
||||
{95228C13-97F5-484A-B4A2-ECF4618B0881}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
@pushd %~dp0
|
||||
@set _P=%~dp0build\Release\publish
|
||||
|
||||
nuget restore
|
||||
|
||||
dotnet build -c Release src\test\WixToolsetTest.BuildTasks
|
||||
dotnet build -c Release src\test\WixToolsetTest.WixCop
|
||||
|
||||
|
@ -15,7 +17,9 @@ dotnet publish -c Release -o %_P%\WixToolset.MSBuild\netcoreapp2.1\ -f netcoreap
|
|||
|
||||
dotnet pack -c Release src\dotnet-wix
|
||||
dotnet pack -c Release src\WixToolset.MSBuild
|
||||
@rem dotnet pack -c Release src\WixToolset.Core.InternalPackage
|
||||
|
||||
@rem Enable this build when WixToolset.Core is fixed to build the setup code correctly.
|
||||
@rem msbuild -p:Configuration=Release .\src\ThmViewerPackage\ThmViewerPackage.wixproj
|
||||
|
||||
@popd
|
||||
@endlocal
|
||||
|
|
|
@ -33,6 +33,8 @@ skip_tags: true
|
|||
artifacts:
|
||||
- path: build\Release\**\*.nupkg
|
||||
name: nuget
|
||||
- path: build\Release\**\*.msi
|
||||
name: msi
|
||||
|
||||
notifications:
|
||||
- provider: Slack
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
|
||||
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Platform Condition=" '$(Platform)' == '' OR '$(Platform)' == 'AnyCPU' ">Win32</Platform>
|
||||
<IntDir>$(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\</IntDir>
|
||||
<OutDir>$(OutputPath)$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'=='' AND '$(VisualStudioVersion)'=='15.0'">
|
||||
<WindowsTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<DisableSpecificWarnings>$(DisableSpecificCompilerWarnings)</DisableSpecificWarnings>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)inc;$(MSBuildProjectDirectory);$(IntDir);$(SqlCESdkIncludePath);$(ProjectAdditionalIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;_WIN32_MSI=500;_WIN32_WINNT=0x0501;$(ArmPreprocessorDefinitions);$(UnicodePreprocessorDefinitions);_CRT_STDIO_LEGACY_WIDE_SPECIFIERS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
|
||||
<CallingConvention Condition="'$(Platform)'=='Win32'">StdCall</CallingConvention>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<AdditionalOptions>-YlprecompDefine</AdditionalOptions>
|
||||
<AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
|
||||
<MultiProcessorCompilation Condition=" $(NUMBER_OF_PROCESSORS) > 4 ">true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>$(ArmPreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectAdditionalResourceIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Lib>
|
||||
<AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ProjectAdditionalLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Lib>
|
||||
<Link>
|
||||
<SubSystem>$(ProjectSubSystem)</SubSystem>
|
||||
<ModuleDefinitionFile>$(ProjectModuleDefinitionFile)</ModuleDefinitionFile>
|
||||
<NoEntryPoint>$(ResourceOnlyDll)</NoEntryPoint>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(ProjectAdditionalLinkLibraries);advapi32.lib;comdlg32.lib;user32.lib;oleaut32.lib;gdi32.lib;shell32.lib;ole32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ArmLibraryDirectories);$(ProjectAdditionalLinkLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/IGNORE:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<ItemDefinitionGroup Condition=" '$(Platform)'=='Win32' and '$(PlatformToolset)'!='v100'">
|
||||
<ClCompile>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition=" '$(Platform)'=='arm' ">
|
||||
<ClCompile>
|
||||
<CallingConvention>CDecl</CallingConvention>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition=" '$(ConfigurationType)'=='StaticLibrary' ">
|
||||
<ClCompile>
|
||||
<DebugInformationFormat>OldStyle</DebugInformationFormat>
|
||||
<OmitDefaultLibName>true</OmitDefaultLibName>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition=" '$(Configuration)'=='Debug' ">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<PreprocessorDefinitions>_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition=" '$(Configuration)'=='Debug' and '$(CLRSupport)'=='true' ">
|
||||
<ClCompile>
|
||||
<BasicRuntimeChecks></BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDll</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition=" '$(Configuration)'=='Release' ">
|
||||
<ClCompile>
|
||||
<Optimization>MinSpace</Optimization>
|
||||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition=" '$(Configuration)'=='Release' and '$(CLRSupport)'=='true' ">
|
||||
<ClCompile>
|
||||
<BasicRuntimeChecks></BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDll</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition=" '$(CLRSupport)'=='true' ">
|
||||
<Link>
|
||||
<KeyFile>$(LinkKeyFile)</KeyFile>
|
||||
<DelaySign>$(LinkDelaySign)</DelaySign>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
</Project>
|
|
@ -8,6 +8,7 @@
|
|||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<EnableSourceLink Condition=" '$(NCrunch)' == '1' ">false</EnableSourceLink>
|
||||
<MSBuildWarningsAsMessages>MSB3246</MSBuildWarningsAsMessages>
|
||||
|
||||
<ProjectName Condition=" '$(ProjectName)' == '' ">$(MSBuildProjectName)</ProjectName>
|
||||
<BaseOutputPath>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\))</BaseOutputPath>
|
||||
|
@ -22,5 +23,6 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<Import Project="Cpp.Build.props" Condition=" '$(MSBuildProjectExtension)'=='.vcxproj' " />
|
||||
<Import Project="Wix.Build.props" Condition=" '$(MSBuildProjectExtension)'=='.wixproj' " />
|
||||
<Import Project="Custom.Build.props" Condition=" Exists('Custom.Build.props') " />
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
|
||||
<Product Name="WiX Toolset Theme Viewer" Manufacturer="WiX Toolset" Language="1033"
|
||||
Version="!(bind.fileVersion.ThmViewerFile)" UpgradeCode="59c4b122-5167-445b-8fc4-09dcd4eced89">
|
||||
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
|
||||
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||
<MediaTemplate />
|
||||
|
||||
<Feature Id="Main">
|
||||
<ComponentGroupRef Id="Components" />
|
||||
</Feature>
|
||||
</Product>
|
||||
|
||||
<Fragment>
|
||||
<ComponentGroup Id="Components" Directory="INSTALLFOLDER:\bin\">
|
||||
<Component>
|
||||
<File Id="ThmViewerFile" Source="thmviewer.exe" />
|
||||
<Shortcut Name="!(bind.property.ProductName)" Directory="ShortcutFolder" Advertise="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
</Fragment>
|
||||
|
||||
<Fragment>
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="ProgramFilesFolder">
|
||||
<Directory Id="INSTALLFOLDER" Name="WiX Toolset v4.0\" />
|
||||
</Directory>
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ShortcutFolder" Name="WiX Toolset\" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
</Fragment>
|
||||
|
||||
</Wix>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\Directory.Build.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>59c4b122-5167-445b-8fc4-09dcd4eced89</ProjectGuid>
|
||||
<OutputName>thmviewer</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Package.wxs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\thmviewer\thmviewer.vcxproj">
|
||||
<Name>thmviewer</Name>
|
||||
<Project>{95228C13-97F5-484A-B4A2-ECF4618B0881}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(OutputPath)\net461\wix.targets" />
|
||||
|
||||
<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\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets'))" />
|
||||
</Target>
|
||||
<Import Project="..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets" Condition="Exists('..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets')" />
|
||||
</Project>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Nerdbank.GitVersioning" version="2.1.65" developmentDependency="true" targetFramework="net40" />
|
||||
</packages>
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
|
||||
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<DefineConstants>$(DefineConstants);CompanyName=$(Company)</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<BindInputPaths Include="$(OutputPath)Win32\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Двоичный файл не отображается.
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
|
||||
|
||||
|
||||
<Theme>
|
||||
<Font Id="0" Height="-48" Weight="700" Foreground="$windowtext">Consolas</Font>
|
||||
<Font Id="1" Height="-12" Weight="700" Foreground="$windowtext" Background="$window">Consolas</Font>
|
||||
<Window Width="220" Height="200" FontId="0" Caption="Theme Viewer">
|
||||
<TreeView Name="Tree" X="0" Y="0" Width="0" Height="0" FontId="1" Visible="yes" FullRowSelect="yes" HasButtons="yes" AlwaysShowSelect="yes" HasLines="yes" LinesAtRoot="yes"/>
|
||||
</Window>
|
||||
</Theme>
|
|
@ -0,0 +1,353 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
static const LPCWSTR THMVWR_WINDOW_CLASS_DISPLAY = L"ThmViewerDisplay";
|
||||
|
||||
struct DISPLAY_THREAD_CONTEXT
|
||||
{
|
||||
HWND hWnd;
|
||||
HINSTANCE hInstance;
|
||||
|
||||
HANDLE hInit;
|
||||
};
|
||||
|
||||
static DWORD WINAPI DisplayThreadProc(
|
||||
__in LPVOID pvContext
|
||||
);
|
||||
static LRESULT CALLBACK DisplayWndProc(
|
||||
__in HWND hWnd,
|
||||
__in UINT uMsg,
|
||||
__in WPARAM wParam,
|
||||
__in LPARAM lParam
|
||||
);
|
||||
static BOOL DisplayOnCreate(
|
||||
__in THEME* pTheme,
|
||||
__in HWND hWnd
|
||||
);
|
||||
|
||||
|
||||
extern "C" HRESULT DisplayStart(
|
||||
__in HINSTANCE hInstance,
|
||||
__in HWND hWnd,
|
||||
__out HANDLE *phThread,
|
||||
__out DWORD* pdwThreadId
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
HANDLE rgHandles[2] = { };
|
||||
DISPLAY_THREAD_CONTEXT context = { };
|
||||
|
||||
rgHandles[0] = ::CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||
ExitOnNullWithLastError(rgHandles[0], hr, "Failed to create load init event.");
|
||||
|
||||
context.hWnd = hWnd;
|
||||
context.hInstance = hInstance;
|
||||
context.hInit = rgHandles[0];
|
||||
|
||||
rgHandles[1] = ::CreateThread(NULL, 0, DisplayThreadProc, reinterpret_cast<LPVOID>(&context), 0, pdwThreadId);
|
||||
ExitOnNullWithLastError(rgHandles[1], hr, "Failed to create display thread.");
|
||||
|
||||
::WaitForMultipleObjects(countof(rgHandles), rgHandles, FALSE, INFINITE);
|
||||
|
||||
*phThread = rgHandles[1];
|
||||
rgHandles[1] = NULL;
|
||||
|
||||
LExit:
|
||||
ReleaseHandle(rgHandles[1]);
|
||||
ReleaseHandle(rgHandles[0]);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static DWORD WINAPI DisplayThreadProc(
|
||||
__in LPVOID pvContext
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
DISPLAY_THREAD_CONTEXT* pContext = static_cast<DISPLAY_THREAD_CONTEXT*>(pvContext);
|
||||
HINSTANCE hInstance = pContext->hInstance;
|
||||
HWND hwndParent = pContext->hWnd;
|
||||
|
||||
// We can signal the initialization event as soon as we have copied the context
|
||||
// values into local variables.
|
||||
::SetEvent(pContext->hInit);
|
||||
|
||||
BOOL fComInitialized = FALSE;
|
||||
|
||||
HANDLE_THEME* pCurrentHandle = NULL;
|
||||
ATOM atomWc = 0;
|
||||
WNDCLASSW wc = { }; // the following are constant for the display window class.
|
||||
wc.lpfnWndProc = DisplayWndProc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.lpszClassName = THMVWR_WINDOW_CLASS_DISPLAY;
|
||||
|
||||
HWND hWnd = NULL;
|
||||
RECT rc = { };
|
||||
int x = CW_USEDEFAULT;
|
||||
int y = CW_USEDEFAULT;
|
||||
|
||||
BOOL fRedoMsg = FALSE;
|
||||
BOOL fRet = FALSE;
|
||||
MSG msg = { };
|
||||
|
||||
BOOL fCreateIfNecessary = FALSE;
|
||||
|
||||
hr = ::CoInitialize(NULL);
|
||||
ExitOnFailure(hr, "Failed to initialize COM on display thread.");
|
||||
fComInitialized = TRUE;
|
||||
|
||||
// As long as the parent window is alive and kicking, keep this thread going (with or without a theme to display ).
|
||||
while (::IsWindow(hwndParent))
|
||||
{
|
||||
if (pCurrentHandle && fCreateIfNecessary)
|
||||
{
|
||||
THEME* pTheme = pCurrentHandle->pTheme;
|
||||
|
||||
if (CW_USEDEFAULT == x && CW_USEDEFAULT == y && ::GetWindowRect(hwndParent, &rc))
|
||||
{
|
||||
x = rc.left;
|
||||
y = rc.bottom + 20;
|
||||
}
|
||||
|
||||
hWnd = ::CreateWindowExW(0, wc.lpszClassName, pTheme->sczCaption, pTheme->dwStyle, x, y, pTheme->nWidth, pTheme->nHeight, hwndParent, NULL, hInstance, pCurrentHandle);
|
||||
ExitOnNullWithLastError(hWnd, hr, "Failed to create display window.");
|
||||
|
||||
fCreateIfNecessary = FALSE;
|
||||
}
|
||||
|
||||
// message pump
|
||||
while (fRedoMsg || 0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0)))
|
||||
{
|
||||
if (fRedoMsg)
|
||||
{
|
||||
fRedoMsg = FALSE;
|
||||
}
|
||||
|
||||
if (-1 == fRet)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
ExitOnFailure(hr, "Unexpected return value from display message pump.");
|
||||
}
|
||||
else if (NULL == msg.hwnd) // Thread message.
|
||||
{
|
||||
if (WM_THMVWR_NEW_THEME == msg.message)
|
||||
{
|
||||
// If there is already a handle, release it.
|
||||
if (pCurrentHandle)
|
||||
{
|
||||
DecrementHandleTheme(pCurrentHandle);
|
||||
pCurrentHandle = NULL;
|
||||
}
|
||||
|
||||
// If the window was created, remember its window location before we destroy
|
||||
// it so so we can open the new window in the same place.
|
||||
if (::IsWindow(hWnd))
|
||||
{
|
||||
::GetWindowRect(hWnd, &rc);
|
||||
x = rc.left;
|
||||
y = rc.top;
|
||||
|
||||
::DestroyWindow(hWnd);
|
||||
}
|
||||
|
||||
// If the display window class was registered, unregister it so we can
|
||||
// reuse the same window class name for the new theme.
|
||||
if (atomWc)
|
||||
{
|
||||
if (!::UnregisterClassW(reinterpret_cast<LPCWSTR>(atomWc), hInstance))
|
||||
{
|
||||
DWORD er = ::GetLastError();
|
||||
er = er;
|
||||
}
|
||||
|
||||
atomWc = 0;
|
||||
}
|
||||
|
||||
// If we were provided a new theme handle, create a new window class to
|
||||
// support it.
|
||||
pCurrentHandle = reinterpret_cast<HANDLE_THEME*>(msg.lParam);
|
||||
if (pCurrentHandle)
|
||||
{
|
||||
wc.hIcon = reinterpret_cast<HICON>(pCurrentHandle->pTheme->hIcon);
|
||||
wc.hCursor = ::LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
|
||||
if (0 < pCurrentHandle->pTheme->cFonts)
|
||||
{
|
||||
wc.hbrBackground = pCurrentHandle->pTheme->rgFonts[pCurrentHandle->pTheme->dwFontId].hBackground;
|
||||
}
|
||||
atomWc = ::RegisterClassW(&wc);
|
||||
if (!atomWc)
|
||||
{
|
||||
ExitWithLastError(hr, "Failed to register display window class.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (WM_THMVWR_SHOWPAGE == msg.message)
|
||||
{
|
||||
if (pCurrentHandle && ::IsWindow(hWnd) && pCurrentHandle->pTheme->hwndParent == hWnd)
|
||||
{
|
||||
DWORD dwPageId = static_cast<DWORD>(msg.lParam);
|
||||
int nCmdShow = static_cast<int>(msg.wParam);
|
||||
|
||||
// First show/hide the controls not associated with a page.
|
||||
for (DWORD i = 0; i < pCurrentHandle->pTheme->cControls; ++i)
|
||||
{
|
||||
THEME_CONTROL* pControl = pCurrentHandle->pTheme->rgControls + i;
|
||||
if (!pControl->wPageId)
|
||||
{
|
||||
ThemeShowControl(pCurrentHandle->pTheme, pControl->wId, nCmdShow);
|
||||
}
|
||||
}
|
||||
|
||||
// If a page id was provided also, show/hide those controls
|
||||
if (dwPageId)
|
||||
{
|
||||
// Ignore error since we aren't using variables and it can only fail when using variables.
|
||||
ThemeShowPage(pCurrentHandle->pTheme, dwPageId, nCmdShow);
|
||||
}
|
||||
}
|
||||
else // display window isn't visible or it doesn't match the current handle.
|
||||
{
|
||||
// Keep the current message around to try again after we break out of this loop
|
||||
// and create the window.
|
||||
fRedoMsg = TRUE;
|
||||
fCreateIfNecessary = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!ThemeHandleKeyboardMessage(pCurrentHandle->pTheme, hwndParent, &msg)) // Window message.
|
||||
{
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LExit:
|
||||
if (::IsWindow(hWnd))
|
||||
{
|
||||
::DestroyWindow(hWnd);
|
||||
}
|
||||
|
||||
if (atomWc)
|
||||
{
|
||||
if (!::UnregisterClassW(THMVWR_WINDOW_CLASS_DISPLAY, hInstance))
|
||||
{
|
||||
DWORD er = ::GetLastError();
|
||||
er = er;
|
||||
}
|
||||
}
|
||||
|
||||
DecrementHandleTheme(pCurrentHandle);
|
||||
|
||||
if (fComInitialized)
|
||||
{
|
||||
::CoUninitialize();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK DisplayWndProc(
|
||||
__in HWND hWnd,
|
||||
__in UINT uMsg,
|
||||
__in WPARAM wParam,
|
||||
__in LPARAM lParam
|
||||
)
|
||||
{
|
||||
static DWORD dwProgress = 0;
|
||||
HANDLE_THEME* pHandleTheme = reinterpret_cast<HANDLE_THEME*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_NCCREATE:
|
||||
{
|
||||
LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
|
||||
IncrementHandleTheme(reinterpret_cast<HANDLE_THEME*>(lpcs->lpCreateParams));
|
||||
::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(lpcs->lpCreateParams));
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CREATE:
|
||||
if (!DisplayOnCreate(pHandleTheme->pTheme, hWnd))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_TIMER:
|
||||
if (!lParam && SUCCEEDED(ThemeSetProgressControl(pHandleTheme->pTheme, wParam, dwProgress)))
|
||||
{
|
||||
dwProgress += rand() % 10 + 1;
|
||||
if (dwProgress > 100)
|
||||
{
|
||||
dwProgress = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
{
|
||||
WCHAR wzText[1024];
|
||||
::StringCchPrintfW(wzText, countof(wzText), L"Command %u\r\n", LOWORD(wParam));
|
||||
OutputDebugStringW(wzText);
|
||||
//::MessageBoxW(hWnd, wzText, L"Command fired", MB_OK);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
{
|
||||
WCHAR wzText[1024];
|
||||
::StringCchPrintfW(wzText, countof(wzText), L"SysCommand %u\r\n", LOWORD(wParam));
|
||||
OutputDebugStringW(wzText);
|
||||
//::MessageBoxW(hWnd, wzText, L"Command fired", MB_OK);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
ThemeUnloadControls(pHandleTheme->pTheme);
|
||||
::PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
case WM_NCDESTROY:
|
||||
DecrementHandleTheme(pHandleTheme);
|
||||
::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
return ThemeDefWindowProc(pHandleTheme ? pHandleTheme->pTheme : NULL, hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
static BOOL DisplayOnCreate(
|
||||
__in THEME* pTheme,
|
||||
__in HWND hWnd
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = ThemeLoadControls(pTheme, hWnd, NULL, 0);
|
||||
ExitOnFailure(hr, "Failed to load theme controls");
|
||||
|
||||
// Pre-populate some control types with data.
|
||||
for (DWORD i = 0; i < pTheme->cControls; ++i)
|
||||
{
|
||||
THEME_CONTROL* pControl = pTheme->rgControls + i;
|
||||
if (THEME_CONTROL_TYPE_RICHEDIT == pControl->type)
|
||||
{
|
||||
hr = ThemeLoadRichEditFromResource(pTheme, pControl->wId, MAKEINTRESOURCEA(THMVWR_RES_RICHEDIT_FILE), ::GetModuleHandleW(NULL));
|
||||
ExitOnFailure(hr, "Failed to load richedit text.");
|
||||
}
|
||||
else if (THEME_CONTROL_TYPE_PROGRESSBAR == pControl->type)
|
||||
{
|
||||
DWORD dwId = ::SetTimer(hWnd, pControl->wId, 500, NULL);
|
||||
dwId = dwId; // prevents warning in "ship" build.
|
||||
Assert(dwId == pControl->wId);
|
||||
}
|
||||
}
|
||||
|
||||
LExit:
|
||||
return SUCCEEDED(hr);
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
struct LOAD_THREAD_CONTEXT
|
||||
{
|
||||
HWND hWnd;
|
||||
LPCWSTR wzThemePath;
|
||||
LPCWSTR wzWxlPath;
|
||||
|
||||
HANDLE hInit;
|
||||
};
|
||||
|
||||
static DWORD WINAPI LoadThreadProc(
|
||||
__in LPVOID pvContext
|
||||
);
|
||||
|
||||
|
||||
extern "C" HRESULT LoadStart(
|
||||
__in_z LPCWSTR wzThemePath,
|
||||
__in_z_opt LPCWSTR wzWxlPath,
|
||||
__in HWND hWnd,
|
||||
__out HANDLE* phThread
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
HANDLE rgHandles[2] = { };
|
||||
LOAD_THREAD_CONTEXT context = { };
|
||||
|
||||
rgHandles[0] = ::CreateEventW(NULL, TRUE, FALSE, NULL);
|
||||
ExitOnNullWithLastError(rgHandles[0], hr, "Failed to create load init event.");
|
||||
|
||||
context.hWnd = hWnd;
|
||||
context.wzThemePath = wzThemePath;
|
||||
context.wzWxlPath = wzWxlPath;
|
||||
context.hInit = rgHandles[0];
|
||||
|
||||
rgHandles[1] = ::CreateThread(NULL, 0, LoadThreadProc, &context, 0, NULL);
|
||||
ExitOnNullWithLastError(rgHandles[1], hr, "Failed to create load thread.");
|
||||
|
||||
::WaitForMultipleObjects(countof(rgHandles), rgHandles, FALSE, INFINITE);
|
||||
|
||||
*phThread = rgHandles[1];
|
||||
rgHandles[1] = NULL;
|
||||
|
||||
LExit:
|
||||
ReleaseHandle(rgHandles[1]);
|
||||
ReleaseHandle(rgHandles[0]);
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
static DWORD WINAPI LoadThreadProc(
|
||||
__in LPVOID pvContext
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
WIX_LOCALIZATION* pWixLoc = NULL;
|
||||
LPWSTR sczThemePath = NULL;
|
||||
LPWSTR sczWxlPath = NULL;
|
||||
BOOL fComInitialized = FALSE;
|
||||
HANDLE hDirectory = INVALID_HANDLE_VALUE;
|
||||
LPWSTR sczDirectory = NULL;
|
||||
LPWSTR wzFileName = NULL;
|
||||
|
||||
THEME* pTheme = NULL;
|
||||
HANDLE_THEME* pHandle = NULL;
|
||||
|
||||
LOAD_THREAD_CONTEXT* pContext = static_cast<LOAD_THREAD_CONTEXT*>(pvContext);
|
||||
HWND hWnd = pContext->hWnd;
|
||||
|
||||
hr = StrAllocString(&sczThemePath, pContext->wzThemePath, 0);
|
||||
ExitOnFailure(hr, "Failed to copy path to initial theme file.");
|
||||
|
||||
if (pContext->wzWxlPath)
|
||||
{
|
||||
hr = StrAllocString(&sczWxlPath, pContext->wzWxlPath, 0);
|
||||
ExitOnFailure(hr, "Failed to copy .wxl path to initial file.");
|
||||
}
|
||||
|
||||
// We can signal the initialization event as soon as we have copied the context
|
||||
// values into local variables.
|
||||
::SetEvent(pContext->hInit);
|
||||
|
||||
hr = ::CoInitialize(NULL);
|
||||
ExitOnFailure(hr, "Failed to initialize COM on load thread.");
|
||||
fComInitialized = TRUE;
|
||||
|
||||
// Open a handle to the directory so we can put a notification on it.
|
||||
hr = PathGetDirectory(sczThemePath, &sczDirectory);
|
||||
ExitOnFailure(hr, "Failed to get path directory.");
|
||||
|
||||
wzFileName = PathFile(sczThemePath);
|
||||
|
||||
hDirectory = ::CreateFileW(sczDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
if (INVALID_HANDLE_VALUE == hDirectory)
|
||||
{
|
||||
ExitWithLastError(hr, "Failed to open directory: %ls", sczDirectory);
|
||||
}
|
||||
|
||||
BOOL fUpdated = FALSE;
|
||||
do
|
||||
{
|
||||
// Get the last modified time on the file we're loading for verification that the
|
||||
// file actually gets changed down below.
|
||||
FILETIME ftModified = { };
|
||||
FileGetTime(sczThemePath, NULL, NULL, &ftModified);
|
||||
|
||||
// Try to load the theme file.
|
||||
hr = ThemeLoadFromFile(sczThemePath, &pTheme);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
::SendMessageW(hWnd, WM_THMVWR_THEME_LOAD_ERROR, 0, hr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sczWxlPath)
|
||||
{
|
||||
hr = LocLoadFromFile(sczWxlPath, &pWixLoc);
|
||||
ExitOnFailure(hr, "Failed to load loc file from path: %ls", sczWxlPath);
|
||||
|
||||
hr = ThemeLocalize(pTheme, pWixLoc);
|
||||
ExitOnFailure(hr, "Failed to localize theme: %ls", sczWxlPath);
|
||||
}
|
||||
|
||||
hr = AllocHandleTheme(pTheme, &pHandle);
|
||||
ExitOnFailure(hr, "Failed to allocate handle to theme");
|
||||
|
||||
::SendMessageW(hWnd, WM_THMVWR_NEW_THEME, 0, reinterpret_cast<LPARAM>(pHandle));
|
||||
pHandle = NULL;
|
||||
}
|
||||
|
||||
fUpdated = FALSE;
|
||||
do
|
||||
{
|
||||
DWORD rgbNotifications[1024];
|
||||
DWORD cbRead = 0;
|
||||
if (!::ReadDirectoryChangesW(hDirectory, rgbNotifications, sizeof(rgbNotifications), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &cbRead, NULL, NULL))
|
||||
{
|
||||
ExitWithLastError(hr, "Failed while watching directory: %ls", sczDirectory);
|
||||
}
|
||||
|
||||
// Wait for half a second to let all the file handles get closed to minimize access
|
||||
// denied errors.
|
||||
::Sleep(500);
|
||||
|
||||
FILE_NOTIFY_INFORMATION* pNotification = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(rgbNotifications);
|
||||
while (pNotification)
|
||||
{
|
||||
// If our file was updated, check to see if the modified time really changed. The notifications
|
||||
// are often trigger happy thinking the file changed two or three times in a row. Maybe it's AV
|
||||
// software creating the problems but actually checking the modified date works well.
|
||||
if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pNotification->FileName, pNotification->FileNameLength / sizeof(WCHAR), wzFileName, -1))
|
||||
{
|
||||
FILETIME ft = { };
|
||||
FileGetTime(sczThemePath, NULL, NULL, &ft);
|
||||
|
||||
fUpdated = (ftModified.dwHighDateTime < ft.dwHighDateTime) || (ftModified.dwHighDateTime == ft.dwHighDateTime && ftModified.dwLowDateTime < ft.dwLowDateTime);
|
||||
break;
|
||||
}
|
||||
|
||||
pNotification = pNotification->NextEntryOffset ? reinterpret_cast<FILE_NOTIFY_INFORMATION*>(reinterpret_cast<BYTE*>(pNotification) + pNotification->NextEntryOffset) : NULL;
|
||||
}
|
||||
} while (!fUpdated);
|
||||
} while(fUpdated);
|
||||
|
||||
LExit:
|
||||
if (fComInitialized)
|
||||
{
|
||||
::CoUninitialize();
|
||||
}
|
||||
|
||||
LocFree(pWixLoc);
|
||||
ReleaseFileHandle(hDirectory);
|
||||
ReleaseStr(sczDirectory);
|
||||
ReleaseStr(sczThemePath);
|
||||
ReleaseStr(sczWxlPath);
|
||||
return hr;
|
||||
}
|
||||
|
||||
extern "C" HRESULT AllocHandleTheme(
|
||||
__in THEME* pTheme,
|
||||
__out HANDLE_THEME** ppHandle
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
HANDLE_THEME* pHandle = NULL;
|
||||
|
||||
pHandle = static_cast<HANDLE_THEME*>(MemAlloc(sizeof(HANDLE_THEME), TRUE));
|
||||
ExitOnNull(pHandle, hr, E_OUTOFMEMORY, "Failed to allocate theme handle.");
|
||||
|
||||
pHandle->cReferences = 1;
|
||||
pHandle->pTheme = pTheme;
|
||||
|
||||
*ppHandle = pHandle;
|
||||
pHandle = NULL;
|
||||
|
||||
LExit:
|
||||
ReleaseMem(pHandle);
|
||||
return hr;
|
||||
}
|
||||
|
||||
extern "C" void IncrementHandleTheme(
|
||||
__in HANDLE_THEME* pHandle
|
||||
)
|
||||
{
|
||||
::InterlockedIncrement(reinterpret_cast<LONG*>(&pHandle->cReferences));
|
||||
}
|
||||
|
||||
extern "C" void DecrementHandleTheme(
|
||||
__in HANDLE_THEME* pHandle
|
||||
)
|
||||
{
|
||||
if (pHandle && 0 == ::InterlockedDecrement(reinterpret_cast<LONG*>(&pHandle->cReferences)))
|
||||
{
|
||||
ThemeFree(pHandle->pTheme);
|
||||
MemFree(pHandle);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Nerdbank.GitVersioning" version="2.1.65" targetFramework="native" developmentDependency="true" />
|
||||
<package id="WixToolset.DUtil" version="4.0.6" targetFramework="native" />
|
||||
</packages>
|
|
@ -0,0 +1,3 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
|
||||
|
||||
#include "precomp.h"
|
|
@ -0,0 +1,69 @@
|
|||
#pragma once
|
||||
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <msiquery.h>
|
||||
#include <objbase.h>
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <stdlib.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4458)
|
||||
#include <gdiplus.h>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include "dutil.h"
|
||||
#include "apputil.h"
|
||||
#include "memutil.h"
|
||||
#include "dirutil.h"
|
||||
#include "fileutil.h"
|
||||
#include "locutil.h"
|
||||
#include "logutil.h"
|
||||
#include "pathutil.h"
|
||||
#include "resrutil.h"
|
||||
#include "shelutil.h"
|
||||
#include "strutil.h"
|
||||
#include "thmutil.h"
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
struct HANDLE_THEME
|
||||
{
|
||||
DWORD cReferences;
|
||||
THEME* pTheme;
|
||||
};
|
||||
|
||||
enum WM_THMVWR
|
||||
{
|
||||
WM_THMVWR_SHOWPAGE = WM_APP,
|
||||
WM_THMVWR_PARSE_FILE,
|
||||
WM_THMVWR_NEW_THEME,
|
||||
WM_THMVWR_THEME_LOAD_ERROR,
|
||||
};
|
||||
|
||||
extern "C" HRESULT DisplayStart(
|
||||
__in HINSTANCE hInstance,
|
||||
__in HWND hWnd,
|
||||
__out HANDLE *phThread,
|
||||
__out DWORD* pdwThreadId
|
||||
);
|
||||
extern "C" HRESULT LoadStart(
|
||||
__in_z LPCWSTR wzThemePath,
|
||||
__in_z LPCWSTR wzWxlPath,
|
||||
__in HWND hWnd,
|
||||
__out HANDLE* phThread
|
||||
);
|
||||
|
||||
extern "C" HRESULT AllocHandleTheme(
|
||||
__in THEME* pTheme,
|
||||
__out HANDLE_THEME** ppHandle
|
||||
);
|
||||
extern "C" void IncrementHandleTheme(
|
||||
__in HANDLE_THEME* pHandle
|
||||
);
|
||||
extern "C" void DecrementHandleTheme(
|
||||
__in HANDLE_THEME* pHandle
|
||||
);
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
|
||||
|
||||
#define IDC_STATIC -1
|
||||
#define THMVWR_RES_THEME_FILE 1
|
||||
#define THMVWR_RES_RICHEDIT_FILE 2
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1003
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,465 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
static const LPCWSTR THMVWR_WINDOW_CLASS_MAIN = L"ThmViewerMain";
|
||||
|
||||
static THEME* vpTheme = NULL;
|
||||
static DWORD vdwDisplayThreadId = 0;
|
||||
|
||||
enum THMVWR_CONTROL
|
||||
{
|
||||
// Non-paged controls
|
||||
THMVWR_CONTROL_TREE = THEME_FIRST_ASSIGN_CONTROL_ID,
|
||||
};
|
||||
|
||||
static THEME_ASSIGN_CONTROL_ID vrgInitControls[] = {
|
||||
{ THMVWR_CONTROL_TREE, L"Tree" },
|
||||
};
|
||||
|
||||
// Internal functions
|
||||
|
||||
static HRESULT ProcessCommandLine(
|
||||
__in_z_opt LPCWSTR wzCommandLine,
|
||||
__out_z LPWSTR* psczThemeFile,
|
||||
__out_z LPWSTR* psczWxlFile
|
||||
);
|
||||
static HRESULT CreateTheme(
|
||||
__in HINSTANCE hInstance,
|
||||
__out THEME** ppTheme
|
||||
);
|
||||
static HRESULT CreateMainWindowClass(
|
||||
__in HINSTANCE hInstance,
|
||||
__in THEME* pTheme,
|
||||
__out ATOM* pAtom
|
||||
);
|
||||
static LRESULT CALLBACK MainWndProc(
|
||||
__in HWND hWnd,
|
||||
__in UINT uMsg,
|
||||
__in WPARAM wParam,
|
||||
__in LPARAM lParam
|
||||
);
|
||||
static void OnThemeLoadError(
|
||||
__in THEME* pTheme,
|
||||
__in HRESULT hrFailure
|
||||
);
|
||||
static void OnNewTheme(
|
||||
__in THEME* pTheme,
|
||||
__in HWND hWnd,
|
||||
__in HANDLE_THEME* pHandle
|
||||
);
|
||||
|
||||
|
||||
int WINAPI wWinMain(
|
||||
__in HINSTANCE hInstance,
|
||||
__in_opt HINSTANCE /* hPrevInstance */,
|
||||
__in_z LPWSTR lpCmdLine,
|
||||
__in int /*nCmdShow*/
|
||||
)
|
||||
{
|
||||
::HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fComInitialized = FALSE;
|
||||
LPWSTR sczThemeFile = NULL;
|
||||
LPWSTR sczWxlFile = NULL;
|
||||
ATOM atom = 0;
|
||||
HWND hWnd = NULL;
|
||||
|
||||
HANDLE hDisplayThread = NULL;
|
||||
HANDLE hLoadThread = NULL;
|
||||
|
||||
BOOL fRet = FALSE;
|
||||
MSG msg = { };
|
||||
|
||||
hr = ::CoInitialize(NULL);
|
||||
ExitOnFailure(hr, "Failed to initialize COM.");
|
||||
fComInitialized = TRUE;
|
||||
|
||||
hr = ProcessCommandLine(lpCmdLine, &sczThemeFile, &sczWxlFile);
|
||||
ExitOnFailure(hr, "Failed to process command line.");
|
||||
|
||||
hr = CreateTheme(hInstance, &vpTheme);
|
||||
ExitOnFailure(hr, "Failed to create theme.");
|
||||
|
||||
hr = CreateMainWindowClass(hInstance, vpTheme, &atom);
|
||||
ExitOnFailure(hr, "Failed to create main window.");
|
||||
|
||||
hWnd = ::CreateWindowExW(0, reinterpret_cast<LPCWSTR>(atom), vpTheme->sczCaption, vpTheme->dwStyle, CW_USEDEFAULT, CW_USEDEFAULT, vpTheme->nWidth, vpTheme->nHeight, HWND_DESKTOP, NULL, hInstance, NULL);
|
||||
ExitOnNullWithLastError(hWnd, hr, "Failed to create window.");
|
||||
|
||||
if (!sczThemeFile)
|
||||
{
|
||||
// Prompt for a path to the theme file.
|
||||
OPENFILENAMEW ofn = { };
|
||||
WCHAR wzFile[MAX_PATH] = { };
|
||||
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = hWnd;
|
||||
ofn.lpstrFile = wzFile;
|
||||
ofn.nMaxFile = countof(wzFile);
|
||||
ofn.lpstrFilter = L"Theme Files\0*.thm\0XML Files\0*.xml\0All Files\0*.*\0";
|
||||
ofn.nFilterIndex = 1;
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
|
||||
ofn.lpstrTitle = vpTheme->sczCaption;
|
||||
|
||||
if (::GetOpenFileNameW(&ofn))
|
||||
{
|
||||
hr = StrAllocString(&sczThemeFile, wzFile, 0);
|
||||
ExitOnFailure(hr, "Failed to copy opened file to theme file.");
|
||||
}
|
||||
else
|
||||
{
|
||||
::MessageBoxW(hWnd, L"Must specify a path to theme file.", vpTheme->sczCaption, MB_OK | MB_ICONERROR);
|
||||
ExitFunction1(hr = E_INVALIDARG);
|
||||
}
|
||||
}
|
||||
|
||||
hr = DisplayStart(hInstance, hWnd, &hDisplayThread, &vdwDisplayThreadId);
|
||||
ExitOnFailure(hr, "Failed to start display.");
|
||||
|
||||
hr = LoadStart(sczThemeFile, sczWxlFile, hWnd, &hLoadThread);
|
||||
ExitOnFailure(hr, "Failed to start load.");
|
||||
|
||||
// message pump
|
||||
while (0 != (fRet = ::GetMessageW(&msg, NULL, 0, 0)))
|
||||
{
|
||||
if (-1 == fRet)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
ExitOnFailure(hr, "Unexpected return value from message pump.");
|
||||
}
|
||||
else if (!ThemeHandleKeyboardMessage(vpTheme, msg.hwnd, &msg))
|
||||
{
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
LExit:
|
||||
if (::IsWindow(hWnd))
|
||||
{
|
||||
::DestroyWindow(hWnd);
|
||||
}
|
||||
|
||||
if (hDisplayThread)
|
||||
{
|
||||
::PostThreadMessageW(vdwDisplayThreadId, WM_QUIT, 0, 0);
|
||||
::WaitForSingleObject(hDisplayThread, 10000);
|
||||
::CloseHandle(hDisplayThread);
|
||||
}
|
||||
|
||||
// TODO: come up with a good way to kill the load thread, probably need to switch
|
||||
// the ReadDirectoryW() to overlapped mode.
|
||||
ReleaseHandle(hLoadThread);
|
||||
|
||||
if (atom && !::UnregisterClassW(reinterpret_cast<LPCWSTR>(atom), hInstance))
|
||||
{
|
||||
DWORD er = ::GetLastError();
|
||||
er = er;
|
||||
}
|
||||
|
||||
ThemeFree(vpTheme);
|
||||
ThemeUninitialize();
|
||||
|
||||
// uninitialize COM
|
||||
if (fComInitialized)
|
||||
{
|
||||
::CoUninitialize();
|
||||
}
|
||||
|
||||
ReleaseStr(sczThemeFile);
|
||||
ReleaseStr(sczWxlFile);
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ProcessCommandLine - process the provided command line arguments.
|
||||
//
|
||||
static HRESULT ProcessCommandLine(
|
||||
__in_z_opt LPCWSTR wzCommandLine,
|
||||
__out_z LPWSTR* psczThemeFile,
|
||||
__out_z LPWSTR* psczWxlFile
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
int argc = 0;
|
||||
LPWSTR* argv = NULL;
|
||||
|
||||
if (wzCommandLine && *wzCommandLine)
|
||||
{
|
||||
hr = AppParseCommandLine(wzCommandLine, &argc, &argv);
|
||||
ExitOnFailure(hr, "Failed to parse command line.");
|
||||
|
||||
for (int i = 0; i < argc; ++i)
|
||||
{
|
||||
if (argv[i][0] == L'-' || argv[i][0] == L'/')
|
||||
{
|
||||
if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, &argv[i][1], -1, L"lang", -1))
|
||||
{
|
||||
if (i + 1 >= argc)
|
||||
{
|
||||
ExitOnRootFailure(hr = E_INVALIDARG, "Must specify a language.");
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LPCWSTR wzExtension = PathExtension(argv[i]);
|
||||
if (CSTR_EQUAL == ::CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, wzExtension, -1, L".wxl", -1))
|
||||
{
|
||||
hr = StrAllocString(psczWxlFile, argv[i], 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = StrAllocString(psczThemeFile, argv[i], 0);
|
||||
}
|
||||
ExitOnFailure(hr, "Failed to copy path to file.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LExit:
|
||||
if (argv)
|
||||
{
|
||||
AppFreeCommandLineArgs(argv);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT CreateTheme(
|
||||
__in HINSTANCE hInstance,
|
||||
__out THEME** ppTheme
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
hr = ThemeInitialize(hInstance);
|
||||
ExitOnFailure(hr, "Failed to initialize theme manager.");
|
||||
|
||||
hr = ThemeLoadFromResource(hInstance, MAKEINTRESOURCEA(THMVWR_RES_THEME_FILE), ppTheme);
|
||||
ExitOnFailure(hr, "Failed to load theme from thmviewer.thm.");
|
||||
|
||||
LExit:
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT CreateMainWindowClass(
|
||||
__in HINSTANCE hInstance,
|
||||
__in THEME* pTheme,
|
||||
__out ATOM* pAtom
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ATOM atom = 0;
|
||||
WNDCLASSW wc = { };
|
||||
|
||||
wc.lpfnWndProc = MainWndProc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.hIcon = reinterpret_cast<HICON>(pTheme->hIcon);
|
||||
wc.hCursor = ::LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
|
||||
wc.hbrBackground = pTheme->rgFonts[pTheme->dwFontId].hBackground;
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.lpszClassName = THMVWR_WINDOW_CLASS_MAIN;
|
||||
atom = ::RegisterClassW(&wc);
|
||||
if (!atom)
|
||||
{
|
||||
ExitWithLastError(hr, "Failed to register main windowclass .");
|
||||
}
|
||||
|
||||
*pAtom = atom;
|
||||
|
||||
LExit:
|
||||
return hr;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK MainWndProc(
|
||||
__in HWND hWnd,
|
||||
__in UINT uMsg,
|
||||
__in WPARAM wParam,
|
||||
__in LPARAM lParam
|
||||
)
|
||||
{
|
||||
HANDLE_THEME* pHandleTheme = reinterpret_cast<HANDLE_THEME*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_NCCREATE:
|
||||
{
|
||||
//LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
|
||||
//pBA = reinterpret_cast<CWixStandardBootstrapperApplication*>(lpcs->lpCreateParams);
|
||||
//::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pBA));
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_NCDESTROY:
|
||||
DecrementHandleTheme(pHandleTheme);
|
||||
::SetWindowLongPtrW(hWnd, GWLP_USERDATA, 0);
|
||||
break;
|
||||
|
||||
case WM_CREATE:
|
||||
{
|
||||
HRESULT hr = ThemeLoadControls(vpTheme, hWnd, vrgInitControls, countof(vrgInitControls));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_THMVWR_THEME_LOAD_ERROR:
|
||||
OnThemeLoadError(vpTheme, lParam);
|
||||
return 0;
|
||||
|
||||
case WM_THMVWR_NEW_THEME:
|
||||
OnNewTheme(vpTheme, hWnd, reinterpret_cast<HANDLE_THEME*>(lParam));
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
::PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
NMHDR* pnmhdr = reinterpret_cast<NMHDR*>(lParam);
|
||||
switch (pnmhdr->code)
|
||||
{
|
||||
case TVN_SELCHANGEDW:
|
||||
{
|
||||
NMTREEVIEWW* ptv = reinterpret_cast<NMTREEVIEWW*>(lParam);
|
||||
::PostThreadMessageW(vdwDisplayThreadId, WM_THMVWR_SHOWPAGE, SW_HIDE, ptv->itemOld.lParam);
|
||||
::PostThreadMessageW(vdwDisplayThreadId, WM_THMVWR_SHOWPAGE, SW_SHOW, ptv->itemNew.lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
//case NM_DBLCLK:
|
||||
// TVITEM item = { };
|
||||
// item.mask = TVIF_PARAM;
|
||||
// item.hItem = TreeView_GetSelection(pnmhdr->hwndFrom);
|
||||
// TreeView_GetItem(pnmhdr->hwndFrom, &item);
|
||||
// ::PostThreadMessageW(vdwDisplayThreadId, WM_THMVWR_SHOWPAGE, SW_SHOW, item.lParam);
|
||||
// return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ThemeDefWindowProc(vpTheme, hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
static void OnThemeLoadError(
|
||||
__in THEME* pTheme,
|
||||
__in HRESULT hrFailure
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
LPWSTR sczMessage = NULL;
|
||||
TVINSERTSTRUCTW tvi = { };
|
||||
|
||||
// Add the application node.
|
||||
tvi.hParent = NULL;
|
||||
tvi.hInsertAfter = TVI_ROOT;
|
||||
tvi.item.mask = TVIF_TEXT | TVIF_PARAM;
|
||||
tvi.item.lParam = 0;
|
||||
tvi.item.pszText = L"Failed to load theme.";
|
||||
tvi.hParent = reinterpret_cast<HTREEITEM>(ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi)));
|
||||
|
||||
hr = StrAllocFormatted(&sczMessage, L"Error 0x%08x.", hrFailure);
|
||||
ExitOnFailure(hr, "Failed to format error message.");
|
||||
|
||||
tvi.item.pszText = sczMessage;
|
||||
ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi));
|
||||
|
||||
hr = StrAllocFromError(&sczMessage, hrFailure, NULL);
|
||||
ExitOnFailure(hr, "Failed to format error message text.");
|
||||
|
||||
tvi.item.pszText = sczMessage;
|
||||
ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi));
|
||||
|
||||
ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_EXPAND, TVE_EXPAND, reinterpret_cast<LPARAM>(tvi.hParent));
|
||||
|
||||
LExit:
|
||||
ReleaseStr(sczMessage);
|
||||
}
|
||||
|
||||
|
||||
static void OnNewTheme(
|
||||
__in THEME* pTheme,
|
||||
__in HWND hWnd,
|
||||
__in HANDLE_THEME* pHandle
|
||||
)
|
||||
{
|
||||
HANDLE_THEME* pOldHandle = reinterpret_cast<HANDLE_THEME*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
|
||||
THEME* pNewTheme = pHandle->pTheme;
|
||||
|
||||
WCHAR wzSelectedPage[MAX_PATH] = { };
|
||||
HTREEITEM htiSelected = NULL;
|
||||
TVINSERTSTRUCTW tvi = { };
|
||||
TVITEMW item = { };
|
||||
|
||||
if (pOldHandle)
|
||||
{
|
||||
DecrementHandleTheme(pOldHandle);
|
||||
pOldHandle = NULL;
|
||||
}
|
||||
|
||||
// Pass the new theme handle to the display thread so it can get the display window prepared
|
||||
// to show the new theme.
|
||||
IncrementHandleTheme(pHandle);
|
||||
::PostThreadMessageW(vdwDisplayThreadId, WM_THMVWR_NEW_THEME, 0, reinterpret_cast<LPARAM>(pHandle));
|
||||
|
||||
::SetWindowLongPtrW(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pHandle));
|
||||
|
||||
// Remember the currently selected item by name so we can try to automatically select it later.
|
||||
// Otherwise, the user would see their window destroyed after every save of their theme file and
|
||||
// have to click to get the window back.
|
||||
item.mask = TVIF_TEXT;
|
||||
item.pszText = wzSelectedPage;
|
||||
item.cchTextMax = countof(wzSelectedPage);
|
||||
item.hItem = reinterpret_cast<HTREEITEM>(ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_GETNEXTITEM, TVGN_CARET, NULL));
|
||||
ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_GETITEM, 0, reinterpret_cast<LPARAM>(&item));
|
||||
|
||||
// Remove the previous items in the tree.
|
||||
ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_DELETEITEM, 0, reinterpret_cast<LPARAM>(TVI_ROOT));
|
||||
|
||||
// Add the application node.
|
||||
tvi.hParent = NULL;
|
||||
tvi.hInsertAfter = TVI_ROOT;
|
||||
tvi.item.mask = TVIF_TEXT | TVIF_PARAM;
|
||||
tvi.item.lParam = 0;
|
||||
tvi.item.pszText = pHandle && pHandle->pTheme && pHandle->pTheme->sczCaption ? pHandle->pTheme->sczCaption : L"Window";
|
||||
|
||||
// Add the pages.
|
||||
tvi.hParent = reinterpret_cast<HTREEITEM>(ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi)));
|
||||
tvi.hInsertAfter = TVI_SORT;
|
||||
for (DWORD i = 0; i < pNewTheme->cPages; ++i)
|
||||
{
|
||||
THEME_PAGE* pPage = pNewTheme->rgPages + i;
|
||||
if (pPage->sczName && *pPage->sczName)
|
||||
{
|
||||
tvi.item.pszText = pPage->sczName;
|
||||
tvi.item.lParam = i + 1; //prgdwPageIds[i]; - TODO: do the right thing here by calling ThemeGetPageIds(), should not assume we know how the page ids will be calculated.
|
||||
|
||||
HTREEITEM hti = reinterpret_cast<HTREEITEM>(ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_INSERTITEMW, 0, reinterpret_cast<LPARAM>(&tvi)));
|
||||
if (*wzSelectedPage && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, pPage->sczName, -1, wzSelectedPage, -1))
|
||||
{
|
||||
htiSelected = hti;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*wzSelectedPage && CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, 0, L"Application", -1, wzSelectedPage, -1))
|
||||
{
|
||||
htiSelected = tvi.hParent;
|
||||
}
|
||||
|
||||
ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_EXPAND, TVE_EXPAND, reinterpret_cast<LPARAM>(tvi.hParent));
|
||||
if (htiSelected)
|
||||
{
|
||||
ThemeSendControlMessage(pTheme, THMVWR_CONTROL_TREE, TVM_SELECTITEM, TVGN_CARET, reinterpret_cast<LPARAM>(htiSelected));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
|
||||
|
||||
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<assemblyIdentity name="thmviewer.exe" version="1.0.0.0" processorArchitecture="x86" type="win32"/>
|
||||
<description>WiX Toolset Theme Viewer</description>
|
||||
<dependency><dependentAssembly><assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*" /></dependentAssembly></dependency>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"><application><supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/><supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/></application></compatibility>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"><security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false"/></requestedPrivileges></security></trustInfo>
|
||||
</assembly>
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
|
||||
|
||||
#include <winver.h>
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
|
||||
//#define MANIFEST_RESOURCE_ID 1
|
||||
//MANIFEST_RESOURCE_ID RT_MANIFEST "thmviewer.manifest"
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
THMVWR_RES_THEME_FILE RCDATA "Resources\\thm.xml"
|
||||
THMVWR_RES_RICHEDIT_FILE RCDATA "Resources\\LoremIpsum.rtf"
|
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
|
||||
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\packages\WixToolset.DUtil.4.0.6\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.6\build\WixToolset.DUtil.props')" />
|
||||
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{95228C13-97F5-484A-B4A2-ECF4618B0881}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<Description>WiX Toolset Theme Viewer</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
|
||||
<ImportGroup Label="Shared">
|
||||
<Import Project="..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets" Condition="Exists('..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets')" />
|
||||
</ImportGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ProjectAdditionalLinkLibraries>comctl32.lib;gdiplus.lib;msimg32.lib;shlwapi.lib</ProjectAdditionalLinkLibraries>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ClCompile Include="display.cpp" />
|
||||
<ClCompile Include="load.cpp" />
|
||||
<ClCompile Include="precomp.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="thmviewer.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="precomp.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources\LoremIpsum.rtf" />
|
||||
<None Include="Resources\thm.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="thmviewer.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="thmviewer.manifest" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
<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\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets'))" />
|
||||
<Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.6\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.6\build\WixToolset.DUtil.props'))" />
|
||||
</Target>
|
||||
</Project>
|
|
@ -0,0 +1,53 @@
|
|||
<?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;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;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</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="thmviewer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="display.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="load.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="thmviewer.build" />
|
||||
<None Include="Resources\thm.xml">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="Resources\LoremIpsum.rtf">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="precomp.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="thmviewer.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="thmviewer.manifest" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Загрузка…
Ссылка в новой задаче