[win] remove online installer

This commit is contained in:
SimplestStudio
2025-08-06 17:50:24 +03:00
parent c14481ee53
commit 01fa3ad774
65 changed files with 0 additions and 12051 deletions

View File

@ -1,19 +0,0 @@
DESTDIR = $$PWD
include(common.pri)
DEFINES += COPYRIGHT_YEAR=$${CURRENT_YEAR}
DEFINES += APP_ICON_PATH=\"./icons/desktopeditors.ico\"
DEFINES += APP_LANG_PATH=\"./langs/langs.iss\"
OTHER_FILES += $$PWD/res/langs/langs.iss
ENV_URL_INSTALL = $$(DESKTOP_URL_UPDATES_MAIN_CHANNEL)
isEmpty(ENV_URL_INSTALL): DEFINES += URL_INSTALL=\\\"\\\"
else: DEFINES += URL_INSTALL=\\\"$${ENV_URL_INSTALL}\\\"
ENV_URL_INSTALL_DEV = $$(DESKTOP_URL_UPDATES_DEV_CHANNEL)
isEmpty(ENV_URL_INSTALL_DEV): DEFINES += URL_INSTALL_DEV=\\\"\\\"
else: DEFINES += URL_INSTALL_DEV=\\\"$${ENV_URL_INSTALL_DEV}\\\"
message(install url: \\\"$$ENV_URL_INSTALL\\\")
message(install dev url: \\\"$$ENV_URL_INSTALL_DEV\\\")

View File

@ -1,129 +0,0 @@
TARGET = online-installer
CONFIG += c++11 utf8_source static_runtime
CONFIG -= app_bundle
CONFIG -= qt
CONFIG -= debug_and_release debug_and_release_target
TEMPLATE = app
CORE_ROOT_DIR = $$PWD/../../../../core
UICLASSES = $$PWD/src/uiclasses
CONFIG += core_no_dst
include($$CORE_ROOT_DIR/Common/base.pri)
INCLUDEPATH += $$PWD/src \
$$UICLASSES
INCLUDEPATH += $$PWD/../../src/prop
HEADERS += $$PWD/src/version.h \
$$PWD/src/resource.h \
$$PWD/src/mainwindow.h \
$$PWD/src/cdownloader.h \
$$PWD/src/translator.h \
$$PWD/src/cjson_p.h \
$$PWD/src/cjson.h \
$$PWD/src/utils.h \
$$UICLASSES/commondefines.h \
$$UICLASSES/baseutils.h \
$$UICLASSES/common.h \
$$UICLASSES/metrics.h \
$$UICLASSES/palette.h \
$$UICLASSES/drawningengine.h \
$$UICLASSES/drawingsurface.h \
$$UICLASSES/object.h \
$$UICLASSES/application.h \
$$UICLASSES/window.h \
$$UICLASSES/widget.h \
$$UICLASSES/label.h \
$$UICLASSES/caption.h \
$$UICLASSES/abstractbutton.h \
$$UICLASSES/button.h \
$$UICLASSES/checkbox.h \
$$UICLASSES/radiobutton.h \
$$UICLASSES/progressbar.h \
$$UICLASSES/layoutitem.h \
$$UICLASSES/layout.h \
$$UICLASSES/boxlayout.h
SOURCES += $$PWD/src/main.cpp \
$$PWD/src/mainwindow.cpp \
$$PWD/src/cdownloader.cpp \
$$PWD/src/translator.cpp \
$$PWD/src/cjson.cpp \
$$PWD/src/utils.cpp \
$$UICLASSES/baseutils.cpp \
$$UICLASSES/common.cpp \
$$UICLASSES/metrics.cpp \
$$UICLASSES/palette.cpp \
$$UICLASSES/drawningengine.cpp \
$$UICLASSES/drawingsurface.cpp \
$$UICLASSES/object.cpp \
$$UICLASSES/application.cpp \
$$UICLASSES/window.cpp \
$$UICLASSES/widget.cpp \
$$UICLASSES/label.cpp \
$$UICLASSES/caption.cpp \
$$UICLASSES/abstractbutton.cpp \
$$UICLASSES/button.cpp \
$$UICLASSES/checkbox.cpp \
$$UICLASSES/radiobutton.cpp \
$$UICLASSES/progressbar.cpp \
$$UICLASSES/layoutitem.cpp \
$$UICLASSES/layout.cpp \
$$UICLASSES/boxlayout.cpp
OTHER_FILES += $$PWD/res/version.rc \
$$PWD/res/manifest/online-installer.exe.manifest
ENV_PRODUCT_VERSION = "2.0.0" # $$(PRODUCT_VERSION)
!isEmpty(ENV_PRODUCT_VERSION) {
FULL_PRODUCT_VERSION = $${ENV_PRODUCT_VERSION}.$$(BUILD_NUMBER)
DEFINES += VER_PRODUCT_VERSION=$$FULL_PRODUCT_VERSION \
VER_PRODUCT_VERSION_COMMAS=$$replace(FULL_PRODUCT_VERSION, \., ",")
}
CONFIG -= embed_manifest_exe
RC_FILE = $$PWD/res/version.rc
QMAKE_CXXFLAGS += -D_UNICODE
contains(QMAKE_TARGET.arch, x86_64):{
QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS,5.02
} else {
QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS,5.01
}
core_release:DESTDIR = $$DESTDIR/build
core_debug:DESTDIR = $$DESTDIR/build/debug
!isEmpty(OO_BUILD_BRANDING) {
DESTDIR = $$DESTDIR/$$OO_BUILD_BRANDING
}
DESTDIR = $$DESTDIR/$$CORE_BUILDS_PLATFORM_PREFIX
build_xp {
DESTDIR = $$DESTDIR/xp
DEFINES += __OS_WIN_XP
}
DEFINES -= NOMINMAX
LIBS += -luser32 \
-lshell32 \
-lshlwapi \
-lwinhttp \
-lwintrust \
-lgdi32 \
-lgdiplus \
-ladvapi32 \
-lrpcrt4 \
-lole32 \
-lmsi \
-lwinmm \
-lcomctl32
OBJECTS_DIR = $$DESTDIR/obj
MOC_DIR = $$DESTDIR/moc
RCC_DIR = $$DESTDIR/rcc

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="*"
name="online-installer.exe"
type="win32"
/>
<description> Online Installer. </description>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 10 and Windows 11 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2020/WindowsSettings">
<heapType>SegmentHeap</heapType>
</asmv3:windowsSettings>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">
<gdiScaling>true</gdiScaling>
</asmv3:windowsSettings>
</asmv3:application>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View File

@ -1,37 +0,0 @@
#pragma code_page(65001)
#include <Windows.h>
#include "../src/version.h"
#include "../src/resource.h"
IDI_MAINICON ICON DISCARDABLE APP_ICON_PATH
IDI_WELCOME RCDATA "./icons/welcome.emf"
IDT_TRANSLATIONS RCDATA APP_LANG_PATH
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "./manifest/online-installer.exe.manifest"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILEVERSION
PRODUCTVERSION VER_PRODUCTVERSION
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK VER_LANG_AND_CHARSET_STR
BEGIN
VALUE "CompanyName", VER_COMPANYNAME_STR
VALUE "FileDescription", VER_FILEDESCRIPTION_STR
VALUE "FileVersion", VER_FILEVERSION_STR
VALUE "InternalName", VER_INTERNALNAME_STR
VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
VALUE "LegalTrademarks1", VER_LEGALTRADEMARKS1_STR
VALUE "LegalTrademarks2", VER_LEGALTRADEMARKS2_STR
VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR
VALUE "ProductName", VER_PRODUCTNAME_STR
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", VER_LANG_ID, VER_CHARSET_ID
END
END

View File

@ -1,279 +0,0 @@
/*
* (c) Copyright Ascensio System SIA 2010-2019
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "cdownloader.h"
#include <Windows.h>
#include <Winhttp.h>
#include <future>
struct Connection {
~Connection() {
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
}
HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL;
};
static DWORD initConnection(const wstring &url, DWORD &dwFileSize, Connection &conn)
{
URL_COMPONENTS urlComp;
ZeroMemory(&urlComp, sizeof(urlComp));
urlComp.dwStructSize = sizeof(urlComp);
urlComp.dwHostNameLength = 1;
urlComp.dwUrlPathLength = 1;
if (!WinHttpCrackUrl(url.c_str(), (DWORD)url.length(), 0, &urlComp))
return GetLastError();
wstring url_host(urlComp.lpszHostName, urlComp.dwHostNameLength);
wstring url_path(urlComp.lpszUrlPath, urlComp.dwUrlPathLength);
conn.hSession = WinHttpOpen(L"WinHTTP Example/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
if (!conn.hSession)
return GetLastError();
DWORD dwEnabledProtocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
WinHttpSetOption(conn.hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &dwEnabledProtocols, sizeof(DWORD));
#ifdef IGNORE_CERTIFICATE_REQUIREMENTS
DWORD dwSecurity = SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_FLAG_IGNORE_CERT_CN_INVALID | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
WinHttpSetOption(conn.hSession, WINHTTP_OPTION_SECURITY_FLAGS, &dwSecurity, sizeof(DWORD));
#endif
conn.hConnect = WinHttpConnect(conn.hSession, url_host.c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0);
if (!conn.hConnect)
return GetLastError();
conn.hRequest = WinHttpOpenRequest(conn.hConnect, L"GET", url_path.c_str(), NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
if (!conn.hRequest)
return GetLastError();
if (!WinHttpSendRequest(conn.hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0))
return GetLastError();
if (!WinHttpReceiveResponse(conn.hRequest, NULL))
return GetLastError();
DWORD dwStatusCode = 0, dwSize = sizeof(DWORD);
if (!WinHttpQueryHeaders(conn.hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwStatusCode, &dwSize, WINHTTP_NO_HEADER_INDEX))
return GetLastError();
if (dwStatusCode >= HTTP_STATUS_BAD_REQUEST)
return ERROR_BAD_FORMAT;
if (!WinHttpQueryHeaders(conn.hRequest, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwFileSize, &dwSize, WINHTTP_NO_HEADER_INDEX))
dwFileSize = 0;
return ERROR_SUCCESS;
}
class CDownloaderPrivate
{
public:
CDownloaderPrivate()
{}
~CDownloaderPrivate()
{}
DWORD downloadToFile()
{
DWORD dwSize = 0, dwProgress = 0, dwProgressMax = 0;
Connection conn;
DWORD result = initConnection(m_url, dwProgressMax, conn);
if (result != ERROR_SUCCESS)
return result;
HANDLE hFile = CreateFile(m_filePath.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return GetLastError();
int prev_percent = -1;
do {
if (!m_run) {
result = ERROR_CANCELLED;
break;
}
dwSize = 0;
if (!WinHttpQueryDataAvailable(conn.hRequest, &dwSize)) {
result = GetLastError();
break;
}
LPSTR lpBuffer = new char[dwSize];
if (!lpBuffer) {
result = ERROR_NOT_ENOUGH_MEMORY;
break;
}
DWORD dwDownloaded = 0;
if (!WinHttpReadData(conn.hRequest, (LPVOID)lpBuffer, dwSize, &dwDownloaded)) {
result = GetLastError();
delete[] lpBuffer;
break;
}
DWORD dwBytesWritten = 0;
BOOL write_res = WriteFile(hFile, lpBuffer, dwDownloaded, &dwBytesWritten, NULL);
delete[] lpBuffer;
if (!write_res) {
result = GetLastError();
break;
}
if (dwBytesWritten != dwDownloaded) {
result = ERROR_OUTOFMEMORY;
break;
}
if (dwProgressMax != 0 && m_progress_callback) {
dwProgress += dwDownloaded;
int percent = static_cast<int>((100.0 * dwProgress) / dwProgressMax);
if (percent != prev_percent) {
m_progress_callback(percent);
prev_percent = percent;
}
}
} while (dwSize > 0);
CloseHandle(hFile);
if (result == ERROR_CANCELLED)
DeleteFile(m_filePath.c_str());
return result;
}
FnVoidUlUl m_query_callback = nullptr;
FnVoidUl m_complete_callback = nullptr;
FnVoidInt m_progress_callback = nullptr;
wstring m_url,
m_filePath;
std::future<void> m_future;
std::atomic_bool m_run,
m_lock;
};
CDownloader::CDownloader() :
pimpl(new CDownloaderPrivate)
{
pimpl->m_run = true;
pimpl->m_lock = false;
}
CDownloader::~CDownloader()
{
pimpl->m_run = false;
if (pimpl->m_future.valid())
pimpl->m_future.wait();
delete pimpl, pimpl = nullptr;
}
bool CDownloader::isUrlAccessible(const wstring &url)
{
if (url.empty())
return false;
DWORD dwFileSize = 0;
Connection conn;
int hr = initConnection(url, dwFileSize, conn);
return hr == ERROR_SUCCESS;
}
void CDownloader::queryContentLenght(const wstring &url)
{
if (url.empty() || pimpl->m_lock)
return;
pimpl->m_lock = true;
pimpl->m_future = std::async(std::launch::async, [=]() {
DWORD dwFileSize = 0;
Connection conn;
DWORD error = initConnection(url, dwFileSize, conn);
if (pimpl->m_query_callback)
pimpl->m_query_callback(error, dwFileSize);
pimpl->m_lock = false;
});
}
void CDownloader::downloadFile(const std::wstring &url, const std::wstring &filePath)
{
pimpl->m_url.clear();
pimpl->m_filePath.clear();
if (url.empty() || filePath.empty() || pimpl->m_lock)
return;
pimpl->m_url = url;
pimpl->m_filePath = filePath;
start();
}
void CDownloader::start()
{
if (pimpl->m_url.empty() || pimpl->m_filePath.empty() || pimpl->m_lock)
return;
pimpl->m_run = true;
pimpl->m_lock = true;
pimpl->m_future = std::async(std::launch::async, [=]() {
DWORD error = pimpl->downloadToFile();
if (pimpl->m_complete_callback)
pimpl->m_complete_callback(error);
pimpl->m_lock = false;
});
}
void CDownloader::stop()
{
pimpl->m_run = false;
if (pimpl->m_future.valid())
pimpl->m_future.wait();
}
wstring CDownloader::GetFilePath()
{
return pimpl->m_filePath;
}
void CDownloader::onQueryResponse(FnVoidUlUl callback)
{
pimpl->m_query_callback = callback;
}
void CDownloader::onComplete(FnVoidUl callback)
{
pimpl->m_complete_callback = callback;
}
void CDownloader::onProgress(FnVoidInt callback)
{
pimpl->m_progress_callback = callback;
}

View File

@ -1,71 +0,0 @@
/*
* (c) Copyright Ascensio System SIA 2010-2019
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#ifndef CDOWNLOADER_H
#define CDOWNLOADER_H
#include <string>
#include <functional>
typedef unsigned long ulong;
typedef std::function<void(int)> FnVoidInt;
typedef std::function<void(ulong)> FnVoidUl;
typedef std::function<void(ulong,ulong)> FnVoidUlUl;
using std::wstring;
class CDownloaderPrivate;
class CDownloader
{
public:
CDownloader();
~CDownloader();
bool isUrlAccessible(const wstring &url);
void queryContentLenght(const wstring &url);
void downloadFile(const wstring &url, const wstring &filePath);
void start();
void stop();
wstring GetFilePath();
/* callback */
void onQueryResponse(FnVoidUlUl callback);
void onComplete(FnVoidUl callback);
void onProgress(FnVoidInt callback);
private:
CDownloaderPrivate *pimpl = nullptr;
};
#endif // CDOWNLOADER_H

View File

@ -1,185 +0,0 @@
/*
* (c) Copyright Ascensio System SIA 2010-2019
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "cjson.h"
#include "cjson_p.h"
#include <codecvt>
static std::string TStrToUtf8(const tstring &str)
{
#ifdef _WIN32
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> utf8_conv;
return utf8_conv.to_bytes(str);
#else
return str;
#endif
}
class JsonObjectPrivate
{
public:
json_object_s *obj = nullptr;
};
class JsonValuePrivate
{
public:
json_value_s *val = nullptr;
};
class JsonDocumentPrivate
{
public:
json_value_s *root = nullptr;
};
JsonValue::JsonValue() : pimpl(new JsonValuePrivate)
{}
JsonValue::JsonValue(const JsonValue &jval) : JsonValue()
{
pimpl->val = jval.pimpl->val;
}
JsonValue::~JsonValue()
{
delete pimpl, pimpl = nullptr;
}
JsonValue& JsonValue::operator=(const JsonValue &jval)
{
if (this == &jval)
return *this;
pimpl->val = jval.pimpl->val;
return *this;
}
JsonObject JsonValue::toObject()
{
JsonObject jobj;
if (pimpl->val && pimpl->val->type == json_type_object)
jobj.pimpl->obj = (json_object_s*)pimpl->val->payload;
return jobj;
}
tstring JsonValue::toTString()
{
tstring str;
if (pimpl->val && pimpl->val->type == json_type_string) {
json_string_s *jstr = (json_string_s*)pimpl->val->payload;
#ifdef _WIN32
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
str = converter.from_bytes(std::string(jstr->string, jstr->string_size));
#else
str = std::string(jstr->string, jstr->string_size);
#endif
}
return str;
}
JsonObject::JsonObject() : pimpl(new JsonObjectPrivate)
{}
JsonObject::JsonObject(const JsonObject &jobj) : JsonObject()
{
pimpl->obj = jobj.pimpl->obj;
}
JsonObject::~JsonObject()
{
delete pimpl, pimpl = nullptr;
}
JsonObject& JsonObject::operator=(const JsonObject &jobj)
{
if (this == &jobj)
return *this;
pimpl->obj = jobj.pimpl->obj;
return *this;
}
JsonValue JsonObject::value(const tstring &key)
{
std::string utf8_key = TStrToUtf8(key);
JsonValue jval;
json_object_element_s *element;
if (pimpl->obj && (element = pimpl->obj->start) != NULL) {
do {
if (strcmp(element->name->string, utf8_key.c_str()) == 0) {
jval.pimpl->val = element->value;
break;
}
} while ((element = element->next) != NULL);
}
return jval;
}
bool JsonObject::contains(const tstring &key)
{
std::string utf8_key = TStrToUtf8(key);
json_object_element_s *element;
if (pimpl->obj && (element = pimpl->obj->start) != NULL) {
do {
if (strcmp(element->name->string, utf8_key.c_str()) == 0)
return true;
} while ((element = element->next) != NULL);
}
return false;
}
JsonDocument::JsonDocument() : pimpl(new JsonDocumentPrivate)
{}
JsonDocument::JsonDocument(const tstring &json) : JsonDocument()
{
std::string utf8_json = TStrToUtf8(json);
pimpl->root = json_parse(utf8_json.c_str(), utf8_json.length());
}
JsonDocument::~JsonDocument()
{
if (pimpl->root)
free(pimpl->root);
delete pimpl, pimpl = nullptr;
}
JsonObject JsonDocument::object()
{
JsonObject obj;
if (pimpl->root && pimpl->root->type == json_type_object && pimpl->root->payload)
obj.pimpl->obj = (json_object_s*)pimpl->root->payload;
return obj;
}

View File

@ -1,96 +0,0 @@
/*
* (c) Copyright Ascensio System SIA 2010-2019
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#ifndef CJSON_H
#define CJSON_H
#include <string>
#ifdef _WIN32
# include <tchar.h>
# define tstring std::wstring
#else
# define _T(str) str
# define tstring std::string
#endif
class JsonObject;
class JsonObjectPrivate;
class JsonValuePrivate;
class JsonDocumentPrivate;
class JsonValue
{
public:
JsonValue();
JsonValue(const JsonValue&);
~JsonValue();
JsonValue& operator=(const JsonValue&);
JsonObject toObject();
tstring toTString();
private:
friend class JsonObject;
JsonValuePrivate *pimpl;
};
class JsonObject
{
public:
JsonObject();
JsonObject(const JsonObject&);
~JsonObject();
JsonObject& operator=(const JsonObject&);
JsonValue value(const tstring&);
bool contains(const tstring&);
private:
friend class JsonDocument;
friend class JsonValue;
JsonObjectPrivate *pimpl;
};
class JsonDocument
{
public:
JsonDocument(const tstring&);
~JsonDocument();
JsonObject object();
private:
JsonDocument();
JsonDocumentPrivate *pimpl;
};
#endif // CJSON_H

File diff suppressed because it is too large Load Diff

View File

@ -1,70 +0,0 @@
#include "application.h"
#include "mainwindow.h"
#include <locale>
#include "resource.h"
#include "utils.h"
#include "baseutils.h"
#include "translator.h"
#include "../../src/defines.h"
#include "../../src/prop/defines_p.h"
#define WINDOW_SIZE Size(768, 480)
int WINAPI _tWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
int num_args = 0;
if (LPTSTR *args = CommandLineToArgvW(lpCmdLine, &num_args)) {
NS_Utils::parseCmdArgs(num_args, args);
LocalFree(args);
}
if (NS_Utils::cmdArgContains(_T("--log")))
NS_Logger::AllowWriteLog();
std::locale::global(std::locale(""));
LCID lcid = MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT);
Translator lang(lcid, IDT_TRANSLATIONS);
HANDLE hMutex = CreateMutex(NULL, FALSE, _T(VER_PRODUCTNAME_STR));
if (GetLastError() == ERROR_ALREADY_EXISTS) {
NS_Utils::ShowMessage(_TR(MSG_ERR_ALREADY_RUNNING));
return 0;
}
if (Utils::getWinVersion() < Utils::Win7) {
wstring msg(_TR(MSG_ERR_SYSTEM));
NS_Utils::Replace(msg, L"%1", _TR(CAPTION));
NS_Utils::ShowMessage(msg);
CloseHandle(hMutex);
return 0;
}
if (!NS_Utils::checkAndWaitForAppClosure()) {
CloseHandle(hMutex);
return 0;
}
wstring path, arch;
bool app_installed = NS_Utils::IsAppInstalled(path, &arch);
Application app(hInst, lpCmdLine, nCmdShow);
app.setFont(L"Segoe UI");
if (NS_Utils::IsRtlLanguage(lcid))
app.setLayoutDirection(LayoutDirection::RightToLeft);
int scrWidth = GetSystemMetrics(SM_CXSCREEN);
int scrHeight = GetSystemMetrics(SM_CYSCREEN);
int x = (scrWidth - WINDOW_SIZE.width) / 2;
int y = (scrHeight - WINDOW_SIZE.height) / 2;
MainWindow w(nullptr, Rect(x, y, WINDOW_SIZE.width, WINDOW_SIZE.height));
w.onAboutToDestroy([&app]() {
app.exit(0);
});
if (!app_installed)
w.initInstallationMode();
else
w.initControlMode(arch);
w.showAll();
int exit_code = app.exec();
CloseHandle(hMutex);
return exit_code;
}

View File

@ -1,916 +0,0 @@
#include "mainwindow.h"
#include "application.h"
#include "utils.h"
#include "checkbox.h"
#include "button.h"
#include "label.h"
#include "boxlayout.h"
#include "radiobutton.h"
#include "progressbar.h"
#include "metrics.h"
#include "palette.h"
#include "caption.h"
#include "resource.h"
#include "translator.h"
#include "cdownloader.h"
#include "baseutils.h"
#include "cjson.h"
#include <Msi.h>
#include <ShlObj.h>
#include <Shlwapi.h>
#include <numeric>
#include "../../src/defines.h"
#include "../../src/prop/defines_p.h"
template <class T>
static void setSelectorStyle(T *sel) // style for CheckBox and RadioButton
{
sel->metrics()->setMetrics(Metrics::TextMarginLeft, 6);
sel->metrics()->setMetrics(Metrics::TextMarginRight, 6);
sel->metrics()->setMetrics(Metrics::PrimitiveRadius, 1);
sel->metrics()->setMetrics(Metrics::AlternatePrimitiveWidth, 2);
sel->palette()->setColor(Palette::Text, Palette::Disabled, 0x888888);
sel->palette()->setColor(Palette::Text, Palette::Normal, 0x333333);
sel->palette()->setColor(Palette::Text, Palette::Hover, 0x333333);
sel->palette()->setColor(Palette::Text, Palette::Pressed, 0x333333);
sel->palette()->setColor(Palette::Background, Palette::Disabled, 0xfefefe);
sel->palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
sel->palette()->setColor(Palette::Background, Palette::Hover, 0xfefefe);
sel->palette()->setColor(Palette::Background, Palette::Pressed, 0xfefefe);
sel->palette()->setColor(Palette::Primitive, Palette::Disabled, 0x888888);
sel->palette()->setColor(Palette::Primitive, Palette::Normal, 0x888888);
sel->palette()->setColor(Palette::Primitive, Palette::Hover, 0x0055ff);
sel->palette()->setColor(Palette::Primitive, Palette::Pressed, 0x0055ff);
}
static void setButtonStyle(Button *btn)
{
btn->palette()->setColor(Palette::Text, Palette::Disabled, 0x888888);
btn->palette()->setColor(Palette::Text, Palette::Normal, 0x333333);
btn->palette()->setColor(Palette::Text, Palette::Hover, 0x333333);
btn->palette()->setColor(Palette::Text, Palette::Pressed, 0x333333);
btn->palette()->setColor(Palette::Background, Palette::Disabled, 0xeeeeee);
btn->palette()->setColor(Palette::Background, Palette::Normal, 0xeeeeee);
btn->palette()->setColor(Palette::Background, Palette::Hover, 0xe0e0e0);
btn->palette()->setColor(Palette::Background, Palette::Pressed, 0xd0d0d0);
btn->palette()->setColor(Palette::Border, Palette::Disabled, 0xbebebe);
btn->palette()->setColor(Palette::Border, Palette::Normal, 0xbebebe);
btn->palette()->setColor(Palette::Border, Palette::Hover, 0xbebebe);
btn->palette()->setColor(Palette::Border, Palette::Pressed, 0xbebebe);
btn->metrics()->setMetrics(Metrics::BorderWidth, 1);
}
static void setProgressStyle(ProgressBar *bar)
{
bar->palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
bar->palette()->setColor(Palette::Base, Palette::Normal, 0xcccccc);
bar->palette()->setColor(Palette::AlternateBase, Palette::Normal, 0x1e7aaa);
}
static void setLabelStyle(Label *lb)
{
lb->palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
lb->palette()->setColor(Palette::Text, Palette::Normal, 0x888888);
}
static void setControlLabelStyle(Label *lb)
{
lb->resize(50, 36);
lb->palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
lb->palette()->setColor(Palette::Text, Palette::Normal, 0x333333);
lb->metrics()->setMetrics(Metrics::TextAlignment, Metrics::AlignHLeft | Metrics::AlignVTop);
}
MainWindow::MainWindow(Widget *parent, const Rect &rc) :
Window(parent, rc),
m_comntLbl(nullptr),
m_versionLbl(nullptr),
m_comntInfoLbl(nullptr),
m_bar(nullptr),
m_launchCheck(nullptr),
m_updRadio(nullptr),
// m_repRadio(nullptr),
m_uninsRadio(nullptr),
m_cancelBtn(nullptr),
m_mode(Mode::Install),
m_resize_conn(0),
m_checkState(UpdateRadio | LaunchCheck),
m_is_checked(false),
m_is_completed(false)
{
setWindowTitle(_TR(CAPTION));
setResizable(false);
setIcon(IDI_MAINICON);
palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
palette()->setColor(Palette::Border, Palette::Normal, 0x888888);
if (Utils::getWinVersion() > Utils::WinXP && Utils::getWinVersion() < Utils::Win10)
metrics()->setMetrics(Metrics::BorderWidth, 1);
Widget *cw = new Widget(this);
cw->palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
setCentralWidget(cw);
setContentsMargins(0,0,0,0);
BoxLayout *cenVlut = new BoxLayout(BoxLayout::Vertical);
cenVlut->setContentMargins(0, 0, 0, 0);
cenVlut->setSpacing(0);
cw->setLayout(cenVlut);
/* Caption section*/
Widget *topPanel = new Widget(cw);
topPanel->resize(50,28);
topPanel->palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
topPanel->setProperty(Widget::HSizeBehavior, Widget::Expanding);
topPanel->setProperty(Widget::VSizeBehavior, Widget::Fixed);
cenVlut->addWidget(topPanel);
BoxLayout *topHlut = new BoxLayout(BoxLayout::Horizontal);
topHlut->setContentMargins(0, 0, 0, 0);
topHlut->setSpacing(0);
topPanel->setLayout(topHlut);
Caption *cap = new Caption(topPanel);
cap->setResizingAvailable(false);
cap->palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
cap->metrics()->setMetrics(Metrics::TextMarginLeft, 12);
cap->metrics()->setMetrics(Metrics::TextAlignment, Metrics::AlignHLeft| Metrics::AlignVCenter);
cap->resize(50,28);
cap->setProperty(Widget::HSizeBehavior, Widget::Expanding);
cap->setProperty(Widget::VSizeBehavior, Widget::Fixed);
Button *closeBtn = new Button(topPanel);
closeBtn->resize(40,28);
closeBtn->setProperty(Widget::HSizeBehavior, Widget::Fixed);
closeBtn->setProperty(Widget::VSizeBehavior, Widget::Fixed);
closeBtn->palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
closeBtn->palette()->setColor(Palette::Background, Palette::Hover, 0xe81123);
closeBtn->palette()->setColor(Palette::Background, Palette::Pressed, 0x8b0a14);
closeBtn->palette()->setColor(Palette::Background, Palette::Disabled, 0x2b2b2b);
closeBtn->palette()->setColor(Palette::Primitive, Palette::Normal, 0x000000);
closeBtn->metrics()->setMetrics(Metrics::PrimitiveWidth, 1);
closeBtn->setStockIcon(Button::CloseIcon);
closeBtn->setIconSize(10, 10);
closeBtn->onClick([this]() {
close();
});
topHlut->addWidget(cap);
topHlut->addWidget(closeBtn);
/* Central section */
m_cenPanel = new Widget(cw);
m_cenPanel->palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
m_cenPanel->setProperty(Widget::HSizeBehavior, Widget::Expanding);
m_cenPanel->setProperty(Widget::VSizeBehavior, Widget::Expanding);
cenVlut->addWidget(m_cenPanel);
m_cenPanelVlut = new BoxLayout(BoxLayout::Vertical);
m_cenPanelVlut->setContentMargins(6, 12, 6, 48);
m_cenPanelVlut->setSpacing(6);
m_cenPanel->setLayout(m_cenPanelVlut);
}
MainWindow::~MainWindow()
{
if (m_future.valid())
m_future.wait();
}
void MainWindow::initInstallationMode()
{
m_is_checked = true;
m_mode = Mode::Install;
/* Image section*/
Label *wlcLbl = new Label(m_cenPanel);
wlcLbl->resize(282, 200);
wlcLbl->setEMFIcon(IDI_WELCOME, 282, 200);
wlcLbl->palette()->setColor(Palette::Background, Palette::Normal, 0xfefefe);
wlcLbl->setProperty(Widget::HSizeBehavior, Widget::Expanding);
wlcLbl->setProperty(Widget::VSizeBehavior, Widget::Fixed);
m_cenPanelVlut->addWidget(wlcLbl);
/* Check box section*/
CheckBox *chkBox = new CheckBox(m_cenPanel, _TR(CHECK_SILENT));
chkBox->setChecked(m_is_checked);
setSelectorStyle(chkBox);
chkBox->adjustSizeBasedOnContent();
int chkMargin = 2 + (chkBox->metrics()->value(Metrics::IconWidth) + chkBox->metrics()->value(Metrics::TextMarginLeft))/2;
chkBox->move(chkMargin + m_cenPanel->size().width/2 - chkBox->size().width/2, 254);
chkBox->onClick([chkBox, this]() {
m_is_checked = chkBox->isChecked();
});
/* Comment section */
wstring warn_text = _TR(LABEL_WARN_CLOSE);
NS_Utils::Replace(warn_text, L"%1", _T(WINDOW_NAME));
Label *comntLbl = new Label(m_cenPanel);
comntLbl->setText(warn_text, true);
comntLbl->setGeometry(0, m_cenPanel->size().height - 130, m_cenPanel->size().width, 48);
setLabelStyle(comntLbl);
/* Install button section */
Button *instlBtn = new Button(m_cenPanel);
instlBtn->setText(_TR(BUTTON_INSTALL));
instlBtn->setGeometry(m_cenPanel->size().width/2 - 50, m_cenPanel->size().height - 76, 100, 28);
setButtonStyle(instlBtn);
instlBtn->onClick([=]() {
m_cenPanel->disconnect(m_resize_conn);
chkBox->close();
comntLbl->close();
instlBtn->close();
startInstall();
});
m_resize_conn = m_cenPanel->onResize([chkBox, comntLbl, instlBtn, chkMargin](int w, int h) {
chkBox->move(chkMargin + w/2 - chkBox->size().width/2, 254);
comntLbl->setGeometry(0, h - 130, w, 48);
instlBtn->setGeometry(w/2 - 50, h - 76, 100, 28);
});
}
void MainWindow::initControlMode(const std::wstring &_arch)
{
m_mode = Mode::Control;
/* Comment section */
m_versionLbl = new Label(m_cenPanel);
setControlLabelStyle(m_versionLbl);
m_versionLbl->setText(fillInstalledVerInfo());
m_versionLbl->setProperty(Widget::HSizeBehavior, Widget::Expanding);
m_versionLbl->setProperty(Widget::VSizeBehavior, Widget::Fixed);
m_versionLbl->metrics()->setMetrics(Metrics::TextMarginLeft, 12);
m_cenPanelVlut->setContentMargins(18, 6, 6, 6);
m_cenPanelVlut->addWidget(m_versionLbl);
if (m_package == _TR(LABEL_UNKN_PACK) || m_ver == _TR(LABEL_UNKN_VER) || _arch.empty() || m_arch != _arch) {
Label *errLbl = new Label(m_cenPanel);
setControlLabelStyle(errLbl);
errLbl->setText(_TR(LABEL_NO_OPTIONS));
errLbl->setProperty(Widget::HSizeBehavior, Widget::Expanding);
errLbl->setProperty(Widget::VSizeBehavior, Widget::Expanding);
errLbl->metrics()->setMetrics(Metrics::TextMarginLeft, 24);
m_cenPanelVlut->addWidget(errLbl);
return;
}
createSelectionPage();
}
bool MainWindow::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
case WM_INVOKEMETHOD: {
if (std::function<void()> *func = (std::function<void()>*)wParam) {
if (*func)
(*func)();
delete func;
}
break;
}
}
return Window::event(msg, wParam, lParam, result);
}
void MainWindow::startInstall()
{
/* Comment section */
m_comntLbl = new Label(m_cenPanel);
m_comntLbl->setText(_TR(LABEL_DOWNLOAD), true);
m_comntLbl->setGeometry(0, m_cenPanel->size().height - 156, m_cenPanel->size().width, 24);
m_comntLbl->metrics()->setMetrics(Metrics::FontHeight, 20);
setLabelStyle(m_comntLbl);
m_comntInfoLbl = new Label(m_cenPanel);
m_comntInfoLbl->setText(_TR(LABEL_ALMOST_DONE), true);
m_comntInfoLbl->setGeometry(0, m_cenPanel->size().height - 112, m_cenPanel->size().width, 40);
setLabelStyle(m_comntInfoLbl);
/* Progress section */
m_bar = new ProgressBar(m_cenPanel);
m_bar->setGeometry(0, m_cenPanel->size().height - 126, m_cenPanel->size().width, 5);
setProgressStyle(m_bar);
m_bar->metrics()->setMetrics(Metrics::IconMarginLeft, 108);
m_bar->metrics()->setMetrics(Metrics::IconMarginRight, 108);
m_resize_conn = m_cenPanel->onResize([this](int w, int h) {
m_comntLbl->setGeometry(0, h - 156, w, 24);
m_comntInfoLbl->setGeometry(0, h - 112, w, 40);
m_bar->setGeometry(0, m_cenPanel->size().height - 126, m_cenPanel->size().width, 5);
});
m_comntLbl->show();
m_comntInfoLbl->show();
m_bar->show();
wstring path = NS_File::generateTmpFileName(L".exe");
startDownload(L"iss", NS_Utils::IsWin64() ? _T("x64") : _T("x86"), path, [=]() {
wstring args;
if (m_is_checked) {
args = _T("/VERYSILENT");
m_comntLbl->setText(_TR(LABEL_INSTALL), true);
m_bar->pulse(true);
} else {
hide();
}
DWORD status = NS_File::runProcess(path, args);
if (status != 0) {
if (!m_is_checked)
show();
m_bar->pulse(false);
m_bar->setProgress(0);
m_comntInfoLbl->setText((status & ERROR_LAUNCH) ? _TR(LABEL_ERR_RUNNING) : _TR(LABEL_ERR_COMMON) + wstring(L" ") + std::to_wstring(status), true);
} else {
if (m_is_checked) {
wstring app_path;
if (NS_Utils::IsAppInstalled(app_path)) {
m_cenPanel->disconnect(m_resize_conn);
m_comntLbl->close();
m_comntInfoLbl->close();
m_bar->close();
invokeMethod(&MainWindow::finishInstall, this, app_path);
} else {
m_bar->pulse(false);
m_bar->setProgress(0);
m_comntLbl->setText(_TR(LABEL_ERR_INSTALL), true);
}
} else {
close();
}
}
});
}
void MainWindow::finishInstall(const std::wstring &app_path)
{
/* Check box section*/
m_is_checked = true;
CheckBox *chkBox = new CheckBox(m_cenPanel, _TR(CHECK_LAUNCH));
chkBox->setChecked(m_is_checked);
setSelectorStyle(chkBox);
chkBox->adjustSizeBasedOnContent();
int chkMargin = 2 + (chkBox->metrics()->value(Metrics::IconWidth) + chkBox->metrics()->value(Metrics::TextMarginLeft))/2;
chkBox->move(chkMargin + m_cenPanel->size().width/2 - chkBox->size().width/2, 254);
chkBox->onClick([chkBox, this]() {
m_is_checked = chkBox->isChecked();
});
/* Comment section */
wstring compl_text = _TR(LABEL_INSTALL_COMPL);
NS_Utils::Replace(compl_text, L"%1", _T(WINDOW_NAME));
Label *comntLbl = new Label(m_cenPanel);
comntLbl->setText(compl_text, true);
comntLbl->setGeometry(0, m_cenPanel->size().height - 130, m_cenPanel->size().width, 48);
setLabelStyle(comntLbl);
/* Install button section */
Button *closeBtn = new Button(m_cenPanel);
closeBtn->setText(_TR(BUTTON_CLOSE));
closeBtn->setGeometry(m_cenPanel->size().width/2 - 50, m_cenPanel->size().height - 76, 100, 28);
setButtonStyle(closeBtn);
closeBtn->onClick([=]() {
if (m_is_checked)
NS_File::runProcess(L"explorer.exe", app_path + _T(APP_LAUNCH_NAME), false);
close();
});
m_resize_conn = m_cenPanel->onResize([chkBox, comntLbl, closeBtn, chkMargin](int w, int h) {
chkBox->move(chkMargin + w/2 - chkBox->size().width/2, 254);
comntLbl->setGeometry(0, h - 130, w, 48);
closeBtn->setGeometry(w/2 - 50, h - 76, 100, 28);
});
chkBox->show();
comntLbl->show();
closeBtn->show();
}
void MainWindow::startUpdate()
{
wstring tmp_path;
if (m_package == L"msi") {
wstring prodCode = NS_Utils::MsiProductCode(_T(REG_UNINST_KEY));
if (prodCode.empty())
prodCode = NS_Utils::MsiProductCode(_T(REG_GROUP_KEY));
if (prodCode.empty()) {
m_comntInfoLbl->setText(_TR(LABEL_ERR_PROD_CODE), true);
createCloseAndBackButtons();
return;
}
wstring packageName = NS_Utils::MsiGetProperty(prodCode.c_str(), INSTALLPROPERTY_PACKAGENAME);
if (packageName.empty()) {
m_comntInfoLbl->setText(_TR(LABEL_ERR_PACK_NAME), true);
createCloseAndBackButtons();
return;
}
tmp_path = NS_File::toNativeSeparators(NS_File::tempPath() + _T("/") + packageName);
} else {
tmp_path = NS_File::toNativeSeparators(NS_File::generateTmpFileName(L"." + m_package));
}
CDownloader *dnl = startDownload(m_package == L"msi" ? L"msi" : L"iss", m_arch, tmp_path, [=]() {
if (!NS_Utils::checkAndWaitForAppClosure(nativeWindowHandle())) {
m_bar->setProgress(0);
m_comntInfoLbl->setText(_TR(LABEL_ERR_CANCELLED), true);
return;
}
m_bar->pulse(true);
m_comntLbl->setText(_TR(LABEL_UPDATING));
wstring args = L"/c call \"" + tmp_path;
args += (m_package == L"msi") ? L"\" /qn /norestart" : L"\" /UPDATE /VERYSILENT /NOLAUNCH";
DWORD status = NS_File::runProcess(L"cmd", args, true);
if (status != 0) {
m_bar->pulse(false);
m_bar->setProgress(0);
m_comntInfoLbl->setText((status & ERROR_LAUNCH) ? _TR(LABEL_ERR_RUNNING) : _TR(LABEL_ERR_COMMON) + wstring(L" ") + std::to_wstring(status), true);
} else {
if (m_checkState & ClrDataCheck) {
wstring dataPath = NS_File::appDataPath();
if (!dataPath.empty())
NS_File::removeDirRecursively(dataPath);
}
if (m_checkState & ClrStnCheck) {
wstring key(L"SOFTWARE\\");
key.append(_T(REG_GROUP_KEY));
SHDeleteKey(HKEY_CURRENT_USER, key.c_str());
}
m_bar->pulse(false);
m_bar->setProgress(100);
m_comntLbl->setText(_TR(LABEL_UPDATE_COMPL));
m_versionLbl->setText(fillInstalledVerInfo());
m_is_completed = true;
}
});
m_cancelBtn->onClick([=]() {
dnl->stop();
});
}
// void MainWindow::startRepair()
// {
// wstring tmp_path;
// if (m_package == L"msi") {
// wstring prodCode = NS_Utils::MsiProductCode(_T(REG_UNINST_KEY));
// if (prodCode.empty())
// prodCode = NS_Utils::MsiProductCode(_T(REG_GROUP_KEY));
// if (prodCode.empty()) {
// m_comntInfoLbl->setText(_TR(LABEL_ERR_PROD_CODE), true);
// createCloseAndBackButtons();
// return;
// }
// wstring packageName = NS_Utils::MsiGetProperty(prodCode.c_str(), INSTALLPROPERTY_PACKAGENAME);
// if (packageName.empty()) {
// m_comntInfoLbl->setText(_TR(LABEL_ERR_PACK_NAME), true);
// createCloseAndBackButtons();
// return;
// }
// tmp_path = NS_File::toNativeSeparators(NS_File::tempPath() + _T("/") + packageName);
// } else {
// tmp_path = NS_File::toNativeSeparators(NS_File::generateTmpFileName(L"." + m_package));
// }
// wstring url = L"https://github.com/%1/%2/releases/download/%3/%4";
// {
// wstring url_filename = L"DesktopEditors_" + m_arch;
// url_filename.append(L"." + m_package);
// wstring url_ver = L"v" + m_ver;
// size_t pos = url_ver.find_last_of(L'.');
// if (pos != std::wstring::npos)
// url_ver = url_ver.substr(0, pos);
// NS_Utils::Replace(url, L"%1", _T(REG_GROUP_KEY));
// NS_Utils::Replace(url, L"%2", _T(APP_NAME));
// NS_Utils::Replace(url, L"%3", url_ver);
// NS_Utils::Replace(url, L"%4", url_filename);
// }
// CDownloader *dnl = startDownload(m_package == L"msi" ? L"msi" : L"iss", m_arch, tmp_path, [=]() {
// if (!NS_Utils::checkAndWaitForAppClosure(nativeWindowHandle())) {
// m_bar->setProgress(0);
// m_comntInfoLbl->setText(_TR(LABEL_ERR_CANCELLED), true);
// return;
// }
// m_bar->pulse(true);
// wstring cmd = (m_package == L"msi") ? L"msiexec" : L"cmd",
// args = (m_package == L"msi") ? L"/fvamus \"" : L"/c \"";
// args += tmp_path;
// args += (m_package == L"msi") ? L"\" /qn" : L" /VERYSILENT\"";
// DWORD status = NS_File::runProcess(cmd, args, true);
// if (status != 0) {
// m_bar->pulse(false);
// m_bar->setProgress(0);
// m_comntInfoLbl->setText((status & ERROR_LAUNCH) ? _TR(LABEL_ERR_RUNNING) : _TR(LABEL_ERR_COMMON) + wstring(L" ") + std::to_wstring(status), true);
// } else {
// if (m_checkState & ClrDataCheck) {
// wstring dataPath = NS_File::appDataPath();
// if (!dataPath.empty())
// NS_File::removeDirRecursively(dataPath);
// }
// if (m_checkState & ClrStnCheck) {
// wstring key(L"SOFTWARE\\");
// key.append(_T(REG_GROUP_KEY));
// SHDeleteKey(HKEY_CURRENT_USER, key.c_str());
// }
// m_bar->pulse(false);
// m_bar->setProgress(100);
// m_comntLbl->setText(_TR(LABEL_REPAIR_COMPL));
// m_is_completed = true;
// }
// });
// m_cancelBtn->onClick([=]() {
// dnl->stop();
// });
// }
void MainWindow::startUninstall()
{
m_cancelBtn->setDisabled(true);
if (!NS_Utils::checkAndWaitForAppClosure(nativeWindowHandle())) {
m_bar->setProgress(0);
m_comntInfoLbl->setText(_TR(LABEL_ERR_CANCELLED), true);
createCloseAndBackButtons();
return;
}
m_bar->pulse(true);
wstring args = L"/c \"" + m_uninst_cmd;
args += (m_package == L"msi") ? L" /qn\"" : L" /VERYSILENT\"";
m_future = std::async(std::launch::async, [=]() {
DWORD status = NS_File::runProcess(L"cmd", args, true);
if (status != 0) {
m_bar->pulse(false);
m_bar->setProgress(0);
m_comntInfoLbl->setText(_TR(LABEL_ERR_UNINST));
createCloseAndBackButtons();
} else {
if (m_checkState & ClrAllCheck) {
wstring dataPath = NS_File::appDataPath();
if (!dataPath.empty())
NS_File::removeDirRecursively(dataPath);
wstring key(L"SOFTWARE\\");
key.append(_T(REG_GROUP_KEY));
SHDeleteKey(HKEY_CURRENT_USER, key.c_str());
}
m_bar->pulse(false);
m_bar->setProgress(100);
m_comntLbl->setText(_TR(LABEL_UNINST_COMPL));
// m_is_completed = true;
createCloseButton();
}
});
}
void MainWindow::createSelectionPage()
{
m_is_completed = false;
/* Check box section*/
CheckBox *clrChkBox = new CheckBox(m_cenPanel, _TR(CHECK_CLR_DATA));
clrChkBox->setDisabled(!(m_checkState & UpdateRadio));
clrChkBox->setChecked(m_checkState & ClrDataCheck);
setSelectorStyle(clrChkBox);
clrChkBox->adjustSizeBasedOnContent();
clrChkBox->move(79, 80);
clrChkBox->onClick([=]() {
m_checkState = (m_checkState & ~ClrDataCheck) | (clrChkBox->isChecked() * ClrDataCheck);
});
CheckBox *stnChkBox = new CheckBox(m_cenPanel, _TR(CHECK_CLR_STNGS));
stnChkBox->setDisabled(!(m_checkState & UpdateRadio));
stnChkBox->setChecked(m_checkState & ClrStnCheck);
setSelectorStyle(stnChkBox);
stnChkBox->adjustSizeBasedOnContent();
stnChkBox->move(79, 112);
stnChkBox->onClick([stnChkBox, this]() {
m_checkState = (m_checkState & ~ClrStnCheck) | (stnChkBox->isChecked() * ClrStnCheck);
});
CheckBox *clrAllChkBox = new CheckBox(m_cenPanel, _TR(CHECK_CLR_ALL));
clrAllChkBox->setDisabled(!(m_checkState & UninstRadio));
clrAllChkBox->setChecked(m_checkState & ClrAllCheck);
setSelectorStyle(clrAllChkBox);
clrAllChkBox->adjustSizeBasedOnContent();
clrAllChkBox->move(79, 182);
clrAllChkBox->onClick([clrAllChkBox, this]() {
m_checkState = (m_checkState & ~ClrAllCheck) | (clrAllChkBox->isChecked() * ClrAllCheck);
});
/* Update radio button section*/
m_updRadio = new RadioButton(m_cenPanel, _TR(RADIO_UPDATE));
m_updRadio->setChecked(m_checkState & UpdateRadio);
setSelectorStyle(m_updRadio);
m_updRadio->adjustSizeBasedOnContent();
m_updRadio->move(50, 48);
m_updRadio->onClick([=]() {
clrChkBox->setDisabled(false);
stnChkBox->setDisabled(false);
clrAllChkBox->setDisabled(true);
// if (m_repRadio->isChecked())
// m_repRadio->setChecked(false);
if (m_uninsRadio->isChecked())
m_uninsRadio->setChecked(false);
m_checkState = (m_checkState | UpdateRadio) & ~(RepairRadio | UninstRadio);
});
/* Repair radio button section*/
// m_repRadio = new RadioButton(m_cenPanel, _TR(RADIO_REPAIR));
// m_repRadio->setChecked(m_checkState & RepairRadio);
// setSelectorStyle(m_repRadio);
// m_repRadio->adjustSizeBasedOnContent();
// m_repRadio->move(50, 82);
// m_repRadio->onClick([=]() {
// clrChkBox->setDisabled(false);
// stnChkBox->setDisabled(false);
// clrAllChkBox->setDisabled(true);
// if (m_updRadio->isChecked())
// m_updRadio->setChecked(false);
// if (m_uninsRadio->isChecked())
// m_uninsRadio->setChecked(false);
// m_checkState = (m_checkState | RepairRadio) & ~(UninstRadio | UpdateRadio);
// });
/* Uninstall radio button section*/
m_uninsRadio = new RadioButton(m_cenPanel, _TR(RADIO_UNINST));
m_uninsRadio->setChecked(m_checkState & UninstRadio);
setSelectorStyle(m_uninsRadio);
m_uninsRadio->adjustSizeBasedOnContent();
m_uninsRadio->move(50, 150);
m_uninsRadio->onClick([=]() {
clrChkBox->setDisabled(true);
stnChkBox->setDisabled(true);
clrAllChkBox->setDisabled(false);
// if (m_repRadio->isChecked())
// m_repRadio->setChecked(false);
if (m_updRadio->isChecked())
m_updRadio->setChecked(false);
m_checkState = (m_checkState | UninstRadio) & ~(UpdateRadio | RepairRadio);
});
/* Apply button section */
Button *applyBtn = new Button(m_cenPanel);
applyBtn->setText(_TR(BUTTON_APPLY));
applyBtn->setGeometry(m_cenPanel->size().width - 100 - 12, m_cenPanel->size().height - 28 - 12, 100, 28);
setButtonStyle(applyBtn);
applyBtn->onClick([=]() {
wstring msg = m_uninsRadio->isChecked() ? _TR(MSG_REMOVE) : /*m_repRadio->isChecked() ? _TR(MSG_REPAIR) :*/ _TR(MSG_UPDATE);
NS_Utils::Replace(msg, L"%1", _T(WINDOW_NAME));
if (IDOK == NS_Utils::ShowTaskDialog(nativeWindowHandle(), msg.c_str(), TD_WARNING_ICON)) {
if (!NS_Utils::checkAndWaitForAppClosure(nativeWindowHandle()))
return;
m_cenPanel->disconnect(m_resize_conn);
m_updRadio->close();
// m_repRadio->close();
clrChkBox->close();
stnChkBox->close();
m_uninsRadio->close();
clrAllChkBox->close();
applyBtn->close();
msg = m_uninsRadio->isChecked() ? _TR(LABEL_UNINSTLING) : /*m_repRadio->isChecked() ? _TR(LABEL_REPAIRING) :*/ _TR(LABEL_DOWNLOAD);
createProgressPage(msg);
if (m_updRadio->isChecked() /*|| m_repRadio->isChecked()*/) {
/* Check box section*/
m_launchCheck = new CheckBox(m_cenPanel, _TR(CHECK_LAUNCH));
m_launchCheck->setChecked(m_checkState & LaunchCheck);
setSelectorStyle(m_launchCheck);
m_launchCheck->adjustSizeBasedOnContent();
m_launchCheck->move(42, 100);
m_launchCheck->onClick([this]() {
m_checkState = (m_checkState & ~LaunchCheck) | (m_launchCheck->isChecked() * LaunchCheck);
});
}
if (m_uninsRadio->isChecked())
startUninstall();
else
// if (m_repRadio->isChecked())
// startRepair();
// else
startUpdate();
}
});
m_resize_conn = m_cenPanel->onResize([applyBtn](int w, int h) {
applyBtn->setGeometry(w - 100 - 12, h - 28 - 12, 100, 28);
});
m_updRadio->show();
// m_repRadio->show();
clrChkBox->show();
stnChkBox->show();
m_uninsRadio->show();
clrAllChkBox->show();
applyBtn->show();
}
void MainWindow::createProgressPage(const std::wstring &text)
{
m_comntLbl = new Label(m_cenPanel);
setControlLabelStyle(m_comntLbl);
m_comntLbl->setText(text);
m_comntLbl->metrics()->setMetrics(Metrics::TextMarginLeft, 12);
m_comntLbl->setGeometry(30, 50, size().width - 30, 24);
m_comntInfoLbl = new Label(m_cenPanel);
setControlLabelStyle(m_comntInfoLbl);
m_comntInfoLbl->metrics()->setMetrics(Metrics::TextMarginLeft, 12);
m_comntInfoLbl->setGeometry(30, 92, m_cenPanel->size().width - 30, 40);
/* Progress section */
m_bar = new ProgressBar(m_cenPanel);
m_bar->setGeometry(42, 80, 250, 5);
setProgressStyle(m_bar);
m_cancelBtn = new Button(m_cenPanel);
m_cancelBtn->setText(_TR(BUTTON_CANCEL));
m_cancelBtn->setGeometry(m_cenPanel->size().width - 100 - 12, m_cenPanel->size().height - 28 - 12, 100, 28);
setButtonStyle(m_cancelBtn);
m_resize_conn = m_cenPanel->onResize([this](int w, int h) {
m_cancelBtn->setGeometry(w - 100 - 12, h - 28 - 12, 100, 28);
});
m_comntLbl->show();
m_comntInfoLbl->show();
m_bar->show();
m_cancelBtn->show();
}
void MainWindow::createCloseButton()
{
invokeMethod([=]() {
m_cenPanel->disconnect(m_resize_conn);
m_cancelBtn->close();
Button *closeBtn = new Button(m_cenPanel);
closeBtn->setText(_TR(BUTTON_CLOSE));
closeBtn->setGeometry(m_cenPanel->size().width - 100 - 12, m_cenPanel->size().height - 28 - 12, 100, 28);
setButtonStyle(closeBtn);
closeBtn->onClick([=]() {
m_cenPanel->disconnect(m_resize_conn);
close();
});
m_resize_conn = m_cenPanel->onResize([closeBtn](int w, int h) {
closeBtn->setGeometry(w - 100 - 12, h - 28 - 12, 100, 28);
});
closeBtn->show();
});
}
void MainWindow::createCloseAndBackButtons()
{
invokeMethod([=]() {
m_cenPanel->disconnect(m_resize_conn);
m_cancelBtn->close();
if (m_launchCheck) {
if (m_is_completed) {
m_comntInfoLbl->hide();
m_launchCheck->show();
} else {
m_launchCheck->close();
m_launchCheck = nullptr;
}
}
Button *closeBtn = new Button(m_cenPanel);
closeBtn->setText(_TR(BUTTON_CLOSE));
closeBtn->setGeometry(m_cenPanel->size().width - 100 - 12, m_cenPanel->size().height - 28 - 12, 100, 28);
setButtonStyle(closeBtn);
closeBtn->onClick([=]() {
m_cenPanel->disconnect(m_resize_conn);
if (m_launchCheck && m_is_completed && (m_checkState & LaunchCheck)) {
wstring app_path;
if (NS_Utils::IsAppInstalled(app_path))
NS_File::runProcess(L"explorer.exe", app_path + _T(APP_LAUNCH_NAME), false);
}
close();
});
Button *backBtn = new Button(m_cenPanel);
backBtn->setText(_TR(BUTTON_BACK));
backBtn->setGeometry(m_cenPanel->size().width - 100 - 12 - 106, m_cenPanel->size().height - 28 - 12, 100, 28);
setButtonStyle(backBtn);
backBtn->onClick([=]() {
m_cenPanel->disconnect(m_resize_conn);
if (m_launchCheck) {
m_launchCheck->close();
m_launchCheck = nullptr;
}
m_comntLbl->close();
m_comntInfoLbl->close();
m_bar->close();
closeBtn->close();
backBtn->close();
createSelectionPage();
});
m_resize_conn = m_cenPanel->onResize([closeBtn, backBtn](int w, int h) {
closeBtn->setGeometry(w - 100 - 12, h - 28 - 12, 100, 28);
backBtn->setGeometry(w - 100 - 12 - 106, h - 28 - 12, 100, 28);
});
closeBtn->show();
backBtn->show();
});
}
wstring MainWindow::fillInstalledVerInfo()
{
wstring text = _TR(LABEL_VERSION);
NS_Utils::InstalledVerInfo(L"DisplayVersion", m_ver, m_arch);
if (m_ver.empty())
m_ver = _TR(LABEL_UNKN_VER);
NS_Utils::InstalledVerInfo(L"UninstallString", m_uninst_cmd, m_arch);
m_package = (m_uninst_cmd.find(L"msiexec") != std::wstring::npos) ? L"msi" : (m_uninst_cmd.find(L".exe") != std::wstring::npos) ? L"exe" : _TR(LABEL_UNKN_PACK);
NS_Utils::Replace(text, L"%1", _T(WINDOW_NAME));
NS_Utils::Replace(text, L"%2", m_ver);
NS_Utils::Replace(text, L"%3", m_arch);
NS_Utils::Replace(text, L"%4", m_package);
return text;
}
CDownloader* MainWindow::startDownload(const std::wstring &install_type, const std::wstring &arch, const std::wstring &path, const std::function<void()> &onComplete)
{
wstring appcast_url = NS_Utils::cmdArgContains(_T("--appcast-dev-channel")) ? _T(URL_INSTALL_DEV) : _T(URL_INSTALL);
wstring tmp_path = NS_File::toNativeSeparators(NS_File::generateTmpFileName(L".json"));
NS_Logger::WriteLog(_T("\nAppcast URL:\n") + appcast_url);
CDownloader *dnl = new CDownloader();
dnl->onComplete([=](ulong error) {
if (error == ERROR_SUCCESS) {
list<tstring> lst;
if (NS_File::readFile(tmp_path, lst)) {
tstring json = std::accumulate(lst.begin(), lst.end(), tstring());
JsonDocument doc(json);
JsonObject root = doc.object();
// tstring version = root.value(_T("version")).toTString();
JsonObject package = root.value(_T("package")).toObject();
#ifdef _WIN32
JsonObject win = package.value(arch == _T("x64") ? _T("win_64") : _T("win_32")).toObject();
#else
JsonObject win = package.value(_T("linux_64")).toObject();
#endif
JsonObject package_type = win.value(install_type).toObject();
tstring url = package_type.value(_T("url")).toTString();
tstring url2 = package_type.value(_T("url2")).toTString();
NS_Logger::WriteLog(_T("\nPrimary package URL:\n") + url + _T("\nSecondary package URL:\n") + url2);
if ((url.empty() || !dnl->isUrlAccessible(url)) && !url2.empty())
url = url2;
NS_Logger::WriteLog(_T("\nDownload from URL:\n") + url);
// tstring hash = package_type.value(_T("md5")).toTString();
// std::transform(hash.begin(), hash.end(), hash.begin(), ::tolower);
NS_File::removeFile(tmp_path);
invokeMethod([=]() {
dnl->stop();
dnl->onProgress([=](int percent) {
m_bar->setProgress(percent);
});
dnl->onComplete([=](ulong error) {
if (m_mode == Mode::Control)
m_cancelBtn->setDisabled(true);
if (error == ERROR_SUCCESS) {
if (NS_File::verifyEmbeddedSignature(path)) {
onComplete();
} else {
m_bar->setProgress(0);
m_comntInfoLbl->setText(_TR(LABEL_NO_VER_AVAIL), true);
}
if (NS_File::fileExists(path))
NS_File::removeFile(path);
} else
if (error == ERROR_CANCELLED) {
m_comntInfoLbl->setText(_TR(LABEL_ERR_CANCELLED), true);
} else {
m_comntInfoLbl->setText(NS_Utils::GetLastErrorAsString(error), true);
}
if (m_mode == Mode::Control)
createCloseAndBackButtons();
});
dnl->downloadFile(url, path);
});
} else {
NS_File::removeFile(tmp_path);
m_comntInfoLbl->setText(_TR(LABEL_ERR_COMMON), true);
if (m_mode == Mode::Control)
createCloseAndBackButtons();
}
} else
if (error == ERROR_CANCELLED) {
m_comntInfoLbl->setText(_TR(LABEL_ERR_CANCELLED), true);
if (m_mode == Mode::Control)
createCloseAndBackButtons();
} else {
m_comntInfoLbl->setText(NS_Utils::GetLastErrorAsString(error), true);
if (m_mode == Mode::Control)
createCloseAndBackButtons();
}
});
dnl->downloadFile(appcast_url, tmp_path);
onAboutToDestroy([=]() {
delete dnl;
});
return dnl;
}
template<typename Fn, typename... Args>
void MainWindow::invokeMethod(Fn&& fn, Args&&... args)
{
std::function<void()> *func = new std::function<void()>(std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...));
PostMessage(m_hWnd, WM_INVOKEMETHOD, (WPARAM)func, 0);
} // NOLINT

