34 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
c035b8a980 Added TODOs. 2022-03-25 12:56:34 +03:00
19 changed files with 1730 additions and 364 deletions

4
.gitignore vendored
View File

@@ -437,5 +437,7 @@ lightgbm.Rcheck/
# GraphViz artifacts
*.gv
*.gv.*
/VersionInfo.h
/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.\

View File

@@ -40,7 +40,7 @@ function makeVersionString([string]$vmaj, [string]$vmin, [string]$vbld, [string]
}
#region Initializing variables
[string]$verMajor = [string]$verMinor = [string]$verBuild = [string]$verRevision = $null
[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
@@ -80,7 +80,7 @@ $config = (Get-IniContent -FilePath $iniFile)["Config"]
$verMajor = $config.Major
$verMinor = $config.Minor
$verBuild = $config.Build
$verRevision = $config.Revision
$verPatch = $config.Patch
$pys = $config.ProductYearStart
$pn = $config.ProductName
$pa = $config.ProductAutors
@@ -109,11 +109,11 @@ $origName = "$pn.exe"
$verMajor = getValue $verMajor
$verMinor = getValue $verMinor
$verBuild = getValue $verBuild
$verRevision = getValue $verRevision
$verPatch = getValue $verPatch
#endregion
$vs = (makeVersionString $verMajor $verMinor $verBuild $verRevision)[0]
$vn = (makeVersionString $verMajor $verMinor $verBuild $verRevision)[1]
$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) {
@@ -154,7 +154,7 @@ else {
# echo " verMajor: [$verMajor]"
# echo " verMinor: [$verMinor]"
# echo " verBuild: [$verBuild]"
# echo " verRevision: [$verRevision]"
# echo " verPatch: [$verPatch]"
# echo ""
# echo " aboutBuild: [$aboutBuild]"
# echo " productNameFull: [$pnf]"

Binary file not shown.

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,71 +0,0 @@
// wLogger v3.1 (Edited version from RBTray project [https://github.com/benbuck/rbtray])
// logger.h
// Usage: LOG_TO_FILE(L"%s(%d): Log message", TEXT(__FUNCTION__), __LINE__);
#pragma once
#include "framework.h"
#define DBUFLEN 256
#define LOG_TO_FILE(fmt, ...) do { StringCchPrintfW(debugBuffer, DBUFLEN, fmt, ##__VA_ARGS__); logfile << GetTimeStamp() << debugBuffer << std::endl; } while (0)
SYSTEMTIME lt;
wchar_t debugTimeBuffer[32];
wchar_t debugBuffer[DBUFLEN];
std::wofstream logfile;
extern wchar_t szTitle[];
wchar_t* GetTimeStamp()
{
GetLocalTime(&lt);
StringCchPrintfW(debugTimeBuffer, 32, L"%d-%02d-%02d %02d:%02d:%02d.%03d | ", lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond, lt.wMilliseconds);
return debugTimeBuffer;
}
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", szTitle, MB_OK | MB_ICONWARNING);
return;
}
if (NULL == dwPathLength)
{
MessageBoxW(NULL, L"Can't get module filename! Working without logging", 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, std::ios::trunc);
if (logfile.is_open())
{
logfile << "\xEF\xBB\xBF"; // (0xEF, 0xBB, 0xBF) - UTF-8 BOM
logfile.imbue(std::locale("en-US.utf8"));
logfile << GetTimeStamp() << "[ " << szTitle << " ] Start log." << std::endl;
logfile << GetTimeStamp() << "Logfile: \"" << log_path.native() << "\"" << std::endl;
}
else
{
MessageBoxW(NULL, L"Can't open logfile! Working without logging", szTitle, MB_OK | MB_ICONWARNING);
}
return;
}
void CloseLogFile()
{
if (logfile)
{
logfile << GetTimeStamp() << "[ " << szTitle << " ] Stop log." << std::endl;
logfile.close();
}
}

View File

@@ -4,20 +4,3 @@
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#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"
#include "VersionInfo.h"
// Extern variables
#define MAX_LOADSTRING 50
WCHAR szTitle[MAX_LOADSTRING]; // wCenterWindow's title

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,10 +35,11 @@
#define IDC_BUTTON_CLOSE 1007
#define IDC_ABOUTHELP 1008
#define IDC_DONATIONLINK 1009
#define IDC_ABOUT_PROGNAME 1010
#define IDC_ABOUT_COPYRIGHT 1011
#define IDC_ABOUT_BUILDTIME 1012
#define IDC_ABOUTEDIT 1013
#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
@@ -46,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 1014
#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,41 +1,45 @@
// wCenterWindow
// wCenterWindow.cpp
//
// TODO: Licensing.
// TODO: Change keyboard low-level hook to RegisterHotKey function.
// TODO: Make x64 version.
//
#include "framework.h"
#include "logger.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 WM_WCW 0x8F00
#define MAX_WINTITLE_BUFFER_LENGTH 1024
#define WM_WCW (WM_APP + 0x0F00)
// Global variables:
HINSTANCE hInst; // Instance
extern WCHAR szTitle[];
WCHAR szClass[MAX_LOADSTRING]; // Window's class
WCHAR szWinTitle[256];
WCHAR szWinClass[256];
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;
BOOL bKPressed = FALSE, bMPressed = FALSE, bShowIcon = TRUE, bWorkArea = TRUE;
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();
@@ -49,14 +53,14 @@ INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
VOID MoveWindowToMonitorCenter(HWND hwnd, BOOL bWorkArea, BOOL bResize)
{
LOG_TO_FILE(L"Entering the %s() function", TEXT(__FUNCTION__));
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;
LOG_TO_FILE(L"%s(%d): Moving the window from %d, %d", TEXT(__FUNCTION__), __LINE__, fgwrc.left, 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);
@@ -86,12 +90,13 @@ 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);
LOG_TO_FILE(L"%s(%d): Moving the window to %d, %d", TEXT(__FUNCTION__), __LINE__, x, y);
LOG_TO_FILE(L"Exit from the %s() function", TEXT(__FUNCTION__));
logger.Out(L"Exit from the %s() function", TEXT(__FUNCTION__));
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow)
@@ -107,9 +112,24 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd
return FALSE;
}
OpenLogFile();
logger.Out(L"Entering the %s() function", TEXT(__FUNCTION__));
LOG_TO_FILE(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);
@@ -134,22 +154,10 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd
return FALSE;
}
int nArgs = 0;
LPWSTR* szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
LOG_TO_FILE(L"Arguments count: %d", nArgs - 1);
for (int i = 1; i < nArgs; i++)
{
LOG_TO_FILE(L"Argument %d: %s", i, szArglist[i]);
}
(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);
szBuffer = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, MAX_WINTITLE_BUFFER_LENGTH);
MSG msg;
BOOL bRet;
@@ -174,10 +182,10 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd
Shell_NotifyIconW(NIM_DELETE, &nid);
DestroyIcon(hIcon);
LOG_TO_FILE(L"Exit from the %s() function, msg.wParam = %d", TEXT(__FUNCTION__), (int)msg.wParam);
logger.Out(L"Exit from the %s() function, msg.wParam = %d", TEXT(__FUNCTION__), (int)msg.wParam);
CloseLogFile();
HeapFree(hHeap, NULL, szBuffer);
CloseHandle(hUpdater);
return (int)msg.wParam;
}
@@ -186,131 +194,171 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
LOG_TO_FILE(L"%s(%d): Recived WM_CREATE message", TEXT(__FUNCTION__), __LINE__);
hMenu = LoadMenuW(hInst, MAKEINTRESOURCE(IDR_MENU));
if (!hMenu)
case WM_CREATE:
{
LOG_TO_FILE(L"%s(%d): Loading context menu failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_MENU);
PostMessageW(hWnd, WM_CLOSE, NULL, NULL);
}
LOG_TO_FILE(L"%s(%d): Context menu successfully loaded", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): Recived WM_CREATE message", TEXT(__FUNCTION__), __LINE__);
hPopup = GetSubMenu(hMenu, 0);
if (!hPopup)
{
LOG_TO_FILE(L"%s(%d): Creating popup menu failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_POPUP);
PostMessageW(hWnd, WM_CLOSE, NULL, NULL);
}
LOG_TO_FILE(L"%s(%d): Popup menu successfully created", TEXT(__FUNCTION__), __LINE__);
hMenu = LoadMenuW(hInst, MAKEINTRESOURCE(IDR_MENU));
if (!hMenu)
{
logger.Out(L"%s(%d): Loading context menu failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_MENU);
PostQuitMessage(0);
}
logger.Out(L"%s(%d): Context menu successfully loaded", TEXT(__FUNCTION__), __LINE__);
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STATE;
bWorkArea ? mii.fState = MFS_CHECKED : mii.fState = MFS_UNCHECKED;
SetMenuItemInfoW(hPopup, ID_POPUPMENU_AREA, FALSE, &mii);
hPopup = GetSubMenu(hMenu, 0);
if (!hPopup)
{
logger.Out(L"%s(%d): Creating popup menu failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_POPUP);
PostQuitMessage(0);
}
logger.Out(L"%s(%d): Popup menu successfully created", TEXT(__FUNCTION__), __LINE__);
nid.cbSize = sizeof(NOTIFYICONDATAW);
nid.hWnd = hWnd;
nid.uVersion = NOTIFYICON_VERSION;
nid.uCallbackMessage = WM_WCW;
nid.hIcon = hIcon;
nid.uID = IDI_TRAYICON;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
StringCchCopyW(nid.szTip, _countof(nid.szTip), szTitle);
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_STATE;
bWorkArea ? mii.fState = MFS_CHECKED : mii.fState = MFS_UNCHECKED;
SetMenuItemInfoW(hPopup, ID_POPUPMENU_AREA, FALSE, &mii);
nid.cbSize = sizeof(NOTIFYICONDATAW);
nid.hWnd = hWnd;
nid.uVersion = NOTIFYICON_VERSION;
nid.uCallbackMessage = WM_WCW;
nid.hIcon = hIcon;
nid.uID = IDI_TRAYICON;
nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
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)
{
LOG_TO_FILE(L"%s(%d): Mouse hook creation failed!", TEXT(__FUNCTION__), __LINE__);
hMouseHook = SetWindowsHookExW(WH_MOUSE_LL, MouseHookProc, hInst, NULL);
if (!hMouseHook)
{
logger.Out(L"%s(%d): Mouse hook creation failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_HOOK);
PostMessageW(hWnd, WM_CLOSE, NULL, NULL);
}
LOG_TO_FILE(L"%s(%d): The mouse hook was successfully installed", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_HOOK);
PostQuitMessage(0);
}
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)
{
LOG_TO_FILE(L"%s(%d): Keyboard hook creation failed!", TEXT(__FUNCTION__), __LINE__);
hKbdHook = SetWindowsHookExW(WH_KEYBOARD_LL, KeyboardHookProc, hInst, NULL);
if (!hKbdHook)
{
logger.Out(L"%s(%d): Keyboard hook creation failed!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_HOOK);
PostMessageW(hWnd, WM_CLOSE, NULL, NULL);
ShowError(IDS_ERR_HOOK);
PostQuitMessage(0);
}
logger.Out(L"%s(%d): The keyboard hook was successfully installed", TEXT(__FUNCTION__), __LINE__);
break;
}
LOG_TO_FILE(L"%s(%d): The keyboard hook was successfully installed", TEXT(__FUNCTION__), __LINE__);
break;
}
case WM_WCW: // Popup menu handler
{
if (IDI_TRAYICON == wParam && (WM_RBUTTONDOWN == lParam || WM_LBUTTONDOWN == lParam))
case WM_TIMER:
{
LOG_TO_FILE(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)
if (fCheckUpdates)
{
LOG_TO_FILE(L"%s(%d): Pressed the 'Hide icon' menuitem", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): Checking for updates is enabled, fCheckUpdates = %s", TEXT(__FUNCTION__), __LINE__, fCheckUpdates ? L"True" : L"False");
bShowIcon = FALSE;
HandlingTrayIcon();
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__);
}
}
if (ID_POPUPMENU_AREA == idMenu)
else
{
LOG_TO_FILE(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);
LOG_TO_FILE(L"%s(%d): Changed 'Use workarea' option to %s", TEXT(__FUNCTION__), __LINE__, bWorkArea ? L"True" : L"False");
logger.Out(L"%s(%d): Checking for updates is disabled, fCheckUpdates = %s", TEXT(__FUNCTION__), __LINE__, fCheckUpdates ? L"True" : L"False");
}
if (ID_POPUPMENU_ABOUT == idMenu && !bKPressed)
{
LOG_TO_FILE(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)
{
LOG_TO_FILE(L"%s(%d): Pressed the 'Exit' menuitem", TEXT(__FUNCTION__), __LINE__);
PostMessageW(hWnd, WM_CLOSE, NULL, NULL);
}
LOG_TO_FILE(L"%s(%d): Exit from the WM_WCW message handler", TEXT(__FUNCTION__), __LINE__);
break;
}
break;
}
case WM_QUERYENDSESSION:
{
LOG_TO_FILE(L"%s(%d): Recieved the WM_QUERYENDSESSION message, lParam = 0x%08X", TEXT(__FUNCTION__), __LINE__, (long)lParam);
case WM_WCW: // Popup menu handler
{
if (IDI_TRAYICON == wParam && (WM_RBUTTONDOWN == lParam || WM_LBUTTONDOWN == lParam))
{
logger.Out(L"%s(%d): Entering the WM_WCW message handler", TEXT(__FUNCTION__), __LINE__);
CloseLogFile();
return TRUE;
break;
}
SetForegroundWindow(hWnd);
POINT pt;
GetCursorPos(&pt);
int idMenu = TrackPopupMenu(hPopup, TPM_RETURNCMD, pt.x, pt.y, 0, hWnd, NULL);
if (ID_POPUPMENU_ICON == idMenu)
{
logger.Out(L"%s(%d): Pressed the 'Hide icon' menuitem", TEXT(__FUNCTION__), __LINE__);
case WM_DESTROY:
{
LOG_TO_FILE(L"%s(%d): Recieved the WM_DESTROY message", TEXT(__FUNCTION__), __LINE__);
fShowIcon = FALSE;
HandlingTrayIcon();
}
if (ID_POPUPMENU_AREA == idMenu)
{
logger.Out(L"%s(%d): Pressed the 'Use workarea' menuitem", TEXT(__FUNCTION__), __LINE__);
PostQuitMessage(0);
break;
}
bWorkArea = !bWorkArea;
bWorkArea ? mii.fState = MFS_CHECKED : mii.fState = MFS_UNCHECKED;
SetMenuItemInfoW(hPopup, ID_POPUPMENU_AREA, FALSE, &mii);
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)
{
logger.Out(L"%s(%d): Pressed the 'About' menuitem", TEXT(__FUNCTION__), __LINE__);
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
bKPressed = TRUE;
DialogBoxW(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, (DLGPROC)About);
bKPressed = FALSE;
}
if (ID_POPUPMENU_EXIT == idMenu)
{
logger.Out(L"%s(%d): Pressed the 'Exit' menuitem", TEXT(__FUNCTION__), __LINE__);
PostQuitMessage(0);
}
logger.Out(L"%s(%d): Exit from the WM_WCW message handler", TEXT(__FUNCTION__), __LINE__);
}
break;
}
case WM_QUERYENDSESSION:
{
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:
{
logger.Out(L"%s(%d): Recieved the WM_DESTROY message", TEXT(__FUNCTION__), __LINE__);
PostQuitMessage(0);
break;
}
default: return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}
@@ -320,7 +368,7 @@ LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
if (WM_MBUTTONUP == wParam) bMPressed = FALSE;
if (WM_MBUTTONDOWN == wParam && bLCTRL && bLWIN && !bMPressed)
{
LOG_TO_FILE(L"%s(%d): Pressed LCTRL + LWIN + MMB", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): Pressed LCTRL + LWIN + MMB", TEXT(__FUNCTION__), __LINE__);
bMPressed = TRUE;
hFgWnd = GetForegroundWindow();
@@ -332,7 +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;
@@ -345,19 +394,19 @@ 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
{
LOG_TO_FILE(L"%s(%d): Pressed LCTRL + LWIN + I", TEXT(__FUNCTION__), __LINE__);
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
{
LOG_TO_FILE(L"%s(%d): Pressed LCTRL + LWIN + C", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): Pressed LCTRL + LWIN + C", TEXT(__FUNCTION__), __LINE__);
bKPressed = TRUE;
hFgWnd = GetForegroundWindow();
@@ -366,15 +415,15 @@ 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
{
LOG_TO_FILE(L"%s(%d): Pressed LCTRL + LWIN + V", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): Pressed LCTRL + LWIN + V", TEXT(__FUNCTION__), __LINE__);
bKPressed = TRUE; bKEYV = TRUE;
hFgWnd = GetForegroundWindow();
if (IsWindowApprooved(hFgWnd))
{
LOG_TO_FILE(L"%s(%d): Opening the 'Manual editing' dialog", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): Opening the 'Manual editing' dialog", TEXT(__FUNCTION__), __LINE__);
DialogBoxW(hInst, MAKEINTRESOURCE(IDD_MANUAL_EDITING), hFgWnd, (DLGPROC)DlgProc);
SetForegroundWindow(hFgWnd);
@@ -389,84 +438,88 @@ 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:
{
LOG_TO_FILE(L"%s(%d): Initializing the 'Manual editing' dialog", TEXT(__FUNCTION__), __LINE__);
SetWindowTextW(hDlg, szTitle);
GetWindowTextW(hFgWnd, szWinTitle, _countof(szWinTitle));
GetClassNameW(hFgWnd, szWinClass, _countof(szWinClass));
GetWindowRect(hFgWnd, &rcFW);
x = rcFW.left;
y = rcFW.top;
w = rcFW.right - rcFW.left;
h = rcFW.bottom - rcFW.top;
SetDlgItemInt(hDlg, IDC_EDIT_X, x, TRUE);
SetDlgItemInt(hDlg, IDC_EDIT_Y, y, TRUE);
SetDlgItemInt(hDlg, IDC_EDIT_WIDTH, w, FALSE);
SetDlgItemInt(hDlg, IDC_EDIT_HEIGHT, h, FALSE);
SetDlgItemTextW(hDlg, IDC_EDIT_TITLE, szWinTitle);
SetDlgItemTextW(hDlg, IDC_EDIT_CLASS, szWinClass);
UpdateWindow(hDlg);
break;
}
case WM_COMMAND:
switch (LOWORD(wParam))
case WM_INITDIALOG:
{
case IDC_BUTTON_SET:
{
LOG_TO_FILE(L"%s(%d): Pressed the 'Set' button", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): Initializing the 'Manual editing' dialog", 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);
h = GetDlgItemInt(hDlg, IDC_EDIT_HEIGHT, NULL, FALSE);
SendMessageW(hFgWnd, WM_ENTERSIZEMOVE, NULL, NULL);
MoveWindow(hFgWnd, x, y, w, h, TRUE);
SendMessageW(hFgWnd, WM_EXITSIZEMOVE, NULL, NULL);
LOG_TO_FILE(L"%s(%d): Window with handle 0x%08X was moved to %d, %d", TEXT(__FUNCTION__), __LINE__, hFgWnd, x, y);
return TRUE;
SetWindowTextW(hDlg, szTitle);
GetWindowTextW(hFgWnd, szWinTitle, _countof(szWinTitle));
GetClassNameW(hFgWnd, szWinClass, _countof(szWinClass));
GetWindowRect(hFgWnd, &rcFW);
x = rcFW.left;
y = rcFW.top;
w = rcFW.right - rcFW.left;
h = rcFW.bottom - rcFW.top;
SetDlgItemInt(hDlg, IDC_EDIT_X, x, TRUE);
SetDlgItemInt(hDlg, IDC_EDIT_Y, y, TRUE);
SetDlgItemInt(hDlg, IDC_EDIT_WIDTH, w, FALSE);
SetDlgItemInt(hDlg, IDC_EDIT_HEIGHT, h, FALSE);
SetDlgItemTextW(hDlg, IDC_EDIT_TITLE, szWinTitle);
SetDlgItemTextW(hDlg, IDC_EDIT_CLASS, szWinClass);
UpdateWindow(hDlg);
break;
}
case IDCANCEL:
case IDC_BUTTON_CLOSE:
{
LOG_TO_FILE(L"%s(%d): Closing the 'Manual editing' dialog", TEXT(__FUNCTION__), __LINE__);
EndDialog(hDlg, LOWORD(wParam));
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_BUTTON_SET:
{
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);
h = GetDlgItemInt(hDlg, IDC_EDIT_HEIGHT, NULL, FALSE);
SendMessageW(hFgWnd, WM_ENTERSIZEMOVE, NULL, NULL);
MoveWindow(hFgWnd, x, y, w, h, TRUE);
SendMessageW(hFgWnd, WM_EXITSIZEMOVE, NULL, NULL);
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:
{
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)
{
LOG_TO_FILE(L"Entering the %s() function, handle = 0x%08X", TEXT(__FUNCTION__), hFW);
logger.Out(L"Entering the %s() function, handle = 0x%08X", TEXT(__FUNCTION__), hFW);
bool bApprooved = FALSE;
if (hFW)
{
if (GetWindowTextW(hFW, (LPWSTR)szBuffer, BUF_LEN - sizeof(WCHAR)))
if (GetWindowTextW(hFW, (LPWSTR)szBuffer, MAX_WINTITLE_BUFFER_LENGTH))
{
LOG_TO_FILE(L"%s(%d): Window title: '%s'", TEXT(__FUNCTION__), __LINE__, (LPWSTR)szBuffer);
logger.Out(L"%s(%d): Window title: '%s'", TEXT(__FUNCTION__), __LINE__, (LPWSTR)szBuffer);
}
if (IsIconic(hFW))
{
LOG_TO_FILE(L"%s(%d): The window is iconified", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): The window is iconified", TEXT(__FUNCTION__), __LINE__);
}
if (IsZoomed(hFW))
{
LOG_TO_FILE(L"%s(%d): The window is maximized", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): The window is maximized", TEXT(__FUNCTION__), __LINE__);
}
LONG_PTR wlp = GetWindowLongPtrW(hFW, GWL_STYLE);
@@ -474,7 +527,7 @@ BOOL IsWindowApprooved(HWND hFW)
{
if (!IsIconic(hFW) && !IsZoomed(hFW))
{
LOG_TO_FILE(L"%s(%d): The window is approved!", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): The window is approved!", TEXT(__FUNCTION__), __LINE__);
bApprooved = TRUE;
}
@@ -482,39 +535,39 @@ BOOL IsWindowApprooved(HWND hFW)
}
else
{
LOG_TO_FILE(L"%s(%d): The window has no caption!", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): The window has no caption!", TEXT(__FUNCTION__), __LINE__);
}
}
if (!bApprooved)
{
LOG_TO_FILE(L"%s(%d): The window is not approved!", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): The window is not approved!", TEXT(__FUNCTION__), __LINE__);
}
LOG_TO_FILE(L"Exit from the %s() function", TEXT(__FUNCTION__));
logger.Out(L"Exit from the %s() function", TEXT(__FUNCTION__));
return bApprooved;
}
VOID HandlingTrayIcon()
{
LOG_TO_FILE(L"Entering the %s() function, bShowIcon = %s", TEXT(__FUNCTION__), bShowIcon ? L"True" : L"False");
logger.Out(L"Entering the %s() function, fShowIcon = %s", TEXT(__FUNCTION__), fShowIcon ? L"True" : L"False");
if (bShowIcon)
if (fShowIcon)
{
bool bResult1 = Shell_NotifyIconW(NIM_ADD, &nid);
LOG_TO_FILE(L"%s(%d): Shell_NotifyIconW(NIM_ADD): %s", TEXT(__FUNCTION__), __LINE__, bResult1 ? L"True" : L"False");
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);
LOG_TO_FILE(L"%s(%d): Shell_NotifyIconW(NIM_SETVERSION): %s", TEXT(__FUNCTION__), __LINE__, bResult2 ? L"True" : L"False");
logger.Out(L"%s(%d): Shell_NotifyIconW(NIM_SETVERSION): %s", TEXT(__FUNCTION__), __LINE__, bResult2 ? L"True" : L"False");
if (!bResult1 || !bResult2)
{
LOG_TO_FILE(L"%s(%d): Error creating trayicon!", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): Error creating trayicon!", TEXT(__FUNCTION__), __LINE__);
ShowError(IDS_ERR_ICON);
Shell_NotifyIconW(NIM_DELETE, &nid);
bShowIcon = FALSE;
fShowIcon = FALSE;
}
else
{
@@ -526,12 +579,12 @@ VOID HandlingTrayIcon()
Shell_NotifyIconW(NIM_DELETE, &nid);
}
LOG_TO_FILE(L"Exit from the %s() function", TEXT(__FUNCTION__));
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);
}
@@ -545,61 +598,63 @@ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
{
case WM_INITDIALOG:
{
LOG_TO_FILE(L"%s(%d): Initializing the 'About' dialog", TEXT(__FUNCTION__), __LINE__);
case WM_INITDIALOG:
{
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);
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 hLink = GetDlgItem(hDlg, IDC_DONATIONLINK);
if (hLink) DestroyWindow(hLink);
HWND hText = GetDlgItem(hDlg, IDC_DONATIONTEXT);
if (hText) DestroyWindow(hText);
#endif // !NO_DONATION
LOG_TO_FILE(L"%s(%d): End of initializing the 'About' dialog", TEXT(__FUNCTION__), __LINE__);
return (INT_PTR)TRUE;
break;
}
case WM_NOTIFY:
{
LPNMHDR pNMHdr = (LPNMHDR)lParam;
if ((NM_CLICK == pNMHdr->code || NM_RETURN == pNMHdr->code) && IDC_DONATIONLINK == pNMHdr->idFrom)
{
PNMLINK pNMLink = (PNMLINK)pNMHdr;
LITEM item = pNMLink->item;
ShellExecuteW(NULL, L"open", item.szUrl, NULL, NULL, SW_SHOW);
LOG_TO_FILE(L"%s(%d): Pressed the donation link! :-)", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): End of initializing the 'About' dialog", TEXT(__FUNCTION__), __LINE__);
return (INT_PTR)TRUE;
break;
}
break;
}
case WM_COMMAND:
{
if (IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam))
case WM_NOTIFY:
{
EndDialog(hDlg, LOWORD(wParam));
LPNMHDR pNMHdr = (LPNMHDR)lParam;
if ((NM_CLICK == pNMHdr->code || NM_RETURN == pNMHdr->code) && IDC_DONATIONLINK == pNMHdr->idFrom)
{
PNMLINK pNMLink = (PNMLINK)pNMHdr;
LITEM item = pNMLink->item;
ShellExecuteW(NULL, L"open", item.szUrl, NULL, NULL, SW_SHOW);
LOG_TO_FILE(L"%s(%d): Closing the 'About' dialog", TEXT(__FUNCTION__), __LINE__);
logger.Out(L"%s(%d): Pressed the donation link! :-)", TEXT(__FUNCTION__), __LINE__);
return (INT_PTR)TRUE;
return (INT_PTR)TRUE;
}
break;
}
case WM_COMMAND:
{
if (IDOK == LOWORD(wParam) || IDCANCEL == LOWORD(wParam))
{
EndDialog(hDlg, LOWORD(wParam));
logger.Out(L"%s(%d): Closing the 'About' dialog", TEXT(__FUNCTION__), __LINE__);
return (INT_PTR)TRUE;
}
break;
}
break;
}
}
return (INT_PTR)FALSE;
}

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

@@ -104,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>
@@ -131,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>powershell -ExecutionPolicy RemoteSigned -File "$(SolutionDir)Update_Version.ps1" &amp;&amp; move /y "$(SolutionDir)VersionInfo.h" "$(ProjectDir)"</Command>
<Command>"$(SolutionDir)pre-build.cmd" "$(SolutionDir)" "$(ProjectDir)"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -186,20 +186,23 @@
</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="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

@@ -30,11 +30,26 @@
<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>
<ItemGroup>
<ClCompile Include="wCenterWindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="logger.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="updater.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="wCenterWindow.rc">
@@ -42,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>