49 Commits

Author SHA1 Message Date
1a3e3ef4b1 Release v2.3.7 2023-11-28 18:16:36 +03:00
b0a14f731a Update check timers have been fixed. 2023-11-28 18:03:12 +03:00
b12bfe08be The Updater thread has been enabled back. 2023-11-28 17:48:23 +03:00
febb3bda2f Some fixes. 2023-11-28 17:34:55 +03:00
2d90c60a1c Replaced PostMessage() function.
The PostMessageW(WM_QUIT) function has been replaced by the PostQuitMessage() function.
2023-11-28 17:18:11 +03:00
382428e6fa Temporarily disabled Updater thread creation. 2023-11-28 17:10:07 +03:00
1f8fb92dbe Replaced macro calling.
The macro call has been replaced with a call to the Out() method of an instance of the CLogger class.
2023-11-28 17:02:14 +03:00
14ee12cb85 Added CLogger class into solution tree, and removed other unnecessary files. 2023-11-28 16:46:33 +03:00
56e6a5b6b2 Added CLogger class. 2023-11-28 16:41:39 +03:00
251b965073 Fixed missing break statement. 2023-11-08 23:37:30 +03:00
b855b0d624 Changed calling updater thread. 2023-11-07 17:55:47 +03:00
0403415607 Fix the git tagname parsing. 2023-11-07 17:48:53 +03:00
18959b1ef0 Fix updates timer. 2023-11-07 17:46:09 +03:00
4299d9b89f Fix updater.cpp. 2023-11-07 17:41:25 +03:00
049375a2d7 Update README.md. 2023-11-07 17:39:58 +03:00
5bf973347f Added a timer to periodically check for updates. 2023-11-07 17:38:24 +03:00
b71793cfed Added option to disable checking for updates.
Added commandline option '/noupdate' to disable check for updates.
2023-11-04 23:36:29 +03:00
0150121c02 Some optimizations.
Moved RECT and KBDLLHOOKSTRUCT structures from global scope to local.
2023-11-04 23:24:09 +03:00
W0LF
8303665159 Update README.md 2023-11-04 22:52:24 +03:00
f2ef0f9bb4 Update .gitignore file. 2023-11-03 15:12:51 +03:00
10db7316fa Release v2.3.6 2023-06-04 15:10:01 +03:00
5e9a553b67 Removed completed TODO. 2023-06-04 15:07:31 +03:00
e74c775f90 Added check for a new version of the application. 2023-06-04 14:23:35 +03:00
aadba59546 Changed the case in the file name. 2023-06-04 13:48:45 +03:00
b58039b4ab Added version information to the beginning of the log file. 2023-05-20 14:25:35 +03:00
9dd557311e Splitted single logger.h file to .h and .cpp files. 2023-05-20 13:52:40 +03:00
8df89dc8e1 Changed logger macros. 2023-05-20 13:08:17 +03:00
cf16651ae2 Moved headers from framework.h to wCenterWindow.h. 2023-05-20 13:00:48 +03:00
9fe46f867c Added globals.h header file for global variables. 2023-05-20 12:51:45 +03:00
bb904723fa Hided 'Donation:' string. 2023-05-20 12:33:51 +03:00
eaed0ae8dc Changed size and positioning of icon's control into About dialog according to new icons. 2023-05-20 12:27:01 +03:00
854a9a473b New program icon. Created by Kirill Topov. 2023-05-20 12:17:43 +03:00
W0LF
61b5f1d39c Merge pull request #3 from dreamforceinc/dev
Release v2.3.5
2023-04-12 09:19:22 +03:00
1dd9883f42 Release v2.3.5 2023-04-12 09:13:46 +03:00
90b281d3a5 Changed control for help text from static to EditText. 2023-04-12 08:54:30 +03:00
bf609d3c08 Added DestroyIcon() function. 2023-04-12 07:35:29 +03:00
582cce5b20 Changed Logger. 2023-04-11 19:02:53 +03:00
710d9d9d3e Added LoadIconMetric() function to drawing better quality icon on HiDPI displays. 2023-04-11 11:56:46 +03:00
b6a6ec685d Simplified the "IsWindowApprooved()" function. 2023-04-08 14:29:33 +03:00
28ea979492 Hid the donation link. 2023-04-08 11:55:56 +03:00
8cd54374ab Update versioning script. 2023-04-08 11:00:40 +03:00
9b3b505ec6 Update pre-build scripts. 2023-04-02 16:50:15 +03:00
d81f43b4a3 Move global szAboutHelp variable to local. 2023-03-26 23:16:05 +03:00
a1db2f16e9 Update versioning script. 2023-03-26 23:05:36 +03:00
117c4f780f Update About dialog. 2023-03-26 22:50:52 +03:00
266afddfe5 Update About dialog. 2023-03-26 22:50:18 +03:00
6b3a90d682 Update versioning scripts. 2023-03-26 21:29:55 +03:00
0f8304ef23 Update versioning scripts. 2023-03-26 21:28:59 +03:00
c035b8a980 Added TODOs. 2022-03-25 12:56:34 +03:00
25 changed files with 1875 additions and 395 deletions

4
.gitignore vendored
View File

@@ -437,3 +437,7 @@ lightgbm.Rcheck/
# GraphViz artifacts
*.gv
*.gv.*
/wCenterWindow/VersionInfo.h
[Pp]atches/
*.patch

View File

@@ -7,6 +7,7 @@ or pressing `LCTRL + LWIN + MMB` (Middle Mouse Button).
You can use `LCTRL + LWIN + I` hotkey for hide/show trayicon.
You can also use commandline option `/hide` for hide trayicon at startup.
The `/noupdate` option is used to disable check for updates. By default, the check is repeated once a day.
`Use workarea` option means that the window is centered without a taskbar, otherwise, the full resolution of the monitor will be used.
@@ -15,7 +16,7 @@ If some windows does not centers you should run wCenterWindow with administrativ
## Automatic startup
Usually, to start the application when Windows starts, it is enough to put the application's shortcut in the "Startup" folder -\
"C:\Users\[*Your user name*]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup". (The easiest way to get there - press 'WIN + R' and type 'shell:startup').\
"C:\Users\\<*Your user name*>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup". (The easiest way to get there - press 'WIN + R' and type 'shell:startup').\
However, in this case wCenterWindow will not be able to work with windows that are open with elevated privileges.
And if you enable the "Run as administrator" option in the shortcut, then wCenterWindow will not start. This is related to the security of Windows (maybe only in 10/11, I did not check).\
This behavior can be bypassed by creating a task in the Task Scheduler with the "Run with highest privileges" option.\

173
Update_Version.ps1 Normal file
View File