View File

@ -1,68 +0,0 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "window.h"
#include <future>
class Label;
class ProgressBar;
class Widget;
class BoxLayout;
class CheckBox;
class RadioButton;
class Button;
class CDownloader;
class MainWindow : public Window
{
public:
MainWindow(Widget *parent, const Rect &rc);
~MainWindow();
void initInstallationMode();
void initControlMode(const std::wstring &arch);
protected:
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*) override;
private:
void startInstall();
void finishInstall(const std::wstring &app_path);
void startUpdate();
// void startRepair();
void startUninstall();
void createSelectionPage();
void createProgressPage(const std::wstring &text);
void createCloseButton();
void createCloseAndBackButtons();
std::wstring fillInstalledVerInfo();
CDownloader* startDownload(const std::wstring &install_type, const std::wstring &arch, const std::wstring &path, const std::function<void()> &onComplete);
template<typename Fn, typename... Args>
void invokeMethod(Fn&& fn, Args&&... args);
enum class Mode : BYTE {Install, Control};
enum Selectors : BYTE {UpdateRadio = 1, RepairRadio = 2, UninstRadio = 4, ClrDataCheck = 8, ClrStnCheck = 16, ClrAllCheck = 32, LaunchCheck = 64};
std::future<void> m_future;
std::wstring m_uninst_cmd,
m_ver,
m_arch,
m_package;
Label *m_comntLbl,
*m_versionLbl,
*m_comntInfoLbl;
ProgressBar *m_bar;
Widget *m_cenPanel;
BoxLayout *m_cenPanelVlut;
CheckBox *m_launchCheck;
RadioButton *m_updRadio,
// *m_repRadio,
*m_uninsRadio;
Button *m_cancelBtn;
Mode m_mode;
int m_resize_conn;
BYTE m_checkState;
bool m_is_checked,
m_is_completed;
};
#endif // MAINWINDOW_H

