mirror of
https://github.com/ONLYOFFICE/desktop-apps.git
synced 2026-02-10 18:05:16 +08:00
[win] remove online installer
This commit is contained in:
@ -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\\\")
|
||||
@ -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 |
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -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>
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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)();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
// }
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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();
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
// }
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -1,12 +0,0 @@
|
||||
#include "layout.h"
|
||||
|
||||
|
||||
Layout::Layout(Object *parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Layout::~Layout()
|
||||
{
|
||||
|
||||
}
|
||||
@ -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
|
||||
@ -1,22 +0,0 @@
|
||||
#include "layoutitem.h"
|
||||
|
||||
|
||||
LayoutItem::LayoutItem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
LayoutItem::~LayoutItem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Widget *LayoutItem::widget()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Layout *LayoutItem::layout()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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();
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
@ -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 ¶m)
|
||||
{
|
||||
auto len = param.length();
|
||||
return std::any_of(cmd_args.cbegin(), cmd_args.cend(), [¶m, 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 ¶m)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -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 ¶m);
|
||||
wstring cmdArgValue(const wstring ¶m);
|
||||
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
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user