@@ -0,0 +1,173 @@
# Update Version v2.1
# Required module: PSIni
# Installation: Install-Module -Name PsIni
$date = Get-Date
function addLeadingZero([int]$nvar) {
[string]$svar = $null
if ($nvar -lt 10) { $svar = '0' + $nvar.ToString() }
else { $svar = $nvar.ToString() }
return $svar
}
function getValue([string]$var) {
switch -CaseSensitive ($var) {
"%y" { $var = $currentYear; break }
"%m" { $var = $currentMonth; break }
"%d" { $var = $currentDay; break }
"%t" { $var = -join ((addLeadingZero($currentHour)), (addLeadingZero($currentMinute)), (addLeadingZero($currentSecond))); break }
"%D" { $var = $spanDays; break }
"%S" { $var = $spanSecs; break }
"%C" { $var = $gitCommitCount; break }
"%c" { $var = $gitRevCount; break }
}
return $var
}
function makeVersionString([string]$vmaj, [string]$vmin, [string]$vbld, [string]$vrev) {
[string]$vstr = $null
if ($vmin -eq "") { $vmin = $vbld = $vrev = 0; $vstr = ($vmaj) -join '.' }
else {
if ($vbld -eq "") { $vbld = $vrev = 0; $vstr = ($vmaj, $vmin) -join '.' }
else {
if ($vrev -eq "") { $vrev = 0; $vstr = ($vmaj, $vmin, $vbld) -join '.' }
else { $vstr = ($vmaj, $vmin, $vbld, $vrev) -join '.' }
}
}
[string]$nstr = ($vmaj, $vmin, $vbld, $vrev) -join ','
return @($vstr, $nstr)
}
#region Initializing variables
[string]$verMajor = [string]$verMinor = [string]$verBuild = [string]$verPatch = $null
[string]$pn = [string]$pa = [string]$aboutBuild = [string]$pnf = [string]$pcf = $null
[string]$buildDateTime = [string]$vs = [string]$vn = [string]$intName = [string]$origName = $null
[int]$pys = [int]$spanDays = [int]$spanSecs = $null
[int]$currentYear = [int]$currentMonth = [int]$currentDay = [int]$currentHour = [int]$currentMinute = [int]$currentSecond = $null
[string]$iniFile = ".\Version.ini"
#endregion
if (-not (Test-Path $iniFile)) {
Write-Error "Can't find file '$iniFile'"
# Start-Sleep -Seconds 3
exit 1
}
[bool]$isGit = $false
if (Test-Path ".\.git") {
$isGit = $true
[int]$gitCommitCount = [int]$gitRevCount = $null
[string]$gitRevDate = [string]$gitVerStr = [string]$gitAHash = $null
$gitCommitCount = $(git rev-list --count HEAD)
$gitRevDate = $(git log -1 HEAD --date=rfc --pretty=format:%ad%n)
$gitVerStr = $(git describe HEAD --long)
if ($LastExitCode -eq 0) {
$gitVerStr = $gitVerStr.Replace('-g', '-')
$gitRevCount = $gitVerStr.Split('-')[-2]
$gitAHash = $gitVerStr.Split('-')[-1]
}
else {
$gitVerStr = ""
$gitRevCount = 0
$gitAHash = $(git describe HEAD --always)
}
}
#region Reading values from INI file
$config = $null
$config = (Get-IniContent -FilePath $iniFile)["Config"]
$verMajor = $config.Major
$verMinor = $config.Minor
$verBuild = $config.Build
$verPatch = $config.Patch
$pys = $config.ProductYearStart
$pn = $config.ProductName
$pa = $config.ProductAutors
$pd = $config.ProductDescription
#endregion
if ($verMajor -eq "") {
Write-Error "Major version cannot be empty!"
# Start-Sleep -Seconds 3
exit 2
}
#region Variables preparation
$currentYear = $date.Year
$currentMonth = $date.Month
$currentDay = $date.Day
$currentHour = $date.Hour
$currentMinute = $date.Minute
$currentSecond = $date.Second
$buildDateTime = "Build date: $($date.GetDateTimeFormats('u').Replace('Z', ''))"
$spanDays = [math]::Round((New-TimeSpan -Start $(Get-Date -Month 1 -Day 1 -Year 2000) -End $date).TotalDays)
$spanSecs = [math]::Round((New-TimeSpan -Start $($date.Date) -End $($date.DateTime)).TotalSeconds)
if ($pys -eq $currentYear) { $pcf = "Copyright (C) $pys by $pa" } else { $pcf = "Copyright (C) $pys-$currentYear by $pa" }
$intName = "$pn-C++"
$origName = "$pn.exe"
$verMajor = getValue $verMajor
$verMinor = getValue $verMinor
$verBuild = getValue $verBuild
$verPatch = getValue $verPatch
#endregion
$vs = (makeVersionString $verMajor $verMinor $verBuild $verPatch)[0]
$vn = (makeVersionString $verMajor $verMinor $verBuild $verPatch)[1]
# if ([string]::IsNullOrEmpty($gitVerStr)) { $pnf = "$pn v$vs" } else { $pnf = "$pn $gitVerStr" }
if ($isGit) {
$aboutBuild = "Git date: $gitRevDate"
$pnf = "$pn v$vs ($gitAHash)"
}
else {
$aboutBuild = $buildDateTime
$pnf = "$pn v$vs"
}
#region Save all variables to file
"// $pn" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode
"// VersionInfo.h" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#pragma once" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#define PRODUCT_NAME `"$pn`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#define PRODUCT_NAME_FULL `"$pnf`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#define PRODUCT_AUTHORS `"$pa`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#define PRODUCT_DESCRIPTION `"$pd`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#define ABOUT_BUILD `"$aboutBuild`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#define INTERNAL_NAME `"$intName`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#define ORIG_FILE_NAME `"$origName`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#define PRODUCT_COPYRIGHT `"$pcf`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#define VERSION_STR `"$vs`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
"#define VERSION_NUM $vn" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
# "#define SPAN_DAYS $spanDays" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
# "#define SPAN_SECS $spanSecs" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
# if ($isGit) {
# # "#define GIT_VERSION_STR `"$gitVerStr`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
# # "#define GIT_REV_DATE `"Git date: $gitRevDate`"" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
# # "#define GIT_REV_COUNT $gitRevCount" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
# # "#define GIT_COMMIT_COUNT $gitCommitCount" | Out-File -FilePath ".\VersionInfo.h" -Encoding unicode -Append
# }
#endregion
#region Print out all variables
# echo " verMajor: [$verMajor]"
# echo " verMinor: [$verMinor]"
# echo " verBuild: [$verBuild]"
# echo " verPatch: [$verPatch]"
# echo ""
# echo " aboutBuild: [$aboutBuild]"
# echo " productNameFull: [$pnf]"
# echo "productCopyrightFull: [$pcf]"
# echo " internalName: [$intName]"
# echo " originalName: [$origName]"
# echo " versionStr: [$vs]"
# echo " versionNum: [$vn]"
# echo " spanDays: [$spanDays]"
# echo " spanSecs: [$spanSecs]"
# echo ""
# echo " gitCommitCount: [$gitCommitCount]"
# echo " gitRevCount: [$gitRevCount]"
# echo " gitRevDate: [$gitRevDate]"
# echo " gitVerStr: [$gitVerStr]"
#endregion

View File

@@ -1,81 +0,0 @@
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET CURRENT_TIME=%TIME%
SET CURRENT_DATE=%DATE%
SET BUILDTIME=%CURRENT_TIME:~0,8%
SET BUILDDATE=%CURRENT_DATE%
SET BUILD_DATETIME=Build time: %BUILDDATE% %BUILDTIME%
SET CURRENT_YEAR=%CURRENT_DATE:~6,4%
SET BUILDSECS=0
SET GIT_COUNT=0
SET GIT_TIME=0
SET GIT_DATE=0
SET GIT_DATETIME=0
SET VerMajor=0
SET VerMinor=0
SET VerPatch=0
SET INT_NAME=0
SET PN=0
SET VS=0
SET VSF=0
SET PCF=0
SET PYS=0
SET PA=0
CD /D %~dp0
IF NOT EXIST "VersionInfo.h" (
ECHO Can't find file 'VersionInfo.h'
TIMEOUT /T 3
EXIT /B 1
)
COPY /Y "VersionInfo.h" "version.h" >nul
FOR /F "tokens=3" %%A IN ('FINDSTR /I /L /C:"define V_MAJOR" "version.h"') DO (SET "VerMajor=%%A")
FOR /F "tokens=3" %%A IN ('FINDSTR /I /L /C:"define V_MINOR" "version.h"') DO (SET "VerMinor=%%A")
FOR /F "tokens=3" %%A IN ('FINDSTR /I /L /C:"define V_PATCH" "version.h"') DO (SET "VerPatch=%%A")
FOR /F "tokens=3" %%A IN ('FINDSTR /I /L /C:"define PRODUCT_NAME" "version.h"') DO (SET "PN=%%~A")
FOR /F "tokens=3" %%A IN ('FINDSTR /I /L /C:"define PRODUCT_YEAR_START" "version.h"') DO (SET "PYS=%%A")
FOR /F "tokens=2*" %%A IN ('FINDSTR /I /L /C:"define PRODUCT_AUTHORS" "version.h"') DO (SET "PA=%%~B")
FOR /F "tokens=1-4 delims=:., " %%A IN ("%BUILDTIME%") DO (SET /A "BUILDSECS=%%A * 3600 + %%B * 60 + %%C")
FOR /F "delims=" %%A IN ('git rev-list --count HEAD') DO (SET /A GIT_COUNT=%%A)
FOR /F "tokens=1,2 delims= " %%A IN ('git log -1 --date=format:%%d.%%m.%%Y ^| find /I "Date:"') DO (SET "GIT_DATE=%%B")
FOR /F "tokens=2-4 delims=, " %%A IN ('git log -1 --date=format:"%%a,%%d-%%h-%%Y,%%T" ^| find /I "Date:"') DO (
SET "GIT_DATETIME=Git time: %%A, %%B %%C"
SET "GIT_TIME=%%C"
)
SET VSF=%VerMajor%.%VerMinor%.%VerPatch%.%GIT_COUNT%
SET VS=%VerMajor%.%VerMinor%.%VerPatch%
SET VNF=%VerMajor%,%VerMinor%,%VerPatch%,%GIT_COUNT%
SET VN=%VerMajor%,%VerMinor%,%VerPatch%
SET PNF=%PN% v%VS% (C++)
SET PCF=Copyright (C) %PYS%-%CURRENT_YEAR% by %PA%
SET INT_NAME=%PN%C++
SET ORIG_NAME=%PN%.exe
ECHO #define BUILD_DATE "%BUILDDATE%">> version.h
ECHO #define BUILD_TIME "%BUILDTIME%">> version.h
ECHO #define BUILD_DATETIME "%BUILD_DATETIME%">> version.h
ECHO #define GIT_DATE "%GIT_DATE%">> version.h
ECHO #define GIT_TIME "%GIT_TIME%">> version.h
ECHO #define GIT_DATETIME "%GIT_DATETIME%">> version.h
ECHO #define GIT_COUNT %GIT_COUNT% >> version.h
ECHO #define V_SECS %BUILDSECS% >> version.h
ECHO #define INTERNAL_NAME "%INT_NAME%">> version.h
ECHO #define ORIG_FILE_NAME "%ORIG_NAME%">> version.h
ECHO #define PRODUCT_NAME_FULL "%PNF%">> version.h
ECHO #define PRODUCT_COPYRIGHT "%PCF%">> version.h
ECHO #define VERSION_NUM %VN% >> version.h
ECHO #define VERSION_STR "%VS%">> version.h
ECHO #define VERSION_NUM_FULL %VNF% >> version.h
ECHO #define VERSION_STR_FULL "%VSF%">> version.h
ENDLOCAL
EXIT