View File

@ -1,53 +0,0 @@
#include "version.h"
#define IDI_MAINICON 101
#define IDI_WELCOME 102
#define IDT_TRANSLATIONS 10001
#define APP_LAUNCH_NAME "\\DesktopEditors.exe"
#define CAPTION
#define MSG_ERR_SYSTEM
#define MSG_ERR_ALREADY_RUNNING
#define MSG_ERR_TRY_CLOSE_APP
#define MSG_ERR_CLOSE_APP
#define MSG_REMOVE
#define MSG_REPAIR
#define MSG_UPDATE
#define LABEL_DOWNLOAD
#define LABEL_INSTALL
#define LABEL_UPDATING
#define LABEL_REPAIRING
#define LABEL_UNINSTLING
#define LABEL_UPDATE_COMPL
#define LABEL_REPAIR_COMPL
#define LABEL_UNINST_COMPL
#define LABEL_VERSION
#define LABEL_UNKN_VER
#define LABEL_UNKN_PACK
#define LABEL_NO_OPTIONS
#define LABEL_NO_VER_AVAIL
#define LABEL_WARN_CLOSE
#define LABEL_ALMOST_DONE
#define LABEL_INSTALL_COMPL
#define LABEL_ERR_PROD_CODE
#define LABEL_ERR_PACK_NAME
#define LABEL_ERR_INSTALL
#define LABEL_ERR_UNINST
#define LABEL_ERR_COMMON
#define LABEL_ERR_RUNNING
#define LABEL_ERR_CANCELLED
#define BUTTON_INSTALL
#define BUTTON_CANCEL
#define BUTTON_APPLY
#define BUTTON_CLOSE
#define BUTTON_BACK
#define RADIO_UPDATE
// #define RADIO_REPAIR
#define RADIO_UNINST
#define CHECK_SILENT
#define CHECK_LAUNCH
#define CHECK_CLR_DATA
#define CHECK_CLR_STNGS
#define CHECK_CLR_ALL

View File

@ -1,270 +0,0 @@
#define WIN32_LEAN_AND_MEAN
#include "translator.h"
#include "resource.h"
#include "utils.h"
#include <Windows.h>
#include <codecvt>
#include <cwctype>
#include <algorithm>
#include <sstream>
bool isSeparator(wchar_t c)
{
return c == L' ' || c == L'\t' || c == L'\r' || c == L'\n';
}
bool isValidStringIdCharacter(wchar_t c)
{
return std::iswalnum(c) || std::iswalpha(c) || c == L'_';
}
bool isValidLocaleCharacter(wchar_t c)
{
return iswalpha(c) || c == L'_';
}
wstring getPrimaryLang(const wstring &lang, bool withScript = false)
{
if (lang.empty()) {
NS_Logger::WriteLog(_T("An error occurred:\n") + wstring(_T(__FUNCTION__)));
return L"en";
}
std::wistringstream iss(lang);
wstring primlang, script;
std::getline(iss, primlang, L'_');
if (primlang.length() == 2 || primlang.length() == 3) {
if (!withScript)
return primlang;
std::getline(iss, script, L'_');
return (script.length() == 4) ? primlang + L"_" + script : primlang;
}
NS_Logger::WriteLog(_T("An error occurred:\n") + wstring(_T(__FUNCTION__)));
return L"en";
}
wstring StrToWStr(const string &str)
{
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
return converter.from_bytes(str);
}
TranslationsMap Translator::translMap = TranslationsMap();
wstring Translator::langName = _T("en_EN");
bool Translator::is_translations_valid = false;
Translator::Translator(unsigned long langId, int resourceId)
{
TCHAR _langName[LOCALE_NAME_MAX_LENGTH] = {0};
if (GetLocaleInfo(langId, LOCALE_SNAME, _langName, LOCALE_NAME_MAX_LENGTH) > 0) {
langName = _langName;
std::replace(langName.begin(), langName.end(), L'-', L'_');
} else
NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
NS_Logger::WriteLog(_T("\nCurrent locale:\n") + langName);
HMODULE hInst = GetModuleHandle(NULL);
if (HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(resourceId), RT_RCDATA)) {
if (HGLOBAL hResData = LoadResource(hInst, hRes)) {
if (LPVOID pData = LockResource(hResData)) {
DWORD dataSize = SizeofResource(hInst, hRes);
if (dataSize > 0) {
string text((const char*)pData, dataSize);
translations = StrToWStr(text);
} else
NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
} else
NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
FreeResource(hResData);
} else
NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
} else
NS_Logger::WriteLog(ADVANCED_ERROR_MESSAGE);
if (!translations.empty()) {
parseTranslations();
if (!is_translations_valid)
NS_Logger::WriteLog(_T("Cannot parse translations, error in string:\n") + error_substr + L" <---");
} else
NS_Logger::WriteLog(_T("Error: translations is empty."));
}
Translator::~Translator()
{
}
wstring Translator::tr(const char *str)
{
wstring translatedStr = StrToWStr(str);
if (is_translations_valid) {
for (auto &strIdPair : translMap) {
//LocaleMap locMap = strIdPair.second;
// for (LocaleMap::const_iterator it = strIdPair.second.begin(); it != strIdPair.second.end(); ++it) {
//wcout << L"\n\n" << translatedStr << L"\n" << it->second;
if (strIdPair.first == translatedStr) {
if (strIdPair.second.find(langName) != strIdPair.second.end())
return strIdPair.second[langName];
else {
wstring primaryLangAndScript = getPrimaryLang(langName, true);
if (strIdPair.second.find(primaryLangAndScript) != strIdPair.second.end())
return strIdPair.second[primaryLangAndScript];
else {
wstring primaryLang = getPrimaryLang(langName);
if (strIdPair.second.find(primaryLang) != strIdPair.second.end())
return strIdPair.second[primaryLang];
}
}
if (strIdPair.second.find(L"en") != strIdPair.second.end())
return strIdPair.second[L"en"];
break;
}
// }
}
}
return translatedStr;
}
void Translator::parseTranslations()
{
int token = TOKEN_BEGIN_DOCUMENT;
wstring stringId, currentLocale;
size_t pos = 0, len = translations.length();
while (pos < len) {
size_t incr = 1;
wchar_t ch = translations.at(pos);
switch (token) {
case TOKEN_BEGIN_DOCUMENT:
case TOKEN_END_VALUE:
if (!isSeparator(ch)) {
if (ch == L';') {
// string is comment
size_t end = translations.find_first_of(L'\n', pos);
incr = (end == wstring::npos) ? len - pos : end - pos + 1;
} else {
size_t end;
for (end = pos; end < len; end++) {
wchar_t c = translations.at(end);
if (!isValidLocaleCharacter(c))
break;
}
size_t locale_len = end - pos;
if (locale_len < 12 && locale_len != 0 && locale_len != 1 && locale_len != 4 && locale_len != 9) {
token = TOKEN_BEGIN_LOCALE;
continue;
} else {
// TOKEN_ERROR
error_substr = translations.substr(0, pos + 1);
return;
}
}
}
break;
case TOKEN_BEGIN_STRING_ID:
if (!isSeparator(ch)) {
size_t end;
wchar_t c;
for (end = pos; end < len; end++) {
c = translations.at(end);
if (!isValidStringIdCharacter(c))
break;
}
c = translations.at(end);
if (end < len && !isSeparator(c) && c != L'=') {
// TOKEN_ERROR
error_substr = translations.substr(0, end + 1);
return;
}
stringId = translations.substr(pos, end - pos);
if (!stringId.empty() && translMap.find(stringId) == translMap.end())
translMap[stringId] = LocaleMap();
token = TOKEN_END_STRING_ID;
incr = end - pos;
}
break;
case TOKEN_END_STRING_ID:
if (!isSeparator(ch)) {
if (ch == L'=') {
token = TOKEN_BEGIN_VALUE;
} else {
// TOKEN_ERROR
error_substr = translations.substr(0, pos + 1);
return;
}
}
break;
case TOKEN_BEGIN_LOCALE: {
size_t end;
for (end = pos; end < len; end++) {
wchar_t c = translations.at(end);
if (!isValidLocaleCharacter(c))
break;
}
size_t locale_len = end - pos;
currentLocale = translations.substr(pos, locale_len);
if (pos + locale_len == len) {
error_substr = translations.substr(0, pos + locale_len);
return;
}
token = TOKEN_END_LOCALE;
incr = locale_len;
break;
}
case TOKEN_END_LOCALE:
if (!isSeparator(ch)) {
if (ch == L'.') {
token = TOKEN_BEGIN_STRING_ID;
} else {
// TOKEN_ERROR
error_substr = translations.substr(0, pos + 1);
return;
}
}
break;
case TOKEN_BEGIN_VALUE: {
size_t end = translations.find_first_of(L'\n', pos);
wstring val;
if (end == wstring::npos) {
val = translations.substr(pos);
incr = len - pos;
} else {
val = translations.substr(pos, end - pos);
incr = end - pos;
}
if (!val.empty() && val.back() == L'\r')
val.pop_back();
size_t p = val.find(L"\\n");
while (p != std::string::npos) {
val.replace(p, 2, L"\\");
val[p] = L'\n';
p = val.find(L"\\n", p + 1);
}
if (!currentLocale.empty() && translMap.find(stringId) != translMap.end())
translMap[stringId][currentLocale] = val;
token = TOKEN_END_VALUE;
break;
}
default:
break;
}
pos += incr;
if (pos == len)
token = TOKEN_END_DOCUMENT;
}
if (token == TOKEN_END_DOCUMENT)
is_translations_valid = true;
}

View File

@ -1,46 +0,0 @@
#ifndef TRANSLATOR_H
#define TRANSLATOR_H
#include <unordered_map>
#include <string>
#include <tchar.h>
#define _TR(str) Translator::tr(#str).c_str()
using std::wstring;
using std::unordered_map;
typedef unordered_map<wstring, wstring> LocaleMap;
typedef unordered_map<wstring, LocaleMap> TranslationsMap;
class Translator
{
public:
Translator(unsigned long langId, int resourceId);
~Translator();
static wstring tr(const char*);
private:
void parseTranslations();
static TranslationsMap translMap;
wstring translations,
error_substr;
static wstring langName;
static bool is_translations_valid;
enum TokenType : unsigned char {
TOKEN_BEGIN_DOCUMENT = 0,
TOKEN_END_DOCUMENT,
TOKEN_BEGIN_STRING_ID,
TOKEN_END_STRING_ID,
TOKEN_BEGIN_LOCALE,
TOKEN_END_LOCALE,
TOKEN_BEGIN_VALUE,
TOKEN_END_VALUE
};
};
#endif // TRANSLATOR_H

View File

@ -1,103 +0,0 @@
#include "abstractbutton.h"
#include "palette.h"
#include "metrics.h"
#include <gdiplus.h>
AbstractButton::AbstractButton(Widget *parent, const std::wstring &text) :
Widget(parent, ObjectType::WidgetType),
m_text(text)
{
}
AbstractButton::~AbstractButton()
{
}
void AbstractButton::setText(const std::wstring &text)
{
m_text = text;
update();
}
void AbstractButton::adjustSizeBasedOnContent()
{
HDC hdc = GetDC(nativeWindowHandle());
Gdiplus::Graphics gr(hdc);
LOGFONTW logFont = {0};
GetObject(m_hFont, sizeof(LOGFONTW), &logFont);
Gdiplus::Font font(hdc, &logFont);
Gdiplus::RectF lutRc, boxRc;
gr.MeasureString(m_text.c_str(), m_text.length(), &font, lutRc, &boxRc);
ReleaseDC(nativeWindowHandle(), hdc);
int w = boxRc.Width + 2*metrics()->value(Metrics::IconWidth) + metrics()->value(Metrics::TextMarginLeft) + metrics()->value(Metrics::TextMarginRight);
int h = max(boxRc.Height + metrics()->value(Metrics::TextMarginTop) + metrics()->value(Metrics::TextMarginBottom), metrics()->value(Metrics::IconHeight));
resize(w, h);
}
int AbstractButton::onClick(const FnVoidVoid &callback)
{
m_click_callbacks[++m_connectionId] = callback;
return m_connectionId;
}
void AbstractButton::disconnect(int connectionId)
{
auto it = m_click_callbacks.find(connectionId);
if (it != m_click_callbacks.end())
m_click_callbacks.erase(it);
}
bool AbstractButton::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
case WM_LBUTTONDOWN: {
if (!m_disabled) {
palette()->setCurrentState(Palette::Pressed);
repaint();
}
return false;
}
case WM_LBUTTONUP: {
if (!m_disabled) {
palette()->setCurrentState(Palette::Hover);
repaint();
click();
}
break;
}
case WM_MOUSEENTER: {
if (!m_disabled) {
palette()->setCurrentState(Palette::Hover);
repaint();
}
break;
}
case WM_MOUSELEAVE: {
if (!m_disabled) {
palette()->setCurrentState(Palette::Normal);
repaint();
}
break;
}
default:
break;
}
return Widget::event(msg, wParam, lParam, result);
}
void AbstractButton::click()
{
if (underMouse()) {
for (auto it = m_click_callbacks.begin(); it != m_click_callbacks.end(); it++) {
if (it->second)
(it->second)();
}
}
}

View File

@ -1,31 +0,0 @@
#ifndef ABSTRACTBUTTON_H
#define ABSTRACTBUTTON_H
#include "widget.h"
#include <unordered_map>
class AbstractButton : public Widget
{
public:
AbstractButton(Widget *parent = nullptr, const std::wstring &text = L"");
virtual ~AbstractButton();
void setText(const std::wstring &text);
void adjustSizeBasedOnContent();
/* callback */
int onClick(const FnVoidVoid &callback);
virtual void disconnect(int) override;
protected:
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*) override;
virtual void click();
std::wstring m_text;
private:
std::unordered_map<int, FnVoidVoid> m_click_callbacks;
};
#endif // ABSTRACTBUTTON_H

View File

