Fixed line endings and applied gitignore

This commit is contained in:
2014-07-26 09:43:40 +03:00
parent 0c57cabe56
commit 7cba5cc109
542 changed files with 112014 additions and 119759 deletions

View File

@ -1,176 +0,0 @@
@echo off
setlocal EnableDelayedExpansion
set VCVARSALL=%VS120COMNTOOLS%..\..\VC\vcvarsall.bat
set MAKENSIS=%PROGRAMFILES%\NSIS\MakeNSIS.exe
set GIT=%PROGRAMFILES%\Git\bin\git.exe
:: Set VERSION_REVISION to non-zero value to override
set VERSION_MAJOR=3
set VERSION_MINOR=2
set VERSION_SUBMINOR=0
set VERSION_REVISION=0
set ISBETA=true
if "%1" == "RELEASE" set ISBETA=false
if "%1" == "BUILDVERSION" goto BUILDVERSION
echo Rainmeter Build
echo ----------------------------------------------
echo.
if not exist "%VCVARSALL%" echo ERROR: vcvarsall.bat not found & goto END
call "%VCVARSALL%" x86 > nul
set MSBUILD="msbuild.exe" /nologo^
/p:PlatformToolset=v120_xp;VisualStudioVersion=12.0^
/p:ExcludeTests=true^
/p:Configuration=Release
if exist "Certificate.bat" call "Certificate.bat" > nul
set SIGNTOOL="signtool.exe" sign /t http://time.certum.pl /f "%CERTFILE%" /p "%CERTKEY%"
if "%1" == "BUILDLANGUAGES" goto BUILDLANGUAGES
if exist "%MAKENSIS%" goto NSISFOUND
set MAKENSIS=%MAKENSIS:Program Files\=Program Files (x86)\%
if not exist "%MAKENSIS%" echo ERROR: MakeNSIS.exe not found & goto END
:NSISFOUND
:BUILDVERSION
if not exist "..\.git" goto UPDATEVERSION
if not "%VERSION_REVISION%" == "0" goto UPDATEVERSION
:: git
if exist "%GIT%" goto GITFOUND
set GIT=%GIT:Program Files\=Program Files (x86)\%
if not exist "%GIT%" echo ERROR: git.exe not found & goto END
:GITFOUND
set /a VERSION_REVISION=0
for /f "usebackq delims= " %%G in (`"%GIT%" rev-list --all --count`) do set VERSION_REVISION=%%G
:UPDATEVERSION
set VERSION_FULL=%VERSION_MAJOR%.%VERSION_MINOR%.%VERSION_SUBMINOR%.%VERSION_REVISION%
set VERSION_SHORT=%VERSION_MAJOR%.%VERSION_MINOR%
if not "%VERSION_SUBMINOR%" == "0" set VERSION_SHORT=!VERSION_SHORT!.%VERSION_SUBMINOR%
:: Update Version.h
> "..\Version.h" echo #pragma once
>>"..\Version.h" echo #define FILEVER %VERSION_MAJOR%,%VERSION_MINOR%,%VERSION_SUBMINOR%,%VERSION_REVISION%
>>"..\Version.h" echo #define PRODUCTVER FILEVER
>>"..\Version.h" echo #define STRFILEVER "%VERSION_FULL%"
>>"..\Version.h" echo #define STRPRODUCTVER STRFILEVER
>>"..\Version.h" echo #define APPVERSION L"%VERSION_MAJOR%.%VERSION_MINOR%.%VERSION_SUBMINOR%"
>>"..\Version.h" echo #define RAINMETER_VERSION ((%VERSION_MAJOR% * 1000000) + (%VERSION_MINOR% * 1000) + %VERSION_SUBMINOR%)
>>"..\Version.h" echo const int revision_number = %VERSION_REVISION%;
>>"..\Version.h" echo const bool revision_beta = %ISBETA%;
:: Update Version.cs
> "..\Version.cs" echo namespace Rainmeter
>>"..\Version.cs" echo {
>>"..\Version.cs" echo public class Version
>>"..\Version.cs" echo {
>>"..\Version.cs" echo #if X64
>>"..\Version.cs" echo public const string Informational = "%VERSION_FULL% (64-bit)";
>>"..\Version.cs" echo #else
>>"..\Version.cs" echo public const string Informational = "%VERSION_FULL% (32-bit)";
>>"..\Version.cs" echo #endif
>>"..\Version.cs" echo }
>>"..\Version.cs" echo }
if "%1" == "BUILDVERSION" goto :eof
echo * Updated Version.h
:: Set vcbuild environment variables and begin build
echo * Starting build for %VERSION_FULL%
for /F "tokens=1-4 delims=:.," %%a in ("%TIME%") do (
set /A "BUILD_BEGIN_TIMESTAMP=(((%%a * 60) + 1%%b %% 100)* 60 + 1%%c %% 100) * 100 + 1%%d %% 100"
)
:: Build Library
echo * Building 32-bit projects
%MSBUILD% /t:rebuild /p:Platform=Win32 /v:q /m ..\Rainmeter.sln > "BuildLog.txt"
if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Build failed & goto END
echo * Building 64-bit projects
%MSBUILD% /t:rebuild /p:Platform=x64 /v:q /m ..\Rainmeter.sln > "BuildLog.txt"
if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Build failed & goto END
:BUILDLANGUAGES
echo * Building languages
:: Build all language libraries
>".\Installer\Languages.nsh" echo.
for /f "tokens=1,2,3 delims=," %%a in (..\Language\List) do (
> "..\Language\Language.rc" echo #include "%%a.h"
>>"..\Language\Language.rc" echo #include "Resource.rc"
>>".\Installer\Languages.nsh" echo ${IncludeLanguage} "%%b" "%%a"
set LANGDLL_PARAMS='%%a - ${LANGFILE_%%b_NAME}' '${LANG_%%b}' '${LANG_%%b_CP}' !LANGDLL_PARAMS!
set LANGUAGE_IDS=${LANG_%%b},!LANGUAGE_IDS!
%MSBUILD% /t:Language /p:Platform=Win32;TargetName=%%c /v:q ..\Rainmeter.sln > "BuildLog.txt"
if not %ERRORLEVEL% == 0 echo ERROR: Building language %%a failed & goto END
)
>>".\Installer\Languages.nsh" echo ^^!define LANGDLL_PARAMS "%LANGDLL_PARAMS%"
>>".\Installer\Languages.nsh" echo ^^!define LANGUAGE_IDS "%LANGUAGE_IDS%"
:: Restore English
echo #include "English.h"> "..\Language\Language.rc"
echo #include "Resource.rc">> "..\Language\Language.rc"
if "%1" == "BUILDLANGUAGES" (
xcopy /Q /S /Y ..\x32-Release\Languages\*.dll ..\x64-Release\Languages\ > nul
xcopy /Q /S /Y ..\x32-Release\Release\Languages\*.dll ..\x32-Debug\Languages\ > nul
xcopy /Q /S /Y ..\x32-Release\Release\Languages\*.dll ..\x64-Debug\Languages\ > nul
if exist "BuildLog.txt" del "BuildLog.txt"
goto END
)
:: Sign binaries
if not "%CERTFILE%" == "" (
echo * Signing binaries
for %%Z in (Rainmeter.dll Rainmeter.exe SkinInstaller.exe SkinInstaller.dll) do (
%SIGNTOOL% ..\x32-Release\%%Z > BuildLog.txt
if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Signing x32\%%Z failed & goto END
%SIGNTOOL% ..\x64-Release\%%Z > BuildLog.txt
if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Signing x64\%%Z failed & goto END
)
)
:: Build installer
echo * Building installer
set INSTALLER_NAME=Rainmeter-%VERSION_SHORT%.exe
if not "%1" == "RELEASE" set INSTALLER_NAME=Rainmeter-%VERSION_SHORT%-r%VERSION_REVISION%-beta.exe
set INSTALLER_DEFINES=^
/DOUTFILE="%INSTALLER_NAME%"^
/DVERSION_FULL="%VERSION_FULL%"^
/DVERSION_SHORT="%VERSION_SHORT%"^
/DVERSION_REVISION="%VERSION_REVISION%"
if not "%1" == "RELEASE" set INSTALLER_DEFINES=!INSTALLER_DEFINES! /DBETA
"%MAKENSIS%" %INSTALLER_DEFINES% .\Installer\Installer.nsi > "BuildLog.txt"
if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Building installer failed & goto END
:: Sign installer
if not "%CERTFILE%" == "" (
echo * Signing installer
%SIGNTOOL% %INSTALLER_NAME% > BuildLog.txt
if not %ERRORLEVEL% == 0 echo ERROR %ERRORLEVEL%: Signing installer failed & goto END
)
:: If we got here, build was successful so delete BuildLog.txt
if exist "BuildLog.txt" del "BuildLog.txt"
for /F "tokens=1-4 delims=:.," %%a in ("%TIME%") do (
set /A "BUILD_END_TIMESTAMP=(((%%a * 60) + 1%%b %% 100)* 60 + %%c %% 100) * 100 + 1%%d %% 100"
)
set /A "BUILD_ELAPSED_TIME=(%BUILD_END_TIMESTAMP% - %BUILD_BEGIN_TIMESTAMP%) / 100"
echo * Build complete. Elapsed time: %BUILD_ELAPSED_TIME% sec
:END
if exist ".\Installer\Languages.nsh" del ".\Installer\Languages.nsh"
echo.
pause

View File

@ -1,2 +0,0 @@
@echo off
"Build.bat" BUILDLANGUAGES

View File

@ -1,2 +0,0 @@
@echo off
"Build.bat" BUILDVERSION

View File

@ -1,7 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("© 2013 - Birunthan Mohanathas")]
[assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyProduct("Rainmeter")]

View File

@ -1,82 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{49D56CA5-54AB-45C9-A245-EAE588FCBFE1}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DllExporter</RootNamespace>
<AssemblyName>DllExporter</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<OutputPath Condition=" '$(Platform)' == 'x86' ">$(SolutionDir)x32-$(Configuration)\Tools\</OutputPath>
<OutputPath Condition=" '$(Platform)' == 'x64' ">$(SolutionDir)x64-$(Configuration)\Tools\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>1607</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>1607</NoWarn>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<NoWarn>1607</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>none</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<NoWarn>1607</NoWarn>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Build.Utilities.v4.0" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,241 +0,0 @@
/*
Copyright (C) 2011 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using Microsoft.Build.Utilities;
using System.IO;
namespace DllExporter
{
class Program
{
static int Main(string[] args)
{
if (args.Length < 4)
{
Console.WriteLine("DllExporter error: Invalid arguments");
return 1;
}
string configurationName = args[0];
string platformTarget = args[1];
string targetDirectory = args[2];
string targetDllName = targetDirectory + args[3];
string targetIlName = targetDllName + ".il";
string targetResName = targetDllName + ".res";
bool is64 = platformTarget.ToLower().Equals("x64");
bool isDebug = configurationName.ToLower().Equals("debug");
string ilasmPath = FindIlasmPath(is64);
if (ilasmPath == null)
{
Console.WriteLine("DllExporter error: ilasm.exe not found");
return 1;
}
string ildasmPath = FindIldasmPath();
if (ildasmPath == null)
{
Console.WriteLine("DllExporter error: ildasm.exe not found");
return 1;
}
Directory.SetCurrentDirectory(targetDirectory);
// Disassemble
Process ildasmProc = new Process();
string ildasmArgs = string.Format(
"/nobar {0} /output=\"{1}\" \"{2}\"",
isDebug ? "/linenum" : "",
targetIlName,
targetDllName);
ildasmProc.StartInfo = new ProcessStartInfo(ildasmPath, ildasmArgs);
ildasmProc.StartInfo.UseShellExecute = false;
ildasmProc.StartInfo.CreateNoWindow = false;
ildasmProc.StartInfo.RedirectStandardOutput = true;
ildasmProc.Start();
ildasmProc.WaitForExit();
if (ildasmProc.ExitCode != 0)
{
Console.WriteLine("DllExporter error: Unable to disassemble!");
Console.WriteLine(ildasmProc.StandardOutput.ReadToEnd());
return ildasmProc.ExitCode;
}
bool hasResource = File.Exists(targetResName);
// Read disassembly and find methods marked with DllExport attribute
List<string> lines = new List<string>(File.ReadAllLines(targetIlName));
int attributeIndex = 0;
int exportCount = 0;
while (true)
{
attributeIndex = lines.FindIndex(attributeIndex, new Predicate<string>(x => x.Contains(".custom instance void") && x.Contains("DllExport::.ctor()")));
if (attributeIndex < 8) break;
int methodIndex = lines.FindLastIndex(attributeIndex, attributeIndex, new Predicate<string>(x => x.Contains(".method")));
if (methodIndex == -1)
{
Console.WriteLine("DllExporter error: Unable to parse disassembly (.method not found)!");
return 1;
}
int functionIndex = lines.FindIndex(methodIndex, new Predicate<string>(x => x.Contains("(")));
if (functionIndex == -1)
{
Console.WriteLine("DllExporter error: Unable to parse disassembly (bracket not found)!");
return 1;
}
int bracketPos = lines[functionIndex].IndexOf('(');
int functionNamePos = lines[functionIndex].LastIndexOf(' ', bracketPos);
string functionName = lines[functionIndex].Substring(functionNamePos, bracketPos - functionNamePos);
// Change calling convention to cdecl
lines[functionIndex] = string.Format("{0} modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) {1}", lines[functionIndex].Substring(0, functionNamePos - 1), lines[functionIndex].Substring(functionNamePos));
int attributeBeginPos = lines[attributeIndex].IndexOf('.');
string spaces = new string(' ', attributeBeginPos);
// Replace attribute with export
++exportCount;
lines[attributeIndex] = string.Format("{0}.export [{1}] as {2}", spaces, exportCount, functionName);
++attributeIndex;
}
if (exportCount == 0)
{
Console.WriteLine("DllExporter warning: Nothing found to export.");
}
// Remove the DllExport class
int classIndex = lines.FindIndex(new Predicate<string>(x => x.Contains(".class ") && x.EndsWith(".DllExport")));
if (classIndex == -1)
{
Console.WriteLine("DllExporter error: Unable to parse disassembly (DllExport class not found)!");
return 1;
}
else
{
int classEndIndex = lines.FindIndex(classIndex, new Predicate<string>(x => x.Contains("} // end of class") && x.EndsWith(".DllExport")));
if (classEndIndex == -1)
{
Console.WriteLine("DllExporter error: Unable to parse disassembly (DllExport class end not found)!");
return 1;
}
lines.RemoveRange(classIndex, classEndIndex - classIndex + 2);
}
// Write everything back
File.WriteAllLines(targetIlName, lines.ToArray());
// Reassemble
Process ilasmProc = new Process();
string resource = hasResource ? string.Format("/resource=\"{0}\"", targetResName) : "";
string ilasmArgs = string.Format("/nologo /quiet /dll {0} {1} /output=\"{2}\" {3} \"{4}\"", isDebug ? "/debug /pdb" : "/optimize", is64 ? "/x64 /PE64" : "", targetDllName, resource, targetIlName);
ilasmProc.StartInfo = new ProcessStartInfo(ilasmPath, ilasmArgs);
ilasmProc.StartInfo.UseShellExecute = false;
ilasmProc.StartInfo.CreateNoWindow = false;
ilasmProc.StartInfo.RedirectStandardOutput = true;
ilasmProc.Start();
ilasmProc.WaitForExit();
if (ilasmProc.ExitCode != 0)
{
Console.WriteLine("DllExporter error: Unable to assemble!");
Console.WriteLine(ilasmProc.StandardOutput.ReadToEnd());
return ilasmProc.ExitCode;
}
// Cleanup
File.Delete(targetIlName);
File.Delete(targetResName);
Console.WriteLine("DllExporter: Processed {0}", args[3]);
return 0;
}
/// <summary>
/// Finds path to ilasm.exe.
/// </summary>
private static string FindIlasmPath(bool x64)
{
var arch = x64 ? DotNetFrameworkArchitecture.Bitness64 : DotNetFrameworkArchitecture.Bitness32;
var path = ToolLocationHelper.GetPathToDotNetFrameworkFile(
"ilasm.exe", TargetDotNetFrameworkVersion.Version20, arch);
return File.Exists(path) ? path : null;
}
/// <summary>
/// Finds path to ildasm.exe.
/// </summary>
private static string FindIldasmPath()
{
var sdkPath = Environment.ExpandEnvironmentVariables(@"%ProgramFiles(x86)%\Microsoft SDKs\Windows\");
if (!Directory.Exists(sdkPath))
{
sdkPath = Environment.ExpandEnvironmentVariables(@"%ProgramFiles%\Microsoft SDKs\Windows\");
}
if (!Directory.Exists(sdkPath))
{
throw new DirectoryNotFoundException("'Microsoft SDKs' directory not found");
}
// Get the version directories.
var sdkVersionDirectories = Directory.GetDirectories(sdkPath);
foreach (var sdkVersionDirectory in sdkVersionDirectories)
{
var binDirectory = Path.Combine(sdkVersionDirectory, @"bin");
if (!Directory.Exists(binDirectory))
{
continue;
}
// Check for e.g. 'Microsoft SDKs\v8.0A\bin\ildasm.exe'.
var ildasmPath = Path.Combine(binDirectory, @"ildasm.exe");
if (File.Exists(ildasmPath))
{
return ildasmPath;
}
// Check for e.g. 'Microsoft SDKs\v8.0A\bin\NETFX 4.0 Tools\ildasm.exe'.
var toolsDirectories = Directory.GetDirectories(binDirectory, "NETFX*Tools");
foreach (var toolDirectory in toolsDirectories)
{
ildasmPath = Path.Combine(toolDirectory, @"ildasm.exe");
if (File.Exists(ildasmPath))
{
return ildasmPath;
}
}
}
return null;
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,959 +0,0 @@
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
!verbose 3
!addplugindir ".\"
!include "MUI2.nsh"
!include "x64.nsh"
!include "FileFunc.nsh"
!include "WordFunc.nsh"
!include "WinVer.nsh"
!include "UAC.nsh"
!ifndef OUTFILE
!define OUTFILE "Rainmeter-test.exe"
!define VERSION_FULL "0.0.0.0"
!define VERSION_SHORT "0.0"
!define VERSION_REVISION "000"
!else
!define INCLUDEFILES
!endif
Name "Rainmeter"
VIAddVersionKey "ProductName" "Rainmeter"
VIAddVersionKey "FileDescription" "Rainmeter Installer"
VIAddVersionKey "FileVersion" "${VERSION_FULL}"
VIAddVersionKey "ProductVersion" "${VERSION_FULL}"
VIAddVersionKey "OriginalFilename" "${OUTFILE}"
VIAddVersionKey "LegalCopyright" "Copyright (C) 2009-2013 - All authors"
VIProductVersion "${VERSION_FULL}"
BrandingText " "
SetCompressor /SOLID lzma
RequestExecutionLevel user
InstallDirRegKey HKLM "SOFTWARE\Rainmeter" ""
ShowInstDetails nevershow
AllowSkipFiles off
XPStyle on
OutFile "..\${OUTFILE}"
ReserveFile "${NSISDIR}\Plugins\LangDLL.dll"
ReserveFile "${NSISDIR}\Plugins\nsDialogs.dll"
ReserveFile "${NSISDIR}\Plugins\System.dll"
ReserveFile ".\UAC.dll"
!define REQUIREDSPACE 5 ; Minimum required space for install (in MB)
; Error levels (for silent install)
!define ERROR_UNSUPPORTED 3
!define ERROR_NOTADMIN 4
!define ERROR_WRITEFAIL 5
!define ERROR_NOVCREDIST 6
!define ERROR_CLOSEFAIL 7
; Additional Windows definitions
!define BCM_SETSHIELD 0x0000160c
!define PF_XMMI_INSTRUCTIONS_AVAILABLE 6
!define PF_XMMI64_INSTRUCTIONS_AVAILABLE 10
!define MUI_ICON ".\Icon.ico"
!define MUI_UNICON ".\Icon.ico"
!define MUI_WELCOMEFINISHPAGE_BITMAP ".\Wizard.bmp"
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_FUNCTION FinishRun
!define MUI_WELCOMEPAGE ; For language strings
Page custom PageWelcome PageWelcomeOnLeave
Page custom PageOptions PageOptionsOnLeave
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
UninstPage custom un.PageOptions un.GetOptions
!insertmacro MUI_UNPAGE_INSTFILES
; Include languages
!macro IncludeLanguage LANGUAGE CUSTOMLANGUAGE
!insertmacro MUI_LANGUAGE ${LANGUAGE}
!insertmacro LANGFILE_INCLUDE "..\..\Language\${CUSTOMLANGUAGE}.nsh"
!macroend
!define IncludeLanguage "!insertmacro IncludeLanguage"
!include "Languages.nsh"
Var NonDefaultLanguage
Var AutoStartup
Var Install64Bit
Var InstallPortable
Var un.DeleteAll
; Install
; --------------------------------------
Function .onInit
${If} ${RunningX64}
${EnableX64FSRedirection}
${EndIf}
${IfNot} ${UAC_IsInnerInstance}
${If} ${IsWin2000}
${OrIf} ${IsWinXP}
${AndIf} ${AtMostServicePack} 2
${OrIf} ${IsWin2003}
${AndIf} ${AtMostServicePack} 0
${IfNot} ${Silent}
MessageBox MB_OK|MB_ICONSTOP "Rainmeter requires Windows XP SP3 or later."
${EndIf}
SetErrorLevel ${ERROR_UNSUPPORTED}
Quit
${EndIf}
System::Call 'kernel32::IsProcessorFeaturePresent(i${PF_XMMI_INSTRUCTIONS_AVAILABLE})i.r0'
${If} $0 = 0
${IfNot} ${Silent}
MessageBox MB_OK|MB_ICONSTOP "Rainmeter requires a Pentium III or later processor."
${EndIf}
SetErrorLevel ${ERROR_UNSUPPORTED}
Quit
${EndIf}
ReadRegStr $0 HKLM "SOFTWARE\Rainmeter" "Language"
ReadRegDWORD $NonDefaultLanguage HKLM "SOFTWARE\Rainmeter" "NonDefault"
${IfNot} ${Silent}
${If} $0 == ""
${OrIf} $0 <> $LANGUAGE
${AndIf} $NonDefaultLanguage != 1
; New install or better match
LangDLL::LangDialog "$(^SetupCaption)" "Please select the installer language.$\n$(SELECTLANGUAGE)" AC ${LANGDLL_PARAMS} ""
Pop $0
${If} $0 == "cancel"
Abort
${EndIf}
${If} $0 <> $LANGUAGE
; User selected non-default language
StrCpy $NonDefaultLanguage 1
${EndIf}
${EndIf}
StrCpy $LANGUAGE $0
${Else}
${If} $0 != ""
StrCpy $LANGUAGE $0
${EndIf}
${GetParameters} $R1
ClearErrors
${GetOptions} $R1 "/LANGUAGE=" $0
${IfNot} ${Errors}
${If} $LANGUAGE != $0
StrCpy $NonDefaultLanguage 1
${EndIf}
StrCpy $LANGUAGE $0
${EndIf}
${GetOptions} $R1 "/STARTUP=" $0
${If} $0 = 1
StrCpy $AutoStartup 1
${EndIf}
${GetOptions} $R1 "/PORTABLE=" $0
${If} $0 = 1
StrCpy $InstallPortable 1
${Else}
${IfNot} ${UAC_IsAdmin}
SetErrorLevel ${ERROR_NOTADMIN}
Quit
${EndIf}
${EndIf}
${GetOptions} $R1 "/VERSION=" $0
${If} $0 = 64
StrCpy $Install64Bit 1
${If} $INSTDIR == ""
StrCpy $INSTDIR "$PROGRAMFILES64\Rainmeter"
${EndIf}
${Else}
${If} $INSTDIR == ""
StrCpy $INSTDIR "$PROGRAMFILES\Rainmeter"
${EndIf}
${EndIf}
ClearErrors
CreateDirectory "$INSTDIR"
WriteINIStr "$INSTDIR\writetest~.rm" "1" "1" "1"
Delete "$INSTDIR\writetest~.rm"
${If} ${Errors}
RMDir "$INSTDIR"
SetErrorLevel ${ERROR_WRITEFAIL}
Quit
${EndIf}
${EndIf}
; If the language was set to a non-existent language, reset it back to English.
${WordFind} ",${LANGUAGE_IDS}" ",$LANGUAGE," "E+1{" $0
${If} ${Errors}
StrCpy $LANGUAGE "1033"
${EndIf}
${Else}
; Exchange settings with user instance
!insertmacro UAC_AsUser_Call Function ExchangeSettings ${UAC_SYNCREGISTERS}
StrCpy $AutoStartup $1
StrCpy $Install64Bit $2
StrCpy $NonDefaultLanguage $3
StrCpy $LANGUAGE $4
StrCpy $INSTDIR $5
${EndIf}
FunctionEnd
Function ExchangeSettings
StrCpy $1 $AutoStartup
StrCpy $2 $Install64Bit
StrCpy $3 $NonDefaultLanguage
StrCpy $4 $LANGUAGE
StrCpy $5 $INSTDIR
HideWindow
FunctionEnd
Function PageWelcome
${If} ${UAC_IsInnerInstance}
${If} ${UAC_IsAdmin}
; Skip page
Abort
${Else}
MessageBox MB_OK|MB_ICONSTOP "$(ADMINERROR) (Inner)"
Quit
${EndIf}
${EndIf}
!insertmacro MUI_HEADER_TEXT "$(INSTALLOPTIONS)" "$(^ComponentsSubText1)"
nsDialogs::Create 1044
Pop $0
nsDialogs::SetRTL $(^RTL)
SetCtlColors $0 "" "${MUI_BGCOLOR}"
${NSD_CreateBitmap} 0u 0u 109u 193u ""
Pop $0
${NSD_SetImage} $0 "$PLUGINSDIR\modern-wizard.bmp" $R0
${NSD_CreateLabel} 120u 10u 195u 38u "$(MUI_TEXT_WELCOME_INFO_TITLE)"
Pop $0
SetCtlColors $0 "" "${MUI_BGCOLOR}"
CreateFont $1 "$(^Font)" "12" "700"
SendMessage $0 ${WM_SETFONT} $1 0
${NSD_CreateLabel} 120u 55u 195u 12u "$(^ComponentsSubText1)"
Pop $0
SetCtlColors $0 "" "${MUI_BGCOLOR}"
${NSD_CreateRadioButton} 120u 70u 205u 12u "$(STANDARDINST)"
Pop $R1
SetCtlColors $R1 "" "${MUI_BGCOLOR}"
${NSD_AddStyle} $R1 ${WS_GROUP}
SendMessage $R1 ${WM_SETFONT} $mui.Header.Text.Font 0
${NSD_CreateLabel} 132u 82u 185u 24u "$(STANDARDINSTDESC)"
Pop $0
SetCtlColors $0 "" "${MUI_BGCOLOR}"
${NSD_CreateRadioButton} 120u 106u 310u 12u "$(PORTABLEINST)"
Pop $R2
SetCtlColors $R2 "" "${MUI_BGCOLOR}"
${NSD_AddStyle} $R2 ${WS_TABSTOP}
SendMessage $R2 ${WM_SETFONT} $mui.Header.Text.Font 0
${NSD_CreateLabel} 132u 118u 185u 52u "$(PORTABLEINSTDESC)"
Pop $0
SetCtlColors $0 "" "${MUI_BGCOLOR}"
${If} $InstallPortable = 1
${NSD_Check} $R2
${Else}
${NSD_Check} $R1
${EndIf}
Call muiPageLoadFullWindow
nsDialogs::Show
${NSD_FreeImage} $R0
FunctionEnd
Function PageWelcomeOnLeave
${NSD_GetState} $R2 $InstallPortable
Call muiPageUnloadFullWindow
FunctionEnd
Function PageOptions
${If} ${UAC_IsInnerInstance}
${AndIf} ${UAC_IsAdmin}
; Skip page
Abort
${EndIf}
!insertmacro MUI_HEADER_TEXT "$(INSTALLOPTIONS)" "$(INSTALLOPTIONSDESC)"
nsDialogs::Create 1018
nsDialogs::SetRTL $(^RTL)
${NSD_CreateGroupBox} 0 0u -1u 36u "$(^DirSubText)"
${NSD_CreateDirRequest} 6u 14u 232u 14u ""
Pop $R0
${NSD_OnChange} $R0 PageOptionsDirectoryOnChange
${NSD_CreateBrowseButton} 242u 14u 50u 14u "$(^BrowseBtn)"
Pop $R1
${NSD_OnClick} $R1 PageOptionsBrowseOnClick
StrCpy $1 0
StrCpy $R2 0
${If} ${RunningX64}
${If} $InstallPortable = 1
${OrIf} $INSTDIR == ""
${NSD_CreateCheckBox} 6u 54u 285u 12u "$(INSTALL64BIT)"
Pop $R2
StrCpy $1 30u
${EndIf}
${EndIf}
${If} $InstallPortable <> 1
${If} $1 = 0
StrCpy $0 54u
StrCpy $1 30u
${Else}
StrCpy $0 66u
StrCpy $1 42u
${EndIf}
${NSD_CreateCheckbox} 6u $0 285u 12u "$(AUTOSTARTUP)"
Pop $R3
${If} $INSTDIR == ""
${NSD_Check} $R3
${Else}
SetShellVarContext all
${If} ${FileExists} "$SMSTARTUP\Rainmeter.lnk"
${NSD_Check} $R3
${EndIf}
SetShellVarContext current
${If} ${FileExists} "$SMSTARTUP\Rainmeter.lnk"
${NSD_Check} $R3
${EndIf}
${EndIf}
${Else}
StrCpy $R3 0
${EndIf}
${If} $1 <> 0
${NSD_CreateGroupBox} 0 42u -1u $1 "$(ADDITIONALOPTIONS)"
${EndIf}
; Set default directory
${If} $InstallPortable = 1
${GetRoot} "$WINDIR" $0
${NSD_SetText} $R0 "$0\Rainmeter"
${Else}
; Disable Directory editbox and Browse button if already installed
SendMessage $R0 ${EM_SETREADONLY} 1 0
${If} $INSTDIR != ""
EnableWindow $R1 0
${NSD_SetText} $R0 "$INSTDIR"
${Else}
; Fresh install
${If} ${RunningX64}
${NSD_SetText} $R0 "$PROGRAMFILES64\Rainmeter"
${NSD_Check} $R2
${Else}
${NSD_SetText} $R0 "$PROGRAMFILES\Rainmeter"
${EndIf}
${EndIf}
${EndIf}
; Show UAC shield on Install button if requiredd
GetDlgItem $0 $HWNDPARENT 1
${If} $InstallPortable = 1
SendMessage $0 ${BCM_SETSHIELD} 0 0
${Else}
SendMessage $0 ${BCM_SETSHIELD} 0 1
; Hide Back button
GetDlgItem $0 $HWNDPARENT 3
ShowWindow $0 ${SW_HIDE}
${EndIf}
nsDialogs::Show
FunctionEnd
Function PageOptionsDirectoryOnChange
${NSD_GetText} $R0 $0
; Disable Install button if not enough space
GetDlgItem $1 $HWNDPARENT 1
${GetRoot} $0 $2
${DriveSpace} "$2\" "/D=F /S=M" $3
${If} $3 < ${REQUIREDSPACE}
EnableWindow $1 0
${Else}
EnableWindow $1 1
${EndIf}
StrCpy $Install64Bit 0
${If} ${RunningX64}
${If} ${FileExists} "$0\Rainmeter.exe"
MoreInfo::GetProductVersion "$0\Rainmeter.exe"
Pop $0
StrCpy $0 $0 2 -7
${If} $0 == 64
StrCpy $Install64Bit 1
${EndIf}
${If} $R2 != 0
${NSD_SetState} $R2 $Install64Bit
EnableWindow $R2 0
${EndIf}
${Else}
${If} $R2 != 0
EnableWindow $R2 1
${EndIf}
${EndIf}
${EndIf}
FunctionEnd
Function PageOptionsBrowseOnClick
${NSD_GetText} $R0 $0
nsDialogs::SelectFolderDialog "$(^DirBrowseText)" $0
Pop $1
${If} $1 != error
${NSD_SetText} $R0 $1
${EndIf}
FunctionEnd
Function PageOptionsOnLeave
; Verify that selected folder is writable
${NSD_GetText} $R0 $0
${If} $InstallPortable = 1
ClearErrors
CreateDirectory "$0"
WriteINIStr "$0\writetest~.rm" "1" "1" "1"
Delete "$0\writetest~.rm"
${If} ${Errors}
RMDir "$0"
MessageBox MB_OK|MB_ICONEXCLAMATION "$(WRITEERROR)"
Abort
${EndIf}
RMDir "$0"
${EndIf}
StrCpy $INSTDIR $0
GetDlgItem $0 $HWNDPARENT 1
EnableWindow $0 0
${If} $R2 != 0
${NSD_GetState} $R2 $Install64Bit
${EndIf}
${If} $R3 != 0
${NSD_GetState} $R3 $AutoStartup
${EndIf}
${If} $InstallPortable <> 1
${IfNot} ${UAC_IsAdmin}
; UAC_IsAdmin seems to return incorrect result sometimes. Recheck with UserInfo::GetAccountType to be sure.
UserInfo::GetAccountType
Pop $0
${If} $0 != "Admin"
UAC_TryAgain:
!insertmacro UAC_RunElevated
${Switch} $0
${Case} 0
${IfThen} $1 = 1 ${|} Quit ${|}
${IfThen} $3 <> 0 ${|} ${Break} ${|}
${If} $1 = 3
MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(ADMINERROR)" /SD IDNO IDOK UAC_TryAgain IDNO 0
${EndIf}
${Case} 1223
Quit
${Case} 1062
MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(LOGONERROR)"
Quit
${Default}
MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(UACERROR) ($0)"
Quit
${EndSwitch}
${EndIf}
${EndIf}
${EndIf}
FunctionEnd
!macro InstallFiles DIR ARCH
SetOutPath "$INSTDIR"
File "..\..\${DIR}-Release\Rainmeter.exe"
File "..\..\${DIR}-Release\Rainmeter.dll"
File "..\..\${DIR}-Release\SkinInstaller.exe"
File "..\..\${DIR}-Release\SkinInstaller.dll"
SetOutPath "$INSTDIR\Plugins"
File /x *Example*.dll "..\..\${DIR}-Release\Plugins\*.dll"
SetOutPath "$INSTDIR\Runtime"
File "$%VS120COMNTOOLS%..\..\VC\redist\${ARCH}\Microsoft.VC120.CRT\msvcp120.dll"
File "$%VS120COMNTOOLS%..\..\VC\redist\${ARCH}\Microsoft.VC120.CRT\msvcr120.dll"
!macroend
!macro RemoveStartMenuShortcuts STARTMENUPATH
Delete "${STARTMENUPATH}\Rainmeter.lnk"
Delete "${STARTMENUPATH}\Rainmeter Help.lnk"
Delete "${STARTMENUPATH}\Rainmeter Help.URL"
Delete "${STARTMENUPATH}\Remove Rainmeter.lnk"
Delete "${STARTMENUPATH}\RainThemes.lnk"
Delete "${STARTMENUPATH}\RainThemes Help.lnk"
Delete "${STARTMENUPATH}\RainBrowser.lnk"
Delete "${STARTMENUPATH}\RainBackup.lnk"
Delete "${STARTMENUPATH}\Rainstaller.lnk"
Delete "${STARTMENUPATH}\Skin Installer.lnk"
Delete "${STARTMENUPATH}\Rainstaller Help.lnk"
RMDir "${STARTMENUPATH}"
!macroend
Section
SetOutPath "$PLUGINSDIR"
SetShellVarContext current
Var /GLOBAL InstArc
${If} $Install64Bit = 1
StrCpy $InstArc "x64"
${Else}
StrCpy $InstArc "x86"
${EndIf}
${If} $InstallPortable <> 1
${AndIfNot} ${AtLeastWinVista}
; Download and install .NET if required
ReadRegDWORD $0 HKLM "SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727" "Install"
${If} $0 <> 1
${If} $Install64Bit <> 1
NSISdl::download /TIMEOUT=30000 "http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe" "$PLUGINSDIR\dotnetfx.exe"
${Else}
NSISdl::download /TIMEOUT=30000 "http://download.microsoft.com/download/a/3/f/a3f1bf98-18f3-4036-9b68-8e6de530ce0a/NetFx64.exe" "$PLUGINSDIR\dotnetfx.exe"
${EndIf}
Pop $0
${If} $0 == "success"
ExecWait '"$PLUGINSDIR\dotnetfx.exe" /q:a /c:"install /q"' $0
Delete "$PLUGINSDIR\dotnetfx.exe"
${If} $0 = 3010
SetRebootFlag true
${ElseIf} $0 <> 0
MessageBox MB_OK|MB_ICONSTOP "$(DOTNETINSTERROR)"
Quit
${EndIf}
${ElseIf} $0 == "cancel"
Quit
${Else}
MessageBox MB_OK|MB_ICONSTOP "$(DOTNETINSTERROR)"
Quit
${EndIf}
${EndIf}
${EndIf}
SetOutPath "$INSTDIR"
; Close Rainmeter (and wait up to five seconds)
${ForEach} $0 10 0 - 1
FindWindow $1 "DummyRainWClass" "Rainmeter control window"
ClearErrors
Delete "$INSTDIR\Rainmeter.exe"
${If} $1 = 0
${AndIfNot} ${Errors}
${Break}
${EndIf}
SendMessage $1 ${WM_CLOSE} 0 0
${If} $0 = 0
${If} ${Silent}
SetErrorLevel ${ERROR_CLOSEFAIL}
Quit
${Else}
MessageBox MB_RETRYCANCEL|MB_ICONSTOP "$(RAINMETERCLOSEERROR)" IDRETRY +2
Quit
${EndIf}
${EndIf}
Sleep 500
${Next}
; Move Rainmeter.ini to %APPDATA% if needed
${IfNot} ${Silent}
${AndIf} ${FileExists} "$INSTDIR\Rainmeter.ini"
${If} $InstallPortable <> 1
${If} $Install64Bit = 1
${AndIf} "$INSTDIR" == "$PROGRAMFILES64\Rainmeter"
${OrIf} "$INSTDIR" == "$PROGRAMFILES\Rainmeter"
MessageBox MB_YESNO|MB_ICONEXCLAMATION "$(SETTINGSFILEERROR)" IDNO SkipIniMove
StrCpy $0 1
!insertmacro UAC_AsUser_Call Function CopyIniToAppData ${UAC_SYNCREGISTERS}
${If} $0 = 1
; Copy succeeded
Delete "$INSTDIR\Rainmeter.ini"
${Else}
MessageBox MB_OK|MB_ICONSTOP "$(SETTINGSMOVEERROR)"
${EndIf}
SkipIniMove:
${EndIf}
${Else}
ReadINIStr $0 "$INSTDIR\Rainmeter.ini" "Rainmeter" "SkinPath"
${If} $0 == "$INSTDIR\Skins\"
DeleteINIStr "$INSTDIR\Rainmeter.ini" "Rainmeter" "SkinPath"
${EndIf}
${EndIf}
${EndIf}
SetOutPath "$INSTDIR"
; Cleanup old stuff
Delete "$INSTDIR\Rainmeter.chm"
Delete "$INSTDIR\Default.ini"
Delete "$INSTDIR\Launcher.exe"
Delete "$INSTDIR\Defaults\Plugins\FileView.dll"
RMDir /r "$INSTDIR\Addons\Rainstaller"
RMDir /r "$INSTDIR\Addons\RainBackup"
${If} $InstallPortable <> 1
CreateDirectory "$INSTDIR\Defaults"
Rename "$INSTDIR\Skins" "$INSTDIR\Defaults\Skins"
Rename "$INSTDIR\Themes" "$INSTDIR\Defaults\Layouts"
Rename "$INSTDIR\Defaults\Themes" "$INSTDIR\Defaults\Layouts"
${Locate} "$INSTDIR\Defaults\Layouts" "/L=F /M=Rainmeter.thm /G=1" "RenameToRainmeterIni"
${If} ${FileExists} "$INSTDIR\Addons\Backup"
${OrIf} ${FileExists} "$INSTDIR\Plugins\Backup"
CreateDirectory "$INSTDIR\Defaults\Backup"
Rename "$INSTDIR\Addons\Backup" "$INSTDIR\Defaults\Backup\Addons"
Rename "$INSTDIR\Plugins\Backup" "$INSTDIR\Defaults\Backup\Plugins"
${EndIf}
Rename "$INSTDIR\Addons" "$INSTDIR\Defaults\Addons"
${Locate} "$INSTDIR\Plugins" "/L=F /M=*.dll /G=0" "MoveNonDefaultPlugins"
${EndIf}
!ifdef INCLUDEFILES
File "..\..\Application\Rainmeter.exe.config"
${If} $instArc == "x86"
!insertmacro InstallFiles "x32" "x86"
${Else}
!insertmacro InstallFiles "x64" "x64"
${EndIf}
RMDir /r "$INSTDIR\Languages"
SetOutPath "$INSTDIR\Languages"
File "..\..\x32-Release\Languages\*.*"
SetOutPath "$INSTDIR\Defaults\Skins"
RMDir /r "$INSTDIR\Skins\illustro"
Delete "$INSTDIR\Skins\*.txt"
File /r "..\Skins\*.*"
SetOutPath "$INSTDIR\Defaults\Layouts"
File /r "..\Layouts\*.*"
!endif
SetOutPath "$INSTDIR"
${If} $InstallPortable <> 1
ReadRegStr $0 HKLM "SOFTWARE\Rainmeter" ""
WriteRegStr HKLM "SOFTWARE\Rainmeter" "" "$INSTDIR"
WriteRegStr HKLM "SOFTWARE\Rainmeter" "Language" "$LANGUAGE"
WriteRegDWORD HKLM "SOFTWARE\Rainmeter" "NonDefault" $NonDefaultLanguage
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "DisplayName" "Rainmeter"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "DisplayIcon" "$INSTDIR\Rainmeter.exe,0"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "URLInfoAbout" "http://rainmeter.net"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "UninstallString" "$INSTDIR\uninst.exe"
!ifdef BETA
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "DisplayVersion" "${VERSION_SHORT} beta r${VERSION_REVISION}"
!else
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter" "DisplayVersion" "${VERSION_SHORT} r${VERSION_REVISION}"
!endif
; Create .rmskin association
WriteRegStr HKCR ".rmskin" "" "Rainmeter.SkinInstaller"
DeleteRegKey HKCR "Rainmeter skin" ; Old key
WriteRegStr HKCR "Rainmeter.SkinInstaller" "" "Rainmeter Skin Installer"
WriteRegStr HKCR "Rainmeter.SkinInstaller\shell" "" "open"
WriteRegStr HKCR "Rainmeter.SkinInstaller\DefaultIcon" "" "$INSTDIR\SkinInstaller.exe,0"
WriteRegStr HKCR "Rainmeter.SkinInstaller\shell\open\command" "" '"$INSTDIR\SkinInstaller.exe" %1'
WriteRegStr HKCR "Rainmeter.SkinInstaller\shell\edit" "" "Install Rainmeter skin"
WriteRegStr HKCR "Rainmeter.SkinInstaller\shell\edit\command" "" '"$INSTDIR\SkinInstaller.exe" %1'
; If .inc isn't associated, use the .ini association for it.
ReadRegStr $1 HKCR ".inc" ""
${If} $1 == ""
ReadRegStr $1 HKCR ".ini" ""
${If} $1 != ""
WriteRegStr HKCR ".inc" "" "$1"
${EndIf}
${EndIf}
; Refresh shell icons if new install
${If} $0 == ""
${RefreshShellIcons}
${EndIf}
; Remove all start menu shortcuts
SetShellVarContext all
Call RemoveStartMenuShortcuts
StrCpy $0 "$SMPROGRAMS\Rainmeter.lnk"
${If} ${FileExists} "$SMPROGRAMS\Rainmeter"
StrCpy $0 "$SMPROGRAMS\Rainmeter\Rainmeter.lnk"
${EndIf}
CreateShortcut "$0" "$INSTDIR\Rainmeter.exe" "" "$INSTDIR\Rainmeter.exe" 0
${If} $AutoStartup = 1
${If} ${FileExists} "$SMSTARTUP\Rainmeter.lnk"
; Remove user shortcut to prevent duplicate with all users shortcut
!insertmacro UAC_AsUser_Call Function RemoveUserStartupShortcut ${UAC_SYNCREGISTERS}
${Else}
!insertmacro UAC_AsUser_Call Function CreateUserStartupShortcut ${UAC_SYNCREGISTERS}
${EndIf}
${EndIf}
SetShellVarContext current
Call RemoveStartMenuShortcuts
!insertmacro UAC_AsUser_Call Function RemoveStartMenuShortcuts ${UAC_SYNCREGISTERS}
WriteUninstaller "$INSTDIR\uninst.exe"
${Else}
${IfNot} ${FileExists} "Rainmeter.ini"
CopyFiles /SILENT "$INSTDIR\Defaults\Layouts\illustro default\Rainmeter.ini" "$INSTDIR\Rainmeter.ini"
${EndIf}
WriteINIStr "$INSTDIR\Rainmeter.ini" "Rainmeter" "Language" "$LANGUAGE"
${EndIf}
SectionEnd
Function CopyIniToAppData
ClearErrors
CreateDirectory "$APPDATA\Rainmeter"
CopyFiles /SILENT "$INSTDIR\Rainmeter.ini" "$APPDATA\Rainmeter\Rainmeter.ini"
${If} ${Errors}
StrCpy $0 0
${EndIf}
FunctionEnd
Function RenameToRainmeterIni
${If} ${FileExists} "$R8\Rainmeter.ini"
Delete "$R8\Rainmeter.thm"
${Else}
Rename "$R9" "$R8\Rainmeter.ini"
${EndIf}
Push $0
FunctionEnd
Function MoveNonDefaultPlugins
${If} $R7 != "AdvancedCPU.dll"
${AndIf} $R7 != "CoreTemp.dll"
${AndIf} $R7 != "FileView.dll"
${AndIf} $R7 != "FolderInfo.dll"
${AndIf} $R7 != "InputText.dll"
${AndIf} $R7 != "iTunesPlugin.dll"
${AndIf} $R7 != "MediaKey.dll"
${AndIf} $R7 != "NowPlaying.dll"
${AndIf} $R7 != "PerfMon.dll"
${AndIf} $R7 != "PingPlugin.dll"
${AndIf} $R7 != "PowerPlugin.dll"
${AndIf} $R7 != "Process.dll"
${AndIf} $R7 != "QuotePlugin.dll"
${AndIf} $R7 != "RecycleManager.dll"
${AndIf} $R7 != "ResMon.dll"
${AndIf} $R7 != "SpeedFanPlugin.dll"
${AndIf} $R7 != "SysInfo.dll"
${AndIf} $R7 != "VirtualDesktops.dll"
${AndIf} $R7 != "WebParser.dll"
${AndIf} $R7 != "WifiStatus.dll"
${AndIf} $R7 != "Win7AudioPlugin.dll"
${AndIf} $R7 != "WindowMessagePlugin.dll"
CreateDirectory "$INSTDIR\Defaults\Plugins"
Delete "$INSTDIR\Defaults\Plugins\$R7"
Rename "$R9" "$INSTDIR\Defaults\Plugins\$R7"
${EndIf}
Push $0
FunctionEnd
Function RemoveStartMenuShortcuts
!insertmacro RemoveStartMenuShortcuts "$SMPROGRAMS\Rainmeter"
FunctionEnd
Function CreateUserStartupShortcut
SetShellVarContext current
CreateShortcut "$SMSTARTUP\Rainmeter.lnk" "$INSTDIR\Rainmeter.exe" "" "$INSTDIR\Rainmeter.exe" 0
FunctionEnd
Function RemoveUserStartupShortcut
SetShellVarContext current
Delete "$SMSTARTUP\Rainmeter.lnk"
FunctionEnd
Function FinishRun
!insertmacro UAC_AsUser_ExecShell "" "$INSTDIR\Rainmeter.exe" "" "" ""
FunctionEnd
; Uninstall
; --------------------------------------
Function un.onInit
UAC_TryAgain:
; Request administrative rights
!insertmacro UAC_RunElevated
${Switch} $0
${Case} 0
${IfThen} $1 = 1 ${|} Quit ${|}
${IfThen} $3 <> 0 ${|} ${Break} ${|}
${If} $1 = 3
MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(ADMINERROR)" /SD IDNO IDOK UAC_TryAgain IDNO 0
${EndIf}
${Case} 1223
Quit
${Case} 1062
MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(LOGONERROR)"
Quit
${Default}
MessageBox MB_OK|MB_ICONSTOP|MB_TOPMOST|MB_SETFOREGROUND "$(UACERROR) ($0)"
Quit
${EndSwitch}
ReadRegStr $0 HKLM "SOFTWARE\Rainmeter" "Language"
${If} $0 != ""
StrCpy $LANGUAGE $0
${EndIf}
FunctionEnd
Function un.PageOptions
!insertmacro MUI_HEADER_TEXT "$(UNSTALLOPTIONS)" "$(UNSTALLOPTIONSDESC)"
nsDialogs::Create 1018
nsDialogs::SetRTL $(^RTL)
${NSD_CreateCheckbox} 0 0u 95% 12u "$(UNSTALLRAINMETER)"
Pop $0
EnableWindow $0 0
${NSD_Check} $0
${NSD_CreateCheckbox} 0 15u 70% 12u "$(UNSTALLSETTINGS)"
Pop $R0
${NSD_CreateLabel} 16 26u 95% 12u "$(UNSTALLSETTINGSDESC)"
nsDialogs::Show
FunctionEnd
Function un.GetOptions
${NSD_GetState} $R0 $un.DeleteAll
FunctionEnd
Section Uninstall
; Close Rainmeter (and wait up to five seconds)
${ForEach} $0 10 0 - 1
FindWindow $1 "DummyRainWClass" "Rainmeter control window"
ClearErrors
Delete "$INSTDIR\Rainmeter.exe"
${If} $1 = 0
${AndIfNot} ${Errors}
${Break}
${EndIf}
SendMessage $1 ${WM_CLOSE} 0 0
${If} $0 = 0
${If} ${Silent}
SetErrorLevel ${ERROR_CLOSEFAIL}
Quit
${Else}
MessageBox MB_RETRYCANCEL|MB_ICONSTOP "$(RAINMETERCLOSEERROR)" IDRETRY +2
Quit
${EndIf}
${EndIf}
Sleep 500
${Next}
; Old stuff
RMDir /r "$INSTDIR\Addons"
RMDir /r "$INSTDIR\Fonts"
RMDir /r "$INSTDIR\Defaults"
RMDir /r "$INSTDIR\Languages"
RMDir /r "$INSTDIR\Plugins"
RMDir /r "$INSTDIR\Runtime"
RMDir /r "$INSTDIR\Skins"
Delete "$INSTDIR\Rainmeter.dll"
Delete "$INSTDIR\Rainmeter.exe"
Delete "$INSTDIR\Rainmeter.exe.config"
Delete "$INSTDIR\SkinInstaller.exe"
Delete "$INSTDIR\SkinInstaller.dll"
Delete "$INSTDIR\uninst.exe"
RMDir "$INSTDIR"
SetShellVarContext all
RMDir /r "$APPDATA\Rainstaller"
SetShellVarContext current
Call un.RemoveShortcuts
${If} $un.DeleteAll = 1
RMDir /r "$APPDATA\Rainmeter"
RMDir /r "$DOCUMENTS\Rainmeter\Skins"
RMDir "$DOCUMENTS\Rainmeter"
RMDir /r "$1\Rainmeter"
${EndIf}
!insertmacro UAC_AsUser_Call Function un.RemoveShortcuts ${UAC_SYNCREGISTERS}
${If} $un.DeleteAll = 1
RMDir /r "$APPDATA\Rainmeter"
RMDir /r "$DOCUMENTS\Rainmeter\Skins"
RMDir "$DOCUMENTS\Rainmeter"
${EndIf}
SetShellVarContext all
Call un.RemoveShortcuts
Delete "$SMPROGRAMS\Rainmeter.lnk"
DeleteRegKey HKLM "SOFTWARE\Rainmeter"
DeleteRegKey HKCR ".rmskin"
DeleteRegKey HKCR "Rainmeter.SkinInstaller"
DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Rainmeter"
${RefreshShellIcons}
SectionEnd
Function un.RemoveShortcuts
!insertmacro RemoveStartMenuShortcuts "$SMPROGRAMS\Rainmeter"
Delete "$SMSTARTUP\Rainmeter.lnk"
Delete "$DESKTOP\Rainmeter.lnk"
FunctionEnd

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,200 +0,0 @@
!ifndef UAC_HDR__INC
!verbose push
!verbose 3
!ifndef UAC_VERBOSE
!define UAC_VERBOSE 3
!endif
!verbose ${UAC_VERBOSE}
!define UAC_HDR__INC 0x00020204 ;MMmmbbrr
!include LogicLib.nsh
!macro _UAC_definemath def val1 op val2
!define /math _UAC_definemath "${val1}" ${op} ${val2}
!ifdef ${def}
!undef ${def}
!endif
!define ${def} "${_UAC_definemath}"
!undef _UAC_definemath
!macroend
!macro _UAC_ParseDefineFlags_orin parse outflags
!searchparse /noerrors ${${parse}} "" _UAC_ParseDefineFlags_orin_f1 "|" _UAC_ParseDefineFlags_orin_f2
!define _UAC_ParseDefineFlags_orin_this ${_UAC_ParseDefineFlags_orin_f1}
!undef ${parse}
!define ${parse} ${_UAC_ParseDefineFlags_orin_f2}
!define _UAC_ParseDefineFlags_orin_saveout ${${outflags}}
!undef ${outflags}
!define /math ${outflags} "${_UAC_ParseDefineFlags_orin_saveout}" | "${_UAC_ParseDefineFlags_orin_this}"
!undef _UAC_ParseDefineFlags_orin_saveout
!undef _UAC_ParseDefineFlags_orin_this
!ifdef _UAC_ParseDefineFlags_orin_f1
!undef _UAC_ParseDefineFlags_orin_f1
!undef _UAC_ParseDefineFlags_orin_f2
!endif
!macroend
!macro _UAC_ParseDefineFlags_Begin _outdef _in
!define _UAC_PDF${_outdef}_parse "${_in}"
!define _UAC_PDF${_outdef}_flags ""
!define _UAC_PDF${_outdef}_r 0
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x1
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x2
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x4
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x8
!insertmacro _UAC_ParseDefineFlags_orin _UAC_PDF${_outdef}_parse _UAC_PDF${_outdef}_flags ;0x10
!macroend
!macro _UAC_ParseDefineFlags_End _outdef
!define ${_outdef} ${_UAC_PDF${_outdef}_r}
!undef _UAC_PDF${_outdef}_r
!undef _UAC_PDF${_outdef}_flags
!undef _UAC_PDF${_outdef}_parse
!macroend
!macro _UAC_ParseDefineFlags_IncludeFlag _outdef flag
!if ${_UAC_PDF${_outdef}_flags} & ${flag}
!insertmacro _UAC_definemath _UAC_PDF${_outdef}_r ${_UAC_PDF${_outdef}_r} | ${flag}
!endif
!macroend
!macro _UAC_ParseDefineFlagsToInt _outdef _in
!insertmacro _UAC_ParseDefineFlags_Begin _UAC_ParseDefineFlagsToInt_tmp "${_in}"
!define ${_outdef} ${_UAC_PDF_UAC_ParseDefineFlagsToInt_tmp_flags}
!insertmacro _UAC_ParseDefineFlags_End _UAC_ParseDefineFlagsToInt_tmp
!undef _UAC_ParseDefineFlagsToInt_tmp
!macroend
!macro _UAC_IncL
!insertmacro _UAC_definemath __UAC_L "${__UAC_L}" + 1
!macroend
!macro _UAC_MakeLL_Cmp cmpop cmp pluginparams
!insertmacro _LOGICLIB_TEMP
UAC::_ ${pluginparams}
pop $_LOGICLIB_TEMP
!insertmacro ${cmpop} $_LOGICLIB_TEMP ${cmp} `${_t}` `${_f}`
!macroend
!macro UAC_RunElevated
UAC::_ 0
!macroend
!macro UAC_PageElevation_RunElevated
UAC::_ 0
!macroend
/*!macro UAC_OnInitElevation_RunElevated
UAC::_ 0
!macroend
!macro UAC_OnInitElevation_OnGuiInit
!macroend*/
!macro UAC_IsAdmin
UAC::_ 2
!macroend
!define UAC_IsAdmin `"" UAC_IsAdmin ""`
!macro _UAC_IsAdmin _a _b _t _f
!insertmacro _UAC_MakeLL_Cmp _!= 0 2s
!macroend
!macro UAC_IsInnerInstance
UAC::_ 3
!macroend
!define UAC_IsInnerInstance `"" UAC_IsInnerInstance ""`
!macro _UAC_IsInnerInstance _a _b _t _f
!insertmacro _UAC_MakeLL_Cmp _!= 0 3s
!macroend
!macro UAC_Notify_OnGuiInit
UAC::_ 4
!macroend
!macro UAC_PageElevation_OnGuiInit
!insertmacro UAC_Notify_OnGuiInit
!macroend
!macro UAC_PageElevation_OnInit
UAC::_ 5
${IfThen} ${Errors} ${|} Quit ${|}
!macroend
!define UAC_SYNCREGISTERS 0x1
#!define UAC_SYNCSTACK 0x2
!define UAC_SYNCOUTDIR 0x4
!define UAC_SYNCINSTDIR 0x8
#!define UAC_CLEARERRFLAG 0x10
!macro UAC_AsUser_Call type name flags
push $0
Get${type}Address $0 ${name}
!verbose push
!verbose ${UAC_VERBOSE}
!insertmacro _UAC_ParseDefineFlagsToInt _UAC_AsUser_Call__flags ${flags}
!verbose pop
StrCpy $0 "1$0:${_UAC_AsUser_Call__flags}"
!undef _UAC_AsUser_Call__flags
Exch $0
UAC::_
!macroend
!macro _UAC_AsUser_GenOp outvar op opparam1 opparam2
!define _UAC_AUGOGR_ID _UAC_AUGOGR_OP${outvar}${op}${opparam1}${opparam2}
!ifndef ${_UAC_AUGOGR_ID} ;Has this exact action been done before?
!if ${outvar} == $0
!define ${_UAC_AUGOGR_ID} $1
!else
!define ${_UAC_AUGOGR_ID} $0
!endif
!if "${opparam1}" == ""
!define _UAC_AUGOGR_OPP1 ${${_UAC_AUGOGR_ID}}
!define _UAC_AUGOGR_OPP2 ${opparam2}
!else
!define _UAC_AUGOGR_OPP1 ${opparam1}
!define _UAC_AUGOGR_OPP2 ${${_UAC_AUGOGR_ID}}
!endif
goto ${_UAC_AUGOGR_ID}_C
${_UAC_AUGOGR_ID}_F:
${op} ${_UAC_AUGOGR_OPP1} ${_UAC_AUGOGR_OPP2}
return
${_UAC_AUGOGR_ID}_C:
!undef _UAC_AUGOGR_OPP1
!undef _UAC_AUGOGR_OPP2
!endif
push ${${_UAC_AUGOGR_ID}}
!insertmacro UAC_AsUser_Call Label ${_UAC_AUGOGR_ID}_F ${UAC_SYNCREGISTERS}
StrCpy ${outvar} ${${_UAC_AUGOGR_ID}}
pop ${${_UAC_AUGOGR_ID}}
!undef _UAC_AUGOGR_ID
!macroend
!macro UAC_AsUser_GetSection datatype secidx outvar
!insertmacro _UAC_AsUser_GenOp ${outvar} SectionGet${datatype} ${secidx} ""
!macroend
!macro UAC_AsUser_GetGlobalVar var
!insertmacro _UAC_AsUser_GenOp ${var} StrCpy "" ${var}
!macroend
!macro UAC_AsUser_GetGlobal outvar srcvar
!insertmacro _UAC_AsUser_GenOp ${outvar} StrCpy "" ${srcvar}
!macroend
!macro UAC_AsUser_ExecShell verb command params workdir show
!insertmacro _UAC_IncL
goto _UAC_L_E_${__UAC_L}
_UAC_L_F_${__UAC_L}:
ExecShell "${verb}" "${command}" ${params} ${show}
return
_UAC_L_E_${__UAC_L}:
!if "${workdir}" != ""
push $outdir
SetOutPath "${workdir}"
!endif
!insertmacro UAC_AsUser_Call Label _UAC_L_F_${__UAC_L} ${UAC_SYNCREGISTERS}|${UAC_SYNCOUTDIR}|${UAC_SYNCINSTDIR} #|${UAC_CLEARERRFLAG}
!if "${workdir}" != ""
pop $outdir
SetOutPath $outdir
!endif
!macroend
!verbose pop
!endif /* UAC_HDR__INC */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

View File

@ -1,23 +0,0 @@
[Rainmeter]
[illustro\Clock]
Active=1
WindowX=(#SCREENAREAWIDTH#-200)
WindowY=0
[illustro\Disk]
Active=2
WindowX=(#SCREENAREAWIDTH#-200)
WindowY=176
[illustro\System]
Active=1
WindowX=(#SCREENAREAWIDTH#-200)
WindowY=68
[illustro\Welcome]
Active=1
WindowX=50.000000%
WindowY=50.000000%
AnchorX=50.000000%
AnchorY=50.000000%

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,138 +0,0 @@
; Lines starting ; (semicolons) are commented out.
; That is, they do not affect the code and are here for demonstration purposes only.
; ----------------------------------
[Rainmeter]
; This section contains general settings that can be used to change how Rainmeter behaves.
Author=poiru
AppVersion=2003000
Update=1000
Background=#@#Background.png
; #@# is equal to Rainmeter\Skins\illustro\@Resources
BackgroundMode=3
BackgroundMargins=0,34,0,14
[Metadata]
; Contains basic information of the skin.
Description=Displays the current date and time.
License=Creative Commons BY-NC-SA 3.0
Version=1.0.0
[Variables]
; Variables declared here can be used later on between two # characters (e.g. #MyVariable#).
fontName=Trebuchet MS
textSize=8
colorBar=235,170,0,255
colorText=255,255,255,205
; ----------------------------------
; MEASURES return some kind of value
; ----------------------------------
[measureTime]
; This measure returns the time in a 24-hour format (i.e. HH:MM).
Measure=Time
Format=%H:%M
; For a 12-hour clock, change the Format option above to: %I:%M %p
; Refer to the Rainmeter manual for other format codes.
[measureDate]
; Returns the date as DD.MM.YYYY
Measure=Time
Format=%d.%m.%Y
[measureDay]
; Returns the current day
Measure=Time
Format=%A
; ----------------------------------
; STYLES are used to "centralize" options
; ----------------------------------
[styleTitle]
StringAlign=CENTER
StringCase=UPPER
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,50
FontColor=#colorText#
FontFace=#fontName#
FontSize=10
AntiAlias=1
ClipString=1
[styleLeftText]
StringAlign=LEFT
; Meters using styleLeftText will be left-aligned.
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleRightText]
StringAlign=RIGHT
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleSeperator]
SolidColor=255,255,255,15
; ----------------------------------
; METERS display images, text, bars, etc.
; ----------------------------------
[meterTitle]
Meter=STRING
MeterStyle=styleTitle
; Using MeterStyle=styleTitle will basically "copy" the
; contents of the [styleTitle] section here during runtime.
MeasureName=measureTime
X=100
Y=12
W=190
H=18
Text="%1"
; %1 stands for the value of MeasureName (measureTime in this case).
[meterDay]
Meter=STRING
MeterStyle=styleLeftText
MeasureName=measureDay
X=10
Y=40
W=190
H=14
Text="%1"
[meterDate]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureDate
X=200
Y=0r
; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels
; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU).
W=190
H=14
Text="%1"
[meterSeperator]
Meter=IMAGE
MeterStyle=styleSeperator
X=10
Y=52
W=190
H=1

View File

@ -1,149 +0,0 @@
; Lines starting ; (semicolons) are commented out.
; That is, they do not affect the code and are here for demonstration purposes only.
; ----------------------------------
; NOTE! If you want to add more disks, take a look at 'Disks 2.ini'.
[Rainmeter]
; This section contains general settings that can be used to change how Rainmeter behaves.
Author=poiru
AppVersion=2003000
Update=1000
Background=#@#Background.png
; #@# is equal to Rainmeter\Skins\illustro\@Resources
BackgroundMode=3
BackgroundMargins=0,34,0,14
[Metadata]
; Contains basic information of the skin.
Description=Displays disk usage.
License=Creative Commons BY-NC-SA 3.0
Version=1.0.0
[Variables]
; Variables declared here can be used later on between two # characters (e.g. #MyVariable#).
fontName=Trebuchet MS
textSize=8
colorBar=235,170,0,255
colorText=255,255,255,205
disk1=C:
; ----------------------------------
; MEASURES return some kind of value
; ----------------------------------
[measureTotalDisk1]
; This measure returns the total disk space
Measure=FreeDiskSpace
Drive=#disk1#
Total=1
UpdateDivider=120
[measureUsedDisk1]
; Returns inverted value of free disk space (i.e. used disk space)
Measure=FreeDiskSpace
Drive=#disk1#
InvertMeasure=1
UpdateDivider=120
; ----------------------------------
; STYLES are used to "centralize" options
; ----------------------------------
[styleTitle]
StringAlign=CENTER
StringCase=UPPER
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,50
FontColor=#colorText#
FontFace=#fontName#
FontSize=10
AntiAlias=1
ClipString=1
[styleLeftText]
StringAlign=LEFT
; Meters using styleLeftText will be left-aligned.
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleRightText]
StringAlign=RIGHT
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleBar]
BarColor=#colorBar#
BarOrientation=HORIZONTAL
SolidColor=255,255,255,15
; ----------------------------------
; METERS display images, text, bars, etc.
; ----------------------------------
[meterTitle]
Meter=STRING
MeterStyle=styleTitle
; Using MeterStyle=styleTitle will basically "copy" the
; contents of the [styleTitle] section here during runtime.
X=100
Y=12
W=190
H=18
Text="Disks"
; Even though the text is set to Disks, Rainmeter will display
; it as DISKS, because styleTitle contains StringCase=UPPER.
[meterLabelDisk1]
Meter=STRING
MeterStyle=styleLeftText
X=10
Y=40
W=190
H=14
Text="#disk1#\"
[meterValueDisk1]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureUsedDisk1
MeasureName2=measureTotalDisk1
X=200
Y=0r
; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels
; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU).
W=190
H=14
Text="%1B/%2B used"
; %1 stands for the value of MeasureName (measureUsedDisk1 in this case).
; %2 stands for the value of MeasureName2.
NumOfDecimals=1
AutoScale=1
; Because disk measures return the free/used space in bytes, we must use AutoScale=1 to
; automatically scale the value into a more readable figure.
LeftMouseUpAction=!Execute ["#disk1#\"]
; Open #disk1# on click
[meterBarDisk1]
Meter=BAR
MeterStyle=styleBar
MeasureName=measureUsedDisk1
X=10
Y=52
W=190
H=1

View File

@ -1,209 +0,0 @@
; Lines starting ; (semicolons) are commented out.
; That is, they do not affect the code and are here for demonstration purposes only.
; ----------------------------------
; HOWTO: Adding more disks
; ----------------------------------
; Adding more disks is a pretty straightforward process. Follow the following steps to turn
; this 2 disks skin into a 3 disks skin. You can then extend it even further as you wish.
;
; 1) Create a new variable called disk3=X: directly below disk2=D: in the [Variables] section
; 2) Create a copy of the [measureTotalDisk2] and [measureUsedDisk2] sections
; 3) Rename the copied sections to [measureTotalDisk3] and [measureUsedDisk3], respectively.
; Also change Drive=#disk2# to Drive=#disk3#
; 4) Create a copy of the [meterLabelDisk2], [meterValueDisk2], and [meterBarDisk2].
; Rename all Disk2's in the copied sections to Disk3.
; 5) Now we need to change the Y= values to adjust height. Change Y= under [meterLabelDisk3]
; to Y=80 (calculated by adding 20 to the Y= value of previous meterLabel).
; Then change Y= under [meterBarDisk3] to Y=92 (calculated by adding 20 to the Y= value of previous meterBar).
; 6) Save the file as '3 Disks.ini'. Now right-click on the Rainmeter tray icon and select
; 'Refresh All'. Now go activate the '3 Disks.ini' skin and enjoy! :)
[Rainmeter]
; This section contains general settings that can be used to change how Rainmeter behaves.
Author=poiru
AppVersion=2003000
Update=1000
Background=#@#Background.png
; #@# is equal to Rainmeter\Skins\illustro\@Resources
BackgroundMode=3
BackgroundMargins=0,34,0,14
[Metadata]
; Contains basic information of the skin.
Description=Displays disk usage.
License=Creative Commons BY-NC-SA 3.0
Version=1.0.0
[Variables]
; Variables declared here can be used later on between two # characters (e.g. #MyVariable#).
fontName=Trebuchet MS
textSize=8
colorBar=235,170,0,255
colorText=255,255,255,205
disk1=C:
disk2=D:
; ----------------------------------
; MEASURES return some kind of value
; ----------------------------------
[measureTotalDisk1]
; This measure returns the total disk space
Measure=FreeDiskSpace
Drive=#disk1#
Total=1
UpdateDivider=120
[measureUsedDisk1]
; Returns inverted value of free disk space (i.e. used disk space)
Measure=FreeDiskSpace
Drive=#disk1#
InvertMeasure=1
UpdateDivider=120
[measureTotalDisk2]
Measure=FreeDiskSpace
Drive=#disk2#
Total=1
UpdateDivider=120
[measureUsedDisk2]
Measure=FreeDiskSpace
Drive=#disk2#
InvertMeasure=1
UpdateDivider=120
; ----------------------------------
; STYLES are used to "centralize" options
; ----------------------------------
[styleTitle]
StringAlign=CENTER
StringCase=UPPER
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,50
FontColor=#colorText#
FontFace=#fontName#
FontSize=10
AntiAlias=1
ClipString=1
[styleLeftText]
StringAlign=LEFT
; Meters using styleLeftText will be left-aligned.
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleRightText]
StringAlign=RIGHT
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleBar]
BarColor=#colorBar#
BarOrientation=HORIZONTAL
SolidColor=255,255,255,15
; ----------------------------------
; METERS display images, text, bars, etc.
; ----------------------------------
[meterTitle]
Meter=STRING
MeterStyle=styleTitle
; Using MeterStyle=styleTitle will basically "copy" the
; contents of the [styleTitle] section here during runtime.
X=100
Y=12
W=190
H=18
Text="Disk"
; Even though the text is set to Disk, Rainmeter will display
; it as DISK, because styleTitle contains StringCase=UPPER.
[meterLabelDisk1]
Meter=STRING
MeterStyle=styleLeftText
X=10
Y=40
W=190
H=14
Text="#disk1#\"
[meterValueDisk1]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureUsedDisk1
MeasureName2=measureTotalDisk1
X=200
Y=0r
; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels
; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU).
W=190
H=14
Text="%1B/%2B used"
; %1 stands for the value of MeasureName (measureUsedDisk1 in this case).
; %2 stands for the value of MeasureName2.
NumOfDecimals=1
AutoScale=1
; Because disk measures return the free/used space in bytes, we must use AutoScale=1 to
; automatically scale the value into a more readable figure.
LeftMouseUpAction=!Execute ["#disk1#\"]
; Open #disk1# on click
[meterBarDisk1]
Meter=BAR
MeterStyle=styleBar
MeasureName=measureUsedDisk1
X=10
Y=52
W=190
H=1
[meterLabelDisk2]
Meter=STRING
MeterStyle=styleLeftText
X=10
Y=60
W=190
H=14
Text="#disk2#\"
LeftMouseUpAction=!Execute ["#disk2#\"]
[meterValueDisk2]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureUsedDisk2
MeasureName2=measureTotalDisk2
X=200
Y=0r
W=190
H=14
Text="%1B/%2B used"
NumOfDecimals=1
AutoScale=1
[meterBarDisk2]
Meter=BAR
MeterStyle=styleBar
MeasureName=measureUsedDisk2
X=10
Y=72
W=190
H=1

View File

@ -1,119 +0,0 @@
; Lines starting ; (semicolons) are commented out.
; That is, they do not affect the code and are here for demonstration purposes only.
; ----------------------------------
[Rainmeter]
; This section contains general settings that can be used to change how Rainmeter behaves.
Author=poiru
AppVersion=2003000
Update=1000
Background=#@#Background.png
; #@# is equal to Rainmeter\Skins\illustro\@Resources
BackgroundMode=3
BackgroundMargins=0,34,0,14
[Metadata]
; Contains basic information of the skin.
Description=Allows searching through Google.
License=Creative Commons BY-NC-SA 3.0
Version=1.0.0
[Variables]
; Variables declared here can be used later on between two # characters (e.g. #MyVariable#).
fontName=Trebuchet MS
textSize=8
colorBar=235,170,0,255
colorText=255,255,255,205
; ----------------------------------
; MEASURES return some kind of value
; ----------------------------------
[measureInput]
; The InputText.dll plugin has special powers: it allows user input.
; However, it's not the easiest way to start learning Rainmeter. Get a
; hold of the basics, and then check out the manual entry for InputText.
Measure=Plugin
Plugin=InputText.dll
SolidColor=20,20,20,255
StringAlign=LEFT
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
X=10
Y=38
W=188
H=17
FocusDismiss=1
DefaultValue=""
Command1=!Execute ["http://www.google.com/search?q=$UserInput$"]
UpdateDivider=86400
; ----------------------------------
; STYLES are used to "centralize" options
; ----------------------------------
[styleTitle]
StringAlign=CENTER
StringCase=UPPER
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,50
FontColor=#colorText#
FontFace=#fontName#
FontSize=10
AntiAlias=1
ClipString=1
[styleLeftText]
StringAlign=LEFT
; Meters using styleLeftText will be left-aligned.
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleSeperator]
SolidColor=255,255,255,15
; ----------------------------------
; METERS display images, text, bars, etc.
; ----------------------------------
[meterTitle]
Meter=STRING
MeterStyle=styleTitle
; Using MeterStyle=styleTitle will basically "copy" the
; contents of the [styleTitle] section here during runtime.
X=100
Y=12
W=190
H=18
Text="Google"
[meterSearch]
Meter=STRING
MeterStyle=styleLeftText
X=10
Y=40
W=190
H=14
Text="Search..."
LeftMouseUpAction=!PluginBang "measureInput ExecuteBatch 1"
[meterSeperator]
Meter=IMAGE
MeterStyle=styleSeperator
X=10
Y=52
W=190
H=1

View File

@ -1,215 +0,0 @@
; Lines starting ; (semicolons) are commented out.
; That is, they do not affect the code and are here for demonstration purposes only.
; ----------------------------------
[Rainmeter]
; This section contains general settings that can be used to change how Rainmeter behaves.
Author=poiru
AppVersion=2003000
Update=1000
Background=#@#Background.png
; #@# is equal to Rainmeter\Skins\illustro\@Resources
BackgroundMode=3
BackgroundMargins=0,34,0,14
[Metadata]
; Contains basic information of the skin.
Description=Shows your IP address and network activity.
License=Creative Commons BY-NC-SA 3.0
Version=1.0.0
[Variables]
; Variables declared here can be used later on between two # characters (e.g. #MyVariable#).
fontName=Trebuchet MS
textSize=8
colorBar=235,170,0,255
colorText=255,255,255,205
maxDownload=10485760
MaxUpload=10485760
; Set maxDownload and maxUpload to your maximum download and upload speed in bits.
; To convert kilobits, megabits, kilobytes, and megabytes into bits, go to www.google.com
; and search for something like "10 megabytes in bits".
; ----------------------------------
; MEASURES return some kind of value
; ----------------------------------
[measureIP]
; This measure returns your IP. WebParser measures are relatively complicated. If you're a beginner with
; Rainmeter, take a look at some of the other illustro skins before modifying this one.
Measure=Plugin
Plugin=WebParser.dll
Url=http://checkip.dyndns.org
UpdateRate=14400
RegExp="(?siU)Address: (.*)</body>"
StringIndex=1
Substitute="":"N/A"
; Substitute works as follows: "A":"B" where A is a string to substitute and B is a string
; to substitute with. In this case, it substutes "" (i.e. empty) to N/A
[measureNetIn]
Measure=NetIn
NetInSpeed=#maxDownload#
; NetInSpeed must be set so your maximun download speed for the download bar to scale correctly
[measureNetOut]
Measure=NetOut
NetOutSpeed=#maxUpload#
; ----------------------------------
; STYLES are used to "centralize" options
; ----------------------------------
[styleTitle]
StringAlign=CENTER
StringCase=UPPER
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,50
FontColor=#colorText#
FontFace=#fontName#
FontSize=10
AntiAlias=1
ClipString=1
[styleLeftText]
StringAlign=LEFT
; Meters using styleLeftText will be left-aligned.
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleRightText]
StringAlign=RIGHT
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleBar]
BarColor=#colorBar#
BarOrientation=HORIZONTAL
SolidColor=255,255,255,15
[styleSeperator]
SolidColor=255,255,255,15
; ----------------------------------
; METERS display images, text, bars, etc.
; ----------------------------------
[meterTitle]
Meter=STRING
MeterStyle=styleTitle
; Using MeterStyle=styleTitle will basically "copy" the
; contents of the [styleTitle] section here during runtime.
X=100
Y=12
W=190
H=18
Text="Network"
; Even though the text is set to Network, Rainmeter will display
; it as NETWORK, because styleTitle contains StringCase=UPPER.
[meterIPLabel]
Meter=STRING
MeterStyle=styleLeftText
X=10
Y=40
W=190
H=14
Text="IP Address"
[meterIPValue]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureIP
X=200
Y=0r
; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels
; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU).
W=190
H=14
Text="%1"
; %1 stands for the value of MeasureName (measureIP in this case).
[meterSeperator]
Meter=IMAGE
MeterStyle=styleSeperator
X=10
Y=52
W=190
H=1
[meterUploadLabel]
Meter=STRING
MeterStyle=styleLeftText
X=10
Y=60
W=190
H=14
Text="Upload"
[meterUploadValue]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureNetOut
X=200
Y=0r
W=190
H=14
Text="%1B/s"
NumOfDecimals=1
AutoScale=1
; Because measureIP returns the current upload speed in bytes, we must use AutoScale=1 to
; automatically scale the value into a more readable figure.
[meterUploadBar]
Meter=BAR
MeterStyle=styleBar
MeasureName=measureNetOut
X=10
Y=72
W=190
H=1
[meterDownloadLabel]
Meter=STRING
MeterStyle=styleLeftText
X=10
Y=80
W=190
H=14
Text="Download"
[meterDownloadValue]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureNetIn
X=200
Y=0r
W=190
H=14
Text="%1B/s"
NumOfDecimals=1
AutoScale=1
[meterDownloadBar]
Meter=BAR
MeterStyle=styleBar
MeasureName=measureNetIn
X=10
Y=92
W=190
H=1

View File

@ -1,147 +0,0 @@
; Lines starting ; (semicolons) are commented out.
; That is, they do not affect the code and are here for demonstration purposes only.
; ----------------------------------
[Rainmeter]
; This section contains general settings that can be used to change how Rainmeter behaves.
Author=poiru
AppVersion=2003000
Update=1000
Background=#@#Background.png
; #@# is equal to Rainmeter\Skins\illustro\@Resources
BackgroundMode=3
BackgroundMargins=0,34,0,14
[Metadata]
; Contains basic information of the skin.
Description=Shows the state and size of your Recycle Bin.
License=Creative Commons BY-NC-SA 3.0
Version=1.0.0
[Variables]
; Variables declared here can be used later on between two # characters (e.g. #MyVariable#).
fontName=Trebuchet MS
textSize=8
colorBar=235,170,0,255
colorText=255,255,255,205
; ----------------------------------
; MEASURES return some kind of value
; ----------------------------------
[measureBinItems]
; This measure returns the amount of items in the Recycle Bin.
Measure=Plugin
Plugin=RecycleManager.dll
RecycleType=COUNT
UpdateDivider=3
; UpdateDivider sets the rate at which the value of the measure is updated. It is
; calculated as follows: UpdateDivider x Update. In this case, Update is set to
; 1000 milliseconds (in the [Rainmeter] section). 1000 x 3 = 3000 ms or 3 seconds.
[measureBinSize]
; Returns the total size of the Recycle Bin in bytes.
Measure=Plugin
Plugin=RecycleManager.dll
RecycleType=SIZE
UpdateDivider=3
; ----------------------------------
; STYLES are used to "centralize" options
; ----------------------------------
[styleTitle]
StringAlign=CENTER
StringCase=UPPER
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,50
FontColor=#colorText#
FontFace=#fontName#
FontSize=10
AntiAlias=1
ClipString=1
[styleLeftText]
StringAlign=LEFT
; Meters using styleLeftText will be left-aligned.
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleRightText]
StringAlign=RIGHT
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleSeperator]
SolidColor=255,255,255,15
; ----------------------------------
; METERS display images, text, bars, etc.
; ----------------------------------
[meterTitle]
Meter=STRING
MeterStyle=styleTitle
; Using MeterStyle=styleTitle will basically "copy" the
; contents of the [styleTitle] section here during runtime.
X=100
Y=12
W=190
H=18
Text="Recycle Bin"
; Even though the text is set to Recycle Bin, Rainmeter will display
; it as RECYCLE BIN, because styleTitle contains StringCase=UPPER.
LeftMouseUpAction=!Execute [!PluginBang "measureBinItems OpenBin"]
RightMouseUpAction=!Execute [!PluginBang "measureBinItems EmptyBin"]
ToolTipText="Left-click to open Recycle Bin#CRLF#Right-click to empty"
; Hovering over this meter will display a tooltip with the text above.
; The #CRLF# variable creates a new line.
[meterBinItems]
Meter=STRING
MeterStyle=styleLeftText
MeasureName=measureBinItems
X=10
Y=40
W=190
H=14
Text="%1 items"
; %1 stands for the value of MeasureName (measureBinItems in this case).
[meterBinSize]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureBinSize
X=200
Y=0r
; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels
; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU).
W=190
H=14
Text="%1B"
AutoScale=1
; Because measureBinSize returns the size in bytes, we must use AutoScale=1 to
; automatically scale the value into a more readable figure.
[meterSeperator]
Meter=IMAGE
MeterStyle=styleSeperator
X=10
Y=52
W=190
H=1

View File

@ -1,206 +0,0 @@
; Lines starting ; (semicolons) are commented out.
; That is, they do not affect the code and are here for demonstration purposes only.
; ----------------------------------
[Rainmeter]
; This section contains general settings that can be used to change how Rainmeter behaves.
Author=poiru
AppVersion=2003000
Update=1000
Background=#@#Background.png
; #@# is equal to Rainmeter\Skins\illustro\@Resources
BackgroundMode=3
BackgroundMargins=0,34,0,14
[Metadata]
; Contains basic information of the skin.
Description=Displays basic system stats.
License=Creative Commons BY-NC-SA 3.0
Version=1.0.0
[Variables]
; Variables declared here can be used later on between two # characters (e.g. #MyVariable#).
fontName=Trebuchet MS
textSize=8
colorBar=235,170,0,255
colorText=255,255,255,205
; ----------------------------------
; MEASURES return some kind of value
; ----------------------------------
[measureCPU]
; This measure returns the average CPU load between all cores.
Measure=CPU
Processor=0
[measureRAM]
; Returns the amount of RAM used in bytes.
Measure=PhysicalMemory
UpdateDivider=20
; UpdateDivider sets the rate at which the value of the measure is updated. It is
; calculated as follows: UpdateDivider x Update. In this case, Update is set to
; 1000 milliseconds (in the [Rainmeter] section). 1000 x 20 = 20000 ms or 20 seconds.
[measureSWAP]
; Returns the amount of SWAP (pagefile) used in bytes.
Measure=SWAPMemory
UpdateDivider=20
; ----------------------------------
; STYLES are used to "centralize" options
; ----------------------------------
[styleTitle]
StringAlign=CENTER
StringCase=UPPER
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,50
FontColor=#colorText#
FontFace=#fontName#
FontSize=10
AntiAlias=1
ClipString=1
[styleLeftText]
StringAlign=LEFT
; Meters using styleLeftText will be left-aligned.
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleRightText]
StringAlign=RIGHT
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleBar]
BarColor=#colorBar#
BarOrientation=HORIZONTAL
SolidColor=255,255,255,15
; ----------------------------------
; METERS display images, text, bars, etc.
; ----------------------------------
[meterTitle]
Meter=STRING
MeterStyle=styleTitle
; Using MeterStyle=styleTitle will basically "copy" the
; contents of the [styleTitle] section here during runtime.
X=100
Y=12
W=190
H=18
Text="System"
; Even though the text is set to System, Rainmeter will display
; it as SYSTEM, because styleTitle contains StringCase=UPPER.
LeftMouseUpAction=!Execute ["taskmgr.exe"]
; Left-clicking this meter will launch taskmgr.exe (the Task Manager).
ToolTipText="Open Task Manager"
; Hovering over this meter will display a tooltip with the text above.
[meterLabelCPU]
Meter=STRING
MeterStyle=styleLeftText
X=10
Y=40
W=190
H=14
Text="CPU Usage"
[meterValueCPU]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureCPU
X=200
Y=0r
; r stands for relative. In this case, the Y postition of meterValueCPU is 0 pixels
; below the Y value of the previous meter (i.e it's the same as in meterLabelCPU).
W=190
H=14
Text="%1%"
; %1 stands for the value of MeasureName (measureCPU in this case).
[meterBarCPU]
Meter=BAR
MeterStyle=styleBar
MeasureName=measureCPU
X=10
Y=52
W=190
H=1
[meterLabelRAM]
Meter=STRING
MeterStyle=styleLeftText
X=10
Y=60
W=190
H=14
Text="RAM Usage"
[meterValueRAM]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureRAM
X=200
Y=0r
W=190
H=14
Text="%1%"
Percentual=1
; Percentual=1 needs to be added her because measureRAM returns the amount
; of RAM used in bytes. Using Percentual=1 will convert that into a percentual value.
[meterBarRAM]
Meter=BAR
MeterStyle=styleBar
MeasureName=measureRAM
X=10
Y=72
W=190
H=1
[meterLabelSWAP]
Meter=STRING
MeterStyle=styleLeftText
X=10
Y=80
W=190
H=14
Text="SWAP Usage"
[meterValueSWAP]
Meter=STRING
MeterStyle=styleRightText
MeasureName=measureSWAP
X=200
Y=0r
W=190
H=14
Text="%1%"
Percentual=1
[meterBarSWAP]
Meter=BAR
MeterStyle=styleBar
MeasureName=measureSWAP
X=10
Y=92
W=190
H=1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,173 +0,0 @@
; Lines starting ; (semicolons) are commented out.
; That is, they do not affect the code and are here for demonstration purposes only.
; ----------------------------------
[Rainmeter]
; This section contains general settings that can be used to change how Rainmeter behaves.
Author=poiru
AppVersion=2003000
Update=1000
[Metadata]
; Contains basic information of the skin.
Description=The welcome skin for illustro.
License=Creative Commons BY-NC-SA 3.0
Version=1.0.0
[Variables]
; Variables declared here can be used later on between two # characters (e.g. #MyVariable#).
fontName=Trebuchet MS
textSize=9
colorBar=235,170,0,255
colorText=255,255,255,205
; ----------------------------------
; STYLES are used to "centralize" options
; ----------------------------------
[styleTitle]
StringAlign=LEFT
StringCase=UPPER
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,50
FontColor=#colorText#
FontFace=#fontName#
FontSize=10
AntiAlias=1
ClipString=1
[styleLeftText]
StringAlign=LEFT
; Meters using styleLeftText will be left-aligned.
StringCase=NONE
StringStyle=BOLD
StringEffect=SHADOW
FontEffectColor=0,0,0,20
FontColor=#colorText#
FontFace=#fontName#
FontSize=#textSize#
AntiAlias=1
ClipString=1
[styleSeperator]
SolidColor=255,255,255,15
; ----------------------------------
; METERS display images, text, bars, etc.
; ----------------------------------
[meterBackground]
Meter=IMAGE
ImageName=Background.png
X=0
Y=0
[meterMidLine]
Meter=IMAGE
SolidColor=255,255,255,80
W=1
H=200
X=245
Y=60
[meterTitle]
Meter=STRING
MeterStyle=styleTitle
; Using MeterStyle=styleTitle will basically "copy" the
; contents of the [styleTitle] section here during runtime.
X=20
Y=18
W=400
H=18
FontSize=11
Text="Welcome to Rainmeter!"
[meterIllustroTitle]
Meter=STRING
MeterStyle=styleLeftText
X=20
Y=55
W=240
H=30
FontColor=255,217,120,255
FontSize=10
Text="illustro: Getting started with Rainmeter skinning"
[meterIllustroLine]
Meter=STRING
MeterStyle=styleLeftText
X=20
Y=95
W=225
H=175
FontColor=#colorText#
FontSize=9
Text="illustro is a simple set of skins designed to show some of the capabilities of Rainmeter. It offers a good place to start learning how to edit Rainmeter to make it your own. Use the "Rainmeter 101" link on the right to learn the basics.#CRLF##CRLF#To explore installed skins and change Rainmeter settings, simply click on the Rainmeter tray icon."
; #CRLF# is a pre-defined varaible for newline.
[meterLinksTitle]
Meter=STRING
MeterStyle=styleLeftText
X=260
Y=55
W=235
H=30
FontColor=255,217,120,255
FontSize=10
Text=Recommended skin suites: Start using Rainmeter now!
[meterLinksLine]
Meter=STRING
MeterStyle=styleLeftText
X=260
Y=95
W=225
H=80
FontColor=#colorText#
FontSize=9
Text=There are literally thousands of skins available for Rainmeter. We have a few popular ones we recommend, which you can install with just a few clicks.
[meterLink1]
Meter=STRING
MeterStyle=styleLeftText
X=260
Y=175
W=225
H=14
FontColor=255,217,120,255
Text="<22> Recommended Skin Suites"
LeftMouseUpAction=!Execute ["http://rainmeter.net/cms/Discover"]
[meterLink2]
Meter=STRING
MeterStyle=styleLeftText
X=260
Y=195
W=225
H=14
FontColor=255,174,69,255
Text="<22> Rainmeter 101"
LeftMouseUpAction=!Execute ["http://rainmeter.net/cms/Rainmeter101"]
[meterLink3]
Meter=STRING
MeterStyle=styleLeftText
X=260
Y=215
W=225
H=14
FontColor=255,174,69,255
Text="<22> Rainmeter Manual"
LeftMouseUpAction=!Execute ["http://rainmeter.net/cms/Support"]
[meterLink4]
Meter=STRING
MeterStyle=styleLeftText
X=260
Y=235
W=225
H=14
FontColor=255,174,69,255
Text="<22> Rainmeter Forums"
LeftMouseUpAction=!Execute ["http://rainmeter.net/forums"]

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Visual C++ project options meant to applied before the default Microsoft property sheets. -->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="UserMacros">
<WinDDK71Dir>$(SolutionDir)..\WinDDK\7600.16385.1\</WinDDK71Dir>
</PropertyGroup>
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Configuration">
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v120_xp</PlatformToolset>
</PropertyGroup>
</Project>

View File

@ -1,129 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Visual C++ project options meant to applied after the default Microsoft property sheets. -->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- Use the Win8 SDK headers even though we are using the v120_xp toolset. -->
<IncludePath>$(VCInstallDir)include;$(VCInstallDir)atlmfc\include;$(WindowsSDK_IncludePath);</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<UseDebugLibraries>true</UseDebugLibraries>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup>
<!-- This is overridden by Build.bat during full build. -->
<RmOutDirRoot Condition=" '$(Platform)' == 'Win32' ">$(SolutionDir)x32-$(Configuration)\</RmOutDirRoot>
<RmOutDirRoot Condition=" '$(Platform)' == 'x64' ">$(SolutionDir)x64-$(Configuration)\</RmOutDirRoot>
<OutDir>$(RmOutDirRoot)</OutDir>
<IntDir>$(OutDir)\Obj\$(ProjectName)\</IntDir>
</PropertyGroup>
<PropertyGroup>
<!-- Avoid .lib files in TestBench. -->
<OutDir Condition="'$(ConfigurationType)'=='StaticLibrary'">$(IntDir)</OutDir>
</PropertyGroup>
<!-- Macros for unit testing. -->
<PropertyGroup Label="UserMacros">
<!-- This is set to true by Build.bat when building full builds. -->
<ExcludeTests>false</ExcludeTests>
<!-- Non-static projects must delayload CppUnitTestFramework.dll to avoid the "module not found"
errors (since CppUnitTestFramework.dll is available only when running tests). -->
<DelayLoadTestDLL>Microsoft.VisualStudio.TestTools.CppUnitTestFramework.dll</DelayLoadTestDLL>
<DelayLoadTestDLL Condition="'$(Platform)'=='x64'">Microsoft.VisualStudio.TestTools.CppUnitTestFramework.x64.dll</DelayLoadTestDLL>
<DelayLoadTestDLL Condition="'$(ConfigurationType)'=='StaticLibrary'"></DelayLoadTestDLL>
<DelayLoadTestDLL Condition="'$(ExcludeTests)'=='true'"></DelayLoadTestDLL>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(ExcludeTests)'=='false'">
<ClCompile>
<AdditionalIncludeDirectories>$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<!-- Ignore C4351 to get rid of "new behavior: elements of array 'array' will be default initialized" -->
<DisableSpecificWarnings>4351;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ExceptionHandling>false</ExceptionHandling>
<!-- Set WINVER=0x0601 and friends (Win7) to avoid using Win8 specific features in the Win8 SDK. -->
<!-- Set _HAS_EXCEPTIONS=0 to accompany the disabled exception handling above. -->
<PreprocessorDefinitions>WIN32;_WINDOWS;WINVER=0x0601;_WIN32_WINNT=0x0601;_WIN32_IE=0x0601;PSAPI_VERSION=1;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
<ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
</Link>
<ResourceCompile>
<Culture>0x0409</Culture>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WholeProgramOptimization>true</WholeProgramOptimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<AdditionalOptions>/Gw %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<MergeSections>.rdata=.text</MergeSections>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<ClCompile>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
<ResourceCompile>
<PreprocessorDefinitions>_WIN64;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Link>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
</Project>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<GenerateManifest>false</GenerateManifest>
<OutDir>$(OutDir)Plugins\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
<Link>
<AdditionalDependencies>$(SolutionDir)Plugins\API\x32\Rainmeter.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
<Link>
<AdditionalDependencies>$(SolutionDir)Plugins\API\x64\Rainmeter.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
</Project>

View File

@ -1,9 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- This is overridden by Build.bat during full build. -->
<RmOutDirRoot Condition=" '$(Platform)' == 'x86' ">$(SolutionDir)x32-$(Configuration)\</RmOutDirRoot>
<RmOutDirRoot Condition=" '$(Platform)' == 'x64' ">$(SolutionDir)x64-$(Configuration)\</RmOutDirRoot>
<OutputPath>$(RmOutDirRoot)Plugins\</OutputPath>
</PropertyGroup>
</Project>

View File

@ -1,85 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{19312085-AA51-4BD6-BE92-4B6098CCA539}</ProjectGuid>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup>
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Lib>
<LinkTimeCodeGeneration Condition="'$(Configuration)'=='Release'">true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ControlTemplate.cpp" />
<ClCompile Include="Dialog.cpp" />
<ClCompile Include="Gfx\Canvas.cpp" />
<ClCompile Include="Gfx\CanvasD2D.cpp" />
<ClCompile Include="Gfx\CanvasGDIP.cpp" />
<ClCompile Include="Gfx\FontCollection.cpp" />
<ClCompile Include="Gfx\FontCollectionD2D.cpp" />
<ClCompile Include="Gfx\FontCollectionGDIP.cpp" />
<ClCompile Include="Gfx\TextFormat.cpp" />
<ClCompile Include="Gfx\TextFormatD2D.cpp" />
<ClCompile Include="Gfx\TextFormatGDIP.cpp" />
<ClCompile Include="Gfx\Util\DWriteFontCollectionLoader.cpp" />
<ClCompile Include="Gfx\Util\DWriteFontFileEnumerator.cpp" />
<ClCompile Include="Gfx\Util\DWriteHelpers.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapDIB.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapLockDIB.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapLockGDIP.cpp" />
<ClCompile Include="MathParser.cpp" />
<ClCompile Include="MenuTemplate.cpp" />
<ClCompile Include="PathUtil.cpp" />
<ClCompile Include="Platform.cpp" />
<ClCompile Include="StdAfx.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="StringUtil.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ControlTemplate.h" />
<ClInclude Include="Dialog.h" />
<ClInclude Include="Gfx\Canvas.h" />
<ClInclude Include="Gfx\CanvasD2D.h" />
<ClInclude Include="Gfx\CanvasGDIP.h" />
<ClInclude Include="Gfx\FontCollection.h" />
<ClInclude Include="Gfx\FontCollectionD2D.h" />
<ClInclude Include="Gfx\FontCollectionGDIP.h" />
<ClInclude Include="Gfx\TextFormat.h" />
<ClInclude Include="Gfx\TextFormatD2D.h" />
<ClInclude Include="Gfx\TextFormatGDIP.h" />
<ClInclude Include="Gfx\Util\DWriteFontCollectionLoader.h" />
<ClInclude Include="Gfx\Util\DWriteFontFileEnumerator.h" />
<ClInclude Include="Gfx\Util\DWriteHelpers.h" />
<ClInclude Include="Gfx\Util\WICBitmapDIB.h" />
<ClInclude Include="Gfx\Util\WICBitmapLockDIB.h" />
<ClInclude Include="Gfx\Util\WICBitmapLockGDIP.h" />
<ClInclude Include="MathParser.h" />
<ClInclude Include="MenuTemplate.h" />
<ClInclude Include="PathUtil.h" />
<ClInclude Include="Platform.h" />
<ClInclude Include="RawString.h" />
<ClInclude Include="StdAfx.h" />
<ClInclude Include="StringUtil.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UnitTest.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{19312085-AA51-4BD6-BE92-4B6098CCA539}</ProjectGuid>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup>
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>.\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>Use</PrecompiledHeader>
</ClCompile>
<Lib>
<LinkTimeCodeGeneration Condition="'$(Configuration)'=='Release'">true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ControlTemplate.cpp" />
<ClCompile Include="Dialog.cpp" />
<ClCompile Include="Gfx\Canvas.cpp" />
<ClCompile Include="Gfx\CanvasD2D.cpp" />
<ClCompile Include="Gfx\CanvasGDIP.cpp" />
<ClCompile Include="Gfx\FontCollection.cpp" />
<ClCompile Include="Gfx\FontCollectionD2D.cpp" />
<ClCompile Include="Gfx\FontCollectionGDIP.cpp" />
<ClCompile Include="Gfx\TextFormat.cpp" />
<ClCompile Include="Gfx\TextFormatD2D.cpp" />
<ClCompile Include="Gfx\TextFormatGDIP.cpp" />
<ClCompile Include="Gfx\Util\DWriteFontCollectionLoader.cpp" />
<ClCompile Include="Gfx\Util\DWriteFontFileEnumerator.cpp" />
<ClCompile Include="Gfx\Util\DWriteHelpers.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapDIB.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapLockDIB.cpp" />
<ClCompile Include="Gfx\Util\WICBitmapLockGDIP.cpp" />
<ClCompile Include="MathParser.cpp" />
<ClCompile Include="MenuTemplate.cpp" />
<ClCompile Include="PathUtil.cpp" />
<ClCompile Include="Platform.cpp" />
<ClCompile Include="StdAfx.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="StringUtil.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ControlTemplate.h" />
<ClInclude Include="Dialog.h" />
<ClInclude Include="Gfx\Canvas.h" />
<ClInclude Include="Gfx\CanvasD2D.h" />
<ClInclude Include="Gfx\CanvasGDIP.h" />
<ClInclude Include="Gfx\FontCollection.h" />
<ClInclude Include="Gfx\FontCollectionD2D.h" />
<ClInclude Include="Gfx\FontCollectionGDIP.h" />
<ClInclude Include="Gfx\TextFormat.h" />
<ClInclude Include="Gfx\TextFormatD2D.h" />
<ClInclude Include="Gfx\TextFormatGDIP.h" />
<ClInclude Include="Gfx\Util\DWriteFontCollectionLoader.h" />
<ClInclude Include="Gfx\Util\DWriteFontFileEnumerator.h" />
<ClInclude Include="Gfx\Util\DWriteHelpers.h" />
<ClInclude Include="Gfx\Util\WICBitmapDIB.h" />
<ClInclude Include="Gfx\Util\WICBitmapLockDIB.h" />
<ClInclude Include="Gfx\Util\WICBitmapLockGDIP.h" />
<ClInclude Include="MathParser.h" />
<ClInclude Include="MenuTemplate.h" />
<ClInclude Include="PathUtil.h" />
<ClInclude Include="Platform.h" />
<ClInclude Include="RawString.h" />
<ClInclude Include="StdAfx.h" />
<ClInclude Include="StringUtil.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UnitTest.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,124 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="Dialog.cpp" />
<ClCompile Include="MenuTemplate.cpp" />
<ClCompile Include="PathUtil.cpp" />
<ClCompile Include="Platform.cpp" />
<ClCompile Include="StringUtil.cpp" />
<ClCompile Include="ControlTemplate.cpp" />
<ClCompile Include="MathParser.cpp" />
<ClCompile Include="Gfx\Canvas.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\CanvasD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\CanvasGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollection.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollectionD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollectionGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormat.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormatD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormatGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteHelpers.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteFontCollectionLoader.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteFontFileEnumerator.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapDIB.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapLockDIB.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapLockGDIP.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="StdAfx.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Dialog.h" />
<ClInclude Include="MenuTemplate.h" />
<ClInclude Include="PathUtil.h" />
<ClInclude Include="Platform.h" />
<ClInclude Include="RawString.h" />
<ClInclude Include="StringUtil.h" />
<ClInclude Include="ControlTemplate.h" />
<ClInclude Include="MathParser.h" />
<ClInclude Include="UnitTest.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="Gfx\Canvas.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\CanvasD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\CanvasGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollection.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollectionD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollectionGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormat.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormatD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormatGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteHelpers.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteFontCollectionLoader.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteFontFileEnumerator.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapDIB.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapLockDIB.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapLockGDIP.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="StdAfx.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="Gfx">
<UniqueIdentifier>{263d9d8c-b463-4f2a-87ab-5f6575a4cc38}</UniqueIdentifier>
</Filter>
<Filter Include="Gfx\Util">
<UniqueIdentifier>{c3efb431-e0f5-4085-9b07-33a7e34c4baa}</UniqueIdentifier>
</Filter>
</ItemGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="Dialog.cpp" />
<ClCompile Include="MenuTemplate.cpp" />
<ClCompile Include="PathUtil.cpp" />
<ClCompile Include="Platform.cpp" />
<ClCompile Include="StringUtil.cpp" />
<ClCompile Include="ControlTemplate.cpp" />
<ClCompile Include="MathParser.cpp" />
<ClCompile Include="Gfx\Canvas.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\CanvasD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\CanvasGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollection.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollectionD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\FontCollectionGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormat.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormatD2D.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\TextFormatGDIP.cpp">
<Filter>Gfx</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteHelpers.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteFontCollectionLoader.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\DWriteFontFileEnumerator.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapDIB.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapLockDIB.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="Gfx\Util\WICBitmapLockGDIP.cpp">
<Filter>Gfx\Util</Filter>
</ClCompile>
<ClCompile Include="StdAfx.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Dialog.h" />
<ClInclude Include="MenuTemplate.h" />
<ClInclude Include="PathUtil.h" />
<ClInclude Include="Platform.h" />
<ClInclude Include="RawString.h" />
<ClInclude Include="StringUtil.h" />
<ClInclude Include="ControlTemplate.h" />
<ClInclude Include="MathParser.h" />
<ClInclude Include="UnitTest.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="Gfx\Canvas.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\CanvasD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\CanvasGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollection.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollectionD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\FontCollectionGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormat.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormatD2D.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\TextFormatGDIP.h">
<Filter>Gfx</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteHelpers.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteFontCollectionLoader.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\DWriteFontFileEnumerator.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapDIB.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapLockDIB.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="Gfx\Util\WICBitmapLockGDIP.h">
<Filter>Gfx\Util</Filter>
</ClInclude>
<ClInclude Include="StdAfx.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="Gfx">
<UniqueIdentifier>{263d9d8c-b463-4f2a-87ab-5f6575a4cc38}</UniqueIdentifier>
</Filter>
<Filter Include="Gfx\Util">
<UniqueIdentifier>{c3efb431-e0f5-4085-9b07-33a7e34c4baa}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>

View File

@ -1,33 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{442084A6-2069-4927-B0C9-51525A720CB2}</ProjectGuid>
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" />
<PropertyGroup>
<OutDir>$(IntDir)</OutDir>
</PropertyGroup>
<ItemGroup>
<ClCompile Include="MathParser_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="PathUtil_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="StringUtil_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="Common.vcxproj">
<Project>{19312085-aa51-4bd6-be92-4b6098cca539}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{442084A6-2069-4927-B0C9-51525A720CB2}</ProjectGuid>
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.props" />
<PropertyGroup>
<OutDir>$(IntDir)</OutDir>
</PropertyGroup>
<ItemGroup>
<ClCompile Include="MathParser_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="PathUtil_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="StringUtil_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="Common.vcxproj">
<Project>{19312085-aa51-4bd6-be92-4b6098cca539}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="PathUtil_Test.cpp" />
<ClCompile Include="StringUtil_Test.cpp" />
<ClCompile Include="MathParser_Test.cpp" />
</ItemGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="PathUtil_Test.cpp" />
<ClCompile Include="StringUtil_Test.cpp" />
<ClCompile Include="MathParser_Test.cpp" />
</ItemGroup>
</Project>

View File

@ -1,50 +1,50 @@
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "ControlTemplate.h"
namespace ControlTemplate
{
void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString)
{
for (UINT i = 0; i < ctCount; ++i)
{
const Control& ct = cts[i];
WCHAR* text = ct.textId ? getString(ct.textId) : nullptr;
RECT r = { ct.x, ct.y, ct.w, ct.h };
MapDialogRect(parent, &r);
HWND wnd = CreateWindowEx(
ct.exStyle,
ct.name,
text,
ct.style,
r.left, r.top, r.right, r.bottom,
parent,
(HMENU)ct.id,
nullptr,
nullptr);
SendMessage(wnd, WM_SETFONT, (WPARAM)font, FALSE);
}
}
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "ControlTemplate.h"
namespace ControlTemplate
{
void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString)
{
for (UINT i = 0; i < ctCount; ++i)
{
const Control& ct = cts[i];
WCHAR* text = ct.textId ? getString(ct.textId) : nullptr;
RECT r = { ct.x, ct.y, ct.w, ct.h };
MapDialogRect(parent, &r);
HWND wnd = CreateWindowEx(
ct.exStyle,
ct.name,
text,
ct.style,
r.left, r.top, r.right, r.bottom,
parent,
(HMENU)ct.id,
nullptr,
nullptr);
SendMessage(wnd, WM_SETFONT, (WPARAM)font, FALSE);
}
}
} // namespace ControlTemplate

View File

@ -1,89 +1,89 @@
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_CONTROLTEMPLATE_H_
#define RM_COMMON_CONTROLTEMPLATE_H_
#include <Windows.h>
namespace ControlTemplate
{
struct Control
{
const WCHAR* name;
WORD id;
WORD textId;
short x;
short y;
short w;
short h;
DWORD style;
DWORD exStyle;
};
typedef WCHAR* (*GetStringFunc)(UINT id);
void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString);
// Helpers to declare control structs.
#define CT_ITEM(name, id, textId, x, y, w, h, style, exStyle) \
{ name, id, textId, x, y, w, h, WS_CHILD | style, exStyle }
#define CT_BUTTON(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_PUSHBUTTON | style, exStyle)
#define CT_CHECKBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_AUTOCHECKBOX | style, exStyle)
#define CT_COMBOBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"ComboBox", id, textId, x, y, w, h, style, exStyle)
#define CT_EDIT(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Edit", id, textId, x, y, w, h, ES_LEFT | style, exStyle)
#define CT_GROUPBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_GROUPBOX | style, exStyle)
#define CT_ICON(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ICON | style, exStyle)
#define CT_LABEL(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_LEFT | style, exStyle)
#define CT_LINEH(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ETCHEDHORZ | style, exStyle)
#define CT_LINKLABEL(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysLink", id, textId, x, y, w, h, style, exStyle)
#define CT_LISTBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"ListBox", id, textId, x, y, w, h, style, exStyle)
#define CT_LISTVIEW(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysListView32", id, textId, x, y, w, h, style, exStyle)
#define CT_TAB(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysTabControl32", id, textId, x, y, w, h, TCS_TABS | style, exStyle)
#define CT_TREEVIEW(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysTreeView32", id, textId, x, y, w, h, style, exStyle)
} // namespace ControlTemplate
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_CONTROLTEMPLATE_H_
#define RM_COMMON_CONTROLTEMPLATE_H_
#include <Windows.h>
namespace ControlTemplate
{
struct Control
{
const WCHAR* name;
WORD id;
WORD textId;
short x;
short y;
short w;
short h;
DWORD style;
DWORD exStyle;
};
typedef WCHAR* (*GetStringFunc)(UINT id);
void CreateControls(const Control* cts, UINT ctCount, HWND parent, HFONT font, GetStringFunc getString);
// Helpers to declare control structs.
#define CT_ITEM(name, id, textId, x, y, w, h, style, exStyle) \
{ name, id, textId, x, y, w, h, WS_CHILD | style, exStyle }
#define CT_BUTTON(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_PUSHBUTTON | style, exStyle)
#define CT_CHECKBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_AUTOCHECKBOX | style, exStyle)
#define CT_COMBOBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"ComboBox", id, textId, x, y, w, h, style, exStyle)
#define CT_EDIT(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Edit", id, textId, x, y, w, h, ES_LEFT | style, exStyle)
#define CT_GROUPBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Button", id, textId, x, y, w, h, BS_GROUPBOX | style, exStyle)
#define CT_ICON(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ICON | style, exStyle)
#define CT_LABEL(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_LEFT | style, exStyle)
#define CT_LINEH(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"Static", id, textId, x, y, w, h, SS_ETCHEDHORZ | style, exStyle)
#define CT_LINKLABEL(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysLink", id, textId, x, y, w, h, style, exStyle)
#define CT_LISTBOX(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"ListBox", id, textId, x, y, w, h, style, exStyle)
#define CT_LISTVIEW(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysListView32", id, textId, x, y, w, h, style, exStyle)
#define CT_TAB(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysTabControl32", id, textId, x, y, w, h, TCS_TABS | style, exStyle)
#define CT_TREEVIEW(id, textId, x, y, w, h, style, exStyle) \
CT_ITEM(L"SysTreeView32", id, textId, x, y, w, h, style, exStyle)
} // namespace ControlTemplate
#endif

View File

@ -1,260 +1,260 @@
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Dialog.h"
HWND Dialog::c_ActiveDialogWindow = nullptr;
//
// BaseDialog
//
BaseDialog::BaseDialog() :
m_Window()
{
}
/*
** Create (if not already) and show the dialog.
**
*/
void BaseDialog::Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless)
{
if (m_Window)
{
// Show existing window.
ShowWindow(m_Window, SW_SHOW);
SetForegroundWindow(m_Window);
return;
}
const WCHAR* font = L"MS Shell Dlg 2";
const size_t titleSize = (wcslen(title) + 1) * sizeof(WCHAR);
const size_t fontSize = (wcslen(font) + 1) * sizeof(WCHAR);
const size_t dataSize = sizeof(DLGTEMPLATE) +
sizeof(WCHAR) + // Menu array.
sizeof(WCHAR) + // Class array.
titleSize + // Title array.
sizeof(WORD) + // Font point size.
fontSize; // Font array.
DLGTEMPLATE* dt = (DLGTEMPLATE*)new BYTE[dataSize];
dt->style = style | DS_SHELLFONT | WS_VISIBLE;
dt->dwExtendedStyle = exStyle;
dt->cdit = 0;
dt->x = x;
dt->y = y;
dt->cx = w;
dt->cy = h;
BYTE* dtExtra = (BYTE*)dt + sizeof(DLGTEMPLATE);
// Menu array.
*(WCHAR*)dtExtra = L'\0';
dtExtra += sizeof(WCHAR);
// Class array.
*(WCHAR*)dtExtra = L'\0';
dtExtra += sizeof(WCHAR);
// Title array.
memcpy(dtExtra, title, titleSize);
dtExtra += titleSize;
// Font point size.
*(WORD*)dtExtra = 8;
dtExtra += sizeof(WORD);
// Font array.
memcpy(dtExtra, font, fontSize);
if (modeless)
{
CreateDialogIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this);
}
else
{
DialogBoxIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this);
}
delete [] dt;
}
void BaseDialog::CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString)
{
ControlTemplate::CreateControls(cts, ctCount, m_Window, font, getString);
}
INT_PTR CALLBACK BaseDialog::InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_INITDIALOG)
{
BaseDialog* dialog = (BaseDialog*)lParam;
dialog->m_Window = hWnd;
SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)dialog);
SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)MainDlgProc);
return dialog->HandleMessage(uMsg, wParam, lParam);
}
return FALSE;
}
INT_PTR CALLBACK BaseDialog::MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BaseDialog* dialog = (BaseDialog*)GetWindowLongPtr(hWnd, DWLP_USER);
return dialog->HandleMessage(uMsg, wParam, lParam);
}
//
// Dialog
//
Dialog::Dialog() : BaseDialog(),
m_Font(),
m_FontBold()
{
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
m_Font = CreateFontIndirect(&ncm.lfMenuFont);
ncm.lfMenuFont.lfWeight = FW_BOLD;
ncm.lfMenuFont.lfHeight -= 2;
m_FontBold = CreateFontIndirect(&ncm.lfMenuFont);
}
Dialog::~Dialog()
{
DestroyWindow(m_Window);
DeleteObject(m_Font);
DeleteObject(m_FontBold);
}
void Dialog::ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless)
{
Show(title, x, y, w, h, style, exStyle, parent, modeless);
}
INT_PTR Dialog::OnActivate(WPARAM wParam, LPARAM lParam)
{
c_ActiveDialogWindow = wParam ? m_Window : nullptr;
return FALSE;
}
bool Dialog::HandleMessage(MSG& msg)
{
if (c_ActiveDialogWindow)
{
if (IsDialogMessage(c_ActiveDialogWindow, &msg))
{
return true;
}
}
return false;
}
/*
** Subclass button control to draw arrow on the right.
**
*/
void Dialog::SetMenuButton(HWND button)
{
SetWindowSubclass(button, MenuButtonProc, 0, 0);
}
LRESULT CALLBACK Dialog::MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
LRESULT result = DefSubclassProc(hWnd, uMsg, wParam, lParam);
switch (uMsg)
{
case WM_PAINT:
{
// Draw arrow on top of the button
RECT buttonRect;
GetClientRect(hWnd, &buttonRect);
int arrowX = buttonRect.right - 18;
int arrowY = buttonRect.top + 4;
RECT arrowRect = { arrowX, arrowY, arrowX + 14, arrowY + 14 };
HDC dc = GetDC(hWnd);
const WORD DFCS_MENUARROWDOWN = 0x0010; // Undocumented
DWORD drawFlags = DFCS_TRANSPARENT | DFCS_MENUARROWDOWN | (IsWindowEnabled(hWnd) ? 0 : DFCS_INACTIVE);
DrawFrameControl(dc, &arrowRect, DFC_MENU, drawFlags);
ReleaseDC(hWnd, dc);
}
break;
case WM_GETTEXT:
{
// Append 3 spaces to the button text to move text to the left so
// that it looks better with BS_CENTER.
WCHAR* str = (WCHAR*)lParam + result;
str[0] = str[1] = str[2] = L' ';
str[3] = '\0';
result += 3;
}
break;
case WM_GETTEXTLENGTH:
result += 3;
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, MenuButtonProc, uIdSubclass);
break;
}
return result;
}
//
// Tab
//
Dialog::Tab::Tab() : BaseDialog(),
m_Initialized(false)
{
}
void Dialog::Tab::CreateTabWindow(short x, short y, short w, short h, HWND owner)
{
const DWORD style = DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
const DWORD exStyle = WS_EX_CONTROLPARENT;
Show(L"", x, y, w, h, style, exStyle, owner, true);
EnableThemeDialogTexture(m_Window, ETDT_ENABLETAB);
}
Dialog::Tab::~Tab()
{
DestroyWindow(m_Window);
}
void Dialog::Tab::Activate()
{
if (!m_Initialized)
{
Initialize();
}
EnableWindow(m_Window, TRUE);
BringWindowToTop(m_Window);
}
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Dialog.h"
HWND Dialog::c_ActiveDialogWindow = nullptr;
//
// BaseDialog
//
BaseDialog::BaseDialog() :
m_Window()
{
}
/*
** Create (if not already) and show the dialog.
**
*/
void BaseDialog::Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless)
{
if (m_Window)
{
// Show existing window.
ShowWindow(m_Window, SW_SHOW);
SetForegroundWindow(m_Window);
return;
}
const WCHAR* font = L"MS Shell Dlg 2";
const size_t titleSize = (wcslen(title) + 1) * sizeof(WCHAR);
const size_t fontSize = (wcslen(font) + 1) * sizeof(WCHAR);
const size_t dataSize = sizeof(DLGTEMPLATE) +
sizeof(WCHAR) + // Menu array.
sizeof(WCHAR) + // Class array.
titleSize + // Title array.
sizeof(WORD) + // Font point size.
fontSize; // Font array.
DLGTEMPLATE* dt = (DLGTEMPLATE*)new BYTE[dataSize];
dt->style = style | DS_SHELLFONT | WS_VISIBLE;
dt->dwExtendedStyle = exStyle;
dt->cdit = 0;
dt->x = x;
dt->y = y;
dt->cx = w;
dt->cy = h;
BYTE* dtExtra = (BYTE*)dt + sizeof(DLGTEMPLATE);
// Menu array.
*(WCHAR*)dtExtra = L'\0';
dtExtra += sizeof(WCHAR);
// Class array.
*(WCHAR*)dtExtra = L'\0';
dtExtra += sizeof(WCHAR);
// Title array.
memcpy(dtExtra, title, titleSize);
dtExtra += titleSize;
// Font point size.
*(WORD*)dtExtra = 8;
dtExtra += sizeof(WORD);
// Font array.
memcpy(dtExtra, font, fontSize);
if (modeless)
{
CreateDialogIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this);
}
else
{
DialogBoxIndirectParam(nullptr, dt, parent, InitialDlgProc, (LPARAM)this);
}
delete [] dt;
}
void BaseDialog::CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString)
{
ControlTemplate::CreateControls(cts, ctCount, m_Window, font, getString);
}
INT_PTR CALLBACK BaseDialog::InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_INITDIALOG)
{
BaseDialog* dialog = (BaseDialog*)lParam;
dialog->m_Window = hWnd;
SetWindowLongPtr(hWnd, DWLP_USER, (LONG_PTR)dialog);
SetWindowLongPtr(hWnd, DWLP_DLGPROC, (LONG_PTR)MainDlgProc);
return dialog->HandleMessage(uMsg, wParam, lParam);
}
return FALSE;
}
INT_PTR CALLBACK BaseDialog::MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BaseDialog* dialog = (BaseDialog*)GetWindowLongPtr(hWnd, DWLP_USER);
return dialog->HandleMessage(uMsg, wParam, lParam);
}
//
// Dialog
//
Dialog::Dialog() : BaseDialog(),
m_Font(),
m_FontBold()
{
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS) - sizeof(ncm.iPaddedBorderWidth);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0);
m_Font = CreateFontIndirect(&ncm.lfMenuFont);
ncm.lfMenuFont.lfWeight = FW_BOLD;
ncm.lfMenuFont.lfHeight -= 2;
m_FontBold = CreateFontIndirect(&ncm.lfMenuFont);
}
Dialog::~Dialog()
{
DestroyWindow(m_Window);
DeleteObject(m_Font);
DeleteObject(m_FontBold);
}
void Dialog::ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless)
{
Show(title, x, y, w, h, style, exStyle, parent, modeless);
}
INT_PTR Dialog::OnActivate(WPARAM wParam, LPARAM lParam)
{
c_ActiveDialogWindow = wParam ? m_Window : nullptr;
return FALSE;
}
bool Dialog::HandleMessage(MSG& msg)
{
if (c_ActiveDialogWindow)
{
if (IsDialogMessage(c_ActiveDialogWindow, &msg))
{
return true;
}
}
return false;
}
/*
** Subclass button control to draw arrow on the right.
**
*/
void Dialog::SetMenuButton(HWND button)
{
SetWindowSubclass(button, MenuButtonProc, 0, 0);
}
LRESULT CALLBACK Dialog::MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
LRESULT result = DefSubclassProc(hWnd, uMsg, wParam, lParam);
switch (uMsg)
{
case WM_PAINT:
{
// Draw arrow on top of the button
RECT buttonRect;
GetClientRect(hWnd, &buttonRect);
int arrowX = buttonRect.right - 18;
int arrowY = buttonRect.top + 4;
RECT arrowRect = { arrowX, arrowY, arrowX + 14, arrowY + 14 };
HDC dc = GetDC(hWnd);
const WORD DFCS_MENUARROWDOWN = 0x0010; // Undocumented
DWORD drawFlags = DFCS_TRANSPARENT | DFCS_MENUARROWDOWN | (IsWindowEnabled(hWnd) ? 0 : DFCS_INACTIVE);
DrawFrameControl(dc, &arrowRect, DFC_MENU, drawFlags);
ReleaseDC(hWnd, dc);
}
break;
case WM_GETTEXT:
{
// Append 3 spaces to the button text to move text to the left so
// that it looks better with BS_CENTER.
WCHAR* str = (WCHAR*)lParam + result;
str[0] = str[1] = str[2] = L' ';
str[3] = '\0';
result += 3;
}
break;
case WM_GETTEXTLENGTH:
result += 3;
break;
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, MenuButtonProc, uIdSubclass);
break;
}
return result;
}
//
// Tab
//
Dialog::Tab::Tab() : BaseDialog(),
m_Initialized(false)
{
}
void Dialog::Tab::CreateTabWindow(short x, short y, short w, short h, HWND owner)
{
const DWORD style = DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;
const DWORD exStyle = WS_EX_CONTROLPARENT;
Show(L"", x, y, w, h, style, exStyle, owner, true);
EnableThemeDialogTexture(m_Window, ETDT_ENABLETAB);
}
Dialog::Tab::~Tab()
{
DestroyWindow(m_Window);
}
void Dialog::Tab::Activate()
{
if (!m_Initialized)
{
Initialize();
}
EnableWindow(m_Window, TRUE);
BringWindowToTop(m_Window);
}

View File

@ -1,97 +1,97 @@
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_DIALOG_H_
#define RM_COMMON_DIALOG_H_
#include <Windows.h>
#include "ControlTemplate.h"
// Shared base class for Dialog and Tab.
class BaseDialog
{
public:
HWND GetControl(WORD id) { return GetDlgItem(m_Window, id); }
protected:
BaseDialog();
virtual ~BaseDialog() {}
void Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless);
void CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString);
virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { return FALSE; }
HWND m_Window;
private:
BaseDialog(const BaseDialog& r);
static INT_PTR CALLBACK InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
class Dialog : public BaseDialog
{
public:
HWND GetWindow() { return m_Window; }
static bool HandleMessage(MSG& msg);
protected:
class Tab : public BaseDialog
{
public:
HWND GetWindow() { return m_Window; }
bool IsInitialized() { return m_Initialized; }
void Activate();
virtual void Initialize() {}
virtual void Resize(int w, int h) {}
protected:
Tab();
virtual ~Tab();
void CreateTabWindow(short x, short y, short w, short h, HWND owner);
bool m_Initialized;
};
Dialog();
virtual ~Dialog();
void ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless = true);
INT_PTR OnActivate(WPARAM wParam, LPARAM lParam);
static void SetMenuButton(HWND button);
HFONT m_Font;
HFONT m_FontBold;
private:
Dialog(const Dialog& r);
static LRESULT CALLBACK MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
static HWND c_ActiveDialogWindow;
};
#endif
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_DIALOG_H_
#define RM_COMMON_DIALOG_H_
#include <Windows.h>
#include "ControlTemplate.h"
// Shared base class for Dialog and Tab.
class BaseDialog
{
public:
HWND GetControl(WORD id) { return GetDlgItem(m_Window, id); }
protected:
BaseDialog();
virtual ~BaseDialog() {}
void Show(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless);
void CreateControls(const ControlTemplate::Control* cts, UINT ctCount, HFONT font, ControlTemplate::GetStringFunc getString);
virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { return FALSE; }
HWND m_Window;
private:
BaseDialog(const BaseDialog& r);
static INT_PTR CALLBACK InitialDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static INT_PTR CALLBACK MainDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
class Dialog : public BaseDialog
{
public:
HWND GetWindow() { return m_Window; }
static bool HandleMessage(MSG& msg);
protected:
class Tab : public BaseDialog
{
public:
HWND GetWindow() { return m_Window; }
bool IsInitialized() { return m_Initialized; }
void Activate();
virtual void Initialize() {}
virtual void Resize(int w, int h) {}
protected:
Tab();
virtual ~Tab();
void CreateTabWindow(short x, short y, short w, short h, HWND owner);
bool m_Initialized;
};
Dialog();
virtual ~Dialog();
void ShowDialogWindow(const WCHAR* title, short x, short y, short w, short h, DWORD style, DWORD exStyle, HWND parent, bool modeless = true);
INT_PTR OnActivate(WPARAM wParam, LPARAM lParam);
static void SetMenuButton(HWND button);
HFONT m_Font;
HFONT m_FontBold;
private:
Dialog(const Dialog& r);
static LRESULT CALLBACK MenuButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
static HWND c_ActiveDialogWindow;
};
#endif

View File

@ -1,71 +1,71 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Canvas.h"
#include "CanvasD2D.h"
#include "CanvasGDIP.h"
namespace Gfx {
Canvas::Canvas() :
m_W(),
m_H(),
m_AccurateText(false)
{
}
Canvas::~Canvas()
{
}
Canvas* Canvas::Create(Renderer renderer)
{
if (renderer == Renderer::GDIP)
{
return new CanvasGDIP();
}
else if (renderer == Renderer::D2D && IsWindows7OrGreater())
{
if (CanvasD2D::Initialize())
{
return new CanvasD2D();
}
CanvasD2D::Finalize();
}
else if (renderer == Renderer::PreferD2D)
{
if (Canvas* canvas = Create(Renderer::D2D))
{
return canvas;
}
return Create(Renderer::GDIP);
}
return nullptr;
};
void Canvas::Resize(int w, int h)
{
m_W = w;
m_H = h;
}
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Canvas.h"
#include "CanvasD2D.h"
#include "CanvasGDIP.h"
namespace Gfx {
Canvas::Canvas() :
m_W(),
m_H(),
m_AccurateText(false)
{
}
Canvas::~Canvas()
{
}
Canvas* Canvas::Create(Renderer renderer)
{
if (renderer == Renderer::GDIP)
{
return new CanvasGDIP();
}
else if (renderer == Renderer::D2D && IsWindows7OrGreater())
{
if (CanvasD2D::Initialize())
{
return new CanvasD2D();
}
CanvasD2D::Finalize();
}
else if (renderer == Renderer::PreferD2D)
{
if (Canvas* canvas = Create(Renderer::D2D))
{
return canvas;
}
return Create(Renderer::GDIP);
}
return nullptr;
};
void Canvas::Resize(int w, int h)
{
m_W = w;
m_H = h;
}
} // namespace Gfx

View File

@ -1,114 +1,114 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_CANVAS_H_
#define RM_GFX_CANVAS_H_
#include "FontCollection.h"
#include "TextFormat.h"
namespace Gfx {
enum class Renderer
{
GDIP,
D2D,
// Attempts to use D2D. If D2D is not available, fallbacks to use GDI+.
PreferD2D
};
// Provides methods for drawing text, bitmaps, etc.
class __declspec(novtable) Canvas
{
public:
virtual ~Canvas();
Canvas(const Canvas& other) = delete;
// Creates the canvas using the specified rendering engine. May return nullptr.
static Canvas* Create(Renderer renderer);
int GetW() const { return m_W; }
int GetH() const { return m_H; }
void SetAccurateText(bool option) { m_AccurateText = option; }
// Resize the draw area of the Canvas. This function must not be called if BeginDraw() has been
// called and has not yet been matched by a correspoding call to EndDraw.
virtual void Resize(int w, int h);
// BeginDraw() must be matched by a corresponding call to EndDraw(). Drawing functions must be
// be called only between BeginDraw() and EndDraw().
virtual bool BeginDraw() = 0;
virtual void EndDraw() = 0;
// Allows the use of Gdiplus::Graphics to perform drawing. Must be called between BeginDraw()
// and EndDraw(). BeginGdiplusGraphicsContext() must be matched by a corresponding call to
// EndGdiplusGraphicsContext(). While in the Gdiplus context, non-const member functions of
// this class must not be called.
virtual Gdiplus::Graphics& BeginGdiplusContext() = 0;
virtual void EndGdiplusContext() = 0;
// Returns a read-only DC. Must be called between BeginDraw() and EndDraw(). GetDC() must be
// matched by a corresponding call to ReleaseDC(). While in the Gdiplus context, non-const
// member functions of this class must not be called.
virtual HDC GetDC() = 0;
virtual void ReleaseDC(HDC dc) = 0;
// The Create* functions allocate objects specific to this Canvas object.
virtual FontCollection* CreateFontCollection() = 0;
virtual TextFormat* CreateTextFormat() = 0;
virtual bool IsTransparentPixel(int x, int y) = 0;
virtual void SetTransform(const Gdiplus::Matrix& matrix) = 0;
virtual void ResetTransform() = 0;
virtual void RotateTransform(float angle, float x, float y, float dx, float dy) = 0;
virtual void SetAntiAliasing(bool enable) = 0;
virtual void SetTextAntiAliasing(bool enable) = 0;
virtual void Clear(const Gdiplus::Color& color = Gdiplus::Color(0, 0, 0, 0)) = 0;
virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) = 0;
virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) = 0;
virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) = 0;
virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) = 0;
virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) = 0;
protected:
Canvas();
int m_W;
int m_H;
// GDI+, by default, includes padding around the string and also has a larger character spacing
// compared to DirectWrite. In order to minimize diffeences between the text renderers,
// an option is provided to enable accurate (typographic) text rendering. If set to |true|,
// it is expected that there is no padding around the text and that the output is similar to
// the default DirectWrite output. Otherwise, the expected result should be similar to that of
// non-typographic GDI+.
bool m_AccurateText;
};
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_CANVAS_H_
#define RM_GFX_CANVAS_H_
#include "FontCollection.h"
#include "TextFormat.h"
namespace Gfx {
enum class Renderer
{
GDIP,
D2D,
// Attempts to use D2D. If D2D is not available, fallbacks to use GDI+.
PreferD2D
};
// Provides methods for drawing text, bitmaps, etc.
class __declspec(novtable) Canvas
{
public:
virtual ~Canvas();
Canvas(const Canvas& other) = delete;
// Creates the canvas using the specified rendering engine. May return nullptr.
static Canvas* Create(Renderer renderer);
int GetW() const { return m_W; }
int GetH() const { return m_H; }
void SetAccurateText(bool option) { m_AccurateText = option; }
// Resize the draw area of the Canvas. This function must not be called if BeginDraw() has been
// called and has not yet been matched by a correspoding call to EndDraw.
virtual void Resize(int w, int h);
// BeginDraw() must be matched by a corresponding call to EndDraw(). Drawing functions must be
// be called only between BeginDraw() and EndDraw().
virtual bool BeginDraw() = 0;
virtual void EndDraw() = 0;
// Allows the use of Gdiplus::Graphics to perform drawing. Must be called between BeginDraw()
// and EndDraw(). BeginGdiplusGraphicsContext() must be matched by a corresponding call to
// EndGdiplusGraphicsContext(). While in the Gdiplus context, non-const member functions of
// this class must not be called.
virtual Gdiplus::Graphics& BeginGdiplusContext() = 0;
virtual void EndGdiplusContext() = 0;
// Returns a read-only DC. Must be called between BeginDraw() and EndDraw(). GetDC() must be
// matched by a corresponding call to ReleaseDC(). While in the Gdiplus context, non-const
// member functions of this class must not be called.
virtual HDC GetDC() = 0;
virtual void ReleaseDC(HDC dc) = 0;
// The Create* functions allocate objects specific to this Canvas object.
virtual FontCollection* CreateFontCollection() = 0;
virtual TextFormat* CreateTextFormat() = 0;
virtual bool IsTransparentPixel(int x, int y) = 0;
virtual void SetTransform(const Gdiplus::Matrix& matrix) = 0;
virtual void ResetTransform() = 0;
virtual void RotateTransform(float angle, float x, float y, float dx, float dy) = 0;
virtual void SetAntiAliasing(bool enable) = 0;
virtual void SetTextAntiAliasing(bool enable) = 0;
virtual void Clear(const Gdiplus::Color& color = Gdiplus::Color(0, 0, 0, 0)) = 0;
virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) = 0;
virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) = 0;
virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) = 0;
virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) = 0;
virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) = 0;
protected:
Canvas();
int m_W;
int m_H;
// GDI+, by default, includes padding around the string and also has a larger character spacing
// compared to DirectWrite. In order to minimize diffeences between the text renderers,
// an option is provided to enable accurate (typographic) text rendering. If set to |true|,
// it is expected that there is no padding around the text and that the output is similar to
// the default DirectWrite output. Otherwise, the expected result should be similar to that of
// non-typographic GDI+.
bool m_AccurateText;
};
} // namespace Gfx
#endif

View File

@ -1,484 +1,484 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "CanvasD2D.h"
#include "TextFormatD2D.h"
#include "Util/DWriteFontCollectionLoader.h"
#include "Util/DWriteHelpers.h"
#include "Util/WICBitmapLockGDIP.h"
#include "../../Library/Litestep.h"
namespace {
D2D1_COLOR_F ToColorF(const Gdiplus::Color& color)
{
return D2D1::ColorF(color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, color.GetA() / 255.0f);
}
D2D1_RECT_F ToRectF(const Gdiplus::Rect& rect)
{
return D2D1::RectF((FLOAT)rect.X, (FLOAT)rect.Y, (FLOAT)(rect.X + rect.Width), (FLOAT)(rect.Y + rect.Height));
}
D2D1_RECT_F ToRectF(const Gdiplus::RectF& rect)
{
return D2D1::RectF(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
}
} // namespace
namespace Gfx {
UINT CanvasD2D::c_Instances = 0;
Microsoft::WRL::ComPtr<ID2D1Factory1> CanvasD2D::c_D2DFactory;
Microsoft::WRL::ComPtr<IDWriteFactory1> CanvasD2D::c_DWFactory;
Microsoft::WRL::ComPtr<IDWriteGdiInterop> CanvasD2D::c_DWGDIInterop;
Microsoft::WRL::ComPtr<IWICImagingFactory> CanvasD2D::c_WICFactory;
CanvasD2D::CanvasD2D() : Canvas(),
m_Bitmap(),
m_TextAntiAliasing(false),
m_CanUseAxisAlignClip(false)
{
}
CanvasD2D::~CanvasD2D()
{
Finalize();
}
bool CanvasD2D::Initialize()
{
++c_Instances;
if (c_Instances == 1)
{
if (!IsWindows7OrGreater()) return false;
D2D1_FACTORY_OPTIONS fo = {};
#ifdef _DEBUG
fo.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
#endif
HRESULT hr = D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
fo,
c_D2DFactory.GetAddressOf());
if (FAILED(hr)) return false;
hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)c_WICFactory.GetAddressOf());
if (FAILED(hr)) return false;
hr = DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(c_DWFactory),
(IUnknown**)c_DWFactory.GetAddressOf());
if (FAILED(hr)) return false;
hr = c_DWFactory->GetGdiInterop(c_DWGDIInterop.GetAddressOf());
if (FAILED(hr)) return false;
hr = c_DWFactory->RegisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance());
if (FAILED(hr)) return false;
}
return true;
}
void CanvasD2D::Finalize()
{
--c_Instances;
if (c_Instances == 0)
{
c_D2DFactory.Reset();
c_WICFactory.Reset();
c_DWGDIInterop.Reset();
if (c_DWFactory)
{
c_DWFactory->UnregisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance());
c_DWFactory.Reset();
}
}
}
void CanvasD2D::Resize(int w, int h)
{
__super::Resize(w, h);
m_Target.Reset();
m_Bitmap.Resize(w, h);
m_GdipBitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, m_Bitmap.GetData()));
m_GdipGraphics.reset(new Gdiplus::Graphics(m_GdipBitmap.get()));
}
bool CanvasD2D::BeginDraw()
{
return true;
}
void CanvasD2D::EndDraw()
{
EndTargetDraw();
}
bool CanvasD2D::BeginTargetDraw()
{
if (m_Target) return true;
const D2D1_PIXEL_FORMAT format = D2D1::PixelFormat(
DXGI_FORMAT_B8G8R8A8_UNORM,
D2D1_ALPHA_MODE_PREMULTIPLIED);
const D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT,
format,
0.0f, // Default DPI
0.0f, // Default DPI
D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE);
// A new Direct2D render target must be created for each sequence of Direct2D draw operations
// since we use GDI+ to render to the same pixel data. Without creating a new render target
// each time, it has been found that Direct2D may overwrite the draws by GDI+ since it is
// unaware of the changes made by GDI+. By creating a new render target and then releasing it
// before the next GDI+ draw operations, we ensure that the pixel data result is as expected
// Once GDI+ drawing is no longer needed, we change to recreate the render target only when the
// bitmap size is changed.
HRESULT hr = c_D2DFactory->CreateWicBitmapRenderTarget(&m_Bitmap, properties, &m_Target);
if (SUCCEEDED(hr))
{
SetTextAntiAliasing(m_TextAntiAliasing);
m_Target->BeginDraw();
// Apply any transforms that occurred before creation of |m_Target|.
UpdateTargetTransform();
return true;
}
return false;
}
void CanvasD2D::EndTargetDraw()
{
if (m_Target)
{
m_Target->EndDraw();
m_Target.Reset();
}
}
Gdiplus::Graphics& CanvasD2D::BeginGdiplusContext()
{
EndTargetDraw();
return *m_GdipGraphics;
}
void CanvasD2D::EndGdiplusContext()
{
}
HDC CanvasD2D::GetDC()
{
EndTargetDraw();
HDC dcMemory = CreateCompatibleDC(nullptr);
SelectObject(dcMemory, m_Bitmap.GetHandle());
return dcMemory;
}
void CanvasD2D::ReleaseDC(HDC dc)
{
DeleteDC(dc);
}
bool CanvasD2D::IsTransparentPixel(int x, int y)
{
if (!(x >= 0 && y >= 0 && x < m_W && y < m_H)) return false;
bool transparent = true;
DWORD* data = (DWORD*)m_Bitmap.GetData();
if (data)
{
DWORD pixel = data[y * m_W + x]; // Top-down DIB.
transparent = (pixel & 0xFF000000) != 0;
}
return transparent;
}
void CanvasD2D::UpdateTargetTransform()
{
Gdiplus::Matrix gdipMatrix;
m_GdipGraphics->GetTransform(&gdipMatrix);
D2D1_MATRIX_3X2_F d2dMatrix;
gdipMatrix.GetElements((Gdiplus::REAL*)&d2dMatrix);
m_Target->SetTransform(d2dMatrix);
m_CanUseAxisAlignClip =
d2dMatrix._12 == 0.0f && d2dMatrix._21 == 0.0f &&
d2dMatrix._31 == 0.0f && d2dMatrix._32 == 0.0f;
}
void CanvasD2D::SetTransform(const Gdiplus::Matrix& matrix)
{
m_GdipGraphics->SetTransform(&matrix);
if (m_Target)
{
UpdateTargetTransform();
}
}
void CanvasD2D::ResetTransform()
{
m_GdipGraphics->ResetTransform();
if (m_Target)
{
m_Target->SetTransform(D2D1::Matrix3x2F::Identity());
}
}
void CanvasD2D::RotateTransform(float angle, float x, float y, float dx, float dy)
{
m_GdipGraphics->TranslateTransform(x, y);
m_GdipGraphics->RotateTransform(angle);
m_GdipGraphics->TranslateTransform(dx, dy);
if (m_Target)
{
UpdateTargetTransform();
}
}
void CanvasD2D::SetAntiAliasing(bool enable)
{
// TODO: Set m_Target aliasing?
m_GdipGraphics->SetSmoothingMode(
enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone);
m_GdipGraphics->SetPixelOffsetMode(
enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault);
}
void CanvasD2D::SetTextAntiAliasing(bool enable)
{
// TODO: Add support for D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE?
m_TextAntiAliasing = enable;
if (m_Target)
{
m_Target->SetTextAntialiasMode(
m_TextAntiAliasing ? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
}
}
void CanvasD2D::Clear(const Gdiplus::Color& color)
{
if (!m_Target) // Use GDI+ if D2D render target has not been created.
{
m_GdipGraphics->Clear(color);
return;
}
m_Target->Clear(ToColorF(color));
}
void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush)
{
if (!BeginTargetDraw()) return;
Gdiplus::Color color;
brush.GetColor(&color);
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
if (FAILED(hr)) return;
TextFormatD2D& formatD2D = (TextFormatD2D&)format;
if (!formatD2D.CreateLayout(
str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing)) return;
D2D1_POINT_2F drawPosition;
drawPosition.x = [&]()
{
if (!m_AccurateText)
{
const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f;
switch (formatD2D.GetHorizontalAlignment())
{
case HorizontalAlignment::Left: return rect.X + xOffset;
case HorizontalAlignment::Right: return rect.X - xOffset;
}
}
return rect.X;
} ();
drawPosition.y = [&]()
{
// GDI+ compatibility.
float yPos = rect.Y - formatD2D.m_LineGap;
switch (formatD2D.GetVerticalAlignment())
{
case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break;
case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break;
}
return yPos;
} ();
if (formatD2D.m_Trimming)
{
D2D1_RECT_F clipRect = ToRectF(rect);
if (m_CanUseAxisAlignClip)
{
m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
}
else
{
const D2D1_LAYER_PARAMETERS layerParams =
D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED);
m_Target->PushLayer(layerParams, nullptr);
}
}
m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get());
if (formatD2D.m_Trimming)
{
if (m_CanUseAxisAlignClip)
{
m_Target->PopAxisAlignedClip();
}
else
{
m_Target->PopLayer();
}
}
}
bool CanvasD2D::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect)
{
TextFormatD2D& formatD2D = (TextFormatD2D&)format;
const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText);
rect.Width = metrics.width;
rect.Height = metrics.height;
return true;
}
bool CanvasD2D::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines)
{
TextFormatD2D& formatD2D = (TextFormatD2D&)format;
formatD2D.m_TextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP);
const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText, rect.Width);
rect.Width = metrics.width;
rect.Height = metrics.height;
lines = metrics.lineCount;
if (rect.Height > 0.0f)
{
// GDI+ draws multi-line text even though the last line may be clipped slightly at the
// bottom. This is a workaround to emulate that behaviour.
rect.Height += 1.0f;
}
else
{
// GDI+ compatibility: Zero height text has no visible lines.
lines = 0;
}
return true;
}
void CanvasD2D::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect)
{
if (srcRect.Width != dstRect.Width || srcRect.Height != dstRect.Height)
{
// If the bitmap needs to be scaled, get rid of the D2D target and use the GDI+ code path
// to draw the bitmap. This is due to antialiasing differences between GDI+ and D2D on
// scaled bitmaps.
EndTargetDraw();
}
if (!m_Target) // Use GDI+ if D2D render target has not been created.
{
m_GdipGraphics->DrawImage(
bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel);
return;
}
// The D2D DrawBitmap seems to perform exactly like Gdiplus::Graphics::DrawImage since we are
// not using a hardware accelerated render target. Nevertheless, we will use it to avoid
// the EndDraw() call needed for GDI+ drawing.
Util::WICBitmapLockGDIP* bitmapLock = new Util::WICBitmapLockGDIP();
Gdiplus::Rect lockRect(0, 0, bitmap->GetWidth(), bitmap->GetHeight());
Gdiplus::Status status = bitmap->LockBits(
&lockRect, Gdiplus::ImageLockModeRead, PixelFormat32bppPARGB, bitmapLock->GetBitmapData());
if (status == Gdiplus::Ok)
{
D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED));
Microsoft::WRL::ComPtr<ID2D1Bitmap> d2dBitmap;
HRESULT hr = m_Target->CreateSharedBitmap(
__uuidof(IWICBitmapLock), bitmapLock, &props, d2dBitmap.GetAddressOf());
if (SUCCEEDED(hr))
{
auto rDst = ToRectF(dstRect);
auto rSrc = ToRectF(srcRect);
m_Target->DrawBitmap(d2dBitmap.Get(), rDst, 1.0F, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rSrc);
}
// D2D will still use the pixel data after this call (at the next Flush() or EndDraw()).
bitmap->UnlockBits(bitmapLock->GetBitmapData());
}
bitmapLock->Release();
}
void CanvasD2D::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush)
{
if (!m_Target) // Use GDI+ if D2D render target has not been created.
{
m_GdipGraphics->FillRectangle(&brush, rect);
return;
}
Gdiplus::Color color;
brush.GetColor(&color);
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
if (SUCCEEDED(hr))
{
m_Target->FillRectangle(ToRectF(rect), solidBrush.Get());
}
}
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "CanvasD2D.h"
#include "TextFormatD2D.h"
#include "Util/DWriteFontCollectionLoader.h"
#include "Util/DWriteHelpers.h"
#include "Util/WICBitmapLockGDIP.h"
#include "../../Library/Litestep.h"
namespace {
D2D1_COLOR_F ToColorF(const Gdiplus::Color& color)
{
return D2D1::ColorF(color.GetR() / 255.0f, color.GetG() / 255.0f, color.GetB() / 255.0f, color.GetA() / 255.0f);
}
D2D1_RECT_F ToRectF(const Gdiplus::Rect& rect)
{
return D2D1::RectF((FLOAT)rect.X, (FLOAT)rect.Y, (FLOAT)(rect.X + rect.Width), (FLOAT)(rect.Y + rect.Height));
}
D2D1_RECT_F ToRectF(const Gdiplus::RectF& rect)
{
return D2D1::RectF(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
}
} // namespace
namespace Gfx {
UINT CanvasD2D::c_Instances = 0;
Microsoft::WRL::ComPtr<ID2D1Factory1> CanvasD2D::c_D2DFactory;
Microsoft::WRL::ComPtr<IDWriteFactory1> CanvasD2D::c_DWFactory;
Microsoft::WRL::ComPtr<IDWriteGdiInterop> CanvasD2D::c_DWGDIInterop;
Microsoft::WRL::ComPtr<IWICImagingFactory> CanvasD2D::c_WICFactory;
CanvasD2D::CanvasD2D() : Canvas(),
m_Bitmap(),
m_TextAntiAliasing(false),
m_CanUseAxisAlignClip(false)
{
}
CanvasD2D::~CanvasD2D()
{
Finalize();
}
bool CanvasD2D::Initialize()
{
++c_Instances;
if (c_Instances == 1)
{
if (!IsWindows7OrGreater()) return false;
D2D1_FACTORY_OPTIONS fo = {};
#ifdef _DEBUG
fo.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
#endif
HRESULT hr = D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
fo,
c_D2DFactory.GetAddressOf());
if (FAILED(hr)) return false;
hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)c_WICFactory.GetAddressOf());
if (FAILED(hr)) return false;
hr = DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(c_DWFactory),
(IUnknown**)c_DWFactory.GetAddressOf());
if (FAILED(hr)) return false;
hr = c_DWFactory->GetGdiInterop(c_DWGDIInterop.GetAddressOf());
if (FAILED(hr)) return false;
hr = c_DWFactory->RegisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance());
if (FAILED(hr)) return false;
}
return true;
}
void CanvasD2D::Finalize()
{
--c_Instances;
if (c_Instances == 0)
{
c_D2DFactory.Reset();
c_WICFactory.Reset();
c_DWGDIInterop.Reset();
if (c_DWFactory)
{
c_DWFactory->UnregisterFontCollectionLoader(Util::DWriteFontCollectionLoader::GetInstance());
c_DWFactory.Reset();
}
}
}
void CanvasD2D::Resize(int w, int h)
{
__super::Resize(w, h);
m_Target.Reset();
m_Bitmap.Resize(w, h);
m_GdipBitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, m_Bitmap.GetData()));
m_GdipGraphics.reset(new Gdiplus::Graphics(m_GdipBitmap.get()));
}
bool CanvasD2D::BeginDraw()
{
return true;
}
void CanvasD2D::EndDraw()
{
EndTargetDraw();
}
bool CanvasD2D::BeginTargetDraw()
{
if (m_Target) return true;
const D2D1_PIXEL_FORMAT format = D2D1::PixelFormat(
DXGI_FORMAT_B8G8R8A8_UNORM,
D2D1_ALPHA_MODE_PREMULTIPLIED);
const D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties(
D2D1_RENDER_TARGET_TYPE_DEFAULT,
format,
0.0f, // Default DPI
0.0f, // Default DPI
D2D1_RENDER_TARGET_USAGE_GDI_COMPATIBLE);
// A new Direct2D render target must be created for each sequence of Direct2D draw operations
// since we use GDI+ to render to the same pixel data. Without creating a new render target
// each time, it has been found that Direct2D may overwrite the draws by GDI+ since it is
// unaware of the changes made by GDI+. By creating a new render target and then releasing it
// before the next GDI+ draw operations, we ensure that the pixel data result is as expected
// Once GDI+ drawing is no longer needed, we change to recreate the render target only when the
// bitmap size is changed.
HRESULT hr = c_D2DFactory->CreateWicBitmapRenderTarget(&m_Bitmap, properties, &m_Target);
if (SUCCEEDED(hr))
{
SetTextAntiAliasing(m_TextAntiAliasing);
m_Target->BeginDraw();
// Apply any transforms that occurred before creation of |m_Target|.
UpdateTargetTransform();
return true;
}
return false;
}
void CanvasD2D::EndTargetDraw()
{
if (m_Target)
{
m_Target->EndDraw();
m_Target.Reset();
}
}
Gdiplus::Graphics& CanvasD2D::BeginGdiplusContext()
{
EndTargetDraw();
return *m_GdipGraphics;
}
void CanvasD2D::EndGdiplusContext()
{
}
HDC CanvasD2D::GetDC()
{
EndTargetDraw();
HDC dcMemory = CreateCompatibleDC(nullptr);
SelectObject(dcMemory, m_Bitmap.GetHandle());
return dcMemory;
}
void CanvasD2D::ReleaseDC(HDC dc)
{
DeleteDC(dc);
}
bool CanvasD2D::IsTransparentPixel(int x, int y)
{
if (!(x >= 0 && y >= 0 && x < m_W && y < m_H)) return false;
bool transparent = true;
DWORD* data = (DWORD*)m_Bitmap.GetData();
if (data)
{
DWORD pixel = data[y * m_W + x]; // Top-down DIB.
transparent = (pixel & 0xFF000000) != 0;
}
return transparent;
}
void CanvasD2D::UpdateTargetTransform()
{
Gdiplus::Matrix gdipMatrix;
m_GdipGraphics->GetTransform(&gdipMatrix);
D2D1_MATRIX_3X2_F d2dMatrix;
gdipMatrix.GetElements((Gdiplus::REAL*)&d2dMatrix);
m_Target->SetTransform(d2dMatrix);
m_CanUseAxisAlignClip =
d2dMatrix._12 == 0.0f && d2dMatrix._21 == 0.0f &&
d2dMatrix._31 == 0.0f && d2dMatrix._32 == 0.0f;
}
void CanvasD2D::SetTransform(const Gdiplus::Matrix& matrix)
{
m_GdipGraphics->SetTransform(&matrix);
if (m_Target)
{
UpdateTargetTransform();
}
}
void CanvasD2D::ResetTransform()
{
m_GdipGraphics->ResetTransform();
if (m_Target)
{
m_Target->SetTransform(D2D1::Matrix3x2F::Identity());
}
}
void CanvasD2D::RotateTransform(float angle, float x, float y, float dx, float dy)
{
m_GdipGraphics->TranslateTransform(x, y);
m_GdipGraphics->RotateTransform(angle);
m_GdipGraphics->TranslateTransform(dx, dy);
if (m_Target)
{
UpdateTargetTransform();
}
}
void CanvasD2D::SetAntiAliasing(bool enable)
{
// TODO: Set m_Target aliasing?
m_GdipGraphics->SetSmoothingMode(
enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone);
m_GdipGraphics->SetPixelOffsetMode(
enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault);
}
void CanvasD2D::SetTextAntiAliasing(bool enable)
{
// TODO: Add support for D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE?
m_TextAntiAliasing = enable;
if (m_Target)
{
m_Target->SetTextAntialiasMode(
m_TextAntiAliasing ? D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE : D2D1_TEXT_ANTIALIAS_MODE_ALIASED);
}
}
void CanvasD2D::Clear(const Gdiplus::Color& color)
{
if (!m_Target) // Use GDI+ if D2D render target has not been created.
{
m_GdipGraphics->Clear(color);
return;
}
m_Target->Clear(ToColorF(color));
}
void CanvasD2D::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush)
{
if (!BeginTargetDraw()) return;
Gdiplus::Color color;
brush.GetColor(&color);
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
if (FAILED(hr)) return;
TextFormatD2D& formatD2D = (TextFormatD2D&)format;
if (!formatD2D.CreateLayout(
str, strLen, rect.Width, rect.Height, !m_AccurateText && m_TextAntiAliasing)) return;
D2D1_POINT_2F drawPosition;
drawPosition.x = [&]()
{
if (!m_AccurateText)
{
const float xOffset = formatD2D.m_TextFormat->GetFontSize() / 6.0f;
switch (formatD2D.GetHorizontalAlignment())
{
case HorizontalAlignment::Left: return rect.X + xOffset;
case HorizontalAlignment::Right: return rect.X - xOffset;
}
}
return rect.X;
} ();
drawPosition.y = [&]()
{
// GDI+ compatibility.
float yPos = rect.Y - formatD2D.m_LineGap;
switch (formatD2D.GetVerticalAlignment())
{
case VerticalAlignment::Bottom: yPos -= formatD2D.m_ExtraHeight; break;
case VerticalAlignment::Center: yPos -= formatD2D.m_ExtraHeight / 2; break;
}
return yPos;
} ();
if (formatD2D.m_Trimming)
{
D2D1_RECT_F clipRect = ToRectF(rect);
if (m_CanUseAxisAlignClip)
{
m_Target->PushAxisAlignedClip(clipRect, D2D1_ANTIALIAS_MODE_ALIASED);
}
else
{
const D2D1_LAYER_PARAMETERS layerParams =
D2D1::LayerParameters(clipRect, nullptr, D2D1_ANTIALIAS_MODE_ALIASED);
m_Target->PushLayer(layerParams, nullptr);
}
}
m_Target->DrawTextLayout(drawPosition, formatD2D.m_TextLayout.Get(), solidBrush.Get());
if (formatD2D.m_Trimming)
{
if (m_CanUseAxisAlignClip)
{
m_Target->PopAxisAlignedClip();
}
else
{
m_Target->PopLayer();
}
}
}
bool CanvasD2D::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect)
{
TextFormatD2D& formatD2D = (TextFormatD2D&)format;
const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText);
rect.Width = metrics.width;
rect.Height = metrics.height;
return true;
}
bool CanvasD2D::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines)
{
TextFormatD2D& formatD2D = (TextFormatD2D&)format;
formatD2D.m_TextFormat->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP);
const DWRITE_TEXT_METRICS metrics = formatD2D.GetMetrics(str, strLen, !m_AccurateText, rect.Width);
rect.Width = metrics.width;
rect.Height = metrics.height;
lines = metrics.lineCount;
if (rect.Height > 0.0f)
{
// GDI+ draws multi-line text even though the last line may be clipped slightly at the
// bottom. This is a workaround to emulate that behaviour.
rect.Height += 1.0f;
}
else
{
// GDI+ compatibility: Zero height text has no visible lines.
lines = 0;
}
return true;
}
void CanvasD2D::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect)
{
if (srcRect.Width != dstRect.Width || srcRect.Height != dstRect.Height)
{
// If the bitmap needs to be scaled, get rid of the D2D target and use the GDI+ code path
// to draw the bitmap. This is due to antialiasing differences between GDI+ and D2D on
// scaled bitmaps.
EndTargetDraw();
}
if (!m_Target) // Use GDI+ if D2D render target has not been created.
{
m_GdipGraphics->DrawImage(
bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel);
return;
}
// The D2D DrawBitmap seems to perform exactly like Gdiplus::Graphics::DrawImage since we are
// not using a hardware accelerated render target. Nevertheless, we will use it to avoid
// the EndDraw() call needed for GDI+ drawing.
Util::WICBitmapLockGDIP* bitmapLock = new Util::WICBitmapLockGDIP();
Gdiplus::Rect lockRect(0, 0, bitmap->GetWidth(), bitmap->GetHeight());
Gdiplus::Status status = bitmap->LockBits(
&lockRect, Gdiplus::ImageLockModeRead, PixelFormat32bppPARGB, bitmapLock->GetBitmapData());
if (status == Gdiplus::Ok)
{
D2D1_BITMAP_PROPERTIES props = D2D1::BitmapProperties(
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED));
Microsoft::WRL::ComPtr<ID2D1Bitmap> d2dBitmap;
HRESULT hr = m_Target->CreateSharedBitmap(
__uuidof(IWICBitmapLock), bitmapLock, &props, d2dBitmap.GetAddressOf());
if (SUCCEEDED(hr))
{
auto rDst = ToRectF(dstRect);
auto rSrc = ToRectF(srcRect);
m_Target->DrawBitmap(d2dBitmap.Get(), rDst, 1.0F, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rSrc);
}
// D2D will still use the pixel data after this call (at the next Flush() or EndDraw()).
bitmap->UnlockBits(bitmapLock->GetBitmapData());
}
bitmapLock->Release();
}
void CanvasD2D::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush)
{
if (!m_Target) // Use GDI+ if D2D render target has not been created.
{
m_GdipGraphics->FillRectangle(&brush, rect);
return;
}
Gdiplus::Color color;
brush.GetColor(&color);
Microsoft::WRL::ComPtr<ID2D1SolidColorBrush> solidBrush;
HRESULT hr = m_Target->CreateSolidColorBrush(ToColorF(color), solidBrush.GetAddressOf());
if (SUCCEEDED(hr))
{
m_Target->FillRectangle(ToRectF(rect), solidBrush.Get());
}
}
} // namespace Gfx

View File

@ -1,118 +1,118 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_CANVASD2D_H_
#define RM_GFX_CANVASD2D_H_
#include "Canvas.h"
#include "FontCollectionD2D.h"
#include "TextFormatD2D.h"
#include "Util/WICBitmapDIB.h"
#include <memory>
#include <string>
#include <ole2.h> // For Gdiplus.h.
#include <GdiPlus.h>
#include <d2d1_1.h>
#include <d2d1helper.h>
#include <dwrite_1.h>
#include <wincodec.h>
#include <wrl/client.h>
namespace Gfx {
// Provides a Direct2D/DirectWrite implementation of Canvas.
class CanvasD2D : public Canvas
{
public:
static bool Initialize();
static void Finalize();
virtual void Resize(int w, int h);
virtual bool BeginDraw();
virtual void EndDraw();
virtual Gdiplus::Graphics& BeginGdiplusContext() override;
virtual void EndGdiplusContext() override;
virtual HDC GetDC() override;
virtual void ReleaseDC(HDC dc) override;
virtual FontCollection* CreateFontCollection() override { return new FontCollectionD2D(); }
virtual TextFormat* CreateTextFormat() override { return new TextFormatD2D(); }
virtual bool IsTransparentPixel(int x, int y) override;
virtual void SetTransform(const Gdiplus::Matrix& matrix) override;
virtual void ResetTransform() override;
virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override;
virtual void SetAntiAliasing(bool enable) override;
virtual void SetTextAntiAliasing(bool enable) override;
virtual void Clear(const Gdiplus::Color& color) override;
virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override;
virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override;
virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override;
virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override;
virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override;
private:
friend class Canvas;
friend class FontCollectionD2D;
friend class TextFormatD2D;
CanvasD2D();
~CanvasD2D();
CanvasD2D(const CanvasD2D& other) = delete;
CanvasD2D& operator=(CanvasD2D other) = delete;
bool BeginTargetDraw();
void EndTargetDraw();
// Sets the |m_Target| transformation to be equal to that of |m_GdipGraphics|.
void UpdateTargetTransform();
Microsoft::WRL::ComPtr<ID2D1RenderTarget> m_Target;
// Underlying pixel data shared by both m_Target and m_GdipBitmap.
Util::WICBitmapDIB m_Bitmap;
// GDI+ objects that share the pixel data of m_Bitmap.
std::unique_ptr<Gdiplus::Graphics> m_GdipGraphics;
std::unique_ptr<Gdiplus::Bitmap> m_GdipBitmap;
bool m_TextAntiAliasing;
// |true| if PushAxisAlignedClip()/PopAxisAlignedClip() can be used.
bool m_CanUseAxisAlignClip;
static UINT c_Instances;
static Microsoft::WRL::ComPtr<ID2D1Factory1> c_D2DFactory;
static Microsoft::WRL::ComPtr<IDWriteFactory1> c_DWFactory;
static Microsoft::WRL::ComPtr<IDWriteGdiInterop> c_DWGDIInterop;
static Microsoft::WRL::ComPtr<IWICImagingFactory> c_WICFactory;
};
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_CANVASD2D_H_
#define RM_GFX_CANVASD2D_H_
#include "Canvas.h"
#include "FontCollectionD2D.h"
#include "TextFormatD2D.h"
#include "Util/WICBitmapDIB.h"
#include <memory>
#include <string>
#include <ole2.h> // For Gdiplus.h.
#include <GdiPlus.h>
#include <d2d1_1.h>
#include <d2d1helper.h>
#include <dwrite_1.h>
#include <wincodec.h>
#include <wrl/client.h>
namespace Gfx {
// Provides a Direct2D/DirectWrite implementation of Canvas.
class CanvasD2D : public Canvas
{
public:
static bool Initialize();
static void Finalize();
virtual void Resize(int w, int h);
virtual bool BeginDraw();
virtual void EndDraw();
virtual Gdiplus::Graphics& BeginGdiplusContext() override;
virtual void EndGdiplusContext() override;
virtual HDC GetDC() override;
virtual void ReleaseDC(HDC dc) override;
virtual FontCollection* CreateFontCollection() override { return new FontCollectionD2D(); }
virtual TextFormat* CreateTextFormat() override { return new TextFormatD2D(); }
virtual bool IsTransparentPixel(int x, int y) override;
virtual void SetTransform(const Gdiplus::Matrix& matrix) override;
virtual void ResetTransform() override;
virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override;
virtual void SetAntiAliasing(bool enable) override;
virtual void SetTextAntiAliasing(bool enable) override;
virtual void Clear(const Gdiplus::Color& color) override;
virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override;
virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override;
virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override;
virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override;
virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override;
private:
friend class Canvas;
friend class FontCollectionD2D;
friend class TextFormatD2D;
CanvasD2D();
~CanvasD2D();
CanvasD2D(const CanvasD2D& other) = delete;
CanvasD2D& operator=(CanvasD2D other) = delete;
bool BeginTargetDraw();
void EndTargetDraw();
// Sets the |m_Target| transformation to be equal to that of |m_GdipGraphics|.
void UpdateTargetTransform();
Microsoft::WRL::ComPtr<ID2D1RenderTarget> m_Target;
// Underlying pixel data shared by both m_Target and m_GdipBitmap.
Util::WICBitmapDIB m_Bitmap;
// GDI+ objects that share the pixel data of m_Bitmap.
std::unique_ptr<Gdiplus::Graphics> m_GdipGraphics;
std::unique_ptr<Gdiplus::Bitmap> m_GdipBitmap;
bool m_TextAntiAliasing;
// |true| if PushAxisAlignedClip()/PopAxisAlignedClip() can be used.
bool m_CanUseAxisAlignClip;
static UINT c_Instances;
static Microsoft::WRL::ComPtr<ID2D1Factory1> c_D2DFactory;
static Microsoft::WRL::ComPtr<IDWriteFactory1> c_DWFactory;
static Microsoft::WRL::ComPtr<IDWriteGdiInterop> c_DWGDIInterop;
static Microsoft::WRL::ComPtr<IWICImagingFactory> c_WICFactory;
};
} // namespace Gfx
#endif

View File

@ -1,242 +1,242 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "CanvasGDIP.h"
namespace Gfx {
CanvasGDIP::CanvasGDIP() : Canvas(),
m_DIBSection(),
m_DIBSectionPixels()
{
}
CanvasGDIP::~CanvasGDIP()
{
Dispose();
}
void CanvasGDIP::Dispose()
{
if (m_DIBSection)
{
DeleteObject(m_DIBSection);
m_DIBSection = nullptr;
m_DIBSectionPixels = nullptr;
}
}
void CanvasGDIP::Resize(int w, int h)
{
__super::Resize(w, h);
Dispose();
BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)};
bh.bV4Width = w;
bh.bV4Height = -h; // Top-down DIB
bh.bV4Planes = 1;
bh.bV4BitCount = 32;
bh.bV4V4Compression = BI_BITFIELDS;
bh.bV4RedMask = 0x00FF0000;
bh.bV4GreenMask = 0x0000FF00;
bh.bV4BlueMask = 0x000000FF;
bh.bV4AlphaMask = 0xFF000000;
m_DIBSection = CreateDIBSection(
nullptr,
(BITMAPINFO*)&bh,
DIB_RGB_COLORS,
(void**)&m_DIBSectionPixels,
nullptr,
0);
// Create GDI+ bitmap from the DIBSection pixels
m_Bitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, (BYTE*)m_DIBSectionPixels));
m_Graphics.reset(new Gdiplus::Graphics(m_Bitmap.get()));
}
bool CanvasGDIP::BeginDraw()
{
m_Graphics->SetInterpolationMode(Gdiplus::InterpolationModeDefault);
m_Graphics->SetCompositingQuality(Gdiplus::CompositingQualityDefault);
return true;
}
void CanvasGDIP::EndDraw()
{
}
Gdiplus::Graphics& CanvasGDIP::BeginGdiplusContext()
{
return *m_Graphics;
}
void CanvasGDIP::EndGdiplusContext()
{
}
HDC CanvasGDIP::GetDC()
{
HDC dcMemory = CreateCompatibleDC(nullptr);
SelectObject(dcMemory, m_DIBSection);
return dcMemory;
}
void CanvasGDIP::ReleaseDC(HDC dc)
{
DeleteDC(dc);
}
bool CanvasGDIP::IsTransparentPixel(int x, int y)
{
if (m_DIBSectionPixels && x >= 0 && y >= 0 && x < m_W && y < m_H)
{
DWORD pixel = m_DIBSectionPixels[y * m_W + x]; // top-down DIB
return ((pixel & 0xFF000000) != 0);
}
return false;
}
void CanvasGDIP::SetTransform(const Gdiplus::Matrix& matrix)
{
m_Graphics->SetTransform(&matrix);
}
void CanvasGDIP::ResetTransform()
{
m_Graphics->ResetTransform();
}
void CanvasGDIP::RotateTransform(float angle, float x, float y, float dx, float dy)
{
m_Graphics->TranslateTransform(x, y);
m_Graphics->RotateTransform(angle);
m_Graphics->TranslateTransform(dx, dy);
}
void CanvasGDIP::SetAntiAliasing(bool enable)
{
m_Graphics->SetSmoothingMode(
enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone);
m_Graphics->SetPixelOffsetMode(
enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault);
}
void CanvasGDIP::SetTextAntiAliasing(bool enable)
{
m_Graphics->SetTextRenderingHint(
enable ? Gdiplus::TextRenderingHintAntiAlias : Gdiplus::TextRenderingHintSingleBitPerPixelGridFit);
}
void CanvasGDIP::Clear(const Gdiplus::Color& color)
{
if (color.GetValue() == 0x00000000)
{
memset(m_DIBSectionPixels, 0, m_W * m_H * 4);
}
else
{
m_Graphics->Clear(color);
}
}
void CanvasGDIP::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush)
{
Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
if (m_AccurateText)
{
tStringFormat.SetTrimming(stringFormat.GetTrimming());
tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
tStringFormat.SetAlignment(stringFormat.GetAlignment());
tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
}
m_Graphics->DrawString(
str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
m_AccurateText ? &tStringFormat : &stringFormat, &brush);
}
bool CanvasGDIP::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect)
{
Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
if (m_AccurateText)
{
tStringFormat.SetTrimming(stringFormat.GetTrimming());
tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
tStringFormat.SetAlignment(stringFormat.GetAlignment());
tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
}
const Gdiplus::Status status = m_Graphics->MeasureString(
str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
m_AccurateText ? &tStringFormat : &stringFormat, &rect);
return status == Gdiplus::Ok;
}
bool CanvasGDIP::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines)
{
Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
// Set trimming and format temporarily.
const Gdiplus::StringTrimming stringTrimming = stringFormat.GetTrimming();
stringFormat.SetTrimming(Gdiplus::StringTrimmingNone);
const INT stringFormatFlags = stringFormat.GetFormatFlags();
stringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip);
if (m_AccurateText)
{
tStringFormat.SetTrimming(stringFormat.GetTrimming());
tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
tStringFormat.SetAlignment(stringFormat.GetAlignment());
tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
}
INT linesFilled = 0;
const Gdiplus::Status status = m_Graphics->MeasureString(
str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
m_AccurateText ? &tStringFormat : &stringFormat, &rect, nullptr, &linesFilled);
lines = linesFilled;
// Restore old options.
stringFormat.SetTrimming(stringTrimming);
stringFormat.SetFormatFlags(stringFormatFlags);
return status == Gdiplus::Ok;
}
void CanvasGDIP::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect)
{
m_Graphics->DrawImage(bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel);
}
void CanvasGDIP::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush)
{
m_Graphics->FillRectangle(&brush, rect);
}
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "CanvasGDIP.h"
namespace Gfx {
CanvasGDIP::CanvasGDIP() : Canvas(),
m_DIBSection(),
m_DIBSectionPixels()
{
}
CanvasGDIP::~CanvasGDIP()
{
Dispose();
}
void CanvasGDIP::Dispose()
{
if (m_DIBSection)
{
DeleteObject(m_DIBSection);
m_DIBSection = nullptr;
m_DIBSectionPixels = nullptr;
}
}
void CanvasGDIP::Resize(int w, int h)
{
__super::Resize(w, h);
Dispose();
BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)};
bh.bV4Width = w;
bh.bV4Height = -h; // Top-down DIB
bh.bV4Planes = 1;
bh.bV4BitCount = 32;
bh.bV4V4Compression = BI_BITFIELDS;
bh.bV4RedMask = 0x00FF0000;
bh.bV4GreenMask = 0x0000FF00;
bh.bV4BlueMask = 0x000000FF;
bh.bV4AlphaMask = 0xFF000000;
m_DIBSection = CreateDIBSection(
nullptr,
(BITMAPINFO*)&bh,
DIB_RGB_COLORS,
(void**)&m_DIBSectionPixels,
nullptr,
0);
// Create GDI+ bitmap from the DIBSection pixels
m_Bitmap.reset(new Gdiplus::Bitmap(w, h, w * 4, PixelFormat32bppPARGB, (BYTE*)m_DIBSectionPixels));
m_Graphics.reset(new Gdiplus::Graphics(m_Bitmap.get()));
}
bool CanvasGDIP::BeginDraw()
{
m_Graphics->SetInterpolationMode(Gdiplus::InterpolationModeDefault);
m_Graphics->SetCompositingQuality(Gdiplus::CompositingQualityDefault);
return true;
}
void CanvasGDIP::EndDraw()
{
}
Gdiplus::Graphics& CanvasGDIP::BeginGdiplusContext()
{
return *m_Graphics;
}
void CanvasGDIP::EndGdiplusContext()
{
}
HDC CanvasGDIP::GetDC()
{
HDC dcMemory = CreateCompatibleDC(nullptr);
SelectObject(dcMemory, m_DIBSection);
return dcMemory;
}
void CanvasGDIP::ReleaseDC(HDC dc)
{
DeleteDC(dc);
}
bool CanvasGDIP::IsTransparentPixel(int x, int y)
{
if (m_DIBSectionPixels && x >= 0 && y >= 0 && x < m_W && y < m_H)
{
DWORD pixel = m_DIBSectionPixels[y * m_W + x]; // top-down DIB
return ((pixel & 0xFF000000) != 0);
}
return false;
}
void CanvasGDIP::SetTransform(const Gdiplus::Matrix& matrix)
{
m_Graphics->SetTransform(&matrix);
}
void CanvasGDIP::ResetTransform()
{
m_Graphics->ResetTransform();
}
void CanvasGDIP::RotateTransform(float angle, float x, float y, float dx, float dy)
{
m_Graphics->TranslateTransform(x, y);
m_Graphics->RotateTransform(angle);
m_Graphics->TranslateTransform(dx, dy);
}
void CanvasGDIP::SetAntiAliasing(bool enable)
{
m_Graphics->SetSmoothingMode(
enable ? Gdiplus::SmoothingModeHighQuality : Gdiplus::SmoothingModeNone);
m_Graphics->SetPixelOffsetMode(
enable ? Gdiplus::PixelOffsetModeHighQuality : Gdiplus::PixelOffsetModeDefault);
}
void CanvasGDIP::SetTextAntiAliasing(bool enable)
{
m_Graphics->SetTextRenderingHint(
enable ? Gdiplus::TextRenderingHintAntiAlias : Gdiplus::TextRenderingHintSingleBitPerPixelGridFit);
}
void CanvasGDIP::Clear(const Gdiplus::Color& color)
{
if (color.GetValue() == 0x00000000)
{
memset(m_DIBSectionPixels, 0, m_W * m_H * 4);
}
else
{
m_Graphics->Clear(color);
}
}
void CanvasGDIP::DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush)
{
Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
if (m_AccurateText)
{
tStringFormat.SetTrimming(stringFormat.GetTrimming());
tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
tStringFormat.SetAlignment(stringFormat.GetAlignment());
tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
}
m_Graphics->DrawString(
str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
m_AccurateText ? &tStringFormat : &stringFormat, &brush);
}
bool CanvasGDIP::MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect)
{
Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
if (m_AccurateText)
{
tStringFormat.SetTrimming(stringFormat.GetTrimming());
tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
tStringFormat.SetAlignment(stringFormat.GetAlignment());
tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
}
const Gdiplus::Status status = m_Graphics->MeasureString(
str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
m_AccurateText ? &tStringFormat : &stringFormat, &rect);
return status == Gdiplus::Ok;
}
bool CanvasGDIP::MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines)
{
Gdiplus::StringFormat& stringFormat = ((TextFormatGDIP&)format).m_StringFormat;
Gdiplus::StringFormat tStringFormat = Gdiplus::StringFormat::GenericTypographic();
// Set trimming and format temporarily.
const Gdiplus::StringTrimming stringTrimming = stringFormat.GetTrimming();
stringFormat.SetTrimming(Gdiplus::StringTrimmingNone);
const INT stringFormatFlags = stringFormat.GetFormatFlags();
stringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip);
if (m_AccurateText)
{
tStringFormat.SetTrimming(stringFormat.GetTrimming());
tStringFormat.SetFormatFlags(stringFormat.GetFormatFlags());
tStringFormat.SetAlignment(stringFormat.GetAlignment());
tStringFormat.SetLineAlignment(stringFormat.GetLineAlignment());
}
INT linesFilled = 0;
const Gdiplus::Status status = m_Graphics->MeasureString(
str, (INT)strLen, ((TextFormatGDIP&)format).m_Font.get(), rect,
m_AccurateText ? &tStringFormat : &stringFormat, &rect, nullptr, &linesFilled);
lines = linesFilled;
// Restore old options.
stringFormat.SetTrimming(stringTrimming);
stringFormat.SetFormatFlags(stringFormatFlags);
return status == Gdiplus::Ok;
}
void CanvasGDIP::DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect)
{
m_Graphics->DrawImage(bitmap, dstRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, Gdiplus::UnitPixel);
}
void CanvasGDIP::FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush)
{
m_Graphics->FillRectangle(&brush, rect);
}
} // namespace Gfx

View File

@ -1,90 +1,90 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_CANVASGDIP_H_
#define RM_GFX_CANVASGDIP_H_
#include "Canvas.h"
#include "FontCollectionGDIP.h"
#include "TextFormatGDIP.h"
#include <memory>
#include <string>
#include <ole2.h> // For Gdiplus.h.
#include <GdiPlus.h>
namespace Gfx {
// Provides a GDI+ implementation of Canvas.
class CanvasGDIP : public Canvas
{
public:
virtual void Resize(int w, int h);
virtual bool BeginDraw();
virtual void EndDraw();
virtual Gdiplus::Graphics& BeginGdiplusContext() override;
virtual void EndGdiplusContext() override;
virtual HDC GetDC() override;
virtual void ReleaseDC(HDC dc) override;
virtual FontCollection* CreateFontCollection() override { return new FontCollectionGDIP(); }
virtual TextFormat* CreateTextFormat() override { return new TextFormatGDIP(); }
virtual bool IsTransparentPixel(int x, int y) override;
virtual void SetTransform(const Gdiplus::Matrix& matrix) override;
virtual void ResetTransform() override;
virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override;
virtual void SetAntiAliasing(bool enable) override;
virtual void SetTextAntiAliasing(bool enable) override;
virtual void Clear(const Gdiplus::Color& color) override;
virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override;
virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override;
virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override;
virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override;
virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override;
private:
friend class Canvas;
CanvasGDIP();
~CanvasGDIP();
CanvasGDIP(const CanvasGDIP& other) = delete;
CanvasGDIP& operator=(CanvasGDIP other) = delete;
void Dispose();
std::unique_ptr<Gdiplus::Graphics> m_Graphics;
std::unique_ptr<Gdiplus::Bitmap> m_Bitmap;
HBITMAP m_DIBSection;
LPDWORD m_DIBSectionPixels;
//static ULONG_PTR c_GdiToken;
};
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_CANVASGDIP_H_
#define RM_GFX_CANVASGDIP_H_
#include "Canvas.h"
#include "FontCollectionGDIP.h"
#include "TextFormatGDIP.h"
#include <memory>
#include <string>
#include <ole2.h> // For Gdiplus.h.
#include <GdiPlus.h>
namespace Gfx {
// Provides a GDI+ implementation of Canvas.
class CanvasGDIP : public Canvas
{
public:
virtual void Resize(int w, int h);
virtual bool BeginDraw();
virtual void EndDraw();
virtual Gdiplus::Graphics& BeginGdiplusContext() override;
virtual void EndGdiplusContext() override;
virtual HDC GetDC() override;
virtual void ReleaseDC(HDC dc) override;
virtual FontCollection* CreateFontCollection() override { return new FontCollectionGDIP(); }
virtual TextFormat* CreateTextFormat() override { return new TextFormatGDIP(); }
virtual bool IsTransparentPixel(int x, int y) override;
virtual void SetTransform(const Gdiplus::Matrix& matrix) override;
virtual void ResetTransform() override;
virtual void RotateTransform(float angle, float x, float y, float dx, float dy) override;
virtual void SetAntiAliasing(bool enable) override;
virtual void SetTextAntiAliasing(bool enable) override;
virtual void Clear(const Gdiplus::Color& color) override;
virtual void DrawTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, const Gdiplus::SolidBrush& brush) override;
virtual bool MeasureTextW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect) override;
virtual bool MeasureTextLinesW(const WCHAR* str, UINT strLen, const TextFormat& format, Gdiplus::RectF& rect, UINT& lines) override;
virtual void DrawBitmap(Gdiplus::Bitmap* bitmap, const Gdiplus::Rect& dstRect, const Gdiplus::Rect& srcRect) override;
virtual void FillRectangle(Gdiplus::Rect& rect, const Gdiplus::SolidBrush& brush) override;
private:
friend class Canvas;
CanvasGDIP();
~CanvasGDIP();
CanvasGDIP(const CanvasGDIP& other) = delete;
CanvasGDIP& operator=(CanvasGDIP other) = delete;
void Dispose();
std::unique_ptr<Gdiplus::Graphics> m_Graphics;
std::unique_ptr<Gdiplus::Bitmap> m_Bitmap;
HBITMAP m_DIBSection;
LPDWORD m_DIBSectionPixels;
//static ULONG_PTR c_GdiToken;
};
} // namespace Gfx
#endif

View File

@ -1,32 +1,32 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "FontCollection.h"
namespace Gfx {
FontCollection::FontCollection()
{
}
FontCollection::~FontCollection()
{
}
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "FontCollection.h"
namespace Gfx {
FontCollection::FontCollection()
{
}
FontCollection::~FontCollection()
{
}
} // namespace Gfx

View File

@ -1,43 +1,43 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_FONTCOLLECTION_H_
#define RM_GFX_FONTCOLLECTION_H_
#include <Windows.h>
namespace Gfx {
// Interface for a collection of fonts that may or may not be installed on the system.
class __declspec(novtable) FontCollection
{
public:
virtual ~FontCollection();
FontCollection(const FontCollection& other) = delete;
// Adds a file to the collection. Returns true if the file was successfully added.
virtual bool AddFile(const WCHAR* file) = 0;
protected:
FontCollection();
};
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_FONTCOLLECTION_H_
#define RM_GFX_FONTCOLLECTION_H_
#include <Windows.h>
namespace Gfx {
// Interface for a collection of fonts that may or may not be installed on the system.
class __declspec(novtable) FontCollection
{
public:
virtual ~FontCollection();
FontCollection(const FontCollection& other) = delete;
// Adds a file to the collection. Returns true if the file was successfully added.
virtual bool AddFile(const WCHAR* file) = 0;
protected:
FontCollection();
};
} // namespace Gfx
#endif

View File

@ -1,79 +1,79 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "FontCollectionD2D.h"
#include "CanvasD2D.h"
#include "Util/DWriteFontCollectionLoader.h"
namespace Gfx {
FontCollectionD2D::FontCollectionD2D() : FontCollection(),
m_Collection()
{
}
FontCollectionD2D::~FontCollectionD2D()
{
Dispose();
}
void FontCollectionD2D::Dispose()
{
for (IDWriteFontFile* fileReference : m_FileReferences)
{
fileReference->Release();
}
m_FileReferences.clear();
}
bool FontCollectionD2D::InitializeCollection()
{
if (!m_Collection)
{
auto loader = Util::DWriteFontCollectionLoader::GetInstance();
CanvasD2D::c_DWFactory->CreateCustomFontCollection(
loader, &m_FileReferences, sizeof(m_FileReferences), &m_Collection);
}
return m_Collection != nullptr;
}
bool FontCollectionD2D::AddFile(const WCHAR* file)
{
// If DirecWrite font collection already exists, we need to destroy it as fonts cannot be added to
// an existing collection. The collection will be recreated on the next call to
// InitializeCollection().
if (m_Collection)
{
m_Collection->Release();
m_Collection = nullptr;
}
IDWriteFontFile* fileReference;
HRESULT hr = CanvasD2D::c_DWFactory->CreateFontFileReference(file, nullptr, &fileReference);
if (SUCCEEDED(hr))
{
m_FileReferences.push_back(fileReference);
return true;
}
return false;
}
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "FontCollectionD2D.h"
#include "CanvasD2D.h"
#include "Util/DWriteFontCollectionLoader.h"
namespace Gfx {
FontCollectionD2D::FontCollectionD2D() : FontCollection(),
m_Collection()
{
}
FontCollectionD2D::~FontCollectionD2D()
{
Dispose();
}
void FontCollectionD2D::Dispose()
{
for (IDWriteFontFile* fileReference : m_FileReferences)
{
fileReference->Release();
}
m_FileReferences.clear();
}
bool FontCollectionD2D::InitializeCollection()
{
if (!m_Collection)
{
auto loader = Util::DWriteFontCollectionLoader::GetInstance();
CanvasD2D::c_DWFactory->CreateCustomFontCollection(
loader, &m_FileReferences, sizeof(m_FileReferences), &m_Collection);
}
return m_Collection != nullptr;
}
bool FontCollectionD2D::AddFile(const WCHAR* file)
{
// If DirecWrite font collection already exists, we need to destroy it as fonts cannot be added to
// an existing collection. The collection will be recreated on the next call to
// InitializeCollection().
if (m_Collection)
{
m_Collection->Release();
m_Collection = nullptr;
}
IDWriteFontFile* fileReference;
HRESULT hr = CanvasD2D::c_DWFactory->CreateFontFileReference(file, nullptr, &fileReference);
if (SUCCEEDED(hr))
{
m_FileReferences.push_back(fileReference);
return true;
}
return false;
}
} // namespace Gfx

View File

@ -1,56 +1,56 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_FONTCOLLECTIOND2D_H_
#define RM_GFX_FONTCOLLECTIOND2D_H_
#include "FontCollection.h"
#include <vector>
#include <dwrite_1.h>
namespace Gfx {
// Wraps the DirectWrite IDWriteFontCollection for use with CanvasD2D.
class FontCollectionD2D final : public FontCollection
{
public:
virtual ~FontCollectionD2D();
FontCollectionD2D(const FontCollectionD2D& other) = delete;
FontCollectionD2D& operator=(FontCollectionD2D other) = delete;
virtual bool AddFile(const WCHAR* file) override;
protected:
FontCollectionD2D();
private:
friend class CanvasD2D;
friend class TextFormatD2D;
void Dispose();
bool InitializeCollection();
std::vector<IDWriteFontFile*> m_FileReferences;
IDWriteFontCollection* m_Collection;
};
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_FONTCOLLECTIOND2D_H_
#define RM_GFX_FONTCOLLECTIOND2D_H_
#include "FontCollection.h"
#include <vector>
#include <dwrite_1.h>
namespace Gfx {
// Wraps the DirectWrite IDWriteFontCollection for use with CanvasD2D.
class FontCollectionD2D final : public FontCollection
{
public:
virtual ~FontCollectionD2D();
FontCollectionD2D(const FontCollectionD2D& other) = delete;
FontCollectionD2D& operator=(FontCollectionD2D other) = delete;
virtual bool AddFile(const WCHAR* file) override;
protected:
FontCollectionD2D();
private:
friend class CanvasD2D;
friend class TextFormatD2D;
void Dispose();
bool InitializeCollection();
std::vector<IDWriteFontFile*> m_FileReferences;
IDWriteFontCollection* m_Collection;
};
} // namespace Gfx
#endif

View File

@ -1,54 +1,54 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "FontCollectionGDIP.h"
namespace Gfx {
FontCollectionGDIP::FontCollectionGDIP() : FontCollection(),
m_PrivateCollection()
{
}
FontCollectionGDIP::~FontCollectionGDIP()
{
Dispose();
}
void FontCollectionGDIP::Dispose()
{
if (m_PrivateCollection)
{
delete m_PrivateCollection;
m_PrivateCollection = nullptr;
}
}
bool FontCollectionGDIP::AddFile(const WCHAR* file)
{
if (!m_PrivateCollection)
{
m_PrivateCollection = new Gdiplus::PrivateFontCollection();
}
const Gdiplus::Status status = m_PrivateCollection->AddFontFile(file);
return status == Gdiplus::Ok;
}
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "FontCollectionGDIP.h"
namespace Gfx {
FontCollectionGDIP::FontCollectionGDIP() : FontCollection(),
m_PrivateCollection()
{
}
FontCollectionGDIP::~FontCollectionGDIP()
{
Dispose();
}
void FontCollectionGDIP::Dispose()
{
if (m_PrivateCollection)
{
delete m_PrivateCollection;
m_PrivateCollection = nullptr;
}
}
bool FontCollectionGDIP::AddFile(const WCHAR* file)
{
if (!m_PrivateCollection)
{
m_PrivateCollection = new Gdiplus::PrivateFontCollection();
}
const Gdiplus::Status status = m_PrivateCollection->AddFontFile(file);
return status == Gdiplus::Ok;
}
} // namespace Gfx

View File

@ -1,55 +1,55 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_FONTCOLLECTIONGDIP_H_
#define RM_GFX_FONTCOLLECTIONGDIP_H_
#include "FontCollection.h"
namespace Gdiplus {
class PrivateFontCollection;
}
namespace Gfx {
// Wraps the GDI+ PrivateFontCollection for use with CanvasGDIP.
class FontCollectionGDIP final : public FontCollection
{
public:
virtual ~FontCollectionGDIP();
FontCollectionGDIP(const FontCollectionGDIP& other) = delete;
FontCollectionGDIP& operator=(FontCollectionGDIP other) = delete;
virtual bool AddFile(const WCHAR* file) override;
protected:
FontCollectionGDIP();
private:
friend class CanvasGDIP;
friend class TextFormatGDIP;
void Dispose();
Gdiplus::PrivateFontCollection* m_PrivateCollection;
};
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_FONTCOLLECTIONGDIP_H_
#define RM_GFX_FONTCOLLECTIONGDIP_H_
#include "FontCollection.h"
namespace Gdiplus {
class PrivateFontCollection;
}
namespace Gfx {
// Wraps the GDI+ PrivateFontCollection for use with CanvasGDIP.
class FontCollectionGDIP final : public FontCollection
{
public:
virtual ~FontCollectionGDIP();
FontCollectionGDIP(const FontCollectionGDIP& other) = delete;
FontCollectionGDIP& operator=(FontCollectionGDIP other) = delete;
virtual bool AddFile(const WCHAR* file) override;
protected:
FontCollectionGDIP();
private:
friend class CanvasGDIP;
friend class TextFormatGDIP;
void Dispose();
Gdiplus::PrivateFontCollection* m_PrivateCollection;
};
} // namespace Gfx
#endif

View File

@ -1,44 +1,44 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "TextFormat.h"
namespace Gfx {
TextFormat::TextFormat() :
m_HorizontalAlignment(HorizontalAlignment::Left),
m_VerticalAlignment(VerticalAlignment::Top)
{
}
TextFormat::~TextFormat()
{
}
void TextFormat::SetHorizontalAlignment(HorizontalAlignment alignment)
{
m_HorizontalAlignment = alignment;
}
void TextFormat::SetVerticalAlignment(VerticalAlignment alignment)
{
m_VerticalAlignment = alignment;
}
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "TextFormat.h"
namespace Gfx {
TextFormat::TextFormat() :
m_HorizontalAlignment(HorizontalAlignment::Left),
m_VerticalAlignment(VerticalAlignment::Top)
{
}
TextFormat::~TextFormat()
{
}
void TextFormat::SetHorizontalAlignment(HorizontalAlignment alignment)
{
m_HorizontalAlignment = alignment;
}
void TextFormat::SetVerticalAlignment(VerticalAlignment alignment)
{
m_VerticalAlignment = alignment;
}
} // namespace Gfx

View File

@ -1,80 +1,80 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_TEXTFORMAT_H_
#define RM_GFX_TEXTFORMAT_H_
#include <Windows.h>
namespace Gfx {
class FontCollection;
enum class HorizontalAlignment : BYTE
{
Left,
Center,
Right
};
enum class VerticalAlignment : BYTE
{
Top,
Center,
Bottom
};
// Represents the logical font properties used to format text.
class __declspec(novtable) TextFormat
{
public:
virtual ~TextFormat();
TextFormat(const TextFormat& other) = delete;
// Returns true if this TextFormat object is valid for use in draw operations.
virtual bool IsInitialized() const = 0;
// Sets the logical properties of the font to use. If the font is not found in the system font
// collection, the given |fontCollection| is also searched. |fontCollection| may be nullptr.
virtual void SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection) = 0;
// Sets the trimming and wrapping of the text. If |trim| is true, subsequent draws using this
// TextFormat object will produce clipped text with an ellipsis if the text overflows the
// bounding rectangle.
virtual void SetTrimming(bool trim) = 0;
virtual void SetHorizontalAlignment(HorizontalAlignment alignment);
HorizontalAlignment GetHorizontalAlignment() const { return m_HorizontalAlignment; }
virtual void SetVerticalAlignment(VerticalAlignment alignment);
VerticalAlignment GetVerticalAlignment() const { return m_VerticalAlignment; }
protected:
TextFormat();
private:
HorizontalAlignment m_HorizontalAlignment;
VerticalAlignment m_VerticalAlignment;
};
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_TEXTFORMAT_H_
#define RM_GFX_TEXTFORMAT_H_
#include <Windows.h>
namespace Gfx {
class FontCollection;
enum class HorizontalAlignment : BYTE
{
Left,
Center,
Right
};
enum class VerticalAlignment : BYTE
{
Top,
Center,
Bottom
};
// Represents the logical font properties used to format text.
class __declspec(novtable) TextFormat
{
public:
virtual ~TextFormat();
TextFormat(const TextFormat& other) = delete;
// Returns true if this TextFormat object is valid for use in draw operations.
virtual bool IsInitialized() const = 0;
// Sets the logical properties of the font to use. If the font is not found in the system font
// collection, the given |fontCollection| is also searched. |fontCollection| may be nullptr.
virtual void SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection) = 0;
// Sets the trimming and wrapping of the text. If |trim| is true, subsequent draws using this
// TextFormat object will produce clipped text with an ellipsis if the text overflows the
// bounding rectangle.
virtual void SetTrimming(bool trim) = 0;
virtual void SetHorizontalAlignment(HorizontalAlignment alignment);
HorizontalAlignment GetHorizontalAlignment() const { return m_HorizontalAlignment; }
virtual void SetVerticalAlignment(VerticalAlignment alignment);
VerticalAlignment GetVerticalAlignment() const { return m_VerticalAlignment; }
protected:
TextFormat();
private:
HorizontalAlignment m_HorizontalAlignment;
VerticalAlignment m_VerticalAlignment;
};
} // namespace Gfx
#endif

View File

@ -1,367 +1,367 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "TextFormatD2D.h"
#include "CanvasD2D.h"
#include "Util/DWriteHelpers.h"
namespace Gfx {
TextFormatD2D::TextFormatD2D() :
m_ExtraHeight(),
m_LineGap(),
m_Trimming()
{
}
TextFormatD2D::~TextFormatD2D()
{
}
void TextFormatD2D::Dispose()
{
m_TextFormat.Reset();
m_TextLayout.Reset();
m_InlineEllipsis.Reset();
m_ExtraHeight = 0.0f;
m_LineGap = 0.0f;
}
bool TextFormatD2D::CreateLayout(
const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation)
{
bool strChanged = false;
if (strLen != m_LastString.length() ||
memcmp(str, m_LastString.c_str(), (strLen + 1) * sizeof(WCHAR)) != 0)
{
strChanged = true;
m_LastString.assign(str, strLen);
}
// The width and height of a DirectWrite layout must be non-negative.
maxW = max(0.0f, maxW);
maxH = max(0.0f, maxH);
if (m_Trimming)
{
// GDI+ compatibility: If we trimming (i.e. clipping), GDI+ draws text lines even if they
// would be clipped. This is arguably a bad 'feature', but some in some cases the height
// might be just a pixel or two too small. In order to render those cases correctly (but
// still clipped as CanvasD2D::DrawTextW() will clip), we'll increase the max height of
// the layout.
maxH += 2.0f;
}
if (m_TextLayout && !strChanged)
{
if (maxW != m_TextLayout->GetMaxWidth())
{
m_TextLayout->SetMaxWidth(maxW);
}
if (maxH != m_TextLayout->GetMaxHeight())
{
m_TextLayout->SetMaxHeight(maxH);
}
}
else
{
CanvasD2D::c_DWFactory->CreateTextLayout(
str, strLen, m_TextFormat.Get(), maxW, maxH, m_TextLayout.ReleaseAndGetAddressOf());
if (!m_TextLayout) return false;
if (gdiEmulation)
{
Microsoft::WRL::ComPtr<IDWriteTextLayout1> textLayout1;
m_TextLayout.As(&textLayout1);
const float xOffset = m_TextFormat->GetFontSize() / 6.0f;
const float emOffset = xOffset / 24.0f;
const DWRITE_TEXT_RANGE range = {0, strLen};
textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range);
}
UINT32 lineCount = 0;
DWRITE_LINE_METRICS lineMetrics[2];
HRESULT hr = m_TextLayout->GetLineMetrics(lineMetrics, _countof(lineMetrics), &lineCount);
if (SUCCEEDED(hr))
{
// If only one line is visible, disable wrapping so that as much text as possible is shown
// after trimming.
// TODO: Fix this for when more than one line is visible.
if (lineCount >= 2 &&
lineMetrics[0].isTrimmed &&
lineMetrics[1].isTrimmed &&
lineMetrics[1].height == 0.0f)
{
m_TextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
}
}
}
return true;
}
void TextFormatD2D::SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection)
{
auto fontCollectionD2D = (FontCollectionD2D*)fontCollection;
Dispose();
WCHAR dwriteFamilyName[LF_FACESIZE];
DWRITE_FONT_WEIGHT dwriteFontWeight =
bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR;
DWRITE_FONT_STYLE dwriteFontStyle =
italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
DWRITE_FONT_STRETCH dwriteFontStretch = DWRITE_FONT_STRETCH_NORMAL;
const float dwriteFontSize = size * (4.0f / 3.0f);
// |fontFamily| uses the GDI/GDI+ font naming convention so try to create DirectWrite font
// using the GDI family name and then create a text format using the DirectWrite family name
// obtained from it.
HRESULT hr = Util::GetDWritePropertiesFromGDIProperties(
CanvasD2D::c_DWFactory.Get(), fontFamily, bold, italic, dwriteFontWeight, dwriteFontStyle,
dwriteFontStretch, dwriteFamilyName, _countof(dwriteFamilyName));
if (SUCCEEDED(hr))
{
hr = CanvasD2D::c_DWFactory->CreateTextFormat(
dwriteFamilyName,
nullptr,
dwriteFontWeight,
dwriteFontStyle,
dwriteFontStretch,
dwriteFontSize,
L"",
&m_TextFormat);
}
if (FAILED(hr))
{
IDWriteFontCollection* dwriteFontCollection = nullptr;
// If |fontFamily| is not in the system collection, use the font collection from
// |fontCollectionD2D| if possible.
if (!Util::IsFamilyInSystemFontCollection(CanvasD2D::c_DWFactory.Get(), fontFamily) &&
(fontCollectionD2D && fontCollectionD2D->InitializeCollection()))
{
IDWriteFont* dwriteFont = Util::FindDWriteFontInFontCollectionByGDIFamilyName(
fontCollectionD2D->m_Collection, fontFamily);
if (dwriteFont)
{
hr = Util::GetFamilyNameFromDWriteFont(
dwriteFont, dwriteFamilyName, _countof(dwriteFamilyName));
if (SUCCEEDED(hr))
{
fontFamily = dwriteFamilyName;
Util::GetPropertiesFromDWriteFont(
dwriteFont, bold, italic, &dwriteFontWeight, &dwriteFontStyle,
&dwriteFontStretch);
}
dwriteFont->Release();
}
dwriteFontCollection = fontCollectionD2D->m_Collection;
}
// Fallback in case above fails.
hr = CanvasD2D::c_DWFactory->CreateTextFormat(
fontFamily,
dwriteFontCollection,
dwriteFontWeight,
dwriteFontStyle,
dwriteFontStretch,
dwriteFontSize,
L"",
&m_TextFormat);
}
if (SUCCEEDED(hr))
{
SetHorizontalAlignment(GetHorizontalAlignment());
SetVerticalAlignment(GetVerticalAlignment());
// Get the family name to in case CreateTextFormat() fallbacked on some other family name.
hr = m_TextFormat->GetFontFamilyName(dwriteFamilyName, _countof(dwriteFamilyName));
if (FAILED(hr)) return;
Microsoft::WRL::ComPtr<IDWriteFontCollection> collection;
Microsoft::WRL::ComPtr<IDWriteFontFamily> fontFamily;
UINT32 familyNameIndex;
BOOL exists;
if (FAILED(m_TextFormat->GetFontCollection(collection.GetAddressOf())) ||
FAILED(collection->FindFamilyName(dwriteFamilyName, &familyNameIndex, &exists)) ||
FAILED(collection->GetFontFamily(familyNameIndex, fontFamily.GetAddressOf())))
{
return;
}
Microsoft::WRL::ComPtr<IDWriteFont> font;
hr = fontFamily->GetFirstMatchingFont(
m_TextFormat->GetFontWeight(),
m_TextFormat->GetFontStretch(),
m_TextFormat->GetFontStyle(),
font.GetAddressOf());
if (FAILED(hr)) return;
DWRITE_FONT_METRICS fmetrics;
font->GetMetrics(&fmetrics);
// GDI+ compatibility: GDI+ adds extra padding below the string when |m_AccurateText| is
// |false|. The bottom padding seems to be based on the font metrics so we can calculate it
// once and keep using it regardless of the actual string. In some cases, GDI+ also adds
// the line gap to the overall height so we will store it as well.
const float pixelsPerDesignUnit = dwriteFontSize / (float)fmetrics.designUnitsPerEm;
m_ExtraHeight =
(((float)fmetrics.designUnitsPerEm / 8.0f) - fmetrics.lineGap) * pixelsPerDesignUnit;
m_LineGap = fmetrics.lineGap * pixelsPerDesignUnit;
}
else
{
Dispose();
}
}
DWRITE_TEXT_METRICS TextFormatD2D::GetMetrics(
const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth)
{
// GDI+ compatibility: If the last character is a newline, GDI+ measurements seem to ignore it.
bool strippedLastNewLine = false;
if (strLen > 2 && str[strLen - 1] == L'\n')
{
strippedLastNewLine = true;
--strLen;
if (str[strLen - 1] == L'\r')
{
--strLen;
}
}
DWRITE_TEXT_METRICS metrics = {0};
Microsoft::WRL::ComPtr<IDWriteTextLayout> textLayout;
HRESULT hr = CanvasD2D::c_DWFactory->CreateTextLayout(
str,
strLen,
m_TextFormat.Get(),
maxWidth,
10000,
textLayout.GetAddressOf());
if (SUCCEEDED(hr))
{
const float xOffset = m_TextFormat->GetFontSize() / 6.0f;
if (gdiEmulation)
{
Microsoft::WRL::ComPtr<IDWriteTextLayout1> textLayout1;
textLayout.As(&textLayout1);
const float emOffset = xOffset / 24.0f;
const DWRITE_TEXT_RANGE range = {0, strLen};
textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range);
}
textLayout->GetMetrics(&metrics);
if (metrics.width > 0.0f)
{
if (gdiEmulation)
{
metrics.width += xOffset * 2;
metrics.height += m_ExtraHeight;
// GDI+ compatibility: If the string contains a newline (even if it is the
// stripped last character), GDI+ adds the line gap to the overall height.
if (strippedLastNewLine || wmemchr(str, L'\n', strLen) != nullptr)
{
metrics.height += m_LineGap;
}
}
else
{
// GDI+ compatibility: With accurate metrics, the line gap needs to be subtracted
// from the overall height if the string does not contain newlines.
if (!strippedLastNewLine && wmemchr(str, L'\n', strLen) == nullptr)
{
metrics.height -= m_LineGap;
}
}
}
else
{
// GDI+ compatibility: Get rid of the height that DirectWrite assigns to zero-width
// strings.
metrics.height = 0.0f;
}
}
return metrics;
}
void TextFormatD2D::SetTrimming(bool trim)
{
m_Trimming = trim;
IDWriteInlineObject* inlineObject = nullptr;
DWRITE_TRIMMING trimming = {};
DWRITE_WORD_WRAPPING wordWrapping = DWRITE_WORD_WRAPPING_NO_WRAP;
if (trim)
{
if (!m_InlineEllipsis)
{
CanvasD2D::c_DWFactory->CreateEllipsisTrimmingSign(
m_TextFormat.Get(), m_InlineEllipsis.GetAddressOf());
}
inlineObject = m_InlineEllipsis.Get();
trimming.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER;
wordWrapping = DWRITE_WORD_WRAPPING_WRAP;
}
m_TextFormat->SetTrimming(&trimming, inlineObject);
m_TextFormat->SetWordWrapping(wordWrapping);
}
void TextFormatD2D::SetHorizontalAlignment(HorizontalAlignment alignment)
{
__super::SetHorizontalAlignment(alignment);
if (m_TextFormat)
{
m_TextFormat->SetTextAlignment(
(alignment == HorizontalAlignment::Left) ? DWRITE_TEXT_ALIGNMENT_LEADING :
(alignment == HorizontalAlignment::Center) ? DWRITE_TEXT_ALIGNMENT_CENTER :
DWRITE_TEXT_ALIGNMENT_TRAILING);
}
}
void TextFormatD2D::SetVerticalAlignment(VerticalAlignment alignment)
{
__super::SetVerticalAlignment(alignment);
if (m_TextFormat)
{
m_TextFormat->SetParagraphAlignment(
(alignment == VerticalAlignment::Top) ? DWRITE_PARAGRAPH_ALIGNMENT_NEAR :
(alignment == VerticalAlignment::Center) ? DWRITE_PARAGRAPH_ALIGNMENT_CENTER :
DWRITE_PARAGRAPH_ALIGNMENT_FAR);
}
}
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "TextFormatD2D.h"
#include "CanvasD2D.h"
#include "Util/DWriteHelpers.h"
namespace Gfx {
TextFormatD2D::TextFormatD2D() :
m_ExtraHeight(),
m_LineGap(),
m_Trimming()
{
}
TextFormatD2D::~TextFormatD2D()
{
}
void TextFormatD2D::Dispose()
{
m_TextFormat.Reset();
m_TextLayout.Reset();
m_InlineEllipsis.Reset();
m_ExtraHeight = 0.0f;
m_LineGap = 0.0f;
}
bool TextFormatD2D::CreateLayout(
const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation)
{
bool strChanged = false;
if (strLen != m_LastString.length() ||
memcmp(str, m_LastString.c_str(), (strLen + 1) * sizeof(WCHAR)) != 0)
{
strChanged = true;
m_LastString.assign(str, strLen);
}
// The width and height of a DirectWrite layout must be non-negative.
maxW = max(0.0f, maxW);
maxH = max(0.0f, maxH);
if (m_Trimming)
{
// GDI+ compatibility: If we trimming (i.e. clipping), GDI+ draws text lines even if they
// would be clipped. This is arguably a bad 'feature', but some in some cases the height
// might be just a pixel or two too small. In order to render those cases correctly (but
// still clipped as CanvasD2D::DrawTextW() will clip), we'll increase the max height of
// the layout.
maxH += 2.0f;
}
if (m_TextLayout && !strChanged)
{
if (maxW != m_TextLayout->GetMaxWidth())
{
m_TextLayout->SetMaxWidth(maxW);
}
if (maxH != m_TextLayout->GetMaxHeight())
{
m_TextLayout->SetMaxHeight(maxH);
}
}
else
{
CanvasD2D::c_DWFactory->CreateTextLayout(
str, strLen, m_TextFormat.Get(), maxW, maxH, m_TextLayout.ReleaseAndGetAddressOf());
if (!m_TextLayout) return false;
if (gdiEmulation)
{
Microsoft::WRL::ComPtr<IDWriteTextLayout1> textLayout1;
m_TextLayout.As(&textLayout1);
const float xOffset = m_TextFormat->GetFontSize() / 6.0f;
const float emOffset = xOffset / 24.0f;
const DWRITE_TEXT_RANGE range = {0, strLen};
textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range);
}
UINT32 lineCount = 0;
DWRITE_LINE_METRICS lineMetrics[2];
HRESULT hr = m_TextLayout->GetLineMetrics(lineMetrics, _countof(lineMetrics), &lineCount);
if (SUCCEEDED(hr))
{
// If only one line is visible, disable wrapping so that as much text as possible is shown
// after trimming.
// TODO: Fix this for when more than one line is visible.
if (lineCount >= 2 &&
lineMetrics[0].isTrimmed &&
lineMetrics[1].isTrimmed &&
lineMetrics[1].height == 0.0f)
{
m_TextLayout->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
}
}
}
return true;
}
void TextFormatD2D::SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection)
{
auto fontCollectionD2D = (FontCollectionD2D*)fontCollection;
Dispose();
WCHAR dwriteFamilyName[LF_FACESIZE];
DWRITE_FONT_WEIGHT dwriteFontWeight =
bold ? DWRITE_FONT_WEIGHT_BOLD : DWRITE_FONT_WEIGHT_REGULAR;
DWRITE_FONT_STYLE dwriteFontStyle =
italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
DWRITE_FONT_STRETCH dwriteFontStretch = DWRITE_FONT_STRETCH_NORMAL;
const float dwriteFontSize = size * (4.0f / 3.0f);
// |fontFamily| uses the GDI/GDI+ font naming convention so try to create DirectWrite font
// using the GDI family name and then create a text format using the DirectWrite family name
// obtained from it.
HRESULT hr = Util::GetDWritePropertiesFromGDIProperties(
CanvasD2D::c_DWFactory.Get(), fontFamily, bold, italic, dwriteFontWeight, dwriteFontStyle,
dwriteFontStretch, dwriteFamilyName, _countof(dwriteFamilyName));
if (SUCCEEDED(hr))
{
hr = CanvasD2D::c_DWFactory->CreateTextFormat(
dwriteFamilyName,
nullptr,
dwriteFontWeight,
dwriteFontStyle,
dwriteFontStretch,
dwriteFontSize,
L"",
&m_TextFormat);
}
if (FAILED(hr))
{
IDWriteFontCollection* dwriteFontCollection = nullptr;
// If |fontFamily| is not in the system collection, use the font collection from
// |fontCollectionD2D| if possible.
if (!Util::IsFamilyInSystemFontCollection(CanvasD2D::c_DWFactory.Get(), fontFamily) &&
(fontCollectionD2D && fontCollectionD2D->InitializeCollection()))
{
IDWriteFont* dwriteFont = Util::FindDWriteFontInFontCollectionByGDIFamilyName(
fontCollectionD2D->m_Collection, fontFamily);
if (dwriteFont)
{
hr = Util::GetFamilyNameFromDWriteFont(
dwriteFont, dwriteFamilyName, _countof(dwriteFamilyName));
if (SUCCEEDED(hr))
{
fontFamily = dwriteFamilyName;
Util::GetPropertiesFromDWriteFont(
dwriteFont, bold, italic, &dwriteFontWeight, &dwriteFontStyle,
&dwriteFontStretch);
}
dwriteFont->Release();
}
dwriteFontCollection = fontCollectionD2D->m_Collection;
}
// Fallback in case above fails.
hr = CanvasD2D::c_DWFactory->CreateTextFormat(
fontFamily,
dwriteFontCollection,
dwriteFontWeight,
dwriteFontStyle,
dwriteFontStretch,
dwriteFontSize,
L"",
&m_TextFormat);
}
if (SUCCEEDED(hr))
{
SetHorizontalAlignment(GetHorizontalAlignment());
SetVerticalAlignment(GetVerticalAlignment());
// Get the family name to in case CreateTextFormat() fallbacked on some other family name.
hr = m_TextFormat->GetFontFamilyName(dwriteFamilyName, _countof(dwriteFamilyName));
if (FAILED(hr)) return;
Microsoft::WRL::ComPtr<IDWriteFontCollection> collection;
Microsoft::WRL::ComPtr<IDWriteFontFamily> fontFamily;
UINT32 familyNameIndex;
BOOL exists;
if (FAILED(m_TextFormat->GetFontCollection(collection.GetAddressOf())) ||
FAILED(collection->FindFamilyName(dwriteFamilyName, &familyNameIndex, &exists)) ||
FAILED(collection->GetFontFamily(familyNameIndex, fontFamily.GetAddressOf())))
{
return;
}
Microsoft::WRL::ComPtr<IDWriteFont> font;
hr = fontFamily->GetFirstMatchingFont(
m_TextFormat->GetFontWeight(),
m_TextFormat->GetFontStretch(),
m_TextFormat->GetFontStyle(),
font.GetAddressOf());
if (FAILED(hr)) return;
DWRITE_FONT_METRICS fmetrics;
font->GetMetrics(&fmetrics);
// GDI+ compatibility: GDI+ adds extra padding below the string when |m_AccurateText| is
// |false|. The bottom padding seems to be based on the font metrics so we can calculate it
// once and keep using it regardless of the actual string. In some cases, GDI+ also adds
// the line gap to the overall height so we will store it as well.
const float pixelsPerDesignUnit = dwriteFontSize / (float)fmetrics.designUnitsPerEm;
m_ExtraHeight =
(((float)fmetrics.designUnitsPerEm / 8.0f) - fmetrics.lineGap) * pixelsPerDesignUnit;
m_LineGap = fmetrics.lineGap * pixelsPerDesignUnit;
}
else
{
Dispose();
}
}
DWRITE_TEXT_METRICS TextFormatD2D::GetMetrics(
const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth)
{
// GDI+ compatibility: If the last character is a newline, GDI+ measurements seem to ignore it.
bool strippedLastNewLine = false;
if (strLen > 2 && str[strLen - 1] == L'\n')
{
strippedLastNewLine = true;
--strLen;
if (str[strLen - 1] == L'\r')
{
--strLen;
}
}
DWRITE_TEXT_METRICS metrics = {0};
Microsoft::WRL::ComPtr<IDWriteTextLayout> textLayout;
HRESULT hr = CanvasD2D::c_DWFactory->CreateTextLayout(
str,
strLen,
m_TextFormat.Get(),
maxWidth,
10000,
textLayout.GetAddressOf());
if (SUCCEEDED(hr))
{
const float xOffset = m_TextFormat->GetFontSize() / 6.0f;
if (gdiEmulation)
{
Microsoft::WRL::ComPtr<IDWriteTextLayout1> textLayout1;
textLayout.As(&textLayout1);
const float emOffset = xOffset / 24.0f;
const DWRITE_TEXT_RANGE range = {0, strLen};
textLayout1->SetCharacterSpacing(emOffset, emOffset, 0.0f, range);
}
textLayout->GetMetrics(&metrics);
if (metrics.width > 0.0f)
{
if (gdiEmulation)
{
metrics.width += xOffset * 2;
metrics.height += m_ExtraHeight;
// GDI+ compatibility: If the string contains a newline (even if it is the
// stripped last character), GDI+ adds the line gap to the overall height.
if (strippedLastNewLine || wmemchr(str, L'\n', strLen) != nullptr)
{
metrics.height += m_LineGap;
}
}
else
{
// GDI+ compatibility: With accurate metrics, the line gap needs to be subtracted
// from the overall height if the string does not contain newlines.
if (!strippedLastNewLine && wmemchr(str, L'\n', strLen) == nullptr)
{
metrics.height -= m_LineGap;
}
}
}
else
{
// GDI+ compatibility: Get rid of the height that DirectWrite assigns to zero-width
// strings.
metrics.height = 0.0f;
}
}
return metrics;
}
void TextFormatD2D::SetTrimming(bool trim)
{
m_Trimming = trim;
IDWriteInlineObject* inlineObject = nullptr;
DWRITE_TRIMMING trimming = {};
DWRITE_WORD_WRAPPING wordWrapping = DWRITE_WORD_WRAPPING_NO_WRAP;
if (trim)
{
if (!m_InlineEllipsis)
{
CanvasD2D::c_DWFactory->CreateEllipsisTrimmingSign(
m_TextFormat.Get(), m_InlineEllipsis.GetAddressOf());
}
inlineObject = m_InlineEllipsis.Get();
trimming.granularity = DWRITE_TRIMMING_GRANULARITY_CHARACTER;
wordWrapping = DWRITE_WORD_WRAPPING_WRAP;
}
m_TextFormat->SetTrimming(&trimming, inlineObject);
m_TextFormat->SetWordWrapping(wordWrapping);
}
void TextFormatD2D::SetHorizontalAlignment(HorizontalAlignment alignment)
{
__super::SetHorizontalAlignment(alignment);
if (m_TextFormat)
{
m_TextFormat->SetTextAlignment(
(alignment == HorizontalAlignment::Left) ? DWRITE_TEXT_ALIGNMENT_LEADING :
(alignment == HorizontalAlignment::Center) ? DWRITE_TEXT_ALIGNMENT_CENTER :
DWRITE_TEXT_ALIGNMENT_TRAILING);
}
}
void TextFormatD2D::SetVerticalAlignment(VerticalAlignment alignment)
{
__super::SetVerticalAlignment(alignment);
if (m_TextFormat)
{
m_TextFormat->SetParagraphAlignment(
(alignment == VerticalAlignment::Top) ? DWRITE_PARAGRAPH_ALIGNMENT_NEAR :
(alignment == VerticalAlignment::Center) ? DWRITE_PARAGRAPH_ALIGNMENT_CENTER :
DWRITE_PARAGRAPH_ALIGNMENT_FAR);
}
}
} // namespace Gfx

View File

@ -1,81 +1,81 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_TEXTFORMATD2D_H_
#define RM_GFX_TEXTFORMATD2D_H_
#include "TextFormat.h"
#include <string>
#include <dwrite_1.h>
#include <wrl/client.h>
namespace Gfx {
// Provides a Direct2D/DirectWrite implementation of TextFormat for use with CanvasD2D.
class TextFormatD2D : public TextFormat
{
public:
TextFormatD2D();
virtual ~TextFormatD2D();
TextFormatD2D(const TextFormatD2D& other) = delete;
TextFormatD2D& operator=(TextFormatD2D other) = delete;
virtual bool IsInitialized() const override { return m_TextFormat != nullptr; }
virtual void SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection) override;
virtual void SetTrimming(bool trim) override;
virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override;
virtual void SetVerticalAlignment(VerticalAlignment alignment) override;
private:
friend class CanvasD2D;
friend class Common_Gfx_TextFormatD2D_Test;
void Dispose();
// Creates a new DirectWrite text layout if |str| has changed since last call. Since creating
// the layout is costly, it is more efficient to keep reusing the text layout until the text
// changes. Returns true if the layout is valid for use.
bool CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation);
DWRITE_TEXT_METRICS GetMetrics(
const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth = 10000.0f);
Microsoft::WRL::ComPtr<IDWriteTextFormat> m_TextFormat;
Microsoft::WRL::ComPtr<IDWriteTextLayout> m_TextLayout;
Microsoft::WRL::ComPtr<IDWriteInlineObject> m_InlineEllipsis;
std::wstring m_LastString;
// Used to emulate GDI+ behaviour.
float m_ExtraHeight;
float m_LineGap;
// Contains the value passed to the last call of of SetTrimming().
bool m_Trimming;
};
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_TEXTFORMATD2D_H_
#define RM_GFX_TEXTFORMATD2D_H_
#include "TextFormat.h"
#include <string>
#include <dwrite_1.h>
#include <wrl/client.h>
namespace Gfx {
// Provides a Direct2D/DirectWrite implementation of TextFormat for use with CanvasD2D.
class TextFormatD2D : public TextFormat
{
public:
TextFormatD2D();
virtual ~TextFormatD2D();
TextFormatD2D(const TextFormatD2D& other) = delete;
TextFormatD2D& operator=(TextFormatD2D other) = delete;
virtual bool IsInitialized() const override { return m_TextFormat != nullptr; }
virtual void SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection) override;
virtual void SetTrimming(bool trim) override;
virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override;
virtual void SetVerticalAlignment(VerticalAlignment alignment) override;
private:
friend class CanvasD2D;
friend class Common_Gfx_TextFormatD2D_Test;
void Dispose();
// Creates a new DirectWrite text layout if |str| has changed since last call. Since creating
// the layout is costly, it is more efficient to keep reusing the text layout until the text
// changes. Returns true if the layout is valid for use.
bool CreateLayout(const WCHAR* str, UINT strLen, float maxW, float maxH, bool gdiEmulation);
DWRITE_TEXT_METRICS GetMetrics(
const WCHAR* str, UINT strLen, bool gdiEmulation, float maxWidth = 10000.0f);
Microsoft::WRL::ComPtr<IDWriteTextFormat> m_TextFormat;
Microsoft::WRL::ComPtr<IDWriteTextLayout> m_TextLayout;
Microsoft::WRL::ComPtr<IDWriteInlineObject> m_InlineEllipsis;
std::wstring m_LastString;
// Used to emulate GDI+ behaviour.
float m_ExtraHeight;
float m_LineGap;
// Contains the value passed to the last call of of SetTrimming().
bool m_Trimming;
};
} // namespace Gfx
#endif

View File

@ -1,83 +1,83 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "Canvas.h"
#include "TextFormatD2D.h"
#include "../UnitTest.h"
#include <memory>
namespace Gfx {
TEST_CLASS(Common_Gfx_TextFormatD2D_Test)
{
public:
std::unique_ptr<Canvas> m_D2D;
Common_Gfx_TextFormatD2D_Test() :
m_D2D(Canvas::Create(Gfx::Renderer::D2D))
{
// TODO: Handle this in CanvasD2D.
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
m_D2D->Resize(10, 10);
m_D2D->SetAntiAliasing(true);
}
TEST_METHOD(TestInaccurateText)
{
std::unique_ptr<TextFormatD2D> textFormat((TextFormatD2D*)m_D2D->CreateTextFormat());
textFormat->SetProperties(L"Arial", 10, false, false, nullptr);
DWRITE_TEXT_METRICS metrics;
metrics = textFormat->GetMetrics(L"test", 4, true);
Assert::AreEqual(26, (int)metrics.width);
Assert::AreEqual(16, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test", 4, false);
Assert::AreEqual(21, (int)metrics.width);
Assert::AreEqual(14, (int)metrics.height);
}
TEST_METHOD(TestTrailingNewlineGdipCompatibility)
{
std::unique_ptr<TextFormatD2D> textFormat((TextFormatD2D*)m_D2D->CreateTextFormat());
textFormat->SetProperties(L"Arial", 10, false, false, nullptr);
DWRITE_TEXT_METRICS metrics;
metrics = textFormat->GetMetrics(L"test\n", 5, false);
Assert::AreEqual(15, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test\r\n", 6, false);
Assert::AreEqual(15, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test\n ", 6, false);
Assert::AreEqual(30, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test\r\n ", 7, false);
Assert::AreEqual(30, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test\n\n", 6, false);
Assert::AreEqual(30, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test\r\n\r\n", 8, false);
Assert::AreEqual(30, (int)metrics.height);
}
};
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "Canvas.h"
#include "TextFormatD2D.h"
#include "../UnitTest.h"
#include <memory>
namespace Gfx {
TEST_CLASS(Common_Gfx_TextFormatD2D_Test)
{
public:
std::unique_ptr<Canvas> m_D2D;
Common_Gfx_TextFormatD2D_Test() :
m_D2D(Canvas::Create(Gfx::Renderer::D2D))
{
// TODO: Handle this in CanvasD2D.
ULONG_PTR gdiplusToken;
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
m_D2D->Resize(10, 10);
m_D2D->SetAntiAliasing(true);
}
TEST_METHOD(TestInaccurateText)
{
std::unique_ptr<TextFormatD2D> textFormat((TextFormatD2D*)m_D2D->CreateTextFormat());
textFormat->SetProperties(L"Arial", 10, false, false, nullptr);
DWRITE_TEXT_METRICS metrics;
metrics = textFormat->GetMetrics(L"test", 4, true);
Assert::AreEqual(26, (int)metrics.width);
Assert::AreEqual(16, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test", 4, false);
Assert::AreEqual(21, (int)metrics.width);
Assert::AreEqual(14, (int)metrics.height);
}
TEST_METHOD(TestTrailingNewlineGdipCompatibility)
{
std::unique_ptr<TextFormatD2D> textFormat((TextFormatD2D*)m_D2D->CreateTextFormat());
textFormat->SetProperties(L"Arial", 10, false, false, nullptr);
DWRITE_TEXT_METRICS metrics;
metrics = textFormat->GetMetrics(L"test\n", 5, false);
Assert::AreEqual(15, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test\r\n", 6, false);
Assert::AreEqual(15, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test\n ", 6, false);
Assert::AreEqual(30, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test\r\n ", 7, false);
Assert::AreEqual(30, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test\n\n", 6, false);
Assert::AreEqual(30, (int)metrics.height);
metrics = textFormat->GetMetrics(L"test\r\n\r\n", 8, false);
Assert::AreEqual(30, (int)metrics.height);
}
};
} // namespace Gfx

View File

@ -1,134 +1,134 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "TextFormatGDIP.h"
#include "FontCollectionGDIP.h"
namespace Gfx {
TextFormatGDIP::TextFormatGDIP()
{
}
TextFormatGDIP::~TextFormatGDIP()
{
}
void TextFormatGDIP::SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection)
{
auto fontCollectionGDIP = (FontCollectionGDIP*)fontCollection;
m_Font.reset();
m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily));
if (m_FontFamily->GetLastStatus() != Gdiplus::Ok)
{
m_FontFamily.reset();
// Not found in system collection so try the private collection.
if (fontCollectionGDIP && fontCollectionGDIP->m_PrivateCollection)
{
m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily, fontCollectionGDIP->m_PrivateCollection));
if (m_FontFamily->GetLastStatus() != Gdiplus::Ok)
{
m_FontFamily.reset();
}
}
}
Gdiplus::FontStyle style = Gdiplus::FontStyleRegular;
if (bold && italic)
{
style = Gdiplus::FontStyleBoldItalic;
}
else if (bold)
{
style = Gdiplus::FontStyleBold;
}
else if (italic)
{
style = Gdiplus::FontStyleItalic;
}
if (size != 0)
{
// Adjust the font size with screen DPI.
HDC dc = GetDC(0);
const int dpi = GetDeviceCaps(dc, LOGPIXELSX);
ReleaseDC(0, dc);
const Gdiplus::REAL fontSize = (Gdiplus::REAL)size * (96.0f / dpi);
if (m_FontFamily)
{
m_Font.reset(new Gdiplus::Font(m_FontFamily.get(), fontSize, style));
if (m_Font->GetLastStatus() != Gdiplus::Ok)
{
m_Font.reset();
}
}
if (!m_Font)
{
// Use default font ("Arial" or GenericSansSerif).
m_Font.reset(new Gdiplus::Font(L"Arial", fontSize, style));
if (m_Font->GetLastStatus() != Gdiplus::Ok)
{
m_Font.reset();
}
}
}
}
void TextFormatGDIP::SetTrimming(bool trim)
{
if (trim)
{
m_StringFormat.SetTrimming(Gdiplus::StringTrimmingEllipsisCharacter);
m_StringFormat.SetFormatFlags(0x0);
}
else
{
m_StringFormat.SetTrimming(Gdiplus::StringTrimmingNone);
m_StringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip | Gdiplus::StringFormatFlagsNoWrap);
}
}
void TextFormatGDIP::SetHorizontalAlignment(HorizontalAlignment alignment)
{
static_assert(Gdiplus::StringAlignmentNear == (int)HorizontalAlignment::Left, "Enum mismatch");
static_assert(Gdiplus::StringAlignmentCenter == (int)HorizontalAlignment::Center, "Enum mismatch");
static_assert(Gdiplus::StringAlignmentFar == (int)HorizontalAlignment::Right, "Enum mismatch");
__super::SetHorizontalAlignment(alignment);
m_StringFormat.SetAlignment((Gdiplus::StringAlignment)alignment);
}
void TextFormatGDIP::SetVerticalAlignment(VerticalAlignment alignment)
{
static_assert(Gdiplus::StringAlignmentNear == (int)VerticalAlignment::Top, "Enum mismatch");
static_assert(Gdiplus::StringAlignmentCenter == (int)VerticalAlignment::Center, "Enum mismatch");
static_assert(Gdiplus::StringAlignmentFar == (int)VerticalAlignment::Bottom, "Enum mismatch");
__super::SetVerticalAlignment(alignment);
m_StringFormat.SetLineAlignment((Gdiplus::StringAlignment)alignment);
}
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "TextFormatGDIP.h"
#include "FontCollectionGDIP.h"
namespace Gfx {
TextFormatGDIP::TextFormatGDIP()
{
}
TextFormatGDIP::~TextFormatGDIP()
{
}
void TextFormatGDIP::SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection)
{
auto fontCollectionGDIP = (FontCollectionGDIP*)fontCollection;
m_Font.reset();
m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily));
if (m_FontFamily->GetLastStatus() != Gdiplus::Ok)
{
m_FontFamily.reset();
// Not found in system collection so try the private collection.
if (fontCollectionGDIP && fontCollectionGDIP->m_PrivateCollection)
{
m_FontFamily.reset(new Gdiplus::FontFamily(fontFamily, fontCollectionGDIP->m_PrivateCollection));
if (m_FontFamily->GetLastStatus() != Gdiplus::Ok)
{
m_FontFamily.reset();
}
}
}
Gdiplus::FontStyle style = Gdiplus::FontStyleRegular;
if (bold && italic)
{
style = Gdiplus::FontStyleBoldItalic;
}
else if (bold)
{
style = Gdiplus::FontStyleBold;
}
else if (italic)
{
style = Gdiplus::FontStyleItalic;
}
if (size != 0)
{
// Adjust the font size with screen DPI.
HDC dc = GetDC(0);
const int dpi = GetDeviceCaps(dc, LOGPIXELSX);
ReleaseDC(0, dc);
const Gdiplus::REAL fontSize = (Gdiplus::REAL)size * (96.0f / dpi);
if (m_FontFamily)
{
m_Font.reset(new Gdiplus::Font(m_FontFamily.get(), fontSize, style));
if (m_Font->GetLastStatus() != Gdiplus::Ok)
{
m_Font.reset();
}
}
if (!m_Font)
{
// Use default font ("Arial" or GenericSansSerif).
m_Font.reset(new Gdiplus::Font(L"Arial", fontSize, style));
if (m_Font->GetLastStatus() != Gdiplus::Ok)
{
m_Font.reset();
}
}
}
}
void TextFormatGDIP::SetTrimming(bool trim)
{
if (trim)
{
m_StringFormat.SetTrimming(Gdiplus::StringTrimmingEllipsisCharacter);
m_StringFormat.SetFormatFlags(0x0);
}
else
{
m_StringFormat.SetTrimming(Gdiplus::StringTrimmingNone);
m_StringFormat.SetFormatFlags(Gdiplus::StringFormatFlagsNoClip | Gdiplus::StringFormatFlagsNoWrap);
}
}
void TextFormatGDIP::SetHorizontalAlignment(HorizontalAlignment alignment)
{
static_assert(Gdiplus::StringAlignmentNear == (int)HorizontalAlignment::Left, "Enum mismatch");
static_assert(Gdiplus::StringAlignmentCenter == (int)HorizontalAlignment::Center, "Enum mismatch");
static_assert(Gdiplus::StringAlignmentFar == (int)HorizontalAlignment::Right, "Enum mismatch");
__super::SetHorizontalAlignment(alignment);
m_StringFormat.SetAlignment((Gdiplus::StringAlignment)alignment);
}
void TextFormatGDIP::SetVerticalAlignment(VerticalAlignment alignment)
{
static_assert(Gdiplus::StringAlignmentNear == (int)VerticalAlignment::Top, "Enum mismatch");
static_assert(Gdiplus::StringAlignmentCenter == (int)VerticalAlignment::Center, "Enum mismatch");
static_assert(Gdiplus::StringAlignmentFar == (int)VerticalAlignment::Bottom, "Enum mismatch");
__super::SetVerticalAlignment(alignment);
m_StringFormat.SetLineAlignment((Gdiplus::StringAlignment)alignment);
}
} // namespace Gfx

View File

@ -1,60 +1,60 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_TEXTFORMATGDIP_H_
#define RM_GFX_TEXTFORMATGDIP_H_
#include "TextFormat.h"
#include <memory>
#include <ole2.h> // For Gdiplus.h.
#include <GdiPlus.h>
namespace Gfx {
// Provides a GDI+ implementation of TextFormat for use with CanvasGDIP.
class TextFormatGDIP : public TextFormat
{
public:
TextFormatGDIP();
virtual ~TextFormatGDIP();
TextFormatGDIP(const TextFormatGDIP& other) = delete;
TextFormatGDIP& operator=(TextFormatGDIP other) = delete;
virtual bool IsInitialized() const override { return m_Font != nullptr; }
virtual void SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection) override;
virtual void SetTrimming(bool trim) override;
virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override;
virtual void SetVerticalAlignment(VerticalAlignment alignment) override;
private:
friend class CanvasGDIP;
std::unique_ptr<Gdiplus::Font> m_Font;
std::unique_ptr<Gdiplus::FontFamily> m_FontFamily;
Gdiplus::StringFormat m_StringFormat;
};
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_TEXTFORMATGDIP_H_
#define RM_GFX_TEXTFORMATGDIP_H_
#include "TextFormat.h"
#include <memory>
#include <ole2.h> // For Gdiplus.h.
#include <GdiPlus.h>
namespace Gfx {
// Provides a GDI+ implementation of TextFormat for use with CanvasGDIP.
class TextFormatGDIP : public TextFormat
{
public:
TextFormatGDIP();
virtual ~TextFormatGDIP();
TextFormatGDIP(const TextFormatGDIP& other) = delete;
TextFormatGDIP& operator=(TextFormatGDIP other) = delete;
virtual bool IsInitialized() const override { return m_Font != nullptr; }
virtual void SetProperties(
const WCHAR* fontFamily, int size, bool bold, bool italic,
const FontCollection* fontCollection) override;
virtual void SetTrimming(bool trim) override;
virtual void SetHorizontalAlignment(HorizontalAlignment alignment) override;
virtual void SetVerticalAlignment(VerticalAlignment alignment) override;
private:
friend class CanvasGDIP;
std::unique_ptr<Gdiplus::Font> m_Font;
std::unique_ptr<Gdiplus::FontFamily> m_FontFamily;
Gdiplus::StringFormat m_StringFormat;
};
} // namespace Gfx
#endif

View File

@ -1,67 +1,67 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "DWriteFontCollectionLoader.h"
#include "DWriteFontFileEnumerator.h"
namespace Gfx {
namespace Util {
DWriteFontCollectionLoader* DWriteFontCollectionLoader::GetInstance()
{
static DWriteFontCollectionLoader s_Instance;
return &s_Instance;
}
ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::AddRef()
{
// This is a singleton class so return a dummy value.
return 1;
}
ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::Release()
{
// This is a singleton class so return a dummy value.
return 1;
}
HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::QueryInterface(IID const& riid, void** ppvObject)
{
if (riid == IID_IUnknown ||
riid == __uuidof(IDWriteFontCollectionLoader))
{
*ppvObject = this;
return S_OK;
}
*ppvObject = nullptr;
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::CreateEnumeratorFromKey(
IDWriteFactory* factory, void const* collectionKey, UINT32 collectionKeySize,
IDWriteFontFileEnumerator** fontFileEnumerator)
{
*fontFileEnumerator = new DWriteFontFileEnumerator(
*(const std::vector<IDWriteFontFile*>*)collectionKey);
return S_OK;
}
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "DWriteFontCollectionLoader.h"
#include "DWriteFontFileEnumerator.h"
namespace Gfx {
namespace Util {
DWriteFontCollectionLoader* DWriteFontCollectionLoader::GetInstance()
{
static DWriteFontCollectionLoader s_Instance;
return &s_Instance;
}
ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::AddRef()
{
// This is a singleton class so return a dummy value.
return 1;
}
ULONG STDMETHODCALLTYPE DWriteFontCollectionLoader::Release()
{
// This is a singleton class so return a dummy value.
return 1;
}
HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::QueryInterface(IID const& riid, void** ppvObject)
{
if (riid == IID_IUnknown ||
riid == __uuidof(IDWriteFontCollectionLoader))
{
*ppvObject = this;
return S_OK;
}
*ppvObject = nullptr;
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE DWriteFontCollectionLoader::CreateEnumeratorFromKey(
IDWriteFactory* factory, void const* collectionKey, UINT32 collectionKeySize,
IDWriteFontFileEnumerator** fontFileEnumerator)
{
*fontFileEnumerator = new DWriteFontFileEnumerator(
*(const std::vector<IDWriteFontFile*>*)collectionKey);
return S_OK;
}
} // namespace Util
} // namespace Gfx

View File

@ -1,53 +1,53 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_
#define RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_
#include <dwrite_1.h>
namespace Gfx {
namespace Util {
// Implements the IDWriteFontCollectionLoader interface as a singleton object. When
// CreateEnumeratorFromKey is called, a new DWriteFontFileEnumerator object is created using
// |fontCollectionKey| (which is assumed to be a pointer to std::vector<IDWriteFontFile*>).
class DWriteFontCollectionLoader : public IDWriteFontCollectionLoader
{
public:
static DWriteFontCollectionLoader* GetInstance();
// IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override;
virtual ULONG STDMETHODCALLTYPE AddRef() override;
virtual ULONG STDMETHODCALLTYPE Release() override;
// IFontCollectionLoader
virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
IDWriteFactory* factory, void const* fontCollectionKey, UINT32 fontCollectionKeySize,
IDWriteFontFileEnumerator** fontFileEnumerator) override;
private:
DWriteFontCollectionLoader() {}
DWriteFontCollectionLoader(const DWriteFontCollectionLoader& other) {}
};
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_
#define RM_GFX_UTIL_DWRITEFONTCOLLECTIONLOADER_H_
#include <dwrite_1.h>
namespace Gfx {
namespace Util {
// Implements the IDWriteFontCollectionLoader interface as a singleton object. When
// CreateEnumeratorFromKey is called, a new DWriteFontFileEnumerator object is created using
// |fontCollectionKey| (which is assumed to be a pointer to std::vector<IDWriteFontFile*>).
class DWriteFontCollectionLoader : public IDWriteFontCollectionLoader
{
public:
static DWriteFontCollectionLoader* GetInstance();
// IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override;
virtual ULONG STDMETHODCALLTYPE AddRef() override;
virtual ULONG STDMETHODCALLTYPE Release() override;
// IFontCollectionLoader
virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
IDWriteFactory* factory, void const* fontCollectionKey, UINT32 fontCollectionKeySize,
IDWriteFontFileEnumerator** fontFileEnumerator) override;
private:
DWriteFontCollectionLoader() {}
DWriteFontCollectionLoader(const DWriteFontCollectionLoader& other) {}
};
} // namespace Util
} // namespace Gfx
#endif

View File

@ -1,78 +1,78 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "DWriteFontFileEnumerator.h"
namespace Gfx {
namespace Util {
DWriteFontFileEnumerator::DWriteFontFileEnumerator(const std::vector<IDWriteFontFile*>& fontFiles) :
m_RefCount(1),
m_FontFiles(fontFiles),
m_CurrentFontFileIndex(-1)
{
}
ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::AddRef()
{
++m_RefCount;
return m_RefCount;
}
ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::Release()
{
--m_RefCount;
if (m_RefCount == 0)
{
delete this;
return 0;
}
return m_RefCount;
}
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::QueryInterface(IID const& riid, void** ppvObject)
{
if (riid == IID_IUnknown ||
riid == __uuidof(IDWriteFontFileEnumerator))
{
*ppvObject = this;
AddRef();
return S_OK;
}
*ppvObject = nullptr;
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::MoveNext(BOOL* hasCurrentFile)
{
*hasCurrentFile = (++m_CurrentFontFileIndex < (int)m_FontFiles.size());
return S_OK;
}
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile)
{
IDWriteFontFile* currentFontFile = m_FontFiles[m_CurrentFontFileIndex];
currentFontFile->AddRef();
*fontFile = currentFontFile;
return S_OK;
}
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "DWriteFontFileEnumerator.h"
namespace Gfx {
namespace Util {
DWriteFontFileEnumerator::DWriteFontFileEnumerator(const std::vector<IDWriteFontFile*>& fontFiles) :
m_RefCount(1),
m_FontFiles(fontFiles),
m_CurrentFontFileIndex(-1)
{
}
ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::AddRef()
{
++m_RefCount;
return m_RefCount;
}
ULONG STDMETHODCALLTYPE DWriteFontFileEnumerator::Release()
{
--m_RefCount;
if (m_RefCount == 0)
{
delete this;
return 0;
}
return m_RefCount;
}
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::QueryInterface(IID const& riid, void** ppvObject)
{
if (riid == IID_IUnknown ||
riid == __uuidof(IDWriteFontFileEnumerator))
{
*ppvObject = this;
AddRef();
return S_OK;
}
*ppvObject = nullptr;
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::MoveNext(BOOL* hasCurrentFile)
{
*hasCurrentFile = (++m_CurrentFontFileIndex < (int)m_FontFiles.size());
return S_OK;
}
HRESULT STDMETHODCALLTYPE DWriteFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile)
{
IDWriteFontFile* currentFontFile = m_FontFiles[m_CurrentFontFileIndex];
currentFontFile->AddRef();
*fontFile = currentFontFile;
return S_OK;
}
} // namespace Util
} // namespace Gfx

View File

@ -1,56 +1,56 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_
#define RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_
#include <vector>
#include <dwrite_1.h>
namespace Gfx {
namespace Util {
// Implements IDWriteFontFileEnumerator by enumerating over std::vector<IDWriteFontFile*>.
class DWriteFontFileEnumerator : public IDWriteFontFileEnumerator
{
public:
DWriteFontFileEnumerator(const std::vector<IDWriteFontFile*>& fontFiles);
// IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override;
virtual ULONG STDMETHODCALLTYPE AddRef() override;
virtual ULONG STDMETHODCALLTYPE Release() override;
// IDWriteFontFileEnumerator
virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile) override;
virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** currentFontFile) override;
private:
ULONG m_RefCount;
const std::vector<IDWriteFontFile*>& m_FontFiles;
// Current index of |m_FontFiles|. The type is int instead of size_t as it starts from -1 as
// required by IDWriteFontFileEnumerator.
int m_CurrentFontFileIndex;
};
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_
#define RM_GFX_UTIL_DWRITEFONTFILEENUMERATOR_H_
#include <vector>
#include <dwrite_1.h>
namespace Gfx {
namespace Util {
// Implements IDWriteFontFileEnumerator by enumerating over std::vector<IDWriteFontFile*>.
class DWriteFontFileEnumerator : public IDWriteFontFileEnumerator
{
public:
DWriteFontFileEnumerator(const std::vector<IDWriteFontFile*>& fontFiles);
// IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID uuid, void** object) override;
virtual ULONG STDMETHODCALLTYPE AddRef() override;
virtual ULONG STDMETHODCALLTYPE Release() override;
// IDWriteFontFileEnumerator
virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile) override;
virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** currentFontFile) override;
private:
ULONG m_RefCount;
const std::vector<IDWriteFontFile*>& m_FontFiles;
// Current index of |m_FontFiles|. The type is int instead of size_t as it starts from -1 as
// required by IDWriteFontFileEnumerator.
int m_CurrentFontFileIndex;
};
} // namespace Util
} // namespace Gfx
#endif

View File

@ -1,218 +1,218 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "DWriteHelpers.h"
namespace Gfx {
namespace Util {
HRESULT GetDWritePropertiesFromGDIProperties(
IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic,
DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle,
DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize)
{
HRESULT hr = E_FAIL;
IDWriteFont* dwriteFont = CreateDWriteFontFromGDIFamilyName(factory, gdiFamilyName);
if (dwriteFont)
{
hr = GetFamilyNameFromDWriteFont(dwriteFont, dwriteFamilyName, dwriteFamilyNameSize);
if (SUCCEEDED(hr))
{
GetPropertiesFromDWriteFont(
dwriteFont, gdiBold, gdiItalic, &dwriteFontWeight, &dwriteFontStyle, &dwriteFontStretch);
}
dwriteFont->Release();
}
return hr;
}
void GetPropertiesFromDWriteFont(
IDWriteFont* dwriteFont, const bool bold, const bool italic,
DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle,
DWRITE_FONT_STRETCH* dwriteFontStretch)
{
*dwriteFontWeight = dwriteFont->GetWeight();
if (bold)
{
if (*dwriteFontWeight == DWRITE_FONT_WEIGHT_NORMAL)
{
*dwriteFontWeight = DWRITE_FONT_WEIGHT_BOLD;
}
else if (*dwriteFontWeight < DWRITE_FONT_WEIGHT_ULTRA_BOLD)
{
// If 'gdiFamilyName' was e.g. 'Segoe UI Light', |dwFontWeight| wil be equal to
// DWRITE_FONT_WEIGHT_LIGHT. If |gdiBold| is true in that case, we need to
// increase the weight a little more for similar results with GDI+.
// TODO: Is +100 enough?
*dwriteFontWeight = (DWRITE_FONT_WEIGHT)(*dwriteFontWeight + 100);
}
}
*dwriteFontStyle = dwriteFont->GetStyle();
if (italic && *dwriteFontStyle == DWRITE_FONT_STYLE_NORMAL)
{
*dwriteFontStyle = DWRITE_FONT_STYLE_ITALIC;
}
*dwriteFontStretch = dwriteFont->GetStretch();
}
IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* gdiFamilyName)
{
Microsoft::WRL::ComPtr<IDWriteGdiInterop> dwGdiInterop;
HRESULT hr = factory->GetGdiInterop(dwGdiInterop.GetAddressOf());
if (SUCCEEDED(hr))
{
LOGFONT lf = {};
wcscpy_s(lf.lfFaceName, gdiFamilyName);
lf.lfHeight = -12;
lf.lfWeight = FW_DONTCARE;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = ANTIALIASED_QUALITY;
lf.lfPitchAndFamily = VARIABLE_PITCH;
IDWriteFont* dwFont;
hr = dwGdiInterop->CreateFontFromLOGFONT(&lf, &dwFont);
if (SUCCEEDED(hr))
{
return dwFont;
}
}
return nullptr;
}
HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, const UINT bufferSize)
{
IDWriteFontFamily* dwriteFontFamily;
HRESULT hr = font->GetFontFamily(&dwriteFontFamily);
if (SUCCEEDED(hr))
{
hr = GetFamilyNameFromDWriteFontFamily(dwriteFontFamily, buffer, bufferSize);
dwriteFontFamily->Release();
}
return hr;
}
HRESULT GetFamilyNameFromDWriteFontFamily(
IDWriteFontFamily* fontFamily, WCHAR* buffer, const UINT bufferSize)
{
IDWriteLocalizedStrings* dwFamilyNames;
HRESULT hr = fontFamily->GetFamilyNames(&dwFamilyNames);
if (SUCCEEDED(hr))
{
// TODO: Determine the best index?
hr = dwFamilyNames->GetString(0, buffer, bufferSize);
dwFamilyNames->Release();
}
return hr;
}
bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName)
{
bool result = false;
IDWriteFontCollection* systemFontCollection;
HRESULT hr = factory->GetSystemFontCollection(&systemFontCollection);
if (SUCCEEDED(hr))
{
UINT32 familyNameIndex;
BOOL familyNameFound;
HRESULT hr = systemFontCollection->FindFamilyName(
familyName, &familyNameIndex, &familyNameFound);
if (SUCCEEDED(hr) && familyNameFound)
{
result = true;
}
systemFontCollection->Release();
}
return result;
}
HRESULT GetGDIFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize)
{
Microsoft::WRL::ComPtr<IDWriteLocalizedStrings> strings;
BOOL stringsExist;
font->GetInformationalStrings(
DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, strings.GetAddressOf(), &stringsExist);
if (strings && stringsExist)
{
return strings->GetString(0, buffer, bufferSize);
}
return E_FAIL;
}
IDWriteFont* FindDWriteFontInFontFamilyByGDIFamilyName(
IDWriteFontFamily* fontFamily, const WCHAR* gdiFamilyName)
{
const UINT32 fontFamilyFontCount = fontFamily->GetFontCount();
for (UINT32 j = 0; j < fontFamilyFontCount; ++j)
{
IDWriteFont* font;
HRESULT hr = fontFamily->GetFont(j, &font);
if (SUCCEEDED(hr))
{
WCHAR buffer[LF_FACESIZE];
hr = GetGDIFamilyNameFromDWriteFont(font, buffer, _countof(buffer));
if (SUCCEEDED(hr) && _wcsicmp(gdiFamilyName, buffer) == 0)
{
return font;
}
font->Release();
}
}
return nullptr;
}
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName(
IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName)
{
const UINT32 fontCollectionFamilyCount = fontCollection->GetFontFamilyCount();
for (UINT32 i = 0; i < fontCollectionFamilyCount; ++i)
{
IDWriteFontFamily* fontFamily;
HRESULT hr = fontCollection->GetFontFamily(i, &fontFamily);
if (SUCCEEDED(hr))
{
IDWriteFont* font = FindDWriteFontInFontFamilyByGDIFamilyName(
fontFamily, gdiFamilyName);
fontFamily->Release();
if (font)
{
return font;
}
}
}
return nullptr;
}
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "DWriteHelpers.h"
namespace Gfx {
namespace Util {
HRESULT GetDWritePropertiesFromGDIProperties(
IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic,
DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle,
DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize)
{
HRESULT hr = E_FAIL;
IDWriteFont* dwriteFont = CreateDWriteFontFromGDIFamilyName(factory, gdiFamilyName);
if (dwriteFont)
{
hr = GetFamilyNameFromDWriteFont(dwriteFont, dwriteFamilyName, dwriteFamilyNameSize);
if (SUCCEEDED(hr))
{
GetPropertiesFromDWriteFont(
dwriteFont, gdiBold, gdiItalic, &dwriteFontWeight, &dwriteFontStyle, &dwriteFontStretch);
}
dwriteFont->Release();
}
return hr;
}
void GetPropertiesFromDWriteFont(
IDWriteFont* dwriteFont, const bool bold, const bool italic,
DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle,
DWRITE_FONT_STRETCH* dwriteFontStretch)
{
*dwriteFontWeight = dwriteFont->GetWeight();
if (bold)
{
if (*dwriteFontWeight == DWRITE_FONT_WEIGHT_NORMAL)
{
*dwriteFontWeight = DWRITE_FONT_WEIGHT_BOLD;
}
else if (*dwriteFontWeight < DWRITE_FONT_WEIGHT_ULTRA_BOLD)
{
// If 'gdiFamilyName' was e.g. 'Segoe UI Light', |dwFontWeight| wil be equal to
// DWRITE_FONT_WEIGHT_LIGHT. If |gdiBold| is true in that case, we need to
// increase the weight a little more for similar results with GDI+.
// TODO: Is +100 enough?
*dwriteFontWeight = (DWRITE_FONT_WEIGHT)(*dwriteFontWeight + 100);
}
}
*dwriteFontStyle = dwriteFont->GetStyle();
if (italic && *dwriteFontStyle == DWRITE_FONT_STYLE_NORMAL)
{
*dwriteFontStyle = DWRITE_FONT_STYLE_ITALIC;
}
*dwriteFontStretch = dwriteFont->GetStretch();
}
IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* gdiFamilyName)
{
Microsoft::WRL::ComPtr<IDWriteGdiInterop> dwGdiInterop;
HRESULT hr = factory->GetGdiInterop(dwGdiInterop.GetAddressOf());
if (SUCCEEDED(hr))
{
LOGFONT lf = {};
wcscpy_s(lf.lfFaceName, gdiFamilyName);
lf.lfHeight = -12;
lf.lfWeight = FW_DONTCARE;
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = ANTIALIASED_QUALITY;
lf.lfPitchAndFamily = VARIABLE_PITCH;
IDWriteFont* dwFont;
hr = dwGdiInterop->CreateFontFromLOGFONT(&lf, &dwFont);
if (SUCCEEDED(hr))
{
return dwFont;
}
}
return nullptr;
}
HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, const UINT bufferSize)
{
IDWriteFontFamily* dwriteFontFamily;
HRESULT hr = font->GetFontFamily(&dwriteFontFamily);
if (SUCCEEDED(hr))
{
hr = GetFamilyNameFromDWriteFontFamily(dwriteFontFamily, buffer, bufferSize);
dwriteFontFamily->Release();
}
return hr;
}
HRESULT GetFamilyNameFromDWriteFontFamily(
IDWriteFontFamily* fontFamily, WCHAR* buffer, const UINT bufferSize)
{
IDWriteLocalizedStrings* dwFamilyNames;
HRESULT hr = fontFamily->GetFamilyNames(&dwFamilyNames);
if (SUCCEEDED(hr))
{
// TODO: Determine the best index?
hr = dwFamilyNames->GetString(0, buffer, bufferSize);
dwFamilyNames->Release();
}
return hr;
}
bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName)
{
bool result = false;
IDWriteFontCollection* systemFontCollection;
HRESULT hr = factory->GetSystemFontCollection(&systemFontCollection);
if (SUCCEEDED(hr))
{
UINT32 familyNameIndex;
BOOL familyNameFound;
HRESULT hr = systemFontCollection->FindFamilyName(
familyName, &familyNameIndex, &familyNameFound);
if (SUCCEEDED(hr) && familyNameFound)
{
result = true;
}
systemFontCollection->Release();
}
return result;
}
HRESULT GetGDIFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize)
{
Microsoft::WRL::ComPtr<IDWriteLocalizedStrings> strings;
BOOL stringsExist;
font->GetInformationalStrings(
DWRITE_INFORMATIONAL_STRING_WIN32_FAMILY_NAMES, strings.GetAddressOf(), &stringsExist);
if (strings && stringsExist)
{
return strings->GetString(0, buffer, bufferSize);
}
return E_FAIL;
}
IDWriteFont* FindDWriteFontInFontFamilyByGDIFamilyName(
IDWriteFontFamily* fontFamily, const WCHAR* gdiFamilyName)
{
const UINT32 fontFamilyFontCount = fontFamily->GetFontCount();
for (UINT32 j = 0; j < fontFamilyFontCount; ++j)
{
IDWriteFont* font;
HRESULT hr = fontFamily->GetFont(j, &font);
if (SUCCEEDED(hr))
{
WCHAR buffer[LF_FACESIZE];
hr = GetGDIFamilyNameFromDWriteFont(font, buffer, _countof(buffer));
if (SUCCEEDED(hr) && _wcsicmp(gdiFamilyName, buffer) == 0)
{
return font;
}
font->Release();
}
}
return nullptr;
}
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName(
IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName)
{
const UINT32 fontCollectionFamilyCount = fontCollection->GetFontFamilyCount();
for (UINT32 i = 0; i < fontCollectionFamilyCount; ++i)
{
IDWriteFontFamily* fontFamily;
HRESULT hr = fontCollection->GetFontFamily(i, &fontFamily);
if (SUCCEEDED(hr))
{
IDWriteFont* font = FindDWriteFontInFontFamilyByGDIFamilyName(
fontFamily, gdiFamilyName);
fontFamily->Release();
if (font)
{
return font;
}
}
}
return nullptr;
}
} // namespace Util
} // namespace Gfx

View File

@ -1,58 +1,58 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_DWRITEHELPERS_H_
#define RM_GFX_UTIL_DWRITEHELPERS_H_
#include <dwrite_1.h>
namespace Gfx {
namespace Util {
// Maps the GDI family name and italic/bold flags to the DirectWrite family name, weight, style,
// and stretch.
HRESULT GetDWritePropertiesFromGDIProperties(
IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic,
DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle,
DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize);
void GetPropertiesFromDWriteFont(
IDWriteFont* dwriteFont, const bool bold, const bool italic,
DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle,
DWRITE_FONT_STRETCH* dwriteFontStretch);
// Creates a IDWriteFont using the GDI family name instead of the DirectWrite family name. For
// example, 'Segoe UI' and 'Segoe UI Semibold' are separate family names with GDI whereas
// DirectWrite uses the family name 'Segoe UI' for both and differentiates them by the font
// style.
IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* fontFamily);
HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize);
HRESULT GetFamilyNameFromDWriteFontFamily(
IDWriteFontFamily* fontFamily, WCHAR* buffer, UINT bufferSize);
bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName);
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName(
IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName);
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_DWRITEHELPERS_H_
#define RM_GFX_UTIL_DWRITEHELPERS_H_
#include <dwrite_1.h>
namespace Gfx {
namespace Util {
// Maps the GDI family name and italic/bold flags to the DirectWrite family name, weight, style,
// and stretch.
HRESULT GetDWritePropertiesFromGDIProperties(
IDWriteFactory* factory, const WCHAR* gdiFamilyName, const bool gdiBold, const bool gdiItalic,
DWRITE_FONT_WEIGHT& dwriteFontWeight, DWRITE_FONT_STYLE& dwriteFontStyle,
DWRITE_FONT_STRETCH& dwriteFontStretch, WCHAR* dwriteFamilyName, UINT dwriteFamilyNameSize);
void GetPropertiesFromDWriteFont(
IDWriteFont* dwriteFont, const bool bold, const bool italic,
DWRITE_FONT_WEIGHT* dwriteFontWeight, DWRITE_FONT_STYLE* dwriteFontStyle,
DWRITE_FONT_STRETCH* dwriteFontStretch);
// Creates a IDWriteFont using the GDI family name instead of the DirectWrite family name. For
// example, 'Segoe UI' and 'Segoe UI Semibold' are separate family names with GDI whereas
// DirectWrite uses the family name 'Segoe UI' for both and differentiates them by the font
// style.
IDWriteFont* CreateDWriteFontFromGDIFamilyName(IDWriteFactory* factory, const WCHAR* fontFamily);
HRESULT GetFamilyNameFromDWriteFont(IDWriteFont* font, WCHAR* buffer, UINT bufferSize);
HRESULT GetFamilyNameFromDWriteFontFamily(
IDWriteFontFamily* fontFamily, WCHAR* buffer, UINT bufferSize);
bool IsFamilyInSystemFontCollection(IDWriteFactory* factory, const WCHAR* familyName);
IDWriteFont* FindDWriteFontInFontCollectionByGDIFamilyName(
IDWriteFontCollection* fontCollection, const WCHAR* gdiFamilyName);
} // namespace Util
} // namespace Gfx
#endif

View File

@ -1,136 +1,136 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "WICBitmapDIB.h"
#include "WICBitmapLockDIB.h"
namespace Gfx {
namespace Util {
WICBitmapDIB::WICBitmapDIB() :
m_DIBSectionBuffer(),
m_DIBSectionBufferPixels(),
m_W(0),
m_H(0)
{
}
WICBitmapDIB::~WICBitmapDIB()
{
if (m_DIBSectionBuffer)
{
DeleteObject(m_DIBSectionBuffer);
m_DIBSectionBufferPixels = nullptr;
}
}
void WICBitmapDIB::Resize(UINT w, UINT h)
{
if (m_DIBSectionBuffer)
{
DeleteObject(m_DIBSectionBuffer);
m_DIBSectionBufferPixels = nullptr;
}
m_W = w;
m_H = h;
BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)};
bh.bV4Width = (LONG)m_W;
bh.bV4Height = -(LONG)m_H; // Top-down DIB
bh.bV4Planes = 1;
bh.bV4BitCount = 32;
bh.bV4V4Compression = BI_BITFIELDS;
bh.bV4RedMask = 0x00FF0000;
bh.bV4GreenMask = 0x0000FF00;
bh.bV4BlueMask = 0x000000FF;
bh.bV4AlphaMask = 0xFF000000;
m_DIBSectionBuffer = CreateDIBSection(
nullptr,
(BITMAPINFO*)&bh,
DIB_RGB_COLORS,
(void**)&m_DIBSectionBufferPixels,
nullptr,
0);
assert(m_DIBSectionBufferPixels);
}
IFACEMETHODIMP WICBitmapDIB::QueryInterface(REFIID riid, void** ppvObject)
{
return E_NOTIMPL;
}
IFACEMETHODIMP_(ULONG) WICBitmapDIB::AddRef()
{
return 0;
}
IFACEMETHODIMP_(ULONG) WICBitmapDIB::Release()
{
return 0;
}
IFACEMETHODIMP WICBitmapDIB::GetSize(UINT* puiWidth, UINT* puiHeight)
{
if (puiWidth) *puiWidth = m_W;
if (puiHeight) *puiHeight = m_H;
return S_OK;
}
IFACEMETHODIMP WICBitmapDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
{
*pPixelFormat = GUID_WICPixelFormat32bppPBGRA;
return S_OK;
}
IFACEMETHODIMP WICBitmapDIB::GetResolution(double* pDpiX, double* pDpiY)
{
return E_NOTIMPL;
}
IFACEMETHODIMP WICBitmapDIB::CopyPalette(IWICPalette* pIPalette)
{
return E_NOTIMPL;
}
IFACEMETHODIMP WICBitmapDIB::CopyPixels(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer)
{
return E_NOTIMPL;
}
IFACEMETHODIMP WICBitmapDIB::Lock(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock)
{
if (ppILock) *ppILock = (IWICBitmapLock*)new WICBitmapLockDIB(this, prcLock);
return S_OK;
}
IFACEMETHODIMP WICBitmapDIB::SetPalette(IWICPalette* pIPalette)
{
return E_NOTIMPL;
}
IFACEMETHODIMP WICBitmapDIB::SetResolution(double dpiX, double dpiY)
{
return E_NOTIMPL;
}
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "WICBitmapDIB.h"
#include "WICBitmapLockDIB.h"
namespace Gfx {
namespace Util {
WICBitmapDIB::WICBitmapDIB() :
m_DIBSectionBuffer(),
m_DIBSectionBufferPixels(),
m_W(0),
m_H(0)
{
}
WICBitmapDIB::~WICBitmapDIB()
{
if (m_DIBSectionBuffer)
{
DeleteObject(m_DIBSectionBuffer);
m_DIBSectionBufferPixels = nullptr;
}
}
void WICBitmapDIB::Resize(UINT w, UINT h)
{
if (m_DIBSectionBuffer)
{
DeleteObject(m_DIBSectionBuffer);
m_DIBSectionBufferPixels = nullptr;
}
m_W = w;
m_H = h;
BITMAPV4HEADER bh = {sizeof(BITMAPV4HEADER)};
bh.bV4Width = (LONG)m_W;
bh.bV4Height = -(LONG)m_H; // Top-down DIB
bh.bV4Planes = 1;
bh.bV4BitCount = 32;
bh.bV4V4Compression = BI_BITFIELDS;
bh.bV4RedMask = 0x00FF0000;
bh.bV4GreenMask = 0x0000FF00;
bh.bV4BlueMask = 0x000000FF;
bh.bV4AlphaMask = 0xFF000000;
m_DIBSectionBuffer = CreateDIBSection(
nullptr,
(BITMAPINFO*)&bh,
DIB_RGB_COLORS,
(void**)&m_DIBSectionBufferPixels,
nullptr,
0);
assert(m_DIBSectionBufferPixels);
}
IFACEMETHODIMP WICBitmapDIB::QueryInterface(REFIID riid, void** ppvObject)
{
return E_NOTIMPL;
}
IFACEMETHODIMP_(ULONG) WICBitmapDIB::AddRef()
{
return 0;
}
IFACEMETHODIMP_(ULONG) WICBitmapDIB::Release()
{
return 0;
}
IFACEMETHODIMP WICBitmapDIB::GetSize(UINT* puiWidth, UINT* puiHeight)
{
if (puiWidth) *puiWidth = m_W;
if (puiHeight) *puiHeight = m_H;
return S_OK;
}
IFACEMETHODIMP WICBitmapDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
{
*pPixelFormat = GUID_WICPixelFormat32bppPBGRA;
return S_OK;
}
IFACEMETHODIMP WICBitmapDIB::GetResolution(double* pDpiX, double* pDpiY)
{
return E_NOTIMPL;
}
IFACEMETHODIMP WICBitmapDIB::CopyPalette(IWICPalette* pIPalette)
{
return E_NOTIMPL;
}
IFACEMETHODIMP WICBitmapDIB::CopyPixels(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer)
{
return E_NOTIMPL;
}
IFACEMETHODIMP WICBitmapDIB::Lock(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock)
{
if (ppILock) *ppILock = (IWICBitmapLock*)new WICBitmapLockDIB(this, prcLock);
return S_OK;
}
IFACEMETHODIMP WICBitmapDIB::SetPalette(IWICPalette* pIPalette)
{
return E_NOTIMPL;
}
IFACEMETHODIMP WICBitmapDIB::SetResolution(double dpiX, double dpiY)
{
return E_NOTIMPL;
}
} // namespace Util
} // namespace Gfx

View File

@ -1,76 +1,76 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_WICBITMAPDIB_H_
#define RM_GFX_UTIL_WICBITMAPDIB_H_
#include <Windows.h>
#include <wincodec.h>
namespace Gfx {
namespace Util {
// Allows the use of a DIB section (HBITMAP) in Direct2D as a WIC bitmap. It is assumed that this
// class is used only with 32bpp PARGB bitmaps and using a sigle thread.
//
// This class does not follow the COM reference count model. RTTI is used instead. This class
// implements only the bare essentials in order to use a DIB section as a Direct2D render target.
class WICBitmapDIB : public IWICBitmap
{
public:
WICBitmapDIB();
~WICBitmapDIB();
WICBitmapDIB(const WICBitmapDIB& other) = delete;
WICBitmapDIB& operator=(WICBitmapDIB other) = delete;
void Resize(UINT w, UINT h);
HBITMAP GetHandle() const { return m_DIBSectionBuffer; }
BYTE* GetData() const { return (BYTE*)m_DIBSectionBufferPixels; }
// IUnknown
IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
IFACEMETHOD_(ULONG, AddRef)();
IFACEMETHOD_(ULONG, Release)();
// IWICBitmapSource
IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
IFACEMETHOD(GetResolution)(double* pDpiX, double* pDpiY);
IFACEMETHOD(CopyPalette)(IWICPalette* pIPalette);
IFACEMETHOD(CopyPixels)(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer);
// IWICBitmap
IFACEMETHOD(Lock)(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock);
IFACEMETHOD(SetPalette)(IWICPalette* pIPalette);
IFACEMETHOD(SetResolution)(double dpiX, double dpiY);
private:
friend class WICBitmapLockDIB;
HBITMAP m_DIBSectionBuffer;
LPDWORD m_DIBSectionBufferPixels;
UINT m_W;
UINT m_H;
};
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_WICBITMAPDIB_H_
#define RM_GFX_UTIL_WICBITMAPDIB_H_
#include <Windows.h>
#include <wincodec.h>
namespace Gfx {
namespace Util {
// Allows the use of a DIB section (HBITMAP) in Direct2D as a WIC bitmap. It is assumed that this
// class is used only with 32bpp PARGB bitmaps and using a sigle thread.
//
// This class does not follow the COM reference count model. RTTI is used instead. This class
// implements only the bare essentials in order to use a DIB section as a Direct2D render target.
class WICBitmapDIB : public IWICBitmap
{
public:
WICBitmapDIB();
~WICBitmapDIB();
WICBitmapDIB(const WICBitmapDIB& other) = delete;
WICBitmapDIB& operator=(WICBitmapDIB other) = delete;
void Resize(UINT w, UINT h);
HBITMAP GetHandle() const { return m_DIBSectionBuffer; }
BYTE* GetData() const { return (BYTE*)m_DIBSectionBufferPixels; }
// IUnknown
IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
IFACEMETHOD_(ULONG, AddRef)();
IFACEMETHOD_(ULONG, Release)();
// IWICBitmapSource
IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
IFACEMETHOD(GetResolution)(double* pDpiX, double* pDpiY);
IFACEMETHOD(CopyPalette)(IWICPalette* pIPalette);
IFACEMETHOD(CopyPixels)(const WICRect* prc, UINT cbStride, UINT cbBufferSize, BYTE* pbBuffer);
// IWICBitmap
IFACEMETHOD(Lock)(const WICRect* prcLock, DWORD flags, IWICBitmapLock** ppILock);
IFACEMETHOD(SetPalette)(IWICPalette* pIPalette);
IFACEMETHOD(SetResolution)(double dpiX, double dpiY);
private:
friend class WICBitmapLockDIB;
HBITMAP m_DIBSectionBuffer;
LPDWORD m_DIBSectionBufferPixels;
UINT m_W;
UINT m_H;
};
} // namespace Util
} // namespace Gfx
#endif

View File

@ -1,91 +1,91 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "WICBitmapLockDIB.h"
namespace Gfx {
namespace Util {
WICBitmapLockDIB::WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect) :
m_Bitmap(bitmap),
m_Rect(lockRect),
m_RefCount(1)
{
}
WICBitmapLockDIB::~WICBitmapLockDIB()
{
}
IFACEMETHODIMP WICBitmapLockDIB::QueryInterface(REFIID riid, void** ppvObject)
{
return E_NOTIMPL;
}
IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::AddRef()
{
++m_RefCount;
return m_RefCount;
}
IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::Release()
{
--m_RefCount;
if (m_RefCount == 0)
{
delete this;
return 0;
}
return m_RefCount;
}
IFACEMETHODIMP WICBitmapLockDIB::GetSize(UINT* puiWidth, UINT* puiHeight)
{
return m_Bitmap->GetSize(puiWidth, puiHeight);
}
IFACEMETHODIMP WICBitmapLockDIB::GetStride(UINT* pcbStride)
{
UINT width = 0;
m_Bitmap->GetSize(&width, nullptr);
if (pcbStride) *pcbStride = (width * 32 + 31) / 32 * 4;
return S_OK;
}
IFACEMETHODIMP WICBitmapLockDIB::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData)
{
UINT stride = 0;
GetStride(&stride);
if (pcbBufferSize) *pcbBufferSize = stride * m_Rect->Height;
if (ppbData) *ppbData = (BYTE*)&m_Bitmap->m_DIBSectionBufferPixels[m_Rect->Y * m_Rect->Width + m_Rect->X];
return S_OK;
}
IFACEMETHODIMP WICBitmapLockDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
{
return m_Bitmap->GetPixelFormat(pPixelFormat);
}
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "WICBitmapLockDIB.h"
namespace Gfx {
namespace Util {
WICBitmapLockDIB::WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect) :
m_Bitmap(bitmap),
m_Rect(lockRect),
m_RefCount(1)
{
}
WICBitmapLockDIB::~WICBitmapLockDIB()
{
}
IFACEMETHODIMP WICBitmapLockDIB::QueryInterface(REFIID riid, void** ppvObject)
{
return E_NOTIMPL;
}
IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::AddRef()
{
++m_RefCount;
return m_RefCount;
}
IFACEMETHODIMP_(ULONG) WICBitmapLockDIB::Release()
{
--m_RefCount;
if (m_RefCount == 0)
{
delete this;
return 0;
}
return m_RefCount;
}
IFACEMETHODIMP WICBitmapLockDIB::GetSize(UINT* puiWidth, UINT* puiHeight)
{
return m_Bitmap->GetSize(puiWidth, puiHeight);
}
IFACEMETHODIMP WICBitmapLockDIB::GetStride(UINT* pcbStride)
{
UINT width = 0;
m_Bitmap->GetSize(&width, nullptr);
if (pcbStride) *pcbStride = (width * 32 + 31) / 32 * 4;
return S_OK;
}
IFACEMETHODIMP WICBitmapLockDIB::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData)
{
UINT stride = 0;
GetStride(&stride);
if (pcbBufferSize) *pcbBufferSize = stride * m_Rect->Height;
if (ppbData) *ppbData = (BYTE*)&m_Bitmap->m_DIBSectionBufferPixels[m_Rect->Y * m_Rect->Width + m_Rect->X];
return S_OK;
}
IFACEMETHODIMP WICBitmapLockDIB::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
{
return m_Bitmap->GetPixelFormat(pPixelFormat);
}
} // namespace Util
} // namespace Gfx

View File

@ -1,62 +1,62 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_WICBITMAPLOCKDIB_H_
#define RM_GFX_UTIL_WICBITMAPLOCKDIB_H_
#include <Windows.h>
#include <wincodec.h>
#include "WICBitmapDIB.h"
namespace Gfx {
namespace Util {
// Implements the IWICBitmapLock interface for use with WICBitmapDIB. It is assumed that this
// class is used only with 32bpp PARGB bitmaps and using a sigle thread.
class WICBitmapLockDIB : public IWICBitmapLock
{
public:
WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect);
virtual ~WICBitmapLockDIB();
void Resize(UINT w, UINT h);
// IUnknown
IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
IFACEMETHOD_(ULONG, AddRef)();
IFACEMETHOD_(ULONG, Release)();
// IWICBitmapLock
IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
IFACEMETHOD(GetStride)(UINT* pcbStride);
IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData);
IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
private:
WICBitmapLockDIB(const WICBitmapLockDIB& other) = delete;
WICBitmapLockDIB& operator=(WICBitmapLockDIB other) = delete;
WICBitmapDIB* m_Bitmap;
const WICRect* m_Rect;
UINT m_RefCount;
};
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_WICBITMAPLOCKDIB_H_
#define RM_GFX_UTIL_WICBITMAPLOCKDIB_H_
#include <Windows.h>
#include <wincodec.h>
#include "WICBitmapDIB.h"
namespace Gfx {
namespace Util {
// Implements the IWICBitmapLock interface for use with WICBitmapDIB. It is assumed that this
// class is used only with 32bpp PARGB bitmaps and using a sigle thread.
class WICBitmapLockDIB : public IWICBitmapLock
{
public:
WICBitmapLockDIB(WICBitmapDIB* bitmap, const WICRect* lockRect);
virtual ~WICBitmapLockDIB();
void Resize(UINT w, UINT h);
// IUnknown
IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
IFACEMETHOD_(ULONG, AddRef)();
IFACEMETHOD_(ULONG, Release)();
// IWICBitmapLock
IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
IFACEMETHOD(GetStride)(UINT* pcbStride);
IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData);
IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
private:
WICBitmapLockDIB(const WICBitmapLockDIB& other) = delete;
WICBitmapLockDIB& operator=(WICBitmapLockDIB other) = delete;
WICBitmapDIB* m_Bitmap;
const WICRect* m_Rect;
UINT m_RefCount;
};
} // namespace Util
} // namespace Gfx
#endif

View File

@ -1,82 +1,82 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "WICBitmapLockGDIP.h"
namespace Gfx {
namespace Util {
WICBitmapLockGDIP::WICBitmapLockGDIP() :
m_RefCount(1)
{
}
IFACEMETHODIMP WICBitmapLockGDIP::QueryInterface(REFIID riid, void** ppvObject)
{
return E_NOTIMPL;
}
IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::AddRef()
{
++m_RefCount;
return m_RefCount;
}
IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::Release()
{
--m_RefCount;
if (m_RefCount == 0)
{
delete this;
return 0;
}
return m_RefCount;
}
IFACEMETHODIMP WICBitmapLockGDIP::GetSize(UINT* puiWidth, UINT* puiHeight)
{
*puiWidth = m_BitmapData.Width;
*puiHeight = m_BitmapData.Height;
return S_OK;
}
IFACEMETHODIMP WICBitmapLockGDIP::GetStride(UINT* pcbStride)
{
*pcbStride = m_BitmapData.Stride;
return S_OK;
}
IFACEMETHODIMP WICBitmapLockGDIP::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData)
{
assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB);
*pcbBufferSize = m_BitmapData.Stride * m_BitmapData.Height;
*ppbData = (BYTE*)m_BitmapData.Scan0;
return S_OK;
}
IFACEMETHODIMP WICBitmapLockGDIP::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
{
assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB);
*pPixelFormat = GUID_WICPixelFormat32bppPBGRA;
return S_OK;
}
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "WICBitmapLockGDIP.h"
namespace Gfx {
namespace Util {
WICBitmapLockGDIP::WICBitmapLockGDIP() :
m_RefCount(1)
{
}
IFACEMETHODIMP WICBitmapLockGDIP::QueryInterface(REFIID riid, void** ppvObject)
{
return E_NOTIMPL;
}
IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::AddRef()
{
++m_RefCount;
return m_RefCount;
}
IFACEMETHODIMP_(ULONG) WICBitmapLockGDIP::Release()
{
--m_RefCount;
if (m_RefCount == 0)
{
delete this;
return 0;
}
return m_RefCount;
}
IFACEMETHODIMP WICBitmapLockGDIP::GetSize(UINT* puiWidth, UINT* puiHeight)
{
*puiWidth = m_BitmapData.Width;
*puiHeight = m_BitmapData.Height;
return S_OK;
}
IFACEMETHODIMP WICBitmapLockGDIP::GetStride(UINT* pcbStride)
{
*pcbStride = m_BitmapData.Stride;
return S_OK;
}
IFACEMETHODIMP WICBitmapLockGDIP::GetDataPointer(UINT* pcbBufferSize, BYTE** ppbData)
{
assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB);
*pcbBufferSize = m_BitmapData.Stride * m_BitmapData.Height;
*ppbData = (BYTE*)m_BitmapData.Scan0;
return S_OK;
}
IFACEMETHODIMP WICBitmapLockGDIP::GetPixelFormat(WICPixelFormatGUID* pPixelFormat)
{
assert(m_BitmapData.PixelFormat == PixelFormat32bppPARGB);
*pPixelFormat = GUID_WICPixelFormat32bppPBGRA;
return S_OK;
}
} // namespace Util
} // namespace Gfx

View File

@ -1,61 +1,61 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_
#define RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_
#include <Windows.h>
#include <ole2.h> // For Gdiplus.h.
#include <GdiPlus.h>
#include <wincodec.h>
namespace Gfx {
namespace Util {
// Allows the creation of a shared ID2D1Bitmap using pixel data in a Gdiplus::Bitmap. It is
// assumed that this class is used only with 32bpp PARGB bitmaps and using a sigle thread.
class WICBitmapLockGDIP : public IWICBitmapLock
{
public:
WICBitmapLockGDIP();
Gdiplus::BitmapData* GetBitmapData() { return &m_BitmapData; }
// IUnknown
IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
IFACEMETHOD_(ULONG, AddRef)();
IFACEMETHOD_(ULONG, Release)();
// IWICBitmapLock
IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
IFACEMETHOD(GetStride)(UINT* pcbStride);
IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData);
IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
private:
WICBitmapLockGDIP(const WICBitmapLockGDIP& other) = delete;
WICBitmapLockGDIP& operator=(WICBitmapLockGDIP other) = delete;
Gdiplus::BitmapData m_BitmapData;
UINT m_RefCount;
};
} // namespace Util
} // namespace Gfx
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_
#define RM_GFX_UTIL_WICBITMAPLOCKGDIP_H_
#include <Windows.h>
#include <ole2.h> // For Gdiplus.h.
#include <GdiPlus.h>
#include <wincodec.h>
namespace Gfx {
namespace Util {
// Allows the creation of a shared ID2D1Bitmap using pixel data in a Gdiplus::Bitmap. It is
// assumed that this class is used only with 32bpp PARGB bitmaps and using a sigle thread.
class WICBitmapLockGDIP : public IWICBitmapLock
{
public:
WICBitmapLockGDIP();
Gdiplus::BitmapData* GetBitmapData() { return &m_BitmapData; }
// IUnknown
IFACEMETHOD(QueryInterface)(REFIID riid, void** ppvObject);
IFACEMETHOD_(ULONG, AddRef)();
IFACEMETHOD_(ULONG, Release)();
// IWICBitmapLock
IFACEMETHOD(GetSize)(UINT* puiWidth, UINT* puiHeight);
IFACEMETHOD(GetStride)(UINT* pcbStride);
IFACEMETHOD(GetDataPointer)(UINT* pcbBufferSize, BYTE** ppbData);
IFACEMETHOD(GetPixelFormat)(WICPixelFormatGUID* pPixelFormat);
private:
WICBitmapLockGDIP(const WICBitmapLockGDIP& other) = delete;
WICBitmapLockGDIP& operator=(WICBitmapLockGDIP other) = delete;
Gdiplus::BitmapData m_BitmapData;
UINT m_RefCount;
};
} // namespace Util
} // namespace Gfx
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +1,39 @@
/*
Copyright (C) 2011 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// Heavily based on ccalc 0.5.1 by Walery Studennikov <hqsoftware@mail.ru>
#ifndef RM_COMMON_MATHPARSER_H_
#define RM_COMMON_MATHPARSER_H_
#include <Windows.h>
namespace MathParser
{
typedef bool (*GetValueFunc)(const WCHAR* str, int len, double* value, void* context);
const WCHAR* Check(const WCHAR* formula);
const WCHAR* CheckedParse(const WCHAR* formula, double* result);
const WCHAR* Parse(
const WCHAR* formula, double* result,
GetValueFunc getValue = nullptr, void* getValueContext = nullptr);
bool IsDelimiter(WCHAR ch);
};
/*
Copyright (C) 2011 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// Heavily based on ccalc 0.5.1 by Walery Studennikov <hqsoftware@mail.ru>
#ifndef RM_COMMON_MATHPARSER_H_
#define RM_COMMON_MATHPARSER_H_
#include <Windows.h>
namespace MathParser
{
typedef bool (*GetValueFunc)(const WCHAR* str, int len, double* value, void* context);
const WCHAR* Check(const WCHAR* formula);
const WCHAR* CheckedParse(const WCHAR* formula, double* result);
const WCHAR* Parse(
const WCHAR* formula, double* result,
GetValueFunc getValue = nullptr, void* getValueContext = nullptr);
bool IsDelimiter(WCHAR ch);
};
#endif

View File

@ -1,124 +1,124 @@
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "MathParser.h"
#include "UnitTest.h"
namespace MathParser {
TEST_CLASS(Common_MathParser_Test)
{
public:
void ParseAssert(double expected, const WCHAR* formula)
{
double value = 0.0;
Assert::IsNull(Parse(formula, &value));
Assert::AreEqual(expected, value);
}
TEST_METHOD(TestParse)
{
ParseAssert(5.0, L"5");
ParseAssert(5.0, L" 5 ");
ParseAssert(5.0, L"((((5))))");
ParseAssert(10.0, L"(5 + 5)");
ParseAssert(-10.0, L"(-5 - 5)");
ParseAssert(10.0, L"-(-5-5)");
ParseAssert(10.0, L"-(-5+-5)");
ParseAssert(1.0, L"1 && 1");
ParseAssert(0.0, L"1 && 0");
ParseAssert(1.0, L"1 || 1");
ParseAssert(1.0, L"1 || -1");
ParseAssert(0.0, L"1 < 2 && 2 > 1");
ParseAssert(1.0, L"(1 < 2) && (2 > 1)");
ParseAssert(sin(50.0), L"sin(50)");
ParseAssert(-sin(100.0), L"-sin((25 + 25) * 2)");
ParseAssert(1.0, L"01");
ParseAssert(11.0, L"011");
ParseAssert(3.0, L"0b11");
ParseAssert(10.0, L"0xA");
ParseAssert(10.0, L"0o12");
ParseAssert(2.0, L"1 ? 2 : 3");
ParseAssert(3.0, L"0 ? 2 : 3");
ParseAssert(5.0, L"1 ? (2 + 3) : 3");
ParseAssert(2.0, L"1 ? 2 : 3");
ParseAssert(4.0, L"1 ? 2 : 0 ? 4 : 5");
ParseAssert(4.0, L"1 ? 2 : 1 ? 4 : 5");
ParseAssert(2.0, L"1 ? 2 : (1 ? 4 : 5)");
ParseAssert(5.0, L"0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:5)))))))))))))))))))))))))))))");
ParseAssert(1.0, L"trunc(1.5)");
ParseAssert(-1.0, L"trunc(-1.5)");
ParseAssert(2.0, L"round(1.555)");
ParseAssert(1.56, L"round(1.555, 2)");
double value;
Assert::IsNotNull(Parse(L"1 ? 0 ? 4 : 5 : 3", &value));
Assert::IsNotNull(Parse(L"++1", &value));
Assert::IsNotNull(Parse(L"((1)", &value));
Assert::IsNotNull(Parse(L"1 / 0", &value));
Assert::IsNotNull(Parse(L"1 &&", &value));
Assert::IsNotNull(Parse(L"a", &value));
Assert::IsNull(Parse(L"e", &value));
Assert::AreEqual(2, (int)value);
Assert::IsNull(Parse(L"pi", &value));
Assert::AreEqual(3, (int)value);
Assert::IsNull(Parse(L"pi", &value, GetValueHelper));
Assert::AreEqual(3, (int)value);
Assert::IsNull(Parse(L"a + 5", &value, GetValueHelper));
Assert::AreEqual(15.0, value);
Assert::IsNull(Parse(L"bbb", &value, GetValueHelper));
Assert::AreEqual(20.0, value);
Assert::IsNull(Parse(L"(ccc_)", &value, GetValueHelper, (void*)1));
Assert::AreEqual(30.0, value);
}
static bool GetValueHelper(const WCHAR* str, int len, double* value, void* context)
{
if (wcsncmp(str, L"a", len) == 0)
{
*value = 10.0;
return true;
}
else if (wcsncmp(str, L"bbb", len) == 0)
{
*value = 20.0;
return true;
}
else if (wcsncmp(str, L"ccc_", len) == 0 && context == (void*)1)
{
*value = 30.0;
return true;
}
else if (wcsncmp(str, L"pi", len) == 0)
{
*value = 40.0;
return true;
}
return false;
}
};
} // namespace StringUtil
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "MathParser.h"
#include "UnitTest.h"
namespace MathParser {
TEST_CLASS(Common_MathParser_Test)
{
public:
void ParseAssert(double expected, const WCHAR* formula)
{
double value = 0.0;
Assert::IsNull(Parse(formula, &value));
Assert::AreEqual(expected, value);
}
TEST_METHOD(TestParse)
{
ParseAssert(5.0, L"5");
ParseAssert(5.0, L" 5 ");
ParseAssert(5.0, L"((((5))))");
ParseAssert(10.0, L"(5 + 5)");
ParseAssert(-10.0, L"(-5 - 5)");
ParseAssert(10.0, L"-(-5-5)");
ParseAssert(10.0, L"-(-5+-5)");
ParseAssert(1.0, L"1 && 1");
ParseAssert(0.0, L"1 && 0");
ParseAssert(1.0, L"1 || 1");
ParseAssert(1.0, L"1 || -1");
ParseAssert(0.0, L"1 < 2 && 2 > 1");
ParseAssert(1.0, L"(1 < 2) && (2 > 1)");
ParseAssert(sin(50.0), L"sin(50)");
ParseAssert(-sin(100.0), L"-sin((25 + 25) * 2)");
ParseAssert(1.0, L"01");
ParseAssert(11.0, L"011");
ParseAssert(3.0, L"0b11");
ParseAssert(10.0, L"0xA");
ParseAssert(10.0, L"0o12");
ParseAssert(2.0, L"1 ? 2 : 3");
ParseAssert(3.0, L"0 ? 2 : 3");
ParseAssert(5.0, L"1 ? (2 + 3) : 3");
ParseAssert(2.0, L"1 ? 2 : 3");
ParseAssert(4.0, L"1 ? 2 : 0 ? 4 : 5");
ParseAssert(4.0, L"1 ? 2 : 1 ? 4 : 5");
ParseAssert(2.0, L"1 ? 2 : (1 ? 4 : 5)");
ParseAssert(5.0, L"0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:(0?1:5)))))))))))))))))))))))))))))");
ParseAssert(1.0, L"trunc(1.5)");
ParseAssert(-1.0, L"trunc(-1.5)");
ParseAssert(2.0, L"round(1.555)");
ParseAssert(1.56, L"round(1.555, 2)");
double value;
Assert::IsNotNull(Parse(L"1 ? 0 ? 4 : 5 : 3", &value));
Assert::IsNotNull(Parse(L"++1", &value));
Assert::IsNotNull(Parse(L"((1)", &value));
Assert::IsNotNull(Parse(L"1 / 0", &value));
Assert::IsNotNull(Parse(L"1 &&", &value));
Assert::IsNotNull(Parse(L"a", &value));
Assert::IsNull(Parse(L"e", &value));
Assert::AreEqual(2, (int)value);
Assert::IsNull(Parse(L"pi", &value));
Assert::AreEqual(3, (int)value);
Assert::IsNull(Parse(L"pi", &value, GetValueHelper));
Assert::AreEqual(3, (int)value);
Assert::IsNull(Parse(L"a + 5", &value, GetValueHelper));
Assert::AreEqual(15.0, value);
Assert::IsNull(Parse(L"bbb", &value, GetValueHelper));
Assert::AreEqual(20.0, value);
Assert::IsNull(Parse(L"(ccc_)", &value, GetValueHelper, (void*)1));
Assert::AreEqual(30.0, value);
}
static bool GetValueHelper(const WCHAR* str, int len, double* value, void* context)
{
if (wcsncmp(str, L"a", len) == 0)
{
*value = 10.0;
return true;
}
else if (wcsncmp(str, L"bbb", len) == 0)
{
*value = 20.0;
return true;
}
else if (wcsncmp(str, L"ccc_", len) == 0 && context == (void*)1)
{
*value = 30.0;
return true;
}
else if (wcsncmp(str, L"pi", len) == 0)
{
*value = 40.0;
return true;
}
return false;
}
};
} // namespace StringUtil

View File

@ -1,64 +1,64 @@
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "MenuTemplate.h"
HMENU MenuTemplate::CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString)
{
UINT itemIndex = 0;
return CreateSubMenu(items, itemIndex, itemCount, getString);
}
HMENU MenuTemplate::CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString)
{
HMENU menu = CreatePopupMenu();
do
{
const MenuTemplate& item = items[itemIndex];
++itemIndex;
UINT itemFlags = MF_STRING;
UINT_PTR itemId = item.id;
const WCHAR* itemText = item.idText ? getString(item.idText) : nullptr;
if (item.type == MenuItem_ItemGrayed)
{
itemFlags |= MF_GRAYED;
}
else if (item.type == MenuItem_Separator)
{
itemFlags = MF_SEPARATOR;
}
else if (item.type == MenuItem_SubMenuBegin)
{
itemFlags = MF_POPUP;
itemId = (UINT_PTR)CreateSubMenu(items, itemIndex, itemCount, getString);
}
else if (item.type == MenuItem_SubMenuEnd)
{
return menu;
}
AppendMenu(menu, itemFlags, itemId, itemText);
}
while (itemIndex < itemCount);
return menu;
}
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "MenuTemplate.h"
HMENU MenuTemplate::CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString)
{
UINT itemIndex = 0;
return CreateSubMenu(items, itemIndex, itemCount, getString);
}
HMENU MenuTemplate::CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString)
{
HMENU menu = CreatePopupMenu();
do
{
const MenuTemplate& item = items[itemIndex];
++itemIndex;
UINT itemFlags = MF_STRING;
UINT_PTR itemId = item.id;
const WCHAR* itemText = item.idText ? getString(item.idText) : nullptr;
if (item.type == MenuItem_ItemGrayed)
{
itemFlags |= MF_GRAYED;
}
else if (item.type == MenuItem_Separator)
{
itemFlags = MF_SEPARATOR;
}
else if (item.type == MenuItem_SubMenuBegin)
{
itemFlags = MF_POPUP;
itemId = (UINT_PTR)CreateSubMenu(items, itemIndex, itemCount, getString);
}
else if (item.type == MenuItem_SubMenuEnd)
{
return menu;
}
AppendMenu(menu, itemFlags, itemId, itemText);
}
while (itemIndex < itemCount);
return menu;
}

View File

@ -1,52 +1,52 @@
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_MENUTEMPLATE_H_
#define RM_COMMON_MENUTEMPLATE_H_
#include <Windows.h>
struct MenuTemplate
{
BYTE type;
WORD id;
WORD idText;
typedef WCHAR* (*GetStringFunc)(UINT id);
static HMENU CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString);
private:
static HMENU CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString);
};
enum MenuTemplateItem
{
MenuItem_Item,
MenuItem_ItemGrayed,
MenuItem_Separator,
MenuItem_SubMenuBegin,
MenuItem_SubMenuEnd
};
#define MENU_ITEM(...) { MenuItem_Item, __VA_ARGS__ }
#define MENU_ITEM_GRAYED(...) { MenuItem_ItemGrayed, __VA_ARGS__ }
#define MENU_SEPARATOR() { MenuItem_Separator }
#define MENU_SUBMENU(idText, ...) { MenuItem_SubMenuBegin, 0, idText }, __VA_ARGS__, { MenuItem_SubMenuEnd }
#endif
/*
Copyright (C) 2012 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_MENUTEMPLATE_H_
#define RM_COMMON_MENUTEMPLATE_H_
#include <Windows.h>
struct MenuTemplate
{
BYTE type;
WORD id;
WORD idText;
typedef WCHAR* (*GetStringFunc)(UINT id);
static HMENU CreateMenu(const MenuTemplate* items, UINT itemCount, GetStringFunc getString);
private:
static HMENU CreateSubMenu(const MenuTemplate* items, UINT& itemIndex, UINT itemCount, GetStringFunc getString);
};
enum MenuTemplateItem
{
MenuItem_Item,
MenuItem_ItemGrayed,
MenuItem_Separator,
MenuItem_SubMenuBegin,
MenuItem_SubMenuEnd
};
#define MENU_ITEM(...) { MenuItem_Item, __VA_ARGS__ }
#define MENU_ITEM_GRAYED(...) { MenuItem_ItemGrayed, __VA_ARGS__ }
#define MENU_SEPARATOR() { MenuItem_Separator }
#define MENU_SUBMENU(idText, ...) { MenuItem_SubMenuBegin, 0, idText }, __VA_ARGS__, { MenuItem_SubMenuEnd }
#endif

View File

@ -1,149 +1,149 @@
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "PathUtil.h"
namespace PathUtil {
bool IsSeparator(WCHAR ch)
{
return ch == L'\\' || ch == L'/';
}
bool IsDotOrDotDot(const WCHAR* path)
{
return path[0] == L'.' && (path[1] == L'\0' || (path[1] == L'.' && path[2] == L'\0'));
}
bool IsUNC(const std::wstring& path)
{
return path.length() >= 2 && IsSeparator(path[0]) && IsSeparator(path[1]);
}
bool IsAbsolute(const std::wstring& path)
{
return (path.find(L":\\") != std::wstring::npos ||
path.find(L":/") != std::wstring::npos ||
IsUNC(path));
}
void AppendBacklashIfMissing(std::wstring& path)
{
if (!path.empty() && !IsSeparator(path[path.length() - 1]))
{
path += L'\\';
}
}
std::wstring GetFolderFromFilePath(const std::wstring& filePath)
{
std::wstring::size_type pos = filePath.find_last_of(L"\\/");
if (pos != std::wstring::npos)
{
return filePath.substr(0, pos + 1);
}
return L".\\";
}
/*
** Extracts volume path from program path.
** E.g.:
** "C:\path\" to "C:"
** "\\server\share\" to "\\server\share"
** "\\server\C:\path\" to "\\server\C:"
*/
std::wstring GetVolume(const std::wstring& path)
{
std::wstring::size_type pos;
if ((pos = path.find_first_of(L':')) != std::wstring::npos)
{
return path.substr(0, pos + 1);
}
else if (IsUNC(path))
{
if ((pos = path.find_first_of(L"\\/", 2)) != std::wstring::npos)
{
std::wstring::size_type pos2;
if ((pos2 = path.find_first_of(L"\\/", pos + 1)) != std::wstring::npos ||
pos != (path.length() - 1))
{
pos = pos2;
}
}
return path.substr(0, pos);
}
return std::wstring();
}
void ExpandEnvironmentVariables(std::wstring& path)
{
std::wstring::size_type pos;
if ((pos = path.find(L'%')) != std::wstring::npos &&
path.find(L'%', pos + 2) != std::wstring::npos)
{
DWORD bufSize = 4096;
WCHAR* buffer = new WCHAR[bufSize];
// %APPDATA% is a special case.
pos = path.find(L"%APPDATA%", pos);
if (pos != std::wstring::npos)
{
HRESULT hr = SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, buffer);
if (SUCCEEDED(hr))
{
size_t len = wcslen(buffer);
do
{
path.replace(pos, 9, buffer, len);
}
while ((pos = path.find(L"%APPDATA%", pos + len)) != std::wstring::npos);
}
}
if ((pos = path.find(L'%')) != std::wstring::npos &&
path.find(L'%', pos + 2) != std::wstring::npos)
{
// Expand the environment variables.
do
{
DWORD ret = ExpandEnvironmentStrings(path.c_str(), buffer, bufSize);
if (ret == 0) // Error
{
break;
}
if (ret <= bufSize) // Fits in the buffer
{
path.assign(buffer, ret - 1);
break;
}
delete [] buffer;
bufSize = ret;
buffer = new WCHAR[bufSize];
}
while (true);
}
delete [] buffer;
}
}
} // namespace PathUtil
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "PathUtil.h"
namespace PathUtil {
bool IsSeparator(WCHAR ch)
{
return ch == L'\\' || ch == L'/';
}
bool IsDotOrDotDot(const WCHAR* path)
{
return path[0] == L'.' && (path[1] == L'\0' || (path[1] == L'.' && path[2] == L'\0'));
}
bool IsUNC(const std::wstring& path)
{
return path.length() >= 2 && IsSeparator(path[0]) && IsSeparator(path[1]);
}
bool IsAbsolute(const std::wstring& path)
{
return (path.find(L":\\") != std::wstring::npos ||
path.find(L":/") != std::wstring::npos ||
IsUNC(path));
}
void AppendBacklashIfMissing(std::wstring& path)
{
if (!path.empty() && !IsSeparator(path[path.length() - 1]))
{
path += L'\\';
}
}
std::wstring GetFolderFromFilePath(const std::wstring& filePath)
{
std::wstring::size_type pos = filePath.find_last_of(L"\\/");
if (pos != std::wstring::npos)
{
return filePath.substr(0, pos + 1);
}
return L".\\";
}
/*
** Extracts volume path from program path.
** E.g.:
** "C:\path\" to "C:"
** "\\server\share\" to "\\server\share"
** "\\server\C:\path\" to "\\server\C:"
*/
std::wstring GetVolume(const std::wstring& path)
{
std::wstring::size_type pos;
if ((pos = path.find_first_of(L':')) != std::wstring::npos)
{
return path.substr(0, pos + 1);
}
else if (IsUNC(path))
{
if ((pos = path.find_first_of(L"\\/", 2)) != std::wstring::npos)
{
std::wstring::size_type pos2;
if ((pos2 = path.find_first_of(L"\\/", pos + 1)) != std::wstring::npos ||
pos != (path.length() - 1))
{
pos = pos2;
}
}
return path.substr(0, pos);
}
return std::wstring();
}
void ExpandEnvironmentVariables(std::wstring& path)
{
std::wstring::size_type pos;
if ((pos = path.find(L'%')) != std::wstring::npos &&
path.find(L'%', pos + 2) != std::wstring::npos)
{
DWORD bufSize = 4096;
WCHAR* buffer = new WCHAR[bufSize];
// %APPDATA% is a special case.
pos = path.find(L"%APPDATA%", pos);
if (pos != std::wstring::npos)
{
HRESULT hr = SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, buffer);
if (SUCCEEDED(hr))
{
size_t len = wcslen(buffer);
do
{
path.replace(pos, 9, buffer, len);
}
while ((pos = path.find(L"%APPDATA%", pos + len)) != std::wstring::npos);
}
}
if ((pos = path.find(L'%')) != std::wstring::npos &&
path.find(L'%', pos + 2) != std::wstring::npos)
{
// Expand the environment variables.
do
{
DWORD ret = ExpandEnvironmentStrings(path.c_str(), buffer, bufSize);
if (ret == 0) // Error
{
break;
}
if (ret <= bufSize) // Fits in the buffer
{
path.assign(buffer, ret - 1);
break;
}
delete [] buffer;
bufSize = ret;
buffer = new WCHAR[bufSize];
}
while (true);
}
delete [] buffer;
}
}
} // namespace PathUtil

View File

@ -1,45 +1,45 @@
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_PATHUTIL_H_
#define RM_COMMON_PATHUTIL_H_
#include <Windows.h>
#include <string>
namespace PathUtil {
bool IsSeparator(WCHAR ch);
bool IsDotOrDotDot(const WCHAR* path);
bool IsUNC(const std::wstring& path);
bool IsAbsolute(const std::wstring& path);
void AppendBacklashIfMissing(std::wstring& path);
std::wstring GetFolderFromFilePath(const std::wstring& filePath);
std::wstring GetVolume(const std::wstring& path);
void ExpandEnvironmentVariables(std::wstring& strPath);
} // namespace PathUtil
#endif
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_PATHUTIL_H_
#define RM_COMMON_PATHUTIL_H_
#include <Windows.h>
#include <string>
namespace PathUtil {
bool IsSeparator(WCHAR ch);
bool IsDotOrDotDot(const WCHAR* path);
bool IsUNC(const std::wstring& path);
bool IsAbsolute(const std::wstring& path);
void AppendBacklashIfMissing(std::wstring& path);
std::wstring GetFolderFromFilePath(const std::wstring& filePath);
std::wstring GetVolume(const std::wstring& path);
void ExpandEnvironmentVariables(std::wstring& strPath);
} // namespace PathUtil
#endif

View File

@ -1,106 +1,106 @@
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "PathUtil.h"
#include "UnitTest.h"
#include <Shlobj.h>
namespace PathUtil {
TEST_CLASS(Common_PathUtil_Test)
{
public:
TEST_METHOD(TestIsSeparator)
{
Assert::IsTrue(IsSeparator(L'\\'));
Assert::IsTrue(IsSeparator(L'/'));
Assert::IsFalse(IsSeparator(L'.'));
}
TEST_METHOD(TestIsDotOrDotDot)
{
Assert::IsTrue(IsDotOrDotDot(L"."));
Assert::IsTrue(IsDotOrDotDot(L".."));
Assert::IsFalse(IsDotOrDotDot(L"..."));
Assert::IsFalse(IsDotOrDotDot(L""));
}
TEST_METHOD(TestIsUNC)
{
Assert::IsTrue(IsUNC(L"\\\\server"));
Assert::IsTrue(IsUNC(L"//server"));
}
TEST_METHOD(TestIsAbsolute)
{
Assert::IsTrue(IsAbsolute(L"\\\\server"));
Assert::IsTrue(IsAbsolute(L"C:\\test"));
Assert::IsTrue(IsAbsolute(L"C:/test"));
Assert::IsFalse(IsAbsolute(L"C:"));
}
TEST_METHOD(TestAppendBacklashIfMissing)
{
std::wstring path;
AppendBacklashIfMissing(path);
Assert::IsTrue(path.empty());
std::wstring path2 = L"C:\\test";
AppendBacklashIfMissing(path2);
Assert::IsTrue(path2 == L"C:\\test\\");
std::wstring path3 = L"C:\\test\\";
AppendBacklashIfMissing(path3);
Assert::IsTrue(path3 == L"C:\\test\\");
}
TEST_METHOD(TestGetFolderFromFilePath)
{
Assert::IsTrue(GetFolderFromFilePath(L"C:\\test.txt") == L"C:\\");
}
TEST_METHOD(TestGetVolume)
{
Assert::IsTrue(GetVolume(L"C:\\test.txt") == L"C:");
Assert::IsTrue(GetVolume(L"\\\\server\\share\\") == L"\\\\server\\share");
Assert::IsTrue(GetVolume(L"\\\\server\\C:\\path\\") == L"\\\\server\\C:");
}
TEST_METHOD(TestExpandEnvironmentVariables)
{
WCHAR appdataPath[MAX_PATH];
SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, appdataPath);
WCHAR windirPath[MAX_PATH];
ExpandEnvironmentStrings(L"%WINDIR%", windirPath, MAX_PATH);
std::wstring test = L"%APPDATA%";
PathUtil::ExpandEnvironmentVariables(test);
Assert::IsTrue(test == appdataPath);
std::wstring test2 = L"%APPDATA%%WINDIR%";
PathUtil::ExpandEnvironmentVariables(test2);
Assert::IsTrue(test2 == ((std::wstring)appdataPath + windirPath));
std::wstring test3 = L"%APPDATA%%WINDIR%%APPDATA%";
PathUtil::ExpandEnvironmentVariables(test3);
Assert::IsTrue(test3 == ((std::wstring)appdataPath + windirPath + appdataPath));
}
};
} // namespace PathUtil
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "PathUtil.h"
#include "UnitTest.h"
#include <Shlobj.h>
namespace PathUtil {
TEST_CLASS(Common_PathUtil_Test)
{
public:
TEST_METHOD(TestIsSeparator)
{
Assert::IsTrue(IsSeparator(L'\\'));
Assert::IsTrue(IsSeparator(L'/'));
Assert::IsFalse(IsSeparator(L'.'));
}
TEST_METHOD(TestIsDotOrDotDot)
{
Assert::IsTrue(IsDotOrDotDot(L"."));
Assert::IsTrue(IsDotOrDotDot(L".."));
Assert::IsFalse(IsDotOrDotDot(L"..."));
Assert::IsFalse(IsDotOrDotDot(L""));
}
TEST_METHOD(TestIsUNC)
{
Assert::IsTrue(IsUNC(L"\\\\server"));
Assert::IsTrue(IsUNC(L"//server"));
}
TEST_METHOD(TestIsAbsolute)
{
Assert::IsTrue(IsAbsolute(L"\\\\server"));
Assert::IsTrue(IsAbsolute(L"C:\\test"));
Assert::IsTrue(IsAbsolute(L"C:/test"));
Assert::IsFalse(IsAbsolute(L"C:"));
}
TEST_METHOD(TestAppendBacklashIfMissing)
{
std::wstring path;
AppendBacklashIfMissing(path);
Assert::IsTrue(path.empty());
std::wstring path2 = L"C:\\test";
AppendBacklashIfMissing(path2);
Assert::IsTrue(path2 == L"C:\\test\\");
std::wstring path3 = L"C:\\test\\";
AppendBacklashIfMissing(path3);
Assert::IsTrue(path3 == L"C:\\test\\");
}
TEST_METHOD(TestGetFolderFromFilePath)
{
Assert::IsTrue(GetFolderFromFilePath(L"C:\\test.txt") == L"C:\\");
}
TEST_METHOD(TestGetVolume)
{
Assert::IsTrue(GetVolume(L"C:\\test.txt") == L"C:");
Assert::IsTrue(GetVolume(L"\\\\server\\share\\") == L"\\\\server\\share");
Assert::IsTrue(GetVolume(L"\\\\server\\C:\\path\\") == L"\\\\server\\C:");
}
TEST_METHOD(TestExpandEnvironmentVariables)
{
WCHAR appdataPath[MAX_PATH];
SHGetFolderPath(nullptr, CSIDL_APPDATA, nullptr, SHGFP_TYPE_CURRENT, appdataPath);
WCHAR windirPath[MAX_PATH];
ExpandEnvironmentStrings(L"%WINDIR%", windirPath, MAX_PATH);
std::wstring test = L"%APPDATA%";
PathUtil::ExpandEnvironmentVariables(test);
Assert::IsTrue(test == appdataPath);
std::wstring test2 = L"%APPDATA%%WINDIR%";
PathUtil::ExpandEnvironmentVariables(test2);
Assert::IsTrue(test2 == ((std::wstring)appdataPath + windirPath));
std::wstring test3 = L"%APPDATA%%WINDIR%%APPDATA%";
PathUtil::ExpandEnvironmentVariables(test3);
Assert::IsTrue(test3 == ((std::wstring)appdataPath + windirPath + appdataPath));
}
};
} // namespace PathUtil

View File

@ -1,102 +1,102 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Platform.h"
namespace Platform {
LPCWSTR GetPlatformName()
{
const bool isServer = IsWindowsServer();
// Note: Place newer versions at the top.
if (IsWindows8Point1OrGreater()) return isServer ? L"Windows Server 2012 R2" : L"Windows 8.1";
if (IsWindows8OrGreater()) return isServer ? L"Windows Server 2012" : L"Windows 8";
if (IsWindows7OrGreater()) return isServer ? L"Windows Server 2008 R2" : L"Windows 7";
if (IsWindowsVistaOrGreater()) return isServer ? L"Windows Server 2008" : L"Windows Vista";
if (IsWindowsXPOrGreater()) return isServer ? L"Windows Server 2003" : L"Windows XP";
return L"Unknown";
}
std::wstring GetPlatformFriendlyName()
{
std::wstring name;
WCHAR buffer[256];
DWORD size = _countof(buffer);
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, L"ProductName", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += buffer;
name += L' ';
name += Is64BitWindows() ? L"64" : L"32";
name += L"-bit";
size = _countof(buffer);
if (RegQueryValueEx(hKey, L"CurrentBuildNumber", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS ||
RegQueryValueEx(hKey, L"CurrentBuild", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += L" (build ";
name += buffer;
name += L')';
}
size = _countof(buffer);
if (RegQueryValueEx(hKey, L"CSDVersion", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += L' ';
name += buffer;
}
}
RegCloseKey(hKey);
}
else
{
name = L"Windows version unknown";
}
return name;
}
/*
** Returns |true| if running on 64-bit Windows.
*/
bool Is64BitWindows()
{
#if _WIN64
return true;
#endif
auto isWow64Process = (decltype(IsWow64Process)*)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process");
if (isWow64Process)
{
BOOL isWow64 = FALSE;
return isWow64Process(GetCurrentProcess(), &isWow64) && isWow64;
}
return false;
}
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Platform.h"
namespace Platform {
LPCWSTR GetPlatformName()
{
const bool isServer = IsWindowsServer();
// Note: Place newer versions at the top.
if (IsWindows8Point1OrGreater()) return isServer ? L"Windows Server 2012 R2" : L"Windows 8.1";
if (IsWindows8OrGreater()) return isServer ? L"Windows Server 2012" : L"Windows 8";
if (IsWindows7OrGreater()) return isServer ? L"Windows Server 2008 R2" : L"Windows 7";
if (IsWindowsVistaOrGreater()) return isServer ? L"Windows Server 2008" : L"Windows Vista";
if (IsWindowsXPOrGreater()) return isServer ? L"Windows Server 2003" : L"Windows XP";
return L"Unknown";
}
std::wstring GetPlatformFriendlyName()
{
std::wstring name;
WCHAR buffer[256];
DWORD size = _countof(buffer);
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{
if (RegQueryValueEx(hKey, L"ProductName", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += buffer;
name += L' ';
name += Is64BitWindows() ? L"64" : L"32";
name += L"-bit";
size = _countof(buffer);
if (RegQueryValueEx(hKey, L"CurrentBuildNumber", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS ||
RegQueryValueEx(hKey, L"CurrentBuild", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += L" (build ";
name += buffer;
name += L')';
}
size = _countof(buffer);
if (RegQueryValueEx(hKey, L"CSDVersion", nullptr, nullptr, (LPBYTE)buffer, (LPDWORD)&size) == ERROR_SUCCESS)
{
name += L' ';
name += buffer;
}
}
RegCloseKey(hKey);
}
else
{
name = L"Windows version unknown";
}
return name;
}
/*
** Returns |true| if running on 64-bit Windows.
*/
bool Is64BitWindows()
{
#if _WIN64
return true;
#endif
auto isWow64Process = (decltype(IsWow64Process)*)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process");
if (isWow64Process)
{
BOOL isWow64 = FALSE;
return isWow64Process(GetCurrentProcess(), &isWow64) && isWow64;
}
return false;
}
} // namespace Platform

View File

@ -1,32 +1,32 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_PLATFORM_H_
#define RM_COMMON_PLATFORM_H_
#include <string>
namespace Platform {
LPCWSTR GetPlatformName();
std::wstring GetPlatformFriendlyName();
bool Is64BitWindows();
} // namespace Platform
#endif
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_PLATFORM_H_
#define RM_COMMON_PLATFORM_H_
#include <string>
namespace Platform {
LPCWSTR GetPlatformName();
std::wstring GetPlatformFriendlyName();
bool Is64BitWindows();
} // namespace Platform
#endif

View File

@ -1,92 +1,92 @@
/*
Copyright (C) 2011 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_RAWSTRING_H_
#define RM_COMMON_RAWSTRING_H_
#include <malloc.h>
class RawString
{
public:
RawString() :
m_String()
{
}
RawString(const wchar_t* str) :
m_String(str_alloc(str))
{
}
RawString(const RawString& rhs) :
m_String(str_alloc(rhs.c_str()))
{
}
~RawString()
{
clear();
}
RawString& operator=(const wchar_t* rhs)
{
clear();
m_String = str_alloc(rhs);
return *this;
}
RawString& operator=(const RawString& rhs)
{
if (&rhs != this)
{
clear();
m_String = str_alloc(rhs.m_String);
}
return *this;
}
const wchar_t* c_str() const
{
return m_String ? m_String : L"";
}
bool empty() const
{
return !m_String || !(*m_String);
}
void clear()
{
if (m_String)
{
free(m_String);
m_String = nullptr;
}
}
private:
wchar_t* str_alloc(const wchar_t* str)
{
return str ? _wcsdup(str) : nullptr;
}
wchar_t* m_String;
};
#endif
/*
Copyright (C) 2011 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_RAWSTRING_H_
#define RM_COMMON_RAWSTRING_H_
#include <malloc.h>
class RawString
{
public:
RawString() :
m_String()
{
}
RawString(const wchar_t* str) :
m_String(str_alloc(str))
{
}
RawString(const RawString& rhs) :
m_String(str_alloc(rhs.c_str()))
{
}
~RawString()
{
clear();
}
RawString& operator=(const wchar_t* rhs)
{
clear();
m_String = str_alloc(rhs);
return *this;
}
RawString& operator=(const RawString& rhs)
{
if (&rhs != this)
{
clear();
m_String = str_alloc(rhs.m_String);
}
return *this;
}
const wchar_t* c_str() const
{
return m_String ? m_String : L"";
}
bool empty() const
{
return !m_String || !(*m_String);
}
void clear()
{
if (m_String)
{
free(m_String);
m_String = nullptr;
}
}
private:
wchar_t* str_alloc(const wchar_t* str)
{
return str ? _wcsdup(str) : nullptr;
}
wchar_t* m_String;
};
#endif

View File

@ -1,95 +1,95 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "StringUtil.h"
namespace StringUtil {
std::string Narrow(const WCHAR* str, int strLen, int cp)
{
std::string narrowStr;
if (str && *str)
{
if (strLen == -1)
{
strLen = (int)wcslen(str);
}
int bufLen = WideCharToMultiByte(cp, 0, str, strLen, nullptr, 0, nullptr, nullptr);
if (bufLen > 0)
{
narrowStr.resize(bufLen);
WideCharToMultiByte(cp, 0, str, strLen, &narrowStr[0], bufLen, nullptr, nullptr);
}
}
return narrowStr;
}
std::wstring Widen(const char* str, int strLen, int cp)
{
std::wstring wideStr;
if (str && *str)
{
if (strLen == -1)
{
strLen = (int)strlen(str);
}
int bufLen = MultiByteToWideChar(cp, 0, str, strLen, nullptr, 0);
if (bufLen > 0)
{
wideStr.resize(bufLen);
MultiByteToWideChar(cp, 0, str, strLen, &wideStr[0], bufLen);
}
}
return wideStr;
}
/*
** Escapes reserved PCRE regex metacharacters.
*/
void EscapeRegExp(std::wstring& str)
{
size_t start = 0;
while ((start = str.find_first_of(L"\\^$|()[{.+*?", start)) != std::wstring::npos)
{
str.insert(start, L"\\");
start += 2;
}
}
/*
** Escapes reserved URL characters.
*/
void EncodeUrl(std::wstring& str)
{
size_t pos = 0;
while ((pos = str.find_first_of(L" !*'();:@&=+$,/?#[]", pos)) != std::wstring::npos)
{
WCHAR buffer[3];
_snwprintf_s(buffer, _countof(buffer), L"%.2X", str[pos]);
str[pos] = L'%';
str.insert(pos + 1, buffer);
pos += 3;
}
}
} // namespace StringUtil
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "StringUtil.h"
namespace StringUtil {
std::string Narrow(const WCHAR* str, int strLen, int cp)
{
std::string narrowStr;
if (str && *str)
{
if (strLen == -1)
{
strLen = (int)wcslen(str);
}
int bufLen = WideCharToMultiByte(cp, 0, str, strLen, nullptr, 0, nullptr, nullptr);
if (bufLen > 0)
{
narrowStr.resize(bufLen);
WideCharToMultiByte(cp, 0, str, strLen, &narrowStr[0], bufLen, nullptr, nullptr);
}
}
return narrowStr;
}
std::wstring Widen(const char* str, int strLen, int cp)
{
std::wstring wideStr;
if (str && *str)
{
if (strLen == -1)
{
strLen = (int)strlen(str);
}
int bufLen = MultiByteToWideChar(cp, 0, str, strLen, nullptr, 0);
if (bufLen > 0)
{
wideStr.resize(bufLen);
MultiByteToWideChar(cp, 0, str, strLen, &wideStr[0], bufLen);
}
}
return wideStr;
}
/*
** Escapes reserved PCRE regex metacharacters.
*/
void EscapeRegExp(std::wstring& str)
{
size_t start = 0;
while ((start = str.find_first_of(L"\\^$|()[{.+*?", start)) != std::wstring::npos)
{
str.insert(start, L"\\");
start += 2;
}
}
/*
** Escapes reserved URL characters.
*/
void EncodeUrl(std::wstring& str)
{
size_t pos = 0;
while ((pos = str.find_first_of(L" !*'();:@&=+$,/?#[]", pos)) != std::wstring::npos)
{
WCHAR buffer[3];
_snwprintf_s(buffer, _countof(buffer), L"%.2X", str[pos]);
str[pos] = L'%';
str.insert(pos + 1, buffer);
pos += 3;
}
}
} // namespace StringUtil

View File

@ -1,79 +1,79 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_STRINGUTIL_H_
#define RM_COMMON_STRINGUTIL_H_
#include <Windows.h>
#include <algorithm>
#include <locale>
#include <string>
/*
** Helper class for case insensitive find function.
*/
template<typename CharT>
struct Is_Equal
{
Is_Equal(const std::locale& loc) : locale(loc) { }
bool operator()(CharT ch1, CharT ch2) { return std::toupper(ch1, locale) == std::toupper(ch2, locale); }
private:
const std::locale& locale;
};
namespace StringUtil {
std::string Narrow(const WCHAR* str, int strLen = -1, int cp = CP_ACP);
inline std::string Narrow(const std::wstring& str, int cp = CP_ACP) { return Narrow(str.c_str(), (int)str.length(), cp); }
inline std::string NarrowUTF8(const WCHAR* str, int strLen = -1) { return Narrow(str, strLen, CP_UTF8); }
inline std::string NarrowUTF8(const std::wstring& str) { return Narrow(str.c_str(), (int)str.length(), CP_UTF8); }
std::wstring Widen(const char* str, int strLen = -1, int cp = CP_ACP);
inline std::wstring Widen(const std::string& str, int cp = CP_ACP) { return Widen(str.c_str(), (int)str.length(), cp); }
inline std::wstring WidenUTF8(const char* str, int strLen = -1) { return Widen(str, strLen, CP_UTF8); }
inline std::wstring WidenUTF8(const std::string& str) { return Widen(str.c_str(), (int)str.length(), CP_UTF8); }
void EscapeRegExp(std::wstring& str);
void EncodeUrl(std::wstring& str);
/*
** Case insensitive find function for std::string and std::wstring.
**
** Modified from http://stackoverflow.com/questions/3152241/case-insensitive-stdstring-find#3152296
*/
template<typename T>
std::size_t CaseInsensitiveFind(const T& str1, const T& str2, const std::locale& loc = std::locale())
{
T::const_iterator iter = std::search(str1.begin(), str1.end(),
str2.begin(), str2.end(), Is_Equal<T::value_type>(loc));
if (iter != str1.end())
{
return (iter - str1.begin());
}
return -1; // not found
}
} // namespace StringUtil
#endif
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_STRINGUTIL_H_
#define RM_COMMON_STRINGUTIL_H_
#include <Windows.h>
#include <algorithm>
#include <locale>
#include <string>
/*
** Helper class for case insensitive find function.
*/
template<typename CharT>
struct Is_Equal
{
Is_Equal(const std::locale& loc) : locale(loc) { }
bool operator()(CharT ch1, CharT ch2) { return std::toupper(ch1, locale) == std::toupper(ch2, locale); }
private:
const std::locale& locale;
};
namespace StringUtil {
std::string Narrow(const WCHAR* str, int strLen = -1, int cp = CP_ACP);
inline std::string Narrow(const std::wstring& str, int cp = CP_ACP) { return Narrow(str.c_str(), (int)str.length(), cp); }
inline std::string NarrowUTF8(const WCHAR* str, int strLen = -1) { return Narrow(str, strLen, CP_UTF8); }
inline std::string NarrowUTF8(const std::wstring& str) { return Narrow(str.c_str(), (int)str.length(), CP_UTF8); }
std::wstring Widen(const char* str, int strLen = -1, int cp = CP_ACP);
inline std::wstring Widen(const std::string& str, int cp = CP_ACP) { return Widen(str.c_str(), (int)str.length(), cp); }
inline std::wstring WidenUTF8(const char* str, int strLen = -1) { return Widen(str, strLen, CP_UTF8); }
inline std::wstring WidenUTF8(const std::string& str) { return Widen(str.c_str(), (int)str.length(), CP_UTF8); }
void EscapeRegExp(std::wstring& str);
void EncodeUrl(std::wstring& str);
/*
** Case insensitive find function for std::string and std::wstring.
**
** Modified from http://stackoverflow.com/questions/3152241/case-insensitive-stdstring-find#3152296
*/
template<typename T>
std::size_t CaseInsensitiveFind(const T& str1, const T& str2, const std::locale& loc = std::locale())
{
T::const_iterator iter = std::search(str1.begin(), str1.end(),
str2.begin(), str2.end(), Is_Equal<T::value_type>(loc));
if (iter != str1.end())
{
return (iter - str1.begin());
}
return -1; // not found
}
} // namespace StringUtil
#endif

View File

@ -1,58 +1,58 @@
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StringUtil.h"
#include "UnitTest.h"
namespace StringUtil {
TEST_CLASS(Common_StringUtil_Test)
{
public:
TEST_METHOD(TestWiden)
{
Assert::AreEqual(L"test", Widen("test").c_str());
Assert::AreEqual(L"te", Widen("test", 2).c_str());
Assert::AreEqual(L"\u0422\u0114st", WidenUTF8("\xd0\xa2\xc4\x94st").c_str());
Assert::AreEqual(L"\u0422", WidenUTF8("\xd0\xa2\xc4\x94st", 2).c_str());
}
TEST_METHOD(TestNarrow)
{
Assert::AreEqual("test", Narrow(L"test").c_str());
Assert::AreEqual("te", Narrow(L"test", 2).c_str());
Assert::AreEqual("\xd0\xa2\xc4\x94st", NarrowUTF8(L"\u0422\u0114st").c_str());
Assert::AreEqual("\xd0\xa2", NarrowUTF8(L"\u0422\u0114st", 1).c_str());
}
TEST_METHOD(TestEscapeRegExp)
{
std::wstring str = L"\\^$|(test)[{. ing+*?";
EscapeRegExp(str);
Assert::AreEqual(L"\\\\\\^\\$\\|\\(test\\)\\[\\{\\. ing\\+\\*\\?", str.c_str());
}
TEST_METHOD(TestEncodeUrl)
{
std::wstring str = L" !*'();:@test&=+$,/?#[ing]";
EncodeUrl(str);
Assert::AreEqual(L"%20%21%2A%27%28%29%3B%3A%40test%26%3D%2B%24%2C%2F%3F%23%5Bing%5D", str.c_str());
}
};
} // namespace StringUtil
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StringUtil.h"
#include "UnitTest.h"
namespace StringUtil {
TEST_CLASS(Common_StringUtil_Test)
{
public:
TEST_METHOD(TestWiden)
{
Assert::AreEqual(L"test", Widen("test").c_str());
Assert::AreEqual(L"te", Widen("test", 2).c_str());
Assert::AreEqual(L"\u0422\u0114st", WidenUTF8("\xd0\xa2\xc4\x94st").c_str());
Assert::AreEqual(L"\u0422", WidenUTF8("\xd0\xa2\xc4\x94st", 2).c_str());
}
TEST_METHOD(TestNarrow)
{
Assert::AreEqual("test", Narrow(L"test").c_str());
Assert::AreEqual("te", Narrow(L"test", 2).c_str());
Assert::AreEqual("\xd0\xa2\xc4\x94st", NarrowUTF8(L"\u0422\u0114st").c_str());
Assert::AreEqual("\xd0\xa2", NarrowUTF8(L"\u0422\u0114st", 1).c_str());
}
TEST_METHOD(TestEscapeRegExp)
{
std::wstring str = L"\\^$|(test)[{. ing+*?";
EscapeRegExp(str);
Assert::AreEqual(L"\\\\\\^\\$\\|\\(test\\)\\[\\{\\. ing\\+\\*\\?", str.c_str());
}
TEST_METHOD(TestEncodeUrl)
{
std::wstring str = L" !*'();:@test&=+$,/?#[ing]";
EncodeUrl(str);
Assert::AreEqual(L"%20%21%2A%27%28%29%3B%3A%40test%26%3D%2B%24%2C%2F%3F%23%5Bing%5D", str.c_str());
}
};
} // namespace StringUtil

View File

@ -1,56 +1,56 @@
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_TIMER_H_
#define RM_COMMON_TIMER_H_
#include <Windows.h>
// Performs timing using the high-resolution performance counter.
class Timer
{
public:
void Start()
{
QueryPerformanceCounter(&m_Start);
}
void Stop()
{
QueryPerformanceCounter(&m_Stop);
}
// Returns the elapsed time in milliseconds.
double GetElapsed() const
{
static LARGE_INTEGER s_Frequency = []()
{
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
return frequency;
} ();
return (m_Stop.QuadPart - m_Start.QuadPart) * 1000.0 / s_Frequency.QuadPart;
}
private:
LARGE_INTEGER m_Start;
LARGE_INTEGER m_Stop;
};
#endif
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_COMMON_TIMER_H_
#define RM_COMMON_TIMER_H_
#include <Windows.h>
// Performs timing using the high-resolution performance counter.
class Timer
{
public:
void Start()
{
QueryPerformanceCounter(&m_Start);
}
void Stop()
{
QueryPerformanceCounter(&m_Stop);
}
// Returns the elapsed time in milliseconds.
double GetElapsed() const
{
static LARGE_INTEGER s_Frequency = []()
{
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
return frequency;
} ();
return (m_Stop.QuadPart - m_Start.QuadPart) * 1000.0 / s_Frequency.QuadPart;
}
private:
LARGE_INTEGER m_Start;
LARGE_INTEGER m_Stop;
};
#endif

View File

@ -1,26 +1,26 @@
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <CppUnitTest.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
// VS IntelliSense doesn't seem to work well with the CppUnitTest.h TEST_CLASS macro. This is a
// simpler version, which seems to work fine.
#undef TEST_CLASS
#define TEST_CLASS(className) class className : public TestClass<className>
/*
Copyright (C) 2013 Rainmeter Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <CppUnitTest.h>
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
// VS IntelliSense doesn't seem to work well with the CppUnitTest.h TEST_CLASS macro. This is a
// simpler version, which seems to work fine.
#undef TEST_CLASS
#define TEST_CLASS(className) class className : public TestClass<className>

View File

@ -1,39 +1,39 @@
## Building Rainmeter
### Get the source code
Use <a href="http://git-scm.com">Git</a> to clone the repository:
git clone https://github.com/rainmeter/rainmeter.git
Alternatively, download the repository contents as a [ZIP archive](https://github.com/rainmeter/rainmeter/archive/master.zip).
### Building with Visual Studio
Rainmeter can be built using any version of Visual Studio 2013. If you don't already have VS2013, you can download the free "Visual Studio Express 2013 for Windows Desktop" version [here](http://www.visualstudio.com/downloads/download-visual-studio-vs).
After Visual Studio has been installed and updated, open Rainmeter.sln at the root of the repository to build.
### Building the installer
First, download and install <a href="https://code.google.com/p/unsis/downloads/list">NSIS Unicode</a> (download the Unicode version, not the ANSI version).
Now you can simply run the <b>Build.bat</b> batch file in the Build folder of your local repository. If you see any "not found" errors, check that the paths in the `set` commands at the top of the file match your environment. To build the release (non-beta) installer, use `Build.bat RELEASE`.
To digitally sign the installer and the Rainmeter executables, obtain a Windows code signing certificate and create a Certificate.bat file alongside Build.bat with the following contents:
set CERTFILE=/path/to/PFXcert.p12
set CERTKEY=certpassword
### Building old versions
The Rainmeter GitHub repository does not contain the full source code history required to build the installer for versions prior to r1249. To obtain the full source from r1 to r1248, use the old Google Code SVN repository located at:
http://rainmeter.googlecode.com/svn
The build instructions above are applicable to r1130 - r1248. Build instructions for r27 - r1129 can be found in svn/wiki/.
## Building Rainmeter
### Get the source code
Use <a href="http://git-scm.com">Git</a> to clone the repository:
git clone https://github.com/rainmeter/rainmeter.git
Alternatively, download the repository contents as a [ZIP archive](https://github.com/rainmeter/rainmeter/archive/master.zip).
### Building with Visual Studio
Rainmeter can be built using any version of Visual Studio 2013. If you don't already have VS2013, you can download the free "Visual Studio Express 2013 for Windows Desktop" version [here](http://www.visualstudio.com/downloads/download-visual-studio-vs).
After Visual Studio has been installed and updated, open Rainmeter.sln at the root of the repository to build.
### Building the installer
First, download and install <a href="https://code.google.com/p/unsis/downloads/list">NSIS Unicode</a> (download the Unicode version, not the ANSI version).
Now you can simply run the <b>Build.bat</b> batch file in the Build folder of your local repository. If you see any "not found" errors, check that the paths in the `set` commands at the top of the file match your environment. To build the release (non-beta) installer, use `Build.bat RELEASE`.
To digitally sign the installer and the Rainmeter executables, obtain a Windows code signing certificate and create a Certificate.bat file alongside Build.bat with the following contents:
set CERTFILE=/path/to/PFXcert.p12
set CERTKEY=certpassword
### Building old versions
The Rainmeter GitHub repository does not contain the full source code history required to build the installer for versions prior to r1249. To obtain the full source from r1 to r1248, use the old Google Code SVN repository located at:
http://rainmeter.googlecode.com/svn
The build instructions above are applicable to r1130 - r1248. Build instructions for r27 - r1129 can be found in svn/wiki/.
The language files for r963 - r1214 were in a separate repository (svn:externals), which is not available any longer. As a result, the language .dll's for those revisions cannot be built.

View File

@ -1,32 +1,32 @@
Rainmeter uses the [Visual Studio Native Unit Testing framework](http://msdn.microsoft.com/en-us/library/hh598953.aspx) for unit testing.
### General notes
All unit test files should have the `<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>` property set. The easiest way to ensure this is to manually edit the `ClCompile` entry of the project .vcxproj file. Make sure it looks something like this:
<ClCompile Include="ConfigParser_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
When building within Visual Studio, the macro `$(ExcludeTests)` evaluates to `false` (i.e. the test files are **not** excluded). When building using Build.bat, it evaluates to `true`, and, consequently, the test files are excluded from the build. This is done in order to both reduce the actual build size and remove any kind of dependency on *Microsoft.VisualStudio.TestTools.CppUnitTestFramework.dll* (see below).
### Project type specific notes
* Static library projects:
Unit testing static library project requires the use of a separate DLL project. The static library project contains the actual code while the DLL project references the static library and includes the testing code.
See `Common\Common.vcxproj` and `Common\Common_Test.vcxproj` for an example.
* Dynamic library projects:
A unit tested dynamic library project should contain both the actual code and the testing code.
In addition, the `$(DelayLoadTestDLL)` macro should be included in the linker *Delay Loaded Dlls* option. The VS unit testing framework introduces a dependency on *Microsoft.VisualStudio.TestTools.CppUnitTestFramework.dll* for dynamic library projects, which means that omitting the `$(DelayLoadTestDLL)` macro will result in the dynamic library failing to load.
### Running tests
When you build the test project, the tests appear in **Test Explorer**. If Test Explorer is not visible, choose **Test** on the Visual Studio menu, choose **Windows**, and then choose **Test Explorer**. From there, you can run all or a subset of the tests.
Rainmeter uses the [Visual Studio Native Unit Testing framework](http://msdn.microsoft.com/en-us/library/hh598953.aspx) for unit testing.
### General notes
All unit test files should have the `<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>` property set. The easiest way to ensure this is to manually edit the `ClCompile` entry of the project .vcxproj file. Make sure it looks something like this:
<ClCompile Include="ConfigParser_Test.cpp">
<ExcludedFromBuild>$(ExcludeTests)</ExcludedFromBuild>
</ClCompile>
When building within Visual Studio, the macro `$(ExcludeTests)` evaluates to `false` (i.e. the test files are **not** excluded). When building using Build.bat, it evaluates to `true`, and, consequently, the test files are excluded from the build. This is done in order to both reduce the actual build size and remove any kind of dependency on *Microsoft.VisualStudio.TestTools.CppUnitTestFramework.dll* (see below).
### Project type specific notes
* Static library projects:
Unit testing static library project requires the use of a separate DLL project. The static library project contains the actual code while the DLL project references the static library and includes the testing code.
See `Common\Common.vcxproj` and `Common\Common_Test.vcxproj` for an example.
* Dynamic library projects:
A unit tested dynamic library project should contain both the actual code and the testing code.
In addition, the `$(DelayLoadTestDLL)` macro should be included in the linker *Delay Loaded Dlls* option. The VS unit testing framework introduces a dependency on *Microsoft.VisualStudio.TestTools.CppUnitTestFramework.dll* for dynamic library projects, which means that omitting the `$(DelayLoadTestDLL)` macro will result in the dynamic library failing to load.
### Running tests
When you build the test project, the tests appear in **Test Explorer**. If Test Explorer is not visible, choose **Test** on the Visual Studio menu, choose **Windows**, and then choose **Test Explorer**. From there, you can run all or a subset of the tests.

View File

@ -1,100 +1,100 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Application.h"
#include "DialogInstall.h"
#include "Install.h"
#include "Resource.h"
bool IsSupportedPlatform();
bool IsSupportedCPU();
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR cmdLine, int)
{
CoInitialize(nullptr);
InitCommonControls();
if (*cmdLine)
{
InstallOptions options;
const int scans = swscanf(
cmdLine, L"OPT:%259[^|]|%ld|%hd|%hd|%d",
options.targetPath,
&options.language,
&options.type,
&options.arch,
&options.launchOnLogin);
if (scans == 5)
{
DoInstall(options);
return 0;
}
return 1;
}
if (!IsSupportedPlatform())
{
MessageBox(
nullptr,
L"Windows XP SP2 or higher is required to install Rainmeter.",
L"Rainmeter Setup", MB_OK | MB_ICONERROR);
return (int)InstallStatus::UnsupportedPlatform;
}
if (!IsSupportedCPU())
{
MessageBox(
nullptr,
L"A Pentium III or later processor is required to install Rainmeter.",
L"Rainmeter Setup", MB_OK | MB_ICONERROR);
return (int)InstallStatus::UnsupportedPlatform;
}
CDialogInstall::Create();
return 0;
}
bool IsSupportedPlatform()
{
OSVERSIONINFOEX osvi = { sizeof(OSVERSIONINFOEX) };
GetVersionEx((OSVERSIONINFO*)&osvi);
if (osvi.wProductType != VER_NT_WORKSTATION ||
(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0))
{
// 2000 or lower.
return false;
}
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 &&
osvi.wServicePackMajor <= (GetSystemMetrics(SM_SERVERR2) == 0 ? 0 : 1))
{
// XP SP1 or lower, 2003 SP0.
return FALSE;
}
return TRUE;
}
bool IsSupportedCPU()
{
return IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0;
}
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Application.h"
#include "DialogInstall.h"
#include "Install.h"
#include "Resource.h"
bool IsSupportedPlatform();
bool IsSupportedCPU();
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR cmdLine, int)
{
CoInitialize(nullptr);
InitCommonControls();
if (*cmdLine)
{
InstallOptions options;
const int scans = swscanf(
cmdLine, L"OPT:%259[^|]|%ld|%hd|%hd|%d",
options.targetPath,
&options.language,
&options.type,
&options.arch,
&options.launchOnLogin);
if (scans == 5)
{
DoInstall(options);
return 0;
}
return 1;
}
if (!IsSupportedPlatform())
{
MessageBox(
nullptr,
L"Windows XP SP2 or higher is required to install Rainmeter.",
L"Rainmeter Setup", MB_OK | MB_ICONERROR);
return (int)InstallStatus::UnsupportedPlatform;
}
if (!IsSupportedCPU())
{
MessageBox(
nullptr,
L"A Pentium III or later processor is required to install Rainmeter.",
L"Rainmeter Setup", MB_OK | MB_ICONERROR);
return (int)InstallStatus::UnsupportedPlatform;
}
CDialogInstall::Create();
return 0;
}
bool IsSupportedPlatform()
{
OSVERSIONINFOEX osvi = { sizeof(OSVERSIONINFOEX) };
GetVersionEx((OSVERSIONINFO*)&osvi);
if (osvi.wProductType != VER_NT_WORKSTATION ||
(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0))
{
// 2000 or lower.
return false;
}
if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 &&
osvi.wServicePackMajor <= (GetSystemMetrics(SM_SERVERR2) == 0 ? 0 : 1))
{
// XP SP1 or lower, 2003 SP0.
return FALSE;
}
return TRUE;
}
bool IsSupportedCPU()
{
return IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0;
}

View File

@ -1,32 +1,32 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_INSTALLER_APPLICATION_H_
#define RM_INSTALLER_APPLICATION_H_
enum class InstallStatus
{
Success,
Error,
UnsupportedPlatform,
VcRedist2010Missing,
VcRedist2012Missing,
DotNetRedistMissing
};
#endif
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_INSTALLER_APPLICATION_H_
#define RM_INSTALLER_APPLICATION_H_
enum class InstallStatus
{
Success,
Error,
UnsupportedPlatform,
VcRedist2010Missing,
VcRedist2012Missing,
DotNetRedistMissing
};
#endif

View File

@ -1,494 +1,494 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "DialogInstall.h"
#include "Install.h"
#include "Resource.h"
#include "Util.h"
#include "../Common/ControlTemplate.h"
#define APPNAME L"Rainmeter"
const WCHAR* kRegistryInstallKey = L"SOFTWARE\\" APPNAME;
CDialogInstall* CDialogInstall::c_Dialog = nullptr;
HICON GetIcon(UINT id, bool large)
{
typedef HRESULT (WINAPI * FPLOADICONMETRIC)(HINSTANCE hinst, PCWSTR pszName, int lims, HICON* phico);
HINSTANCE hExe = GetModuleHandle(nullptr);
HINSTANCE hComctl = GetModuleHandle(L"Comctl32");
if (hComctl)
{
// Try LoadIconMetric for better quality with high DPI
FPLOADICONMETRIC loadIconMetric = (FPLOADICONMETRIC)GetProcAddress(hComctl, "LoadIconMetric");
if (loadIconMetric)
{
HICON icon;
HRESULT hr = loadIconMetric(hExe, MAKEINTRESOURCE(id), large ? LIM_LARGE : LIM_SMALL, &icon);
if (SUCCEEDED(hr))
{
return icon;
}
}
}
return (HICON)LoadImage(
hExe,
MAKEINTRESOURCE(id),
IMAGE_ICON,
GetSystemMetrics(large ? SM_CXICON : SM_CXSMICON),
GetSystemMetrics(large ? SM_CYICON : SM_CYSMICON),
LR_SHARED);
}
WCHAR* GetString(UINT id)
{
switch (id)
{
case 1: return L"Install";
case 2: return L"Rainmeter 3.0.2 beta setup";
case 3: return L"Click 'Install' to proceed. Rainmeter will launch after setup.";
case 5: return L"Close";
case 6: return L"Language:";
case 7: return L"Destination folder:";
case 9: return L"...";
case 10: return L"Launch Rainmeter automatically on login";
case 13: return L"Cancel";
case 14: return L"C:\\Program Files\\Rainmeter";
case 15: return L"Standard install (recommended)";
case 16: return L"Portable install";
case 17: return L"Installation type:";
}
return L"";
}
CDialogInstall::CDialogInstall() : Dialog(),
m_InstallProcess(),
m_InstallProcessWaitThread()
{
}
CDialogInstall::~CDialogInstall()
{
}
CDialogInstall* CDialogInstall::Create()
{
c_Dialog = new CDialogInstall();
c_Dialog->ShowDialogWindow(
L"Rainmeter Setup",
0, 0, 350, 210,
DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU,
WS_EX_APPWINDOW | WS_EX_CONTROLPARENT,
nullptr,
false);
return c_Dialog;
}
INT_PTR CDialogInstall::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
return OnInitDialog(wParam, lParam);
case WM_ACTIVATE:
return OnActivate(wParam, lParam);
case WM_COMMAND:
return OnCommand(wParam, lParam);
case WM_NOTIFY:
return OnNotify(wParam, lParam);
case WM_CLOSE:
{
delete this;
}
return TRUE;
}
return FALSE;
}
INT_PTR CDialogInstall::OnInitDialog(WPARAM wParam, LPARAM lParam)
{
static const ControlTemplate::Control s_Controls[] =
{
CT_ICON(Id_HeaderIcon, 0,
10, 10, 24, 24,
WS_VISIBLE, 0),
CT_LABEL(Id_HeaderTitleLabel, 2,
40, 6, 250, 14,
WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0),
CT_LABEL(-1, 3,
40, 20, 250, 9,
WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0),
CT_BUTTON(Id_InstallButton, 1,
199, 191, 70, 14,
WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0),
CT_BUTTON(Id_CancelButton, 13,
274, 191, 70, 14,
WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0),
CT_TAB(Id_Tab, 0,
-2, 36, 400, 150,
WS_VISIBLE | WS_TABSTOP | TCS_FIXEDWIDTH, 0) // Last for correct tab order.
};
CreateControls(s_Controls, _countof(s_Controls), m_Font, GetString);
m_TabContents.Create(m_Window);
m_TabContents.Activate();
SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)GetIcon(IDI_APPICON, false));
HWND item = GetControl(Id_HeaderIcon);
Static_SetIcon(item, GetIcon(IDI_APPICON, true));
item = GetControl(Id_HeaderTitleLabel);
SendMessage(item, WM_SETFONT, (WPARAM)m_FontBold, 0);
item = GetControl(Id_InstallButton);
SendMessage(m_Window, WM_NEXTDLGCTL, (WPARAM)item, TRUE);
if (IsWindowsVistaOrGreater() && !Util::IsProcessUserAdmin())
{
Button_SetElevationRequiredState(item, TRUE);
}
return TRUE;
}
INT_PTR CDialogInstall::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch (LOWORD(wParam))
{
case Id_CancelButton:
PostMessage(m_Window, WM_CLOSE, 0, 0);
break;
case Id_InstallButton:
LaunchInstallProcess();
break;
default:
return FALSE;
}
return TRUE;
}
INT_PTR CDialogInstall::OnNotify(WPARAM wParam, LPARAM lParam)
{
return 0;
}
void CDialogInstall::LaunchInstallProcess()
{
const bool isProcsesUserAdmin = Util::IsProcessUserAdmin();
if (!isProcsesUserAdmin && (IsWindowsVistaOrGreater() && !Util::CanProcessUserElevate()))
{
MessageBox(
m_Window,
L"Adminstrative privileges are required to install Rainmeter.\n\nClick OK to close setup.",
L"Rainmeter Setup", MB_OK | MB_ICONERROR);
PostMessage(m_Window, WM_CLOSE, 0, 0);
return;
}
m_InstallProcessWaitThread = CreateThread(
nullptr, 0, ElevatedProcessWaitThreadProc, nullptr, CREATE_SUSPENDED, nullptr);
if (!m_InstallProcessWaitThread)
{
// TODO.
}
WCHAR exePath[MAX_PATH];
GetModuleFileName(nullptr, exePath, _countof(exePath));
HWND item = m_TabContents.GetControl(TabContents::Id_LanguageComboBox);
const LCID lcid = (LCID)ComboBox_GetItemData(item, ComboBox_GetCurSel(item));
item = m_TabContents.GetControl(TabContents::Id_InstallationTypeComboBox);
const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item));
WCHAR targetPath[MAX_PATH];
item = m_TabContents.GetControl(TabContents::Id_DestinationEdit);
Edit_GetText(item, targetPath, _countof(targetPath));
item = m_TabContents.GetControl(TabContents::Id_LaunchOnLoginCheckBox);
const int launchOnLogin = Button_GetCheck(item) == BST_CHECKED ? 1 : 0;
WCHAR params[512];
wsprintf(
params, L"OPT:%s|%ld|%hd|%hd|%d",
targetPath, lcid, LOWORD(typeData), HIWORD(typeData), launchOnLogin);
// Launch the installer process and, if needed, request elevation.
SHELLEXECUTEINFO sei = {sizeof(sei)};
sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
sei.lpVerb = isProcsesUserAdmin ? L"open" : L"runas";
sei.lpFile = exePath;
sei.lpParameters = params;
sei.hwnd = m_Window;
sei.nShow = SW_NORMAL;
if (!ShellExecuteEx(&sei) || !sei.hProcess)
{
MessageBox(m_Window,
L"Adminstrative privileges are required to install Rainmeter.\n\nClick OK to close setup.",
L"Rainmeter Setup", MB_OK | MB_ICONERROR);
PostMessage(m_Window, WM_CLOSE, 0, 0);
return;
}
m_InstallProcess = sei.hProcess;
ResumeThread(m_InstallProcessWaitThread);
}
DWORD WINAPI CDialogInstall::ElevatedProcessWaitThreadProc(void* param)
{
WaitForSingleObject(c_Dialog->m_InstallProcess, INFINITE);
CloseHandle(c_Dialog->m_InstallProcess);
c_Dialog->m_InstallProcess = nullptr;
CloseHandle(c_Dialog->m_InstallProcessWaitThread);
c_Dialog->m_InstallProcessWaitThread = nullptr;
PostMessage(c_Dialog->m_Window, WM_CLOSE, 0, 0);
return 0;
}
/*
** Constructor.
**
*/
CDialogInstall::TabContents::TabContents() : Tab()
{
}
void CDialogInstall::TabContents::Create(HWND owner)
{
Tab::CreateTabWindow(10, 50, 380, 135, owner);
static const ControlTemplate::Control s_Controls[] =
{
CT_LABEL(-1, 6,
0, 3, 107, 9,
WS_VISIBLE, 0),
CT_COMBOBOX(Id_LanguageComboBox, 0,
107, 0, 222, 14,
WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL, 0),
CT_LABEL(-1, 17,
0, 21, 107, 9,
WS_VISIBLE, 0),
CT_COMBOBOX(Id_InstallationTypeComboBox, 0,
107, 18, 222, 14,
WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL, 0),
CT_LABEL(-1, 7,
0, 43, 107, 9,
WS_VISIBLE, 0),
CT_EDIT(Id_DestinationEdit, 0,
107, 40, 192, 14,
WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY, WS_EX_CLIENTEDGE),
CT_BUTTON(Id_DestinationBrowseButton, 9,
303, 40, 25, 14,
WS_VISIBLE | WS_TABSTOP, 0),
CT_CHECKBOX(Id_LaunchOnLoginCheckBox, 10,
0, 69, 250, 9,
WS_VISIBLE | WS_TABSTOP, 0),
};
CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString);
HWND item = GetControl(Id_LanguageComboBox);
ComboBox_AddString(item, L"English - English (United States)");
ComboBox_SetCurSel(item, 0);
PopulateInstallationTypes();
UpdateDestinationDirectory();
}
void CDialogInstall::TabContents::Initialize()
{
}
INT_PTR CDialogInstall::TabContents::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
return OnCommand(wParam, lParam);
}
return FALSE;
}
INT_PTR CDialogInstall::TabContents::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch (LOWORD(wParam))
{
case Id_DestinationBrowseButton:
{
WCHAR buffer[MAX_PATH];
BROWSEINFO bi = {0};
bi.hwndOwner = c_Dialog->GetWindow();
bi.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
PIDLIST_ABSOLUTE pidl = SHBrowseForFolder(&bi);
if (pidl && SHGetPathFromIDList(pidl, buffer))
{
HWND item = GetControl(Id_DestinationEdit);
Static_SetText(item, buffer);
CoTaskMemFree(pidl);
}
}
break;
case Id_InstallationTypeComboBox:
{
if (HIWORD(wParam) == CBN_SELCHANGE)
{
UpdateDestinationDirectory();
}
break;
}
default:
return FALSE;
}
return TRUE;
}
InstallType CDialogInstall::TabContents::GetInstallType()
{
HWND item = GetControl(TabContents::Id_InstallationTypeComboBox);
const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item));
return (InstallType)LOWORD(typeData);
}
InstallArch CDialogInstall::TabContents::GetInstallArch()
{
HWND item = GetControl(TabContents::Id_InstallationTypeComboBox);
const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item));
return (InstallArch)HIWORD(typeData);
}
void CDialogInstall::TabContents::PopulateInstallationTypes()
{
HWND item = GetControl(Id_InstallationTypeComboBox);
int index = 0;
if (Util::IsSystem64Bit())
{
InstallArch existingArch;
const bool alreadyInstalled = IsAlreadyInstalled(existingArch);
if (!alreadyInstalled || existingArch == InstallArch::X64)
{
index = ComboBox_AddString(item, L"Standard 64-bit installation (recommended)");
ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X64));
}
if (!alreadyInstalled || existingArch == InstallArch::X32)
{
index = ComboBox_AddString(item, L"Standard 32-bit installation");
ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X32));
}
index = ComboBox_AddString(item, L"Portable 64-bit installation");
ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Portable, InstallArch::X64));
}
else
{
index = ComboBox_AddString(item, L"Standard 32-bit installation (recommended)");
ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X32));
}
index = ComboBox_AddString(item, L"Portable 32-bit installation");
ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Portable, InstallArch::X32));
ComboBox_SetCurSel(item, 0);
}
void CDialogInstall::TabContents::UpdateDestinationDirectory()
{
WCHAR buffer[MAX_PATH];
buffer[0] = L'\0';
if (GetInstallType() == InstallType::Standard)
{
const bool hasRegistryKey = Util::GetRegistryString(
HKEY_LOCAL_MACHINE, kRegistryInstallKey, nullptr, buffer, _countof(buffer));
if (!hasRegistryKey)
{
const WCHAR* installPath =
GetInstallArch() == InstallArch::X32 ? L"%ProgramFiles%\\" APPNAME : L"%ProgramW6432%\\" APPNAME;
ExpandEnvironmentStrings(installPath, buffer, _countof(buffer));
}
}
else
{
ExpandEnvironmentStrings(L"%SystemDrive%\\" APPNAME, buffer, _countof(buffer));
}
HWND item = GetControl(Id_DestinationEdit);
Edit_SetText(item, buffer);
}
bool CDialogInstall::TabContents::IsAlreadyInstalled(InstallArch& arch)
{
WCHAR buffer[MAX_PATH];
const bool hasRegistryKey = Util::GetRegistryString(
HKEY_LOCAL_MACHINE, kRegistryInstallKey, nullptr, buffer, _countof(buffer));
if (hasRegistryKey)
{
PathAppend(buffer, L"Rainmeter.exe");
if (PathFileExists(buffer))
{
// FIXME: This is an ugly way to check if Rainmeter.exe is 32-bit.
HMODULE rainmeterExe = LoadLibrary(buffer);
if (rainmeterExe)
{
arch = InstallArch::X32;
CloseHandle(rainmeterExe);
}
else
{
arch = InstallArch::X64;
}
return true;
}
}
return false;
}
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "DialogInstall.h"
#include "Install.h"
#include "Resource.h"
#include "Util.h"
#include "../Common/ControlTemplate.h"
#define APPNAME L"Rainmeter"
const WCHAR* kRegistryInstallKey = L"SOFTWARE\\" APPNAME;
CDialogInstall* CDialogInstall::c_Dialog = nullptr;
HICON GetIcon(UINT id, bool large)
{
typedef HRESULT (WINAPI * FPLOADICONMETRIC)(HINSTANCE hinst, PCWSTR pszName, int lims, HICON* phico);
HINSTANCE hExe = GetModuleHandle(nullptr);
HINSTANCE hComctl = GetModuleHandle(L"Comctl32");
if (hComctl)
{
// Try LoadIconMetric for better quality with high DPI
FPLOADICONMETRIC loadIconMetric = (FPLOADICONMETRIC)GetProcAddress(hComctl, "LoadIconMetric");
if (loadIconMetric)
{
HICON icon;
HRESULT hr = loadIconMetric(hExe, MAKEINTRESOURCE(id), large ? LIM_LARGE : LIM_SMALL, &icon);
if (SUCCEEDED(hr))
{
return icon;
}
}
}
return (HICON)LoadImage(
hExe,
MAKEINTRESOURCE(id),
IMAGE_ICON,
GetSystemMetrics(large ? SM_CXICON : SM_CXSMICON),
GetSystemMetrics(large ? SM_CYICON : SM_CYSMICON),
LR_SHARED);
}
WCHAR* GetString(UINT id)
{
switch (id)
{
case 1: return L"Install";
case 2: return L"Rainmeter 3.0.2 beta setup";
case 3: return L"Click 'Install' to proceed. Rainmeter will launch after setup.";
case 5: return L"Close";
case 6: return L"Language:";
case 7: return L"Destination folder:";
case 9: return L"...";
case 10: return L"Launch Rainmeter automatically on login";
case 13: return L"Cancel";
case 14: return L"C:\\Program Files\\Rainmeter";
case 15: return L"Standard install (recommended)";
case 16: return L"Portable install";
case 17: return L"Installation type:";
}
return L"";
}
CDialogInstall::CDialogInstall() : Dialog(),
m_InstallProcess(),
m_InstallProcessWaitThread()
{
}
CDialogInstall::~CDialogInstall()
{
}
CDialogInstall* CDialogInstall::Create()
{
c_Dialog = new CDialogInstall();
c_Dialog->ShowDialogWindow(
L"Rainmeter Setup",
0, 0, 350, 210,
DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU,
WS_EX_APPWINDOW | WS_EX_CONTROLPARENT,
nullptr,
false);
return c_Dialog;
}
INT_PTR CDialogInstall::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
return OnInitDialog(wParam, lParam);
case WM_ACTIVATE:
return OnActivate(wParam, lParam);
case WM_COMMAND:
return OnCommand(wParam, lParam);
case WM_NOTIFY:
return OnNotify(wParam, lParam);
case WM_CLOSE:
{
delete this;
}
return TRUE;
}
return FALSE;
}
INT_PTR CDialogInstall::OnInitDialog(WPARAM wParam, LPARAM lParam)
{
static const ControlTemplate::Control s_Controls[] =
{
CT_ICON(Id_HeaderIcon, 0,
10, 10, 24, 24,
WS_VISIBLE, 0),
CT_LABEL(Id_HeaderTitleLabel, 2,
40, 6, 250, 14,
WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0),
CT_LABEL(-1, 3,
40, 20, 250, 9,
WS_VISIBLE | SS_ENDELLIPSIS | SS_NOPREFIX, 0),
CT_BUTTON(Id_InstallButton, 1,
199, 191, 70, 14,
WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0),
CT_BUTTON(Id_CancelButton, 13,
274, 191, 70, 14,
WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 0),
CT_TAB(Id_Tab, 0,
-2, 36, 400, 150,
WS_VISIBLE | WS_TABSTOP | TCS_FIXEDWIDTH, 0) // Last for correct tab order.
};
CreateControls(s_Controls, _countof(s_Controls), m_Font, GetString);
m_TabContents.Create(m_Window);
m_TabContents.Activate();
SendMessage(m_Window, WM_SETICON, ICON_SMALL, (LPARAM)GetIcon(IDI_APPICON, false));
HWND item = GetControl(Id_HeaderIcon);
Static_SetIcon(item, GetIcon(IDI_APPICON, true));
item = GetControl(Id_HeaderTitleLabel);
SendMessage(item, WM_SETFONT, (WPARAM)m_FontBold, 0);
item = GetControl(Id_InstallButton);
SendMessage(m_Window, WM_NEXTDLGCTL, (WPARAM)item, TRUE);
if (IsWindowsVistaOrGreater() && !Util::IsProcessUserAdmin())
{
Button_SetElevationRequiredState(item, TRUE);
}
return TRUE;
}
INT_PTR CDialogInstall::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch (LOWORD(wParam))
{
case Id_CancelButton:
PostMessage(m_Window, WM_CLOSE, 0, 0);
break;
case Id_InstallButton:
LaunchInstallProcess();
break;
default:
return FALSE;
}
return TRUE;
}
INT_PTR CDialogInstall::OnNotify(WPARAM wParam, LPARAM lParam)
{
return 0;
}
void CDialogInstall::LaunchInstallProcess()
{
const bool isProcsesUserAdmin = Util::IsProcessUserAdmin();
if (!isProcsesUserAdmin && (IsWindowsVistaOrGreater() && !Util::CanProcessUserElevate()))
{
MessageBox(
m_Window,
L"Adminstrative privileges are required to install Rainmeter.\n\nClick OK to close setup.",
L"Rainmeter Setup", MB_OK | MB_ICONERROR);
PostMessage(m_Window, WM_CLOSE, 0, 0);
return;
}
m_InstallProcessWaitThread = CreateThread(
nullptr, 0, ElevatedProcessWaitThreadProc, nullptr, CREATE_SUSPENDED, nullptr);
if (!m_InstallProcessWaitThread)
{
// TODO.
}
WCHAR exePath[MAX_PATH];
GetModuleFileName(nullptr, exePath, _countof(exePath));
HWND item = m_TabContents.GetControl(TabContents::Id_LanguageComboBox);
const LCID lcid = (LCID)ComboBox_GetItemData(item, ComboBox_GetCurSel(item));
item = m_TabContents.GetControl(TabContents::Id_InstallationTypeComboBox);
const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item));
WCHAR targetPath[MAX_PATH];
item = m_TabContents.GetControl(TabContents::Id_DestinationEdit);
Edit_GetText(item, targetPath, _countof(targetPath));
item = m_TabContents.GetControl(TabContents::Id_LaunchOnLoginCheckBox);
const int launchOnLogin = Button_GetCheck(item) == BST_CHECKED ? 1 : 0;
WCHAR params[512];
wsprintf(
params, L"OPT:%s|%ld|%hd|%hd|%d",
targetPath, lcid, LOWORD(typeData), HIWORD(typeData), launchOnLogin);
// Launch the installer process and, if needed, request elevation.
SHELLEXECUTEINFO sei = {sizeof(sei)};
sei.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI | SEE_MASK_NOCLOSEPROCESS;
sei.lpVerb = isProcsesUserAdmin ? L"open" : L"runas";
sei.lpFile = exePath;
sei.lpParameters = params;
sei.hwnd = m_Window;
sei.nShow = SW_NORMAL;
if (!ShellExecuteEx(&sei) || !sei.hProcess)
{
MessageBox(m_Window,
L"Adminstrative privileges are required to install Rainmeter.\n\nClick OK to close setup.",
L"Rainmeter Setup", MB_OK | MB_ICONERROR);
PostMessage(m_Window, WM_CLOSE, 0, 0);
return;
}
m_InstallProcess = sei.hProcess;
ResumeThread(m_InstallProcessWaitThread);
}
DWORD WINAPI CDialogInstall::ElevatedProcessWaitThreadProc(void* param)
{
WaitForSingleObject(c_Dialog->m_InstallProcess, INFINITE);
CloseHandle(c_Dialog->m_InstallProcess);
c_Dialog->m_InstallProcess = nullptr;
CloseHandle(c_Dialog->m_InstallProcessWaitThread);
c_Dialog->m_InstallProcessWaitThread = nullptr;
PostMessage(c_Dialog->m_Window, WM_CLOSE, 0, 0);
return 0;
}
/*
** Constructor.
**
*/
CDialogInstall::TabContents::TabContents() : Tab()
{
}
void CDialogInstall::TabContents::Create(HWND owner)
{
Tab::CreateTabWindow(10, 50, 380, 135, owner);
static const ControlTemplate::Control s_Controls[] =
{
CT_LABEL(-1, 6,
0, 3, 107, 9,
WS_VISIBLE, 0),
CT_COMBOBOX(Id_LanguageComboBox, 0,
107, 0, 222, 14,
WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL, 0),
CT_LABEL(-1, 17,
0, 21, 107, 9,
WS_VISIBLE, 0),
CT_COMBOBOX(Id_InstallationTypeComboBox, 0,
107, 18, 222, 14,
WS_VISIBLE | WS_TABSTOP | CBS_DROPDOWNLIST | WS_VSCROLL, 0),
CT_LABEL(-1, 7,
0, 43, 107, 9,
WS_VISIBLE, 0),
CT_EDIT(Id_DestinationEdit, 0,
107, 40, 192, 14,
WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY, WS_EX_CLIENTEDGE),
CT_BUTTON(Id_DestinationBrowseButton, 9,
303, 40, 25, 14,
WS_VISIBLE | WS_TABSTOP, 0),
CT_CHECKBOX(Id_LaunchOnLoginCheckBox, 10,
0, 69, 250, 9,
WS_VISIBLE | WS_TABSTOP, 0),
};
CreateControls(s_Controls, _countof(s_Controls), c_Dialog->m_Font, GetString);
HWND item = GetControl(Id_LanguageComboBox);
ComboBox_AddString(item, L"English - English (United States)");
ComboBox_SetCurSel(item, 0);
PopulateInstallationTypes();
UpdateDestinationDirectory();
}
void CDialogInstall::TabContents::Initialize()
{
}
INT_PTR CDialogInstall::TabContents::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_COMMAND:
return OnCommand(wParam, lParam);
}
return FALSE;
}
INT_PTR CDialogInstall::TabContents::OnCommand(WPARAM wParam, LPARAM lParam)
{
switch (LOWORD(wParam))
{
case Id_DestinationBrowseButton:
{
WCHAR buffer[MAX_PATH];
BROWSEINFO bi = {0};
bi.hwndOwner = c_Dialog->GetWindow();
bi.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
PIDLIST_ABSOLUTE pidl = SHBrowseForFolder(&bi);
if (pidl && SHGetPathFromIDList(pidl, buffer))
{
HWND item = GetControl(Id_DestinationEdit);
Static_SetText(item, buffer);
CoTaskMemFree(pidl);
}
}
break;
case Id_InstallationTypeComboBox:
{
if (HIWORD(wParam) == CBN_SELCHANGE)
{
UpdateDestinationDirectory();
}
break;
}
default:
return FALSE;
}
return TRUE;
}
InstallType CDialogInstall::TabContents::GetInstallType()
{
HWND item = GetControl(TabContents::Id_InstallationTypeComboBox);
const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item));
return (InstallType)LOWORD(typeData);
}
InstallArch CDialogInstall::TabContents::GetInstallArch()
{
HWND item = GetControl(TabContents::Id_InstallationTypeComboBox);
const LPARAM typeData = ComboBox_GetItemData(item, ComboBox_GetCurSel(item));
return (InstallArch)HIWORD(typeData);
}
void CDialogInstall::TabContents::PopulateInstallationTypes()
{
HWND item = GetControl(Id_InstallationTypeComboBox);
int index = 0;
if (Util::IsSystem64Bit())
{
InstallArch existingArch;
const bool alreadyInstalled = IsAlreadyInstalled(existingArch);
if (!alreadyInstalled || existingArch == InstallArch::X64)
{
index = ComboBox_AddString(item, L"Standard 64-bit installation (recommended)");
ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X64));
}
if (!alreadyInstalled || existingArch == InstallArch::X32)
{
index = ComboBox_AddString(item, L"Standard 32-bit installation");
ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X32));
}
index = ComboBox_AddString(item, L"Portable 64-bit installation");
ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Portable, InstallArch::X64));
}
else
{
index = ComboBox_AddString(item, L"Standard 32-bit installation (recommended)");
ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Standard, InstallArch::X32));
}
index = ComboBox_AddString(item, L"Portable 32-bit installation");
ComboBox_SetItemData(item, index, MAKELPARAM(InstallType::Portable, InstallArch::X32));
ComboBox_SetCurSel(item, 0);
}
void CDialogInstall::TabContents::UpdateDestinationDirectory()
{
WCHAR buffer[MAX_PATH];
buffer[0] = L'\0';
if (GetInstallType() == InstallType::Standard)
{
const bool hasRegistryKey = Util::GetRegistryString(
HKEY_LOCAL_MACHINE, kRegistryInstallKey, nullptr, buffer, _countof(buffer));
if (!hasRegistryKey)
{
const WCHAR* installPath =
GetInstallArch() == InstallArch::X32 ? L"%ProgramFiles%\\" APPNAME : L"%ProgramW6432%\\" APPNAME;
ExpandEnvironmentStrings(installPath, buffer, _countof(buffer));
}
}
else
{
ExpandEnvironmentStrings(L"%SystemDrive%\\" APPNAME, buffer, _countof(buffer));
}
HWND item = GetControl(Id_DestinationEdit);
Edit_SetText(item, buffer);
}
bool CDialogInstall::TabContents::IsAlreadyInstalled(InstallArch& arch)
{
WCHAR buffer[MAX_PATH];
const bool hasRegistryKey = Util::GetRegistryString(
HKEY_LOCAL_MACHINE, kRegistryInstallKey, nullptr, buffer, _countof(buffer));
if (hasRegistryKey)
{
PathAppend(buffer, L"Rainmeter.exe");
if (PathFileExists(buffer))
{
// FIXME: This is an ugly way to check if Rainmeter.exe is 32-bit.
HMODULE rainmeterExe = LoadLibrary(buffer);
if (rainmeterExe)
{
arch = InstallArch::X32;
CloseHandle(rainmeterExe);
}
else
{
arch = InstallArch::X64;
}
return true;
}
}
return false;
}

View File

@ -1,97 +1,97 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_INSTALLER_DIALOGINSTALL_H_
#define RM_INSTALLER_DIALOGINSTALL_H_
#include "Install.h"
#include "../Common/Dialog.h"
class CDialogInstall : public Dialog
{
public:
CDialogInstall();
virtual ~CDialogInstall();
static CDialogInstall* CDialogInstall::Create();
static void Open(int tab = 0);
static void Open(const WCHAR* name);
static void ShowAboutLog();
protected:
// Layouts tab
class TabContents : public Tab
{
public:
enum Id
{
Id_LanguageComboBox = 100,
Id_InstallationTypeComboBox,
Id_DestinationEdit,
Id_DestinationBrowseButton,
Id_LaunchOnLoginCheckBox
};
TabContents();
void Create(HWND owner);
virtual void Initialize();
InstallType GetInstallType();
InstallArch GetInstallArch();
void PopulateInstallationTypes();
void UpdateDestinationDirectory();
bool IsAlreadyInstalled(InstallArch& arch);
protected:
virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR OnCommand(WPARAM wParam, LPARAM lParam);
};
static CDialogInstall* c_Dialog;
virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam);
INT_PTR OnNotify(WPARAM wParam, LPARAM lParam);
INT_PTR OnCommand(WPARAM wParam, LPARAM lParam);
private:
enum Id
{
Id_CancelButton = IDCANCEL,
Id_HeaderIcon = 100,
Id_HeaderTitleLabel,
Id_InstallButton,
Id_Tab
};
TabContents m_TabContents;
HANDLE m_InstallProcess;
HANDLE m_InstallProcessWaitThread;
void LaunchInstallProcess();
static DWORD WINAPI ElevatedProcessWaitThreadProc(void* param);
};
#endif
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_INSTALLER_DIALOGINSTALL_H_
#define RM_INSTALLER_DIALOGINSTALL_H_
#include "Install.h"
#include "../Common/Dialog.h"
class CDialogInstall : public Dialog
{
public:
CDialogInstall();
virtual ~CDialogInstall();
static CDialogInstall* CDialogInstall::Create();
static void Open(int tab = 0);
static void Open(const WCHAR* name);
static void ShowAboutLog();
protected:
// Layouts tab
class TabContents : public Tab
{
public:
enum Id
{
Id_LanguageComboBox = 100,
Id_InstallationTypeComboBox,
Id_DestinationEdit,
Id_DestinationBrowseButton,
Id_LaunchOnLoginCheckBox
};
TabContents();
void Create(HWND owner);
virtual void Initialize();
InstallType GetInstallType();
InstallArch GetInstallArch();
void PopulateInstallationTypes();
void UpdateDestinationDirectory();
bool IsAlreadyInstalled(InstallArch& arch);
protected:
virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR OnCommand(WPARAM wParam, LPARAM lParam);
};
static CDialogInstall* c_Dialog;
virtual INT_PTR HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR OnInitDialog(WPARAM wParam, LPARAM lParam);
INT_PTR OnNotify(WPARAM wParam, LPARAM lParam);
INT_PTR OnCommand(WPARAM wParam, LPARAM lParam);
private:
enum Id
{
Id_CancelButton = IDCANCEL,
Id_HeaderIcon = 100,
Id_HeaderTitleLabel,
Id_InstallButton,
Id_Tab
};
TabContents m_TabContents;
HANDLE m_InstallProcess;
HANDLE m_InstallProcessWaitThread;
void LaunchInstallProcess();
static DWORD WINAPI ElevatedProcessWaitThreadProc(void* param);
};
#endif

View File

@ -1,147 +1,147 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Install.h"
#include "Resource.h"
extern "C" {
#include "lzma/Alloc.h"
#include "lzma/7zFile.h"
#include "lzma/7zVersion.h"
#include "lzma/LzmaDec.h"
#include "lzma/7zCrc.h"
#include "lzma/7z.h"
#include "lzma/7zMemInStream.h"
#include "lzma/7zAlloc.h"
} // extern "C"
void ExtractPayload(const void* payload, size_t payloadSize, const WCHAR* prefix)
{
CMemInStream memStream;
MemInStream_Init(&memStream, payload, payloadSize);
CrcGenerateTable();
ISzAlloc alloc = { SzAlloc, SzFree };
CSzArEx db;
SzArEx_Init(&db);
SRes res = SzArEx_Open(&db, &memStream.s, &alloc, &alloc);
if (res != SZ_OK)
{
SzArEx_Free(&db, &alloc);
return;
}
WCHAR buffer[MAX_PATH];
UInt32 blockIndex = 0xFFFFFFFF;
Byte* outBuffer = 0;
size_t outBufferSize = 0;
for (UInt32 i = 0; i < db.db.NumFiles; i++)
{
size_t offset = 0;
size_t outSizeProcessed = 0;
const CSzFileItem* f = db.db.Files + i;
SzArEx_GetFileNameUtf16(&db, i, (UInt16*)buffer);
WCHAR* destPath = buffer;
if (wcsncmp(destPath, prefix, 3) == 0 ||
wcsncmp(destPath, L"ALL", 3) == 0)
{
// Skip the prefix (X64/X32/ALL) and the path separater.
destPath += 4;
}
else
{
// This file isn't for this arch.
continue;
}
if (!f->IsDir)
{
res = SzArEx_Extract(
&db, &memStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset,
&outSizeProcessed, &alloc, &alloc);
if (res != SZ_OK)
{
break;
}
}
for (size_t j = 0; destPath[j] != L'\0'; ++j)
{
if (destPath[j] == L'/')
{
destPath[j] = L'\0';
CreateDirectory(destPath, NULL);
destPath[j] = CHAR_PATH_SEPARATOR;
}
}
if (f->IsDir)
{
CreateDirectory(destPath, NULL);
continue;
}
CSzFile outFile;
if (OutFile_OpenW(&outFile, destPath))
{
res = SZ_ERROR_FAIL;
break;
}
size_t processedSize = outSizeProcessed;
if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 ||
processedSize != outSizeProcessed)
{
res = SZ_ERROR_FAIL;
break;
}
if (File_Close(&outFile))
{
res = SZ_ERROR_FAIL;
break;
}
if (f->AttribDefined) SetFileAttributesW(destPath, f->Attrib);
}
IAlloc_Free(&alloc, outBuffer);
SzArEx_Free(&db, &alloc);
if (res == SZ_OK)
{
// Success.
}
}
void DoInstall(InstallOptions& options)
{
#ifdef INSTALLER_INCLUDE_PAYLOAD
const auto module = GetModuleHandle(nullptr);
HRSRC payload = FindResource(
module, MAKEINTRESOURCE(IDR_PAYLOAD), MAKEINTRESOURCE(PAYLOAD_RESOURCE_TYPEID));
const size_t payloadSize = SizeofResource(module, payload);
const void* payloadData = LockResource(LoadResource(module, payload));
SetCurrentDirectory(options.targetPath);
ExtractPayload(
payloadData, payloadSize, options.arch == InstallArch::X32 ? L"X32" : L"X64");
#endif
}
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Install.h"
#include "Resource.h"
extern "C" {
#include "lzma/Alloc.h"
#include "lzma/7zFile.h"
#include "lzma/7zVersion.h"
#include "lzma/LzmaDec.h"
#include "lzma/7zCrc.h"
#include "lzma/7z.h"
#include "lzma/7zMemInStream.h"
#include "lzma/7zAlloc.h"
} // extern "C"
void ExtractPayload(const void* payload, size_t payloadSize, const WCHAR* prefix)
{
CMemInStream memStream;
MemInStream_Init(&memStream, payload, payloadSize);
CrcGenerateTable();
ISzAlloc alloc = { SzAlloc, SzFree };
CSzArEx db;
SzArEx_Init(&db);
SRes res = SzArEx_Open(&db, &memStream.s, &alloc, &alloc);
if (res != SZ_OK)
{
SzArEx_Free(&db, &alloc);
return;
}
WCHAR buffer[MAX_PATH];
UInt32 blockIndex = 0xFFFFFFFF;
Byte* outBuffer = 0;
size_t outBufferSize = 0;
for (UInt32 i = 0; i < db.db.NumFiles; i++)
{
size_t offset = 0;
size_t outSizeProcessed = 0;
const CSzFileItem* f = db.db.Files + i;
SzArEx_GetFileNameUtf16(&db, i, (UInt16*)buffer);
WCHAR* destPath = buffer;
if (wcsncmp(destPath, prefix, 3) == 0 ||
wcsncmp(destPath, L"ALL", 3) == 0)
{
// Skip the prefix (X64/X32/ALL) and the path separater.
destPath += 4;
}
else
{
// This file isn't for this arch.
continue;
}
if (!f->IsDir)
{
res = SzArEx_Extract(
&db, &memStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset,
&outSizeProcessed, &alloc, &alloc);
if (res != SZ_OK)
{
break;
}
}
for (size_t j = 0; destPath[j] != L'\0'; ++j)
{
if (destPath[j] == L'/')
{
destPath[j] = L'\0';
CreateDirectory(destPath, NULL);
destPath[j] = CHAR_PATH_SEPARATOR;
}
}
if (f->IsDir)
{
CreateDirectory(destPath, NULL);
continue;
}
CSzFile outFile;
if (OutFile_OpenW(&outFile, destPath))
{
res = SZ_ERROR_FAIL;
break;
}
size_t processedSize = outSizeProcessed;
if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 ||
processedSize != outSizeProcessed)
{
res = SZ_ERROR_FAIL;
break;
}
if (File_Close(&outFile))
{
res = SZ_ERROR_FAIL;
break;
}
if (f->AttribDefined) SetFileAttributesW(destPath, f->Attrib);
}
IAlloc_Free(&alloc, outBuffer);
SzArEx_Free(&db, &alloc);
if (res == SZ_OK)
{
// Success.
}
}
void DoInstall(InstallOptions& options)
{
#ifdef INSTALLER_INCLUDE_PAYLOAD
const auto module = GetModuleHandle(nullptr);
HRSRC payload = FindResource(
module, MAKEINTRESOURCE(IDR_PAYLOAD), MAKEINTRESOURCE(PAYLOAD_RESOURCE_TYPEID));
const size_t payloadSize = SizeofResource(module, payload);
const void* payloadData = LockResource(LoadResource(module, payload));
SetCurrentDirectory(options.targetPath);
ExtractPayload(
payloadData, payloadSize, options.arch == InstallArch::X32 ? L"X32" : L"X64");
#endif
}

View File

@ -1,45 +1,45 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_INSTALLER_INSTALL_H_
#define RM_INSTALLER_INSTALL_H_
enum InstallType : char
{
Standard,
Portable
};
enum InstallArch : char
{
X32,
X64
};
struct InstallOptions
{
WCHAR targetPath[MAX_PATH];
InstallType type;
InstallArch arch;
LCID language;
BOOL launchOnLogin;
};
void DoInstall(InstallOptions& options);
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_INSTALLER_INSTALL_H_
#define RM_INSTALLER_INSTALL_H_
enum InstallType : char
{
Standard,
Portable
};
enum InstallArch : char
{
X32,
X64
};
struct InstallOptions
{
WCHAR targetPath[MAX_PATH];
InstallType type;
InstallArch arch;
LCID language;
BOOL launchOnLogin;
};
void DoInstall(InstallOptions& options);
#endif

View File

@ -1,54 +1,54 @@
#include <windows.h>
#include "Resource.h"
#include "../Version.h"
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
#pragma code_page(1252)
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION FILEVER
PRODUCTVERSION PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4"
{
VALUE "FileVersion", STRFILEVER
VALUE "LegalCopyright", "© 2013 - All authors"
VALUE "OriginalFilename", "Rainmeter-Setup.exe"
VALUE "ProductName", "Rainmeter"
#ifdef _WIN64
VALUE "ProductVersion", STRPRODUCTVER " (64-bit)"
#else
VALUE "ProductVersion", STRPRODUCTVER " (32-bit)"
#endif //_WIN64
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x409, 1252
}
}
//
// Icon
//
IDI_APPICON ICON "Installer.ico"
#ifdef INSTALLER_INCLUDE_PAYLOAD
IDR_PAYLOAD PAYLOAD_RESOURCE_TYPEID payload.7z
#endif
#include <windows.h>
#include "Resource.h"
#include "../Version.h"
LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT
#pragma code_page(1252)
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION FILEVER
PRODUCTVERSION PRODUCTVER
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
{
BLOCK "StringFileInfo"
{
BLOCK "040904E4"
{
VALUE "FileVersion", STRFILEVER
VALUE "LegalCopyright", "© 2013 - All authors"
VALUE "OriginalFilename", "Rainmeter-Setup.exe"
VALUE "ProductName", "Rainmeter"
#ifdef _WIN64
VALUE "ProductVersion", STRPRODUCTVER " (64-bit)"
#else
VALUE "ProductVersion", STRPRODUCTVER " (32-bit)"
#endif //_WIN64
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x409, 1252
}
}
//
// Icon
//
IDI_APPICON ICON "Installer.ico"
#ifdef INSTALLER_INCLUDE_PAYLOAD
IDR_PAYLOAD PAYLOAD_RESOURCE_TYPEID payload.7z
#endif

View File

@ -1,83 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}</ProjectGuid>
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)Build\VS\Rainmeter.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>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>Imagehlp.lib;Wininet.lib;Comctl32.lib;Version.lib;UxTheme.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies Condition="'$(Configuration)'=='Release'">$(WinDDK71Dir)\lib\Crt\i386\msvcrt.lib;$(WinDDK71Dir)\lib\wxp\i386\msvcrt_winxp.obj;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries Condition="'$(Configuration)'=='Release'">true</IgnoreAllDefaultLibraries>
</Link>
<Manifest>
<AdditionalManifestFiles>..\Application\Application.manifest</AdditionalManifestFiles>
</Manifest>
<ClCompile>
<DisableSpecificWarnings>4800;4996</DisableSpecificWarnings>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Common\ControlTemplate.cpp" />
<ClCompile Include="..\Common\Dialog.cpp" />
<ClCompile Include="Application.cpp" />
<ClCompile Include="DialogInstall.cpp" />
<ClCompile Include="Install.cpp" />
<ClCompile Include="lzma\7zAlloc.c" />
<ClCompile Include="lzma\7zBuf.c" />
<ClCompile Include="lzma\7zCrc.c" />
<ClCompile Include="lzma\7zCrcOpt.c" />
<ClCompile Include="lzma\7zDec.c" />
<ClCompile Include="lzma\7zFile.c" />
<ClCompile Include="lzma\7zIn.c" />
<ClCompile Include="lzma\7zMemInStream.c" />
<ClCompile Include="lzma\7zStream.c" />
<ClCompile Include="lzma\Alloc.c" />
<ClCompile Include="lzma\Bcj2.c" />
<ClCompile Include="lzma\Bra.c" />
<ClCompile Include="lzma\Bra86.c" />
<ClCompile Include="lzma\CpuArch.c" />
<ClCompile Include="lzma\LzmaDec.c" />
<ClCompile Include="StdAfx.cpp" />
<ClCompile Include="Util.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Application.h" />
<ClInclude Include="DialogInstall.h" />
<ClInclude Include="Install.h" />
<ClInclude Include="lzma\7z.h" />
<ClInclude Include="lzma\7zAlloc.h" />
<ClInclude Include="lzma\7zBuf.h" />
<ClInclude Include="lzma\7zCrc.h" />
<ClInclude Include="lzma\7zFile.h" />
<ClInclude Include="lzma\7zMemInStream.h" />
<ClInclude Include="lzma\7zVersion.h" />
<ClInclude Include="lzma\Alloc.h" />
<ClInclude Include="lzma\Bcj2.h" />
<ClInclude Include="lzma\Bra.h" />
<ClInclude Include="lzma\CpuArch.h" />
<ClInclude Include="lzma\LzmaDec.h" />
<ClInclude Include="lzma\Types.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="StdAfx.h" />
<ClInclude Include="Util.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Installer.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)Build\VS\Rainmeter.Cpp.Default.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{2FCFBFD2-2720-4BDD-B620-4BDD3DBB8D3D}</ProjectGuid>
<ConfigurationType>Application</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(SolutionDir)Build\VS\Rainmeter.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>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<Link>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>Imagehlp.lib;Wininet.lib;Comctl32.lib;Version.lib;UxTheme.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies Condition="'$(Configuration)'=='Release'">$(WinDDK71Dir)\lib\Crt\i386\msvcrt.lib;$(WinDDK71Dir)\lib\wxp\i386\msvcrt_winxp.obj;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries Condition="'$(Configuration)'=='Release'">true</IgnoreAllDefaultLibraries>
</Link>
<Manifest>
<AdditionalManifestFiles>..\Application\Application.manifest</AdditionalManifestFiles>
</Manifest>
<ClCompile>
<DisableSpecificWarnings>4800;4996</DisableSpecificWarnings>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\Common\ControlTemplate.cpp" />
<ClCompile Include="..\Common\Dialog.cpp" />
<ClCompile Include="Application.cpp" />
<ClCompile Include="DialogInstall.cpp" />
<ClCompile Include="Install.cpp" />
<ClCompile Include="lzma\7zAlloc.c" />
<ClCompile Include="lzma\7zBuf.c" />
<ClCompile Include="lzma\7zCrc.c" />
<ClCompile Include="lzma\7zCrcOpt.c" />
<ClCompile Include="lzma\7zDec.c" />
<ClCompile Include="lzma\7zFile.c" />
<ClCompile Include="lzma\7zIn.c" />
<ClCompile Include="lzma\7zMemInStream.c" />
<ClCompile Include="lzma\7zStream.c" />
<ClCompile Include="lzma\Alloc.c" />
<ClCompile Include="lzma\Bcj2.c" />
<ClCompile Include="lzma\Bra.c" />
<ClCompile Include="lzma\Bra86.c" />
<ClCompile Include="lzma\CpuArch.c" />
<ClCompile Include="lzma\LzmaDec.c" />
<ClCompile Include="StdAfx.cpp" />
<ClCompile Include="Util.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Application.h" />
<ClInclude Include="DialogInstall.h" />
<ClInclude Include="Install.h" />
<ClInclude Include="lzma\7z.h" />
<ClInclude Include="lzma\7zAlloc.h" />
<ClInclude Include="lzma\7zBuf.h" />
<ClInclude Include="lzma\7zCrc.h" />
<ClInclude Include="lzma\7zFile.h" />
<ClInclude Include="lzma\7zMemInStream.h" />
<ClInclude Include="lzma\7zVersion.h" />
<ClInclude Include="lzma\Alloc.h" />
<ClInclude Include="lzma\Bcj2.h" />
<ClInclude Include="lzma\Bra.h" />
<ClInclude Include="lzma\CpuArch.h" />
<ClInclude Include="lzma\LzmaDec.h" />
<ClInclude Include="lzma\Types.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="StdAfx.h" />
<ClInclude Include="Util.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Installer.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,155 +1,155 @@
<?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>{22670730-eb79-4df9-bed9-27fff1350132}</UniqueIdentifier>
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{774a1827-ac91-40b9-ad18-8a3d68983c64}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{a4963a10-e359-400f-86fa-bdce98dd5dc2}</UniqueIdentifier>
<Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
</Filter>
<Filter Include="lzma">
<UniqueIdentifier>{9588f54f-9188-40b7-b750-260f5f514ee5}</UniqueIdentifier>
</Filter>
<Filter Include="Common">
<UniqueIdentifier>{6acda1fa-eb7e-490b-ae49-ed7ff8b2534d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Application.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Install.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="StdAfx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="lzma\Alloc.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\Bcj2.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\Bra.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\Bra86.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\CpuArch.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\LzmaDec.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zAlloc.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zBuf.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zCrc.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zCrcOpt.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zDec.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zFile.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zIn.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zMemInStream.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zStream.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="DialogInstall.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Common\ControlTemplate.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\Dialog.cpp">
<Filter>Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Application.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DialogInstall.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Install.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="StdAfx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="lzma\Alloc.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\Bcj2.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\Bra.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\CpuArch.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\LzmaDec.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\Types.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7z.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zAlloc.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zBuf.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zCrc.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zFile.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zMemInStream.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zVersion.h">
<Filter>lzma</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Installer.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<?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>{22670730-eb79-4df9-bed9-27fff1350132}</UniqueIdentifier>
<Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{774a1827-ac91-40b9-ad18-8a3d68983c64}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{a4963a10-e359-400f-86fa-bdce98dd5dc2}</UniqueIdentifier>
<Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
</Filter>
<Filter Include="lzma">
<UniqueIdentifier>{9588f54f-9188-40b7-b750-260f5f514ee5}</UniqueIdentifier>
</Filter>
<Filter Include="Common">
<UniqueIdentifier>{6acda1fa-eb7e-490b-ae49-ed7ff8b2534d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Application.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Install.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="StdAfx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Util.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="lzma\Alloc.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\Bcj2.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\Bra.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\Bra86.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\CpuArch.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\LzmaDec.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zAlloc.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zBuf.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zCrc.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zCrcOpt.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zDec.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zFile.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zIn.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zMemInStream.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="lzma\7zStream.c">
<Filter>lzma</Filter>
</ClCompile>
<ClCompile Include="DialogInstall.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Common\ControlTemplate.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="..\Common\Dialog.cpp">
<Filter>Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Application.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DialogInstall.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Install.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="StdAfx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="lzma\Alloc.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\Bcj2.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\Bra.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\CpuArch.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\LzmaDec.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\Types.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7z.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zAlloc.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zBuf.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zCrc.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zFile.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zMemInStream.h">
<Filter>lzma</Filter>
</ClInclude>
<ClInclude Include="lzma\7zVersion.h">
<Filter>lzma</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Installer.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View File

@ -1,6 +1,6 @@
#define IDI_APPICON 101
#define IDR_PAYLOAD 102
#define PAYLOAD_RESOURCE_TYPEID 1000
#define IDC_STATIC -1
#define IDI_APPICON 101
#define IDR_PAYLOAD 102
#define PAYLOAD_RESOURCE_TYPEID 1000
#define IDC_STATIC -1

View File

@ -1,19 +1,19 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"

View File

@ -1,36 +1,36 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_INSTALLER_STDAFX_H_
#define RM_INSTALLER_STDAFX_H_
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <shellapi.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <wininet.h>
#include <VersionHelpers.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_INSTALLER_STDAFX_H_
#define RM_INSTALLER_STDAFX_H_
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <shellapi.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <wininet.h>
#include <VersionHelpers.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#endif

View File

@ -1,281 +1,281 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Util.h"
namespace Util {
//
// System functions.
//
bool IsSystem64Bit()
{
#ifdef _WIN64
return true;
#else
BOOL system64 = FALSE;
typedef BOOL (WINAPI * FPIsWow64Process)(HANDLE hProcess, BOOL* Wow64Process);
auto isWow64Process = (FPIsWow64Process)GetProcAddress(
GetModuleHandle(L"kernel32"), "IsWow64Process");
if (isWow64Process)
{
isWow64Process(GetCurrentProcess(), &system64);
}
return system64;
#endif
}
//
// Process functions.
//
bool IsProcessUserAdmin()
{
BOOL runningAsAdmin = FALSE;
// Allocate and initialize a SID of the administrators group.
PSID adminGroupSid = nullptr;
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
if (AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&adminGroupSid))
{
// Check if the primary access token of the process has the admin group SID.
if (!CheckTokenMembership(nullptr, adminGroupSid, &runningAsAdmin))
{
runningAsAdmin = TRUE;
}
FreeSid(adminGroupSid);
adminGroupSid = nullptr;
}
return runningAsAdmin;
}
bool CanProcessUserElevate()
{
OSVERSIONINFO osvi = {sizeof(osvi)};
GetVersionEx(&osvi);
if (osvi.dwMajorVersion >= 6)
{
// Check if UAC is enabled with Vista and above.
BOOL uacEnabled = FALSE;
// First try with undocumented CheckElevationEnabled function.
// See: http://blog.airesoft.co.uk/2011/03/uaceen-nothing-yet/
typedef DWORD (WINAPI * FPCheckElevationEnabled)(BOOL* pResult);
auto checkElevationEnabled = (FPCheckElevationEnabled)GetProcAddress(
GetModuleHandle(L"kernel32"), "CheckElevationEnabled");
if (checkElevationEnabled && checkElevationEnabled(&uacEnabled) == ERROR_SUCCESS)
{
return uacEnabled;
}
else
{
// Try checking registry.
const WCHAR* subKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
DWORD data;
if (GetRegistryDword(HKEY_LOCAL_MACHINE, subKey, L"EnableLUA", &data) &&
data != 0)
{
return true;
}
}
}
return false;
}
//
// File and directory functions.
//
bool CopyDirectory(const WCHAR* fromPath, const WCHAR* toPath)
{
int fromPathLength = wcslen(fromPath);
int toPathLength = wcslen(toPath);
// SHFileOperation expects double null terminated strings.
WCHAR* from = (WCHAR*)malloc((fromPathLength + 2) * sizeof(WCHAR));
wcscpy(from, fromPath);
from[fromPathLength + 2] = L'\0';
WCHAR* to = (WCHAR*)malloc((toPathLength + 2) * sizeof(WCHAR));
wcscpy(to, toPath);
to[toPathLength + 2] = L'\0';
SHFILEOPSTRUCT fo =
{
nullptr,
FO_COPY,
from,
to,
FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION
};
BOOL copied = (SHFileOperation(&fo) == 0);
free(from);
free(to);
return copied;
}
bool CreateShortcutFile(const WCHAR* filePath, const WCHAR* targetPath)
{
IShellLink* psl;
HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
if (SUCCEEDED(hr))
{
IPersistFile* ppf;
hr = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
if (SUCCEEDED(hr))
{
psl->SetPath(filePath);
hr = ppf->Save(targetPath, TRUE);
ppf->Release();
}
psl->Release();
}
return SUCCEEDED(hr);
}
bool IsDirectoryWritable()
{
return TRUE;
}
//
// Registry functions.
//
bool GetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD* data)
{
DWORD type;
DWORD dataSize = sizeof(DWORD);
return (SHGetValue(rootKey, subKey, value, &type, data, &dataSize) == ERROR_SUCCESS &&
type == REG_DWORD);
}
bool GetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, WCHAR* data, DWORD bufferLength)
{
DWORD type;
DWORD dataSize = bufferLength * sizeof(data[0]);
return (SHGetValue(rootKey, subKey, value, &type, data, &dataSize) == ERROR_SUCCESS &&
type == REG_SZ);
}
bool SetRegistryData(DWORD type, HKEY rootKey, const WCHAR* subKey, const WCHAR* value, BYTE* data, DWORD dataSize)
{
BOOL result = FALSE;
HKEY regKey;
if (RegCreateKeyEx(rootKey, subKey, 0, 0, 0, KEY_SET_VALUE, nullptr, &regKey, nullptr) == ERROR_SUCCESS)
{
if (RegSetValueEx(regKey, value, 0, type, data, dataSize) == ERROR_SUCCESS)
{
result = TRUE;
}
RegCloseKey(regKey);
}
return result;
}
bool SetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD data)
{
return SetRegistryData(REG_DWORD, rootKey, subKey, value, (BYTE*)&data, sizeof(DWORD));
}
bool SetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, const WCHAR* data)
{
DWORD dataSize = (wcslen(data) + 1) * sizeof(WCHAR);
return SetRegistryData(REG_SZ, rootKey, subKey, value, (BYTE*)data, dataSize);
}
//
// Misc. functions.
//
bool DownloadFile(const WCHAR* url, const WCHAR* file)
{
bool result = false;
HINTERNET hNet = InternetOpen(L"Mozilla/5.0", INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0);
if (hNet)
{
HANDLE hFile = CreateFile(file, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile)
{
HINTERNET hUrl = InternetOpenUrl(hNet, url, nullptr, 0, INTERNET_FLAG_RESYNCHRONIZE, 0);
if (hUrl)
{
const DWORD bufferSize = 8192;
BYTE* buffer = (BYTE*)malloc(bufferSize);
if (buffer)
{
DWORD readSize;
while (InternetReadFile(hUrl, buffer, bufferSize, &readSize))
{
if (readSize == 0)
{
// All data read.
result = true;
break;
}
DWORD writeSize;
if (!WriteFile(hFile, buffer, readSize, &writeSize, nullptr) ||
readSize != writeSize)
{
break;
}
}
free(buffer);
}
InternetCloseHandle(hUrl);
}
CloseHandle(hFile);
if (!result)
{
DeleteFile(file);
}
}
InternetCloseHandle(hNet);
}
return result;
}
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "StdAfx.h"
#include "Util.h"
namespace Util {
//
// System functions.
//
bool IsSystem64Bit()
{
#ifdef _WIN64
return true;
#else
BOOL system64 = FALSE;
typedef BOOL (WINAPI * FPIsWow64Process)(HANDLE hProcess, BOOL* Wow64Process);
auto isWow64Process = (FPIsWow64Process)GetProcAddress(
GetModuleHandle(L"kernel32"), "IsWow64Process");
if (isWow64Process)
{
isWow64Process(GetCurrentProcess(), &system64);
}
return system64;
#endif
}
//
// Process functions.
//
bool IsProcessUserAdmin()
{
BOOL runningAsAdmin = FALSE;
// Allocate and initialize a SID of the administrators group.
PSID adminGroupSid = nullptr;
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
if (AllocateAndInitializeSid(
&NtAuthority,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
&adminGroupSid))
{
// Check if the primary access token of the process has the admin group SID.
if (!CheckTokenMembership(nullptr, adminGroupSid, &runningAsAdmin))
{
runningAsAdmin = TRUE;
}
FreeSid(adminGroupSid);
adminGroupSid = nullptr;
}
return runningAsAdmin;
}
bool CanProcessUserElevate()
{
OSVERSIONINFO osvi = {sizeof(osvi)};
GetVersionEx(&osvi);
if (osvi.dwMajorVersion >= 6)
{
// Check if UAC is enabled with Vista and above.
BOOL uacEnabled = FALSE;
// First try with undocumented CheckElevationEnabled function.
// See: http://blog.airesoft.co.uk/2011/03/uaceen-nothing-yet/
typedef DWORD (WINAPI * FPCheckElevationEnabled)(BOOL* pResult);
auto checkElevationEnabled = (FPCheckElevationEnabled)GetProcAddress(
GetModuleHandle(L"kernel32"), "CheckElevationEnabled");
if (checkElevationEnabled && checkElevationEnabled(&uacEnabled) == ERROR_SUCCESS)
{
return uacEnabled;
}
else
{
// Try checking registry.
const WCHAR* subKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
DWORD data;
if (GetRegistryDword(HKEY_LOCAL_MACHINE, subKey, L"EnableLUA", &data) &&
data != 0)
{
return true;
}
}
}
return false;
}
//
// File and directory functions.
//
bool CopyDirectory(const WCHAR* fromPath, const WCHAR* toPath)
{
int fromPathLength = wcslen(fromPath);
int toPathLength = wcslen(toPath);
// SHFileOperation expects double null terminated strings.
WCHAR* from = (WCHAR*)malloc((fromPathLength + 2) * sizeof(WCHAR));
wcscpy(from, fromPath);
from[fromPathLength + 2] = L'\0';
WCHAR* to = (WCHAR*)malloc((toPathLength + 2) * sizeof(WCHAR));
wcscpy(to, toPath);
to[toPathLength + 2] = L'\0';
SHFILEOPSTRUCT fo =
{
nullptr,
FO_COPY,
from,
to,
FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION
};
BOOL copied = (SHFileOperation(&fo) == 0);
free(from);
free(to);
return copied;
}
bool CreateShortcutFile(const WCHAR* filePath, const WCHAR* targetPath)
{
IShellLink* psl;
HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl);
if (SUCCEEDED(hr))
{
IPersistFile* ppf;
hr = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
if (SUCCEEDED(hr))
{
psl->SetPath(filePath);
hr = ppf->Save(targetPath, TRUE);
ppf->Release();
}
psl->Release();
}
return SUCCEEDED(hr);
}
bool IsDirectoryWritable()
{
return TRUE;
}
//
// Registry functions.
//
bool GetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD* data)
{
DWORD type;
DWORD dataSize = sizeof(DWORD);
return (SHGetValue(rootKey, subKey, value, &type, data, &dataSize) == ERROR_SUCCESS &&
type == REG_DWORD);
}
bool GetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, WCHAR* data, DWORD bufferLength)
{
DWORD type;
DWORD dataSize = bufferLength * sizeof(data[0]);
return (SHGetValue(rootKey, subKey, value, &type, data, &dataSize) == ERROR_SUCCESS &&
type == REG_SZ);
}
bool SetRegistryData(DWORD type, HKEY rootKey, const WCHAR* subKey, const WCHAR* value, BYTE* data, DWORD dataSize)
{
BOOL result = FALSE;
HKEY regKey;
if (RegCreateKeyEx(rootKey, subKey, 0, 0, 0, KEY_SET_VALUE, nullptr, &regKey, nullptr) == ERROR_SUCCESS)
{
if (RegSetValueEx(regKey, value, 0, type, data, dataSize) == ERROR_SUCCESS)
{
result = TRUE;
}
RegCloseKey(regKey);
}
return result;
}
bool SetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD data)
{
return SetRegistryData(REG_DWORD, rootKey, subKey, value, (BYTE*)&data, sizeof(DWORD));
}
bool SetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, const WCHAR* data)
{
DWORD dataSize = (wcslen(data) + 1) * sizeof(WCHAR);
return SetRegistryData(REG_SZ, rootKey, subKey, value, (BYTE*)data, dataSize);
}
//
// Misc. functions.
//
bool DownloadFile(const WCHAR* url, const WCHAR* file)
{
bool result = false;
HINTERNET hNet = InternetOpen(L"Mozilla/5.0", INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0);
if (hNet)
{
HANDLE hFile = CreateFile(file, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile)
{
HINTERNET hUrl = InternetOpenUrl(hNet, url, nullptr, 0, INTERNET_FLAG_RESYNCHRONIZE, 0);
if (hUrl)
{
const DWORD bufferSize = 8192;
BYTE* buffer = (BYTE*)malloc(bufferSize);
if (buffer)
{
DWORD readSize;
while (InternetReadFile(hUrl, buffer, bufferSize, &readSize))
{
if (readSize == 0)
{
// All data read.
result = true;
break;
}
DWORD writeSize;
if (!WriteFile(hFile, buffer, readSize, &writeSize, nullptr) ||
readSize != writeSize)
{
break;
}
}
free(buffer);
}
InternetCloseHandle(hUrl);
}
CloseHandle(hFile);
if (!result)
{
DeleteFile(file);
}
}
InternetCloseHandle(hNet);
}
return result;
}
} // namespace Util

View File

@ -1,41 +1,41 @@
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_INSTALLER_UTIL_H_
#define RM_INSTALLER_UTIL_H_
namespace Util {
bool IsSystem64Bit();
bool IsProcessUserAdmin();
bool CanProcessUserElevate();
bool CopyDirectory(const WCHAR* fromPath, const WCHAR* toPath);
bool CreateShortcutFile(const WCHAR* filePath, const WCHAR* targetPath);
bool GetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD* data);
bool GetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, WCHAR* data, DWORD dataSize);
bool SetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD data);
bool SetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, const WCHAR* data);
bool DownloadFile(const WCHAR* url, const WCHAR* file);
} // namespace Util
/*
Copyright (C) 2013 Birunthan Mohanathas
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef RM_INSTALLER_UTIL_H_
#define RM_INSTALLER_UTIL_H_
namespace Util {
bool IsSystem64Bit();
bool IsProcessUserAdmin();
bool CanProcessUserElevate();
bool CopyDirectory(const WCHAR* fromPath, const WCHAR* toPath);
bool CreateShortcutFile(const WCHAR* filePath, const WCHAR* targetPath);
bool GetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD* data);
bool GetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, WCHAR* data, DWORD dataSize);
bool SetRegistryDword(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, DWORD data);
bool SetRegistryString(HKEY rootKey, const WCHAR* subKey, const WCHAR* value, const WCHAR* data);
bool DownloadFile(const WCHAR* url, const WCHAR* file);
} // namespace Util
#endif

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