BIN
Version.ini Normal file

Binary file not shown.

View File

@@ -1,12 +0,0 @@
// wCenterWindow
// version.h
//
#pragma once
#define V_MAJOR 2
#define V_MINOR 3
#define V_PATCH 4
#define PRODUCT_NAME "wCenterWindow"
#define PRODUCT_AUTHORS "W0LF aka 'dreamforce'"
#define PRODUCT_YEAR_START 2020
#define PRODUCT_DESCRIPTION "Centers windows by hotkey"

19
pre-build.cmd Normal file
View File

@@ -0,0 +1,19 @@
@ECHO OFF
REM In VisualStudio add to Pre-Build events:
REM "$(SolutionDir)pre-build.cmd" "$(SolutionDir)" "$(ProjectDir)"
REM Then in "Resource Includes..." add '#include "VersionInfo.rc"' into 'Compile-time Directives'
IF "%~1" == "" GOTO :no_args
IF "%~2" == "" GOTO :no_args
SET solutionDir=%1
SET projectDir=%2
CD /D %solutionDir%
powershell -ExecutionPolicy RemoteSigned -File Update_Version.ps1
MOVE /Y %solutionDir%VersionInfo.h %projectDir%VersionInfo.h
EXIT
:no_args
ECHO Not enough arguments!
EXIT 1

View File

@@ -1,10 +1,15 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31112.23
# Visual Studio Version 17
VisualStudioVersion = 17.5.33516.290
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wCenterWindow", "wCenterWindow\wCenterWindow.vcxproj", "{F1A1603A-F5D0-47B8-8E4B-CF17747BCFBA}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{C7B4FD1E-DC1B-46A4-842C-5130F09EFCB5}"
ProjectSection(SolutionItems) = preProject
Version.ini = Version.ini
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64

78
wCenterWindow/CLogger.cpp Normal file
View File

@@ -0,0 +1,78 @@
// wCenterWindow
// CLogger.cpp
#include "CLogger.h"
#include <filesystem>
inline wchar_t* CLogger::GetTimeStamp() {
GetLocalTime(&lt);
swprintf_s(logTimeBuffer, L"%d-%02d-%02d %02d:%02d:%02d.%03d | ", lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds);
return logTimeBuffer;
}
void CLogger::Out(const wchar_t* fmt, ...) {
if (fsLogFile.is_open()) {
va_list args;
va_start(args, fmt);
EnterCriticalSection(&cs);
_vsnwprintf_s(logBuffer, _countof(logBuffer), _TRUNCATE, fmt, args);
va_end(args);
fsLogFile << GetTimeStamp() << logBuffer << std::endl;
LeaveCriticalSection(&cs);
}
}
void CLogger::Init() {
InitializeCriticalSection(&cs);
wchar_t szPath[MAX_PATH] = { 0 };
DWORD dwPathLength = GetModuleFileNameW(NULL, szPath, MAX_PATH);
DWORD dwError = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER == dwError) {
MessageBoxW(NULL, L"Warning!\nPath to log file is too long! Working without logging.", szAppTitle.c_str(), MB_OK | MB_ICONWARNING);
return;
}
if (NULL == dwPathLength) {
MessageBoxW(NULL, L"Warning!\nCan't get application's filename! Working without logging.", szAppTitle.c_str(), MB_OK | MB_ICONWARNING);
return;
}
std::filesystem::path log_path = szPath;
log_path.replace_extension(L".log");
std::filesystem::path bak_path = log_path;
bak_path.replace_extension(L".bak");
if (std::filesystem::exists(log_path)) std::filesystem::rename(log_path, bak_path);
#ifdef _DEBUG
log_path = L"D:\\test.log";
#endif
fsLogFile.open(log_path, std::ios::trunc);
if (fsLogFile.is_open()) {
fsLogFile << "\xEF\xBB\xBF"; // (0xEF, 0xBB, 0xBF) - UTF-8 BOM
fsLogFile.imbue(std::locale("en-US.utf8"));
fsLogFile << GetTimeStamp() << "[ " << szAppTitleVer.c_str() << " ] Start log." << std::endl;
fsLogFile << GetTimeStamp() << "Logfile: \"" << log_path.native() << "\"" << std::endl;
}
else {
MessageBoxW(NULL, L"Warning!\nCan't create log file! Working without logging.", szAppTitle.c_str(), MB_OK | MB_ICONWARNING);
}
}
CLogger::CLogger(const wchar_t* _appTitle) {
szAppTitle = _appTitle;
szAppTitleVer = _appTitle;
Init();
}
CLogger::CLogger(const wchar_t* _appTitle, const wchar_t* _appVersion) {
szAppTitle = _appTitle; szAppVersion = _appVersion;
szAppTitleVer = _appTitle;
szAppTitleVer.append(L", v").append(_appVersion);
Init();
}
CLogger::~CLogger() {
if (fsLogFile) {
fsLogFile << GetTimeStamp() << "Stop log." << std::endl;
fsLogFile.close();
DeleteCriticalSection(&cs);
}
}

31
wCenterWindow/CLogger.h Normal file
View File

@@ -0,0 +1,31 @@
// wCenterWindow
// CLogger.h
#pragma once
#include <Windows.h>
#include <fstream>
#define MAX_LOGBUFFER_LENGTH 512
class CLogger
{
public:
void Out(const wchar_t*, ...);
CLogger(const wchar_t*);
CLogger(const wchar_t*, const wchar_t*);
~CLogger();
private:
SYSTEMTIME lt;
CRITICAL_SECTION cs;
HANDLE hLoggerThread = NULL;
HANDLE hLoggerEvent = NULL;
wchar_t logTimeBuffer[28]{ 0 };
wchar_t logBuffer[MAX_LOGBUFFER_LENGTH]{ 0 };
std::wofstream fsLogFile;
std::wstring szAppTitle{ 0 };
std::wstring szAppVersion{ 0 };
std::wstring szAppTitleVer{ 0 };
inline wchar_t* GetTimeStamp();
void Init();
};

View File

@@ -1,70 +0,0 @@
// wCenterWindow
// Logger.cpp
//
#include "framework.h"
#define TS_LEN 30
std::ofstream logfile;
extern WCHAR szTitle[];
extern LPVOID szBuffer;
std::string GetTimeStamp()
{
SYSTEMTIME lt;
GetLocalTime(&lt);
CHAR ts[TS_LEN];
StringCchPrintfA(ts, TS_LEN, "%d-%02d-%02d %02d:%02d:%02d.%03d - ", lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds);
return ts;
}
void OpenLogFile()
{
WCHAR lpszPath[MAX_PATH + 1] = { 0 };
DWORD dwPathLength = GetModuleFileNameW(NULL, lpszPath, MAX_PATH);
DWORD dwError = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER == dwError)
{
MessageBoxW(NULL, L"Path to logfile is too long! Working without logging", (LPCWSTR)szTitle, MB_OK | MB_ICONWARNING);
return;
}
if (NULL == dwPathLength)
{
MessageBoxW(NULL, L"Can't get module filename! Working without logging", (LPCWSTR)szTitle, MB_OK | MB_ICONWARNING);
return;
}
std::filesystem::path log_path = lpszPath;
log_path.replace_extension(L".log");
std::filesystem::path bak_path = log_path;
bak_path.replace_extension(L".bak");
if (std::filesystem::exists(log_path)) std::filesystem::rename(log_path, bak_path);
#ifdef _DEBUG
log_path = L"d:\\test.log";
#endif
logfile.open(log_path);
if (logfile.is_open())
{
logfile << std::boolalpha;
diag_log("Start logging");
diag_log("Logfile: ", log_path);
diag_log("Logfile was successfully opened");
}
else
{
MessageBoxW(NULL, L"Can't open logfile! Working without logging", (LPCWSTR)szTitle, MB_OK | MB_ICONWARNING);
}
return;
}
void CloseLogFile()
{
if (logfile)
{
diag_log("End logging");
logfile.close();
}
}

View File