@ -1,191 +0,0 @@
#include "application.h"
#include "widget.h"
#include "src/resource.h"
#include <gdiplus.h>
class Application::ApplicationPrivate
{
public:
ApplicationPrivate();
~ApplicationPrivate();
std::wstring font;
ULONG_PTR gdi_token;
HINSTANCE hInstance;
LayoutDirection layoutDirection;
int windowId;
ATOM registerClass(LPCWSTR className, HINSTANCE hInstance);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
};
Application::ApplicationPrivate::ApplicationPrivate() :
gdi_token(0),
hInstance(nullptr),
layoutDirection(LayoutDirection::LeftToRight),
windowId(0)
{
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
Gdiplus::GdiplusStartup(&gdi_token, &gdiplusStartupInput, nullptr);
}
Application::ApplicationPrivate::~ApplicationPrivate()
{
Gdiplus::GdiplusShutdown(gdi_token);
}
ATOM Application::ApplicationPrivate::registerClass(LPCWSTR className, HINSTANCE hInstance)
{
WNDCLASSEX wcx;
memset(&wcx, 0, sizeof(wcx));
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
wcx.hInstance = hInstance;
wcx.lpfnWndProc = WndProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
// wcx.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON));
// wcx.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAINICON));
wcx.lpszClassName = className;
wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
return RegisterClassEx(&wcx);
}
LRESULT CALLBACK Application::ApplicationPrivate::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
if (msg == WM_CREATE) {
if (CREATESTRUCT *cs = (CREATESTRUCT*)lParam) {
if (Widget *wgt = (Widget*)cs->lpCreateParams) {
wgt->setNativeWindowHandle(hWnd);
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)wgt);
LRESULT result = 0;
if (wgt->event(msg, wParam, lParam, &result))
return result;
}
}
} else
if (Widget *wgt = (Widget*)GetWindowLongPtr(hWnd, GWLP_USERDATA)) {
LRESULT result = 0;
if (wgt->event(msg, wParam, lParam, &result))
return result;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
Application *Application::inst = nullptr;
Application::Application(HINSTANCE hInstance, PWSTR cmdline, int cmdshow) :
Application()
{
d_ptr->hInstance = hInstance;
if (!d_ptr->hInstance)
d_ptr->hInstance = GetModuleHandle(NULL);
inst = this;
}
Application::Application() :
Object(nullptr),
d_ptr(new ApplicationPrivate)
{
}
Application *Application::instance()
{
return inst;
}
HINSTANCE Application::moduleHandle()
{
return d_ptr->hInstance;
}
void Application::setLayoutDirection(LayoutDirection layoutDirection)
{
d_ptr->layoutDirection = layoutDirection;
}
void Application::setFont(const std::wstring &font) const
{
d_ptr->font = font;
}
std::wstring Application::font() const
{
return d_ptr->font;
}
Application::~Application()
{
delete d_ptr, d_ptr = nullptr;
}
int Application::exec()
{
MSG msg;
BOOL res;
while ((res = GetMessage(&msg, NULL, 0, 0)) != 0 && res != -1) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
void Application::exit(int code)
{
PostQuitMessage(code);
}
void Application::registerWidget(Widget *wgt, ObjectType objType, const Rect &rc)
{
std::wstring className;
DWORD style = WS_CLIPCHILDREN;
DWORD exStyle = d_ptr->layoutDirection == LayoutDirection::RightToLeft ? WS_EX_LAYOUTRTL : 0;
HWND hWndParent = wgt->parentWidget() ? wgt->parentWidget()->nativeWindowHandle() : HWND_DESKTOP;
switch (objType) {
case ObjectType::WindowType:
className = L"MainWindow " + std::to_wstring(++d_ptr->windowId);
style |= WS_OVERLAPPEDWINDOW;
exStyle |= WS_EX_APPWINDOW;
break;
case ObjectType::DialogType:
className = L"Dialog " + std::to_wstring(++d_ptr->windowId);
style |= WS_CAPTION | WS_SYSMENU /*| DS_MODALFRAME*/;
exStyle |= WS_EX_DLGMODALFRAME;
break;
case ObjectType::PopupType:
className = L"Popup " + std::to_wstring(++d_ptr->windowId);
style |= WS_POPUP;
exStyle |= WS_EX_TOOLWINDOW | WS_EX_LAYERED;
break;
case ObjectType::WidgetType:
default:
className = L"Widget " + std::to_wstring(++d_ptr->windowId);
style |= WS_CHILD;
break;
}
// if (wgt->parent()) {
// if (wgt->parentWidget()->isCreated()) {
// d_ptr->registerClass(className.c_str(), hInstance);
// wgt->m_hWnd = CreateWindowEx(exStyle, className.c_str(), wgt->title().c_str(), style, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWndParent, NULL, hInstance, NULL);
// SetWindowLongPtr(wgt->m_hWnd, GWLP_USERDATA, (LONG_PTR)wgt);
// } else {
// wgt->connectOnCreate([=]() {
// wgt->m_hWnd = CreateWindowEx(exStyle, className.c_str(), wgt->title().c_str(), style, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hWndParent, NULL, hInstance, NULL);
// SetWindowLongPtr(wgt->m_hWnd, GWLP_USERDATA, (LONG_PTR)wgt);
// });
// }
// } else {
d_ptr->registerClass(className.c_str(), d_ptr->hInstance);
CreateWindowEx(exStyle, className.c_str(), wgt->title().c_str(), style, rc.x, rc.y, rc.width, rc.height,
hWndParent, NULL, d_ptr->hInstance, (LPVOID)wgt);
// }
}

View File

@ -1,36 +0,0 @@
#ifndef APPLICATION_H
#define APPLICATION_H
#include "object.h"
#include "common.h"
#include <Windows.h>
class Widget;
class Application : public Object
{
public:
Application(HINSTANCE hInstance, PWSTR cmdline, int cmdshow);
Application(const Application&) = delete;
~Application();
Application& operator=(const Application&) = delete;
static Application *instance();
HINSTANCE moduleHandle();
void setLayoutDirection(LayoutDirection);
void setFont(const std::wstring &font) const;
std::wstring font() const;
int exec();
void exit(int);
private:
Application();
friend class Widget;
void registerWidget(Widget*, ObjectType, const Rect &rc);
class ApplicationPrivate;
ApplicationPrivate *d_ptr;
static Application *inst;
};
#endif // APPLICATION_H

View File

@ -1,126 +0,0 @@
#include "baseutils.h"
#include <string>
#include <shlwapi.h>
#include <sddl.h>
static int getLuma(COLORREF color)
{
return int(0.299 * GetRValue(color) + 0.587 * GetGValue(color) + 0.114 * GetBValue(color));
}
static COLORREF LighterColor(COLORREF color, WORD factor)
{
WORD h = 0, l = 0, s = 0;
ColorRGBToHLS(color, &h, &l, &s);
double k = (double)factor/100;
l = min(240, (unsigned)round(k * l));
return ColorHLSToRGB(h, l, s);
}
static std::wstring GetCurrentUserSID()
{
static std::wstring user_sid;
if (user_sid.empty()) {
HANDLE hToken = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
DWORD tokenLen = 0;
GetTokenInformation(hToken, TokenUser, NULL, 0, &tokenLen);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (PTOKEN_USER pTokenUser = (PTOKEN_USER)malloc(tokenLen)) {
if (GetTokenInformation(hToken, TokenUser, pTokenUser, tokenLen, &tokenLen)) {
LPWSTR sid = NULL;
if (ConvertSidToStringSid(pTokenUser->User.Sid, &sid)) {
user_sid = sid;
LocalFree(sid);
}
}
free(pTokenUser);
}
}
CloseHandle(hToken);
}
}
return user_sid;
}
static DWORD RegQueryDwordValue(HKEY rootKey, LPCWSTR subkey, LPCWSTR value)
{
HKEY hKey;
DWORD dwValue = 0;
if (RegOpenKeyEx(rootKey, subkey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
DWORD dwType = REG_DWORD;
DWORD dwSize = sizeof(DWORD);
RegQueryValueEx(hKey, value, nullptr, &dwType, (LPBYTE)&dwValue, &dwSize);
RegCloseKey(hKey);
}
return dwValue;
}
Utils::WinVer Utils::getWinVersion()
{
static WinVer winVer = WinVer::Undef;
if (winVer == WinVer::Undef) {
if (HMODULE module = GetModuleHandleA("ntdll")) {
NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEXW);
*(FARPROC*)&RtlGetVersion = GetProcAddress(module, "RtlGetVersion");
if (RtlGetVersion) {
OSVERSIONINFOEXW os = {0};
os.dwOSVersionInfoSize = sizeof(os);
RtlGetVersion(&os);
#define MjrVer os.dwMajorVersion
#define MinVer os.dwMinorVersion
#define BldVer os.dwBuildNumber
winVer = MjrVer == 5L && (MinVer == 1L || MinVer == 2L) ? WinVer::WinXP :
MjrVer == 6L && MinVer == 0L ? WinVer::WinVista :
MjrVer == 6L && MinVer == 1L ? WinVer::Win7 :
MjrVer == 6L && MinVer == 2L ? WinVer::Win8 :
MjrVer == 6L && MinVer == 3L ? WinVer::Win8_1 :
MjrVer == 10L && MinVer == 0L && BldVer < 22000 ? WinVer::Win10 :
MjrVer == 10L && MinVer == 0L && BldVer >= 22000 ? WinVer::Win11 :
MjrVer == 10L && MinVer > 0L ? WinVer::Win11 :
MjrVer > 10L ? WinVer::Win11 : WinVer::Undef;
}
}
}
return winVer;
}
COLORREF Utils::getColorizationColor(bool isActive, COLORREF topColor)
{
int luma = getLuma(topColor);
if (isActive) {
if (RegQueryDwordValue(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\DWM", L"ColorPrevalence") != 0) {
DWORD dwcolor = 0;
BOOL opaque = TRUE;
HRESULT(WINAPI *DwmGetColorizationColor)(DWORD*, BOOL*) = NULL;
if (HMODULE module = LoadLibrary(L"dwmapi")) {
*(FARPROC*)&DwmGetColorizationColor = GetProcAddress(module, "DwmGetColorizationColor");
if (DwmGetColorizationColor && !SUCCEEDED(DwmGetColorizationColor(&dwcolor, &opaque))) {
dwcolor = 0;
}
FreeLibrary(module);
if (dwcolor)
return RGB((dwcolor & 0xff0000) >> 16, (dwcolor & 0xff00) >> 8, dwcolor & 0xff);
}
} else {
if (RegQueryDwordValue(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", L"SystemUsesLightTheme") != 0) {
std::wstring userSid = GetCurrentUserSID();
if (!userSid.empty()) {
userSid.append(L"\\Control Panel\\Desktop");
if (RegQueryDwordValue(HKEY_USERS, userSid.c_str(), L"AutoColorization") != 0)
return LighterColor(topColor, 95);
}
}
}
int res = -0.002*luma*luma + 0.93*luma + 6;
return RGB(res, res, res);
}
int res = -0.0007*luma*luma + 0.78*luma + 25;
return RGB(res, res, res);
}
// bool Utils::isColorDark(COLORREF color)
// {
// return int(0.299 * GetRValue(color) + 0.587 * GetGValue(color) + 0.114 * GetBValue(color)) < 128;
// }

View File

@ -1,17 +0,0 @@
#ifndef BASEUTILS_H
#define BASEUTILS_H
#include <Windows.h>
namespace Utils
{
enum WinVer : BYTE {
Undef, WinXP, WinVista, Win7, Win8, Win8_1, Win10, Win11
};
WinVer getWinVersion();
// bool isColorDark(COLORREF color);
COLORREF getColorizationColor(bool isActive = true, COLORREF topColor = 0x00ffffff);
};
#endif // BASEUTILS_H

View File

@ -1,211 +0,0 @@
#include "boxlayout.h"
#include "widget.h"
#include <cmath>
BoxLayout::BoxLayout(Direction direction) :
m_direction(direction)
{
m_margins = Margins(6,6,6,6);
m_spacing = 6;
}
BoxLayout::~BoxLayout()
{
for (auto it = m_destroy_conn.begin(); it != m_destroy_conn.end(); it++)
it->first->disconnect(it->second);
}
void BoxLayout::addWidget(Widget *wgt)
{
m_widgets.push_back(wgt);
// int destroy_conn = wgt->onAboutToDestroy([=]() {
// auto it = std::find(m_widgets.begin(), m_widgets.end(), wgt);
// if (it != m_widgets.end())
// m_widgets.erase(it);
// auto it_conn = m_destroy_conn.find(wgt);
// if (it_conn != m_destroy_conn.end())
// m_destroy_conn.erase(it_conn);
// });
// m_destroy_conn[wgt] = destroy_conn;
}
void BoxLayout::setContentMargins(int left, int top, int right, int bottom)
{
m_margins = Margins(left, top, right, bottom);
}
void BoxLayout::setSpacing(int spacing)
{
m_spacing = spacing;
}
void BoxLayout::onResize(int w, int h)
{
int amount = m_widgets.size();
if (amount > 0) {
int x = m_margins.left;
int y = m_margins.top;
int sum_width = w - (m_margins.right + m_margins.left);
int sum_height = h - (m_margins.bottom + m_margins.top);
int num_fixed = 0;
int sum_fixed_width_or_height = 0;
int last_expanding = -1;
if (m_direction == Horizontal) {
sum_width -= (amount - 1) * m_spacing;
for (int i = 0; i < amount; i++) {
Widget::SizeBehavior sb = (Widget::SizeBehavior)m_widgets[i]->property(Widget::HSizeBehavior);
if (sb == Widget::SizeBehavior::Fixed) {
int _w = 0, _h = 0;
m_widgets[i]->size(&_w, &_h);
sum_fixed_width_or_height += _w;
++num_fixed;
} else
if (sb == Widget::SizeBehavior::Expanding) {
last_expanding = i;
}
}
if (num_fixed != 0 && last_expanding != -1) {
int sep_width = (int)std::round((float)(sum_width - sum_fixed_width_or_height)/(amount - num_fixed));
for (int i = 0; i < amount; i++) {
if (i == last_expanding)
sep_width = (sum_width - sum_fixed_width_or_height) - (amount - num_fixed - 1)*sep_width;
int _w = 0, _h = 0;
m_widgets[i]->size(&_w, &_h);
Widget::SizeBehavior hsb = (Widget::SizeBehavior)m_widgets[i]->property(Widget::HSizeBehavior);
Widget::SizeBehavior vsb = (Widget::SizeBehavior)m_widgets[i]->property(Widget::VSizeBehavior);
if (hsb == Widget::SizeBehavior::Fixed) {
if (vsb == Widget::SizeBehavior::Fixed) {
m_widgets[i]->move(x, y);
} else
if (vsb == Widget::SizeBehavior::Expanding) {
m_widgets[i]->setGeometry(x, y, _w, sum_height);
}
x += _w + m_spacing;
} else
if (hsb == Widget::SizeBehavior::Expanding) {
if (vsb == Widget::SizeBehavior::Fixed) {
m_widgets[i]->setGeometry(x, y, sep_width, _h);
} else
if (vsb == Widget::SizeBehavior::Expanding) {
m_widgets[i]->setGeometry(x, y, sep_width, sum_height);
}
x += sep_width + m_spacing;
}
}
} else {
int sep_width = (int)std::round((float)sum_width/amount);
for (int i = 0; i < amount; i++) {
if (i == amount - 1)
sep_width = sum_width - i*sep_width;
Widget::SizeBehavior hsb = (Widget::SizeBehavior)m_widgets[i]->property(Widget::HSizeBehavior);
Widget::SizeBehavior vsb = (Widget::SizeBehavior)m_widgets[i]->property(Widget::VSizeBehavior);
if (hsb == Widget::SizeBehavior::Fixed) {
if (vsb == Widget::SizeBehavior::Fixed) {
m_widgets[i]->move(x, y);
} else
if (vsb == Widget::SizeBehavior::Expanding) {
int _w = 0, _h = 0;
m_widgets[i]->size(&_w, &_h);
m_widgets[i]->setGeometry(x, y, _w, sum_height);
}
} else
if (hsb == Widget::SizeBehavior::Expanding) {
if (vsb == Widget::SizeBehavior::Fixed) {
int _w = 0, _h = 0;
m_widgets[i]->size(&_w, &_h);
m_widgets[i]->setGeometry(x, y, sep_width, _h);
} else
if (vsb == Widget::SizeBehavior::Expanding) {
m_widgets[i]->setGeometry(x, y, sep_width, sum_height);
}
}
x += sep_width + m_spacing;
}
}
} else {
sum_height -= (amount - 1) * m_spacing;
for (int i = 0; i < amount; i++) {
Widget::SizeBehavior sb = (Widget::SizeBehavior)m_widgets[i]->property(Widget::VSizeBehavior);
if (sb == Widget::SizeBehavior::Fixed) {
int _w = 0, _h = 0;
m_widgets[i]->size(&_w, &_h);
sum_fixed_width_or_height += _h;
++num_fixed;
} else
if (sb == Widget::SizeBehavior::Expanding) {
last_expanding = i;
}
}
if (num_fixed != 0 && last_expanding != -1) {
int sep_height = (int)std::round((float)(sum_height - sum_fixed_width_or_height)/(amount - num_fixed));
for (int i = 0; i < amount; i++) {
if (i == last_expanding)
sep_height = (sum_height - sum_fixed_width_or_height) - (amount - num_fixed - 1)*sep_height;
int _w = 0, _h = 0;
m_widgets[i]->size(&_w, &_h);
Widget::SizeBehavior hsb = (Widget::SizeBehavior)m_widgets[i]->property(Widget::HSizeBehavior);
Widget::SizeBehavior vsb = (Widget::SizeBehavior)m_widgets[i]->property(Widget::VSizeBehavior);
if (vsb == Widget::SizeBehavior::Fixed) {
if (hsb == Widget::SizeBehavior::Fixed) {
m_widgets[i]->move(x, y);
} else
if (hsb == Widget::SizeBehavior::Expanding) {
m_widgets[i]->setGeometry(x, y, sum_width, _h);
}
y += _h + m_spacing;
} else
if (vsb == Widget::SizeBehavior::Expanding) {
if (hsb == Widget::SizeBehavior::Fixed) {
m_widgets[i]->setGeometry(x, y, _w, sep_height);
} else
if (hsb == Widget::SizeBehavior::Expanding) {
m_widgets[i]->setGeometry(x, y, sum_width, sep_height);
}
y += sep_height + m_spacing;
}
}
} else {
int sep_height = (int)std::round((float)sum_height/amount);
for (int i = 0; i < amount; i++) {
if (i == amount - 1)
sep_height = sum_height - i*sep_height;
Widget::SizeBehavior hsb = (Widget::SizeBehavior)m_widgets[i]->property(Widget::HSizeBehavior);
Widget::SizeBehavior vsb = (Widget::SizeBehavior)m_widgets[i]->property(Widget::VSizeBehavior);
if (vsb == Widget::SizeBehavior::Fixed) {
if (hsb == Widget::SizeBehavior::Fixed) {
m_widgets[i]->move(x, y);
} else
if (hsb == Widget::SizeBehavior::Expanding) {
int _w = 0, _h = 0;
m_widgets[i]->size(&_w, &_h);
m_widgets[i]->setGeometry(x, y, sum_width, _h);
}
} else
if (vsb == Widget::SizeBehavior::Expanding) {
if (hsb == Widget::SizeBehavior::Fixed) {
int _w = 0, _h = 0;
m_widgets[i]->size(&_w, &_h);
m_widgets[i]->setGeometry(x, y, _w, sep_height);
} else
if (hsb == Widget::SizeBehavior::Expanding) {
m_widgets[i]->setGeometry(x, y, sum_width, sep_height);
}
}
y += sep_height + m_spacing;
}
}
}
}
}

View File

@ -1,33 +0,0 @@
#ifndef BOXLAYOUT_H
#define BOXLAYOUT_H
#include "layout.h"
#include <unordered_map>
class BoxLayout : public Layout
{
public:
enum Direction : unsigned char {
Horizontal,
Vertical
};
BoxLayout(Direction);
~BoxLayout();
virtual void addWidget(Widget *wgt) override;
virtual void setContentMargins(int, int, int, int);
virtual void setSpacing(int);
protected:
private:
virtual void onResize(int w, int h) override;
std::unordered_map<Widget*, int> m_destroy_conn;
std::vector<Widget*> m_widgets;
Direction m_direction;
int m_spacing;
int m_total_fixed_size;
};
#endif // BOXLAYOUT_H

View File

@ -1,203 +0,0 @@
#include "button.h"
#include "baseutils.h"
#include "drawningengine.h"
#include "metrics.h"
#include "palette.h"
#include <windowsx.h>
static bool isArrangingAllowed() {
BOOL arranging = FALSE;
SystemParametersInfoA(SPI_GETWINARRANGING, 0, &arranging, 0);
return (arranging == TRUE);
}
Button::Button(Widget *parent, const std::wstring &text) :
AbstractButton(parent, text),
m_hIcon(nullptr),
m_hEmfBmp(nullptr),
m_stockIcon(StockIcon::None),
supportSnapLayouts(false),
snapLayoutAllowed(false),
snapLayoutTimerIsSet(false)
{
}
Button::~Button()
{
if (m_hIcon) {
DestroyIcon(m_hIcon);
m_hIcon = nullptr;
}
if (m_hEmfBmp) {
delete m_hEmfBmp, m_hEmfBmp = nullptr;
}
}
void Button::setIcon(const std::wstring &path, int w, int h)
{
if (m_hIcon) {
DestroyIcon(m_hIcon);
m_hIcon = nullptr;
}
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
m_hIcon = (HICON)LoadImage(NULL, path.c_str(), IMAGE_ICON, w, h, LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_SHARED);
update();
}
void Button::setIcon(int id, int w, int h)
{
if (m_hIcon) {
DestroyIcon(m_hIcon);
m_hIcon = nullptr;
}
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
HMODULE hInst = GetModuleHandle(NULL);
m_hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON, w, h, LR_COPYFROMRESOURCE | LR_DEFAULTCOLOR | LR_SHARED);
update();
}
void Button::setEMFIcon(const std::wstring &path, int w, int h)
{
if (m_hEmfBmp) {
delete m_hEmfBmp, m_hEmfBmp = nullptr;
}
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
m_hEmfBmp = new Gdiplus::Bitmap(path.c_str());
update();
}
void Button::setEMFIcon(int id, int w, int h)
{
if (m_hEmfBmp) {
delete m_hEmfBmp, m_hEmfBmp = nullptr;
}
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
HMODULE hInst = GetModuleHandle(NULL);
if (HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(id), RT_RCDATA)) {
if (HGLOBAL hResData = LoadResource(hInst, hRes)) {
if (LPVOID pData = LockResource(hResData)) {
DWORD dataSize = SizeofResource(hInst, hRes);
if (dataSize > 0) {
if (HGLOBAL hGlobal = GlobalAlloc(GHND, dataSize)) {
if (LPVOID pBuffer = GlobalLock(hGlobal)) {
memcpy(pBuffer, pData, dataSize);
IStream *pStream = nullptr;
HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
if (SUCCEEDED(hr)) {
m_hEmfBmp = new Gdiplus::Bitmap(pStream);
pStream->Release();
}
GlobalUnlock(hGlobal);
}
GlobalFree(hGlobal);
}
}
}
FreeResource(hResData);
}
}
update();
}
void Button::setIconSize(int w, int h)
{
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
update();
}
void Button::setSupportSnapLayouts()
{
if (Utils::getWinVersion() > Utils::WinVer::Win10) {
snapLayoutAllowed = isArrangingAllowed();
supportSnapLayouts = true;
}
}
void Button::setStockIcon(StockIcon stockIcon)
{
m_stockIcon = stockIcon;
update();
}
bool Button::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
case WM_PAINT: {
RECT rc;
GetClientRect(m_hWnd, &rc);
engine()->Begin(this, m_hWnd, &rc);
engine()->FillBackground();
// engine()->DrawRoundedRect();
if (metrics()->value(Metrics::BorderWidth) != 0)
engine()->DrawBorder();
if (m_hIcon)
engine()->DrawIcon(m_hIcon);
if (m_hEmfBmp)
engine()->DrawEmfIcon(m_hEmfBmp);
if (!m_text.empty())
engine()->DrawText(rc, m_text, m_hFont);
if (m_stockIcon == StockIcon::CloseIcon)
engine()->DrawStockCloseIcon();
else
if (m_stockIcon == StockIcon::RestoreIcon)
engine()->DrawStockRestoreIcon();
else
if (m_stockIcon == StockIcon::MinimizeIcon)
engine()->DrawStockMinimizeIcon();
else
if (m_stockIcon == StockIcon::MaximizeIcon)
engine()->DrawStockMaximizeIcon();
engine()->End();
*result = FALSE;
return true;
}
case WM_NCHITTEST: {
if (supportSnapLayouts && snapLayoutAllowed) {
if (!snapLayoutTimerIsSet) {
snapLayoutTimerIsSet = true;
palette()->setCurrentState(Palette::Hover);
SetTimer(m_hWnd, SNAP_LAYOUTS_TIMER_ID, 100, NULL);
repaint();
}
*result = HTMAXBUTTON;
return true;
}
return false;
}
case WM_TIMER: {
if (wParam == SNAP_LAYOUTS_TIMER_ID) {
if (!underMouse()) {
KillTimer(m_hWnd, wParam);
snapLayoutTimerIsSet = false;
palette()->setCurrentState(Palette::Normal);
repaint();
}
}
break;
}
case WM_CAPTURECHANGED: {
if (Utils::getWinVersion() > Utils::WinVer::Win10) {
click();
}
break;
}
default:
break;
}
return AbstractButton::event(msg, wParam, lParam, result);
}

View File

@ -1,44 +0,0 @@
#ifndef BUTTON_H
#define BUTTON_H
#include "abstractbutton.h"
#include <gdiplus.h>
class Button : public AbstractButton
{
public:
Button(Widget *parent = nullptr, const std::wstring &text = L"");
virtual ~Button();
enum StockIcon : BYTE {
None,
MinimizeIcon,
MaximizeIcon,
RestoreIcon,
CloseIcon
};
void setIcon(const std::wstring &path, int w, int h);
void setIcon(int id, int w, int h);
void setEMFIcon(const std::wstring &path, int w, int h);
void setEMFIcon(int id, int w, int h);
void setIconSize(int w, int h);
void setSupportSnapLayouts();
void setStockIcon(StockIcon stockIcon);
/* callback */
protected:
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*) override;
private:
HICON m_hIcon;
Gdiplus::Bitmap *m_hEmfBmp;
int m_stockIcon;
bool supportSnapLayouts,
snapLayoutAllowed;
bool snapLayoutTimerIsSet;
};
#endif // BUTTON_H

View File

@ -1,117 +0,0 @@
#include "caption.h"
#include "baseutils.h"
#include "metrics.h"
#include "drawningengine.h"
#include <windowsx.h>
#define RESIZE_AREA_PART 0.14
Caption::Caption(Widget *parent) :
Label(parent),
m_isResizingAvailable(true)
{
m_hwndRoot = GetAncestor(m_hWnd, GA_ROOT);
}
Caption::~Caption()
{
}
void Caption::setResizingAvailable(bool isResizingAvailable)
{
m_isResizingAvailable = isResizingAvailable;
}
bool Caption::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
case WM_PAINT: {
RECT rc;
GetClientRect(m_hWnd, &rc);
engine()->Begin(this, m_hWnd, &rc);
engine()->FillBackground();
// DrawRoundedRect();
if (metrics()->value(Metrics::BorderWidth) != 0)
engine()->DrawBorder();
if (!m_title.empty())
engine()->DrawText(rc, m_title, m_hFont);
engine()->End();
*result = FALSE;
return true;
}
case WM_LBUTTONDOWN:
case WM_NCLBUTTONDOWN: {
if (isResizingAvailable()) {
int y = GET_Y_LPARAM(lParam);
if (HCURSOR hCursor = LoadCursor(NULL, isPointInResizeArea(y) ? IDC_SIZENS : IDC_ARROW))
SetCursor(hCursor);
}
if (postMsg(WM_NCLBUTTONDOWN)) {
*result = TRUE;
return true;
}
return false;
}
case WM_LBUTTONDBLCLK: {
if (postMsg(WM_NCLBUTTONDBLCLK)) {
*result = TRUE;
return true;
}
return false;
}
case WM_MOUSEMOVE:
case WM_NCMOUSEMOVE: {
if (isResizingAvailable()) {
int y = GET_Y_LPARAM(lParam);
if (HCURSOR hCursor = LoadCursor(NULL, isPointInResizeArea(y) ? IDC_SIZENS : IDC_ARROW))
SetCursor(hCursor);
}
break;
}
case WM_MOUSEENTER: {
//palette()->setCurrentState(Palette::Hover);
repaint();
break;
}
case WM_MOUSELEAVE: {
//palette()->setCurrentState(Palette::Normal);
repaint();
break;
}
default:
break;
}
return Widget::event(msg, wParam, lParam, result);
}
bool Caption::isResizingAvailable()
{
return m_isResizingAvailable && Utils::getWinVersion() >= Utils::WinVer::Win10 && !IsZoomed(m_hwndRoot);
}
bool Caption::isPointInResizeArea(int posY)
{
int w = 0, h = 0;
size(&w, &h);
return posY <= RESIZE_AREA_PART * h;
}
bool Caption::postMsg(DWORD cmd) {
POINT pt;
::GetCursorPos(&pt);
ScreenToClient(m_hWnd, &pt);
::ReleaseCapture();
::PostMessage(m_hwndRoot, cmd, isResizingAvailable() && isPointInResizeArea(pt.y) ? HTTOP : HTCAPTION, POINTTOPOINTS(pt));
return true;
}

View File

@ -1,30 +0,0 @@
#ifndef CAPTION_H
#define CAPTION_H
#include "label.h"
#include <Windows.h>
class Caption : public Label
{
public:
Caption(Widget *parent = nullptr);
~Caption();
void setResizingAvailable(bool);
/* callback */
protected:
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*) override;
private:
bool isResizingAvailable();
bool isPointInResizeArea(int posY);
bool postMsg(DWORD cmd);
HWND m_hwndRoot;
bool m_isResizingAvailable;
};
#endif // CAPTION_H

View File

@ -1,59 +0,0 @@
#include "checkbox.h"
#include "drawningengine.h"
#include "metrics.h"
#include <windowsx.h>
CheckBox::CheckBox(Widget *parent, const std::wstring &text) :
AbstractButton(parent, text),
m_checked(false)
{
metrics()->setMetrics(Metrics::TextAlignment, Metrics::AlignHLeft | Metrics::AlignVCenter);
}
CheckBox::~CheckBox()
{
}
void CheckBox::setChecked(bool checked)
{
m_checked = checked;
update();
}
bool CheckBox::isChecked()
{
return m_checked;
}
bool CheckBox::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
case WM_PAINT: {
RECT rc;
GetClientRect(m_hWnd, &rc);
engine()->Begin(this, m_hWnd, &rc);
engine()->DrawCheckBox(m_text, m_hFont, m_checked);
if (metrics()->value(Metrics::BorderWidth) != 0)
engine()->DrawBorder();
engine()->End();
*result = FALSE;
return true;
}
default:
break;
}
return AbstractButton::event(msg, wParam, lParam, result);
}
void CheckBox::click()
{
m_checked = !m_checked;
update();
AbstractButton::click();
}

View File

@ -1,26 +0,0 @@
#ifndef CHECKBOX_H
#define CHECKBOX_H
#include "abstractbutton.h"
class CheckBox : public AbstractButton
{
public:
CheckBox(Widget *parent = nullptr, const std::wstring &text = L"");
virtual ~CheckBox();
void setChecked(bool checked);
bool isChecked();
/* callback */
protected:
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*) override;
virtual void click() override;
private:
bool m_checked;
};
#endif // CHECKBOX_H

View File

@ -1,81 +0,0 @@
#include "common.h"
Margins::Margins() :
left(0), top(0), right(0), bottom(0)
{}
Margins::Margins(int l, int t, int r, int b) :
left(l), top(t), right(r), bottom(b)
{}
Margins::Margins(const Margins &mrg)
{
left = mrg.left;
top = mrg.top;
right = mrg.right;
bottom = mrg.bottom;
}
Margins& Margins::operator=(const Margins &mrg)
{
if (this == &mrg)
return *this;
left = mrg.left;
top = mrg.top;
right = mrg.right;
bottom = mrg.bottom;
return *this;
}
Rect::Rect() :
x(0), y(0), width(0), height(0)
{}
Rect::Rect(int x, int y, int w, int h) :
x(x), y(y), width(w), height(h)
{}
Rect::Rect(const Rect &rc)
{
x = rc.x;
y = rc.y;
width = rc.width;
height = rc.height;
}
Rect& Rect::operator=(const Rect &rc)
{
if (this == &rc)
return *this;
x = rc.x;
y = rc.y;
width = rc.width;
height = rc.height;
return *this;
}
Size::Size() :
width(0), height(0)
{}
Size::Size(int w, int h) :
width(w), height(h)
{}
Size::Size(const Size &sz)
{
width = sz.width;
height = sz.height;
}
Size& Size::operator=(const Size &sz)
{
if (this == &sz)
return *this;
width = sz.width;
height = sz.height;
return *this;
}

View File

@ -1,37 +0,0 @@
#ifndef COMMON_H
#define COMMON_H
struct Margins {
Margins();
Margins(int, int, int, int);
Margins(const Margins&);
Margins& operator=(const Margins&);
int left, top, right, bottom;
};
struct Rect {
Rect();
Rect(int, int, int, int);
Rect(const Rect &rc);
Rect& operator=(const Rect &rc);
int x, y, width, height;
};
struct Size {
Size();
Size(int, int);
Size(const Size&);
Size& operator=(const Size&);
int width, height;
};
enum LayoutDirection : unsigned char {
LeftToRight = 0,
RightToLeft
};
#endif // COMMON_H

View File

@ -1,17 +0,0 @@
#ifndef COMMONDEFINES_H
#define COMMONDEFINES_H
#include <functional>
#define SNAP_LAYOUTS_TIMER_ID 0x1f000000
#define PROGRESS_PULSE_TIMER_ID 0x2f000000
#define WM_MOUSEENTER (WM_APP + 1)
#define WM_INVOKEMETHOD (WM_APP + 2)
typedef std::function<void(void)> FnVoidVoid;
typedef std::function<void(int)> FnVoidInt;
typedef std::function<void(int, int)> FnVoidIntInt;
typedef std::function<void(bool*)> FnVoidBoolPtr;
#endif // COMMONDEFINES_H

View File

@ -1,76 +0,0 @@
#include "dialog.h"
#include "metrics.h"
#include "palette.h"
#include "drawningengine.h"
Dialog::Dialog(Widget *parent, const Rect &rc) :
Widget(parent, ObjectType::DialogType, rc)
{
}
Dialog::~Dialog()
{
}
bool Dialog::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
case WM_SHOWWINDOW: {
if (wParam) {
if (Widget *parent = parentWidget())
EnableWindow(parent->nativeWindowHandle(), FALSE);
}
break;
}
case WM_PAINT: {
RECT rc;
GetClientRect(m_hWnd, &rc);
engine()->Begin(this, m_hWnd);
engine()->FillBackground(rc);
//engine()->DrawRoundedRect(rc);
if (metrics()->value(Metrics::BorderWidth) != 0)
engine()->DrawBorder(rc);
// if (!m_title.empty())
// engine()->DrawText(rc, m_title);
engine()->End();
*result = FALSE;
return true;
}
case WM_MOUSEENTER: {
palette()->setCurrentState(Palette::Hover);
repaint();
break;
}
case WM_NCMOUSELEAVE:
case WM_MOUSELEAVE: {
palette()->setCurrentState(Palette::Normal);
repaint();
break;
}
/*case WM_NCHITTEST: {
*result = HTCAPTION;
return true;
}*/
case WM_CLOSE: {
if (Widget *parent = parentWidget())
EnableWindow(parent->nativeWindowHandle(), TRUE);
break;
}
default:
break;
}
return Widget::event(msg, wParam, lParam, result);
}

View File

@ -1,25 +0,0 @@
#ifndef DIALOG_H
#define DIALOG_H
#include "widget.h"
#include <Windows.h>
#define DEFAULT_DLG_RECT Rect(100,100,800,600)
class Dialog : public Widget
{
public:
Dialog(Widget *parent = nullptr, const Rect &rc = DEFAULT_DLG_RECT);
virtual ~Dialog();
/* callback */
protected:
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*) override;
private:
};
#endif // DIALOG_H

View File

@ -1,33 +0,0 @@
#include "drawingsurface.h"
#include "drawningengine.h"
#include "metrics.h"
#include "palette.h"
DrawningSurface::DrawningSurface() :
m_metrics(new Metrics),
m_palette(new Palette)
{
m_engine = DrawingEngine::instance();
}
DrawningSurface::~DrawningSurface()
{
delete m_palette, m_palette = nullptr;
delete m_metrics, m_metrics = nullptr;
}
Metrics *DrawningSurface::metrics()
{
return m_metrics;
}
Palette *DrawningSurface::palette()
{
return m_palette;
}
DrawingEngine *DrawningSurface::engine()
{
return m_engine;
}

View File

@ -1,26 +0,0 @@
#ifndef DRAWNINGSURFACE_H
#define DRAWNINGSURFACE_H
class Metrics;
class Palette;
class DrawingEngine;
class DrawningSurface
{
public:
DrawningSurface();
virtual ~DrawningSurface();
Metrics *metrics();
Palette *palette();
protected:
DrawingEngine *engine();
private:
Metrics *m_metrics;
Palette *m_palette;
DrawingEngine *m_engine;
};
#endif // DRAWNINGSURFACE_H

View File

@ -1,573 +0,0 @@
#include "drawningengine.h"
#include "drawingsurface.h"
#include "palette.h"
#include "metrics.h"
#include <gdiplusheaders.h>
static Gdiplus::Color ColorFromColorRef(COLORREF rgb)
{
Gdiplus::Color color;
color.SetFromCOLORREF(rgb);
return color;
}
static void RoundedPath(Gdiplus::GraphicsPath &ph, int x, int y, int width, int height, int rad)
{
ph.AddArc(x, y, rad * 2, rad * 2, 180, 90);
ph.AddLine(x + rad, y, x + width - rad, y);
ph.AddArc(x + width - rad * 2, y, rad * 2, rad * 2, 270, 90);
ph.AddLine(x + width, y + rad, x + width, y + height - rad);
ph.AddArc(x + width - rad * 2, y + height - rad * 2, rad * 2, rad * 2, 0, 90);
ph.AddLine(x + width - rad, y + height, x + rad, y + height);
ph.AddArc(x, y + height - rad * 2, rad * 2, rad * 2, 90, 90);
ph.AddLine(x, y + height - rad, x, y + rad);
ph.CloseFigure();
}
DrawingEngine::DrawingEngine() :
m_ds(nullptr),
m_ps(nullptr),
m_hwnd(nullptr),
m_hdc(nullptr),
m_memDC(nullptr),
m_memBmp(nullptr),
m_oldBmp(nullptr),
m_graphics(nullptr)
{
}
DrawingEngine* DrawingEngine::instance()
{
static DrawingEngine inst;
return &inst;
}
DrawingEngine::~DrawingEngine()
{
}
DrawningSurface *DrawingEngine::surface()
{
return m_ds;
}
void DrawingEngine::Begin(DrawningSurface *ds, HWND hwnd, RECT *rc)
{
if (m_ds) {
printf("Engine is buisy...\n");
fflush(stdout);
return;
}
m_ds = ds;
m_rc = rc;
m_hwnd = hwnd;
m_ps = new PAINTSTRUCT;
m_hdc = BeginPaint(hwnd, m_ps);
}
void DrawingEngine::FillBackground() const
{
HBRUSH bkgBrush = CreateSolidBrush(m_ds->palette()->color(Palette::Background));
HBRUSH oldBkgBrush = (HBRUSH)SelectObject(m_hdc, bkgBrush);
FillRect(m_hdc, m_rc, bkgBrush);
SelectObject(m_hdc, oldBkgBrush);
DeleteObject(bkgBrush);
}
// void DrawingEngine::DrawRoundedRect()
// {
// int x = m_rc->left + m_ds->metrics()->value(Metrics::BorderWidth) - 1;
// int y = m_rc->top + m_ds->metrics()->value(Metrics::BorderWidth) - 1;
// int width = m_rc->right - m_rc->left - m_ds->metrics()->value(Metrics::BorderWidth) * 2 + 1;
// int height = m_rc->bottom - m_rc->top - m_ds->metrics()->value(Metrics::BorderWidth) * 2 + 1;
// int rad = m_ds->metrics()->value(Metrics::BorderRadius);
// m_memDC = CreateCompatibleDC(m_hdc);
// m_memBmp = CreateCompatibleBitmap(m_hdc, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top);
// m_oldBmp = (HBITMAP)SelectObject(m_memDC, m_memBmp);
// m_graphics = new Gdiplus::Graphics(m_memDC);
// m_graphics->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
// m_graphics->Clear(ColorFromColorRef(m_ds->palette()->color(Palette::Background)));
// Gdiplus::GraphicsPath ph;
// RoundedPath(ph, x, y, width, height, rad);
// Gdiplus::SolidBrush brush(ColorFromColorRef(m_ds->palette()->color(Palette::Base)));
// m_graphics->FillPath(&brush, &ph);
// if (m_ds->metrics()->value(Metrics::BorderWidth) != 0) {
// Gdiplus::Pen pen(ColorFromColorRef(m_ds->palette()->color(Palette::Border)), m_ds->metrics()->value(Metrics::BorderWidth));
// m_graphics->DrawPath(&pen, &ph);
// }
// BitBlt(m_hdc, m_rc->left, m_rc->top, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top, m_memDC, 0, 0, SRCCOPY);
// delete m_graphics;
// m_graphics = nullptr;
// SelectObject(m_memDC, m_oldBmp);
// m_oldBmp = nullptr;
// DeleteObject(m_memBmp);
// m_memBmp = nullptr;
// DeleteDC(m_memDC);
// m_memDC = nullptr;
// }
void DrawingEngine::DrawBorder() const
{
RECT rc;
SetRect(&rc, m_rc->left, m_rc->top, m_rc->right, m_rc->bottom);
DWORD dwOldLayout = GetLayout(m_hdc);
if (dwOldLayout & LAYOUT_RTL)
rc.right -= 1;
HBRUSH brdBrush = CreateSolidBrush(m_ds->palette()->color(Palette::Border));
HBRUSH oldBrdBrush = (HBRUSH)SelectObject(m_hdc, brdBrush);
for (int i = 0; i < m_ds->metrics()->value(Metrics::BorderWidth); i++) {
FrameRect(m_hdc, &rc, brdBrush);
rc.left += 1;
rc.top += 1;
rc.right -= 1;
rc.bottom -= 1;
}
SelectObject(m_hdc, oldBrdBrush);
DeleteObject(brdBrush);
}
void DrawingEngine::DrawTopBorder(int brdWidth, COLORREF brdColor) const
{
HPEN pen = CreatePen(PS_SOLID, brdWidth, brdColor);
HPEN oldPen = (HPEN)SelectObject(m_hdc, pen);
MoveToEx(m_hdc, m_rc->left - 1, m_rc->top + brdWidth - 1, NULL);
LineTo(m_hdc, m_rc->right, m_rc->top + brdWidth - 1);
SelectObject(m_hdc, oldPen);
DeleteObject(pen);
}
void DrawingEngine::DrawIcon(HICON hIcon) const
{
int x = m_rc->left + (m_rc->right - m_rc->left - m_ds->metrics()->value(Metrics::IconWidth)) / 2;
int y = m_rc->top + (m_rc->bottom - m_rc->top - m_ds->metrics()->value(Metrics::IconHeight)) / 2;
DrawIconEx(m_hdc, x, y, hIcon, m_ds->metrics()->value(Metrics::IconWidth), m_ds->metrics()->value(Metrics::IconHeight), 0, NULL, DI_NORMAL);
}
void DrawingEngine::DrawEmfIcon(Gdiplus::Bitmap *hEmfBmp) const
{
int w = m_ds->metrics()->value(Metrics::IconWidth);
int h = m_ds->metrics()->value(Metrics::IconHeight);
int x = m_rc->left + (m_rc->right - m_rc->left - w) / 2;
int y = m_rc->top + (m_rc->bottom - m_rc->top - h) / 2;
Gdiplus::Graphics gr(m_hdc);
// gr.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);
// gr.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);
// gr.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
gr.DrawImage(hEmfBmp, x, y, w, h);
}
void DrawingEngine::DrawImage(Gdiplus::Bitmap *hBmp) const
{
int x = m_rc->left + (m_rc->right - m_rc->left - m_ds->metrics()->value(Metrics::IconWidth)) / 2;
int y = m_rc->top + (m_rc->bottom - m_rc->top - m_ds->metrics()->value(Metrics::IconHeight)) / 2;
Gdiplus::Graphics gr(m_hdc);
gr.SetInterpolationMode(Gdiplus::InterpolationModeBilinear);
gr.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);
gr.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
gr.DrawImage(hBmp, x, y, m_ds->metrics()->value(Metrics::IconWidth), m_ds->metrics()->value(Metrics::IconHeight));
}
void DrawingEngine::DrawStockCloseIcon()
{
HPEN hPen = CreatePen(PS_SOLID, m_ds->metrics()->value(Metrics::PrimitiveWidth), m_ds->palette()->color(Palette::Primitive));
HPEN oldPen = (HPEN)SelectObject(m_hdc, hPen);
int x = m_rc->left + (m_rc->right - m_rc->left)/2;
int y = m_rc->top + (m_rc->bottom - m_rc->top)/2;
MoveToEx(m_hdc, x, y, NULL);
LineTo(m_hdc, x + m_ds->metrics()->value(Metrics::IconWidth)/2, y + m_ds->metrics()->value(Metrics::IconHeight)/2);
MoveToEx(m_hdc, x, y, NULL);
LineTo(m_hdc, x + m_ds->metrics()->value(Metrics::IconWidth)/2, y - m_ds->metrics()->value(Metrics::IconHeight)/2);
MoveToEx(m_hdc, x, y, NULL);
LineTo(m_hdc, x - m_ds->metrics()->value(Metrics::IconWidth)/2, y + m_ds->metrics()->value(Metrics::IconHeight)/2);
MoveToEx(m_hdc, x, y, NULL);
LineTo(m_hdc, x - m_ds->metrics()->value(Metrics::IconWidth)/2, y - m_ds->metrics()->value(Metrics::IconHeight)/2);
SelectObject(m_hdc, oldPen);
DeleteObject(hPen);
}
void DrawingEngine::DrawStockMinimizeIcon()
{
HPEN hPen = CreatePen(PS_SOLID, m_ds->metrics()->value(Metrics::PrimitiveWidth), m_ds->palette()->color(Palette::Primitive));
HPEN oldPen = (HPEN)SelectObject(m_hdc, hPen);
int x = m_rc->left + (m_rc->right - m_rc->left - m_ds->metrics()->value(Metrics::IconWidth)) / 2;
int y = m_rc->top + (m_rc->bottom - m_rc->top - m_ds->metrics()->value(Metrics::IconHeight)) / 2;
MoveToEx(m_hdc, x, y + m_ds->metrics()->value(Metrics::IconHeight)/2, NULL);
LineTo(m_hdc, x + m_ds->metrics()->value(Metrics::IconWidth), y + m_ds->metrics()->value(Metrics::IconHeight)/2);
SelectObject(m_hdc, oldPen);
DeleteObject(hPen);
}
void DrawingEngine::DrawStockMaximizeIcon()
{
HPEN hPen = CreatePen(PS_SOLID, m_ds->metrics()->value(Metrics::PrimitiveWidth), m_ds->palette()->color(Palette::Primitive));
HPEN oldPen = (HPEN)SelectObject(m_hdc, hPen);
int x = m_rc->left + (m_rc->right - m_rc->left - m_ds->metrics()->value(Metrics::IconWidth)) / 2;
int y = m_rc->top + (m_rc->bottom - m_rc->top - m_ds->metrics()->value(Metrics::IconHeight)) / 2;
int quarterw = m_ds->metrics()->value(Metrics::IconWidth)/4;
int restw = m_ds->metrics()->value(Metrics::IconWidth) - quarterw;
int quarterh = m_ds->metrics()->value(Metrics::IconHeight)/4;
int resth = m_ds->metrics()->value(Metrics::IconHeight) - quarterh;
MoveToEx(m_hdc, x, y + quarterh, NULL);
LineTo(m_hdc, x + restw - 1, y + quarterh);
LineTo(m_hdc, x + restw - 1, y + m_ds->metrics()->value(Metrics::IconHeight) - 1);
LineTo(m_hdc, x, y + m_ds->metrics()->value(Metrics::IconHeight) - 1);
LineTo(m_hdc, x, y + quarterh + m_ds->metrics()->value(Metrics::PrimitiveWidth) - 1);
MoveToEx(m_hdc, x + quarterw, y + quarterh, NULL);
LineTo(m_hdc, x + quarterw, y);
LineTo(m_hdc, x + m_ds->metrics()->value(Metrics::IconWidth) - 1, y);
LineTo(m_hdc, x + m_ds->metrics()->value(Metrics::IconWidth) - 1, y + resth - 1);
LineTo(m_hdc, x + restw - 1, y + resth - 1);
SelectObject(m_hdc, oldPen);
DeleteObject(hPen);
}
void DrawingEngine::DrawStockRestoreIcon()
{
HPEN hPen = CreatePen(PS_SOLID, m_ds->metrics()->value(Metrics::PrimitiveWidth), m_ds->palette()->color(Palette::Primitive));
HPEN oldPen = (HPEN)SelectObject(m_hdc, hPen);
int x = m_rc->left + (m_rc->right - m_rc->left - m_ds->metrics()->value(Metrics::IconWidth)) / 2;
int y = m_rc->top + (m_rc->bottom - m_rc->top - m_ds->metrics()->value(Metrics::IconHeight)) / 2;
MoveToEx(m_hdc, x, y, NULL);
LineTo(m_hdc, x + m_ds->metrics()->value(Metrics::IconWidth) - 1, y);
LineTo(m_hdc, x + m_ds->metrics()->value(Metrics::IconWidth) - 1, y + m_ds->metrics()->value(Metrics::IconHeight) - 1);
LineTo(m_hdc, x, y + m_ds->metrics()->value(Metrics::IconHeight) - 1);
LineTo(m_hdc, x, y + m_ds->metrics()->value(Metrics::PrimitiveWidth) - 1);
SelectObject(m_hdc, oldPen);
DeleteObject(hPen);
}
void DrawingEngine::DrawCheckBox(const std::wstring &text, HFONT hFont, bool checked)
{
int x = m_rc->left + 1;
int y = m_rc->top + (m_rc->bottom - m_rc->top - m_ds->metrics()->value(Metrics::IconHeight)) / 2;
m_memDC = CreateCompatibleDC(m_hdc);
m_memBmp = CreateCompatibleBitmap(m_hdc, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top);
m_oldBmp = (HBITMAP)SelectObject(m_memDC, m_memBmp);
m_graphics = new Gdiplus::Graphics(m_memDC);
m_graphics->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
m_graphics->Clear(ColorFromColorRef(m_ds->palette()->color(Palette::Background)));
DWORD dwOldLayout = GetLayout(m_memDC);
Gdiplus::Matrix origMatrix;
m_graphics->GetTransform(&origMatrix);
if (dwOldLayout & LAYOUT_RTL) {
Gdiplus::Matrix rtlMatrix(-1.0f, 0.0f, 0.0f, 1.0f, float(m_rc->right + m_rc->left - 1), 0.0f);
m_graphics->SetTransform(&rtlMatrix);
}
Gdiplus::Pen pen(ColorFromColorRef(m_ds->palette()->color(Palette::Primitive)), m_ds->metrics()->value(Metrics::PrimitiveWidth));
Gdiplus::Rect rc(x, y, m_ds->metrics()->value(Metrics::IconWidth) - 1, m_ds->metrics()->value(Metrics::IconHeight) - 1);
// m_graphics->DrawRectangle(&pen, rc);
Gdiplus::GraphicsPath ph;
RoundedPath(ph, rc.X, rc.Y, rc.Width, rc.Height, m_ds->metrics()->value(Metrics::PrimitiveRadius));
m_graphics->DrawPath(&pen, &ph);
if (checked) {
pen.SetWidth(m_ds->metrics()->value(Metrics::AlternatePrimitiveWidth));
pen.SetColor(ColorFromColorRef(m_ds->palette()->color(Palette::AlternatePrimitive)));
Gdiplus::PointF pts[3] = {
Gdiplus::PointF(float(x + 2), float(y + m_ds->metrics()->value(Metrics::IconHeight)/2 - 1)),
Gdiplus::PointF(float(x + m_ds->metrics()->value(Metrics::IconWidth)/2 - 2), float(y + m_ds->metrics()->value(Metrics::IconHeight) - 5)),
Gdiplus::PointF(float(x + m_ds->metrics()->value(Metrics::IconWidth) - 3), float(y + 4))
};
m_graphics->DrawLines(&pen, pts, 3);
}
if (!text.empty()) {
RECT rc;
int offset = (dwOldLayout & LAYOUT_RTL) ? m_ds->metrics()->value(Metrics::IconWidth) : 0;
SetRect(&rc, m_rc->left + m_ds->metrics()->value(Metrics::IconWidth) - offset, m_rc->top, m_rc->right - offset, m_rc->bottom);
m_graphics->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
m_graphics->SetTransform(&origMatrix);
LayeredDrawText(rc, text, hFont, dwOldLayout & LAYOUT_RTL);
}
StretchBlt(m_hdc, m_rc->left, m_rc->top, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top, m_memDC, 0, 0, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top, SRCCOPY);
delete m_graphics;
m_graphics = nullptr;
SelectObject(m_memDC, m_oldBmp);
m_oldBmp = nullptr;
DeleteObject(m_memBmp);
m_memBmp = nullptr;
DeleteDC(m_memDC);
m_memDC = nullptr;
}
void DrawingEngine::DrawRadioButton(const std::wstring &text, HFONT hFont, bool checked)
{
int x = m_rc->left + 1;
int y = m_rc->top + (m_rc->bottom - m_rc->top - m_ds->metrics()->value(Metrics::IconHeight)) / 2;
m_memDC = CreateCompatibleDC(m_hdc);
m_memBmp = CreateCompatibleBitmap(m_hdc, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top);
m_oldBmp = (HBITMAP)SelectObject(m_memDC, m_memBmp);
m_graphics = new Gdiplus::Graphics(m_memDC);
m_graphics->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
m_graphics->Clear(ColorFromColorRef(m_ds->palette()->color(Palette::Background)));
DWORD dwOldLayout = GetLayout(m_memDC);
Gdiplus::Matrix origMatrix;
m_graphics->GetTransform(&origMatrix);
if (dwOldLayout & LAYOUT_RTL) {
Gdiplus::Matrix rtlMatrix(-1.0f, 0.0f, 0.0f, 1.0f, float(m_rc->right + m_rc->left - 1), 0.0f);
m_graphics->SetTransform(&rtlMatrix);
}
Gdiplus::Pen pen(ColorFromColorRef(m_ds->palette()->color(Palette::Primitive)), m_ds->metrics()->value(Metrics::PrimitiveWidth));
m_graphics->DrawEllipse(&pen, x, y, m_ds->metrics()->value(Metrics::IconHeight) - 1, m_ds->metrics()->value(Metrics::IconHeight) - 1);
if (checked) {
Gdiplus::SolidBrush chunkBrush(ColorFromColorRef(m_ds->palette()->color(Palette::AlternatePrimitive)));
m_graphics->FillEllipse(&chunkBrush, float(x) + 2.7f, float(y) + 2.7f, float(m_ds->metrics()->value(Metrics::IconHeight)) - 5.4f - 1.0f, float(m_ds->metrics()->value(Metrics::IconHeight)) - 5.4f - 1.0f);
}
if (!text.empty()) {
RECT rc;
int offset = (dwOldLayout & LAYOUT_RTL) ? m_ds->metrics()->value(Metrics::IconWidth) : 0;
SetRect(&rc, m_rc->left + m_ds->metrics()->value(Metrics::IconWidth) - offset, m_rc->top, m_rc->right - offset, m_rc->bottom);
m_graphics->SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
m_graphics->SetTransform(&origMatrix);
LayeredDrawText(rc, text, hFont, dwOldLayout & LAYOUT_RTL);
}
StretchBlt(m_hdc, m_rc->left, m_rc->top, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top, m_memDC, 0, 0, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top, SRCCOPY);
delete m_graphics;
m_graphics = nullptr;
SelectObject(m_memDC, m_oldBmp);
m_oldBmp = nullptr;
DeleteObject(m_memBmp);
m_memBmp = nullptr;
DeleteDC(m_memDC);
m_memDC = nullptr;
}
void DrawingEngine::DrawProgressBar(int progress, int pulse_pos)
{
int x = m_rc->left + m_ds->metrics()->value(Metrics::BorderWidth) + m_ds->metrics()->value(Metrics::IconMarginLeft);
int y = m_rc->top + m_ds->metrics()->value(Metrics::BorderWidth) + m_ds->metrics()->value(Metrics::IconMarginTop);
int width = m_rc->right - m_rc->left - m_ds->metrics()->value(Metrics::BorderWidth) * 2 -
m_ds->metrics()->value(Metrics::IconMarginRight) - m_ds->metrics()->value(Metrics::IconMarginLeft) - 1;
int height = m_rc->bottom - m_rc->top - m_ds->metrics()->value(Metrics::BorderWidth) * 2 -
m_ds->metrics()->value(Metrics::IconMarginBottom) - m_ds->metrics()->value(Metrics::IconMarginTop) - 1;
int rad = m_ds->metrics()->value(Metrics::BorderRadius);
m_memDC = CreateCompatibleDC(m_hdc);
m_memBmp = CreateCompatibleBitmap(m_hdc, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top);
m_oldBmp = (HBITMAP)SelectObject(m_memDC, m_memBmp);
m_graphics = new Gdiplus::Graphics(m_memDC);
m_graphics->SetSmoothingMode(Gdiplus::SmoothingModeHighSpeed);
m_graphics->Clear(ColorFromColorRef(m_ds->palette()->color(Palette::Background)));
Gdiplus::GraphicsPath ph;
RoundedPath(ph, x, y, width, height, rad);
Gdiplus::SolidBrush prgBrush(ColorFromColorRef(m_ds->palette()->color(Palette::Base)));
m_graphics->FillPath(&prgBrush, &ph);
{
int _x = x, _width;
if (pulse_pos != -1) {
_width = width/5;
_x = x + (int)round(double((width - _width) * pulse_pos)/100);
} else {
if (progress < 0)
progress = 0;
else
if (progress > 100)
progress = 100;
_width = (int)round(double(width * progress)/100);
}
Gdiplus::GraphicsPath _ph;
RoundedPath(_ph, _x, y, _width, height, rad);
Gdiplus::SolidBrush chunkBrush(ColorFromColorRef(m_ds->palette()->color(Palette::AlternateBase)));
m_graphics->FillPath(&chunkBrush, &_ph);
}
if (m_ds->metrics()->value(Metrics::BorderWidth) != 0) {
Gdiplus::Pen pen(ColorFromColorRef(m_ds->palette()->color(Palette::Border)), m_ds->metrics()->value(Metrics::BorderWidth));
m_graphics->DrawPath(&pen, &ph);
}
StretchBlt(m_hdc, m_rc->left, m_rc->top, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top, m_memDC, 0, 0, m_rc->right - m_rc->left, m_rc->bottom - m_rc->top, SRCCOPY);
delete m_graphics;
m_graphics = nullptr;
SelectObject(m_memDC, m_oldBmp);
m_oldBmp = nullptr;
DeleteObject(m_memBmp);
m_memBmp = nullptr;
DeleteDC(m_memDC);
m_memDC = nullptr;
}
void DrawingEngine::DrawText(const RECT &rc, const std::wstring &text, HFONT hFont, bool multiline) const
{
HFONT hOldFont = (HFONT) SelectObject(m_hdc, hFont);
SetBkMode(m_hdc, TRANSPARENT);
SetTextColor(m_hdc, m_ds->palette()->color(Palette::Text));
RECT _rc{rc.left + m_ds->metrics()->value(Metrics::TextMarginLeft), rc.top + m_ds->metrics()->value(Metrics::TextMarginTop),
rc.right - m_ds->metrics()->value(Metrics::TextMarginRight), rc.bottom - m_ds->metrics()->value(Metrics::TextMarginBottom)};
UINT fmt = multiline ? 0 : DT_SINGLELINE;
UINT algn = m_ds->metrics()->value(Metrics::TextAlignment);
if (algn & Metrics::AlignHLeft)
fmt |= DT_LEFT;
if (algn & Metrics::AlignHCenter)
fmt |= DT_CENTER;
if (algn & Metrics::AlignHRight)
fmt |= DT_RIGHT;
if (algn & Metrics::AlignVTop)
fmt |= DT_TOP;
if (algn & Metrics::AlignVCenter)
fmt |= DT_VCENTER;
if (algn & Metrics::AlignVBottom)
fmt |= DT_BOTTOM;
::DrawText(m_hdc, text.c_str(), text.length(), &_rc, fmt);
SelectObject(m_hdc, hOldFont);
SetBkMode(m_hdc, OPAQUE);
}
void DrawingEngine::End()
{
EndPaint(m_hwnd, m_ps);
delete m_ps;
m_ps = nullptr;
m_hdc = nullptr;
m_hwnd = nullptr;
m_rc = nullptr;
m_ds = nullptr;
}
// void DrawingEngine::LayeredBegin(DrawningSurface *ds, HWND hwnd, RECT *rc)
// {
// if (m_ds) {
// printf("Engine is buisy....\n");
// fflush(stdout);
// return;
// }
// m_ds = ds;
// m_rc = rc;
// m_hwnd = hwnd;
// m_hdc = GetDC(m_hwnd);
// m_memDC = CreateCompatibleDC(m_hdc);
// m_memBmp = CreateCompatibleBitmap(m_hdc, rc->right - rc->left, rc->bottom - rc->top);
// m_oldBmp = (HBITMAP)SelectObject(m_memDC, m_memBmp);
// m_graphics = new Gdiplus::Graphics(m_memDC);
// m_graphics->SetSmoothingMode(Gdiplus::SmoothingMode::SmoothingModeAntiAlias);
// // gr->SetCompositingMode(Gdiplus::CompositingMode::CompositingModeSourceOver);
// // gr->SetInterpolationMode(Gdiplus::InterpolationModeHighQuality);
// }
// void DrawingEngine::LayeredDrawRoundedRect() const
// {
// int x = m_rc->left + m_ds->metrics()->value(Metrics::ShadowWidth) + m_ds->metrics()->value(Metrics::BorderWidth) - 1;
// int y = m_rc->top + m_ds->metrics()->value(Metrics::ShadowWidth) + m_ds->metrics()->value(Metrics::BorderWidth) - 1;
// int width = m_rc->right - m_rc->left - (m_ds->metrics()->value(Metrics::ShadowWidth) + m_ds->metrics()->value(Metrics::BorderWidth)) * 2 + 1;
// int height = m_rc->bottom - m_rc->top - (m_ds->metrics()->value(Metrics::ShadowWidth) + m_ds->metrics()->value(Metrics::BorderWidth)) * 2 + 1;
// int rad = m_ds->metrics()->value(Metrics::BorderRadius);
// Gdiplus::GraphicsPath ph;
// RoundedPath(ph, x, y, width, height, rad);
// if (m_ds->metrics()->value(Metrics::BorderWidth) != 0) {
// Gdiplus::Pen pen(ColorFromColorRef(m_ds->palette()->color(Palette::Border)), m_ds->metrics()->value(Metrics::BorderWidth));
// m_graphics->DrawPath(&pen, &ph);
// }
// Gdiplus::SolidBrush brush(ColorFromColorRef(m_ds->palette()->color(Palette::Background)));
// m_graphics->FillPath(&brush, &ph);
// }
void DrawingEngine::LayeredDrawText(RECT &rc, const std::wstring &text, HFONT hFont, bool rtl) const
{
// Gdiplus::FontFamily fntFam(L"Segoe UI");
// Gdiplus::Font font(&fntFam, m_ds->metrics()->value(Metrics::FontHeight), Gdiplus::FontStyleRegular, Gdiplus::Unit::UnitPixel);
LOGFONTW logFont = {0};
GetObject(hFont, sizeof(LOGFONTW), &logFont);
Gdiplus::Font font(m_memDC, &logFont);
Gdiplus::RectF rcF(rc.left + m_ds->metrics()->value(Metrics::TextMarginLeft), rc.top + m_ds->metrics()->value(Metrics::TextMarginTop),
rc.right - m_ds->metrics()->value(Metrics::TextMarginRight) - rc.left - m_ds->metrics()->value(Metrics::TextMarginLeft),
rc.bottom - m_ds->metrics()->value(Metrics::TextMarginBottom) - rc.top - m_ds->metrics()->value(Metrics::TextMarginTop));
Gdiplus::StringAlignment h_algn, v_algn;
UINT algn = m_ds->metrics()->value(Metrics::TextAlignment);
if (algn & Metrics::AlignHLeft)
h_algn = Gdiplus::StringAlignmentNear;
if (algn & Metrics::AlignHCenter)
h_algn = Gdiplus::StringAlignmentCenter;
if (algn & Metrics::AlignHRight)
h_algn = Gdiplus::StringAlignmentFar;
if (algn & Metrics::AlignVTop)
v_algn = Gdiplus::StringAlignmentNear;
if (algn & Metrics::AlignVCenter)
v_algn = Gdiplus::StringAlignmentCenter;
if (algn & Metrics::AlignVBottom)
v_algn = Gdiplus::StringAlignmentFar;
Gdiplus::StringFormat strFmt;
strFmt.SetAlignment(h_algn);
strFmt.SetLineAlignment(v_algn);
if (rtl)
strFmt.SetFormatFlags(Gdiplus::StringFormatFlagsDirectionRightToLeft);
Gdiplus::SolidBrush brush(ColorFromColorRef(m_ds->palette()->color(Palette::Text)));
m_graphics->DrawString(text.c_str(), -1, &font, rcF, &strFmt, &brush);
}
// void DrawingEngine::LayeredDrawShadow(int shadowWidth, int rad)
// {
// #define SHADOW_TRANSPATENCY 0x26
// for (int i = 0; i < shadowWidth; i++) {
// int x = m_rc->left + i;
// int y = m_rc->top + i;
// int width = m_rc->right - m_rc->left - i * 2 - 1;
// int height = m_rc->bottom - m_rc->top - i * 2 - 1;
// Gdiplus::GraphicsPath ph;
// RoundedPath(ph, x, y, width, height, rad);
// int alpha = shadowWidth > 1 ? SHADOW_TRANSPATENCY * (i * i) / ((shadowWidth - 1) * (shadowWidth - 1)) : SHADOW_TRANSPATENCY;
// Gdiplus::Pen pen(Gdiplus::Color(alpha, 0, 0, 0), 1);
// m_graphics->DrawPath(&pen, &ph);
// }
// }
// void DrawingEngine::LayeredUpdate(BYTE alpha)
// {
// RECT wrc;
// GetWindowRect(m_hwnd, &wrc);
// HDC scrDC = GetDC(NULL);
// POINT ptSrc = {0, 0};
// POINT ptDst = {wrc.left, wrc.top};
// SIZE szDst = {wrc.right - wrc.left, wrc.bottom - wrc.top};
// BLENDFUNCTION bf;
// bf.AlphaFormat = AC_SRC_ALPHA;
// bf.BlendFlags = 0;
// bf.BlendOp = AC_SRC_OVER;
// bf.SourceConstantAlpha = alpha;
// UpdateLayeredWindow(m_hwnd, scrDC, &ptDst, &szDst, m_memDC, &ptSrc, 0, &bf, ULW_ALPHA);
// ReleaseDC(NULL, scrDC);
// }
// void DrawingEngine::LayeredEnd()
// {
// delete m_graphics;
// m_graphics = nullptr;
// SelectObject(m_memDC, m_oldBmp);
// m_oldBmp = nullptr;
// DeleteObject(m_memBmp);
// m_memBmp = nullptr;
// DeleteDC(m_memDC);
// m_memDC = nullptr;
// ReleaseDC(m_hwnd, m_hdc);
// m_hdc = nullptr;
// m_hwnd = nullptr;
// m_rc = nullptr;
// m_ds = nullptr;
// }