@@ -1,59 +0,0 @@
// wCenterWindow
// Logger.h
//
#pragma once
#include "framework.h"
extern std::ofstream logfile;
std::string GetTimeStamp();
template <typename T1>
void diag_log(T1 arg1)
{
logfile << GetTimeStamp() << arg1 << std::endl;
}
template <typename T1, typename T2>
void diag_log(T1 arg1, T2 arg2)
{
logfile << GetTimeStamp() << arg1 << arg2 << std::endl;
}
template <typename T1, typename T2, typename T3>
void diag_log(T1 arg1, T2 arg2, T3 arg3)
{
logfile << GetTimeStamp() << arg1 << arg2 << arg3 << std::endl;
}
template <typename T1, typename T2, typename T3, typename T4>
void diag_log(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
logfile << GetTimeStamp() << arg1 << arg2 << arg3 << arg4 << std::endl;
}
template <typename T1, typename T2, typename T3, typename T4, typename T5>
void diag_log(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5)
{
logfile << GetTimeStamp() << arg1 << arg2 << arg3 << arg4 << arg5 << std::endl;
}
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
void diag_log(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6)
{
logfile << GetTimeStamp() << arg1 << arg2 << arg3 << arg4 << arg5 << arg6 << std::endl;
}
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
void diag_log(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7)
{
logfile << GetTimeStamp() << arg1 << arg2 << arg3 << arg4 << arg5 << arg6 << arg7 << std::endl;
}
template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
void diag_log(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8)
{
logfile << GetTimeStamp() << arg1 << arg2 << arg3 << arg4 << arg5 << arg6 << arg7 << arg8 << std::endl;
}
void OpenLogFile();
void CloseLogFile();

Binary file not shown.

View File

@@ -4,16 +4,3 @@
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <iostream>
#include <fstream>
#include <filesystem>
#include <string>
#include <strsafe.h>
#include <windows.h>
#include <shellapi.h>
#include <CommCtrl.h>
// Project Specific Header Files
#include "Logger.h"

1010
wCenterWindow/picojson.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -19,8 +19,10 @@
#define IDS_ERR_MENU 117
#define IDS_ERR_POPUP 118
#define IDS_ERR_HOOK 119
#define IDS_ERR_MAXMIN 120
#define IDS_RUNNING 121
#define IDS_ERR_TIMER 120
#define IDS_ERR_MAXMIN 121
#define IDS_RUNNING 122
#define IDT_TIMER 123
#define IDR_MAINFRAME 128
#define IDD_MANUAL_EDITING 129
#define IDC_EDIT_X 1000
@@ -33,6 +35,11 @@
#define IDC_BUTTON_CLOSE 1007
#define IDC_ABOUTHELP 1008
#define IDC_DONATIONLINK 1009
#define IDC_DONATIONTEXT 1010
#define IDC_ABOUT_PROGNAME 1011
#define IDC_ABOUT_COPYRIGHT 1012
#define IDC_ABOUT_BUILDTIME 1013
#define IDC_ABOUTEDIT 1014
#define IDC_STATIC -1
// Next default values for new objects
@@ -42,7 +49,7 @@
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 130
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1010
#define _APS_NEXT_SYMED_VALUE 122
#define _APS_NEXT_CONTROL_VALUE 1015
#define _APS_NEXT_SYMED_VALUE 124
#endif
#endif

222
wCenterWindow/updater.cpp Normal file
View File

@@ -0,0 +1,222 @@
// wCenterWindow
// updater.h
//
#include "wCenterWindow.h"
#include "updater.h"
#include "picojson.h"
#include <cwctype>
#define GITHUB_URL TEXT("api.github.com")
#define GITHUB_URI TEXT("/repos/dreamforceinc/wCenterWindow/releases/latest")
picojson::value json;
struct Version
{
UINT Major = 0;
UINT Minor = 0;
UINT Build = 0;
UINT Patch = 0;
} verApp, verGh;
bool GetLatestRelease(const std::wstring& urn);
void FillVersionStructure(Version& ver, const std::wstring& str);
std::vector<std::wstring> Split(const std::wstring& s, wchar_t delim);
std::wstring ConvertUtf8ToWide(const std::string& str);
UINT WINAPI Updater(LPVOID)
{
logger.Out(L"Entering the %s() function", TEXT(__FUNCTION__));
if (!GetLatestRelease(GITHUB_URI))
{
logger.Out(L"[UPDT] %s(%d): Failed getting releases!", TEXT(__FUNCTION__), __LINE__);
MessageBoxW(NULL, L"Failed getting releases!", szTitle, MB_OK | MB_ICONERROR);
_endthreadex(101);
return 101;
}
std::wstring j_tag_name, j_file_name, j_file_ext, j_file_url, j_page_url;
int64_t j_file_size = 0;
picojson::object obj, obj2;
picojson::object::iterator it, it2;
if (json.is<picojson::object>())
{
logger.Out(L"[UPDT] %s(%d): Parsing JSON object", TEXT(__FUNCTION__), __LINE__);
obj = json.get<picojson::object>();
it = obj.find("message"), it2;
if (it != obj.end())
{
std::string u = (*it).second.get<std::string>();
logger.Out(L"[UPDT] %s(%d): Error! The url is %s", TEXT(__FUNCTION__), __LINE__, u);
_endthreadex(102);
return 102;
}
for (it = obj.begin(); it != obj.end(); it++)
{
if ((*it).first == "tag_name") j_tag_name = ConvertUtf8ToWide((*it).second.to_str());
if ((*it).first == "html_url") j_page_url = ConvertUtf8ToWide((*it).second.to_str());
if ((*it).first == "assets" && (*it).second.is<picojson::array>())
{
picojson::array a = (*it).second.get<picojson::array>();
obj2 = a[0].get<picojson::object>();
for (it2 = obj2.begin(); it2 != obj2.end(); it2++)
{
if ((*it2).first == "name") j_file_name = ConvertUtf8ToWide((*it2).second.to_str());
if ((*it2).first == "browser_download_url") j_file_url = ConvertUtf8ToWide((*it2).second.to_str());
if ((*it2).first == "size") j_file_size = static_cast<int64_t>((*it2).second.get<double>());
}
}
}
}
else
{
logger.Out(L"[UPDT] %s(%d): Error! Cannot recognize JSON object!", TEXT(__FUNCTION__), __LINE__);
_endthreadex(103);
return 103;
}
size_t pos = 0;
while (std::iswdigit(j_tag_name.at(pos)) == 0) pos++;
std::wstring gh_version = j_tag_name.substr(pos);
logger.Out(L"[UPDT] %s(%d): AppVersion : %s", TEXT(__FUNCTION__), __LINE__, TEXT(VERSION_STR));
logger.Out(L"[UPDT] %s(%d): GitVersion : %s", TEXT(__FUNCTION__), __LINE__, gh_version.c_str());
//logger.Out(L"[UPDT] %s(%d): FileName : %s", TEXT(__FUNCTION__), __LINE__, j_file_name.c_str());
//logger.Out(L"[UPDT] %s(%d): FileSize : %d", TEXT(__FUNCTION__), __LINE__, j_file_size);
//logger.Out(L"[UPDT] %s(%d): File Url : %s", TEXT(__FUNCTION__), __LINE__, j_file_url.c_str());
//logger.Out(L"[UPDT] %s(%d): Page Url : %s", TEXT(__FUNCTION__), __LINE__, j_page_url.c_str());
FillVersionStructure(verApp, TEXT(VERSION_STR));
FillVersionStructure(verGh, gh_version);
if ((verGh.Major > verApp.Major) || (verGh.Minor > verApp.Minor) || (verGh.Build > verApp.Build) || (verGh.Patch > verApp.Patch))
{
logger.Out(L"[UPDT] %s(%d): An update is available!", TEXT(__FUNCTION__), __LINE__);
if (IDYES == MessageBoxW(NULL, L"An update is available!\nDo you want to open the download page?", szTitle, MB_YESNO | MB_ICONINFORMATION))
{
logger.Out(L"[UPDT] %s(%d): Opening download page by default browser", TEXT(__FUNCTION__), __LINE__);
ShellExecuteW(NULL, L"open", j_page_url.c_str(), NULL, NULL, SW_SHOW);
}
else
{
logger.Out(L"[UPDT] %s(%d): The user refused the update", TEXT(__FUNCTION__), __LINE__);
}
}
else
{
logger.Out(L"[UPDT] %s(%d): No updates is available", TEXT(__FUNCTION__), __LINE__);
}
logger.Out(L"[UPDT] Exit from the %s() function", TEXT(__FUNCTION__));
_endthreadex(0);
return 0;
}
bool GetLatestRelease(const std::wstring& urn)
{
std::wstring user_agent = L"User-Agent: ";
user_agent.append(szTitle);
const std::wstring url = GITHUB_URL;
bool ret = true;
DWORD err = 0;
logger.Out(L"[UPDT] %s(%d): %s", TEXT(__FUNCTION__), __LINE__, user_agent.c_str());
HINTERNET hInternet = InternetOpenW(user_agent.c_str(), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (hInternet != NULL)
{
HINTERNET hConnect = InternetConnectW(hInternet, url.c_str(), INTERNET_DEFAULT_HTTPS_PORT, L"", L"", INTERNET_SERVICE_HTTP, INTERNET_FLAG_SECURE, 0);
if (hConnect != NULL)
{
HINTERNET hRequest = HttpOpenRequestW(hConnect, L"GET", urn.c_str(), NULL, NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_UI, 0);
if (hRequest != NULL)
{
BOOL isSend = HttpSendRequestW(hRequest, NULL, 0, 0, 0);
if (isSend)
{
char szData[1024]{ 0 };
DWORD dwBytesRead = 0;
std::string buffer;
do
{
InternetReadFile(hRequest, szData, sizeof(szData), &dwBytesRead);
buffer.append(szData, dwBytesRead);
} while (dwBytesRead != 0);
picojson::parse(json, buffer);
std::string jerr = picojson::get_last_error();
if (!jerr.empty())
{
std::cout << jerr << std::endl;
ret = false;
}
}
else
{
err = GetLastError();
logger.Out(L"[UPDT] %s(%d): HttpSendRequestW() error: %d", TEXT(__FUNCTION__), __LINE__, err);
ret = false;
}
}
else
{
err = GetLastError();
logger.Out(L"[UPDT] %s(%d): HttpOpenRequestW() error: %d", TEXT(__FUNCTION__), __LINE__, err);
ret = false;
}
InternetCloseHandle(hRequest);
}
else
{
err = GetLastError();
logger.Out(L"[UPDT] %s(%d): InternetConnectW() error: %d", TEXT(__FUNCTION__), __LINE__, err);
ret = false;
}
InternetCloseHandle(hConnect);
}
else
{
err = GetLastError();
logger.Out(L"[UPDT] %s(%d): InternetOpenW() error: %d", TEXT(__FUNCTION__), __LINE__, err);
ret = false;
}
InternetCloseHandle(hInternet);
return ret;
}
std::vector<std::wstring> Split(const std::wstring& s, wchar_t delim)
{
std::vector<std::wstring> result;
std::wstringstream ss(s);
std::wstring item;
while (getline(ss, item, delim)) result.push_back(item);
return result;
}
void FillVersionStructure(Version& ver, const std::wstring& str)
{
std::vector<std::wstring> v;
v = Split(str, '.');
if (v.size() < 4) v.push_back(L"0");
ver.Major = std::stoul(v[0]);
ver.Minor = std::stoul(v[1]);
ver.Build = std::stoul(v[2]);
ver.Patch = std::stoul(v[3]);
}
std::wstring ConvertUtf8ToWide(const std::string& str)
{
int count = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
std::wstring wstr(count, 0);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &wstr[0], count);
return wstr;
}