View File

@ -1,59 +0,0 @@
#ifndef DRAWNINGENGINE_H
#define DRAWNINGENGINE_H
#include <Windows.h>
#include <gdiplus.h>
#include <string>
class DrawningSurface;
class DrawingEngine
{
public:
DrawingEngine(const DrawingEngine&) = delete;
DrawingEngine& operator=(const DrawingEngine&) = delete;
static DrawingEngine *instance();
DrawningSurface *surface();
void Begin(DrawningSurface*, HWND, RECT *rc);
void FillBackground() const;
// void DrawRoundedRect();
void DrawBorder() const;
void DrawTopBorder(int, COLORREF) const;
void DrawIcon(HICON hIcon) const;
void DrawEmfIcon(Gdiplus::Bitmap *hEmfBmp) const;
void DrawImage(Gdiplus::Bitmap *hBmp) const;
void DrawStockCloseIcon();
void DrawStockMinimizeIcon();
void DrawStockMaximizeIcon();
void DrawStockRestoreIcon();
void DrawCheckBox(const std::wstring &text, HFONT hFont, bool checked = false);
void DrawRadioButton(const std::wstring &text, HFONT hFont, bool checked = false);
void DrawProgressBar(int progress, int pulse_pos);
void DrawText(const RECT &rc, const std::wstring &text, HFONT hFont, bool multiline = false) const;
void End();
// void LayeredBegin(DrawningSurface*, HWND, RECT *rc);
// void LayeredDrawRoundedRect() const;
void LayeredDrawText(RECT &rc, const std::wstring &text, HFONT hFont, bool rtl = false) const;
// void LayeredDrawShadow(int shadowWidth, int rad);
// void LayeredUpdate(BYTE alpha);
// void LayeredEnd();
private:
DrawingEngine();
~DrawingEngine();
DrawningSurface *m_ds;
RECT *m_rc;
PAINTSTRUCT *m_ps;
HWND m_hwnd;
HDC m_hdc;
HDC m_memDC;
HBITMAP m_memBmp;
HBITMAP m_oldBmp;
Gdiplus::Graphics *m_graphics;
};
#endif // DRAWNINGENGINE_H

View File

@ -1,191 +0,0 @@
#include "label.h"
#include "metrics.h"
#include "drawningengine.h"
Label::Label(Widget *parent) :
Widget(parent, ObjectType::WidgetType),
m_hIcon(nullptr),
m_hEmfBmp(nullptr),
m_hBmp(nullptr),
m_multiline(false)
{
}
Label::~Label()
{
if (m_hIcon) {
DestroyIcon(m_hIcon);
m_hIcon = nullptr;
}
if (m_hEmfBmp) {
delete m_hEmfBmp, m_hEmfBmp = nullptr;
}
if (m_hBmp) {
delete m_hBmp, m_hBmp = nullptr;
}
}
void Label::setText(const std::wstring &text, bool multiline)
{
m_text = text;
m_multiline = multiline;
update();
}
void Label::setIcon(const std::wstring &path, int w, int h)
{
if (m_hIcon) {
DestroyIcon(m_hIcon);
m_hIcon = nullptr;
}
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
m_hIcon = (HICON)LoadImage(NULL, path.c_str(), IMAGE_ICON, w, h, LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_SHARED);
update();
}
void Label::setIcon(int id, int w, int h)
{
if (m_hIcon) {
DestroyIcon(m_hIcon);
m_hIcon = nullptr;
}
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
HMODULE hInst = GetModuleHandle(NULL);
m_hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON, w, h, LR_COPYFROMRESOURCE | LR_DEFAULTCOLOR | LR_SHARED);
update();
}
void Label::setEMFIcon(const std::wstring &path, int w, int h)
{
if (m_hEmfBmp) {
delete m_hEmfBmp, m_hEmfBmp = nullptr;
}
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
m_hEmfBmp = new Gdiplus::Bitmap(path.c_str());
update();
}
void Label::setEMFIcon(int id, int w, int h)
{
if (m_hEmfBmp) {
delete m_hEmfBmp, m_hEmfBmp = nullptr;
}
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
HMODULE hInst = GetModuleHandle(NULL);
if (HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(id), RT_RCDATA)) {
if (HGLOBAL hResData = LoadResource(hInst, hRes)) {
if (LPVOID pData = LockResource(hResData)) {
DWORD dataSize = SizeofResource(hInst, hRes);
if (dataSize > 0) {
if (HGLOBAL hGlobal = GlobalAlloc(GHND, dataSize)) {
if (LPVOID pBuffer = GlobalLock(hGlobal)) {
memcpy(pBuffer, pData, dataSize);
IStream *pStream = nullptr;
HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
if (SUCCEEDED(hr)) {
m_hEmfBmp = new Gdiplus::Bitmap(pStream);
pStream->Release();
}
GlobalUnlock(hGlobal);
}
GlobalFree(hGlobal);
}
}
}
FreeResource(hResData);
}
}
update();
}
void Label::setImage(int id, int w, int h)
{
if (m_hBmp) {
delete m_hBmp, m_hBmp = nullptr;
}
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
HMODULE hInst = GetModuleHandle(NULL);
if (HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(id), L"PNG")) {
if (HGLOBAL hResData = LoadResource(hInst, hRes)) {
if (LPVOID pData = LockResource(hResData)) {
DWORD dataSize = SizeofResource(hInst, hRes);
if (dataSize > 0) {
if (HGLOBAL hGlobal = GlobalAlloc(GHND, dataSize)) {
if (LPVOID pBuffer = GlobalLock(hGlobal)) {
memcpy(pBuffer, pData, dataSize);
IStream *pStream = nullptr;
HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &pStream);
if (SUCCEEDED(hr)) {
m_hBmp = new Gdiplus::Bitmap(pStream);
pStream->Release();
}
GlobalUnlock(hGlobal);
}
GlobalFree(hGlobal);
}
}
}
FreeResource(hResData);
}
}
update();
}
void Label::setIconSize(int w, int h)
{
metrics()->setMetrics(Metrics::IconWidth, w);
metrics()->setMetrics(Metrics::IconHeight, h);
update();
}
bool Label::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
case WM_PAINT: {
RECT rc;
GetClientRect(m_hWnd, &rc);
engine()->Begin(this, m_hWnd, &rc);
engine()->FillBackground();
// DrawRoundedRect();
if (metrics()->value(Metrics::BorderWidth) != 0)
engine()->DrawBorder();
if (m_hBmp)
engine()->DrawImage(m_hBmp);
if (m_hIcon)
engine()->DrawIcon(m_hIcon);
if (m_hEmfBmp)
engine()->DrawEmfIcon(m_hEmfBmp);
if (!m_text.empty())
engine()->DrawText(rc, m_text, m_hFont, m_multiline);
engine()->End();
*result = FALSE;
return true;
}
// case WM_MOUSEENTER: {
// palette()->setCurrentState(Palette::Hover);
// repaint();
// break;
// }
// case WM_MOUSELEAVE: {
// palette()->setCurrentState(Palette::Normal);
// repaint();
// break;
// }
default:
break;
}
return Widget::event(msg, wParam, lParam, result);
}

View File

@ -1,35 +0,0 @@
#ifndef LABEL_H
#define LABEL_H
#include "widget.h"
#include <Windows.h>
#include <gdiplus.h>
class Label : public Widget
{
public:
Label(Widget *parent = nullptr);
virtual ~Label();
void setText(const std::wstring &text, bool multiline = false);
void setIcon(const std::wstring &path, int w, int h);
void setIcon(int id, int w, int h);
void setEMFIcon(const std::wstring &path, int w, int h);
void setEMFIcon(int id, int w, int h);
void setImage(int id, int w, int h);
void setIconSize(int w, int h);
/* callback */
protected:
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*) override;
private:
std::wstring m_text;
HICON m_hIcon;
Gdiplus::Bitmap *m_hEmfBmp;
Gdiplus::Bitmap *m_hBmp;
bool m_multiline;
};
#endif // LABEL_H

View File

@ -1,12 +0,0 @@
#include "layout.h"
Layout::Layout(Object *parent)
{
}
Layout::~Layout()
{
}

View File

@ -1,27 +0,0 @@
#ifndef LAYOUT_H
#define LAYOUT_H
#include "object.h"
#include "layoutitem.h"
#include "common.h"
// #include <vector>
class Layout : public LayoutItem
{
public:
Layout(Object *parent = nullptr);
virtual ~Layout();
virtual void addWidget(Widget *wgt) = 0;
protected:
Margins m_margins;
private:
friend class Widget;
virtual void onResize(int w, int h) = 0;
};
#endif // LAYOUT_H

View File

@ -1,22 +0,0 @@
#include "layoutitem.h"
LayoutItem::LayoutItem()
{
}
LayoutItem::~LayoutItem()
{
}
Widget *LayoutItem::widget()
{
return nullptr;
}
Layout *LayoutItem::layout()
{
return nullptr;
}

View File

@ -1,20 +0,0 @@
#ifndef LAYOUTITEM_H
#define LAYOUTITEM_H
class Widget;
class Layout;
class LayoutItem
{
public:
LayoutItem();
~LayoutItem();
virtual Widget *widget();
virtual Layout *layout();
protected:
};
#endif // LAYOUTITEM_H

View File

@ -1,42 +0,0 @@
#include "metrics.h"
Metrics::Metrics()
{
metrics[BorderWidth] = 0;
metrics[BorderRadius] = 0;
metrics[IconWidth] = 16;
metrics[IconHeight] = 16;
metrics[IconMarginLeft] = 0;
metrics[IconMarginRight] = 0;
metrics[IconMarginTop] = 0;
metrics[IconMarginBottom] = 0;
metrics[IconAlignment] = Alignment::AlignCenter;
metrics[FontWidth] = 0;
metrics[FontHeight] = 18;
metrics[PrimitiveWidth] = 1;
metrics[PrimitiveRadius] = 0;
metrics[AlternatePrimitiveWidth] = 1;
metrics[ShadowWidth] = 10;
metrics[ShadowRadius] = 10;
metrics[TextMarginLeft] = 0;
metrics[TextMarginTop] = 0;
metrics[TextMarginRight] = 0;
metrics[TextMarginBottom] = 0;
metrics[TextAlignment] = Alignment::AlignCenter;
}
Metrics::~Metrics()
{
}
int Metrics::value(Role role)
{
return metrics[role];
}
void Metrics::setMetrics(Role role, int value)
{
metrics[role] = value;
}

View File

@ -1,55 +0,0 @@
#ifndef METRICS_H
#define METRICS_H
class Metrics
{
public:
Metrics();
~Metrics();
enum Alignment : unsigned char {
AlignHLeft = 1,
AlignHCenter = 2,
AlignHRight = 4,
AlignVTop = 8,
AlignVCenter = 16,
AlignVBottom = 32,
AlignCenter = AlignHCenter | AlignVCenter
};
enum Role : unsigned char {
BorderWidth,
BorderRadius,
IconWidth,
IconHeight,
IconMarginLeft,
IconMarginTop,
IconMarginRight,
IconMarginBottom,
IconAlignment,
FontWidth,
FontHeight,
PrimitiveWidth,
AlternatePrimitiveWidth,
PrimitiveRadius,
ShadowWidth,
ShadowRadius,
TextMarginLeft,
TextMarginTop,
TextMarginRight,
TextMarginBottom,
TextAlignment,
METRICS_COUNT
};
void setMetrics(Role, int);
int value(Role);
protected:
private:
int metrics[METRICS_COUNT];
};
#endif // METRICS_H

View File

@ -1,40 +0,0 @@
#include "object.h"
int Object::m_connectionId = 0;
Object::Object(Object *parent) :
m_parent(parent)
{
}
Object::~Object()
{
}
Object *Object::parent()
{
return m_parent;
}
void Object::setParent(Object *parent)
{
m_parent = parent;
}
void Object::setObjectName(const std::wstring &object_name)
{
m_object_name = object_name;
}
std::wstring Object::objectName()
{
return m_object_name;
}
void Object::disconnect(int connectionId)
{
}

View File

@ -1,35 +0,0 @@
#ifndef OBJECT_H
#define OBJECT_H
#include <string>
class Object
{
public:
Object(Object *parent = nullptr);
virtual ~Object();
enum ObjectType : unsigned char {
ApplicationType,
WindowType,
DialogType,
WidgetType,
PopupType
};
Object *parent();
void setParent(Object*);
void setObjectName(const std::wstring&);
std::wstring objectName();
virtual void disconnect(int);
protected:
static int m_connectionId;
private:
Object *m_parent;
std::wstring m_object_name;
};
#endif // OBJECT_H

View File

@ -1,64 +0,0 @@
#include "palette.h"
Palette::Palette()
{
palette[Background][Disabled] = 0x21252b;
palette[Background][Normal] = 0x21252b;
palette[Background][Hover] = 0x34383f;
palette[Background][Pressed] = 0x30343c;
palette[Border][Disabled] = 0x21252b;
palette[Border][Normal] = 0x21252b;
palette[Border][Hover] = 0x34383f;
palette[Border][Pressed] = 0x30343c;
palette[Base][Disabled] = 0x0000ff;
palette[Base][Normal] = 0x0000ff;
palette[Base][Hover] = 0x0000ff;
palette[Base][Pressed] = 0x0000ff;
palette[AlternateBase][Disabled] = 0xff0000;
palette[AlternateBase][Normal] = 0xff0000;
palette[AlternateBase][Hover] = 0xff0000;
palette[AlternateBase][Pressed] = 0xff0000;
palette[Text][Disabled] = 0xeeeeee;
palette[Text][Normal] = 0xeeeeee;
palette[Text][Hover] = 0xaaaaaa;
palette[Text][Pressed] = 0xaaaaaa;
palette[Primitive][Disabled] = 0xeeeeee;
palette[Primitive][Normal] = 0xeeeeee;
palette[Primitive][Hover] = 0xeeeeee;
palette[Primitive][Pressed] = 0xeeeeee;
palette[AlternatePrimitive][Disabled] = 0x888888;
palette[AlternatePrimitive][Normal] = 0x333333;
palette[AlternatePrimitive][Hover] = 0x333333;
palette[AlternatePrimitive][Pressed] = 0x333333;
setCurrentState(Normal);
}
Palette::~Palette()
{
}
COLORREF Palette::color(Role role)
{
return RGB((currentColors[role] & 0xff0000) >> 16, (currentColors[role] & 0xff00) >> 8, currentColors[role] & 0xff);
}
void Palette::setColor(Role role, State state, DWORD color)
{
palette[role][state] = color;
currentColors[role] = palette[role][currentState];
}
void Palette::setCurrentState(State state)
{
currentColors[Background] = palette[Background][state];
currentColors[Border] = palette[Border][state];
currentColors[Base] = palette[Base][state];
currentColors[AlternateBase] = palette[AlternateBase][state];
currentColors[Text] = palette[Text][state];
currentColors[Primitive] = palette[Primitive][state];
currentColors[AlternatePrimitive] = palette[AlternatePrimitive][state];
currentState = state;
}

View File

@ -1,42 +0,0 @@
#ifndef PALETTE_H
#define PALETTE_H
#include <Windows.h>
class Palette
{
public:
Palette();
~Palette();
enum Role : BYTE {
Background = 0,
Border,
Base,
AlternateBase,
Text,
Primitive,
AlternatePrimitive,
PALETTE_ROLE_COUNT
};
enum State : BYTE {
Disabled = 0,
Normal,
Hover,
Pressed,
PALETTE_STATE_COUNT
};
COLORREF color(Role);
void setColor(Role, State, DWORD);
void setCurrentState(State);
private:
DWORD palette[PALETTE_ROLE_COUNT][PALETTE_STATE_COUNT];
DWORD currentColors[PALETTE_ROLE_COUNT];
State currentState;
};
#endif // PALETTE_H

View File

@ -1,110 +0,0 @@
#include "progressbar.h"
#include "drawningengine.h"
#define DEFAULT_PULSE_STEP 1
ProgressBar::ProgressBar(Widget *parent) :
Widget(parent, ObjectType::WidgetType),
m_progress(0),
m_pulse_pos(-1),
m_pulse_direction(1),
m_pulse_step(DEFAULT_PULSE_STEP)
{
}
ProgressBar::~ProgressBar()
{
}
void ProgressBar::setProgress(int progress)
{
m_progress = progress;
update();
}
void ProgressBar::pulse(bool enable)
{
m_pulse_pos = enable ? 0 : -1;
m_pulse_direction = 1;
if (enable) {
// timeBeginPeriod(1);
SetTimer(m_hWnd, PROGRESS_PULSE_TIMER_ID, 17, NULL);
} else {
KillTimer(m_hWnd, PROGRESS_PULSE_TIMER_ID);
// timeEndPeriod(1);
}
}
void ProgressBar::setPulseStep(int step)
{
if (step < 1)
step = 1;
else
if (step > 50)
step = 50;
m_pulse_step = step;
}
bool ProgressBar::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
// case WM_LBUTTONDOWN: {
// palette()->setCurrentState(Palette::Pressed);
// repaint();
// return false;
// }
// case WM_LBUTTONUP: {
// palette()->setCurrentState(Palette::Hover);
// repaint();
// break;
// }
// case WM_MOUSEENTER: {
// palette()->setCurrentState(Palette::Hover);
// repaint();
// break;
// }
// case WM_MOUSELEAVE:
// case WM_NCMOUSELEAVE: {
// palette()->setCurrentState(Palette::Normal);
// repaint();
// break;
// }
case WM_PAINT: {
RECT rc;
GetClientRect(m_hWnd, &rc);
engine()->Begin(this, m_hWnd, &rc);
engine()->DrawProgressBar(m_progress, m_pulse_pos);
engine()->End();
*result = FALSE;
return true;
}
case WM_TIMER: {
if (wParam == PROGRESS_PULSE_TIMER_ID) {
m_pulse_pos += m_pulse_direction * m_pulse_step;
if (m_pulse_pos >= 100) {
m_pulse_pos = 100;
m_pulse_direction = -1;
} else
if (m_pulse_pos <= 0) {
m_pulse_pos = 0;
m_pulse_direction = 1;
}
update();
}
break;
}
default:
break;
}
return Widget::event(msg, wParam, lParam, result);
}

View File

@ -1,30 +0,0 @@
#ifndef PROGRESSBAR_H
#define PROGRESSBAR_H
#include "widget.h"
//#include <gdiplus.h>
class ProgressBar : public Widget
{
public:
ProgressBar(Widget *parent = nullptr);
virtual ~ProgressBar();
void setProgress(int progress);
void pulse(bool);
void setPulseStep(int);
/* callback */
protected:
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*) override;
private:
int m_progress,
m_pulse_pos,
m_pulse_direction,
m_pulse_step;
};
#endif // PROGRESSBAR_H

View File

@ -1,59 +0,0 @@
#include "radiobutton.h"
#include "drawningengine.h"
#include "metrics.h"
#include <windowsx.h>
RadioButton::RadioButton(Widget *parent, const std::wstring &text) :
AbstractButton(parent, text),
m_checked(false)
{
metrics()->setMetrics(Metrics::TextAlignment, Metrics::AlignHLeft | Metrics::AlignVCenter);
}
RadioButton::~RadioButton()
{
}
void RadioButton::setChecked(bool checked)
{
m_checked = checked;
update();
}
bool RadioButton::isChecked()
{
return m_checked;
}
bool RadioButton::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
case WM_PAINT: {
RECT rc;
GetClientRect(m_hWnd, &rc);
engine()->Begin(this, m_hWnd, &rc);
engine()->DrawRadioButton(m_text, m_hFont, m_checked);
if (metrics()->value(Metrics::BorderWidth) != 0)
engine()->DrawBorder();
engine()->End();
*result = FALSE;
return true;
}
default:
break;
}
return AbstractButton::event(msg, wParam, lParam, result);
}
void RadioButton::click()
{
m_checked = true;
update();
AbstractButton::click();
}

View File

@ -1,26 +0,0 @@
#ifndef RADIOBUTTON_H
#define RADIOBUTTON_H
#include "abstractbutton.h"
class RadioButton : public AbstractButton
{
public:
RadioButton(Widget *parent = nullptr, const std::wstring &text = L"");
virtual ~RadioButton();
void setChecked(bool checked);
bool isChecked();
/* callback */
protected:
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*) override;
virtual void click() override;
private:
bool m_checked;
};
#endif // RADIOBUTTON_H

View File

@ -1,417 +0,0 @@
#include "widget.h"
#include "application.h"
#include "metrics.h"
#include "palette.h"
#include "drawningengine.h"
#include <CommCtrl.h>
static bool isAllocOnHeap(void *addr) {
if (HANDLE procHeap = GetProcessHeap()) {
if (HeapLock(procHeap)) {
bool res = false;
PROCESS_HEAP_ENTRY entry = {0};
while (HeapWalk(procHeap, &entry)) {
if ((entry.wFlags & PROCESS_HEAP_REGION) && addr >= (void*)entry.Region.lpFirstBlock && addr <= (void*)entry.Region.lpLastBlock) {
res = true;
break;
}
}
if (!HeapUnlock(procHeap))
res = false;
return res;
}
}
return false;
}
Widget::Widget(Widget *parent) :
Widget(parent, ObjectType::WidgetType)
{}
Widget::Widget(Widget *parent, ObjectType type, HWND hwnd, const Rect &rc) :
Object(parent),
DrawningSurface(),
m_hWnd(hwnd),
m_hFont(nullptr),
m_layout(nullptr),
m_disabled(false),
m_is_created(false),
m_is_destroyed(false),
m_is_class_destroyed(false),
m_mouse_entered(false)
{
m_properties[Properties::HSizeBehavior] = SizeBehavior::Expanding;
m_properties[Properties::VSizeBehavior] = SizeBehavior::Expanding;
if (m_hWnd) {
LONG style = ::GetWindowLong(m_hWnd, GWL_STYLE) | WS_CHILD;
::SetWindowLong(m_hWnd, GWL_STYLE, style);
SetParent(m_hWnd, parent->nativeWindowHandle());
} else {
Application::instance()->registerWidget(this, type, rc);
}
}
Widget::~Widget()
{
m_is_class_destroyed = true;
if (m_layout) {
if (isAllocOnHeap(m_layout))
delete m_layout;
m_layout = nullptr;
}
if (!m_is_destroyed)
DestroyWindow(m_hWnd);
if (m_hFont)
DeleteObject(m_hFont);
}
void Widget::setGeometry(int x, int y, int width, int height)
{
SetWindowPos(m_hWnd, NULL, x, y, width, height, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER /*| SWP_NOSENDCHANGING*/);
}
void Widget::setDisabled(bool disable)
{
m_disabled = disable;
palette()->setCurrentState(disable ? Palette::Disabled : Palette::Normal);
update();
}
void Widget::close()
{
PostMessage(m_hWnd, WM_CLOSE, 0, 0);
}
void Widget::move(int x, int y)
{
SetWindowPos(m_hWnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER /*| SWP_NOSENDCHANGING*/);
}
void Widget::resize(int w, int h)
{
SetWindowPos(m_hWnd, NULL, 0, 0, w, h, SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER /*| SWP_NOSENDCHANGING*/);
}
Widget *Widget::parentWidget()
{
return dynamic_cast<Widget*>(parent());
}
std::wstring Widget::title()
{
return m_title;
}
Size Widget::size()
{
RECT rc;
GetClientRect(m_hWnd, &rc);
return Size(rc.right - rc.left, rc.bottom - rc.top);
}
void Widget::size(int *width, int *height)
{
RECT rc;
GetClientRect(m_hWnd, &rc);
*width = rc.right - rc.left;
*height = rc.bottom - rc.top;
}
void Widget::setWindowTitle(const std::wstring &title)
{
m_title = title;
SetWindowText(m_hWnd, title.c_str());
}
void Widget::setProperty(Properties property, int val)
{
m_properties[property] = val;
}
void Widget::setFont(const std::wstring &font)
{
if (m_hFont) {
DeleteObject(m_hFont);
m_hFont = nullptr;
}
m_hFont = CreateFontW(metrics()->value(Metrics::FontHeight), metrics()->value(Metrics::FontWidth), 0, 0, FW_NORMAL, 0, 0, 0,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH,
font.empty() ? L"Arial" : font.c_str());
}
void Widget::show()
{
ShowWindow(m_hWnd, SW_SHOWNORMAL);
UpdateWindow(m_hWnd);
}
void Widget::hide()
{
ShowWindow(m_hWnd, SW_HIDE);
}
void Widget::repaint()
{
if (IsWindowVisible(m_hWnd))
RedrawWindow(m_hWnd, NULL, NULL, RDW_INVALIDATE | RDW_NOERASE | RDW_INTERNALPAINT | RDW_UPDATENOW);
}
void Widget::update()
{
if (IsWindowVisible(m_hWnd))
RedrawWindow(m_hWnd, NULL, NULL, RDW_INVALIDATE | RDW_NOERASE | RDW_INTERNALPAINT);
}
void Widget::setLayout(Layout *layout)
{
if (m_layout) {
// TODO: error: trying to add a layout when the widget contains a layout
} else {
m_layout = layout;
}
}
bool Widget::isCreated()
{
return m_is_created;
}
bool Widget::underMouse()
{
POINT pt;
GetCursorPos(&pt);
return WindowFromPoint(pt) == m_hWnd;
}
int Widget::property(Properties property)
{
return m_properties[property];
}
Layout *Widget::layout()
{
return m_layout;
}
HWND Widget::nativeWindowHandle()
{
return m_hWnd;
}
Widget *Widget::widgetFromHwnd(Widget *parent, HWND hwnd)
{
return new Widget(parent, Object::WidgetType, hwnd);
}
int Widget::onResize(const FnVoidIntInt &callback)
{
m_resize_callbacks[++m_connectionId] = callback;
return m_connectionId;
}
int Widget::onMove(const FnVoidIntInt &callback)
{
m_move_callbacks[++m_connectionId] = callback;
return m_connectionId;
}
int Widget::onAboutToDestroy(const FnVoidVoid &callback)
{
m_destroy_callbacks[++m_connectionId] = callback;
return m_connectionId;
}
int Widget::onCreate(const FnVoidVoid &callback)
{
m_create_callbacks[++m_connectionId] = callback;
return m_connectionId;
}
int Widget::onClose(const FnVoidBoolPtr &callback)
{
m_close_callbacks[++m_connectionId] = callback;
return m_connectionId;
}
void Widget::disconnect(int connectionId)
{
{
auto it = m_resize_callbacks.find(connectionId);
if (it != m_resize_callbacks.end()) {
m_resize_callbacks.erase(it);
return;
}
}
{
auto it = m_move_callbacks.find(connectionId);
if (it != m_move_callbacks.end()) {
m_move_callbacks.erase(it);
return;
}
}
{
auto it = m_destroy_callbacks.find(connectionId);
if (it != m_destroy_callbacks.end()) {
m_destroy_callbacks.erase(it);
return;
}
}
{
auto it = m_create_callbacks.find(connectionId);
if (it != m_create_callbacks.end()) {
m_create_callbacks.erase(it);
return;
}
}
{
auto it = m_close_callbacks.find(connectionId);
if (it != m_close_callbacks.end()) {
m_close_callbacks.erase(it);
return;
}
}
}
bool Widget::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
case WM_ACTIVATE:
break;
case WM_CREATE: {
m_is_created = true;
for (auto it = m_create_callbacks.begin(); it != m_create_callbacks.end(); it++)
if (it->second)
(it->second)();
setFont(Application::instance()->font());
break;
}
case WM_SIZE:
if (m_layout)
m_layout->onResize(LOWORD(lParam), HIWORD(lParam));
for (auto it = m_resize_callbacks.begin(); it != m_resize_callbacks.end(); it++)
if (it->second)
(it->second)(LOWORD(lParam), HIWORD(lParam));
break;
case WM_MOVE:
for (auto it = m_move_callbacks.begin(); it != m_move_callbacks.end(); it++)
if (it->second)
(it->second)(LOWORD(lParam), HIWORD(lParam));
break;
case WM_PAINT: {
RECT rc;
GetClientRect(m_hWnd, &rc);
engine()->Begin(this, m_hWnd, &rc);
engine()->FillBackground();
if (metrics()->value(Metrics::BorderWidth) != 0)
engine()->DrawBorder();
//DrawRoundedRect();
engine()->End();
*result = FALSE;
return true;
}
case WM_LBUTTONDOWN:
case WM_NCLBUTTONDOWN: {
break;
}
case WM_ERASEBKGND: {
*result = FALSE;
return true;
}
case WM_LBUTTONDBLCLK: {
break;
}
case WM_LBUTTONUP: {
break;
}
case WM_MOUSEMOVE: {
if (!m_mouse_entered) {
m_mouse_entered = true;
PostMessage(m_hWnd, WM_MOUSEENTER, 0, 0);
}
// add here impl onMouseMove
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE /*| TME_HOVER*/;
tme.dwHoverTime = HOVER_DEFAULT;
_TrackMouseEvent(&tme);
break;
}
case WM_NCMOUSEMOVE: {
if (!m_mouse_entered) {
m_mouse_entered = true;
PostMessage(m_hWnd, WM_MOUSEENTER, 0, 0);
}
// add here impl onMouseMove
break;
}
case WM_MOUSEHOVER:
case WM_NCMOUSEHOVER: {
break;
}
case WM_MOUSEENTER: {
// palette()->setCurrentState(Palette::Hover);
// repaint();
break;
}
case WM_MOUSELEAVE:
case WM_NCMOUSELEAVE: {
if (m_mouse_entered) {
m_mouse_entered = false;
}
// palette()->setCurrentState(Palette::Normal);
// repaint();
break;
}
case WM_CLOSE: {
bool accept = true;
for (auto it = m_close_callbacks.begin(); it != m_close_callbacks.end(); it++)
if (it->second)
(it->second)(&accept);
if (accept)
DestroyWindow(m_hWnd);
*result = TRUE;
return true;
}
case WM_DESTROY: {
m_is_destroyed = true;
for (auto it = m_destroy_callbacks.begin(); it != m_destroy_callbacks.end(); it++)
if (it->second)
(it->second)();
if (!m_is_class_destroyed) {
if (isAllocOnHeap(this)) {
SetWindowLongPtr(m_hWnd, GWLP_USERDATA, 0);
delete this;
}
}
break;
}
default:
break;
}
return false;
}
void Widget::setNativeWindowHandle(HWND hWnd)
{
m_hWnd = hWnd;
}

View File

@ -1,90 +0,0 @@
#ifndef WIDGET_H
#define WIDGET_H
#include "object.h"
#include "drawingsurface.h"
#include "layout.h"
#include "commondefines.h"
#include <unordered_map>
#include <Windows.h>
class Widget : public Object, public DrawningSurface
{
public:
Widget(Widget *parent = nullptr);
virtual ~Widget();
enum Properties : BYTE {
HSizeBehavior,
VSizeBehavior,
PROPERTIES_COUNT
};
enum SizeBehavior : BYTE {
Fixed,
Expanding,
//Preferred
};
virtual void setGeometry(int, int, int, int);
void setDisabled(bool);
void close();
void move(int, int);
void resize(int, int);
Widget* parentWidget();
std::wstring title();
Size size();
void size(int*, int*);
void setWindowTitle(const std::wstring &title);
void setProperty(Properties, int);
void setFont(const std::wstring &font);
void show();
void hide();
void repaint();
void update();
void setLayout(Layout *lut);
bool isCreated();
bool underMouse();
int property(Properties);
Layout* layout();
HWND nativeWindowHandle();
static Widget* widgetFromHwnd(Widget *parent, HWND);
/* callback */
int onResize(const FnVoidIntInt &callback);
int onMove(const FnVoidIntInt &callback);
int onAboutToDestroy(const FnVoidVoid &callback);
int onCreate(const FnVoidVoid &callback);
int onClose(const FnVoidBoolPtr &callback);
virtual void disconnect(int) override;
protected:
friend class Application;
Widget(Widget *parent, ObjectType type, HWND hWnd = nullptr, const Rect &rc = Rect(CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT));
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*);
HWND m_hWnd;
HFONT m_hFont;
Layout *m_layout;
std::wstring m_title;
bool m_disabled;
private:
void setNativeWindowHandle(HWND);
int m_properties[PROPERTIES_COUNT];
std::unordered_map<int, FnVoidIntInt> m_resize_callbacks,
m_move_callbacks;
std::unordered_map<int, FnVoidVoid> m_create_callbacks,
m_destroy_callbacks;
std::unordered_map<int, FnVoidBoolPtr> m_close_callbacks;
bool m_is_created,
m_is_destroyed,
m_is_class_destroyed,
m_mouse_entered;
};
#endif // WIDGET_H

View File