5
wCenterWindow/updater.h Normal file
View File

@@ -0,0 +1,5 @@
// wCenterWindow
// updater.h
//
#pragma once
UINT WINAPI Updater(void*);

View File

@@ -1,67 +1,66 @@
// wCenterWindow
// wCenterWindow.cpp
//
// TODO: Licensing.
// TODO: Change keyboard low-level hook to RegisterHotKey function.
// TODO: Make x64 version.
//
#include "framework.h"
#include "wCenterWindow.h"
#include "updater.h"
#define NO_DONATION
#define KEY_I 0x49
#define KEY_C 0x43
#define KEY_V 0x56
#define BUF_LEN 1024
#define MAX_LOADSTRING 50
#define WM_WCW 0x8F00
#define MAX_WINTITLE_BUFFER_LENGTH 1024
#define WM_WCW (WM_APP + 0x0F00)
// Global variables:
HINSTANCE hInst; // Instance
WCHAR szTitle[MAX_LOADSTRING]; // Window's title
WCHAR szClass[MAX_LOADSTRING]; // Window's class
WCHAR szAbout[MAX_LOADSTRING * 12]; // Description text
WCHAR szWinTitle[256];
WCHAR szWinClass[256];
WCHAR szWinCore[] = L"Windows.UI.Core.CoreWindow";
WCHAR szWorkerW[] = L"WorkerW";
HANDLE hHeap = NULL;
HHOOK hMouseHook = NULL, hKbdHook = NULL; // Hook's handles
HINSTANCE hInst; // Instance
WCHAR szTitle[MAX_LOADSTRING]{ 0 }; // wCenterWindow's title
WCHAR szClass[MAX_LOADSTRING]{ 0 }; // Window's class
WCHAR szWinTitle[256]{ 0 };
WCHAR szWinClass[256]{ 0 };
HANDLE hHeap = NULL, hUpdater = NULL;
UINT dwUpdaterID = 0;
HHOOK hMouseHook = NULL, hKbdHook = NULL; // Hook's handles
HICON hIcon = NULL;
HMENU hMenu = NULL, hPopup = NULL;
HWND hWnd = NULL, hFgWnd = NULL, hTaskBar = NULL, hDesktop = NULL, hProgman = NULL;
bool bKPressed = FALSE, bMPressed = FALSE, bShowIcon = TRUE, bWorkArea = TRUE;
bool bLCTRL = FALSE, bLWIN = FALSE, bKEYV = FALSE;
HWND hWnd = NULL, hFgWnd = NULL;
BOOL bKPressed = FALSE, bMPressed = FALSE, fShowIcon = TRUE, fCheckUpdates = TRUE, bWorkArea = TRUE;
BOOL bLCTRL = FALSE, bLWIN = FALSE, bKEYV = FALSE;
CLogger logger(TEXT(PRODUCT_NAME), TEXT(VERSION_STR));
RECT rcFW = { 0 };
NOTIFYICONDATAW nid = { 0 };
LPKBDLLHOOKSTRUCT pkhs = { 0 };
MENUITEMINFO mii = { 0 };
LPVOID szBuffer;
// {2D7B7F30-4B5F-4380-9807-57D7A2E37F6C}
static const GUID guid = { 0x2d7b7f30, 0x4b5f, 0x4380, { 0x98, 0x7, 0x57, 0xd7, 0xa2, 0xe3, 0x7f, 0x6c } };
// static const GUID guid = { 0x2d7b7f30, 0x4b5f, 0x4380, { 0x98, 0x7, 0x57, 0xd7, 0xa2, 0xe3, 0x7f, 0x6c } };
// Forward declarations of functions included in this code module:
VOID HandlingTrayIcon();
VOID ShowError(UINT);
bool IsWindowApprooved(HWND);
BOOL IsWindowApprooved(HWND);
BOOL CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK KeyboardHookProc(int, WPARAM, LPARAM);
LRESULT CALLBACK MouseHookProc(int, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
std::string ConvertWideToUtf8(const std::wstring&);
VOID MoveWindowToMonitorCenter(HWND hwnd, BOOL bWorkArea, BOOL bResize)
{
diag_log("Entering MoveWindowToMonitorCenter(), handle = 0x", hwnd);
logger.Out(L"Entering the %s() function", TEXT(__FUNCTION__));
RECT fgwrc = { 0 };
GetWindowRect(hwnd, &fgwrc);
LONG nWidth = fgwrc.right - fgwrc.left;
LONG nHeight = fgwrc.bottom - fgwrc.top;
diag_log("Moving window from x = ", fgwrc.left, ", y = ", fgwrc.top);
logger.Out(L"%s(%d): Moving the window from %d, %d", TEXT(__FUNCTION__), __LINE__, fgwrc.left, fgwrc.top);
MONITORINFO mi = { 0 };
mi.cbSize = sizeof(MONITORINFO);
@@ -91,16 +90,15 @@ VOID MoveWindowToMonitorCenter(HWND hwnd, BOOL bWorkArea, BOOL bResize)
int x = (aw - nWidth) / 2;
int y = (ah - nHeight) / 2;
logger.Out(L"%s(%d): Moving the window to %d, %d", TEXT(__FUNCTION__), __LINE__, x, y);
SendMessageW(hwnd, WM_ENTERSIZEMOVE, NULL, NULL);
MoveWindow(hwnd, x, y, nWidth, nHeight, TRUE);
SendMessageW(hwnd, WM_EXITSIZEMOVE, NULL, NULL);
diag_log("Moving window to x = ", x, ", y = ", y);
diag_log("Quiting MoveWindowToMonitorCenter()");
logger.Out(L"Exit from the %s() function", TEXT(__FUNCTION__));
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
{
hInst = hInstance;
@@ -114,14 +112,31 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd
return FALSE;
}
OpenLogFile();
diag_log("Entering WinMain()");
logger.Out(L"Entering the %s() function", TEXT(__FUNCTION__));
int nArgs = 0;
LPWSTR* szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
logger.Out(L"Arguments count: %d", nArgs - 1);
if (nArgs > 1)
{
for (int i = 1; i < nArgs; i++)
{
logger.Out(L"Argument %d: %s", i, szArglist[i]);
if (0 == lstrcmpiW(szArglist[i], L"/hide")) fShowIcon = FALSE;
if (0 == lstrcmpiW(szArglist[i], L"/noupdate")) fCheckUpdates = FALSE;
}
}
LocalFree(szArglist);
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIconW(hInstance, MAKEINTRESOURCE(IDI_TRAYICON));
LoadIconMetric(hInst, MAKEINTRESOURCE(IDI_TRAYICON), LIM_LARGE, &(wcex.hIcon));
wcex.hCursor = LoadCursorW(nullptr, IDC_ARROW);
wcex.lpszClassName = szClass;
wcex.hIconSm = wcex.hIcon;
@@ -139,27 +154,10 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd
return FALSE;
}
int nArgs = 0;
LPWSTR* szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
std::string arg;
diag_log("Arguments: ", nArgs - 1);
for (int i = 1; i < nArgs; i++)
{
arg = ConvertWideToUtf8(szArglist[i]);
diag_log("Argument #", i, ": ", arg);
}
(nArgs >= 2 && 0 == lstrcmpiW(szArglist[1], L"/hide")) ? bShowIcon = FALSE : bShowIcon = TRUE;
LocalFree(szArglist);
HandlingTrayIcon();
hHeap = GetProcessHeap();
szBuffer = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, BUF_LEN);
hTaskBar = FindWindowW(L"Shell_TrayWnd", NULL);
hProgman = FindWindowW(L"Progman", NULL);
hDesktop = GetDesktopWindow();
szBuffer = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, MAX_WINTITLE_BUFFER_LENGTH);
MSG msg;
BOOL bRet;
@@ -182,10 +180,12 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd
if (hKbdHook) UnhookWindowsHookEx(hKbdHook);
if (hMenu) DestroyMenu(hMenu);
Shell_NotifyIconW(NIM_DELETE, &nid);
DestroyIcon(hIcon);
logger.Out(L"Exit from the %s() function, msg.wParam = %d", TEXT(__FUNCTION__), (int)msg.wParam);
diag_log("Quiting WinMain(), msg.wParam = ", (int)msg.wParam);
CloseLogFile();
HeapFree(hHeap, NULL, szBuffer);
CloseHandle(hUpdater);
return (int)msg.wParam;
}
@@ -196,24 +196,25 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
case WM_CREATE:
{
diag_log("Recived WM_CREATE message");
logger.Out(L"%s(%d): Recived WM_CREATE message", TEXT(__FUNCTION__), __LINE__);
hMenu = LoadMenuW(hInst, MAKEINTRESOURCE(IDR_MENU));
if (!hMenu)
{
diag_log("Loading context menu failed!");
logger.Out(L"%s(%d): Loading context menu failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_MENU);
PostMessageW(hWnd, WM_CLOSE, NULL, NULL);
PostQuitMessage(0);
}
diag_log("Context menu successfully loaded");
logger.Out(L"%s(%d): Context menu successfully loaded", TEXT(__FUNCTION__), __LINE__);
hPopup = GetSubMenu(hMenu, 0);
if (!hPopup)
{
diag_log("Creating popup menu failed!");
logger.Out(L"%s(%d): Creating popup menu failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_POPUP);
PostMessageW(hWnd, WM_CLOSE, NULL, NULL);
PostQuitMessage(0);
}
diag_log("Popup menu successfully created");
logger.Out(L"%s(%d): Popup menu successfully created", TEXT(__FUNCTION__), __LINE__);
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STATE;
@@ -227,92 +228,137 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
nid.hIcon = hIcon;
nid.uID = IDI_TRAYICON;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nid.dwInfoFlags = NIIF_NONE;
nid.dwState = NIS_HIDDEN;
nid.dwStateMask = NIS_HIDDEN;
StringCchCopyW(nid.szTip, _countof(nid.szTip), szTitle);
if (fCheckUpdates)
{
if (!SetTimer(hWnd, IDT_TIMER, 30000, NULL)) // 30 seconds
{
logger.Out(L"%s(%d): Creating timer failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_TIMER);
fCheckUpdates = FALSE;
}
logger.Out(L"%s(%d): Timer successfully created", TEXT(__FUNCTION__), __LINE__);
}
#ifndef _DEBUG
hMouseHook = SetWindowsHookExW(WH_MOUSE_LL, MouseHookProc, hInst, NULL);
if (!hMouseHook)
{
diag_log("Creating mouse hook failed!");
logger.Out(L"%s(%d): Mouse hook creation failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_HOOK);
PostMessageW(hWnd, WM_CLOSE, NULL, NULL);
PostQuitMessage(0);
}
diag_log("Mouse hook was successfully set");
logger.Out(L"%s(%d): The mouse hook was successfully installed", TEXT(__FUNCTION__), __LINE__);
#endif // !_DEBUG
hKbdHook = SetWindowsHookExW(WH_KEYBOARD_LL, KeyboardHookProc, hInst, NULL);
if (!hKbdHook)
{
diag_log("Creating keyboard hook failed!");
ShowError(IDS_ERR_HOOK);
PostMessageW(hWnd, WM_CLOSE, NULL, NULL);
}
diag_log("Keyboard hook was successfully set");
logger.Out(L"%s(%d): Keyboard hook creation failed!", TEXT(__FUNCTION__), __LINE__);
LoadStringW(hInst, IDS_ABOUT, szAbout, _countof(szAbout));
ShowError(IDS_ERR_HOOK);
PostQuitMessage(0);
}
logger.Out(L"%s(%d): The keyboard hook was successfully installed", TEXT(__FUNCTION__), __LINE__);
break;
}
case WM_WCW:
case WM_TIMER:
{
if (fCheckUpdates)
{
logger.Out(L"%s(%d): Checking for updates is enabled, fCheckUpdates = %s", TEXT(__FUNCTION__), __LINE__, fCheckUpdates ? L"True" : L"False");
hUpdater = (HANDLE)_beginthreadex(NULL, 0, &Updater, NULL, 0, &dwUpdaterID);
if (NULL == hUpdater)
{
DWORD dwLastError = GetLastError();
logger.Out(L"%s(%d): Creating Updater thread failed! Error: %d", TEXT(__FUNCTION__), __LINE__, dwLastError);
}
else
{
if (!SetTimer(hWnd, IDT_TIMER, 86400000, NULL)) // 1 day
{
logger.Out(L"%s(%d): Creating timer failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_TIMER);
fCheckUpdates = FALSE;
}
logger.Out(L"%s(%d): Timer successfully created", TEXT(__FUNCTION__), __LINE__);
}
}
else
{
logger.Out(L"%s(%d): Checking for updates is disabled, fCheckUpdates = %s", TEXT(__FUNCTION__), __LINE__, fCheckUpdates ? L"True" : L"False");
}
break;
}
case WM_WCW: // Popup menu handler
{
if (IDI_TRAYICON == wParam && (WM_RBUTTONDOWN == lParam || WM_LBUTTONDOWN == lParam))
{
diag_log("Entering menu handler");
logger.Out(L"%s(%d): Entering the WM_WCW message handler", TEXT(__FUNCTION__), __LINE__);
SetForegroundWindow(hWnd);
POINT pt;
GetCursorPos(&pt);
int idMenu = TrackPopupMenu(hPopup, TPM_RETURNCMD, pt.x, pt.y, 0, hWnd, NULL);
if (ID_POPUPMENU_ICON == idMenu)
{
diag_log("Pressed 'Hide icon' menuitem");
bShowIcon = FALSE;
logger.Out(L"%s(%d): Pressed the 'Hide icon' menuitem", TEXT(__FUNCTION__), __LINE__);
fShowIcon = FALSE;
HandlingTrayIcon();
}
if (ID_POPUPMENU_AREA == idMenu)
{
diag_log("Pressed 'Use workarea' menuitem");
logger.Out(L"%s(%d): Pressed the 'Use workarea' menuitem", TEXT(__FUNCTION__), __LINE__);
bWorkArea = !bWorkArea;
bWorkArea ? mii.fState = MFS_CHECKED : mii.fState = MFS_UNCHECKED;
SetMenuItemInfoW(hPopup, ID_POPUPMENU_AREA, FALSE, &mii);
diag_log("Changed 'Use workarea' option to ", bWorkArea);
logger.Out(L"%s(%d): Changed 'Use workarea' option to %s", TEXT(__FUNCTION__), __LINE__, bWorkArea ? L"True" : L"False");
}
if (ID_POPUPMENU_ABOUT == idMenu && !bKPressed)
{
diag_log("Pressed 'About' menuitem");
logger.Out(L"%s(%d): Pressed the 'About' menuitem", TEXT(__FUNCTION__), __LINE__);
bKPressed = TRUE;
DialogBoxW(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, (DLGPROC)About);
bKPressed = FALSE;
}
if (ID_POPUPMENU_EXIT == idMenu)
{
diag_log("Pressed 'Exit' menuitem");
PostMessageW(hWnd, WM_CLOSE, NULL, NULL);
logger.Out(L"%s(%d): Pressed the 'Exit' menuitem", TEXT(__FUNCTION__), __LINE__);
PostQuitMessage(0);
}
diag_log("Quiting menu handler");
logger.Out(L"%s(%d): Exit from the WM_WCW message handler", TEXT(__FUNCTION__), __LINE__);
}
break;
}
case WM_QUERYENDSESSION:
{
diag_log("Recieved WM_QUERYENDSESSION message, lParam = ", lParam);
CloseLogFile();
logger.Out(L"%s(%d): Recieved the WM_QUERYENDSESSION message, lParam = 0x%08X", TEXT(__FUNCTION__), __LINE__, (long)lParam);
PostQuitMessage(0);
return TRUE;
break;
}
case WM_DESTROY:
{
diag_log("Recived WM_DESTROY message");
logger.Out(L"%s(%d): Recieved the WM_DESTROY message", TEXT(__FUNCTION__), __LINE__);
PostQuitMessage(0);
break;
}
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
default: return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}
@@ -322,7 +368,8 @@ LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
if (WM_MBUTTONUP == wParam) bMPressed = FALSE;
if (WM_MBUTTONDOWN == wParam && bLCTRL && bLWIN && !bMPressed)
{
diag_log("Pressed LCTRL + LWIN + MMB");
logger.Out(L"%s(%d): Pressed LCTRL + LWIN + MMB", TEXT(__FUNCTION__), __LINE__);
bMPressed = TRUE;
hFgWnd = GetForegroundWindow();
if (IsWindowApprooved(hFgWnd)) MoveWindowToMonitorCenter(hFgWnd, bWorkArea, FALSE);
@@ -333,8 +380,8 @@ LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
pkhs = (KBDLLHOOKSTRUCT*)lParam;
LPKBDLLHOOKSTRUCT pkhs = { 0 };
pkhs = (LPKBDLLHOOKSTRUCT)lParam;
if (WM_KEYUP == wParam)
{
if (VK_LCONTROL == pkhs->vkCode) bLCTRL = FALSE;
@@ -347,18 +394,20 @@ LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
if (VK_LCONTROL == pkhs->vkCode) bLCTRL = TRUE;
if (VK_LWIN == pkhs->vkCode) bLWIN = TRUE;
if (KEY_I == pkhs->vkCode && bLCTRL && bLWIN && !bKPressed) // 'I' key
if (KEY_I == pkhs->vkCode && bLCTRL && bLWIN && !bKPressed) // 'I' key
{
diag_log("Pressed LCTRL + LWIN + I");
logger.Out(L"%s(%d): Pressed LCTRL + LWIN + I", TEXT(__FUNCTION__), __LINE__);
bKPressed = TRUE;
bShowIcon = !bShowIcon;
fShowIcon = !fShowIcon;
HandlingTrayIcon();
return TRUE;
}
if (KEY_C == pkhs->vkCode && bLCTRL && bLWIN && !bKPressed && !bKEYV) // 'C' key
if (KEY_C == pkhs->vkCode && bLCTRL && bLWIN && !bKPressed && !bKEYV) // 'C' key
{
diag_log("Pressed LCTRL + LWIN + C");
logger.Out(L"%s(%d): Pressed LCTRL + LWIN + C", TEXT(__FUNCTION__), __LINE__);
bKPressed = TRUE;
hFgWnd = GetForegroundWindow();
if (IsWindowApprooved(hFgWnd)) MoveWindowToMonitorCenter(hFgWnd, bWorkArea, FALSE);
@@ -366,14 +415,16 @@ LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
return TRUE;
}
if (KEY_V == pkhs->vkCode && bLCTRL && bLWIN && !bKPressed && !bKEYV) // 'V' key
if (KEY_V == pkhs->vkCode && bLCTRL && bLWIN && !bKPressed && !bKEYV) // 'V' key
{
diag_log("Pressed LCTRL + LWIN + V");
logger.Out(L"%s(%d): Pressed LCTRL + LWIN + V", TEXT(__FUNCTION__), __LINE__);
bKPressed = TRUE; bKEYV = TRUE;
hFgWnd = GetForegroundWindow();
if (IsWindowApprooved(hFgWnd))
{
diag_log("Opening 'Manual editing' dialog");
logger.Out(L"%s(%d): Opening the 'Manual editing' dialog", TEXT(__FUNCTION__), __LINE__);
DialogBoxW(hInst, MAKEINTRESOURCE(IDD_MANUAL_EDITING), hFgWnd, (DLGPROC)DlgProc);
SetForegroundWindow(hFgWnd);
}
@@ -387,12 +438,14 @@ LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
BOOL CALLBACK DlgProc(HWND hDlg, UINT dlgmsg, WPARAM wParam, LPARAM lParam)
{
RECT rcFW = { 0 };
int x, y, w, h;
switch (dlgmsg)
{
case WM_INITDIALOG:
{
diag_log("Initializing 'Manual editing' dialog");
logger.Out(L"%s(%d): Initializing the 'Manual editing' dialog", TEXT(__FUNCTION__), __LINE__);
SetWindowTextW(hDlg, szTitle);
GetWindowTextW(hFgWnd, szWinTitle, _countof(szWinTitle));
GetClassNameW(hFgWnd, szWinClass, _countof(szWinClass));
@@ -412,11 +465,13 @@ BOOL CALLBACK DlgProc(HWND hDlg, UINT dlgmsg, WPARAM wParam, LPARAM lParam)
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_BUTTON_SET:
{
diag_log("Pressed 'Set' button");
logger.Out(L"%s(%d): Pressed the 'Set' button", TEXT(__FUNCTION__), __LINE__);
x = GetDlgItemInt(hDlg, IDC_EDIT_X, NULL, TRUE);
y = GetDlgItemInt(hDlg, IDC_EDIT_Y, NULL, TRUE);
w = GetDlgItemInt(hDlg, IDC_EDIT_WIDTH, NULL, FALSE);
@@ -424,76 +479,112 @@ BOOL CALLBACK DlgProc(HWND hDlg, UINT dlgmsg, WPARAM wParam, LPARAM lParam)
SendMessageW(hFgWnd, WM_ENTERSIZEMOVE, NULL, NULL);
MoveWindow(hFgWnd, x, y, w, h, TRUE);
SendMessageW(hFgWnd, WM_EXITSIZEMOVE, NULL, NULL);
diag_log("Window with handle 0x", hFgWnd, " was moved to x = ", x, ", y = ", y);
logger.Out(L"%s(%d): Window with handle 0x%08X was moved to %d, %d", TEXT(__FUNCTION__), __LINE__, hFgWnd, x, y);
return TRUE;
break;
}
case IDCANCEL:
case IDC_BUTTON_CLOSE:
{
diag_log("Closing 'Manual editing' dialog");
logger.Out(L"%s(%d): Closing the 'Manual editing' dialog", TEXT(__FUNCTION__), __LINE__);
EndDialog(hDlg, LOWORD(wParam));
break;
}
}
break;
}
}
return FALSE;
}
bool IsWindowApprooved(HWND hFW)
BOOL IsWindowApprooved(HWND hFW)
{
diag_log("Entering IsWindowApprooved(), handle = 0x", hFW);
logger.Out(L"Entering the %s() function, handle = 0x%08X", TEXT(__FUNCTION__), hFW);
bool bApprooved = FALSE;
if (hFW)
{
GetClassNameW(hFW, szWinClass, _countof(szWinClass));
if (GetWindowTextW(hFW, (LPWSTR)szBuffer, BUF_LEN - sizeof(WCHAR))) diag_log("Title: '", ConvertWideToUtf8((LPWSTR)szBuffer), "'");
if (IsIconic(hFW)) diag_log("Window is iconic");
if (IsZoomed(hFW)) diag_log("Window is maximized");
if ((wcscmp(szWinClass, szWinCore) != 0) &&
(wcscmp(szWinClass, szWorkerW) != 0) &&
(hFW != hDesktop && hFW != hTaskBar && hFW != hProgman))
if (GetWindowTextW(hFW, (LPWSTR)szBuffer, MAX_WINTITLE_BUFFER_LENGTH))
{
logger.Out(L"%s(%d): Window title: '%s'", TEXT(__FUNCTION__), __LINE__, (LPWSTR)szBuffer);
}
if (IsIconic(hFW))
{
logger.Out(L"%s(%d): The window is iconified", TEXT(__FUNCTION__), __LINE__);
}
if (IsZoomed(hFW))
{
logger.Out(L"%s(%d): The window is maximized", TEXT(__FUNCTION__), __LINE__);
}
LONG_PTR wlp = GetWindowLongPtrW(hFW, GWL_STYLE);
if (wlp & WS_CAPTION)
{
if (!IsIconic(hFW) && !IsZoomed(hFW))
{
diag_log("Window is approved");
logger.Out(L"%s(%d): The window is approved!", TEXT(__FUNCTION__), __LINE__);
bApprooved = TRUE;
}
else ShowError(IDS_ERR_MAXMIN);
}
else diag_log("The window belongs to the Windows environment");
else
{
logger.Out(L"%s(%d): The window has no caption!", TEXT(__FUNCTION__), __LINE__);
}
}
if (!bApprooved) diag_log("Window is not approved!");
diag_log("Quiting IsWindowApprooved()");
if (!bApprooved)
{
logger.Out(L"%s(%d): The window is not approved!", TEXT(__FUNCTION__), __LINE__);
}
logger.Out(L"Exit from the %s() function", TEXT(__FUNCTION__));
return bApprooved;
}
VOID HandlingTrayIcon()
{
diag_log("Entering HandlingTrayIcon(), bShowIcon = ", bShowIcon);
if (bShowIcon)
logger.Out(L"Entering the %s() function, fShowIcon = %s", TEXT(__FUNCTION__), fShowIcon ? L"True" : L"False");
if (fShowIcon)
{
bool bResult1 = Shell_NotifyIconW(NIM_ADD, &nid);
diag_log("Shell_NotifyIconW(NIM_ADD): ", bResult1);
logger.Out(L"%s(%d): Shell_NotifyIconW(NIM_ADD): %s", TEXT(__FUNCTION__), __LINE__, bResult1 ? L"True" : L"False");
bool bResult2 = Shell_NotifyIconW(NIM_SETVERSION, &nid);
diag_log("Shell_NotifyIconW(NIM_SETVERSION): ", bResult2);
logger.Out(L"%s(%d): Shell_NotifyIconW(NIM_SETVERSION): %s", TEXT(__FUNCTION__), __LINE__, bResult2 ? L"True" : L"False");
if (!bResult1 || !bResult2)
{
diag_log("Error creating trayicon!");
logger.Out(L"%s(%d): Error creating trayicon!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_ICON);
bShowIcon = FALSE;
Shell_NotifyIconW(NIM_DELETE, &nid);
fShowIcon = FALSE;
}
else
{
Shell_NotifyIconW(NIM_MODIFY, &nid);
}
}
else
{
Shell_NotifyIconW(NIM_DELETE, &nid);
}
diag_log("Quiting HandlingTrayIcon()");
logger.Out(L"Exit from the %s() function", TEXT(__FUNCTION__));
}
VOID ShowError(UINT uID)
{
WCHAR szErrorText[MAX_LOADSTRING]; // Error's text
WCHAR szErrorText[MAX_LOADSTRING]; // Error's text
LoadStringW(hInst, uID, szErrorText, _countof(szErrorText));
MessageBoxW(NULL, szErrorText, szTitle, MB_OK | MB_ICONERROR | MB_TOPMOST);
}
@@ -509,8 +600,29 @@ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
case WM_INITDIALOG:
{
diag_log("Initializing 'About' dialog");
SetDlgItemTextW(hDlg, IDC_ABOUTHELP, szAbout);
logger.Out(L"%s(%d): Initializing the 'About' dialog", TEXT(__FUNCTION__), __LINE__);
WCHAR szAboutProgName[MAX_LOADSTRING];
WCHAR szAboutCopyright[MAX_LOADSTRING];
WCHAR szAboutBuildTime[MAX_LOADSTRING];
WCHAR szAboutHelp[MAX_LOADSTRING * 12];
MultiByteToWideChar(1251, 0, PRODUCT_NAME_FULL, _countof(PRODUCT_NAME_FULL), szAboutProgName, MAX_LOADSTRING);
MultiByteToWideChar(1251, 0, PRODUCT_COPYRIGHT, _countof(PRODUCT_COPYRIGHT), szAboutCopyright, MAX_LOADSTRING);
MultiByteToWideChar(1251, 0, ABOUT_BUILD, _countof(ABOUT_BUILD), szAboutBuildTime, MAX_LOADSTRING);
LoadStringW(hInst, IDS_ABOUT, szAboutHelp, _countof(szAboutHelp));
SetDlgItemTextW(hDlg, IDC_ABOUT_PROGNAME, szAboutProgName);
SetDlgItemTextW(hDlg, IDC_ABOUT_COPYRIGHT, szAboutCopyright);
SetDlgItemTextW(hDlg, IDC_ABOUT_BUILDTIME, szAboutBuildTime);
SetDlgItemTextW(hDlg, IDC_ABOUTEDIT, szAboutHelp);
#ifdef NO_DONATION
HWND hLink = GetDlgItem(hDlg, IDC_DONATIONLINK);
if (hLink) DestroyWindow(hLink);
HWND hText = GetDlgItem(hDlg, IDC_DONATIONTEXT);
if (hText) DestroyWindow(hText);
#endif // !NO_DONATION
logger.Out(L"%s(%d): End of initializing the 'About' dialog", TEXT(__FUNCTION__), __LINE__);
return (INT_PTR)TRUE;
break;
}
@@ -523,7 +635,9 @@ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
PNMLINK pNMLink = (PNMLINK)pNMHdr;
LITEM item = pNMLink->item;
ShellExecuteW(NULL, L"open", item.szUrl, NULL, NULL, SW_SHOW);
diag_log("Pressed donation link");
logger.Out(L"%s(%d): Pressed the donation link! :-)", TEXT(__FUNCTION__), __LINE__);
return (INT_PTR)TRUE;
}
break;
@@ -534,7 +648,9 @@ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
if (IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam))
{
EndDialog(hDlg, LOWORD(wParam));
diag_log("Closing 'About' dialog");
logger.Out(L"%s(%d): Closing the 'About' dialog", TEXT(__FUNCTION__), __LINE__);
return (INT_PTR)TRUE;
}
break;
@@ -542,11 +658,3 @@ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
}
return (INT_PTR)FALSE;
}
std::string ConvertWideToUtf8(const std::wstring& wstr)
{
int count = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), NULL, 0, NULL, NULL);
std::string str(count, 0);
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &str[0], count, NULL, NULL);
return str;
}