@ -1,534 +0,0 @@
#include "window.h"
#include "baseutils.h"
#include "palette.h"
#include "metrics.h"
#include "drawningengine.h"
#include <windowsx.h>
#define DCX_USESTYLE 0x00010000
#define NC_AREA_WIDTH 3
#define MAIN_WINDOW_BORDER_WIDTH 1
using WinVer = Utils::WinVer;
static BOOL CALLBACK EnumChildProc(_In_ HWND hwnd, _In_ LPARAM lParam)
{
ShowWindow(hwnd, SW_SHOWNORMAL);
UpdateWindow(hwnd);
return TRUE;
}
static double GetLogicalDpi(HWND hWnd)
{
if (HMODULE module = GetModuleHandleA("user32")) {
UINT(WINAPI *_GetDpiForWindow)(HWND) = NULL;
*(FARPROC*)&_GetDpiForWindow = GetProcAddress(module, "GetDpiForWindow");
if (_GetDpiForWindow)
return (double)_GetDpiForWindow(hWnd)/96;
}
HDC hdc = GetDC(NULL);
double dpi = (double)GetDeviceCaps(hdc, LOGPIXELSX)/96;
ReleaseDC(NULL, hdc);
return dpi;
}
static Rect availableGeometry(HWND hwnd)
{
Rect rc;
if (HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST)) {
MONITORINFOEX monInfo;
ZeroMemory(&monInfo, sizeof(monInfo));
monInfo.cbSize = sizeof(MONITORINFOEX);
if (GetMonitorInfo(monitor, &monInfo))
rc = Rect(monInfo.rcWork.left, monInfo.rcWork.top, monInfo.rcWork.right - monInfo.rcWork.left, monInfo.rcWork.bottom - monInfo.rcWork.top);
}
return rc;
}
static void GetFrameMetricsForDpi(FRAME &frame, double dpi, bool maximized = false)
{
WinVer ver = Utils::getWinVersion();
int row = ver == WinVer::WinXP ? 0 :
ver <= WinVer::Win7 ? 1 :
ver <= WinVer::Win8_1 ? 2 :
ver <= WinVer::Win10 ? 3 : 4;
int column = dpi <= 1.0 ? 0 :
dpi <= 1.25 ? 1 :
dpi <= 1.5 ? 2 :
dpi <= 1.75 ? 3 :
dpi <= 2.0 ? 4 :
dpi <= 2.25 ? 5 :
dpi <= 2.5 ? 6 :
dpi <= 3.0 ? 7 :
dpi <= 3.5 ? 8 :
dpi <= 4.0 ? 9 :
dpi <= 4.5 ? 10 :
dpi <= 5.0 ? 11 : 12;
const int left[5][13] = { // Left margin for scales 100-500%
{0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2}, // WinXp: for NC width 3px
{7, 8, 10, 11, 12, 13, 15, 17, 20, 22, 25, 27, 32}, // WinVista - Win7
{7, 8, 10, 11, 12, 13, 15, 17, 20, 22, 25, 27, 32}, // Win8 - Win8.1
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win10
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // Win11
};
frame.left = left[row][column];
const int top[5][13] = { // Top margin for scales 100-500%
{0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2}, // WinXp: for NC width 3px
{7, 8, 10, 11, 12, 13, 15, 17, 20, 22, 25, 27, 32}, // WinVista - Win7
{7, 8, 10, 11, 12, 13, 15, 17, 20, 22, 25, 27, 32}, // Win8 - Win8.1
{31, 38, 45, 52, 58, 65, 72, 85, 99, 112, 126, 139, 167}, // Win10
{30, 37, 43, 50, 56, 63, 69, 82, 95, 108, 121, 134, 161} // Win11
};
frame.top = top[row][column];
if (!maximized)
return;
const int left_ofs[5][13] = { // Left offset for scales 100-500%
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // WinXp
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // WinVista - Win7
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win8 - Win8.1
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win10
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // Win11
};
frame.left -= left_ofs[row][column];
const int top_ofs[5][13] = { // Top offset for scales 100-500%
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // WinXp
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // WinVista - Win7
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win8 - Win8.1
{8, 9, 11, 12, 13, 14, 16, 18, 21, 24, 27, 30, 36}, // Win10
{7, 8, 9, 10, 11, 12, 13, 15, 17, 19, 21, 23, 28} // Win11
};
frame.top -= top_ofs[row][column];
}
static bool isTaskbarAutoHideOn()
{
APPBARDATA ABData;
ABData.cbSize = sizeof(ABData);
return (SHAppBarMessage(ABM_GETSTATE, &ABData) & ABS_AUTOHIDE) != 0;
}
static bool isThemeActive()
{
static BOOL(WINAPI *IsThemeActive)() = NULL;
if (!IsThemeActive) {
if (HMODULE module = GetModuleHandleA("uxtheme"))
*(FARPROC*)&IsThemeActive = GetProcAddress(module, "IsThemeActive");
}
return IsThemeActive ? (bool)IsThemeActive() : true;
}
Window::Window(Widget *parent, const Rect &rc) :
Widget(parent, ObjectType::WindowType, nullptr, rc),
m_centralWidget(nullptr),
m_contentMargins(0,0,0,0),
m_resAreaWidth(0),
m_state(-1),
m_borderless(true),
m_isResizable(true),
m_scaleChanged(false),
m_init_size(rc.width, rc.height)
{
//setLayout(new BoxLayout(BoxLayout::Vertical));
m_isThemeActive = isThemeActive();
m_isTaskbarAutoHideOn = isTaskbarAutoHideOn();
m_borderless = true;//isCustomWindowStyle();
if (m_borderless && Utils::getWinVersion() < WinVer::Win10) {
LONG style = ::GetWindowLong(m_hWnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW;
::SetWindowLong(m_hWnd, GWL_STYLE, style & ~WS_CAPTION);
}
m_isMaximized = IsZoomed(m_hWnd);
m_dpi = GetLogicalDpi(m_hWnd);
GetFrameMetricsForDpi(m_frame, m_dpi, m_isMaximized);
if (m_borderless && Utils::getWinVersion() == WinVer::Win10) {
HDC hdc = GetDC(NULL);
m_brdWidth = GetSystemMetrics(SM_CXBORDER) * GetDeviceCaps(hdc, LOGPIXELSX)/96;
ReleaseDC(NULL, hdc);
m_brdColor = Utils::getColorizationColor(true, palette()->color(Palette::Background));
}
SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
Window::~Window()
{
//if (m_layout)
// delete m_layout, m_layout = nullptr;
}
void Window::setCentralWidget(Widget *wgt)
{
m_centralWidget = wgt;
}
void Window::setContentsMargins(int left, int top, int right, int bottom)
{
m_contentMargins = Margins(left, top, right, bottom);
if (IsWindowVisible(m_hWnd))
SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
void Window::setResizable(bool isResizable)
{
if (m_isResizable != isResizable) {
m_isResizable = isResizable;
LONG style = ::GetWindowLong(m_hWnd, GWL_STYLE);
::SetWindowLong(m_hWnd, GWL_STYLE, m_isResizable ? style | WS_MAXIMIZEBOX : style & ~WS_MAXIMIZEBOX);
}
}
void Window::showAll()
{
ShowWindow(m_hWnd, SW_SHOWNORMAL);
UpdateWindow(m_hWnd);
EnumChildWindows(m_hWnd, EnumChildProc, 0);
SetForegroundWindow(m_hWnd);
}
void Window::showNormal()
{
ShowWindow(m_hWnd, SW_RESTORE);
}
void Window::showMinimized()
{
ShowWindow(m_hWnd, SW_SHOWMINIMIZED);
}
void Window::showMaximized()
{
ShowWindow(m_hWnd, SW_SHOWMAXIMIZED);
}
void Window::setIcon(int id)
{
HMODULE hInstance = GetModuleHandle(NULL);
HICON hIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(id), IMAGE_ICON, 96, 96, LR_DEFAULTCOLOR | LR_SHARED);
SendMessage(m_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
SendMessage(m_hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
}
bool Window::isMinimized()
{
WINDOWPLACEMENT wpl;
wpl.length = sizeof(wpl);
if (GetWindowPlacement(m_hWnd, &wpl))
return wpl.showCmd == SW_SHOWMINIMIZED;
return false;
}
bool Window::isMaximized()
{
WINDOWPLACEMENT wpl;
wpl.length = sizeof(wpl);
if (GetWindowPlacement(m_hWnd, &wpl))
return wpl.showCmd == SW_SHOWMAXIMIZED;
return false;
}
Widget *Window::centralWidget()
{
return m_centralWidget;
}
int Window::onStateChanged(const FnVoidInt &callback)
{
m_state_callbacks[++m_connectionId] = callback;
return m_connectionId;
}
void Window::disconnect(int connectionId)
{
auto it = m_state_callbacks.find(connectionId);
if (it != m_state_callbacks.end())
m_state_callbacks.erase(it);
}
bool Window::event(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *result)
{
switch (msg) {
case WM_DPICHANGED: {
m_dpi = (double)HIWORD(wParam)/96;
RECT *prc = (RECT*)lParam;
GetFrameMetricsForDpi(m_frame, m_dpi, m_isMaximized);
SetWindowPos(m_hWnd, NULL, prc->left, prc->top, prc->right - prc->left, prc->bottom - prc->top, SWP_NOZORDER | SWP_NOACTIVATE);
break;
}
case WM_NCMOUSEMOVE:
case WM_MOUSEMOVE: {
//int x = GET_X_LPARAM(lParam);
//int y = GET_Y_LPARAM(lParam);
//printf("Window Move Event: %d x %d \t %lld\n", x, y, (long long)this);
//fflush(stdout);
break;
}
case WM_MOUSEHOVER:
case WM_NCMOUSEHOVER: {
//int x = GET_X_LPARAM(lParam);
//int y = GET_Y_LPARAM(lParam);
//printf("Window Hover Event: %d x %d \t %lld\n", x, y, (long long)this);
//fflush(stdout);
break;
}
case WM_PAINT: {
RECT rc;
GetClientRect(m_hWnd, &rc);
engine()->Begin(this, m_hWnd, &rc);
engine()->FillBackground();
if (metrics()->value(Metrics::BorderWidth) != 0)
engine()->DrawBorder();
if (m_brdWidth != 0)
engine()->DrawTopBorder(m_brdWidth, m_brdColor);
engine()->End();
*result = FALSE;
return true;
}
case WM_NCPAINT: {
if (Utils::getWinVersion() > WinVer::Win7 || !m_borderless)
return false;
if (HDC hdc = ::GetDCEx(m_hWnd, 0, DCX_WINDOW | DCX_USESTYLE)) {
RECT rcc, rcw;
::GetClientRect(m_hWnd, &rcc);
::GetWindowRect(m_hWnd, &rcw);
POINT pt;
pt.x = rcw.left;
pt.y = rcw.top;
::MapWindowPoints(0, m_hWnd, (LPPOINT)&rcw, (sizeof(RECT)/sizeof(POINT)));
::OffsetRect(&rcc, -rcw.left, -rcw.top);
::OffsetRect(&rcw, -rcw.left, -rcw.top);
HRGN rgntemp = NULL;
if (wParam == NULLREGION || wParam == ERROR) {
::ExcludeClipRect(hdc, rcc.left, rcc.top, rcc.right, rcc.bottom);
} else {
rgntemp = ::CreateRectRgn(rcc.left + pt.x, rcc.top + pt.y, rcc.right + pt.x, rcc.bottom + pt.y);
if (::CombineRgn(rgntemp, (HRGN)wParam, rgntemp, RGN_DIFF) == NULLREGION) {
// nothing to paint
}
::OffsetRgn(rgntemp, -pt.x, -pt.y);
::ExtSelectClipRgn(hdc, rgntemp, RGN_AND);
}
HBRUSH hbrushBkg = ::CreateSolidBrush(palette()->color(Palette::Background));
::FillRect(hdc, &rcw, hbrushBkg);
::DeleteObject(hbrushBkg);
// HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
// GetWindowRgn(msg->hwnd, hrgn);
HBRUSH hbrushBrd = ::CreateSolidBrush(palette()->color(Palette::Border));
::FrameRect(hdc, &rcw, hbrushBrd); // Drawing NC border when using ~WS_CAPTION
// ::FrameRgn(hdc, hrgn, hbrushBrd, 1, 1); // Drawing NC border when using WS_CAPTION
::DeleteObject(hbrushBrd);
// ::DeleteObject(hrgn);
::ReleaseDC(m_hWnd, hdc);
if (rgntemp != 0)
::DeleteObject(rgntemp);
return true;
}
return false;
}
case WM_NCCALCSIZE: {
if (!m_borderless || !wParam)
return false;
NCCALCSIZE_PARAMS *params = (NCCALCSIZE_PARAMS*)lParam;
if (!m_isThemeActive) {
*result = m_isMaximized ? 0 : DefWindowProc(m_hWnd, WM_NCCALCSIZE, wParam, lParam);
return true;
}
LRESULT res = DefWindowProc(m_hWnd, WM_NCCALCSIZE, wParam, lParam);
params->rgrc[0].left -= m_frame.left;
params->rgrc[0].top -= m_frame.top;
params->rgrc[0].right += m_frame.left;
params->rgrc[0].bottom += m_frame.left;
if (m_isMaximized && m_isTaskbarAutoHideOn && (Utils::getWinVersion() >= WinVer::Win10))
params->rgrc[0].bottom -= 2;
*result = res;
return true;
}
case WM_NCHITTEST: {
if (m_isResizable) {
if (m_borderless) {
RECT rect;
GetWindowRect(m_hWnd, &rect);
long x = GET_X_LPARAM(lParam);
long y = GET_Y_LPARAM(lParam);
if (x <= rect.left + m_resAreaWidth) {
if (y <= rect.top + m_resAreaWidth)
*result = HTTOPLEFT;
else
if (y > rect.top + m_resAreaWidth && y < rect.bottom - m_resAreaWidth)
*result = HTLEFT;
else
if (y >= rect.bottom - m_resAreaWidth)
*result = HTBOTTOMLEFT;
} else
if (x > rect.left + m_resAreaWidth && x < rect.right - m_resAreaWidth) {
if (y <= rect.top + m_resAreaWidth)
*result = HTTOP;
else
if (y >= rect.bottom - m_resAreaWidth)
*result = HTBOTTOM;
} else
if (x >= rect.right - m_resAreaWidth) {
if (y <= rect.top + m_resAreaWidth)
*result = HTTOPRIGHT;
else
if (y > rect.top + m_resAreaWidth && y < rect.bottom - m_resAreaWidth)
*result = HTRIGHT;
else
if (y >= rect.bottom - m_resAreaWidth)
*result = HTBOTTOMRIGHT;
}
return *result != 0;
}
} else {
LRESULT hit = DefWindowProc(m_hWnd, msg, wParam, lParam);
if (hit == HTBOTTOM || hit == HTLEFT || hit == HTRIGHT || hit == HTTOP ||
hit == HTBOTTOMLEFT || hit == HTBOTTOMRIGHT || hit == HTTOPLEFT || hit == HTTOPRIGHT) {
*result = HTCLIENT;
return true;
}
}
return false;
}
case WM_NCACTIVATE: {
if (m_borderless) {
if (Utils::getWinVersion() > WinVer::WinXP && Utils::getWinVersion() < WinVer::Win10) {
// Prevent drawing of inactive system frame (needs ~WS_CAPTION or temporary ~WS_VISIBLE to work)
*result = DefWindowProc(m_hWnd, WM_NCACTIVATE, wParam, -1);
return true;
} else
if (Utils::getWinVersion() == WinVer::Win10) {
m_brdColor = Utils::getColorizationColor(LOWORD(wParam), palette()->color(Palette::Background));
RECT rc;
GetClientRect(m_hWnd, &rc);
rc.bottom = m_brdWidth;
RedrawWindow(m_hWnd, &rc, NULL, RDW_INVALIDATE | RDW_NOERASE | RDW_INTERNALPAINT | RDW_UPDATENOW);
}
}
return false;
}
case WM_GETMINMAXINFO: {
bool isMaximized = (bool)IsZoomed(m_hWnd);
if (m_isMaximized != isMaximized) {
m_isMaximized = isMaximized;
GetFrameMetricsForDpi(m_frame, m_dpi, isMaximized);
if (m_borderless && Utils::getWinVersion() == WinVer::Win10) {
if (isMaximized) {
m_brdWidth = 0;
} else {
HDC hdc = GetDC(NULL);
m_brdWidth = GetSystemMetrics(SM_CXBORDER) * GetDeviceCaps(hdc, LOGPIXELSX)/96;
ReleaseDC(NULL, hdc);
}
}
}
if (!m_isResizable) {
MINMAXINFO* minMaxInfo = (MINMAXINFO*)lParam;
minMaxInfo->ptMinTrackSize.x = m_init_size.width;
minMaxInfo->ptMinTrackSize.y = m_init_size.height;
minMaxInfo->ptMaxTrackSize.x = m_init_size.width;
minMaxInfo->ptMaxTrackSize.y = m_init_size.height;
}
break;
}
case WM_THEMECHANGED: {
bool _isThemeActive = isThemeActive();
if (m_isThemeActive != _isThemeActive)
m_isThemeActive = _isThemeActive;
break;
}
case WM_SETTINGCHANGE: {
// if (wParam == SPI_SETWINARRANGING) {
// if (Utils::getWinVersion() > Utils::WinVer::Win10)
// SendMessage((HWND)m_boxTitleBtns->winId(), WM_SETTINGCHANGE, 0, 0);
// }
// printf(" Settings...\n");
// fflush(stdout);
// snapLayoutAllowed = isArrangingAllowed();
break;
}
case WM_SIZING: {
// if (m_borderless)
// RedrawWindow(m_hWnd, NULL, NULL, RDW_INVALIDATE | RDW_NOERASE | RDW_INTERNALPAINT);
break;
}
case WM_SIZE: {
switch (wParam) {
case SIZE_MAXIMIZED:
case SIZE_MINIMIZED:
case SIZE_RESTORED: {
if (m_state != (int)wParam) {
m_state = (int)wParam;
for (auto it = m_state_callbacks.begin(); it != m_state_callbacks.end(); it++)
if (it->second)
(it->second)(m_state);
if (m_borderless) {
if (m_isMaximized) {
if (Utils::getWinVersion() < WinVer::Win10) {
m_resAreaWidth = 0;
Rect rc = availableGeometry(m_hWnd);
int offset = 0;
if (Utils::getWinVersion() == WinVer::WinXP) {
if (isTaskbarAutoHideOn())
offset += NC_AREA_WIDTH + 1;
if (m_isThemeActive) {
rc.x += -NC_AREA_WIDTH;
rc.y += -NC_AREA_WIDTH;
rc.width += 2*NC_AREA_WIDTH;
rc.height += 2*NC_AREA_WIDTH;
}
} else
if (Utils::getWinVersion() > WinVer::WinXP && isTaskbarAutoHideOn())
offset += 2;
SetWindowPos(m_hWnd, NULL, rc.x, rc.y, rc.width, rc.height - offset, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
}
} else {
if (Utils::getWinVersion() < WinVer::Win10) {
m_resAreaWidth = (int)round(MAIN_WINDOW_BORDER_WIDTH * m_dpi);
if (Utils::getWinVersion() == WinVer::WinXP)
m_resAreaWidth -= NC_AREA_WIDTH;
}
}
}
}
if (m_centralWidget) {
int top_offset = 0;
if (m_borderless && !m_isMaximized && Utils::getWinVersion() == Utils::WinVer::Win10)
top_offset = m_brdWidth;
m_centralWidget->setGeometry(m_contentMargins.left + m_resAreaWidth, m_contentMargins.top + top_offset + m_resAreaWidth,
LOWORD(lParam) - m_contentMargins.right - m_contentMargins.left - 2*m_resAreaWidth,
HIWORD(lParam) - m_contentMargins.bottom - m_contentMargins.top - top_offset - 2*m_resAreaWidth);
}
break;
}
default:
break;
}
break;
}
default:
break;
}
return Widget::event(msg, wParam, lParam, result);
}

View File

@ -1,67 +0,0 @@
#ifndef WINDOW_H
#define WINDOW_H
#include "widget.h"
#define DEFAULT_WINDOW_RECT Rect(100,100,1368,768)
struct FRAME {
FRAME() : left(0), top(0)
{}
FRAME(FRAME &frame) {
left = frame.left;
top = frame.top;
}
int left, top;
};
class Window : public Widget
{
public:
Window(Widget *parent = nullptr, const Rect &rc = DEFAULT_WINDOW_RECT);
virtual ~Window();
void setCentralWidget(Widget*);
void setContentsMargins(int, int, int, int);
void setResizable(bool);
void showAll();
void showNormal();
void showMinimized();
void showMaximized();
void setIcon(int);
void setLayout(Layout*) = delete;
bool isMinimized();
bool isMaximized();
Widget *centralWidget();
Layout *layout() = delete;
/* callback */
int onStateChanged(const FnVoidInt &callback);
virtual void disconnect(int) override;
protected:
virtual bool event(UINT, WPARAM, LPARAM, LRESULT*) override;
private:
Widget *m_centralWidget;
Margins m_contentMargins;
COLORREF m_brdColor;
int m_brdWidth,
m_resAreaWidth,
m_state;
double m_dpi;
FRAME m_frame;
bool m_borderless,
m_isResizable,
m_isMaximized,
m_isThemeActive,
m_isTaskbarAutoHideOn,
m_scaleChanged;
Size m_init_size;
std::unordered_map<int, FnVoidInt> m_state_callbacks;
};
#endif // WINDOW_H

View File

@ -1,520 +0,0 @@
/*
* (c) Copyright Ascensio System SIA 2010-2019
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "utils.h"
#include "baseutils.h"
#include "resource.h"
#include "translator.h"
#include <shlwapi.h>
#include <fstream>
#include <algorithm>
#include <Softpub.h>
#include <TlHelp32.h>
#include <Msi.h>
#include <ShlObj.h>
// #include <sstream>
#include "../../src/defines.h"
#include "../../src/prop/defines_p.h"
#define APP_REG_PATH "\\" REG_GROUP_KEY "\\" REG_APP_NAME
#define BIT123_LAYOUTRTL 0x08000000
#ifndef LOCALE_IREADINGLAYOUT
# define LOCALE_IREADINGLAYOUT 0x70
#endif
static void RegQueryStringValue(HKEY rootKey, LPCWSTR subkey, REGSAM advFlags, LPCWSTR value, wstring &result)
{
HKEY hKey;
if (RegOpenKeyExW(rootKey, subkey, 0, KEY_READ | advFlags, &hKey) == ERROR_SUCCESS) {
DWORD type = REG_SZ, cbData = 0;
if (SHGetValue(hKey, L"", value, &type, NULL, &cbData) == ERROR_SUCCESS) {
wchar_t *pvData = (wchar_t*)malloc(cbData);
if (SHGetValue(hKey, L"", value, &type, (void*)pvData, &cbData) == ERROR_SUCCESS)
result = pvData;
free(pvData);
}
RegCloseKey(hKey);
}
}
namespace NS_Utils
{
std::vector<wstring> cmd_args;
void parseCmdArgs(int argc, wchar_t *argv[])
{
for (int i = 0; i < argc; i++)
cmd_args.push_back(argv[i]);
}
bool cmdArgContains(const wstring &param)
{
auto len = param.length();
return std::any_of(cmd_args.cbegin(), cmd_args.cend(), [&param, len](const wstring &arg) {
return arg.find(param) == 0 && (len == arg.length() || arg[len] == L'=' || arg[len] == L':' || arg[len] == L'|');
});
}
wstring cmdArgValue(const wstring &param)
{
auto len = param.length();
for (const auto &arg : cmd_args) {
if (arg.find(param) == 0 && len < arg.length() && (arg[len] == L'=' || arg[len] == L':' || arg[len] == L'|'))
return arg.substr(len + 1);
}
return L"";
}
wstring GetLastErrorAsString(DWORD _errID)
{
DWORD errID = _errID != 0 ? _errID : ::GetLastError();
if (errID == 0)
return _T("");
LPTSTR msgBuff = NULL;
size_t size = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&msgBuff, 0, NULL);
wstring msg = _TR(LABEL_ERR_COMMON) + wstring(L" ") + std::to_wstring(errID);
if (size > 0) {
msg.append(L"\n" + wstring(msgBuff, (int)size));
LocalFree(msgBuff);
}
return msg;
}
void ShowMessage(wstring str, bool showError)
{
if (showError)
str += _T(" ") + GetLastErrorAsString();
wstring caption(_T(" "));
caption.append(_TR(CAPTION));
LCID lcid = MAKELCID(GetUserDefaultUILanguage(), SORT_DEFAULT);
UINT flags = MB_ICONERROR | MB_SERVICE_NOTIFICATION_NT3X | MB_SETFOREGROUND;
if (IsRtlLanguage(lcid))
flags |= MB_RTLREADING;
MessageBox(NULL, str.c_str(), caption.c_str(), flags);
}
int ShowTaskDialog(HWND parent, const wstring &msg, PCWSTR icon)
{
HWND fakeParent = NULL;
HMODULE hInst = GetModuleHandle(NULL);
if (!parent) {
WNDCLASS wc = {0};
wc.lpfnWndProc = DefWindowProc;
wc.hInstance = hInst;
wc.lpszClassName = L"FakeWindowClass";
RegisterClass(&wc);
fakeParent = CreateWindowEx(0, wc.lpszClassName, _TR(CAPTION), WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, hInst, NULL);
HICON hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MAINICON), IMAGE_ICON, 96, 96, LR_DEFAULTCOLOR | LR_SHARED);
SendMessage(fakeParent, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
SendMessage(fakeParent, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
ShowWindow(fakeParent, SW_SHOWMINIMIZED);
UpdateWindow(fakeParent);
parent = fakeParent;
}
int result = IDCANCEL;
wstring caption(_T(" "));
caption.append(_TR(CAPTION));
if (HMODULE lib = LoadLibrary(L"Comctl32")) {
HRESULT (WINAPI *_TaskDialog)(HWND, HINSTANCE, PCWSTR, PCWSTR, PCWSTR, TASKDIALOG_COMMON_BUTTON_FLAGS, PCWSTR, int*);
*(FARPROC*)&_TaskDialog = GetProcAddress(lib, "TaskDialog");
if (_TaskDialog)
_TaskDialog(parent, hInst, caption.c_str(), msg.c_str(), NULL, TDCBF_OK_BUTTON | TDCBF_CANCEL_BUTTON, icon, &result);
FreeLibrary(lib);
}
if (fakeParent)
DestroyWindow(fakeParent);
return result;
}
bool IsRtlLanguage(unsigned long lcid)
{
if (Utils::getWinVersion() >= Utils::WinVer::Win7) {
DWORD layout = 0;
if (GetLocaleInfo(lcid, LOCALE_IREADINGLAYOUT | LOCALE_RETURN_NUMBER, (LPWSTR)&layout, sizeof(layout)/sizeof(WCHAR)) > 0)
return layout == 1;
} else {
LOCALESIGNATURE lsig;
if (GetLocaleInfo(lcid, LOCALE_FONTSIGNATURE, (LPWSTR)&lsig, sizeof(lsig)/sizeof(WCHAR)) > 0)
return (lsig.lsUsb[3] & BIT123_LAYOUTRTL) != 0;
}
return false;
}
bool IsWin64()
{
#ifdef _WIN64
return true;
#else
BOOL wow64 = FALSE;
return IsWow64Process(GetCurrentProcess(), &wow64) && wow64;
#endif
}
bool IsAppInstalled(wstring &path, wstring *arch)
{
std::vector<REGSAM> flags{0};
if (NS_Utils::IsWin64()) {
#ifdef _WIN64
flags.push_back(KEY_WOW64_32KEY);
#else
flags.push_back(KEY_WOW64_64KEY);
#endif
}
wstring subkey(L"Software");
subkey += _T(APP_REG_PATH);
for (auto &flag : flags) {
RegQueryStringValue(HKEY_LOCAL_MACHINE, subkey.c_str(), flag, L"AppPath", path);
if (!path.empty() && (path.back() == L'\\' || path.back() == L'/'))
path.pop_back();
if (!path.empty() /*&& NS_File::fileExists(path + _T(APP_LAUNCH_NAME))*/) {
if (arch) {
#ifdef _WIN64
*arch = (flag == 0) ? L"x64" : L"x86";
#else
*arch = (flag == 0) ? L"x86" : L"x64";
#endif
}
return true;
}
}
return false;
}
bool checkAndWaitForAppClosure(HWND parent)
{
bool accept = true;
if (HWND app_hwnd = FindWindow(WINDOW_CLASS_NAME, NULL)) {
wstring msg(_TR(MSG_ERR_TRY_CLOSE_APP));
NS_Utils::Replace(msg, L"%1", _T(WINDOW_NAME));
accept = (IDOK == NS_Utils::ShowTaskDialog(parent, msg.c_str(), TD_INFORMATION_ICON));
if (accept) {
PostMessage(app_hwnd, UM_INSTALL_UPDATE, 0, 0);
Sleep(3000);
while(true) {
if ((app_hwnd = FindWindow(WINDOW_CLASS_NAME, NULL)) != nullptr) {
wstring msg(_TR(MSG_ERR_CLOSE_APP));
NS_Utils::Replace(msg, L"%1", _T(WINDOW_NAME));
int result = NS_Utils::ShowTaskDialog(parent, msg.c_str(), TD_WARNING_ICON);
if (result != IDOK) {
accept = false;
break;
}
} else {
break;
}
}
}
}
return accept;
}
void InstalledVerInfo(LPCWSTR value, wstring &name, wstring &arch)
{
if (!name.empty())
name.clear();
std::vector<REGSAM> flags{0};
if (NS_Utils::IsWin64()) {
#ifdef _WIN64
flags.push_back(KEY_WOW64_32KEY);
#else
flags.push_back(KEY_WOW64_64KEY);
#endif
}
for (auto &flag : flags) {
wstring subkey(L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\");
subkey += _T(REG_UNINST_KEY);
for (int i = 0; i < 2; i++) {
RegQueryStringValue(HKEY_LOCAL_MACHINE, subkey.c_str(), flag, value, name);
if (!name.empty()) {
if (arch.empty()) {
#ifdef _WIN64
arch = (flag == 0) ? L"x64" : L"x86";
#else
arch = (flag == 0) ? L"x86" : L"x64";
#endif
}
return;
}
subkey += L"_is1";
}
}
}
void Replace(wstring &str, const wstring &from, const wstring &to) {
if (from.empty())
return;
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::wstring::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length();
}
}
wstring MsiGetProperty(LPCWSTR prodCode, LPCWSTR propName)
{
DWORD buffSize = 0;
UINT res = MsiGetProductInfoW(prodCode, propName, NULL, &buffSize);
if ((res == ERROR_MORE_DATA || res == ERROR_SUCCESS) && buffSize > 0) {
++buffSize;
wchar_t *value = new wchar_t[buffSize];
if (MsiGetProductInfoW(prodCode, propName, value, &buffSize) == ERROR_SUCCESS) {
wstring propValue = value;
delete[] value;
return propValue;
}
delete[] value;
}
return wstring();
}
wstring MsiProductCode(const wstring &prodName)
{
DWORD ind = 0;
WCHAR prodCode[39];
while (MsiEnumProductsEx(NULL, NULL, MSIINSTALLCONTEXT_MACHINE, ind++, prodCode, NULL, NULL, NULL) == ERROR_SUCCESS) {
if (MsiGetProperty(prodCode, INSTALLPROPERTY_PRODUCTNAME) == prodName)
return prodCode;
}
return wstring();
}
}
namespace NS_File
{
DWORD runProcess(const wstring &fileName, const wstring &args, bool runAsAdmin, bool wait)
{
SHELLEXECUTEINFO shExInfo = {0};
shExInfo.cbSize = sizeof(shExInfo);
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE /*| SEE_MASK_FLAG_NO_UI*/;
shExInfo.hwnd = NULL;
shExInfo.lpVerb = runAsAdmin ? _T("runas") : _T("open");
shExInfo.lpFile = fileName.c_str();
shExInfo.lpParameters = args.c_str();
shExInfo.lpDirectory = NULL;
shExInfo.nShow = SW_HIDE;
shExInfo.hInstApp = NULL;
if (ShellExecuteEx(&shExInfo)) {
DWORD exitCode = 0;
if (wait && (WaitForSingleObject(shExInfo.hProcess, INFINITE) == WAIT_FAILED || !GetExitCodeProcess(shExInfo.hProcess, &exitCode)))
exitCode = GetLastError();
CloseHandle(shExInfo.hProcess);
return exitCode;
}
return GetLastError() | ERROR_LAUNCH;
}
// bool isProcessRunning(const wstring &fileName)
// {
// HANDLE snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
// if (snapShot == INVALID_HANDLE_VALUE)
// return false;
// PROCESSENTRY32 entry;
// entry.dwSize = sizeof(PROCESSENTRY32);
// if (!Process32First(snapShot, &entry)) {
// CloseHandle(snapShot);
// return false;
// }
// do {
// if (lstrcmpi(entry.szExeFile, fileName.c_str()) == 0) {
// CloseHandle(snapShot);
// return true;
// }
// } while (Process32Next(snapShot, &entry));
// CloseHandle(snapShot);
// return false;
// }
bool readFile(const wstring &filePath, list<wstring> &linesList)
{
std::wifstream file(filePath.c_str(), std::ios_base::in);
if (!file.is_open()) {
NS_Logger::WriteLog(L"An error occurred while opening:\n" + filePath);
return false;
}
wstring line;
while (std::getline(file, line))
linesList.push_back(line);
file.close();
return true;
}
bool fileExists(const wstring &filePath)
{
DWORD attr = ::GetFileAttributes(filePath.c_str());
return (attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY));
}
bool removeFile(const wstring &filePath)
{
return DeleteFile(filePath.c_str()) != 0;
}
bool removeDirRecursively(const wstring &dir)
{
WCHAR pFrom[_MAX_PATH + 1] = {0};
swprintf_s(pFrom, sizeof(pFrom)/sizeof(WCHAR), L"%s%c", dir.c_str(), L'\0');
SHFILEOPSTRUCT fop = {
NULL,
FO_DELETE,
pFrom,
NULL,
FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT,
FALSE,
0,
NULL
};
return SHFileOperation(&fop) == 0;
}
wstring fromNativeSeparators(const wstring &path)
{
wstring _path(path);
std::replace(_path.begin(), _path.end(), L'\\', L'/');
return _path;
}
wstring toNativeSeparators(const wstring &path)
{
wstring _path(path);
std::replace(_path.begin(), _path.end(), L'/', L'\\');
return _path;
}
wstring parentPath(const wstring &path)
{
auto delim = (path.size() > 2) ? path.find_last_of(_T("\\/"), path.size() - 2) : wstring::npos;
return (delim == wstring::npos) ? _T("") : path.substr(0, delim);
}
wstring tempPath()
{
TCHAR buff[MAX_PATH + 1] = {0};
DWORD res = ::GetTempPath(MAX_PATH + 1, buff);
if (res != 0) {
buff[res - 1] = '\0';
return fromNativeSeparators(buff);
}
return _T("");
}
wstring appPath()
{
TCHAR buff[MAX_PATH] = {0};
DWORD res = ::GetModuleFileName(NULL, buff, MAX_PATH);
return (res != 0) ? fromNativeSeparators(parentPath(buff)) : _T("");
}
wstring generateTmpFileName(const wstring &ext)
{
wstring uuid_tstr;
UUID uuid = {0};
RPC_WSTR wszUuid = NULL;
if (UuidCreate(&uuid) == RPC_S_OK && UuidToStringW(&uuid, &wszUuid) == RPC_S_OK) {
uuid_tstr = ((wchar_t*)wszUuid);
RpcStringFreeW(&wszUuid);
} else
uuid_tstr = L"00000000-0000-0000-0000-000000000000";
return NS_File::tempPath() + _T("/") + _T(FILE_PREFIX) + uuid_tstr + ext;
}
bool verifyEmbeddedSignature(const wstring &fileName)
{
WINTRUST_FILE_INFO wfi;
ZeroMemory(&wfi, sizeof(wfi));
wfi.cbStruct = sizeof(WINTRUST_FILE_INFO);
wfi.pcwszFilePath = fileName.c_str();
wfi.hFile = NULL;
wfi.pgKnownSubject = NULL;
GUID guidAction = WINTRUST_ACTION_GENERIC_VERIFY_V2;
WINTRUST_DATA wtd;
ZeroMemory(&wtd, sizeof(wtd));
wtd.cbStruct = sizeof(WINTRUST_DATA);
wtd.pPolicyCallbackData = NULL;
wtd.pSIPClientData = NULL;
wtd.dwUIChoice = WTD_UI_NONE;
wtd.fdwRevocationChecks = WTD_REVOKE_NONE;
wtd.dwUnionChoice = WTD_CHOICE_FILE;
wtd.dwStateAction = WTD_STATEACTION_VERIFY;
wtd.hWVTStateData = NULL;
wtd.pwszURLReference = NULL;
wtd.dwUIContext = 0;
wtd.pFile = &wfi;
return WinVerifyTrust(NULL, &guidAction, &wtd) == ERROR_SUCCESS;
}
wstring appDataPath()
{
TCHAR buff[MAX_PATH] = {0};
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, buff))) {
wstring path(buff);
path.append(_T(APP_REG_PATH));
path.append(_T("\\data"));
return path;
}
return _T("");
}
}
namespace NS_Logger
{
bool allow_write_log = false;
void AllowWriteLog()
{
allow_write_log = true;
}
void WriteLog(const wstring &log, bool showMessage)
{
if (allow_write_log) {
wstring filpPath(NS_File::appPath() + _T("/installer_log.txt"));
std::wofstream file(filpPath.c_str(), std::ios::app);
if (!file.is_open()) {
return;
}
file << log << std::endl;
file.close();
}
if (showMessage)
NS_Utils::ShowMessage(log);
}
}

View File

@ -1,94 +0,0 @@
/*
* (c) Copyright Ascensio System SIA 2010-2019
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#ifndef UTILS_H
#define UTILS_H
#include <Windows.h>
#include <string>
#include <list>
using std::string;
using std::wstring;
using std::to_wstring;
using std::list;
#define ERROR_LAUNCH 0x20000000
#define DEFAULT_ERROR_MESSAGE _T("An error occurred:\n") + \
wstring(_T(__FUNCTION__)) + _T(" Line: ") + to_wstring(__LINE__)
#define ADVANCED_ERROR_MESSAGE DEFAULT_ERROR_MESSAGE + \
_T(" ") + NS_Utils::GetLastErrorAsString()
namespace NS_Utils
{
void parseCmdArgs(int argc, wchar_t *argv[]);
bool cmdArgContains(const wstring &param);
wstring cmdArgValue(const wstring &param);
wstring GetLastErrorAsString(DWORD errID = 0);
void ShowMessage(wstring str, bool showError = false);
int ShowTaskDialog(HWND parent, const wstring &msg, PCWSTR icon);
bool IsRtlLanguage(unsigned long lcid);
bool IsWin64();
bool IsAppInstalled(wstring &path, wstring *arch = nullptr);
bool checkAndWaitForAppClosure(HWND parent = nullptr);
void InstalledVerInfo(LPCWSTR value, wstring &name, wstring &arch);
void Replace(wstring &str, const wstring &from, const wstring &to);
wstring MsiGetProperty(LPCWSTR prodCode, LPCWSTR propName);
wstring MsiProductCode(const wstring &prodName);
}
namespace NS_File
{
DWORD runProcess(const wstring &fileName, const wstring &args, bool runAsAdmin = false, bool wait = true);
// bool isProcessRunning(const wstring &fileName);
bool readFile(const wstring &filePath, list<wstring> &linesList);
bool fileExists(const wstring &filePath);
bool removeFile(const wstring &filePath);
bool removeDirRecursively(const wstring &dir);
wstring fromNativeSeparators(const wstring &path);
wstring toNativeSeparators(const wstring &path);
wstring parentPath(const wstring &path);
wstring tempPath();
wstring appPath();
wstring appDataPath();
wstring generateTmpFileName(const wstring &ext);
bool verifyEmbeddedSignature(const wstring &fileName);
}
namespace NS_Logger
{
void AllowWriteLog();
void WriteLog(const wstring &log, bool showMessage = false);
}
#endif // UTILS_H

View File

@ -1,84 +0,0 @@
/*
* (c) Copyright Ascensio System SIA 2010-2019
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#ifndef VERSION_H
#define VERSION_H
#define VER_STRINGIFY(d) #d
#define TO_STR(v) VER_STRINGIFY(v)
#ifdef VER_PRODUCT_VERSION
# define VER_FILEVERSION VER_PRODUCT_VERSION_COMMAS
# define VER_FILEVERSION_STR TO_STR(VER_PRODUCT_VERSION)
# define VER_PRODUCTVERSION VER_FILEVERSION
# define VER_PRODUCTVERSION_STR TO_STR(VER_PRODUCT_VERSION)
#else
# define VER_STR_LONG(mj,mn,b,r) VER_STRINGIFY(mj) "." VER_STRINGIFY(mn) "." VER_STRINGIFY(b) "." VER_STRINGIFY(r) "\0"
# define VER_STR_SHORT(mj,mn) VER_STRINGIFY(mj) "." VER_STRINGIFY(mn) "\0"
# define VER_NUM_MAJOR 5
# define VER_NUM_MINOR 2
# define VER_NUM_BUILD 46
# define VER_NUM_REVISION 24
# define VER_NUMBER VER_NUM_MAJOR,VER_NUM_MINOR,VER_NUM_BUILD,VER_NUM_REVISION
# define VER_STRING VER_STR_LONG(VER_NUM_MAJOR,VER_NUM_MINOR,VER_NUM_BUILD,VER_NUM_REVISION)
# define VER_STRING_SHORT VER_STR_SHORT(VER_NUM_MAJOR,VER_NUM_MINOR)
# define VER_FILEVERSION VER_NUMBER
# define VER_FILEVERSION_STR VER_STRING
# define VER_PRODUCTVERSION VER_FILEVERSION
# define VER_PRODUCTVERSION_STR VER_STRING_SHORT
#endif
#define VER_LANG_AND_CHARSET_STR "040904E4"
#define VER_LANG_ID 0x0409
#define VER_CHARSET_ID 1252
#define VER_FILEDESCRIPTION_STR "ONLYOFFICE Online Installer\0"
#define VER_PRODUCTNAME_STR "ONLYOFFICE Online Installer\0"
#define VER_COMPANYNAME_STR "Ascensio System SIA\0"
#define VER_LEGALCOPYRIGHT_STR "Copyright (C) Ascensio System SIA " TO_STR(COPYRIGHT_YEAR) ". All rights reserved\0"
#define VER_COMPANYDOMAIN_STR "www.onlyoffice.com\0"
#define VER_INTERNALNAME_STR "AppIcons\0"
#define VER_LEGALTRADEMARKS1_STR "All rights reserved\0"
#define VER_LEGALTRADEMARKS2_STR VER_LEGALTRADEMARKS1_STR
#define VER_ORIGINALFILENAME_STR "online-installer.exe\0"
#ifdef APP_USE_PRIVATE_ASSETS
# include "src/version_p.h"
#endif
#endif