View File

@@ -1,4 +1,32 @@
// wCenterWindow
// wCenterWindow.h
//
#pragma once
#include "resource.h"
#define MAX_LOADSTRING 50
// Windows Header Files
#include <fstream>
#include <sstream>
#include <filesystem>
#include <string>
#include <vector>
#include <strsafe.h>
#include <windows.h>
#include <wininet.h>
#include <shellapi.h>
#include <CommCtrl.h>
#include <process.h>
// Logger header file
#include "CLogger.h"
// VerionInfo header file
#include "VersionInfo.h"
// wCenterWindow's title
extern WCHAR szTitle[MAX_LOADSTRING];
// An instance of the "CLogger" class
extern CLogger logger;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

View File

@@ -73,16 +73,25 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<EnableMicrosoftCodeAnalysis>false</EnableMicrosoftCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<CopyCppRuntimeToOutputDir>false</CopyCppRuntimeToOutputDir>
<CopyLocalDeploymentContent>false</CopyLocalDeploymentContent>
<CopyLocalProjectReference>false</CopyLocalProjectReference>
<CopyLocalDebugSymbols>false</CopyLocalDebugSymbols>
<EnableMicrosoftCodeAnalysis>false</EnableMicrosoftCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<CopyLocalDeploymentContent>false</CopyLocalDeploymentContent>
<CopyLocalProjectReference>false</CopyLocalProjectReference>
<CopyLocalDebugSymbols>false</CopyLocalDebugSymbols>
<CopyCppRuntimeToOutputDir>false</CopyCppRuntimeToOutputDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -95,7 +104,7 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>comctl32.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Manifest>
<AdditionalManifestFiles>%(AdditionalManifestFiles)</AdditionalManifestFiles>
@@ -103,7 +112,7 @@
</ManifestFromManagedAssembly>
</Manifest>
<PreBuildEvent>
<Command>"$(SolutionDir)Update_version.bat"</Command>
<Command>"$(SolutionDir)pre-build.cmd" "$(SolutionDir)" "$(ProjectDir)"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -113,8 +122,8 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ConformanceMode>false</ConformanceMode>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
@@ -122,13 +131,13 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>comctl32.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Manifest>
<AdditionalManifestFiles>%(AdditionalManifestFiles)</AdditionalManifestFiles>
</Manifest>
<PreBuildEvent>
<Command>"$(SolutionDir)Update_version.bat"</Command>
<Command>"$(SolutionDir)pre-build.cmd" "$(SolutionDir)" "$(ProjectDir)"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -148,7 +157,7 @@
<AdditionalManifestFiles>%(AdditionalManifestFiles)</AdditionalManifestFiles>
</Manifest>
<PreBuildEvent>
<Command>"$(SolutionDir)Update_version.bat"</Command>
<Command>powershell -File "$(SolutionDir)Update_Version.ps1" move /y "$(SolutionDir)VersionInfo.h" "$(ProjectDir)"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -160,38 +169,40 @@
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<GenerateDebugInformation>false</GenerateDebugInformation>
<AdditionalDependencies>comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Manifest>
<AdditionalManifestFiles>%(AdditionalManifestFiles)</AdditionalManifestFiles>
</Manifest>
<PreBuildEvent>
<Command>"$(SolutionDir)Update_version.bat"</Command>
<Command>powershell -File "$(SolutionDir)Update_Version.ps1" move /y "$(SolutionDir)VersionInfo.h" "$(ProjectDir)"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="CLogger.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="Logger.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="picojson.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="updater.h" />
<ClInclude Include="wCenterWindow.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="Logger.cpp" />
<ClCompile Include="CLogger.cpp" />
<ClCompile Include="updater.cpp" />
<ClCompile Include="wCenterWindow.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="wCenterWindow.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="small.ico" />
<Image Include="wCenterWindow.ico" />
</ItemGroup>
<ItemGroup>

View File

@@ -27,7 +27,16 @@
<ClInclude Include="wCenterWindow.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Logger.h">
<ClInclude Include="logger.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="globals.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="picojson.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="updater.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
@@ -35,7 +44,10 @@
<ClCompile Include="wCenterWindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Logger.cpp">
<ClCompile Include="logger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="updater.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
@@ -45,9 +57,6 @@
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="small.ico">
<Filter>Resource Files</Filter>
</Image>
<Image Include="wCenterWindow.ico">
<Filter>Resource Files</Filter>
</Image>

View File

@@ -1,7 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommandArguments>/test1 /test2</LocalDebuggerCommandArguments>
<LocalDebuggerCommandArguments>
</LocalDebuggerCommandArguments>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>