Добавлена папка source в CristalDiskMark

This commit is contained in:
2026-05-29 13:04:54 +07:00
commit bdc2295ee4
240 changed files with 94035 additions and 0 deletions
@@ -0,0 +1,279 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "DiskMark.h"
#include "DiskMarkDlg.h"
#include "AboutDlg.h"
IMPLEMENT_DYNCREATE(CAboutDlg, CDialog)
CAboutDlg::CAboutDlg(CWnd* pParent /*=NULL*/)
: CDialogFx(CAboutDlg::IDD, pParent)
{
CMainDialogFx* p = (CMainDialogFx*)pParent;
m_ZoomType = p->GetZoomType();
m_FontScale = p->GetFontScale();
m_FontRatio = p->GetFontRatio();
m_FontFace = p->GetFontFace();
m_FontRender = p->GetFontRender();
m_CurrentLangPath = p->GetCurrentLangPath();
m_DefaultLangPath = p->GetDefaultLangPath();
m_ThemeDir = p->GetThemeDir();
m_CurrentTheme = p->GetCurrentTheme();
m_DefaultTheme = p->GetDefaultTheme();
m_Ini = p->GetIniPath();
#ifdef SUISHO_SHIZUKU_SUPPORT
m_BackgroundName = L"About";
#else
m_BackgroundName = L"";
#endif
}
CAboutDlg::~CAboutDlg()
{
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogFx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LOGO, m_CtrlLogo);
DDX_Control(pDX, IDC_PROJECT_SITE_1, m_CtrlProjectSite1);
DDX_Control(pDX, IDC_PROJECT_SITE_2, m_CtrlProjectSite2);
DDX_Control(pDX, IDC_PROJECT_SITE_3, m_CtrlProjectSite3);
DDX_Control(pDX, IDC_PROJECT_SITE_4, m_CtrlProjectSite4);
DDX_Control(pDX, IDC_PROJECT_SITE_5, m_CtrlProjectSite5);
DDX_Control(pDX, IDC_VERSION, m_CtrlVersion);
DDX_Control(pDX, IDC_LICENSE, m_CtrlLicense);
DDX_Control(pDX, IDC_RELEASE, m_CtrlRelease);
DDX_Control(pDX, IDC_COPYRIGHT1, m_CtrlCopyright1);
DDX_Control(pDX, IDC_COPYRIGHT2, m_CtrlCopyright2);
DDX_Control(pDX, IDC_COPYRIGHT3, m_CtrlCopyright3);
DDX_Control(pDX, IDC_EDITION, m_CtrlEdition);
}
BOOL CAboutDlg::OnInitDialog()
{
CDialogFx::OnInitDialog();
SetWindowTitle(i18n(L"WindowTitle", L"ABOUT"));
m_bShowWindow = TRUE;
m_CtrlVersion.SetWindowTextW(PRODUCT_NAME L" " PRODUCT_VERSION);
m_CtrlEdition.SetWindowTextW(PRODUCT_EDITION);
m_CtrlRelease.SetWindowTextW(L"Release: " PRODUCT_RELEASE);
m_CtrlCopyright1.SetWindowTextW(PRODUCT_COPYRIGHT_1);
m_CtrlCopyright2.SetWindowTextW(PRODUCT_COPYRIGHT_2);
m_CtrlCopyright3.SetWindowTextW(PRODUCT_COPYRIGHT_3);
m_CtrlLicense.SetWindowTextW(PRODUCT_LICENSE);
UpdateDialogSize();
CenterWindow();
ShowWindow(SW_SHOW);
return TRUE;
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialogFx)
ON_BN_CLICKED(IDC_LOGO, &CAboutDlg::OnLogo)
ON_BN_CLICKED(IDC_LICENSE, &CAboutDlg::OnLicense)
ON_BN_CLICKED(IDC_VERSION, &CAboutDlg::OnVersion)
#ifdef SUISHO_SHIZUKU_SUPPORT
ON_BN_CLICKED(IDC_PROJECT_SITE_1, &CAboutDlg::OnProjectSite1)
ON_BN_CLICKED(IDC_PROJECT_SITE_2, &CAboutDlg::OnProjectSite2)
ON_BN_CLICKED(IDC_PROJECT_SITE_3, &CAboutDlg::OnProjectSite3)
ON_BN_CLICKED(IDC_PROJECT_SITE_4, &CAboutDlg::OnProjectSite4)
ON_BN_CLICKED(IDC_PROJECT_SITE_5, &CAboutDlg::OnProjectSite5)
#endif
END_MESSAGE_MAP()
void CAboutDlg::UpdateDialogSize()
{
CDialogFx::UpdateDialogSize();
m_bHighContrast = FALSE;
ChangeZoomType(m_ZoomType);
SetClientSize(SIZE_X, SIZE_Y, m_ZoomRatio);
UpdateBackground(TRUE, m_bDarkMode);
#ifdef SUISHO_AOI_SUPPORT
m_CtrlLogo.InitControl(32, 484, 128, 144, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlSecretVoice.InitControl(392, 288, 60, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite1.InitControl(184, 508, 148, 16, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite2.InitControl(244, 540, 108, 16, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite3.InitControl(232, 556, 180, 16, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite4.InitControl(244, 576, 120, 16, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite5.InitControl(0, 0, 0, 0, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlSecretVoice.SetHandCursor();
m_CtrlProjectSite1.SetHandCursor();
m_CtrlProjectSite2.SetHandCursor();
m_CtrlProjectSite3.SetHandCursor();
m_CtrlProjectSite4.SetHandCursor();
m_CtrlProjectSite5.SetHandCursor();
#elif MSI_MEI_SUPPORT
m_CtrlProjectSite1.InitControl(24, 460, 348, 128, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite2.InitControl(168, 604, 36, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite3.InitControl(332, 604, 104, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite4.InitControl(20, 20, 120, 40, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite5.InitControl(464, 604, 168, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlLogo.InitControl(80, 64, 128, 128, m_ZoomRatio, m_hPal, &m_BkDC, IP(L"Logo"), 1, BS_CENTER, OwnerDrawImage, FALSE, FALSE, FALSE);
m_CtrlProjectSite1.SetHandCursor();
m_CtrlProjectSite2.SetHandCursor();
m_CtrlProjectSite3.SetHandCursor();
m_CtrlProjectSite4.SetHandCursor();
m_CtrlProjectSite5.SetHandCursor();
#elif SUISHO_SHIZUKU_SUPPORT
m_CtrlProjectSite1.InitControl(64, 372, 140, 16, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite2.InitControl(64, 416, 148, 16, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite3.InitControl(64, 432, 184, 16, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite4.InitControl(40, 460, 208, 16, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlProjectSite5.InitControl(92, 504, 432, 124, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlLogo.InitControl(80, 12, 128, 128, m_ZoomRatio, m_hPal, &m_BkDC, IP(L"Logo"), 1, BS_CENTER, OwnerDrawImage, FALSE, FALSE, FALSE);
m_CtrlProjectSite1.SetHandCursor();
m_CtrlProjectSite2.SetHandCursor();
m_CtrlProjectSite3.SetHandCursor();
m_CtrlProjectSite4.SetHandCursor();
m_CtrlProjectSite5.SetHandCursor();
#else
m_CtrlLogo.InitControl(20, 20, 128, 128, m_ZoomRatio, m_hPal, &m_BkDC, IP(L"Logo"), 1, BS_CENTER, OwnerDrawImage, FALSE, FALSE, FALSE);
m_CtrlProjectSite1.ShowWindow(SW_HIDE);
m_CtrlProjectSite2.ShowWindow(SW_HIDE);
m_CtrlProjectSite3.ShowWindow(SW_HIDE);
m_CtrlProjectSite4.ShowWindow(SW_HIDE);
m_CtrlProjectSite5.ShowWindow(SW_HIDE);
#endif
m_CtrlLogo.SetHandCursor();
#ifdef MSI_MEI_SUPPORT
COLORREF fontColor = RGB(255, 255, 255);
#else
COLORREF fontColor = RGB(0, 0, 0);
#endif
m_CtrlVersion.SetFontEx(m_FontFace, 20, 20, m_ZoomRatio, m_FontRatio, fontColor, FW_BOLD, m_FontRender);
m_CtrlEdition.SetFontEx(m_FontFace, 20, 20, m_ZoomRatio, m_FontRatio, fontColor, FW_BOLD, m_FontRender);
m_CtrlRelease.SetFontEx(m_FontFace, 16, 16, m_ZoomRatio, m_FontRatio, fontColor, FW_NORMAL, m_FontRender);
m_CtrlCopyright1.SetFontEx(m_FontFace, 16, 16, m_ZoomRatio, m_FontRatio, fontColor, FW_NORMAL, m_FontRender);
m_CtrlCopyright2.SetFontEx(m_FontFace, 16, 16, m_ZoomRatio, m_FontRatio, fontColor, FW_NORMAL, m_FontRender);
m_CtrlCopyright3.SetFontEx(m_FontFace, 16, 16, m_ZoomRatio, m_FontRatio, fontColor, FW_NORMAL, m_FontRender);
m_CtrlLicense.SetFontEx(m_FontFace, 16, 16, m_ZoomRatio, m_FontRatio, fontColor, FW_NORMAL, m_FontRender);
m_CtrlVersion.SetHandCursor();
m_CtrlLicense.SetHandCursor();
#ifdef SUISHO_AOI_SUPPORT
m_CtrlVersion.InitControl(0, 136, 288, 28, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlEdition.InitControl(0, 164, 288, 28, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlRelease.InitControl(0, 200, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlCopyright1.InitControl(0, 220, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlCopyright2.InitControl(0, 240, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlCopyright3.InitControl(0, 260, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlLicense.InitControl(0, 280, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
#elif MSI_MEI_SUPPORT
m_CtrlVersion.InitControl(0, 204, 288, 28, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlEdition.InitControl(0, 232, 288, 28, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlRelease.InitControl(0, 268, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlCopyright1.InitControl(0, 288, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlCopyright2.InitControl(0, 308, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlCopyright3.InitControl(0, 328, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlLicense.InitControl(0, 0, 0, 0, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
#elif SUISHO_SHIZUKU_SUPPORT
m_CtrlVersion.InitControl(0, 152, 288, 28, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlEdition.InitControl(0, 180, 288, 28, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlRelease.InitControl(0, 216, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlCopyright1.InitControl(0, 236, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlCopyright2.InitControl(0, 256, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlCopyright3.InitControl(0, 276, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
m_CtrlLicense.InitControl(0, 296, 288, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, FALSE, FALSE, FALSE);
#else
m_CtrlVersion.InitControl(160, 12, 364, 28, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_CtrlEdition.InitControl(160, 40, 364, 28, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_CtrlRelease.InitControl(160, 76, 364, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_CtrlCopyright1.InitControl(160, 96, 364, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_CtrlCopyright2.InitControl(160, 116, 364, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_CtrlCopyright3.InitControl(160, 136, 364, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_CENTER, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_CtrlLicense.InitControl(160, 136, 364, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_CtrlCopyright3.ShowWindow(SW_HIDE);
#endif
Invalidate();
}
void CAboutDlg::OnLogo()
{
if (GetUserDefaultLCID() == 0x0411)// Japanese
{
OpenUrl(URL_MAIN_JA);
}
else // Other Language
{
OpenUrl(URL_MAIN_EN);
}
}
void CAboutDlg::OnVersion()
{
if (GetUserDefaultLCID() == 0x0411)// Japanese
{
OpenUrl(URL_VERSION_JA);
}
else // Other Language
{
OpenUrl(URL_VERSION_EN);
}
}
void CAboutDlg::OnLicense()
{
if (GetUserDefaultLCID() == 0x0411)// Japanese
{
OpenUrl(URL_LICENSE_JA);
}
else // Other Language
{
OpenUrl(URL_LICENSE_EN);
}
}
#ifdef SUISHO_SHIZUKU_SUPPORT
void CAboutDlg::OnProjectSite1()
{
OpenUrl(URL_PROJECT_SITE_1);
}
void CAboutDlg::OnProjectSite2()
{
OpenUrl(URL_PROJECT_SITE_2);
}
void CAboutDlg::OnProjectSite3()
{
OpenUrl(URL_PROJECT_SITE_3);
}
void CAboutDlg::OnProjectSite4()
{
OpenUrl(URL_PROJECT_SITE_4);
}
void CAboutDlg::OnProjectSite5()
{
OpenUrl(URL_PROJECT_SITE_5);
}
#endif
@@ -0,0 +1,67 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "DialogFx.h"
#include "StaticFx.h"
#include "ButtonFx.h"
class CAboutDlg : public CDialogFx
{
DECLARE_DYNCREATE(CAboutDlg)
#ifdef SUISHO_AOI_SUPPORT
static const int SIZE_X = 640;
static const int SIZE_Y = 640;
#elif MSI_MEI_SUPPORT
static const int SIZE_X = 640;
static const int SIZE_Y = 640;
#elif SUISHO_SHIZUKU_SUPPORT
static const int SIZE_X = 640;
static const int SIZE_Y = 660;
#else
static const int SIZE_X = 540;
static const int SIZE_Y = 168;
#endif
public:
CAboutDlg(CWnd* pParent = NULL);
virtual ~CAboutDlg();
enum { IDD = IDD_ABOUT };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
virtual BOOL OnInitDialog();
virtual void UpdateDialogSize();
DECLARE_MESSAGE_MAP()
afx_msg void OnLogo();
afx_msg void OnVersion();
afx_msg void OnLicense();
afx_msg void OnProjectSite1();
afx_msg void OnProjectSite2();
afx_msg void OnProjectSite3();
afx_msg void OnProjectSite4();
afx_msg void OnProjectSite5();
CButtonFx m_CtrlLogo;
CButtonFx m_CtrlSecretVoice;
CButtonFx m_CtrlProjectSite1;
CButtonFx m_CtrlProjectSite2;
CButtonFx m_CtrlProjectSite3;
CButtonFx m_CtrlProjectSite4;
CButtonFx m_CtrlProjectSite5;
CButtonFx m_CtrlVersion;
CButtonFx m_CtrlLicense;
CStaticFx m_CtrlEdition;
CStaticFx m_CtrlRelease;
CStaticFx m_CtrlCopyright1;
CStaticFx m_CtrlCopyright2;
CStaticFx m_CtrlCopyright3;
};
@@ -0,0 +1,22 @@
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<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 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>True/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
@@ -0,0 +1,935 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "DiskMark.h"
#include "DiskMarkDlg.h"
#include "DiskBench.h"
#include <afxmt.h>
#include <winioctl.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
#pragma warning(disable : 4996)
static CString TestFilePath;
static CString TestFileDir;
static CString DiskSpdExe;
static HANDLE hFile;
static int DiskTestCount;
static UINT64 DiskTestSize;
static int BenchType[9];
static int BenchSize[9];
static int BenchQueues[9];
static int BenchThreads[9];
// static int Affinity;
static BOOL MixMode;
static int MixRatio;
static void ShowErrorMessage(CString message);
static void Interval(void* dlg);
static BOOL Init(void* dlg);
static void DiskSpd(void* dlg, DISK_SPD_CMD cmd);
static UINT Exit(void* dlg);
static void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime);
static volatile BOOL WaitFlag;
#define DISK_SPD_EXE_32 L"CdmResource\\diskspd\\diskspd32.exe"
#define DISK_SPD_EXE_64 L"CdmResource\\diskspd\\diskspd64.exe"
#define DISK_SPD_EXE_32_LEGACY L"CdmResource\\diskspd\\diskspd32L.exe"
#define DISK_SPD_EXE_64_LEGACY L"CdmResource\\diskspd\\diskspd64L.exe"
#define DISK_SPD_EXE_ARM32 L"CdmResource\\diskspd\\diskspdA32.exe"
#define DISK_SPD_EXE_ARM64 L"CdmResource\\diskspd\\diskspdA64.exe"
PROCESS_INFORMATION pi;
int ExecAndWait(TCHAR *pszCmd, BOOL bNoWindow, double *latency)
{
DWORD Code = 0;
BOOL bSuccess;
STARTUPINFO si;
memset(&si, 0, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
if (bNoWindow) {
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
}
CString name;
name.Format(L"CrystalDiskMark%08X", GetCurrentProcessId());
auto size = 8;
HANDLE hSharedMemory = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, NULL, size, name.GetString());
if (hSharedMemory != NULL)
{
auto pMemory = (double*)MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, NULL, NULL, size);
if (pMemory != NULL)
{
bSuccess = CreateProcess(NULL, pszCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (bSuccess != TRUE)
{
UnmapViewOfFile(pMemory);
CloseHandle(hSharedMemory);
return 0;
}
WaitForInputIdle(pi.hProcess, INFINITE);
WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &Code);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
pi.hProcess = NULL;
*latency = (double)*pMemory * 1000; // milli sec to micro sec
UnmapViewOfFile(pMemory);
CloseHandle(hSharedMemory);
}
}
return Code;
}
void ShowErrorMessage(CString message)
{
DWORD lastErrorCode = GetLastError();
CString errorMessage;
LPVOID lpMessageBuffer;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, lastErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMessageBuffer, 0, NULL);
errorMessage.Format(L"0x%08X:%s", lastErrorCode, (LPTSTR) lpMessageBuffer);
AfxMessageBox(message + L"\r\n" + errorMessage);
LocalFree( lpMessageBuffer );
}
void Interval(void* dlg)
{
int intervalTime = ((CDiskMarkDlg*) dlg)->m_IntervalTime;
CString title;
for (int i = 0; i < intervalTime; i++)
{
if (!((CDiskMarkDlg*) dlg)->m_DiskBenchStatus)
{
return;
}
title.Format(L"Interval Time %d/%d sec", i, intervalTime);
::PostMessage(((CDiskMarkDlg*) dlg)->GetSafeHwnd(), WM_UPDATE_MESSAGE, (WPARAM) &title, 0);
Sleep(1000);
}
}
UINT ExecDiskBenchAll(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if(Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_0); Interval(dlg);
DiskSpd(dlg, TEST_READ_1); Interval(dlg);
DiskSpd(dlg, TEST_READ_2); Interval(dlg);
DiskSpd(dlg, TEST_READ_3);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_0); Interval(dlg);
DiskSpd(dlg, TEST_WRITE_1); Interval(dlg);
DiskSpd(dlg, TEST_WRITE_2); Interval(dlg);
DiskSpd(dlg, TEST_WRITE_3);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_0); Interval(dlg);
DiskSpd(dlg, TEST_MIX_1); Interval(dlg);
DiskSpd(dlg, TEST_MIX_2); Interval(dlg);
DiskSpd(dlg, TEST_MIX_3);
}
#endif
}
return Exit(dlg);
}
UINT ExecDiskBenchAllPeak(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_4); Interval(dlg);
DiskSpd(dlg, TEST_READ_5);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_4); Interval(dlg);
DiskSpd(dlg, TEST_WRITE_5);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_4); Interval(dlg);
DiskSpd(dlg, TEST_MIX_5);
}
#endif
}
return Exit(dlg);
}
UINT ExecDiskBenchAllReal(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_6); Interval(dlg);
DiskSpd(dlg, TEST_READ_7);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_6); Interval(dlg);
DiskSpd(dlg, TEST_WRITE_7);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_6); Interval(dlg);
DiskSpd(dlg, TEST_MIX_7);
}
#endif
}
return Exit(dlg);
}
UINT ExecDiskBenchAllDemo(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_8);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_8);
}
}
return Exit(dlg);
}
UINT ExecDiskBench0(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_0);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_0);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_0);
}
#endif
}
return Exit(dlg);
}
UINT ExecDiskBench1(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_1);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_1);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_1);
}
#endif
}
return Exit(dlg);
}
UINT ExecDiskBench2(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_2);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_2);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_2);
}
#endif
}
return Exit(dlg);
}
UINT ExecDiskBench3(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_3);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_3);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_3);
}
#endif
}
return Exit(dlg);
}
UINT ExecDiskBench4(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_4);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_4);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_4);
}
#endif
}
return Exit(dlg);
}
UINT ExecDiskBench5(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_5);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_5);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_5);
}
#endif
}
return Exit(dlg);
}
UINT ExecDiskBench6(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_6);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_6);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_6);
}
#endif
}
return Exit(dlg);
}
UINT ExecDiskBench7(LPVOID dlg)
{
int benchmark = ((CDiskMarkDlg*)dlg)->m_Benchmark;
if (Init(dlg))
{
if (benchmark & BENCHMARK_READ)
{
DiskSpd(dlg, TEST_READ_7);
}
if ((benchmark & BENCHMARK_READ) && (benchmark & BENCHMARK_WRITE))
{
Interval(dlg);
}
if (benchmark & BENCHMARK_WRITE)
{
DiskSpd(dlg, TEST_WRITE_7);
}
#ifdef MIX_MODE
if (MixMode)
{
Interval(dlg);
DiskSpd(dlg, TEST_MIX_7);
}
#endif
}
return Exit(dlg);
}
BOOL Init(void* dlg)
{
BOOL FlagArc;
BOOL result;
static CString cstr;
TCHAR drive;
ULARGE_INTEGER freeBytesAvailableToCaller;
ULARGE_INTEGER totalNumberOfBytes;
ULARGE_INTEGER totalNumberOfFreeBytes;
// Init m_Ini
TCHAR *ptrEnd;
TCHAR temp[MAX_PATH];
::GetModuleFileName(NULL, temp, MAX_PATH);
if ((ptrEnd = _tcsrchr(temp, '\\')) != NULL)
{
*ptrEnd = '\0';
}
pi.hProcess = NULL;
#ifdef _M_ARM
DiskSpdExe.Format(L"%s\\%s", temp, DISK_SPD_EXE_ARM32);
#elif _M_ARM64
DiskSpdExe.Format(L"%s\\%s", temp, DISK_SPD_EXE_ARM64);
#elif _M_X64
if(IsWin8orLater())
{
DiskSpdExe.Format(L"%s\\%s", temp, DISK_SPD_EXE_64);
}
else
{
DiskSpdExe.Format(L"%s\\%s", temp, DISK_SPD_EXE_64_LEGACY);
}
#else
if (IsWin8orLater())
{
DiskSpdExe.Format(L"%s\\%s", temp, DISK_SPD_EXE_32);
}
else
{
DiskSpdExe.Format(L"%s\\%s", temp, DISK_SPD_EXE_32_LEGACY);
}
#endif
if (! IsFileExist(DiskSpdExe))
{
AfxMessageBox(((CDiskMarkDlg*) dlg)->m_MesDiskSpdNotFound);
((CDiskMarkDlg*) dlg)->m_DiskBenchStatus = FALSE;
return FALSE;
}
DiskTestCount = ((CDiskMarkDlg*) dlg)->m_IndexTestCount + 1;
CString testSize = ((CDiskMarkDlg*)dlg)->m_ValueTestSize;
if (testSize.Find(L"M") == -1) // GiB
{
DiskTestSize = (UINT64)_tstoi(testSize) * 1024;
}
else // MiB
{
DiskTestSize = (UINT64)_tstoi(testSize);
}
for (int i = 0; i < 9; i++)
{
BenchType[i] = ((CDiskMarkDlg*)dlg)->m_BenchType[i];
BenchSize[i] = ((CDiskMarkDlg*)dlg)->m_BenchSize[i];
BenchQueues[i] = ((CDiskMarkDlg*)dlg)->m_BenchQueues[i];
BenchThreads[i] = ((CDiskMarkDlg*)dlg)->m_BenchThreads[i];
}
MixMode = ((CDiskMarkDlg*)dlg)->m_MixMode;
MixRatio = ((CDiskMarkDlg*)dlg)->m_MixRatio;
CString RootPath;
if(((CDiskMarkDlg*)dlg)->m_MaxIndexTestDrive != ((CDiskMarkDlg*)dlg)->m_IndexTestDrive)
{
drive = ((CDiskMarkDlg*)dlg)->m_ValueTestDrive.GetAt(0);
cstr.Format(L"%C:\\", drive);
GetDiskFreeSpaceEx(cstr, &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes);
if (totalNumberOfBytes.QuadPart < ((ULONGLONG)8 * 1024 * 1024 * 1024)) // < 8 GB
{
((CDiskMarkDlg*)dlg)->m_TestDriveInfo.Format(L"%C: %.1f%% (%.1f/%.1f MiB)", drive,
(double)(totalNumberOfBytes.QuadPart - totalNumberOfFreeBytes.QuadPart) / (double)totalNumberOfBytes.QuadPart * 100,
(totalNumberOfBytes.QuadPart - totalNumberOfFreeBytes.QuadPart) / 1024 / 1024.0,
totalNumberOfBytes.QuadPart / 1024 / 1024.0);
}
else
{
((CDiskMarkDlg*)dlg)->m_TestDriveInfo.Format(L"%C: %.1f%% (%.1f/%.1f GiB)", drive,
(double)(totalNumberOfBytes.QuadPart - totalNumberOfFreeBytes.QuadPart) / (double)totalNumberOfBytes.QuadPart * 100,
(totalNumberOfBytes.QuadPart - totalNumberOfFreeBytes.QuadPart) / 1024 / 1024 / 1024.0,
totalNumberOfBytes.QuadPart / 1024 / 1024 / 1024.0);
}
RootPath.Format(L"%c:\\", drive);
}
else
{
RootPath = ((CDiskMarkDlg*)dlg)->m_TestTargetPath;
RootPath += L"\\";
}
TestFileDir.Format(L"%sCrystalDiskMark%08X", (LPTSTR)RootPath.GetString(), timeGetTime());
CreateDirectory(TestFileDir, NULL);
TestFilePath.Format(L"%s\\CrystalDiskMark%08X.tmp", (LPTSTR)TestFileDir.GetString(), timeGetTime());
DWORD FileSystemFlags;
GetVolumeInformation(RootPath, NULL, NULL, NULL, NULL, &FileSystemFlags, NULL, NULL);
if(FileSystemFlags & FS_VOL_IS_COMPRESSED)
{
FlagArc = TRUE;
}
else
{
FlagArc = FALSE;
}
// Check Disk Capacity //
OSVERSIONINFO osVersionInfo;
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osVersionInfo);
ULARGE_INTEGER FreeBytesAvailableToCaller, TotalNumberOfBytes, TotalNumberOfFreeBytes;
GetDiskFreeSpaceEx(RootPath, &FreeBytesAvailableToCaller, &TotalNumberOfBytes, &TotalNumberOfFreeBytes);
if(DiskTestSize > TotalNumberOfFreeBytes.QuadPart / 1024 / 1024 )
{
AfxMessageBox(((CDiskMarkDlg*)dlg)->m_MesDiskCapacityError);
((CDiskMarkDlg*)dlg)->m_DiskBenchStatus = FALSE;
return FALSE;
}
CString title;
title.Format(L"Preparing... Create Test File");
::PostMessage(((CDiskMarkDlg*)dlg)->GetSafeHwnd(), WM_UPDATE_MESSAGE, (WPARAM)& title, 0);
// Preapare Test File
hFile = ::CreateFile(TestFilePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
AfxMessageBox(((CDiskMarkDlg*)dlg)->m_MesDiskCreateFileError);
((CDiskMarkDlg*)dlg)->m_DiskBenchStatus = FALSE;
return FALSE;
}
// Set End Of File to prevent fragmentation of test file
LARGE_INTEGER nFileSize;
nFileSize.QuadPart = 1024 * 1024 * DiskTestSize;
LARGE_INTEGER nStart;
nStart.QuadPart = 0;
SetFilePointerEx(hFile, nFileSize, NULL, FILE_BEGIN);
SetEndOfFile(hFile);
SetFilePointerEx(hFile, nStart, NULL, FILE_BEGIN);
// COMPRESSION_FORMAT_NONE
USHORT lpInBuffer = COMPRESSION_FORMAT_NONE;
DWORD lpBytesReturned = 0;
DeviceIoControl(hFile, FSCTL_SET_COMPRESSION, (LPVOID) &lpInBuffer,
sizeof(USHORT), NULL, 0, (LPDWORD)&lpBytesReturned, NULL);
// Fill Test Data
char* buf = NULL;
int BufSize;
int Loop;
int i;
DWORD writesize;
BufSize = 1024 * 1024;
Loop = (int)DiskTestSize;
buf = (char*) VirtualAlloc(NULL, BufSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (buf == NULL)
{
AfxMessageBox(L"Failed VirtualAlloc().");
((CDiskMarkDlg*) dlg)->m_DiskBenchStatus = FALSE;
return FALSE;
}
if (((CDiskMarkDlg*) dlg)->m_TestData == TEST_DATA_ALL0X00)
{
for (i = 0; i < BufSize; i++)
{
buf[i] = 0;
}
}
else
{
// Compatible with DiskSpd
for (i = 0; i < BufSize; i++)
{
buf[i] = (char) (rand() % 256);
}
}
for (i = 0; i < Loop; i++)
{
if (((CDiskMarkDlg*) dlg)->m_DiskBenchStatus)
{
result = WriteFile(hFile, buf, BufSize, &writesize, NULL);
}
else
{
CloseHandle(hFile);
VirtualFree(buf, 0, MEM_RELEASE);
((CDiskMarkDlg*) dlg)->m_DiskBenchStatus = FALSE;
return FALSE;
}
}
VirtualFree(buf, 0, MEM_RELEASE);
CloseHandle(hFile);
return TRUE;
}
void CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
if(idEvent == TIMER_ID)
{
WaitFlag = FALSE;
KillTimer(hwnd, idEvent);
}
}
UINT Exit(void* dlg)
{
DeleteFile(TestFilePath);
RemoveDirectory(TestFileDir);
static CString cstr;
cstr = L"";
if(((CDiskMarkDlg*)dlg)->m_TestData == TEST_DATA_ALL0X00)
{
cstr = ALL_0X00_0FILL;
}
::PostMessage(((CDiskMarkDlg*)dlg)->GetSafeHwnd(), WM_UPDATE_MESSAGE, NULL, (LPARAM)&cstr);
::PostMessage(((CDiskMarkDlg*)dlg)->GetSafeHwnd(), WM_EXIT_BENCHMARK, 0, 0);
((CDiskMarkDlg*)dlg)->m_DiskBenchStatus = FALSE;
((CDiskMarkDlg*)dlg)->m_WinThread = NULL;
return 0;
}
void DiskSpd(void* dlg, DISK_SPD_CMD cmd)
{
static CString cstr;
double *maxScore = NULL;
double *minLatency = NULL;
CString command;
CString title;
CString option;
CString bufOption;
int duration = 5;
int index = 0;
int j = 0;
if (!((CDiskMarkDlg*) dlg)->m_DiskBenchStatus)
{
return;
}
if (((CDiskMarkDlg*) dlg)->m_TestData == TEST_DATA_ALL0X00)
{
bufOption += L" -Z";
}
else
{
switch (cmd)
{
case TEST_WRITE_0:
case TEST_WRITE_1:
case TEST_WRITE_2:
case TEST_WRITE_3:
case TEST_WRITE_4:
case TEST_WRITE_5:
case TEST_WRITE_6:
case TEST_WRITE_7:
case TEST_WRITE_8:
index = cmd - TEST_WRITE_0;
cstr.Format(L" -Z%dK", BenchSize[index]);
bufOption += cstr;
break;
case TEST_MIX_0:
case TEST_MIX_1:
case TEST_MIX_2:
case TEST_MIX_3:
case TEST_MIX_4:
case TEST_MIX_5:
case TEST_MIX_6:
case TEST_MIX_7:
case TEST_MIX_8:
index = cmd - TEST_MIX_0;
cstr.Format(L" -Z%dK", BenchSize[index]);
bufOption += cstr;
break;
}
}
switch (cmd)
{
case TEST_READ_0:
case TEST_READ_1:
case TEST_READ_2:
case TEST_READ_3:
case TEST_READ_4:
case TEST_READ_5:
case TEST_READ_6:
case TEST_READ_7:
case TEST_READ_8:
index = cmd - TEST_READ_0;
if (BenchType[index])
{
title.Format(L"Random Read");
option.Format(L"-b%dK -o%d -t%d -W0 -S -w0 -r", BenchSize[index], BenchQueues[index], BenchThreads[index]);
}
else
{
title.Format(L"Sequential Read");
option.Format(L"-b%dK -o%d -t%d -W0 -S -w0", BenchSize[index], BenchQueues[index], BenchThreads[index]);
}
maxScore = &(((CDiskMarkDlg*) dlg)->m_ReadScore[index]);
minLatency = &(((CDiskMarkDlg*)dlg)->m_ReadLatency[index]);
break;
case TEST_WRITE_0:
case TEST_WRITE_1:
case TEST_WRITE_2:
case TEST_WRITE_3:
case TEST_WRITE_4:
case TEST_WRITE_5:
case TEST_WRITE_6:
case TEST_WRITE_7:
case TEST_WRITE_8:
index = cmd - TEST_WRITE_0;
if (BenchType[index])
{
title.Format(L"Random Write");
option.Format(L"-b%dK -o%d -t%d -W0 -S -w100 -r", BenchSize[index], BenchQueues[index], BenchThreads[index]);
}
else
{
title.Format(L"Sequential Write");
option.Format(L"-b%dK -o%d -t%d -W0 -S -w100", BenchSize[index], BenchQueues[index], BenchThreads[index]);
}
option += bufOption;
maxScore = &(((CDiskMarkDlg*)dlg)->m_WriteScore[index]);
minLatency = &(((CDiskMarkDlg*)dlg)->m_WriteLatency[index]);
break;
#ifdef MIX_MODE
case TEST_MIX_0:
case TEST_MIX_1:
case TEST_MIX_2:
case TEST_MIX_3:
case TEST_MIX_4:
case TEST_MIX_5:
case TEST_MIX_6:
case TEST_MIX_7:
case TEST_MIX_8:
index = cmd - TEST_MIX_0;
if (BenchType[index])
{
title.Format(L"Random Mix");
option.Format(L"-b%dK -o%d -t%d -W0 -S -w%d -r", BenchSize[index], BenchQueues[index], BenchThreads[index], MixRatio);
}
else
{
title.Format(L"Sequential Mix");
option.Format(L"-b%dK -o%d -t%d -W0 -S -w%d", BenchSize[index], BenchQueues[index], BenchThreads[index], MixRatio);
}
option += bufOption;
maxScore = &(((CDiskMarkDlg*)dlg)->m_MixScore[index]);
minLatency = &(((CDiskMarkDlg*)dlg)->m_MixLatency[index]);
break;
#endif
}
option += L" -ag";
if(IsWin8orLater() && BenchType[index] == 0 && BenchThreads[index] > 1) // Sequential
{
option += L" -si";
}
double score = 0.0;
double latency = 0.0;
if (maxScore == NULL || minLatency == NULL)
{
return ;
}
*maxScore = 0.0;
*minLatency = -1.0;
for (j = 0; j <= DiskTestCount; j++)
{
if (j == 0)
{
duration = ((CDiskMarkDlg*)dlg)->m_MeasureTime;
cstr.Format(L"Preparing... %s", title.GetString());
}
else
{
duration = ((CDiskMarkDlg*)dlg)->m_MeasureTime;
cstr.Format(L"%s (%d/%d)", title.GetString(), j, DiskTestCount);
}
::PostMessage(((CDiskMarkDlg*) dlg)->GetSafeHwnd(), WM_UPDATE_MESSAGE, (WPARAM) &cstr, 0);
command.Format(L"\"%s\" %s -d%d -A%d -L \"%s\"", (LPTSTR)DiskSpdExe.GetString(), (LPTSTR)option.GetString(), duration, GetCurrentProcessId(), (LPTSTR)TestFilePath.GetString());
score = ExecAndWait((TCHAR*) (command.GetString()), TRUE, &latency) / 10 / 1000.0;
if (j > 0 && score > *maxScore)
{
*maxScore = score;
::PostMessage(((CDiskMarkDlg*) dlg)->GetSafeHwnd(), WM_UPDATE_SCORE, 0, 0);
}
if (j > 0 && score > 0.0 && (latency < *minLatency || *minLatency < 0))
{
*minLatency = latency;
::PostMessage(((CDiskMarkDlg*)dlg)->GetSafeHwnd(), WM_UPDATE_SCORE, 0, 0);
}
if (!((CDiskMarkDlg*) dlg)->m_DiskBenchStatus)
{
return;
}
}
::PostMessage(((CDiskMarkDlg*) dlg)->GetSafeHwnd(), WM_UPDATE_SCORE, 0, 0);
}
@@ -0,0 +1,88 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#define TIMER_ID 5963
// Common Message
#define ALL_0X00_0FILL L"<0Fill>"
// Benchmark
#define BENCHMARK_READ 1
#define BENCHMARK_WRITE 2
#define BENCHMARK_READ_WRITE 3
enum TEST_DATA_TYPE
{
TEST_DATA_RANDOM = 0,
TEST_DATA_ALL0X00,
TEST_DATA_ALL0XFF,
};
enum AFFINITY_MODE
{
AFFINITY_DISABLED = 0,
AFFINITY_ENABLED,
};
enum PROFILE
{
PROFILE_DEFAULT = 0,
PROFILE_PEAK,
PROFILE_REAL,
PROFILE_DEMO,
PROFILE_DEFAULT_MIX,
PROFILE_PEAK_MIX,
PROFILE_REAL_MIX,
};
enum DISK_SPD_CMD
{
TEST_CREATE_FILE = 0,
TEST_DELETE_FILE,
TEST_READ_0,
TEST_READ_1,
TEST_READ_2,
TEST_READ_3,
TEST_READ_4,
TEST_READ_5,
TEST_READ_6,
TEST_READ_7,
TEST_READ_8,
TEST_WRITE_0,
TEST_WRITE_1,
TEST_WRITE_2,
TEST_WRITE_3,
TEST_WRITE_4,
TEST_WRITE_5,
TEST_WRITE_6,
TEST_WRITE_7,
TEST_WRITE_8,
TEST_MIX_0,
TEST_MIX_1,
TEST_MIX_2,
TEST_MIX_3,
TEST_MIX_4,
TEST_MIX_5,
TEST_MIX_6,
TEST_MIX_7,
TEST_MIX_8,
};
UINT ExecDiskBenchAll(LPVOID dlg);
UINT ExecDiskBenchAllPeak(LPVOID dlg);
UINT ExecDiskBenchAllReal(LPVOID dlg);
UINT ExecDiskBenchAllDemo(LPVOID dlg);
UINT ExecDiskBench0(LPVOID dlg);
UINT ExecDiskBench1(LPVOID dlg);
UINT ExecDiskBench2(LPVOID dlg);
UINT ExecDiskBench3(LPVOID dlg);
UINT ExecDiskBench4(LPVOID dlg);
UINT ExecDiskBench5(LPVOID dlg);
UINT ExecDiskBench6(LPVOID dlg);
UINT ExecDiskBench7(LPVOID dlg);
@@ -0,0 +1,117 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "DiskMark.h"
#include "DiskMarkDlg.h"
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
#include <afxole.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
BEGIN_MESSAGE_MAP(CDiskMarkApp, CWinApp)
ON_COMMAND(ID_HELP, &CWinApp::OnHelp)
END_MESSAGE_MAP()
CDiskMarkApp::CDiskMarkApp()
{
}
CDiskMarkApp theApp;
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
static BOOL IsFileExistEx(const TCHAR* path, const TCHAR* fileName);
static BOOL RunAsRestart();
BOOL CDiskMarkApp::InitInstance()
{
// Remove current directory from DLL search order to prevent DLL hijacking
typedef BOOL(WINAPI* PFN_SetDllDirectory)(LPCTSTR);
PFN_SetDllDirectory pfnSetDllDirectory = (PFN_SetDllDirectory)GetProcAddress(
GetModuleHandle(_T("kernel32")), "SetDllDirectoryW");
if (pfnSetDllDirectory) { pfnSetDllDirectory(_T("")); }
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinApp::InitInstance();
#ifndef UWP
if (! IsUserAnAdmin())
{
if (RunAsRestart())
{
return FALSE;
}
}
#endif
// Multimedia Timer Setting
TIMECAPS tc;
timeGetDevCaps(&tc,sizeof(TIMECAPS));
timeBeginPeriod(tc.wPeriodMin);
BOOL flagReExec = FALSE;
CDiskMarkDlg dlg;
m_pMainWnd = &dlg;
if (dlg.DoModal() == RE_EXEC)
{
flagReExec = TRUE;
}
timeEndPeriod(tc.wPeriodMin);
if(flagReExec)
{
TCHAR str[MAX_PATH];
::GetModuleFileName(NULL, str, MAX_PATH);
ShellExecute(NULL, NULL, str, NULL, NULL, SW_SHOWNORMAL);
}
return FALSE;
}
BOOL IsFileExistEx(const TCHAR* path, const TCHAR* fileName)
{
if(! IsFileExist(path))
{
CString cstr;
cstr.Format(L"Not Found \"%s\".", fileName);
AfxMessageBox(cstr);
return FALSE;
}
return TRUE;
}
BOOL RunAsRestart()
{
int count;
TCHAR** cmd = ::CommandLineToArgvW(::GetCommandLine(), &count);
if (count < 2 || _tcscmp(cmd[1], L"runas") != 0)
{
TCHAR path[MAX_PATH];
::GetModuleFileName(NULL, path, MAX_PATH);
if (::ShellExecute(NULL, L"runas", path, L"runas", NULL, SW_SHOWNORMAL) > (HINSTANCE)32)
{
return TRUE;
}
}
return FALSE;
}
@@ -0,0 +1,24 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "resource.h"
class CDiskMarkApp : public CWinApp
{
public:
CDiskMarkApp();
public:
virtual BOOL InitInstance();
DECLARE_MESSAGE_MAP()
};
extern CDiskMarkApp theApp;
@@ -0,0 +1,477 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// “ú–{Œê (“ú–{) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
#pragma code_page(932)
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"#define _AFX_NO_SPLITTER_RESOURCES\r\n"
"#define _AFX_NO_OLE_RESOURCES\r\n"
"#define _AFX_NO_TRACKER_RESOURCES\r\n"
"#define _AFX_NO_PROPERTY_RESOURCES\r\n"
"\r\n"
"#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)\r\n"
"LANGUAGE 17, 1\r\n"
"#pragma code_page(932)\r\n"
"#include ""res\\DiskMark.rc2"" // non-Microsoft Visual C++ edited resources\r\n"
"#include ""afxres.rc"" // Standard components\r\n"
"#endif\r\n"
"\0"
END
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_DISKMARK_DIALOG DIALOGEX 0, 0, 267, 344
STYLE DS_SETFONT | DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "CrystalDiskMark"
MENU IDR_MENU
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
PUSHBUTTON "", IDC_HIDE, 0, 0, 0, 0 | WS_TABSTOP
PUSHBUTTON "All",IDC_BUTTON_ALL,7,32,62,37, BS_CENTER | BS_MULTILINE | BS_NOTIFY | WS_TABSTOP
COMBOBOX IDC_COMBO_COUNT,56,14,39,200, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_SIZE,103,14,45,200, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_DRIVE,160,14,99,200, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_UNIT, 0, 14, 39, 200, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
#ifdef _MIX_MODE
COMBOBOX IDC_COMBO_MIX, 56, 14, 39, 200, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
#endif
PUSHBUTTON "TEST0",IDC_BUTTON_TEST_0,7,70,62,37, BS_CENTER | BS_MULTILINE | BS_NOTIFY
PUSHBUTTON "TEST1",IDC_BUTTON_TEST_1,7,109,62,37, BS_CENTER | BS_MULTILINE | BS_NOTIFY
PUSHBUTTON "TEST2",IDC_BUTTON_TEST_2,7,149,62,37, BS_CENTER | BS_MULTILINE | BS_NOTIFY
PUSHBUTTON "TEST3",IDC_BUTTON_TEST_3,7,189,62,37, BS_CENTER | BS_MULTILINE | BS_NOTIFY
LTEXT "",IDC_TEST_READ_0,72,69,77,37,
LTEXT "",IDC_TEST_READ_1,71,108,77,37
LTEXT "",IDC_TEST_READ_2,70,149,77,37
LTEXT "",IDC_TEST_READ_3,71,189,77,37
LTEXT "",IDC_TEST_WRITE_0,160,69,77,37
LTEXT "",IDC_TEST_WRITE_1,160,109,77,37
LTEXT "",IDC_TEST_WRITE_2,156,149,77,37
LTEXT "",IDC_TEST_WRITE_3,156,190,77,37
CONTROL "", IDC_COMMENT, "EDIT", WS_CHILD | ES_MULTILINE | ES_WANTRETURN | WS_TABSTOP, 7, 269, 252, 21,
LTEXT "Read [MB/s]",IDC_READ_UNIT,76,58,29,8
LTEXT "Write [MB/s]",IDC_WRITE_UNIT,160,60,29,8
LTEXT "Demo", IDC_DEMO_SETTING, 76, 58, 29, 8
#ifdef _MIX_MODE
LTEXT "", IDC_TEST_MIX_0, 160, 69, 77, 37, SS_NOTIFY
LTEXT "", IDC_TEST_MIX_1, 160, 109, 77, 37, SS_NOTIFY
LTEXT "", IDC_TEST_MIX_2, 156, 149, 77, 37, SS_NOTIFY
LTEXT "", IDC_TEST_MIX_3, 156, 190, 77, 37, SS_NOTIFY
LTEXT "Mix [MB/s]",IDC_MIX_UNIT,160,60,29,8
#endif
END
IDD_ABOUT DIALOGEX 0, 0, 477, 362
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "CrystalDiskMark"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "",IDC_LOGO,26,17,156,107
PUSHBUTTON "",IDC_VERSION,240,18,193,8
LTEXT "",IDC_EDITION,241,38,33,8
LTEXT "",IDC_RELEASE,239,62,33,8
LTEXT "",IDC_COPYRIGHT1,241,84,33,8
LTEXT "",IDC_COPYRIGHT2, 241, 84, 33, 8
LTEXT "",IDC_COPYRIGHT3, 241, 84, 33, 8
PUSHBUTTON "",IDC_LICENSE,239,110,33,8
PUSHBUTTON "",IDC_PROJECT_SITE_1,77,144,228,21
PUSHBUTTON "",IDC_PROJECT_SITE_2,77,194,232,22
PUSHBUTTON "",IDC_PROJECT_SITE_3,196,229,270,31
PUSHBUTTON "",IDC_PROJECT_SITE_4,196,267,270,31
PUSHBUTTON "",IDC_PROJECT_SITE_5,196,267,270,31
END
IDD_SETTINGS DIALOGEX 0, 0, 154, 76
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Queues&Threads"
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
LTEXT "Default", IDC_LABEL_DEFAULT, 72, 69, 77, 37
LTEXT "Peak", IDC_LABEL_PEAK, 72, 69, 77, 37
LTEXT "Demo", IDC_LABEL_DEMO, 72, 69, 77, 37
LTEXT "Measure Time", IDC_LABEL_MEASURE_TIME, 72, 69, 77, 37
LTEXT "Interval Time", IDC_LABEL_INTERVAL_TIME, 72, 69, 77, 37
LTEXT "Type",IDC_LABEL_TYPE, 72, 69, 77, 37
LTEXT "Size",IDC_LABEL_SIZE,72,69,77,37
LTEXT "Queues",IDC_LABEL_QUEUES,71,108,77,37
LTEXT "Threads",IDC_LABEL_THREADS,71,108,77,37
COMBOBOX IDC_COMBO_BENCH_TYPE_0, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_SIZE_0, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_QUEUE_0, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_THREAD_0, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_TYPE_1, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_SIZE_1, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_QUEUE_1, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_THREAD_1, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_TYPE_2, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_SIZE_2, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_QUEUE_2, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_THREAD_2, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_TYPE_3, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_SIZE_3, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_QUEUE_3, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_THREAD_3, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_TYPE_4, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_SIZE_4, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_QUEUE_4, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_THREAD_4, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_TYPE_5, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_SIZE_5, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_QUEUE_5, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_THREAD_5, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_TYPE_8, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_SIZE_8, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_QUEUE_8, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_BENCH_THREAD_8, 1, 1, 1, 1, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_MEASURE_TIME, 56, 14, 39, 30, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_COMBO_INTERVAL_TIME, 56, 14, 39, 30, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Default", IDC_SET_DEFAULT, 26, 17, 156, 107, BS_CENTER | BS_MULTILINE
PUSHBUTTON "NVMe SSD", IDC_SET_NVME_8, 26, 17, 156, 107, BS_CENTER | BS_MULTILINE
PUSHBUTTON "Flash Memory", IDC_SET_FLASH_MEMORY, 26, 17, 156, 107, BS_CENTER | BS_MULTILINE
PUSHBUTTON "OK", IDC_OK, 48, 68, 83, 14, BS_CENTER
END
IDD_FONT DIALOGEX 0, 0, 180, 89
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Font Setting"
FONT 12, "MS Shell Dlg", 400, 0, 0x80
BEGIN
LTEXT "Font Face", IDC_FONT_FACE, 1, 1, 1, 1
LTEXT "Font Scale", IDC_FONT_SCALE, 1, 1, 1, 1
LTEXT "Render Method", IDC_FONT_RENDER, 1, 1, 1, 1
COMBOBOX IDC_FONT_FACE_COMBO,7,6,166,20,CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_FONT_SCALE_COMBO, 7, 28, 166, 148, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_FONT_RENDER_COMBO, 7, 28, 166, 148, CBS_DROPDOWNLIST | CBS_OWNERDRAWVARIABLE | CBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Default", IDC_SET_DEFAULT, 26, 17, 156, 107, BS_CENTER
PUSHBUTTON "OK",IDC_OK,48,68,83,14,BS_CENTER
END
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 9,0,3,0
PRODUCTVERSION 9,0,3,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "041103a4"
BEGIN
VALUE "FileVersion", "9.0.3.0"
VALUE "ProductVersion", "9.0.3.0"
VALUE "OriginalFilename", "DiskMark.exe"
VALUE "InternalName", "DiskMark.exe"
VALUE "Comments", "https://crystalmark.info/"
VALUE "CompanyName", "Crystal Dew World"
#ifdef SUISHO_AOI_SUPPORT
VALUE "FileDescription", "CrystalDiskMark Aoi Edition"
VALUE "ProductName", "CrystalDiskMark Aoi Edition"
VALUE "LegalCopyright", "(C) 2007-2026 hiyohiyo, (C) 2023-2026 nijihashi sola"
#elif MSI_MEI_SUPPORT
VALUE "FileDescription", "CrystalDiskMark MSI Mei Mihoshi Edition"
VALUE "ProductName", "CrystalDiskMark MSI Mei Mihoshi Edition"
VALUE "LegalCopyright", "(C) 2007-2026 hiyohiyo, (C) 2024-2026 Micro-Star INT'L CO., LTD."
#elif SUISHO_SHIZUKU_SUPPORT
VALUE "FileDescription", "CrystalDiskMark Shizuku Edition"
VALUE "ProductName", "CrystalDiskMark Shizuku Edition"
VALUE "LegalCopyright", "(C) 2007-2026 hiyohiyo, (C) 2012-2026 kirino kasumu"
#else
VALUE "FileDescription", "CrystalDiskMark"
VALUE "ProductName", "CrystalDiskMark"
VALUE "LegalCopyright", "(C) 2007-2026 hiyohiyo6"
#endif
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x411, 932
END
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_DISKMARK_DIALOG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 259
TOPMARGIN, 7
BOTTOMMARGIN, 338
END
IDD_ABOUT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 161
TOPMARGIN, 7
BOTTOMMARGIN, 95
END
IDD_SETTINGS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 147
TOPMARGIN, 7
BOTTOMMARGIN, 69
END
IDD_FONT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 173
TOPMARGIN, 6
BOTTOMMARGIN, 82
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDR_MENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "Copy", ID_COPY
MENUITEM "Save (text)", ID_SAVE_TEXT
MENUITEM "Save (image)", ID_SAVE_IMAGE
MENUITEM "Exit", ID_EXIT
END
POPUP "&Settings"
BEGIN
POPUP "Test Mode"
BEGIN
MENUITEM "Default (Random)", ID_MODE_DEFAULT
MENUITEM "All 0x00 (0 Fill)", ID_MODE_ALL0X00
END
MENUITEM SEPARATOR
MENUITEM "Default", ID_SETTING_DEFAULT
MENUITEM "NVMe SSD", ID_SETTING_NVME_8
MENUITEM "Flash Memory", ID_SETTING_FLASH_MEMORY
MENUITEM SEPARATOR
MENUITEM "&Settings", ID_SETTINGS_QUEUESTHREADS
END
POPUP "&Profile"
BEGIN
MENUITEM "Default", ID_PROFILE_DEFAULT
MENUITEM "Peak Performance", ID_PROFILE_PEAK
MENUITEM "Real World Performance", ID_PROFILE_REAL
MENUITEM "Demonstration", ID_PROFILE_DEMO
#ifdef _MIX_MODE
MENUITEM "Default w/MIX", ID_PROFILE_DEFAULT_MIX
MENUITEM "Peak Performance w/ MIX", ID_PROFILE_PEAK_MIX
MENUITEM "Real World Performance w/ MIX", ID_PROFILE_REAL_MIX
#endif
MENUITEM SEPARATOR
#ifdef SUISHO_SHIZUKU_SUPPORT
MENUITEM "Read&&Wr&ite", ID_BENCHMARK_READ_WRITE
MENUITEM "Re&ad", ID_BENCHMARK_READ_ONLY
MENUITEM "&Write", ID_BENCHMARK_WRITE_ONLY
#else
MENUITEM "Read&&Wr&ite [+Mix]", ID_BENCHMARK_READ_WRITE
MENUITEM "Re&ad [+Mix]", ID_BENCHMARK_READ_ONLY
MENUITEM "&Write [+Mix]", ID_BENCHMARK_WRITE_ONLY
#endif
END
POPUP "&Theme"
BEGIN
POPUP "Zoom"
BEGIN
MENUITEM "100%", ID_ZOOM_100
MENUITEM "125%", ID_ZOOM_125
MENUITEM "150%", ID_ZOOM_150
MENUITEM "200%", ID_ZOOM_200
MENUITEM "250%", ID_ZOOM_250
MENUITEM "300%", ID_ZOOM_300
MENUITEM "Auto", ID_ZOOM_AUTO
END
MENUITEM "Font Setting", ID_FONT_SETTING
MENUITEM SEPARATOR
END
POPUP "&Help"
BEGIN
MENUITEM "Help", ID_HELP
MENUITEM "Crystal Dew World [Web]", ID_CRYSTALDEWWORLD
MENUITEM SEPARATOR
MENUITEM "About CrystalDiskMark", ID_ABOUT
END
POPUP "&Language"
BEGIN
POPUP "A-N"
BEGIN
MENUITEM "DUMMY", ID_A_DUMMY
END
POPUP "O-Z"
BEGIN
MENUITEM "DUMMY", ID_O_DUMMY
END
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
#ifdef SUISHO_AOI_SUPPORT
IDR_MAINFRAME ICON "res\\DiskMarkA.ico"
IDI_TRAY_ICON ICON "res\\DiskMarkA16.ico"
#elif MSI_MEI_SUPPORT
IDR_MAINFRAME ICON "res\\DiskMarkM.ico"
IDI_TRAY_ICON ICON "res\\DiskMarkM16.ico"
#elif SUISHO_SHIZUKU_SUPPORT
IDR_MAINFRAME ICON "res\\DiskMarkS.ico"
IDI_TRAY_ICON ICON "res\\DiskMarkS16.ico"
#else
IDR_MAINFRAME ICON "res\\DiskMark.ico"
IDI_TRAY_ICON ICON "res\\DiskMark16.ico"
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_ACCELERATOR ACCELERATORS
BEGIN
"C", ID_COPY, VIRTKEY, CONTROL, SHIFT, NOINVERT
"T", ID_SAVE_TEXT, VIRTKEY, CONTROL, NOINVERT
"S", ID_SAVE_IMAGE, VIRTKEY, CONTROL, NOINVERT
VK_F4, ID_EXIT, VIRTKEY, ALT, NOINVERT
VK_F1, ID_HELP, VIRTKEY, NOINVERT
"Q", ID_SETTINGS_QUEUESTHREADS, VIRTKEY, CONTROL, NOINVERT
"F", ID_FONT_SETTING, VIRTKEY, CONTROL, NOINVERT
VK_ESCAPE, IDOK, VIRTKEY, NOINVERT
VK_F5, IDOK, VIRTKEY, NOINVERT
END
/////////////////////////////////////////////////////////////////////////////
//
// AFX_DIALOG_LAYOUT
//
IDD_DISKMARK_DIALOG AFX_DIALOG_LAYOUT
BEGIN
0
END
IDD_SETTINGS AFX_DIALOG_LAYOUT
BEGIN
0
END
#endif // “ú–{Œê (“ú–{) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
LANGUAGE 17, 1
#pragma code_page(932)
#include "res\DiskMark.rc2" // non-Microsoft Visual C++ edited resources
#include "afxres.rc" // Standard components
#endif
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
@@ -0,0 +1,114 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33502.453
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DiskMark", "DiskMark.vcxproj", "{CDF33C67-147E-4C50-BC76-99A6BCB214D9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|ARM64 = Debug|ARM64
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release(UWP)|ARM = Release(UWP)|ARM
Release(UWP)|ARM64 = Release(UWP)|ARM64
Release(UWP)|Win32 = Release(UWP)|Win32
Release(UWP)|x64 = Release(UWP)|x64
Release|ARM = Release|ARM
Release|ARM64 = Release|ARM64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
ReleaseAoi(UWP)|ARM = ReleaseAoi(UWP)|ARM
ReleaseAoi(UWP)|ARM64 = ReleaseAoi(UWP)|ARM64
ReleaseAoi(UWP)|Win32 = ReleaseAoi(UWP)|Win32
ReleaseAoi(UWP)|x64 = ReleaseAoi(UWP)|x64
ReleaseAoi|ARM = ReleaseAoi|ARM
ReleaseAoi|ARM64 = ReleaseAoi|ARM64
ReleaseAoi|Win32 = ReleaseAoi|Win32
ReleaseAoi|x64 = ReleaseAoi|x64
ReleaseMSIMei|ARM = ReleaseMSIMei|ARM
ReleaseMSIMei|ARM64 = ReleaseMSIMei|ARM64
ReleaseMSIMei|Win32 = ReleaseMSIMei|Win32
ReleaseMSIMei|x64 = ReleaseMSIMei|x64
ReleaseShizuku(UWP)|ARM = ReleaseShizuku(UWP)|ARM
ReleaseShizuku(UWP)|ARM64 = ReleaseShizuku(UWP)|ARM64
ReleaseShizuku(UWP)|Win32 = ReleaseShizuku(UWP)|Win32
ReleaseShizuku(UWP)|x64 = ReleaseShizuku(UWP)|x64
ReleaseShizuku|ARM = ReleaseShizuku|ARM
ReleaseShizuku|ARM64 = ReleaseShizuku|ARM64
ReleaseShizuku|Win32 = ReleaseShizuku|Win32
ReleaseShizuku|x64 = ReleaseShizuku|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Debug|ARM.ActiveCfg = Debug|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Debug|ARM.Build.0 = Debug|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Debug|ARM64.ActiveCfg = Debug|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Debug|ARM64.Build.0 = Debug|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Debug|Win32.ActiveCfg = Debug|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Debug|Win32.Build.0 = Debug|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Debug|x64.ActiveCfg = Debug|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Debug|x64.Build.0 = Debug|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release(UWP)|ARM.ActiveCfg = Release(UWP)|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release(UWP)|ARM.Build.0 = Release(UWP)|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release(UWP)|ARM64.ActiveCfg = Release(UWP)|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release(UWP)|ARM64.Build.0 = Release(UWP)|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release(UWP)|Win32.ActiveCfg = Release(UWP)|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release(UWP)|Win32.Build.0 = Release(UWP)|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release(UWP)|x64.ActiveCfg = Release(UWP)|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release(UWP)|x64.Build.0 = Release(UWP)|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release|ARM.ActiveCfg = Release|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release|ARM.Build.0 = Release|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release|ARM64.ActiveCfg = Release|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release|ARM64.Build.0 = Release|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release|Win32.ActiveCfg = Release|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release|Win32.Build.0 = Release|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release|x64.ActiveCfg = Release|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.Release|x64.Build.0 = Release|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi(UWP)|ARM.ActiveCfg = ReleaseAoi(UWP)|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi(UWP)|ARM.Build.0 = ReleaseAoi(UWP)|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi(UWP)|ARM64.ActiveCfg = ReleaseAoi(UWP)|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi(UWP)|ARM64.Build.0 = ReleaseAoi(UWP)|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi(UWP)|Win32.ActiveCfg = ReleaseAoi(UWP)|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi(UWP)|Win32.Build.0 = ReleaseAoi(UWP)|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi(UWP)|x64.ActiveCfg = ReleaseAoi(UWP)|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi(UWP)|x64.Build.0 = ReleaseAoi(UWP)|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi|ARM.ActiveCfg = ReleaseAoi|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi|ARM.Build.0 = ReleaseAoi|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi|ARM64.ActiveCfg = ReleaseAoi|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi|ARM64.Build.0 = ReleaseAoi|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi|Win32.ActiveCfg = ReleaseAoi|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi|Win32.Build.0 = ReleaseAoi|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi|x64.ActiveCfg = ReleaseAoi|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseAoi|x64.Build.0 = ReleaseAoi|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseMSIMei|ARM.ActiveCfg = ReleaseMSIMei|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseMSIMei|ARM.Build.0 = ReleaseMSIMei|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseMSIMei|ARM64.ActiveCfg = ReleaseMSIMei|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseMSIMei|ARM64.Build.0 = ReleaseMSIMei|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseMSIMei|Win32.ActiveCfg = ReleaseMSIMei|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseMSIMei|Win32.Build.0 = ReleaseMSIMei|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseMSIMei|x64.ActiveCfg = ReleaseMSIMei|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseMSIMei|x64.Build.0 = ReleaseMSIMei|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku(UWP)|ARM.ActiveCfg = ReleaseShizuku(UWP)|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku(UWP)|ARM.Build.0 = ReleaseShizuku(UWP)|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku(UWP)|ARM64.ActiveCfg = ReleaseShizuku(UWP)|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku(UWP)|ARM64.Build.0 = ReleaseShizuku(UWP)|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku(UWP)|Win32.ActiveCfg = ReleaseShizuku(UWP)|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku(UWP)|Win32.Build.0 = ReleaseShizuku(UWP)|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku(UWP)|x64.ActiveCfg = ReleaseShizuku(UWP)|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku(UWP)|x64.Build.0 = ReleaseShizuku(UWP)|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku|ARM.ActiveCfg = ReleaseShizuku|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku|ARM.Build.0 = ReleaseShizuku|ARM
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku|ARM64.ActiveCfg = ReleaseShizuku|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku|ARM64.Build.0 = ReleaseShizuku|ARM64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku|Win32.ActiveCfg = ReleaseShizuku|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku|Win32.Build.0 = ReleaseShizuku|Win32
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku|x64.ActiveCfg = ReleaseShizuku|x64
{CDF33C67-147E-4C50-BC76-99A6BCB214D9}.ReleaseShizuku|x64.Build.0 = ReleaseShizuku|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {81DC78FD-9979-489D-930A-DA0CD60B9148}
EndGlobalSection
EndGlobal
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,171 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="Priscilla">
<UniqueIdentifier>{342a84d1-5b9a-4a10-b0ca-cc618409b820}</UniqueIdentifier>
</Filter>
<Filter Include="Library">
<UniqueIdentifier>{1e1cebf3-7ec5-4e7b-b130-da0db639e588}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AboutDlg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DiskBench.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DiskMark.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DiskMarkDlg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SettingsDlg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Priscilla\ButtonFx.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Priscilla\ComboBoxFx.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Priscilla\EditFx.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Priscilla\StaticFx.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="FontSelectionDlg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Priscilla\DialogFx.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Priscilla\FontComboBoxFx.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Priscilla\MainDialogFx.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Priscilla\OsInfoFx.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Priscilla\UtilityFx.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Priscilla\DarkMode.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Library\stdafx.cpp">
<Filter>Library</Filter>
</ClCompile>
<ClCompile Include="Priscilla\UAHMenuBar.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Priscilla\stb_image_impl.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
<ClCompile Include="Priscilla\stb_image_write_impl.cpp">
<Filter>Priscilla</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="AboutDlg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DiskBench.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DiskMark.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DiskMarkDlg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SettingsDlg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Priscilla\ButtonFx.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Priscilla\ComboBoxFx.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Priscilla\CommonFx.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Priscilla\DialogFx.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Priscilla\EditFx.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Priscilla\StaticFx.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="FontSelectionDlg.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Priscilla\FontComboBoxFx.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Priscilla\MainDialogFx.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Priscilla\OsInfoFx.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Priscilla\UtilityFx.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Priscilla\DarkMode.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Library\Resource.h">
<Filter>Library</Filter>
</ClInclude>
<ClInclude Include="Library\stdafx.h">
<Filter>Library</Filter>
</ClInclude>
<ClInclude Include="Priscilla\UAHMenuBar.h">
<Filter>Priscilla</Filter>
</ClInclude>
<ClInclude Include="Priscilla\stb_image_write.h">
<Filter>Priscilla</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="res\DiskMark.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="res\DiskMark.rc2">
<Filter>Resource Files</Filter>
</None>
<None Include="res\DiskMark16.ico">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DiskMark.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Manifest Include="DeclareDPIAware.manifest">
<Filter>Resource Files</Filter>
</Manifest>
</ItemGroup>
</Project>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,292 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "AboutDlg.h"
#include "SettingsDlg.h"
#include "FontSelectionDlg.h"
#include "DialogFx.h"
#include "MainDialogFx.h"
#include "ButtonFx.h"
#include "StaticFx.h"
#include "ComboBoxFx.h"
#include "EditFx.h"
#include "UtilityFx.h"
#include "OsInfoFx.h"
#include "DarkMode.h"
class CDiskMarkDlg : public CMainDialogFx
{
public:
CDiskMarkDlg(CWnd* pParent = NULL);
~CDiskMarkDlg();
enum { IDD = IDD_DISKMARK_DIALOG };
enum SCORE_UNIT
{
SCORE_MBS = 0,
SCORE_GBS,
SCORE_IOPS,
SCORE_US,
};
enum BENCH_TYPE
{
BENCH_SEQ = 0,
BENCH_RND,
};
volatile CWinThread* m_WinThread;
volatile BOOL m_DiskBenchStatus;
void InitScore();
void UpdateScore();
double m_ReadScore[9];
double m_WriteScore[9];
double m_ReadLatency[9];
double m_WriteLatency[9];
#ifdef MIX_MODE
double m_MixScore[9];
double m_MixLatency[9];
#endif
void SetMeter(CStaticFx* control, double score, double latency, int blockSize, int unit);
void ChangeLang(CString LangName);
void UpdateDialogSize();
void ChangeButtonStatus(BOOL status);
void SetScoreToolTip(CStaticFx* cx, double score, double latency, int blockSize);
void UpdateThemeInfo();
CString m_ValueTestUnit;
CString m_ValueTestCount;
CString m_ValueTestSize;
CString m_ValueTestDrive;
CString m_TestDriveInfo;
CString m_TestTargetPath;
long m_TestDriveLetter;
int m_MaxIndexTestDrive;
int m_IndexTestUnit;
int m_IndexTestCount;
int m_IndexTestSize;
int m_IndexTestDrive;
int m_IndexTestMix;
int m_BenchType[9];
int m_BenchSize[9];
int m_BenchQueues[9];
int m_BenchThreads[9];
int m_IntervalTime;
int m_MeasureTime;
int m_TestData;
int m_Profile;
int m_Benchmark;
int m_MarginButtonTop;
int m_MarginButtonLeft;
int m_MarginButtonBottom;
int m_MarginButtonRight;
int m_MarginMeterTop;
int m_MarginMeterLeft;
int m_MarginMeterBottom;
int m_MarginMeterRight;
int m_MarginCommentTop;
int m_MarginCommentLeft;
int m_MarginCommentBottom;
int m_MarginCommentRight;
int m_MarginDemoTop;
int m_MarginDemoLeft;
int m_MarginDemoBottom;
int m_MarginDemoRight;
BOOL m_AdminMode;
BOOL m_MixMode;
int m_MixRatio;
// Message //
CString m_MesDiskCapacityError;
CString m_MesDiskWriteError;
CString m_MesDiskReadError;
CString m_MesStopBenchmark;
CString m_MesDiskCreateFileError;
CString m_MesDiskSpdNotFound;
void SetWindowTitle(CString message);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
void OnAll();
void OnTest0();
void OnTest1();
void OnTest2();
void OnTest3();
void Stop();
void OnSequentialPeak();
void OnRandomPeak();
void OnSequentialReal();
void OnRandomReal();
void SelectDrive();
CString GetResultString(int type, double score, double latency, int size, int queues, int threads);
CString GetButtonText(int type, int size, int queues, int threads, int unit);
CString GetButtonToolTipText(int type, int size, int queues, int threads, int unit);
CString m_TitleTestDrive;
CString m_TitleTestCount;
CString m_TitleTestSize;
CString m_TitleTestQSize;
protected:
HICON m_hIcon;
HICON m_hIconMini;
HACCEL m_hAccelerator;
int m_SizeX;
int m_SizeY;
CAboutDlg* m_AboutDlg;
CSettingsDlg* m_SettingsDlg;
void SetControlFont();
void InitDrive();
void UpdateDriveToolTip();
BOOL CheckRadioZoomType(int id, int value);
void CheckRadioZoomType();
void CheckRadioPresetMode();
void UpdateQueuesThreads();
void EnableMenus();
void DisableMenus();
void SaveText(CString fileName);
void SetLayeredWindow(HWND hWnd, BYTE alpha);
void UpdateComboTooltip();
virtual BOOL CheckThemeEdition(CString name);
BOOL IsDefaultMode();
BOOL IsNVMe8Mode();
BOOL IsFlashMemoryMode();
#ifdef MIX_MODE
CStaticFx m_TestMix0;
CStaticFx m_TestMix1;
CStaticFx m_TestMix2;
CStaticFx m_TestMix3;
CStaticFx m_MixUnit;
CComboBoxFx m_ComboMix;
#endif
CButtonFx m_ButtonAll;
CButtonFx m_ButtonTest0;
CButtonFx m_ButtonTest1;
CButtonFx m_ButtonTest2;
CButtonFx m_ButtonTest3;
CStaticFx m_TestRead0;
CStaticFx m_TestRead1;
CStaticFx m_TestRead2;
CStaticFx m_TestRead3;
CStaticFx m_TestWrite0;
CStaticFx m_TestWrite1;
CStaticFx m_TestWrite2;
CStaticFx m_TestWrite3;
CEditFx m_Comment;
CComboBoxFx m_ComboCount;
CComboBoxFx m_ComboSize;
CComboBoxFx m_ComboDrive;
CComboBoxFx m_ComboUnit;
CStaticFx m_WriteUnit;
CStaticFx m_ReadUnit;
CStaticFx m_DemoSetting;
virtual BOOL OnInitDialog();
virtual void OnOK();
virtual void OnCancel();
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg LRESULT OnUpdateScore(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnUpdateMessage(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnExitBenchmark(WPARAM wParam, LPARAM lParam);
afx_msg void OnZoom100();
afx_msg void OnZoom125();
afx_msg void OnZoom150();
afx_msg void OnZoom200();
afx_msg void OnZoom250();
afx_msg void OnZoom300();
afx_msg void OnZoomAuto();
afx_msg void OnExit();
afx_msg void OnAbout();
afx_msg void OnFontSetting();
LRESULT OnQueryEndSession(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnCopy();
afx_msg void OnHelp();
afx_msg void OnCrystalDewWorld();
afx_msg void OnModeDefault();
afx_msg void OnModeAll0x00();
afx_msg void OnSettingDefault();
afx_msg void OnSettingNVMe8();
afx_msg void OnSettingFlashMemory();
afx_msg void OnProfileDefault();
afx_msg void OnProfilePeak();
afx_msg void OnProfileReal();
afx_msg void OnProfileDemo();
afx_msg void OnSaveText();
afx_msg void OnSaveImage();
afx_msg void OnSettingsQueuesThreads();
afx_msg void OnCbnSelchangeComboDrive();
afx_msg void OnCbnSelchangeComboUnit();
afx_msg void UpdateUnitLabel();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
void ProfileDefault();
void ProfilePeak();
void ProfileReal();
void ProfileDemo();
void SettingsQueuesThreads(int type);
#ifdef MIX_MODE
afx_msg void OnProfileDefaultMix();
afx_msg void OnProfilePeakMix();
afx_msg void OnProfileRealMix();
void ProfileDefaultMix();
void ProfilePeakMix();
void ProfileRealMix();
afx_msg void OnCbnSelchangeComboMix();
#endif
afx_msg void OnBenchmarkReadWrite();
afx_msg void OnBenchmarkReadOnly();
afx_msg void OnBenchmarkWriteOnly();
void BenchmarkReadWrite();
void BenchmarkReadOnly();
void BenchmarkWriteOnly();
};
@@ -0,0 +1,243 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "DiskMark.h"
#include "DiskMarkDlg.h"
#include "FontSelectionDlg.h"
int CALLBACK EnumFontFamExProc(ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, int FontType, LPARAM lParam);
IMPLEMENT_DYNAMIC(CFontSelectionDlg, CDialog)
CFontSelectionDlg::CFontSelectionDlg(CWnd* pParent)
: CDialogFx(CFontSelectionDlg::IDD, pParent)
{
CMainDialogFx* p = (CMainDialogFx*)pParent;
m_ZoomType = p->GetZoomType();
m_FontScale = p->GetFontScale();
m_FontRatio = 1.0; // p->GetFontRatio();
m_FontFace = p->GetFontFace();
m_FontRender = p->GetFontRender();
m_CurrentLangPath = p->GetCurrentLangPath();
m_DefaultLangPath = p->GetDefaultLangPath();
m_ThemeDir = p->GetThemeDir();
m_CurrentTheme = p->GetCurrentTheme();
m_DefaultTheme = p->GetDefaultTheme();
m_Ini = p->GetIniPath();
m_BackgroundName = L"";
}
CFontSelectionDlg::~CFontSelectionDlg()
{
}
void CFontSelectionDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_OK, m_CtrlOk);
DDX_Control(pDX, IDC_FONT_FACE, m_LabelFontFace);
DDX_Control(pDX, IDC_FONT_SCALE, m_LabelFontScale);
DDX_Control(pDX, IDC_FONT_RENDER, m_LabelFontRender);
DDX_Control(pDX, IDC_FONT_FACE_COMBO, m_CtrlFontFace);
DDX_Control(pDX, IDC_FONT_SCALE_COMBO, m_CtrlFontScale);
DDX_Control(pDX, IDC_FONT_RENDER_COMBO, m_CtrlFontRender);
DDX_Control(pDX, IDC_SET_DEFAULT, m_CtrlDefault);
}
BEGIN_MESSAGE_MAP(CFontSelectionDlg, CDialogFx)
ON_BN_CLICKED(IDC_OK, &CFontSelectionDlg::OnOk)
ON_BN_CLICKED(IDC_SET_DEFAULT, &CFontSelectionDlg::OnSetDefault)
END_MESSAGE_MAP()
BOOL CFontSelectionDlg::OnInitDialog()
{
CDialogFx::OnInitDialog();
SetWindowTitle(i18n(L"WindowTitle", L"FONT_SETTING"));
SetDefaultFont(m_FontFace);
CString cstr;
for (int i = 50; i <= 150; i += 10)
{
cstr.Format(L"%d", i);
m_CtrlFontScale.AddString(cstr);
if (m_FontScale == i) { m_CtrlFontScale.SetCurSel(m_CtrlFontScale.GetCount() - 1); }
}
m_CtrlFontRender.AddString(i18n(L"Dialog", L"ENABLED"));
m_CtrlFontRender.AddString(i18n(L"Dialog", L"DISABLED"));
if (m_FontRender == CLEARTYPE_NATURAL_QUALITY)
{
m_CtrlFontRender.SetCurSel(0);
}
else
{
m_CtrlFontRender.SetCurSel(1);
}
m_LabelFontFace.SetWindowTextW(i18n(L"Dialog", L"FONT_FACE"));
m_LabelFontScale.SetWindowTextW(i18n(L"Dialog", L"FONT_SCALE"));
m_LabelFontRender.SetWindowTextW(L"ClearType");
m_CtrlDefault.SetWindowTextW(i18n(L"Dialog", L"DEFAULT"));
UpdateDialogSize();
return TRUE;
}
void CFontSelectionDlg::UpdateDialogSize()
{
CDialogFx::UpdateDialogSize();
COLORREF textColor = RGB(0, 0, 0);
COLORREF textSelectedColor = RGB(0, 0, 0);
ChangeZoomType(m_ZoomType);
SetClientSize(SIZE_X, SIZE_Y, m_ZoomRatio);
UpdateBackground(FALSE, m_bDarkMode);
m_LabelFontFace.SetFontEx(m_FontFace, 16, 16, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelFontScale.SetFontEx(m_FontFace, 16, 16, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelFontRender.SetFontEx(m_FontFace, 16, 16, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelFontFace.InitControl(8, 8, 432, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelFontScale.InitControl(8, 80, 208, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelFontRender.InitControl(240, 80, 208, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_CtrlFontFace.InitControl(20, 32, 440, 360, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_CtrlFontScale.InitControl(20, 104, 208, 360, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_CtrlFontRender.InitControl(252, 104, 208, 360, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_CtrlDefault.InitControl(40, 156, 168, 32, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_CtrlOk.InitControl(272, 156, 168, 32, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_CtrlFontFace.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_CtrlFontScale.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_CtrlFontRender.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_CtrlFontFace.SetFontHeight(20, m_ZoomRatio, m_FontRatio);
m_CtrlFontFace.SetFontEx(m_FontFace, 20, 20, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_CtrlFontFace.SetItemHeightEx(-1, 36, m_ZoomRatio, m_FontRatio);
for (int i = 0; i < m_CtrlFontFace.GetCount(); i++)
{
m_CtrlFontFace.SetItemHeightEx(i, 32, m_ZoomRatio, m_FontRatio);
}
m_CtrlFontScale.SetFontHeight(20, m_ZoomRatio, m_FontRatio);
m_CtrlFontScale.SetFontEx(m_FontFace, 20, 20, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_CtrlFontScale.SetItemHeightEx(-1, 36, m_ZoomRatio, m_FontRatio);
for (int i = 0; i < m_CtrlFontScale.GetCount(); i++)
{
m_CtrlFontScale.SetItemHeightEx(i, 32, m_ZoomRatio, m_FontRatio);
}
m_CtrlFontRender.SetFontHeight(20, m_ZoomRatio, m_FontRatio);
m_CtrlFontRender.SetFontEx(m_FontFace, 20, 20, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_CtrlFontRender.SetItemHeightEx(-1, 36, m_ZoomRatio, m_FontRatio);
for (int i = 0; i < m_CtrlFontRender.GetCount(); i++)
{
m_CtrlFontRender.SetItemHeightEx(i, 32, m_ZoomRatio, m_FontRatio);
}
m_CtrlDefault.SetFontEx(m_FontFace, 16, 16, m_ZoomRatio, m_FontRatio, FW_NORMAL, m_FontRender);
m_CtrlOk.SetFontEx(m_FontFace, 16, 16, m_ZoomRatio, m_FontRatio, FW_NORMAL, m_FontRender);
m_CtrlDefault.SetHandCursor();
m_CtrlOk.SetHandCursor();
SetDarkModeControl(m_CtrlDefault.GetSafeHwnd(), m_bDarkMode);
SetDarkModeControl(m_CtrlOk.GetSafeHwnd(), m_bDarkMode);
Invalidate();
}
void CFontSelectionDlg::OnOk()
{
CString cstr;
m_CtrlFontFace.GetLBText(m_CtrlFontFace.GetCurSel(), m_FontFace);
m_CtrlFontScale.GetLBText(m_CtrlFontScale.GetCurSel(), cstr);
m_FontScale = _wtoi(cstr);
if (m_CtrlFontRender.GetCurSel() == 0)
{
m_FontRender = CLEARTYPE_NATURAL_QUALITY;
}
else
{
m_FontRender = ANTIALIASED_QUALITY;
}
CDialog::OnOK();
}
int CALLBACK EnumFontFamExProc(ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, int FontType, LPARAM lParam)
{
CFontComboBox* pFontComboBox = (CFontComboBox*)lParam;
if(pFontComboBox->FindStringExact(0, (TCHAR*)lpelfe->elfLogFont.lfFaceName) == CB_ERR
&& _tcschr((TCHAR*)lpelfe->elfLogFont.lfFaceName, L'@') == NULL
&& lpelfe->elfLogFont.lfCharSet != SYMBOL_CHARSET
)
{
pFontComboBox->AddString((TCHAR*)lpelfe->elfLogFont.lfFaceName);
}
return TRUE;
}
void CFontSelectionDlg::OnSetDefault()
{
SetDefaultFont(L"");
m_CtrlFontScale.SetCurSel(5);
m_CtrlFontRender.SetCurSel(0);
}
void CFontSelectionDlg::SetDefaultFont(CString fontFace)
{
m_CtrlFontFace.ResetContent();
CClientDC dc(this);
LOGFONT logfont;
ZeroMemory(&logfont, sizeof(LOGFONT));
logfont.lfCharSet = DEFAULT_CHARSET;
::EnumFontFamiliesExW(dc.m_hDC, &logfont, (FONTENUMPROC)EnumFontFamExProc, (LPARAM)&m_CtrlFontFace, 0);
int no = m_CtrlFontFace.FindStringExact(0, fontFace);
if (no >= 0)
{
m_CtrlFontFace.SetCurSel(no);
}
else
{
no = m_CtrlFontFace.FindStringExact(0, DEFAULT_FONT_FACE_1);
if (no >= 0)
{
m_CtrlFontFace.SetCurSel(no);
}
else
{
no = m_CtrlFontFace.FindStringExact(0, DEFAULT_FONT_FACE_2);
if (no >= 0)
{
m_CtrlFontFace.SetCurSel(no);
}
else
{
m_CtrlFontFace.SetCurSel(0);
}
}
}
for (int i = 0; i < m_CtrlFontFace.GetCount(); i++)
{
m_CtrlFontFace.SetItemHeightEx(i, 32, m_ZoomRatio, m_FontRatio);
}
}
@@ -0,0 +1,48 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "afxwin.h"
#include "ButtonFx.h"
#include "ComboBoxFx.h"
#include "FontComboBoxFx.h"
class CFontSelectionDlg : public CDialogFx
{
DECLARE_DYNAMIC(CFontSelectionDlg)
static const int SIZE_X = 480;
static const int SIZE_Y = 204;
enum { IDD = IDD_FONT };
public:
CFontSelectionDlg(CWnd* pParent = NULL);
virtual ~CFontSelectionDlg();
protected:
virtual void DoDataExchange(CDataExchange* pDX);
virtual BOOL OnInitDialog();
virtual void UpdateDialogSize();
void SetDefaultFont(CString fontFace);
DECLARE_MESSAGE_MAP()
afx_msg void OnSetDefault();
afx_msg void OnOk();
CStaticFx m_LabelFontFace;
CStaticFx m_LabelFontScale;
CStaticFx m_LabelFontRender;
CButtonFx m_CtrlOk;
CButtonFx m_CtrlDefault;
CFontComboBox m_CtrlFontFace;
CComboBoxFx m_CtrlFontScale;
CComboBoxFx m_CtrlFontRender;
};
@@ -0,0 +1,183 @@
//{{NO_DEPENDENCIES}}
//
#define IDD_DISKMARK_DIALOG 102
#define IDR_MENU 129
#define IDR_MAINFRAME 130
#define IDD_ABOUT 131
#define IDD_COMMENT 132
#define IDR_PNG1 134
#define IDR_PNG2 135
#define IDR_ACCELERATOR 136
#define IDI_ICON1 138
#define IDI_TRAY_ICON 138
#define IDD_SETTINGS 139
#define IDD_FONT 140
#define IDC_OK 1001
#define IDC_BUTTON_ALL 1003
#define IDC_BUTTON_TEST_0 1004
#define IDC_BUTTON_TEST_1 1005
#define IDC_BUTTON_TEST_2 1006
#define IDC_BUTTON_TEST_3 1007
#define IDC_TEST_READ_0 1009
#define IDC_TEST_READ_1 1010
#define IDC_TEST_READ_2 1011
#define IDC_TEST_READ_3 1012
#define IDC_TEST_WRITE_0 1014
#define IDC_TEST_WRITE_1 1015
#define IDC_TEST_WRITE_2 1016
#define IDC_TEST_WRITE_3 1017
#define IDC_TEST_MIX_0 1019
#define IDC_TEST_MIX_1 1020
#define IDC_TEST_MIX_2 1021
#define IDC_TEST_MIX_3 1022
#define IDC_COMMENT 1023
#define IDC_COMMENT_EX 1024
#define IDC_COMBO_UNIT 1025
#define IDC_COMBO_COUNT 1026
#define IDC_COMBO_DRIVE 1027
#define IDC_COMBO_SIZE 1028
#define IDC_READ_UNIT 1029
#define IDC_WRITE_UNIT 1030
#define IDC_MIX_UNIT 1031
#define IDC_COMBO_MIX 1032
#define IDC_DEMO_SETTING 1033
#define IDC_HIDE 1034
#define IDC_LOGO 1100
#define IDC_PROJECT_SITE_1 1101
#define IDC_PROJECT_SITE_2 1102
#define IDC_PROJECT_SITE_3 1103
#define IDC_PROJECT_SITE_4 1104
#define IDC_PROJECT_SITE_5 1105
#define IDC_VERSION 1106
#define IDC_RELEASE 1107
#define IDC_COPYRIGHT1 1108
#define IDC_COPYRIGHT2 1109
#define IDC_COPYRIGHT3 1110
#define IDC_LICENSE 1111
#define IDC_EDITION 1112
#define IDC_FONT_FACE_COMBO 1201
#define IDC_FONT_SCALE_COMBO 1202
#define IDC_FONT_RENDER_COMBO 1203
#define IDC_FONT_FACE 1204
#define IDC_FONT_SCALE 1205
#define IDC_FONT_RENDER 1206
#define IDC_LABEL_DEMO 1301
#define IDC_COMBO_DATA 1302
#define IDC_LABEL_DATA 1303
#define IDC_SET_DEFAULT 1304
#define IDC_SET_NVME_8 1306
#define IDC_SET_FLASH_MEMORY 1307
#define IDC_LABEL_AFFINITY 1308
#define IDC_COMBO_AFFINITY 1309
#define IDC_LABEL_PEAK 1310
#define IDC_LABEL_TYPE 1311
#define IDC_LABEL_SIZE 1312
#define IDC_LABEL_QUEUES 1313
#define IDC_LABEL_THREADS 1314
#define IDC_LABEL_MEASURE_TIME 1315
#define IDC_LABEL_INTERVAL_TIME 1316
#define IDC_COMBO_MEASURE_TIME 1317
#define IDC_COMBO_INTERVAL_TIME 1318
#define IDC_LABEL_DEFAULT 1319
#define IDC_COMBO_BENCH_TYPE_0 1320
#define IDC_COMBO_BENCH_TYPE_1 1321
#define IDC_COMBO_BENCH_TYPE_2 1322
#define IDC_COMBO_BENCH_TYPE_3 1323
#define IDC_COMBO_BENCH_TYPE_4 1324
#define IDC_COMBO_BENCH_TYPE_5 1325
#define IDC_COMBO_BENCH_TYPE_8 1328
#define IDC_COMBO_BENCH_SIZE_0 1330
#define IDC_COMBO_BENCH_SIZE_1 1331
#define IDC_COMBO_BENCH_SIZE_2 1332
#define IDC_COMBO_BENCH_SIZE_3 1333
#define IDC_COMBO_BENCH_SIZE_4 1334
#define IDC_COMBO_BENCH_SIZE_5 1335
#define IDC_COMBO_BENCH_SIZE_8 1338
#define IDC_COMBO_BENCH_QUEUE_0 1340
#define IDC_COMBO_BENCH_QUEUE_1 1341
#define IDC_COMBO_BENCH_QUEUE_2 1342
#define IDC_COMBO_BENCH_QUEUE_3 1343
#define IDC_COMBO_BENCH_QUEUE_4 1344
#define IDC_COMBO_BENCH_QUEUE_5 1345
#define IDC_COMBO_BENCH_QUEUE_8 1348
#define IDC_COMBO_BENCH_THREAD_0 1350
#define IDC_COMBO_BENCH_THREAD_1 1351
#define IDC_COMBO_BENCH_THREAD_2 1352
#define IDC_COMBO_BENCH_THREAD_3 1353
#define IDC_COMBO_BENCH_THREAD_4 1354
#define IDC_COMBO_BENCH_THREAD_5 1355
#define IDC_COMBO_BENCH_THREAD_8 1358
#define ID_EXIT 32771
#define ID_ABOUT 32772
#define ID_THEME 32775
#define ID_THEME_DUMMY 32776
#define ID_COPY 32777
#define ID_LANGUAGE_DUMMY 32778
#define ID_LANGUAGE_A 32779
#define ID_LANGUAGE_O 32780
#define ID_A_DUMMY 32781
#define ID_O_DUMMY 32782
#define ID_BACK_PAGE 32787
#define ID_PRINT 32788
#define ID_FUNCTION_ZOOM 32789
#define ID_ZOOM_100 32803
#define ID_ZOOM_125 32804
#define ID_ZOOM_150 32805
#define ID_ZOOM_200 32806
#define ID_ZOOM_250 32807
#define ID_ZOOM_300 32808
#define ID_ZOOM_AUTO 33809
#define ID_HELP_HELP 32810
#define ID_CRYSTALDEWWORLD 32811
#define ID_FILE_BENCHMARKMODE 32812
#define ID_MODE_DEFAULT 32815
#define ID_MODE_ALL0X00 32816
#define ID_MODE_ALL0XFF 32817
#define ID_SETTINGS_QUEUESTHREADS 32818
#define ID_SAVE_TEXT 32819
#define ID_SAVE_IMAGE 32820
#define ID_FONT_SETTING 32821
#define ID_SETTING_DEFAULT 32822
#define ID_SETTING_NVME_8 32823
#define ID_SETTING_FLASH_MEMORY 32824
#define ID_INTERVAL_TIME_0 33820
#define ID_INTERVAL_TIME_1 33821
#define ID_INTERVAL_TIME_3 33822
#define ID_INTERVAL_TIME_5 33823
#define ID_INTERVAL_TIME_10 33824
#define ID_INTERVAL_TIME_30 33825
#define ID_INTERVAL_TIME_60 33826
#define ID_INTERVAL_TIME_180 33827
#define ID_INTERVAL_TIME_300 33828
#define ID_INTERVAL_TIME_600 33829
#define ID_PROFILE_DEFAULT 33830
#define ID_PROFILE_PEAK 33831
#define ID_PROFILE_REAL 33832
#define ID_PROFILE_DEMO 33833
#define ID_PROFILE_DEFAULT_MIX 33834
#define ID_PROFILE_PEAK_MIX 33835
#define ID_PROFILE_REAL_MIX 33836
#define ID_BENCHMARK_READ_WRITE 33837
#define ID_BENCHMARK_READ_ONLY 33838
#define ID_BENCHMARK_WRITE_ONLY 33839
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 141
#define _APS_NEXT_COMMAND_VALUE 33840
#define _APS_NEXT_CONTROL_VALUE 1360
#define _APS_NEXT_SYMED_VALUE 107
#endif
#endif
@@ -0,0 +1,5 @@
// stdafx.cpp : source file that includes just the standard includes
// DiskInfo.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
@@ -0,0 +1,228 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#ifndef _SECURE_ATL
#define _SECURE_ATL 1
#endif
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN
#endif
#ifndef WINVER
#define WINVER 0x0501
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#ifndef _WIN32_WINDOWS
#define _WIN32_WINDOWS 0x0410
#endif
#ifndef _WIN32_IE
#define _WIN32_IE 0x0600
#endif
#define _AFX_NO_MFC_CONTROLS_IN_DIALOGS
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS
#define _AFX_ALL_WARNINGS
#include <afxwin.h> // MFC core and standard component
#include <afxext.h> // Extended MFC
#include <afxdtctl.h> // MFC IE4 Common Control support
#include <afxcmn.h> // MFC Windows Common Control support
#include "CommonFx.h"
#include "UtilityFx.h"
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#ifdef UWP
#ifdef SUISHO_SHIZUKU_SUPPORT
#ifdef _M_ARM
#define PRODUCT_EDITION L"Shizuku Edition ARM32"
#elif _M_ARM64
#define PRODUCT_EDITION L"Shizuku Edition ARM64"
#elif _M_X64
#define PRODUCT_EDITION L"Shizuku Edition x64"
#else
#define PRODUCT_EDITION L"Shizuku Edition x86"
#endif
#else
#ifdef _M_ARM
#define PRODUCT_EDITION L"ARM32"
#elif _M_ARM64
#define PRODUCT_EDITION L"ARM64"
#elif _M_X64
#define PRODUCT_EDITION L"x64"
#else
#define PRODUCT_EDITION L"x86"
#endif
#endif
#else
#ifdef SUISHO_AOI_SUPPORT
#ifdef _M_ARM
#define PRODUCT_EDITION L"Aoi Edition ARM32"
#elif _M_ARM64
#define PRODUCT_EDITION L"Aoi Edition ARM64"
#elif _M_X64
#define PRODUCT_EDITION L"Aoi Edition x64"
#else
#define PRODUCT_EDITION L"Aoi Edition x86"
#endif
#elif MSI_MEI_SUPPORT
#ifdef _M_ARM
#define PRODUCT_EDITION L"MSI Mei Mihoshi Edition ARM32"
#elif _M_ARM64
#define PRODUCT_EDITION L"MSI Mei Mihoshi Edition ARM64"
#elif _M_X64
#define PRODUCT_EDITION L"MSI Mei Mihoshi Edition x64"
#else
#define PRODUCT_EDITION L"MSI Mei Mihoshi Edition x86"
#endif
#elif SUISHO_SHIZUKU_SUPPORT
#ifdef _M_ARM
#define PRODUCT_EDITION L"Shizuku Edition ARM32"
#elif _M_ARM64
#define PRODUCT_EDITION L"Shizuku Edition ARM64"
#elif _M_X64
#define PRODUCT_EDITION L"Shizuku Edition x64"
#else
#define PRODUCT_EDITION L"Shizuku Edition x86"
#endif
#else
#ifdef _M_ARM
#define PRODUCT_EDITION L"ARM32"
#elif _M_ARM64
#define PRODUCT_EDITION L"ARM64"
#elif _M_X64
#define PRODUCT_EDITION L"x64"
#else
#define PRODUCT_EDITION L"x86"
#endif
#endif
#endif
// Version Information
#define PRODUCT_NAME L"CrystalDiskMark"
#define PRODUCT_FILENAME L"CrystalDiskMark"
#define PRODUCT_VERSION L"9.0.3"
#define PRODUCT_SHORT_NAME L"CDM"
#define PRODUCT_RELEASE L"2026/05/24"
#define PRODUCT_COPY_YEAR L"2007-2026"
#define PRODUCT_LICENSE L"MIT License"
#ifdef SUISHO_AOI_SUPPORT
#define PRODUCT_COPYRIGHT_1 L"© 2007-2026 hiyohiyo"
#define PRODUCT_COPYRIGHT_2 L"© 2023-2026 nijihashi sola"
#define PRODUCT_COPYRIGHT_3 L""
#elif MSI_MEI_SUPPORT
#define PRODUCT_COPYRIGHT_1 L"© 2007-2026 hiyohiyo"
#define PRODUCT_COPYRIGHT_2 L"© 2024-2026 Micro-Star INT'L CO., LTD."
#define PRODUCT_COPYRIGHT_3 L""
#elif SUISHO_SHIZUKU_SUPPORT
#define PRODUCT_COPYRIGHT_1 L"© 2007-2026 hiyohiyo"
#define PRODUCT_COPYRIGHT_2 L"© 2012-2026 kirino kasumu"
#define PRODUCT_COPYRIGHT_3 L""
#else
#define PRODUCT_COPYRIGHT_1 L"© 2007-2026 hiyohiyo"
#define PRODUCT_COPYRIGHT_2 L""
#define PRODUCT_COPYRIGHT_3 L""
#endif
#ifdef MSI_MEI_SUPPORT
#define URL_MAIN_JA L"https://jp.msi.com/"
#define URL_MAIN_EN L"https://www.msi.com/"
#else
#define URL_MAIN_JA L"https://crystalmark.info/ja/"
#define URL_MAIN_EN L"https://crystalmark.info/en/"
#endif
#define URL_CRYSTAL_DEW_WORLD_JA L"https://crystalmark.info/ja/"
#define URL_CRYSTAL_DEW_WORLD_EN L"https://crystalmark.info/en/"
#define URL_VERSION_JA L"https://crystalmark.info/ja/software/crystaldiskmark/crystaldiskmark-history/"
#define URL_VERSION_EN L"https://crystalmark.info/en/software/crystaldiskmark/crystaldiskmark-history/"
#define URL_LICENSE_JA L"https://crystalmark.info/ja/software/crystaldiskmark/crystaldiskmark-license/"
#define URL_LICENSE_EN L"https://crystalmark.info/en/software/crystaldiskmark/crystaldiskmark-license/"
#define URL_HELP_JA L"https://crystalmark.info/ja/software/crystaldiskmark/"
#define URL_HELP_EN L"https://crystalmark.info/en/software/crystaldiskmark/"
#define URL_DISKSPD L"https://github.com/microsoft/diskspd"
#ifdef SUISHO_AOI_SUPPORT
#define URL_PROJECT_SITE_1 L"https://twitter.com/sola_no_crayon"
#define URL_PROJECT_SITE_2 L"https://twitter.com/harakeiko0718"
#define URL_PROJECT_SITE_3 L"https://instagram.com/kotomi_wicke?igshid=OGQ5ZDc2ODk2ZA=="
#define URL_PROJECT_SITE_4 L"https://twitter.com/bellche"
#define URL_PROJECT_SITE_5 L""
#elif MSI_MEI_SUPPORT
#define URL_PROJECT_SITE_1 L"https://jp.msi.com/Landing/mihoshimei/nb"
#define URL_PROJECT_SITE_2 L"https://twitter.com/hoshi_u3"
#define URL_PROJECT_SITE_3 L"https://twitter.com/mokowata"
#define URL_PROJECT_SITE_4 L"https://jp.msi.com/"
#define URL_PROJECT_SITE_5 L"https://jp.msi.com/"
#elif SUISHO_SHIZUKU_SUPPORT
#define URL_PROJECT_SITE_1 L"https://twitter.com/kirinokasumu"
#define URL_PROJECT_SITE_2 L"https://linux-ha.osdn.jp/wp/"
#define URL_PROJECT_SITE_3 L"https://ch.nicovideo.jp/oss"
#define URL_PROJECT_SITE_4 L"https://twitter.com/bellche"
#define URL_PROJECT_SITE_5 L"https://suishoshizuku.com/"
#endif
#define MAX_THREADS 64
#define MAX_QUEUES 512
static const int RE_EXEC = 5963;
#pragma warning(disable : 4996)
//------------------------------------------------
// Option Flags
//------------------------------------------------
// For Task Tray Icon Feature
// #define OPTION_TASK_TRAY
//------------------------------------------------
// Global Sttings
//------------------------------------------------
#define DEFAULT_FONT_FACE_1 L"Segoe UI"
#define DEFAULT_FONT_FACE_2 L"Tahoma"
#define THEME_DIR L"CdmResource\\themes\\"
#define LANGUAGE_DIR L"CdmResource\\language\\"
#define VOICE_DIR L"CdmResource\\voice\\"
#define MENU_THEME_INDEX 3
#define MENU_LANG_INDEX 5
#define DEFAULT_THEME L"Default"
#define DEFAULT_LANGUAGE L"English"
#define TIMER_UPDATE_DIALOG 500
#define WM_UPDATE_SCORE (WM_APP+0x1001)
#define WM_UPDATE_MESSAGE (WM_APP+0x1002)
#define WM_EXIT_BENCHMARK (WM_APP+0x1003)
@@ -0,0 +1,991 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "ButtonFx.h"
#if _MSC_VER <= 1310
#define ON_WM_MOUSEHOVER() \
{ 0x2A1 /*WM_MOUSEHOVER*/, 0, 0, 0, AfxSig_vwp, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) > (OnMouseHover)) },
#define ON_WM_MOUSELEAVE() \
{ 0x2A3 /*WM_MOUSELEAVE*/, 0, 0, 0, AfxSig_vv, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< void (AFX_MSG_CALL CWnd::*)(void) > (OnMouseLeave)) },
#endif
////------------------------------------------------
// CButtonFx
////------------------------------------------------
CButtonFx::CButtonFx()
{
// Control
m_X = 0;
m_Y = 0;
m_RenderMode = SystemDraw;
m_bHighContrast = FALSE;
m_bDarkMode = FALSE;
m_bDrawFrame = FALSE;
m_FrameColor = RGB(128, 128, 128);
m_hPal = NULL;
// Glass
m_GlassColor = RGB(255, 255, 255);
m_GlassAlpha = 255;
// Meter
m_bMeter = FALSE;
m_MeterRatio = 0.0;
// Image
m_ImageCount = 0;
m_BkDC = NULL;
m_bBkBitmapInit = FALSE;
m_bBkLoad = FALSE;
// Font
m_TextAlign = BS_LEFT;
m_TextColor = RGB(0, 0, 0);
// Mouse
m_bHover = FALSE;
m_bFocas = FALSE;
m_bTrackingNow = FALSE;
m_bHandCursor = FALSE;
m_bSelected = FALSE;
// Text Format
m_TextFormat = 0;
m_LabelFormat = DT_LEFT | DT_TOP | DT_SINGLELINE;
m_UnitFormat = DT_RIGHT | DT_BOTTOM | DT_SINGLELINE;
// Margin
m_Margin.top = 0;
m_Margin.left = 0;
m_Margin.bottom = 0;
m_Margin.right = 0;
}
CButtonFx::~CButtonFx()
{
}
IMPLEMENT_DYNAMIC(CButtonFx, CButton)
BEGIN_MESSAGE_MAP(CButtonFx, CButton)
//{{AFX_MSG_MAP(CButtonFx)
ON_WM_ERASEBKGND()
ON_WM_MOUSEMOVE()
ON_WM_MOUSEHOVER()
ON_WM_MOUSELEAVE()
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
ON_WM_SETCURSOR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//------------------------------------------------
// Control
//------------------------------------------------
BOOL CButtonFx::InitControl(int x, int y, int width, int height, double zoomRatio, HPALETTE hPal, CDC* bkDC,
LPCTSTR imagePath, int imageCount, DWORD textAlign, int renderMode, BOOL bHighContrast, BOOL bDarkMode, BOOL bDrawFrame)
{
m_X = (int)(x * zoomRatio);
m_Y = (int)(y * zoomRatio);
m_CtrlSize.cx = (int)(width * zoomRatio + 0.5);
m_CtrlSize.cy = (int)(height * zoomRatio + 0.5);
MoveWindow(m_X, m_Y, m_CtrlSize.cx, m_CtrlSize.cy);
m_hPal = hPal;
m_BkDC = bkDC;
m_ImagePath = imagePath;
m_ImageCount = imageCount;
m_RenderMode = renderMode;
if (BS_LEFT <= textAlign && textAlign <= BS_CENTER)
{
m_TextAlign = textAlign;
}
if(m_ToolTip.m_hWnd != NULL)
{
if (m_ToolTip.GetToolCount() != 0)
{
m_ToolTip.DelTool(this, 1);
}
CRect rect;
GetClientRect(rect);
m_ToolTip.AddTool(this, m_ToolTipText, rect, 1);
}
m_bHighContrast = bHighContrast;
m_bDarkMode = bDarkMode;
m_bDrawFrame = bDrawFrame;
if (m_bHighContrast)
{
ModifyStyle(BS_OWNERDRAW, m_TextAlign);
return TRUE;
}
else if(renderMode & SystemDraw)
{
ModifyStyle(BS_OWNERDRAW, m_TextAlign);
return TRUE;
}
else
{
SetBkReload();
ModifyStyle(0, BS_OWNERDRAW);
}
if (renderMode & OwnerDrawImage)
{
if (!LoadBitmap(imagePath))
{
ModifyStyle(BS_OWNERDRAW, m_TextAlign);
}
}
else
{
m_ImageCount = 1;
m_CtrlImage.Destroy();
m_CtrlImage.Create(m_CtrlSize.cx, m_CtrlSize.cy * m_ImageCount, 32);
m_CtrlBitmap.Detach();
m_CtrlBitmap.Attach((HBITMAP)m_CtrlImage);
DWORD length = m_CtrlSize.cx * m_CtrlSize.cy * m_ImageCount * 4;
BYTE* bitmapBits = new BYTE[length];
m_CtrlBitmap.GetBitmapBits(length, bitmapBits);
BYTE r, g, b, a;
if (renderMode & OwnerDrawGlass)
{
r = (BYTE)GetRValue(m_GlassColor);
g = (BYTE)GetGValue(m_GlassColor);
b = (BYTE)GetBValue(m_GlassColor);
a = m_GlassAlpha;
}
else // OwnerDrawTransparent
{
r = 0;
g = 0;
b = 0;
a = 0;
}
for (int y = 0; y < (int)(m_CtrlSize.cy * m_ImageCount); y++)
{
for (int x = 0; x < m_CtrlSize.cx; x++)
{
DWORD p = (y * m_CtrlSize.cx + x) * 4;
#if _MSC_VER > 1310
#pragma warning( disable : 6386 )
#endif
bitmapBits[p + 0] = b;
bitmapBits[p + 1] = g;
bitmapBits[p + 2] = r;
bitmapBits[p + 3] = a;
#if _MSC_VER > 1310
#pragma warning( default : 6386 )
#endif
}
}
m_CtrlBitmap.SetBitmapBits(length, bitmapBits);
delete[] bitmapBits;
}
Invalidate();
return TRUE;
}
BOOL CButtonFx::ReloadImage(LPCTSTR imagePath, UINT imageCount)
{
if (imagePath != NULL && m_ImagePath.Compare(imagePath) == 0)
{
return FALSE;
}
m_ImagePath = imagePath;
m_ImageCount = imageCount;
LoadBitmap(imagePath);
Invalidate();
return TRUE;
}
void CButtonFx::SetMargin(int top, int left, int bottom, int right, double zoomRatio)
{
m_Margin.top = (int)(top * zoomRatio);
m_Margin.left = (int)(left * zoomRatio);
m_Margin.bottom = (int)(bottom * zoomRatio);
m_Margin.right = (int)(right * zoomRatio);
}
CSize CButtonFx::GetSize(void)
{
return m_CtrlSize;
}
void CButtonFx::SetDrawFrame(BOOL bDrawFrame)
{
if (bDrawFrame && m_bHighContrast)
{
ModifyStyleEx(0, WS_EX_STATICEDGE, SWP_DRAWFRAME);
}
else
{
ModifyStyleEx(WS_EX_STATICEDGE, 0, SWP_DRAWFRAME);
}
m_bDrawFrame = bDrawFrame;
}
void CButtonFx::SetGlassColor(COLORREF glassColor, BYTE glassAlpha)
{
m_GlassColor = glassColor;
m_GlassAlpha = glassAlpha;
}
void CButtonFx::SetMeter(BOOL bMeter, double meterRatio)
{
m_bMeter = bMeter;
if (meterRatio > 1.0)
{
m_MeterRatio = 1.0;
}
else if (meterRatio > 0)
{
m_MeterRatio = meterRatio;
}
else
{
m_MeterRatio = 0.0;
}
Invalidate();
}
void CButtonFx::SetLabelUnit(CString label, CString unit)
{
m_Label = label;
m_Unit = unit;
}
void CButtonFx::SetLabelUnitFormat(UINT labelFormat, UINT unitFormat)
{
m_LabelFormat = labelFormat;
m_UnitFormat = unitFormat;
}
void CButtonFx::SetTextFormat(UINT format)
{
m_TextFormat = format;
}
//------------------------------------------------
// Draw Control
//------------------------------------------------
void CButtonFx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (m_bHighContrast) { return CButton::DrawItem(lpDrawItemStruct); }
CDC* drawDC = CDC::FromHandle(lpDrawItemStruct->hDC);
LoadCtrlBk(drawDC);
if (! (GetStyle() & BS_NOTIFY))
{
DrawControl(drawDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageNormal);
}
else if (IsWindowEnabled())
{
if (m_bSelected && m_ImageCount > ControlImageSelected)
{
DrawControl(drawDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageSelected);
}
else if ((lpDrawItemStruct->itemState & ODS_SELECTED || m_bHover) && m_ImageCount > ControlImageHover)
{
DrawControl(drawDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageHover);
}
else if ((lpDrawItemStruct->itemState & ODS_FOCUS || m_bFocas) && m_ImageCount > ControlImageFocus)
{
DrawControl(drawDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageFocus);
}
else
{
DrawControl(drawDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageNormal);
}
}
else
{
if (m_ImageCount > ControlImageDisabled)
{
DrawControl(drawDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageDisabled);
}
else
{
DrawControl(drawDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageNormal);
}
}
}
void CButtonFx::DrawControl(CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, CBitmap& ctrlBitmap, CBitmap& bkBitmap, int no)
{
CDC* pMemDC = new CDC;
CBitmap* pOldMemBitmap;
if(m_hPal && drawDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( drawDC->GetSafeHdc(), m_hPal, FALSE );
drawDC->RealizePalette();
drawDC->SetStretchBltMode(HALFTONE);
}
pMemDC->CreateCompatibleDC(drawDC);
if(m_hPal && pMemDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( pMemDC->GetSafeHdc(), m_hPal, FALSE );
pMemDC->RealizePalette();
pMemDC->SetStretchBltMode(HALFTONE);
}
pOldMemBitmap = pMemDC->SelectObject(&ctrlBitmap);
CDC* pBkDC = new CDC;
CBitmap* pOldBkBitmap;
pBkDC->CreateCompatibleDC(drawDC);
if(m_hPal && pBkDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( pBkDC->GetSafeHdc(), m_hPal, FALSE );
pBkDC->RealizePalette();
pBkDC->SetStretchBltMode(HALFTONE);
}
pOldBkBitmap = pBkDC->SelectObject(&bkBitmap);
CBitmap DrawBmp;
DrawBmp.CreateCompatibleBitmap(drawDC, m_CtrlSize.cx, m_CtrlSize.cy);
CDC* pDrawBmpDC = new CDC;
CBitmap* pOldDrawBitmap;
pDrawBmpDC->CreateCompatibleDC(drawDC);
if(m_hPal && pDrawBmpDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( pDrawBmpDC->GetSafeHdc(), m_hPal, FALSE );
pDrawBmpDC->RealizePalette();
pDrawBmpDC->SetStretchBltMode(HALFTONE);
}
pOldDrawBitmap = pDrawBmpDC->SelectObject(&DrawBmp);
int color = drawDC->GetDeviceCaps(BITSPIXEL) * drawDC->GetDeviceCaps(PLANES);
if (!m_CtrlImage.IsNull())
{
if (m_CtrlImage.GetBPP() == 32)
{
CBitmap* bk32Bitmap;
CImage bk32Image;
if (color == 32)
{
bk32Bitmap = &bkBitmap;
}
else
{
bk32Image.Create(m_CtrlSize.cx, m_CtrlSize.cy, 32);
::StretchBlt(bk32Image.GetDC(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, *pBkDC, 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
bk32Bitmap = CBitmap::FromHandle((HBITMAP)bk32Image);
}
BITMAP CtlBmpInfo, DstBmpInfo;
bk32Bitmap->GetBitmap(&DstBmpInfo);
DWORD DstLineBytes = DstBmpInfo.bmWidthBytes;
DWORD DstMemSize = DstLineBytes * DstBmpInfo.bmHeight;
ctrlBitmap.GetBitmap(&CtlBmpInfo);
DWORD CtlLineBytes = CtlBmpInfo.bmWidthBytes;
DWORD CtlMemSize = CtlLineBytes * CtlBmpInfo.bmHeight;
if ((DstBmpInfo.bmWidthBytes != CtlBmpInfo.bmWidthBytes)
|| (DstBmpInfo.bmHeight != CtlBmpInfo.bmHeight / m_ImageCount))
{
// Error Check //
}
else
{
BYTE* DstBuffer = new BYTE[DstMemSize];
bk32Bitmap->GetBitmapBits(DstMemSize, DstBuffer);
BYTE* CtlBuffer = new BYTE[CtlMemSize];
ctrlBitmap.GetBitmapBits(CtlMemSize, CtlBuffer);
if (m_bMeter)
{
int meter = (int)(m_CtrlSize.cx * m_MeterRatio);
int baseY;
baseY = m_CtrlSize.cy;
for (LONG py = 0; py < DstBmpInfo.bmHeight; py++)
{
int dn = py * DstLineBytes;
int cn = (baseY + py) * CtlLineBytes;
for (LONG px = 0; px < meter; px++)
{
BYTE a = CtlBuffer[cn + 3];
BYTE na = 255 - a;
DstBuffer[dn + 0] = (BYTE)((CtlBuffer[cn + 0] * a + DstBuffer[dn + 0] * na) / 255);
DstBuffer[dn + 1] = (BYTE)((CtlBuffer[cn + 1] * a + DstBuffer[dn + 1] * na) / 255);
DstBuffer[dn + 2] = (BYTE)((CtlBuffer[cn + 2] * a + DstBuffer[dn + 2] * na) / 255);
dn += (DstBmpInfo.bmBitsPixel / 8);
cn += (CtlBmpInfo.bmBitsPixel / 8);
}
cn -= baseY * CtlLineBytes;
for (LONG px = meter; px < DstBmpInfo.bmWidth; px++)
{
BYTE a = CtlBuffer[cn + 3];
BYTE na = 255 - a;
DstBuffer[dn + 0] = (BYTE)((CtlBuffer[cn + 0] * a + DstBuffer[dn + 0] * na) / 255);
DstBuffer[dn + 1] = (BYTE)((CtlBuffer[cn + 1] * a + DstBuffer[dn + 1] * na) / 255);
DstBuffer[dn + 2] = (BYTE)((CtlBuffer[cn + 2] * a + DstBuffer[dn + 2] * na) / 255);
dn += (DstBmpInfo.bmBitsPixel / 8);
cn += (CtlBmpInfo.bmBitsPixel / 8);
}
}
}
else
{
int baseY = m_CtrlSize.cy * no;
for (LONG py = 0; py < DstBmpInfo.bmHeight; py++)
{
int dn = py * DstLineBytes;
int cn = (baseY + py) * CtlLineBytes;
for (LONG px = 0; px < DstBmpInfo.bmWidth; px++)
{
#if _MSC_VER > 1310
#pragma warning( disable : 6385 )
#pragma warning( disable : 6386 )
#endif
BYTE a = CtlBuffer[cn + 3];
BYTE na = 255 - a;
DstBuffer[dn + 0] = (BYTE)((CtlBuffer[cn + 0] * a + DstBuffer[dn + 0] * na) / 255);
DstBuffer[dn + 1] = (BYTE)((CtlBuffer[cn + 1] * a + DstBuffer[dn + 1] * na) / 255);
DstBuffer[dn + 2] = (BYTE)((CtlBuffer[cn + 2] * a + DstBuffer[dn + 2] * na) / 255);
dn += (DstBmpInfo.bmBitsPixel / 8);
cn += (CtlBmpInfo.bmBitsPixel / 8);
#if _MSC_VER > 1310
#pragma warning( default : 6386 )
#pragma warning( default : 6385 )
#endif
}
}
}
if (color == 32)
{
DrawBmp.SetBitmapBits(DstMemSize, DstBuffer);
}
else
{
bk32Bitmap->SetBitmapBits(DstMemSize, DstBuffer);
::StretchBlt(pDrawBmpDC->GetSafeHdc(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, bk32Image.GetDC(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
bk32Image.ReleaseDC();
}
DrawString(pDrawBmpDC, lpDrawItemStruct);
drawDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
delete[] DstBuffer;
delete[] CtlBuffer;
}
}
else
{
if (m_bMeter)
{
int meter = (int)(m_CtrlSize.cx * (m_MeterRatio));
pDrawBmpDC->StretchBlt(meter, 0, m_CtrlSize.cx - meter, m_CtrlSize.cy, pMemDC, meter, m_CtrlSize.cy * 0, m_CtrlSize.cx - meter, m_CtrlSize.cy, SRCCOPY);
pDrawBmpDC->StretchBlt(0, 0, meter, m_CtrlSize.cy, pMemDC, 0, m_CtrlSize.cy * 1, meter, m_CtrlSize.cy, SRCCOPY);
DrawString(pDrawBmpDC, lpDrawItemStruct);
drawDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
}
else
{
pDrawBmpDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pMemDC, 0, m_CtrlSize.cy * no, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
DrawString(pDrawBmpDC, lpDrawItemStruct);
drawDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
}
}
}
else
{
pDrawBmpDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pBkDC, 0, m_CtrlSize.cy * no, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
DrawString(pDrawBmpDC, lpDrawItemStruct);
drawDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
}
if (m_bDrawFrame)
{
HGDIOBJ oldPen;
POINT point;
COLORREF color1;
COLORREF color2;
if (m_bHover)
{
color1 = RGB(0x20, 0x98, 0xF4);
color2 = RGB(0x20, 0x8B, 0xDE);
}
else
{
// Windows 11 color
color1 = RGB(0x00, 0x78, 0xD4);
color2 = RGB(0x00, 0x6B, 0xBE);
}
CPen pen1; pen1.CreatePen(PS_SOLID, 1, color1);
CPen pen2; pen2.CreatePen(PS_SOLID, 1, color2);
oldPen = SelectObject(drawDC->m_hDC, pen1);
MoveToEx(drawDC->m_hDC, 0, m_CtrlSize.cy - 1, &point);
LineTo(drawDC->m_hDC, m_CtrlSize.cx - 1, m_CtrlSize.cy - 1);
LineTo(drawDC->m_hDC, m_CtrlSize.cx - 1, 0);
LineTo(drawDC->m_hDC, m_CtrlSize.cx - 1, m_CtrlSize.cy - 1);
SelectObject(drawDC->m_hDC, pen2);
MoveToEx(drawDC->m_hDC, 0, m_CtrlSize.cy - 2, &point);
LineTo(drawDC->m_hDC, 0, 0);
LineTo(drawDC->m_hDC, m_CtrlSize.cx - 1, 0);
SelectObject(drawDC->m_hDC, oldPen);
pen1.DeleteObject();
pen2.DeleteObject();
}
pDrawBmpDC->SelectObject(&pOldDrawBitmap);
pDrawBmpDC->DeleteDC();
delete pDrawBmpDC;
pMemDC->SelectObject(&pOldMemBitmap);
pMemDC->DeleteDC();
delete pMemDC;
pBkDC->SelectObject(&pOldBkBitmap);
pBkDC->DeleteDC();
delete pBkDC;
}
void CButtonFx::DrawString(CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CString title;
GetWindowText(title);
if (title.IsEmpty())
{
return;
}
drawDC->SetBkMode(TRANSPARENT);
CRect rect = (CRect)(lpDrawItemStruct->rcItem);
rect.top += m_Margin.top;
rect.left += m_Margin.left;
rect.bottom -= m_Margin.bottom;
rect.right -= m_Margin.right;
HGDIOBJ oldFont = drawDC->SelectObject(m_Font);
CArray<CString, CString> arr;
arr.RemoveAll();
CString resToken;
int curPos = 0;
resToken = title.Tokenize(_T("\r\n"), curPos);
while (resToken != _T(""))
{
arr.Add(resToken);
resToken = title.Tokenize(_T("\r\n"), curPos);
}
CSize extent;
if ((m_RenderMode & OwnerDrawTransparent) && m_bDarkMode)
{
SetTextColor(drawDC->m_hDC, RGB(255, 255, 255));
}
else
{
SetTextColor(drawDC->m_hDC, m_TextColor);
}
if (m_bMeter && rect.Width() < extent.cx)
{
title.Replace(_T(","), _T("."));
int score = _tstoi((LPCTSTR)title);
title.Format(_T("%d"), score);
extent = drawDC->GetTextExtent(title);
}
if (!m_Label.IsEmpty() && m_TextFormat != BS_CENTER)
{
drawDC->DrawText(title, title.GetLength(), rect, m_TextFormat);
drawDC->SelectObject(oldFont);
oldFont = drawDC->SelectObject(m_FontToolTip);
drawDC->DrawText(m_Label, m_Label.GetLength(), rect, m_LabelFormat);
drawDC->DrawText(m_Unit, m_Unit.GetLength(), rect, m_UnitFormat);
}
else if (!m_Label.IsEmpty())
{
drawDC->DrawText(title, title.GetLength(), rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawDC->SelectObject(oldFont);
oldFont = drawDC->SelectObject(m_FontToolTip);
drawDC->DrawText(m_Label, m_Label.GetLength(), rect, m_LabelFormat);
drawDC->DrawText(m_Unit, m_Unit.GetLength(), rect, m_UnitFormat);
}
else
{
for (int i = 0; i < arr.GetCount(); i++)
{
CRect r;
r.top = rect.top + (LONG)(((double)rect.Height()) / arr.GetCount() * i);
r.bottom = rect.top + (LONG)(((double)rect.Height()) / arr.GetCount() * (i + 1.0));
r.left = rect.left;
r.right = rect.right;
CRect rectI;
HGDIOBJ oldFont = drawDC->SelectObject(m_Font);
if ((m_RenderMode & OwnerDrawTransparent) && m_bDarkMode)
{
SetTextColor(drawDC->m_hDC, RGB(255, 255, 255));
}
else
{
SetTextColor(drawDC->m_hDC, m_TextColor);
}
GetTextExtentPoint32(drawDC->m_hDC, arr.GetAt(i), arr.GetAt(i).GetLength() + 1, &extent);
if (m_TextAlign == BS_LEFT)
{
drawDC->DrawText(arr.GetAt(i), arr.GetAt(i).GetLength(), r, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
else if (m_TextAlign == BS_RIGHT)
{
drawDC->DrawText(arr.GetAt(i), arr.GetAt(i).GetLength(), r, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
}
else
{
drawDC->DrawText(arr.GetAt(i), arr.GetAt(i).GetLength(), r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
drawDC->SelectObject(oldFont);
}
}
}
//------------------------------------------------
// Image
//------------------------------------------------
BOOL CButtonFx::LoadBitmap(LPCTSTR fileName)
{
if (m_bHighContrast) { return FALSE; }
if (fileName == NULL) { return FALSE; }
m_CtrlImage.Destroy();
m_CtrlImage.Load(fileName);
if (m_CtrlImage.IsNull()) { return FALSE; }
return LoadBitmap((HBITMAP)m_CtrlImage);
}
BOOL CButtonFx::LoadBitmap(HBITMAP hBitmap)
{
if (m_bHighContrast) { return FALSE; }
m_CtrlBitmap.Detach();
m_CtrlBitmap.Attach(hBitmap);
return SetBitmap(m_CtrlBitmap);
}
void CButtonFx::SetBkReload(void)
{
m_bBkBitmapInit = FALSE;
m_bBkLoad = FALSE;
}
BOOL CButtonFx::SetBitmap(CBitmap& bitmap)
{
if (m_bHighContrast) { return FALSE; }
BITMAP bitmapInfo;
bitmap.GetBitmap(&bitmapInfo);
if (m_CtrlSize.cx != bitmapInfo.bmWidth
|| m_CtrlSize.cy != bitmapInfo.bmHeight / m_ImageCount)
{
ModifyStyle(BS_OWNERDRAW, 0);
return FALSE;
}
else
{
ModifyStyle(0, BS_OWNERDRAW);
return TRUE;
}
}
void CButtonFx::LoadCtrlBk(CDC* drawDC)
{
if (m_bHighContrast) { SetBkReload(); return; }
if (m_BkBitmap.m_hObject != NULL)
{
BITMAP bitmapInfo;
m_BkBitmap.GetBitmap(&bitmapInfo);
if (bitmapInfo.bmBitsPixel != drawDC->GetDeviceCaps(BITSPIXEL))
{
SetBkReload();
}
}
if (&m_CtrlBitmap != NULL)
{
if (!m_bBkBitmapInit)
{
m_BkBitmap.DeleteObject();
m_BkBitmap.CreateCompatibleBitmap(drawDC, m_CtrlSize.cx, m_CtrlSize.cy);
m_bBkBitmapInit = TRUE;
}
if (!m_bBkLoad)
{
CBitmap* pOldBitmap;
CDC* pMemDC = new CDC;
pMemDC->CreateCompatibleDC(drawDC);
pOldBitmap = pMemDC->SelectObject(&m_BkBitmap);
pMemDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, m_BkDC, m_X, m_Y, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
pMemDC->SelectObject(pOldBitmap);
pMemDC->DeleteDC();
delete pMemDC;
m_bBkLoad = TRUE;
}
}
}
//------------------------------------------------
// Font
//------------------------------------------------
void CButtonFx::SetFontEx(CString face, int size, int sizeToolTip, double zoomRatio, double fontRatio, COLORREF textColor, LONG fontWeight, BYTE fontRender)
{
LOGFONT logFont = { 0 };
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfHeight = (LONG)(-1 * size * zoomRatio * fontRatio);
logFont.lfQuality = fontRender;
logFont.lfWeight = fontWeight;
if (face.GetLength() < 32)
{
wsprintf(logFont.lfFaceName, _T("%s"), (LPCTSTR)face);
}
else
{
wsprintf(logFont.lfFaceName, _T(""));
}
m_Font.DeleteObject();
m_Font.CreateFontIndirect(&logFont);
SetFont(&m_Font);
logFont.lfHeight = (LONG)(-1 * sizeToolTip * zoomRatio * fontRatio);
m_FontToolTip.DeleteObject();
m_FontToolTip.CreateFontIndirect(&logFont);
m_TextColor = textColor;
if (m_ToolTip.m_hWnd != NULL)
{
m_ToolTip.SetFont(&m_FontToolTip);
}
}
//------------------------------------------------
// Mouse
//------------------------------------------------
void CButtonFx::SetHandCursor(BOOL bHandCuror)
{
m_bHandCursor = bHandCuror;
}
void CButtonFx::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bTrackingNow)
{
#if _MSC_VER <= 1310
typedef BOOL(WINAPI* Func_TrackMouseEvent)(LPTRACKMOUSEEVENT);
static Func_TrackMouseEvent p_TrackMouseEvent = NULL;
static BOOL bInit_TrackMouseEvent = FALSE;
if (bInit_TrackMouseEvent && p_TrackMouseEvent == NULL)
{
return; // TrackMouseEvent is not available
}
else
{
HMODULE hModule = GetModuleHandle(_T("user32.dll"));
if (hModule)
{
p_TrackMouseEvent = (Func_TrackMouseEvent)GetProcAddress(hModule, "TrackMouseEvent");
}
}
if (p_TrackMouseEvent != NULL)
{
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bTrackingNow = p_TrackMouseEvent(&tme);
}
bInit_TrackMouseEvent = TRUE;
#else
if (!m_bTrackingNow)
{
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bTrackingNow = _TrackMouseEvent(&tme);
}
#endif
}
CButton::OnMouseMove(nFlags, point);
}
void CButtonFx::OnMouseHover(UINT nFlags, CPoint point)
{
#if _MSC_VER > 1310
CButton::OnMouseHover(nFlags, point);
#endif
m_bHover = TRUE;
Invalidate();
}
void CButtonFx::OnMouseLeave()
{
#if _MSC_VER > 1310
CButton::OnMouseLeave();
#endif
m_bTrackingNow = FALSE;
m_bHover = FALSE;
Invalidate();
}
void CButtonFx::OnSetfocus()
{
m_bFocas = TRUE;
Invalidate();
}
void CButtonFx::OnKillfocus()
{
m_bFocas = FALSE;
Invalidate();
}
BOOL CButtonFx::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
HCURSOR hCursor = NULL;
if (m_bHandCursor)
{
hCursor = AfxGetApp()->LoadStandardCursor(IDC_HAND);
if (hCursor)
{
::SetCursor(hCursor);
}
}
else
{
hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
if (hCursor)
{
::SetCursor(hCursor);
}
}
return TRUE;
}
void CButtonFx::SetSelected(BOOL bSelected)
{
m_bSelected = bSelected;
Invalidate();
}
//------------------------------------------------
// ToolTip
//------------------------------------------------
void CButtonFx::SetToolTipText(LPCTSTR text)
{
if (text == NULL) { return; }
InitToolTip();
m_ToolTipText = text;
if (m_ToolTip.GetToolCount() == 0)
{
CRect rect;
GetClientRect(rect);
m_ToolTip.AddTool(this, m_ToolTipText, rect, 1);
}
else
{
m_ToolTip.UpdateTipText(m_ToolTipText, this, 1);
}
SetToolTipActivate(TRUE);
}
void CButtonFx::SetToolTipActivate(BOOL bActivate)
{
if (m_ToolTip.GetToolCount() == 0) { return; }
m_ToolTip.Activate(bActivate);
}
void CButtonFx::SetToolTipWindowText(LPCTSTR text)
{
SetToolTipText(text);
SetWindowText(text);
}
CString CButtonFx::GetToolTipText()
{
return m_ToolTipText;
}
void CButtonFx::InitToolTip()
{
if (m_ToolTip.m_hWnd == NULL)
{
m_ToolTip.Create(this, TTS_ALWAYSTIP | TTS_BALLOON | TTS_NOANIMATE | TTS_NOFADE);
m_ToolTip.Activate(FALSE);
m_ToolTip.SetFont(&m_FontToolTip);
m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, 1024);
m_ToolTip.SetDelayTime(TTDT_AUTOPOP, 8000);
m_ToolTip.SetDelayTime(TTDT_INITIAL, 500);
m_ToolTip.SetDelayTime(TTDT_RESHOW, 100);
}
}
BOOL CButtonFx::PreTranslateMessage(MSG* pMsg)
{
InitToolTip();
m_ToolTip.RelayEvent(pMsg);
return CButton::PreTranslateMessage(pMsg);
}
BOOL CButtonFx::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
@@ -0,0 +1,131 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include <afxtempl.h>
#include "ImageFx.h"
class CButtonFx : public CButton
{
DECLARE_DYNAMIC(CButtonFx);
public:
// Constructors
CButtonFx();
virtual ~CButtonFx();
// Control
BOOL InitControl(int x, int y, int width, int height, double zoomRatio, HPALETTE hPal, CDC* bkDC,
LPCTSTR imagePath, int imageCount, DWORD textAlign, int renderMode, BOOL bHighContrast, BOOL bDarkMode, BOOL bDrawFrame);
BOOL ReloadImage(LPCTSTR imagePath, UINT imageCount);
void SetMargin(int top, int left, int bottom, int right, double zoomRatio);
CSize GetSize(void);
void SetDrawFrame(BOOL bDrawFrame);
void SetGlassColor(COLORREF glassColor, BYTE glassAlpha);
void SetMeter(BOOL bMeter, double meterRatio);
void SetLabelUnit(CString label, CString unit);
void SetLabelUnitFormat(UINT labelFormat, UINT unitFormat);
void SetTextFormat(UINT format);
// Font
void SetFontEx(CString face, int size, int sizeToolTip, double zoomRatio, double fontRatio = 1.0,
COLORREF textColor = RGB(0, 0, 0), LONG fontWeight = FW_NORMAL, BYTE fontRender = CLEARTYPE_NATURAL_QUALITY);
// Mouse
void SetHandCursor(BOOL bHandCuror = TRUE);
void SetSelected(BOOL bSelected = TRUE);
// ToolTip
void SetToolTipText(LPCTSTR text);
void SetToolTipActivate(BOOL bActivate = TRUE);
void SetToolTipWindowText(LPCTSTR text);
CString GetToolTipText();
protected:
// Draw Control
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
virtual void DrawControl(CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, CBitmap& ctrlBitmap, CBitmap& bkBitmap, int no);
virtual void DrawString(CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct);
// Image
BOOL LoadBitmap(LPCTSTR pFileName);
BOOL LoadBitmap(HBITMAP hBitmap);
void SetBkReload(void);
BOOL SetBitmap(CBitmap& bitmap);
void LoadCtrlBk(CDC* drawDC);
// ToolTip
void InitToolTip();
virtual BOOL PreTranslateMessage(MSG* pMsg);
// Message Map
DECLARE_MESSAGE_MAP()
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnMouseHover(UINT nFlags, CPoint point);
afx_msg void OnMouseLeave();
afx_msg void OnKillfocus();
afx_msg void OnSetfocus();
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
protected:
// Control
int m_X;
int m_Y;
CSize m_CtrlSize;
CRect m_Margin;
int m_RenderMode;
BOOL m_bHighContrast;
BOOL m_bDarkMode;
BOOL m_bDrawFrame;
COLORREF m_FrameColor;
HPALETTE m_hPal;
CString m_Label;
CString m_Unit;
UINT m_TextFormat;
UINT m_LabelFormat;
UINT m_UnitFormat;
// Glass
COLORREF m_GlassColor;
BYTE m_GlassAlpha;
// Meter
BOOL m_bMeter;
double m_MeterRatio;
// Image
CString m_ImagePath;
int m_ImageCount;
CDC* m_BkDC;
CBitmap m_BkBitmap;
BOOL m_bBkBitmapInit;
BOOL m_bBkLoad;
CBitmap m_CtrlBitmap;
CImage m_CtrlImage;
// Font
DWORD m_TextAlign;
CFont m_Font;
CFont m_FontToolTip;
COLORREF m_TextColor;
// ToolTip
CToolTipCtrl m_ToolTip;
CString m_ToolTipText;
// Mouse
BOOL m_bHover;
BOOL m_bFocas;
BOOL m_bTrackingNow;
BOOL m_bHandCursor;
BOOL m_bSelected;
};
@@ -0,0 +1,836 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "ComboBoxFx.h"
#if _MSC_VER <= 1310
#define ON_WM_MOUSEHOVER() \
{ 0x2A1 /*WM_MOUSEHOVER*/, 0, 0, 0, AfxSig_vwp, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) > (OnMouseHover)) },
#define ON_WM_MOUSELEAVE() \
{ 0x2A3 /*WM_MOUSELEAVE*/, 0, 0, 0, AfxSig_vv, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< void (AFX_MSG_CALL CWnd::*)(void) > (OnMouseLeave)) },
#endif
////------------------------------------------------
// CComboBoxFx
////------------------------------------------------
CComboBoxFx::CComboBoxFx()
{
// Control
m_X = 0;
m_Y = 0;
m_ZoomRatio = 1.0;
m_bHighContrast = FALSE;
m_bDarkMode = FALSE;
m_RenderMode = SystemDraw;
m_Margin.top = 0;
m_Margin.left = 0;
m_Margin.bottom = 0;
m_Margin.right = 0;
// Alpha/Glass
m_Alpha = 255;
m_GlassColor = RGB(255, 255, 255);
m_GlassAlpha = 255;
// Image
m_ImageCount = 0;
m_ImagePath = _T("");
m_BkDC = NULL;
m_bBkBitmapInit = FALSE;
m_bBkLoad = FALSE;
// Font
m_TextAlign = SS_LEFT;
m_TextColor = RGB(0, 0, 0);
m_TextColorSelected = RGB(255, 255, 255);
m_BkColor = RGB(255, 255, 255);
m_BkColorSelected = RGB(230, 230, 230);
m_TextColorHc = RGB(255, 255, 255);
m_TextColorSelectedHc = RGB(0, 0, 0);
m_BkColorHc = RGB(0, 0, 0);
m_BkColorSelectedHc = RGB(0, 255, 255);
m_FontHeight = 16;
m_FontRender = CLEARTYPE_NATURAL_QUALITY;
// Mouse
m_bHover = FALSE;
m_bFocas = FALSE;
m_bTrackingNow = FALSE;
m_bHandCursor = FALSE;
}
CComboBoxFx::~CComboBoxFx()
{
m_BkBrush.DeleteObject();
}
IMPLEMENT_DYNAMIC(CComboBoxFx, CComboBox)
BEGIN_MESSAGE_MAP(CComboBoxFx, CComboBox)
//{{AFX_MSG_MAP(CComboBoxFx)
ON_WM_CTLCOLOR()
ON_WM_MOUSEMOVE()
ON_WM_MOUSEHOVER()
ON_WM_MOUSELEAVE()
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
ON_WM_SETCURSOR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//------------------------------------------------
// Control
//------------------------------------------------
BOOL CComboBoxFx::InitControl(int x, int y, int width, int height, double zoomRatio, CDC* bkDC,
LPCWSTR imagePath, int imageCount, DWORD textAlign, int renderMode, BOOL bHighContrast, BOOL bDarkMode,
COLORREF bkColor, COLORREF bkColorSelected, COLORREF glassColor, BYTE glassAlpha)
{
m_X = (int)(x * zoomRatio);
m_Y = (int)(y * zoomRatio);
m_ZoomRatio = zoomRatio;
m_CtrlSize.cx = (int)(width * zoomRatio);
m_CtrlSize.cy = (int)(height * zoomRatio);
MoveWindow(m_X, m_Y, m_CtrlSize.cx, m_CtrlSize.cy);
m_BkDC = bkDC;
m_ImagePath = imagePath;
m_ImageCount = imageCount;
m_RenderMode = renderMode;
m_BkColor = bkColor;
m_BkColorSelected = bkColorSelected;
m_GlassColor = glassColor;
m_GlassAlpha = glassAlpha;
// BkBrush
m_BkBrush.DeleteObject();
if (bDarkMode)
{
m_BkBrush.CreateSolidBrush(RGB(32, 32, 32));
}
else
{
m_BkBrush.CreateSolidBrush(bkColor);
}
if (ES_LEFT <= textAlign && textAlign <= ES_RIGHT)
{
m_TextAlign = textAlign;
ModifyStyle(0, m_TextAlign);
}
if (m_ToolTip.m_hWnd != NULL)
{
if (m_ToolTip.GetToolCount() != 0)
{
m_ToolTip.DelTool(this, 1);
}
CRect rect;
GetClientRect(rect);
m_ToolTip.AddTool(this, m_ToolTipText, rect, 1);
}
m_bHighContrast = bHighContrast;
m_bDarkMode = bDarkMode;
if (renderMode & SystemDraw)
{
#if _MSC_VER <= 1310
if (IsNT3())
{
ModifyStyle(0, WS_BORDER, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
#endif
return TRUE;
}
else
{
m_ImageCount = 1;
m_CtrlImage.Destroy();
m_CtrlImage.Create(m_CtrlSize.cx, m_CtrlSize.cy * m_ImageCount, 32);
m_CtrlBitmap.Detach();
m_CtrlBitmap.Attach((HBITMAP)m_CtrlImage);
DWORD length = m_CtrlSize.cx * m_CtrlSize.cy * m_ImageCount * 4;
BYTE* bitmapBits = new BYTE[length];
m_CtrlBitmap.GetBitmapBits(length, bitmapBits);
BYTE r, g, b, a;
if (renderMode & OwnerDrawGlass)
{
r = (BYTE)GetRValue(m_GlassColor);
g = (BYTE)GetGValue(m_GlassColor);
b = (BYTE)GetBValue(m_GlassColor);
a = m_GlassAlpha;
}
else // OwnerDrawTransparent
{
r = 0;
g = 0;
b = 0;
a = 0;
}
for (int y = 0; y < (int)(m_CtrlSize.cy * m_ImageCount); y++)
{
for (int x = 0; x < m_CtrlSize.cx; x++)
{
DWORD p = (y * m_CtrlSize.cx + x) * 4;
#if _MSC_VER > 1310
#pragma warning( disable : 6386 )
#endif
bitmapBits[p + 0] = b;
bitmapBits[p + 1] = g;
bitmapBits[p + 2] = r;
bitmapBits[p + 3] = a;
#if _MSC_VER > 1310
#pragma warning( default : 6386 )
#endif
}
}
m_CtrlBitmap.SetBitmapBits(length, bitmapBits);
delete[] bitmapBits;
}
SetBkReload();
Invalidate();
return TRUE;
}
void CComboBoxFx::SetFontHeight(int height, double zoomRatio, double fontRatio)
{
m_FontHeight = (LONG)(-1 * height * zoomRatio * fontRatio);
}
void CComboBoxFx::SetItemHeightEx(int nIndex, int height, double zoomRatio, double fontRatio)
{
if (nIndex == -1)
{
CRect rc;
GetWindowRect(&rc);
CComboBox::SetItemHeight(-1, (UINT)(height * zoomRatio - rc.Height() + GetItemHeight(-1)));
}
else
{
CComboBox::SetItemHeight(nIndex, (UINT)(height * zoomRatio * fontRatio));
}
}
void CComboBoxFx::SetItemHeightAll(int height, double zoomRatio, double fontRatio)
{
m_FontHeight = (LONG)(-1 * height * zoomRatio * fontRatio);
CRect rc;
GetWindowRect(&rc);
CComboBox::SetItemHeight(-1, (UINT)(height * zoomRatio - rc.Height() + GetItemHeight(-1)));
for(int i = 0; i < this->GetCount(); i++)
{
CComboBox::SetItemHeight(i, (UINT)(height * zoomRatio * fontRatio));
}
}
void CComboBoxFx::SetMargin(int top, int left, int bottom, int right, double zoomRatio)
{
m_Margin.top = (int)(top * zoomRatio);
m_Margin.left = (int)(left * zoomRatio);
m_Margin.bottom = (int)(bottom * zoomRatio);
m_Margin.right = (int)(right * zoomRatio);
m_ZoomRatio = zoomRatio;
}
CSize CComboBoxFx::GetSize(void)
{
return m_CtrlSize;
}
void CComboBoxFx::SetGlassColor(COLORREF glassColor, BYTE glassAlpha)
{
m_GlassColor = glassColor;
m_GlassAlpha = glassAlpha;
}
void CComboBoxFx::SetAlpha(BYTE alpha)
{
m_Alpha = alpha;
}
HWND CComboBoxFx::GetListHwnd()
{
#if _MSC_VER > 1310
COMBOBOXINFO info = { 0 };
info.cbSize = sizeof(COMBOBOXINFO);
GetComboBoxInfo(&info);
return info.hwndList;
#else
return NULL;
#endif
}
HBRUSH CComboBoxFx::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor);
switch (nCtlColor) {
case CTLCOLOR_EDIT:
pDC->SetBkMode(TRANSPARENT);
return hbr;
case CTLCOLOR_LISTBOX:
pDC->SetBkMode(TRANSPARENT);
return m_BkBrush;
default:
return hbr;
}
}
//------------------------------------------------
// Draw Control
//------------------------------------------------
void CComboBoxFx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (lpDrawItemStruct->itemID == -1) { return; }
static COLORREF textColor;
static COLORREF textColorSelected;
static COLORREF bkColor;
static COLORREF bkColorSelected;
static int count = 0;
if (m_bHighContrast)
{
textColor = GetTextColor(lpDrawItemStruct->hDC);
textColorSelected = RGB(0, 0, 0);
bkColor = GetBkColor(lpDrawItemStruct->hDC);
bkColorSelected = RGB(0, 255, 255);
if (bkColor <= RGB(0x80, 0x80, 0x80)) { textColor = RGB(255, 255, 255); }
else { textColor = RGB(0, 0, 0); }
}
else if (m_bDarkMode)
{
textColor = RGB(255, 255, 255);
textColorSelected = RGB(255, 255, 255);
bkColor = RGB(32, 32, 32);
bkColorSelected = RGB(77, 77, 77);
}
else
{
textColor = m_TextColor;
textColorSelected = m_TextColorSelected;
bkColor = m_BkColor;
bkColorSelected = m_BkColorSelected;
}
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
LoadCtrlBk(pDC);
CString title;
GetLBText(lpDrawItemStruct->itemID, title);
CBrush Brush;
CBrush* pOldBrush;
if (lpDrawItemStruct->rcItem.left != 0 && !m_bHighContrast)
{
DrawControl(title, pDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageNormal);
Brush.CreateSolidBrush(bkColorSelected);
pOldBrush = pDC->SelectObject(&Brush);
if (lpDrawItemStruct->itemState & ODS_SELECTED)
{
RECT rc = lpDrawItemStruct->rcItem;
// rc.top = (LONG)(rc.bottom - 2 * m_ZoomRatio);
rc.right = (LONG)(rc.left + 3 * m_ZoomRatio);
FillRect(lpDrawItemStruct->hDC, &rc, (HBRUSH)Brush);
}
DrawString(title, pDC, lpDrawItemStruct, textColor);
#if _MSC_VER <= 1310
if (IsNT3() && IsWindowEnabled())
{
DWORD oldTextAlign = m_TextAlign;
m_TextAlign = ES_RIGHT;
DrawString(_T("v"), pDC, lpDrawItemStruct, textColor);
m_TextAlign = oldTextAlign;
}
#endif
}
else
{
if (lpDrawItemStruct->itemState & ODS_SELECTED)
{
Brush.CreateSolidBrush(bkColorSelected);
pOldBrush = pDC->SelectObject(&Brush);
FillRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, (HBRUSH)Brush);
DrawString(title, pDC, lpDrawItemStruct, textColorSelected);
}
else
{
Brush.CreateSolidBrush(bkColor);
pOldBrush = pDC->SelectObject(&Brush);
FillRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, (HBRUSH)Brush);
DrawString(title, pDC, lpDrawItemStruct, textColor);
}
}
pDC->SelectObject(pOldBrush);
Brush.DeleteObject();
}
void CComboBoxFx::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
lpMeasureItemStruct->itemHeight = abs(m_FontHeight);
}
void CComboBoxFx::DrawControl(CString title, CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, CBitmap& ctrlBitmap, CBitmap& bkBitmap, int no)
{
CDC* pMemDC = new CDC;
CBitmap* pOldMemBitmap;
pMemDC->CreateCompatibleDC(drawDC);
pOldMemBitmap = pMemDC->SelectObject(&ctrlBitmap);
CDC* pBkDC = new CDC;
CBitmap* pOldBkBitmap;
pBkDC->CreateCompatibleDC(drawDC);
pOldBkBitmap = pBkDC->SelectObject(&bkBitmap);
CBitmap DrawBmp;
DrawBmp.CreateCompatibleBitmap(drawDC, m_CtrlSize.cx, m_CtrlSize.cy);
CDC* pDrawBmpDC = new CDC;
CBitmap* pOldDrawBitmap;
pDrawBmpDC->CreateCompatibleDC(drawDC);
pOldDrawBitmap = pDrawBmpDC->SelectObject(&DrawBmp);
int color = drawDC->GetDeviceCaps(BITSPIXEL) * drawDC->GetDeviceCaps(PLANES);
if (!m_CtrlImage.IsNull())
{
if (m_CtrlImage.GetBPP() == 32)
{
CBitmap* bk32Bitmap;
CImage bk32Image;
if (color == 32)
{
bk32Bitmap = &bkBitmap;
}
else
{
bk32Image.Create(m_CtrlSize.cx, m_CtrlSize.cy, 32);
::BitBlt(bk32Image.GetDC(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, *pBkDC, 0, 0, SRCCOPY);
bk32Bitmap = CBitmap::FromHandle((HBITMAP)bk32Image);
}
BITMAP CtlBmpInfo, DstBmpInfo;
bk32Bitmap->GetBitmap(&DstBmpInfo);
DWORD DstLineBytes = DstBmpInfo.bmWidthBytes;
DWORD DstMemSize = DstLineBytes * DstBmpInfo.bmHeight;
ctrlBitmap.GetBitmap(&CtlBmpInfo);
DWORD CtlLineBytes = CtlBmpInfo.bmWidthBytes;
DWORD CtlMemSize = CtlLineBytes * CtlBmpInfo.bmHeight;
BYTE* DstBuffer = new BYTE[DstMemSize];
bk32Bitmap->GetBitmapBits(DstMemSize, DstBuffer);
BYTE* CtlBuffer = new BYTE[CtlMemSize];
ctrlBitmap.GetBitmapBits(CtlMemSize, CtlBuffer);
int baseY = m_CtrlSize.cy * no;
for (LONG py = 0; py < DstBmpInfo.bmHeight; py++)
{
int dn = py * DstLineBytes;
int cn = (baseY + py) * CtlLineBytes;
for (LONG px = 0; px < DstBmpInfo.bmWidth; px++)
{
#if _MSC_VER > 1310
#pragma warning( disable : 6385 )
#pragma warning( disable : 6386 )
#endif
BYTE a = CtlBuffer[cn + 3];
BYTE na = 255 - a;
DstBuffer[dn + 0] = (BYTE)((CtlBuffer[cn + 0] * a + DstBuffer[dn + 0] * na) / 255);
DstBuffer[dn + 1] = (BYTE)((CtlBuffer[cn + 1] * a + DstBuffer[dn + 1] * na) / 255);
DstBuffer[dn + 2] = (BYTE)((CtlBuffer[cn + 2] * a + DstBuffer[dn + 2] * na) / 255);
dn += (DstBmpInfo.bmBitsPixel / 8);
cn += (CtlBmpInfo.bmBitsPixel / 8);
#if _MSC_VER > 1310
#pragma warning( default : 6386 )
#pragma warning( default : 6385 )
#endif
}
}
if (color == 32)
{
DrawBmp.SetBitmapBits(DstMemSize, DstBuffer);
}
else
{
bk32Bitmap->SetBitmapBits(DstMemSize, DstBuffer);
::BitBlt(pDrawBmpDC->GetSafeHdc(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, bk32Image.GetDC(), 0, 0, SRCCOPY);
bk32Image.ReleaseDC();
}
drawDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, SRCCOPY);
delete[] DstBuffer;
delete[] CtlBuffer;
}
else
{
pDrawBmpDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pMemDC, 0, m_CtrlSize.cy * no, SRCCOPY);
drawDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, SRCCOPY);
}
}
else
{
pDrawBmpDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pBkDC, 0, m_CtrlSize.cy * no, SRCCOPY);
drawDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, SRCCOPY);
}
pDrawBmpDC->SelectObject(&pOldDrawBitmap);
pDrawBmpDC->DeleteDC();
delete pDrawBmpDC;
pMemDC->SelectObject(&pOldMemBitmap);
pMemDC->DeleteDC();
delete pMemDC;
pBkDC->SelectObject(&pOldBkBitmap);
pBkDC->DeleteDC();
delete pBkDC;
}
void CComboBoxFx::DrawString(CString title, CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, COLORREF textColor)
{
if (title.IsEmpty())
{
return;
}
drawDC->SetBkMode(TRANSPARENT);
CRect rect = (CRect)(lpDrawItemStruct->rcItem);
rect.top += m_Margin.top;
rect.left += m_Margin.left;
rect.bottom -= m_Margin.bottom;
rect.right -= m_Margin.right;
drawDC->SetTextColor(textColor);
if (m_TextAlign == ES_LEFT)
{
drawDC->DrawText(title, title.GetLength(), rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
else if (m_TextAlign == ES_RIGHT)
{
drawDC->DrawText(title, title.GetLength(), rect, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
}
else
{
drawDC->DrawText(title, title.GetLength(), rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
//------------------------------------------------
// Image
//------------------------------------------------
BOOL CComboBoxFx::LoadBitmap(LPCTSTR fileName)
{
if (m_bHighContrast) { return FALSE; }
if (fileName == NULL) { return FALSE; }
m_CtrlImage.Destroy();
m_CtrlImage.Load(fileName);
if (m_CtrlImage.IsNull()) { return FALSE; }
return LoadBitmap((HBITMAP)m_CtrlImage);
}
BOOL CComboBoxFx::LoadBitmap(HBITMAP hBitmap)
{
if (m_bHighContrast) { return FALSE; }
m_CtrlBitmap.Detach();
m_CtrlBitmap.Attach(hBitmap);
return SetBitmap(m_CtrlBitmap);
}
void CComboBoxFx::SetBkReload(void)
{
m_bBkBitmapInit = FALSE;
m_bBkLoad = FALSE;
}
BOOL CComboBoxFx::SetBitmap(CBitmap& bitmap)
{
if (m_bHighContrast) { return FALSE; }
BITMAP bitmapinfo;
bitmap.GetBitmap(&bitmapinfo);
if (m_CtrlSize.cx != bitmapinfo.bmWidth
|| m_CtrlSize.cy != bitmapinfo.bmHeight / m_ImageCount)
{
return FALSE;
}
else
{
return TRUE;
}
}
void CComboBoxFx::LoadCtrlBk(CDC* drawDC)
{
if (m_bHighContrast) { SetBkReload(); return; }
if (m_BkBitmap.m_hObject != NULL)
{
BITMAP bitmapInfo;
m_BkBitmap.GetBitmap(&bitmapInfo);
if (bitmapInfo.bmBitsPixel != drawDC->GetDeviceCaps(BITSPIXEL))
{
SetBkReload();
}
}
if (&m_CtrlBitmap != NULL)
{
if (!m_bBkBitmapInit)
{
m_BkBitmap.DeleteObject();
m_BkBitmap.CreateCompatibleBitmap(drawDC, m_CtrlSize.cx, m_CtrlSize.cy);
m_bBkBitmapInit = TRUE;
}
if (!m_bBkLoad)
{
CBitmap* pOldBitmap;
CDC* pMemDC = new CDC;
pMemDC->CreateCompatibleDC(drawDC);
pOldBitmap = pMemDC->SelectObject(&m_BkBitmap);
pMemDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, m_BkDC, m_X, m_Y, SRCCOPY);
pMemDC->SelectObject(pOldBitmap);
pMemDC->DeleteDC();
delete pMemDC;
m_bBkLoad = TRUE;
}
}
}
//------------------------------------------------
// Font
//------------------------------------------------
void CComboBoxFx::SetFontEx(CString face, int size, int sizeToolTip, double zoomRatio, double fontRatio,
COLORREF textColor, COLORREF textColorSelected, LONG fontWeight, BYTE fontRender)
{
LOGFONT logFont = { 0 };
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfHeight = (LONG)(-1 * size * zoomRatio * fontRatio);
logFont.lfQuality = fontRender;
logFont.lfWeight = fontWeight;
m_FontRender = fontRender;
if (face.GetLength() < 32)
{
wsprintf(logFont.lfFaceName, _T("%s"), (LPCTSTR)face);
}
else
{
wsprintf(logFont.lfFaceName, _T(""));
}
m_Font.DeleteObject();
m_Font.CreateFontIndirect(&logFont);
SetFont(&m_Font);
logFont.lfHeight = (LONG)(-1 * sizeToolTip * zoomRatio);
m_FontToolTip.DeleteObject();
m_FontToolTip.CreateFontIndirect(&logFont);
if (! m_bHighContrast)
{
m_TextColor = textColor;
m_TextColorSelected = textColorSelected;
}
if (m_ToolTip.m_hWnd != NULL)
{
m_ToolTip.SetFont(&m_FontToolTip);
}
}
//------------------------------------------------
// Mouse
//------------------------------------------------
void CComboBoxFx::SetHandCursor(BOOL bHandCuror)
{
m_bHandCursor = bHandCuror;
}
void CComboBoxFx::OnMouseMove(UINT nFlags, CPoint point)
{
#if _MSC_VER <= 1310
typedef BOOL(WINAPI* Func_TrackMouseEvent)(LPTRACKMOUSEEVENT);
static Func_TrackMouseEvent p_TrackMouseEvent = NULL;
static BOOL bInit_TrackMouseEvent = FALSE;
if (bInit_TrackMouseEvent && p_TrackMouseEvent == NULL)
{
return; // TrackMouseEvent is not available
}
else
{
HMODULE hModule = GetModuleHandle(_T("user32.dll"));
if (hModule)
{
p_TrackMouseEvent = (Func_TrackMouseEvent)GetProcAddress(hModule, "TrackMouseEvent");
}
}
if (p_TrackMouseEvent != NULL)
{
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bTrackingNow = p_TrackMouseEvent(&tme);
}
bInit_TrackMouseEvent = TRUE;
#else
if (!m_bTrackingNow)
{
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bTrackingNow = _TrackMouseEvent(&tme);
}
#endif
CComboBox::OnMouseMove(nFlags, point);
}
void CComboBoxFx::OnMouseHover(UINT nFlags, CPoint point)
{
#if _MSC_VER > 1310
CComboBox::OnMouseHover(nFlags, point);
#endif
m_bHover = TRUE;
Invalidate();
}
void CComboBoxFx::OnMouseLeave()
{
#if _MSC_VER > 1310
CComboBox::OnMouseLeave();
#endif
m_bTrackingNow = FALSE;
m_bHover = FALSE;
Invalidate();
}
void CComboBoxFx::OnSetfocus()
{
m_bFocas = TRUE;
Invalidate();
}
void CComboBoxFx::OnKillfocus()
{
m_bFocas = FALSE;
Invalidate();
}
BOOL CComboBoxFx::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
HCURSOR hCursor = NULL;
if (m_bHandCursor)
{
hCursor = AfxGetApp()->LoadStandardCursor(IDC_HAND);
if (hCursor)
{
::SetCursor(hCursor);
}
}
else
{
hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
if (hCursor)
{
::SetCursor(hCursor);
}
}
return TRUE;
}
//------------------------------------------------
// ToolTip
//------------------------------------------------
void CComboBoxFx::SetToolTipText(LPCTSTR text)
{
if (text == NULL) { return; }
InitToolTip();
m_ToolTipText = text;
if (m_ToolTip.GetToolCount() == 0)
{
CRect rect;
GetClientRect(rect);
m_ToolTip.AddTool(this, m_ToolTipText, rect, 1);
}
else
{
m_ToolTip.UpdateTipText(m_ToolTipText, this, 1);
}
SetToolTipActivate(TRUE);
}
void CComboBoxFx::SetToolTipActivate(BOOL bActivate)
{
if (m_ToolTip.GetToolCount() == 0) { return; }
m_ToolTip.Activate(bActivate);
}
void CComboBoxFx::SetToolTipWindowText(LPCTSTR pText)
{
SetToolTipText(pText);
SetWindowText(pText);
}
CString CComboBoxFx::GetToolTipText()
{
return m_ToolTipText;
}
void CComboBoxFx::InitToolTip()
{
if (m_ToolTip.m_hWnd == NULL)
{
m_ToolTip.Create(this, TTS_ALWAYSTIP | TTS_BALLOON | TTS_NOANIMATE | TTS_NOFADE);
m_ToolTip.Activate(FALSE);
m_ToolTip.SetFont(&m_FontToolTip);
m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, 1024);
m_ToolTip.SetDelayTime(TTDT_AUTOPOP, 8000);
m_ToolTip.SetDelayTime(TTDT_INITIAL, 500);
m_ToolTip.SetDelayTime(TTDT_RESHOW, 100);
}
}
BOOL CComboBoxFx::PreTranslateMessage(MSG* pMsg)
{
InitToolTip();
m_ToolTip.RelayEvent(pMsg);
return CComboBox::PreTranslateMessage(pMsg);
}
@@ -0,0 +1,130 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "ImageFx.h"
class CComboBoxFx : public CComboBox
{
DECLARE_DYNAMIC(CComboBoxFx);
// Constructors
public:
CComboBoxFx();
virtual ~CComboBoxFx();
// Control
public:
BOOL InitControl(int x, int y, int width, int height, double zoomRatio, CDC* bkDC,
LPCWSTR imagePath, int imageCount, DWORD textAlign, int renderMode, BOOL bHighContrast, BOOL m_bDarkMode,
COLORREF bkColor, COLORREF bkColorSelected, COLORREF glassColor, BYTE glassAlpha
);
void SetFontHeight(int height, double zoomRatio, double fontRatio = 1.0);
void SetItemHeightEx(int nIndex, int height, double zoomRatio, double fontRatio = 1.0);
void SetItemHeightAll(int height, double zoomRatio, double fontRatio = 1.0);
void SetMargin(int top, int left, int bottom, int right, double zoomRatio);
CSize GetSize(void);
void SetGlassColor(COLORREF glassColor, BYTE glassAlpha);
void SetAlpha(BYTE alpha);
HWND GetListHwnd();
// Font
void SetFontEx(CString face, int size, int sizeToolTip, double zoomRatio, double fontRatio = 1.0,
COLORREF textColor = RGB(0, 0, 0), COLORREF textColorSelected = RGB(0, 0, 0), LONG fontWeight = FW_NORMAL, BYTE fontRender = CLEARTYPE_NATURAL_QUALITY);
// ToolTip
void SetToolTipText(LPCTSTR pText);
void SetToolTipActivate(BOOL bActivate = TRUE);
void SetToolTipWindowText(LPCTSTR pText);
CString GetToolTipText();
// Mouse
void SetHandCursor(BOOL bHandCuror = TRUE);
protected:
// Draw Control
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
virtual void DrawControl(CString title, CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, CBitmap& ctrlBitmap, CBitmap& bkBitmap, int no);
virtual void DrawString(CString title, CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, COLORREF textColor);
// Image
BOOL LoadBitmap(LPCTSTR fileName);
BOOL LoadBitmap(HBITMAP hBitmap);
void SetBkReload(void);
BOOL SetBitmap(CBitmap& bitmap);
void LoadCtrlBk(CDC* drawDC);
// ToolTip
void InitToolTip();
virtual BOOL PreTranslateMessage(MSG* pMsg);
// Message Map
DECLARE_MESSAGE_MAP()
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnMouseHover(UINT nFlags, CPoint point);
afx_msg void OnMouseLeave();
afx_msg void OnKillfocus();
afx_msg void OnSetfocus();
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
protected:
// Control
int m_X;
int m_Y;
double m_ZoomRatio;
CSize m_CtrlSize;
CRect m_Margin;
int m_RenderMode;
BOOL m_bHighContrast;
BOOL m_bDarkMode;
BYTE m_FontRender; // For FontComboBoxFx
// Alpha/Glass
BYTE m_Alpha;
COLORREF m_GlassColor;
BYTE m_GlassAlpha;
// Image
CString m_ImagePath;
int m_ImageCount;
CDC* m_BkDC;
CBitmap m_BkBitmap;
BOOL m_bBkBitmapInit;
BOOL m_bBkLoad;
CBitmap m_CtrlBitmap;
CImage m_CtrlImage;
// Font
DWORD m_TextAlign;
CFont m_Font;
CFont m_FontToolTip;
COLORREF m_TextColor;
COLORREF m_TextColorSelected;
COLORREF m_BkColor;
COLORREF m_BkColorSelected;
COLORREF m_TextColorHc;
COLORREF m_TextColorSelectedHc;
COLORREF m_BkColorHc;
COLORREF m_BkColorSelectedHc;
LONG m_FontHeight;
// ToolTip
CToolTipCtrl m_ToolTip;
CString m_ToolTipText;
// Mouse
BOOL m_bHover;
BOOL m_bFocas;
BOOL m_bTrackingNow;
BOOL m_bHandCursor;
// Brush
CBrush m_BkBrush;
};
@@ -0,0 +1,89 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
//------------------------------------------------
// Naming Conventions
//------------------------------------------------
// BOOL bXxxxYyyy
// HANDLE hXxxxYyyy
// Pointer pXxxxYyyy
// Function SampleFunction
// Variable sampleVariable
// Const Value ConstVaiable
// Member Variable m_XxxxYyyy
//------------------------------------------------
// Order for C*****Fx Control
//------------------------------------------------
// Control > Draw Control > Image > Font > Mouse > ToolTip
//
//------------------------------------------------
// Utility Macros
//------------------------------------------------
#define SAFE_DELETE(p) {if(p){delete (p);(p)=NULL;}}
#if _MSC_VER > 1310
#define MENU_MODIFY_MENU menu->ModifyMenu
#define SUBMENU_MODIFY_MENU subMenu.ModifyMenu
#else
#define MENU_MODIFY_MENU if(!IsNT3())menu->ModifyMenu
#define SUBMENU_MODIFY_MENU if(!IsNT3())subMenu.ModifyMenu
#endif
//------------------------------------------------
// WM_APP
//------------------------------------------------
// WM_APP + 0x0000-0x0BFF: User Application
// WM_APP + 0x0C00-0x0FFF: Project Priscilla
// WM_APP + 0x0C00-0x0CFF: Theme
// WM_APP + 0x0D00-0x0DFF: Language
// WP_APP + 0x0E00-0x0FFF: Reserved
// WM_APP + 0x1000-0x3FFF: User Application
#define WM_THEME_ID (WM_APP + 0x0C00)
#define WM_LANGUAGE_ID (WM_APP + 0x0D00)
//------------------------------------------------
// TIMER ID
//------------------------------------------------
// 0x0000 - 0x0FFF: Project Priscilla
// 0x1000 - : User Application
static const int TimerUpdateDialogSizeDpiChanged = 0x0001;
static const int TimerUpdateDialogSizeDisplayChange = 0x0002;
static const int TimerUpdateDialogSizeSysColorChange = 0x0003;
static const int TimerUpdateDialogSizeSettingChange = 0x0004;
//------------------------------------------------
// Const Values
//------------------------------------------------
static const int ControlImageNormal = 0x0000;
static const int ControlImageHover = 0x0001;
static const int ControlImageFocus = 0x0002;
static const int ControlImageSelected = 0x0003;
static const int ControlImageDisabled = 0x0004;
static const int SystemDraw = 0x0001;
static const int OwnerDrawImage = 0x0002;
static const int OwnerDrawGlass = 0x0004;
static const int OwnerDrawTransparent = 0x0008;
static const int ZoomTypeAuto = 0;
static const int ZoomType050 = 50;
static const int ZoomType064 = 64;
static const int ZoomType075 = 75;
static const int ZoomType100 = 100;
static const int ZoomType125 = 125;
static const int ZoomType150 = 150;
static const int ZoomType200 = 200;
static const int ZoomType250 = 250;
static const int ZoomType300 = 300;
@@ -0,0 +1,261 @@
/*---------------------------------------------------------------------------*/
// Author : Richard Yu
// Web : https://github.com/ysc3839/win32-darkmode
// License : MIT License
// https://github.com/ysc3839/win32-darkmode/blob/master/LICENSE
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "OsInfoFx.h"
#include "IatHook.h"
enum IMMERSIVE_HC_CACHE_MODE
{
IHCM_USE_CACHED_VALUE,
IHCM_REFRESH
};
// 1903 18362
enum class PreferredAppMode
{
Default,
AllowDark,
ForceDark,
ForceLight,
Max
};
enum WINDOWCOMPOSITIONATTRIB
{
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
WCA_ALLOW_NCPAINT = 4,
WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
WCA_FORCE_ICONIC_REPRESENTATION = 7,
WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
WCA_THEME_ATTRIBUTES = 10,
WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
WCA_DISALLOW_PEEK = 16,
WCA_CLOAK = 17,
WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
WCA_FREEZE_REPRESENTATION = 20,
WCA_EVER_UNCLOAKED = 21,
WCA_VISUAL_OWNER = 22,
WCA_HOLOGRAPHIC = 23,
WCA_EXCLUDED_FROM_DDA = 24,
WCA_PASSIVEUPDATEMODE = 25,
WCA_USEDARKMODECOLORS = 26,
WCA_LAST = 27
};
struct WINDOWCOMPOSITIONATTRIBDATA
{
WINDOWCOMPOSITIONATTRIB Attrib;
PVOID pvData;
SIZE_T cbData;
};
using fnRtlGetNtVersionNumbers = void (WINAPI*)(LPDWORD major, LPDWORD minor, LPDWORD build);
using fnSetWindowCompositionAttribute = BOOL(WINAPI*)(HWND hWnd, WINDOWCOMPOSITIONATTRIBDATA*);
// 1809 17763
using fnShouldAppsUseDarkMode = bool (WINAPI*)(); // ordinal 132
using fnAllowDarkModeForWindow = bool (WINAPI*)(HWND hWnd, bool allow); // ordinal 133
using fnAllowDarkModeForApp = bool (WINAPI*)(bool allow); // ordinal 135, in 1809
using fnFlushMenuThemes = void (WINAPI*)(); // ordinal 136
using fnRefreshImmersiveColorPolicyState = void (WINAPI*)(); // ordinal 104
using fnIsDarkModeAllowedForWindow = bool (WINAPI*)(HWND hWnd); // ordinal 137
using fnGetIsImmersiveColorUsingHighContrast = bool (WINAPI*)(IMMERSIVE_HC_CACHE_MODE mode); // ordinal 106
using fnOpenNcThemeData = HTHEME(WINAPI*)(HWND hWnd, LPCWSTR pszClassList); // ordinal 49
// 1903 18362
using fnShouldSystemUseDarkMode = bool (WINAPI*)(); // ordinal 138
using fnSetPreferredAppMode = PreferredAppMode(WINAPI*)(PreferredAppMode appMode); // ordinal 135, in 1903
using fnIsDarkModeAllowedForApp = bool (WINAPI*)(); // ordinal 139
fnSetWindowCompositionAttribute _SetWindowCompositionAttribute = nullptr;
fnShouldAppsUseDarkMode _ShouldAppsUseDarkMode = nullptr;
fnAllowDarkModeForWindow _AllowDarkModeForWindow = nullptr;
fnAllowDarkModeForApp _AllowDarkModeForApp = nullptr;
fnFlushMenuThemes _FlushMenuThemes = nullptr;
fnRefreshImmersiveColorPolicyState _RefreshImmersiveColorPolicyState = nullptr;
fnIsDarkModeAllowedForWindow _IsDarkModeAllowedForWindow = nullptr;
fnGetIsImmersiveColorUsingHighContrast _GetIsImmersiveColorUsingHighContrast = nullptr;
fnOpenNcThemeData _OpenNcThemeData = nullptr;
// 1903 18362
fnShouldSystemUseDarkMode _ShouldSystemUseDarkMode = nullptr;
fnSetPreferredAppMode _SetPreferredAppMode = nullptr;
bool g_darkModeSupported = false;
bool g_darkModeEnabled = false;
DWORD g_buildNumber = 0;
bool AllowDarkModeForWindow(HWND hWnd, bool allow)
{
if (g_darkModeSupported)
return _AllowDarkModeForWindow(hWnd, allow);
return false;
}
bool IsHighContrast()
{
HIGHCONTRASTW highContrast = { sizeof(highContrast) };
if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(highContrast), &highContrast, FALSE))
return highContrast.dwFlags & HCF_HIGHCONTRASTON;
return false;
}
void AllowDarkModeForApp(bool allow)
{
if (_AllowDarkModeForApp)
_AllowDarkModeForApp(allow);
else if (_SetPreferredAppMode)
_SetPreferredAppMode(allow ? PreferredAppMode::AllowDark : PreferredAppMode::Default);
}
void RefreshTitleBarThemeColor(HWND hWnd)
{
BOOL dark = FALSE;
if (_IsDarkModeAllowedForWindow(hWnd) &&
_ShouldAppsUseDarkMode() &&
!IsHighContrast())
{
dark = TRUE;
}
if (g_buildNumber < 18362)
SetPropW(hWnd, L"UseImmersiveDarkModeColors", reinterpret_cast<HANDLE>(static_cast<INT_PTR>(dark)));
else if (_SetWindowCompositionAttribute)
{
WINDOWCOMPOSITIONATTRIBDATA data = { WCA_USEDARKMODECOLORS, &dark, sizeof(dark) };
_SetWindowCompositionAttribute(hWnd, &data);
}
}
constexpr bool CheckBuildNumber(DWORD buildNumber)
{
return (buildNumber >= 17763);
}
void FixDarkScrollBar()
{
HMODULE hComctl = LoadLibraryExW(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (hComctl)
{
auto addr = FindDelayLoadThunkInModule(hComctl, "uxtheme.dll", 49); // OpenNcThemeData
if (addr)
{
DWORD oldProtect;
if (VirtualProtect(addr, sizeof(IMAGE_THUNK_DATA), PAGE_READWRITE, &oldProtect))
{
auto MyOpenThemeData = [](HWND hWnd, LPCWSTR classList) -> HTHEME {
if (wcscmp(classList, L"ScrollBar") == 0)
{
hWnd = nullptr;
classList = L"Explorer::ScrollBar";
}
return _OpenNcThemeData(hWnd, classList);
};
addr->u1.Function = reinterpret_cast<ULONG_PTR>(static_cast<fnOpenNcThemeData>(MyOpenThemeData));
VirtualProtect(addr, sizeof(IMAGE_THUNK_DATA), oldProtect, &oldProtect);
}
}
}
}
BOOL InitDarkMode()
{
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
HMODULE user32 = GetModuleHandleW(L"user32.dll");
if (!ntdll || !user32) return FALSE;
auto RtlGetNtVersionNumbers = reinterpret_cast<fnRtlGetNtVersionNumbers>(GetProcAddress(ntdll, "RtlGetNtVersionNumbers"));
if (RtlGetNtVersionNumbers)
{
DWORD major, minor;
RtlGetNtVersionNumbers(&major, &minor, &g_buildNumber);
g_buildNumber &= ~0xF0000000;
if (major == 10 && minor == 0 && CheckBuildNumber(g_buildNumber))
{
HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (hUxtheme)
{
_OpenNcThemeData = reinterpret_cast<fnOpenNcThemeData>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(49)));
_RefreshImmersiveColorPolicyState = reinterpret_cast<fnRefreshImmersiveColorPolicyState>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(104)));
_GetIsImmersiveColorUsingHighContrast = reinterpret_cast<fnGetIsImmersiveColorUsingHighContrast>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(106)));
_ShouldAppsUseDarkMode = reinterpret_cast<fnShouldAppsUseDarkMode>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(132)));
_AllowDarkModeForWindow = reinterpret_cast<fnAllowDarkModeForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133)));
auto ord135 = GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));
if (g_buildNumber < 18362)
_AllowDarkModeForApp = reinterpret_cast<fnAllowDarkModeForApp>(ord135);
else
_SetPreferredAppMode = reinterpret_cast<fnSetPreferredAppMode>(ord135);
//_FlushMenuThemes = reinterpret_cast<fnFlushMenuThemes>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(136)));
_IsDarkModeAllowedForWindow = reinterpret_cast<fnIsDarkModeAllowedForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(137)));
_SetWindowCompositionAttribute = reinterpret_cast<fnSetWindowCompositionAttribute>(GetProcAddress(user32, "SetWindowCompositionAttribute"));
if (_OpenNcThemeData &&
_RefreshImmersiveColorPolicyState &&
_ShouldAppsUseDarkMode &&
_AllowDarkModeForWindow &&
(_AllowDarkModeForApp || _SetPreferredAppMode) &&
//_FlushMenuThemes &&
_IsDarkModeAllowedForWindow)
{
g_darkModeSupported = true;
AllowDarkModeForApp(true);
_RefreshImmersiveColorPolicyState();
g_darkModeEnabled = _ShouldAppsUseDarkMode() && !IsHighContrast();
// FixDarkScrollBar();
}
}
}
}
return (BOOL)g_darkModeEnabled;
}
BOOL SetDarkMode(HWND hWnd)
{
BOOL bDarkMode = FALSE;
if (IsDarkModeSupport())
{
bDarkMode = InitDarkMode();
AllowDarkModeForWindow(hWnd, bDarkMode);
RefreshTitleBarThemeColor(hWnd);
}
return bDarkMode;
}
void UnsetDarkMode(HWND hWnd)
{
if (IsDarkModeSupport())
{
InitDarkMode();
AllowDarkModeForWindow(hWnd, FALSE);
RefreshTitleBarThemeColor(hWnd);
}
}
void SetDarkModeControl(HWND hWnd, BOOL bDarkMode)
{
if (IsDarkModeSupport())
{
SetWindowTheme(hWnd, L"Explorer", nullptr);
AllowDarkModeForWindow(hWnd, bDarkMode);
SendMessageW(hWnd, WM_THEMECHANGED, 0, 0);
}
}
@@ -0,0 +1,18 @@
/*---------------------------------------------------------------------------*/
// Author : Richard Yu
// Web : https://github.com/ysc3839/win32-darkmode
// License : MIT License
// https://github.com/ysc3839/win32-darkmode/blob/master/LICENSE
/*---------------------------------------------------------------------------*/
#pragma once
BOOL SetDarkMode(HWND hWnd);
void UnsetDarkMode(HWND hWnd);
void SetDarkModeControl(HWND hWnd, BOOL bDarkMode);
void FixDarkScrollBar();
bool AllowDarkModeForWindow(HWND hWnd, bool allow);
// BOOL InitDarkMode();
// void RefreshTitleBarThemeColor(HWND hWnd);
@@ -0,0 +1,738 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "Resource.h"
#include "DialogFx.h"
#include "UtilityFx.h"
#include "OsInfoFx.h"
#include <cmath>
#include "DarkMode.h"
// defined by Windows 8.1/Windows 2012 R2
#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02E0
#endif
////------------------------------------------------
// CDialogFx
////------------------------------------------------
CDialogFx::CDialogFx(UINT dlgResouce, CWnd* pParent)
:CDialog(dlgResouce, pParent)
{
// Dialog
m_bInitializing = TRUE;
m_bDpiChanging = FALSE;
m_bShowWindow = FALSE;
m_bModelessDlg = FALSE;
m_bHighContrast = FALSE;
m_bDarkMode = FALSE;
m_bDisableDarkMode = FALSE;
m_bBkImage = FALSE;
m_MenuId = 0;
m_ParentWnd = NULL;
m_DlgWnd = NULL;
m_hAccelerator = NULL;
m_bDrag = FALSE;
m_FontScale = 100;
m_FontRatio = 1.0;
m_FontRender = CLEARTYPE_NATURAL_QUALITY;
m_hPal = NULL;
m_SizeX = 0;
m_MaxSizeX = 65535;
m_MinSizeX = 0;
m_SizeY = 0;
m_MaxSizeY = 65535;
m_MinSizeY = 0;
// Zoom
m_Dpi = 96;
m_ZoomRatio = 1.0;
m_ZoomType = ZoomTypeAuto;
// Color for SubClass
m_LabelText = 0x00000000;
m_MeterText = 0x00000000;
m_ComboText = 0x00000000;
m_ComboTextSelected = 0x00808080;
m_ComboBk = 0x00FFFFFF;
m_ComboBkSelected = 0x00808080;
m_ButtonText = 0x00000000;
m_EditText = 0x00000000;
m_EditBk = 0x00FFFFFF;
m_ListText1 = 0x00000000;
m_ListText2 = 0x00000000;
m_ListTextSelected = 0x00000000;
m_ListBk1 = 0x00FFFFFF;
m_ListBk2 = 0x00FFFFFF;
m_ListBkSelected = 0x00808080;
m_ListLine1 = 0x00000000;
m_ListLine2 = 0x00000000;
m_Glass = 0x00808080;
m_Frame = 0x00808080;
m_Background = 0xFFFFFFFF; // Disabled
m_ComboAlpha = 0;
m_EditAlpha = 0;
m_GlassAlpha = 0;
m_CharacterPosition = 0;
// Theme for SubClass
m_OffsetX = 0;
// Voice for SubClass
m_VoiceVolume = 0;
}
CDialogFx::~CDialogFx()
{
if(m_hPal) DeleteObject(m_hPal);
}
BEGIN_MESSAGE_MAP(CDialogFx, CDialog)
ON_WM_SIZE()
ON_WM_TIMER()
ON_WM_ERASEBKGND()
ON_MESSAGE(WM_DPICHANGED, &CDialogFx::OnDpiChanged)
ON_MESSAGE(WM_DISPLAYCHANGE, &CDialogFx::OnDisplayChange)
ON_MESSAGE(WM_SYSCOLORCHANGE, &CDialogFx::OnSysColorChange)
ON_MESSAGE(WM_SETTINGCHANGE, &CDialogFx::OnSettingChange)
ON_MESSAGE(WM_ENTERSIZEMOVE, &CDialogFx::OnEnterSizeMove)
ON_MESSAGE(WM_EXITSIZEMOVE, &CDialogFx::OnExitSizeMove)
END_MESSAGE_MAP()
//------------------------------------------------
// Dialog
//------------------------------------------------
BOOL CDialogFx::Create(UINT nIDTemplate, CWnd* pDlgWnd, UINT menuId, CWnd* pParentWnd)
{
m_bModelessDlg = TRUE;
m_ParentWnd = pParentWnd;
m_DlgWnd = pDlgWnd;
m_MenuId = menuId;
if (m_MenuId != 0 && m_ParentWnd != NULL)
{
CMenu* menu = m_ParentWnd->GetMenu();
menu->EnableMenuItem(m_MenuId, MF_GRAYED);
m_ParentWnd->SetMenu(menu);
m_ParentWnd->DrawMenuBar();
}
return CDialog::Create(nIDTemplate, pParentWnd);
}
int CDialogFx::GetDpi()
{
INT dpi = 96;
CDC* pDC = GetDC();
dpi = GetDeviceCaps(pDC->m_hDC, LOGPIXELSY);
ReleaseDC(pDC);
HMODULE hModule = GetModuleHandle(_T("Shcore.dll"));
if (hModule)
{
typedef HRESULT(WINAPI* FuncGetDpiForMonitor) (HMONITOR hmonitor, UINT dpiType, UINT* dpiX, UINT* dpiY);
typedef HMONITOR(WINAPI* FuncMonitorFromWindow) (HWND hwnd, DWORD dwFlags);
FuncGetDpiForMonitor pGetDpiForMonitor = (FuncGetDpiForMonitor)GetProcAddress(hModule, "GetDpiForMonitor");
FuncMonitorFromWindow pMonitorFromWindow = (FuncMonitorFromWindow)GetProcAddress(hModule, "MonitorFromWindow");
if (pGetDpiForMonitor && pMonitorFromWindow)
{
UINT dpiX, dpiY;
pGetDpiForMonitor(pMonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST), 0, &dpiX, &dpiY);
dpi = dpiY;
}
}
return dpi;
}
BOOL CDialogFx::OnInitDialog()
{
CDialog::OnInitDialog();
m_bHighContrast = IsHighContrast();
m_Dpi = GetDpi();
m_hAccelerator = ::LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ACCELERATOR));
// m_bInitializing = FALSE;
return TRUE;
}
void CDialogFx::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
if (nType == SIZE_RESTORED)
{
UpdateBackground(TRUE, FALSE);
Invalidate();
}
}
BOOL CDialogFx::PreTranslateMessage(MSG* pMsg)
{
if(m_hAccelerator != NULL)
{
if(::TranslateAccelerator(m_hWnd, m_hAccelerator, pMsg) != 0)
{
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
void CDialogFx::PostNcDestroy()
{
if (m_bModelessDlg)
{
m_DlgWnd = NULL;
delete this;
}
else
{
CDialog::PostNcDestroy();
}
}
void CDialogFx::UpdateDialogSize()
{
#if _MSC_VER > 1310
if (! m_bDisableDarkMode)
{
m_bDarkMode = SetDarkMode(m_hWnd);
}
else
{
UnsetDarkMode(m_hWnd);
m_bDarkMode = FALSE;
}
#endif
}
void CDialogFx::SetClientSize(int sizeX, int sizeY, double zoomRatio)
{
RECT rw, rc;
GetWindowRect(&rw);
GetClientRect(&rc);
if (rc.right != 0)
{
int ncaWidth = (rw.right - rw.left) - (rc.right - rc.left);
int ncaHeight = (rw.bottom - rw.top) - (rc.bottom - rc.top);
SetWindowPos(NULL, 0, 0, (int)(sizeX * zoomRatio) + ncaWidth, (int)(sizeY * zoomRatio) + ncaHeight, SWP_NOMOVE | SWP_NOZORDER);
GetWindowRect(&rw);
GetClientRect(&rc);
int ncaHeightMenu = (rw.bottom - rw.top) - (rc.bottom - rc.top);
if (ncaHeight != ncaHeightMenu)
{
SetWindowPos(NULL, 0, 0, (int)(sizeX * zoomRatio) + ncaWidth, (int)(sizeY * zoomRatio) + ncaHeightMenu, SWP_NOMOVE | SWP_NOZORDER);
}
}
}
void CDialogFx::UpdateBackground(BOOL resize, BOOL bDarkMode)
{
BOOL result = FALSE;
CImage srcBitmap;
double ratio = m_ZoomRatio;
m_bBkImage = FALSE;
#if _MSC_VER > 1310
if (resize) { m_ZoomRatio = 3.0; }
result = srcBitmap.Load(IP(m_BackgroundName));
if (resize) { m_ZoomRatio = ratio; }
#else
if (resize) { m_ZoomRatio = 1.0; }
result = srcBitmap.Load(IP(m_BackgroundName));
if (resize) { m_ZoomRatio = ratio; }
#endif
HDC hScreenDC = ::GetDC(NULL); // get desktop DC
if(!m_hPal && GetDeviceCaps(hScreenDC, RASTERCAPS) & RC_PALETTE)
{
m_hPal = CreateHalftonePalette(hScreenDC);
}
DeleteDC(hScreenDC); // delete it after use
if (result)
{
m_bBkImage = TRUE;
CBitmap baseBitmap;
CDC baseDC;
CDC* pWndDC = GetDC();
#if _MSC_VER > 1310
int w = (int)(m_ZoomRatio / 3.0 * srcBitmap.GetWidth());
int h = (int)(m_ZoomRatio / 3.0 * srcBitmap.GetHeight());
#else
int w = (int)(m_ZoomRatio * srcBitmap.GetWidth());
int h = (int)(m_ZoomRatio * srcBitmap.GetHeight());
#endif
int orgw = srcBitmap.GetWidth();
int orgh = srcBitmap.GetHeight();
if(m_hPal && pWndDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( pWndDC->GetSafeHdc(), m_hPal, TRUE );
pWndDC->RealizePalette();
pWndDC->SetStretchBltMode(HALFTONE);
}
baseBitmap.CreateCompatibleBitmap(pWndDC, orgw, orgh);
baseDC.CreateCompatibleDC(pWndDC);
if(m_hPal && baseDC.GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( baseDC.GetSafeHdc(), m_hPal, FALSE );
baseDC.RealizePalette();
baseDC.SetStretchBltMode(HALFTONE);
}
m_BkBitmap.DeleteObject();
m_BkDC.DeleteDC();
m_BkBitmap.CreateCompatibleBitmap(pWndDC, w, h);
m_BkDC.CreateCompatibleDC(pWndDC);
if(m_hPal && baseDC.GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( m_BkDC.GetSafeHdc(), m_hPal, FALSE );
m_BkDC.RealizePalette();
m_BkDC.SetStretchBltMode(HALFTONE);
}
ReleaseDC(pWndDC);
baseDC.SelectObject(&baseBitmap);
m_BkDC.SelectObject(&m_BkBitmap);
srcBitmap.BitBlt(baseDC.GetSafeHdc(), 0, 0, SRCCOPY);
srcBitmap.Destroy();
m_BkDC.SetStretchBltMode(HALFTONE);
SetBrushOrgEx(m_BkDC, 0, 0, NULL);
m_BkDC.StretchBlt(0, 0, w, h, &baseDC, 0, 0, orgw, orgh, SRCCOPY);
baseBitmap.DeleteObject();
baseDC.DeleteDC();
m_BrushDlg.DeleteObject();
m_BrushDlg.CreatePatternBrush(&m_BkBitmap);
return;
}
else if (m_bHighContrast)
{
m_BrushDlg.DeleteObject();
m_BrushDlg.CreateSolidBrush(RGB(0, 0, 0));
}
else
{
CBitmap baseBitmap;
CDC baseDC;
CDC* pWndDC = GetDC();
CRect rect;
GetClientRect(&rect);
int w = rect.Width();
int h = rect.Height();
m_BkBitmap.DeleteObject();
m_BkBitmap.CreateCompatibleBitmap(pWndDC, w, h);
m_BkDC.DeleteDC();
m_BkDC.CreateCompatibleDC(pWndDC);
m_BkDC.SelectObject(&m_BkBitmap);
m_BrushDlg.DeleteObject();
COLORREF bkColor;
if (m_Background != 0xFFFFFFFF)
{
bkColor = m_Background;
}
else if (bDarkMode)
{
bkColor = RGB(32, 32, 32);
}
else
{
bkColor = RGB(255, 255, 255);
}
m_BrushDlg.CreateSolidBrush(bkColor);
m_BkDC.FillRect(&rect, &m_BrushDlg);
ReleaseDC(pWndDC);
}
}
void CDialogFx::SetWindowTitle(CString title)
{
SetWindowText(_T(" ") + title + _T(" "));
}
void CDialogFx::OnOK()
{
}
void CDialogFx::OnCancel()
{
if (m_bModelessDlg)
{
if (m_MenuId != 0 && m_ParentWnd != NULL)
{
CMenu* menu = m_ParentWnd->GetMenu();
menu->EnableMenuItem(m_MenuId, MF_ENABLED);
m_ParentWnd->SetMenu(menu);
m_ParentWnd->DrawMenuBar();
}
CDialog::DestroyWindow();
}
else
{
CDialog::OnCancel();
}
}
//------------------------------------------------
// Font
//------------------------------------------------
int CDialogFx::GetFontScale()
{
return m_FontScale;
}
BYTE CDialogFx::GetFontRender()
{
return m_FontRender;
}
double CDialogFx::GetFontRatio()
{
return m_FontRatio;
}
CString CDialogFx::GetFontFace()
{
return m_FontFace;
}
//------------------------------------------------
// Zoom
//------------------------------------------------
DWORD CDialogFx::ChangeZoomType(DWORD zoomType)
{
DWORD current = (DWORD)ceil(m_Dpi / 96.0 * 100);
int width = GetSystemMetrics(SM_CXSCREEN);
if(zoomType == ZoomTypeAuto)
{
#if _MSC_VER > 1310
if (current >= 300)
{
zoomType = ZoomType300;
}
else if (current >= 250)
{
zoomType = ZoomType250;
}
else
#endif
if(current >= 200)
{
zoomType = ZoomType200;
}
else if(current >= 150)
{
zoomType = ZoomType150;
}
else if(current >= 125)
{
zoomType = ZoomType125;
}
#ifdef CRYSTALMARK_RETRO
#ifdef SUISHO_SHIZUKU_SUPPORT
else if (width < 900) { zoomType = ZoomType050; }
else if (width < 1200){ zoomType = ZoomType075; }
#else
// else if (width < 732) { zoomType = ZoomType050; }
else if (width < 732) { zoomType = ZoomType064; }
else if (width < 976) { zoomType = ZoomType075; }
#endif
#endif
else
{
zoomType = ZoomType100;
}
}
m_ZoomRatio = zoomType / 100.0;
return zoomType;
}
//------------------------------------------------
// Theme
//------------------------------------------------
BOOL CDialogFx::IsHighContrast()
{
HIGHCONTRAST hc = { sizeof(HIGHCONTRAST) };
SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(HIGHCONTRAST), &hc, 0);
return hc.dwFlags & HCF_HIGHCONTRASTON;
}
BOOL CDialogFx::IsDisableDarkMode()
{
return m_bDisableDarkMode;
}
//------------------------------------------------
// Utility
//------------------------------------------------
CString CDialogFx::IP(CString imageName) /// ImagePath
{
CString imagePath;
imagePath.Format(_T("%s%s\\%s-%03d.png"), (LPCTSTR)m_ThemeDir, (LPCTSTR)m_CurrentTheme, (LPCTSTR)imageName, (DWORD)(m_ZoomRatio * 100));
if (IsFileExist(imagePath))
{
return imagePath;
}
imagePath.Format(_T("%s%s\\%s-%03d.png"), (LPCTSTR)m_ThemeDir, (LPCTSTR)m_ParentTheme1, (LPCTSTR)imageName, (DWORD)(m_ZoomRatio * 100));
if (IsFileExist(imagePath))
{
return imagePath;
}
imagePath.Format(_T("%s%s\\%s-%03d.png"), (LPCTSTR)m_ThemeDir, (LPCTSTR)m_ParentTheme2, (LPCTSTR)imageName, (DWORD)(m_ZoomRatio * 100));
if (IsFileExist(imagePath))
{
return imagePath;
}
imagePath.Format(_T("%s%s\\%s-%03d.png"), (LPCTSTR)m_ThemeDir, (LPCTSTR)m_DefaultTheme, (LPCTSTR)imageName, (DWORD)(m_ZoomRatio * 100));
if (IsFileExist(imagePath))
{
return imagePath;
}
return _T("");
}
CString CDialogFx::i18n(CString section, CString key, BOOL inEnglish)
{
TCHAR str[256];
CString cstr;
if(inEnglish)
{
GetPrivateProfileStringFx(section, key, _T(""), str, 256, m_DefaultLangPath);
cstr = str;
}
else
{
GetPrivateProfileStringFx(section, key, _T(""), str, 256, m_CurrentLangPath);
cstr = str;
if(cstr.IsEmpty())
{
GetPrivateProfileStringFx(section, key, _T(""), str, 256, m_DefaultLangPath);
cstr = str;
}
}
return cstr;
}
void CDialogFx::OpenUrl(CString url)
{
INT_PTR result = 0;
result = (INT_PTR)(ShellExecute(NULL, _T("open"), (LPCTSTR)url, NULL, NULL, SW_SHOWNORMAL));
if(result <= 32)
{
CString args;
args.Format(_T("url.dll,FileProtocolHandler %s"), (LPCTSTR)url);
ShellExecute(NULL, _T("open"), _T("rundll32.exe"), args, NULL, SW_SHOWNORMAL);
}
}
void CDialogFx::SetLayeredWindow(HWND hWnd, BYTE alpha)
{
#if _MSC_VER > 1310
if (IsWin2k()) { return; }
::SetWindowLong(hWnd, GWL_EXSTYLE, ::GetWindowLong(hWnd, GWL_EXSTYLE) ^ WS_EX_LAYERED);
::SetWindowLong(hWnd, GWL_EXSTYLE, ::GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
if (m_bHighContrast)
{
::SetLayeredWindowAttributes(hWnd, 0, 255, LWA_ALPHA);
}
else
{
::SetLayeredWindowAttributes(hWnd, 0, alpha, LWA_ALPHA);
}
#endif
}
//------------------------------------------------
// MessageMap
//------------------------------------------------
void CDialogFx::OnTimer(UINT_PTR nIDEvent)
{
switch (nIDEvent)
{
case TimerUpdateDialogSizeDpiChanged:
if (m_bDrag)
{
KillTimer(TimerUpdateDialogSizeDpiChanged);
SetTimer(TimerUpdateDialogSizeDpiChanged, TIMER_UPDATE_DIALOG, NULL);
}
else
{
m_bDpiChanging = FALSE;
KillTimer(TimerUpdateDialogSizeDpiChanged);
UpdateDialogSize();
}
break;
case TimerUpdateDialogSizeDisplayChange:
KillTimer(TimerUpdateDialogSizeDisplayChange);
UpdateDialogSize();
break;
case TimerUpdateDialogSizeSysColorChange:
KillTimer(TimerUpdateDialogSizeSysColorChange);
UpdateDialogSize();
break;
case TimerUpdateDialogSizeSettingChange:
KillTimer(TimerUpdateDialogSizeSettingChange);
UpdateDialogSize();
break;
}
}
BOOL CDialogFx::OnEraseBkgnd(CDC* pDC)
{
if (m_bHighContrast)
{
return CDialog::OnEraseBkgnd(pDC);
}
if(m_hPal && pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( pDC->GetSafeHdc(), m_hPal, TRUE );
pDC->RealizePalette();
pDC->SetStretchBltMode(HALFTONE);
}
CRect rect;
GetClientRect(&rect);
return pDC->StretchBlt(0, 0, rect.Width(), rect.Height(), &m_BkDC, 0, 0, rect.Width(), rect.Height(), SRCCOPY);
}
afx_msg LRESULT CDialogFx::OnDpiChanged(WPARAM wParam, LPARAM lParam)
{
if (m_bInitializing) { return 0; }
static ULONGLONG preTime = 0;
ULONGLONG currentTime = GetTickCountFx();
if (currentTime - preTime < 1000)
{
return 0;
}
else
{
preTime = currentTime;
}
m_Dpi = (INT)HIWORD(wParam);
#if _MSC_VER > 1310
if (IsWindowsBuildOrGreater(16299)) // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
{
ChangeZoomType(m_ZoomType);
m_bDpiChanging = TRUE;
SetTimer(TimerUpdateDialogSizeDpiChanged, TIMER_UPDATE_DIALOG, NULL);
}
else
#endif
if(m_ZoomType == ZoomTypeAuto)
{
DWORD oldZoomRatio = (DWORD)(m_ZoomRatio * 100);
if (ChangeZoomType(m_ZoomType) != oldZoomRatio)
{
m_bDpiChanging = TRUE;
SetTimer(TimerUpdateDialogSizeDpiChanged, TIMER_UPDATE_DIALOG, NULL);
}
}
return 0;
}
afx_msg LRESULT CDialogFx::OnDisplayChange(WPARAM wParam, LPARAM lParam)
{
if (m_bInitializing) { return 0; }
CDC* cdc = GetDC();
if (cdc)
{
int color = cdc->GetDeviceCaps(BITSPIXEL) * cdc->GetDeviceCaps(PLANES);
if (color != wParam)
{
SetTimer(TimerUpdateDialogSizeDisplayChange, TIMER_UPDATE_DIALOG, NULL);
}
ReleaseDC(cdc);
}
return 0;
}
afx_msg LRESULT CDialogFx::OnSysColorChange(WPARAM wParam, LPARAM lParam)
{
if (m_bInitializing) { return 0; }
m_bHighContrast = IsHighContrast();
SetTimer(TimerUpdateDialogSizeSysColorChange, TIMER_UPDATE_DIALOG, NULL);
return 0;
}
afx_msg LRESULT CDialogFx::OnSettingChange(WPARAM wParam, LPARAM lParam)
{
if (m_bInitializing) { return 0; }
if (!lstrcmp(LPCTSTR(lParam), _T("ImmersiveColorSet")))
{
SetTimer(TimerUpdateDialogSizeSettingChange, TIMER_UPDATE_DIALOG, NULL);
}
return 0;
}
afx_msg LRESULT CDialogFx::OnEnterSizeMove(WPARAM wParam, LPARAM lParam)
{
m_bDrag = TRUE;
return TRUE;
}
afx_msg LRESULT CDialogFx::OnExitSizeMove(WPARAM wParam, LPARAM lParam)
{
m_bDrag = FALSE;
return TRUE;
}
@@ -0,0 +1,156 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "ImageFx.h"
class CDialogFx : public CDialog
{
public:
CDialogFx(UINT dlgResouce, CWnd* pParent = NULL);
virtual ~CDialogFx();
// Dialog
virtual BOOL Create(UINT nIDTemplate, CWnd* dlgWnd, UINT menuId, CWnd* pParentWnd = NULL);
// Font
int GetFontScale();
BYTE GetFontRender();
double GetFontRatio();
CString GetFontFace();
// Theme
BOOL IsDisableDarkMode();
protected:
// Dialog
virtual BOOL OnInitDialog();
virtual BOOL PreTranslateMessage(MSG* pMsg);
virtual void PostNcDestroy();
virtual void UpdateDialogSize();
virtual void SetClientSize(int sizeX, int sizeY, double zoomRatio);
virtual void UpdateBackground(BOOL resize, BOOL darkMode);
virtual void SetWindowTitle(CString title);
virtual void OnOK();
virtual void OnCancel();
// Zoom
DWORD ChangeZoomType(DWORD zoomType);
// Theme
BOOL IsHighContrast();
// Utility
virtual CString IP(CString imageName);
CString i18n(CString section, CString key, BOOL inEnglish = FALSE);
void OpenUrl(CString url);
void SetLayeredWindow(HWND hWnd, BYTE alpha);
int GetDpi();
// MessageMap
DECLARE_MESSAGE_MAP()
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg LRESULT OnDpiChanged(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnDisplayChange(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnSysColorChange(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnSettingChange(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnEnterSizeMove(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnExitSizeMove(WPARAM wParam, LPARAM lParam);
protected:
// Dialog
BOOL m_bInitializing;
BOOL m_bDpiChanging;
BOOL m_bShowWindow;
BOOL m_bModelessDlg;
BOOL m_bHighContrast;
BOOL m_bDarkMode;
BOOL m_bDisableDarkMode;
BOOL m_bBkImage;
UINT m_MenuId;
CWnd* m_ParentWnd;
CWnd* m_DlgWnd;
CString m_Ini;
HACCEL m_hAccelerator;
BOOL m_bDrag;
CString m_FontFace;
int m_FontScale;
double m_FontRatio;
BYTE m_FontRender;
HPALETTE m_hPal;
int m_SizeX;
int m_MaxSizeX;
int m_MinSizeX;
int m_SizeY;
int m_MaxSizeY;
int m_MinSizeY;
// Zoom
int m_Dpi;
DWORD m_ZoomType;
double m_ZoomRatio;
// Color for SubClass
COLORREF m_LabelText;
COLORREF m_MeterText;
COLORREF m_ComboText;
COLORREF m_ComboTextSelected;
COLORREF m_ComboBk;
COLORREF m_ComboBkSelected;
COLORREF m_ButtonText;
COLORREF m_EditText;
COLORREF m_EditBk;
COLORREF m_ListText1;
COLORREF m_ListText2;
COLORREF m_ListTextSelected;
COLORREF m_ListBk1;
COLORREF m_ListBk2;
COLORREF m_ListBkSelected;
COLORREF m_ListLine1;
COLORREF m_ListLine2;
COLORREF m_Glass;
COLORREF m_Frame;
COLORREF m_Background;
BYTE m_ComboAlpha;
BYTE m_EditAlpha;
BYTE m_GlassAlpha;
BYTE m_CharacterPosition;
// Theme for SubClass
int m_OffsetX;
CString m_ThemeDir;
CString m_CurrentTheme;
CString m_DefaultTheme;
CString m_ParentTheme1;
CString m_ParentTheme2;
CString m_RandomThemeLabel;
CString m_RandomThemeName;
// Language for SubClass
CString m_LangDir;
CString m_CurrentLang;
CString m_CurrentLangPath;
CString m_DefaultLangPath;
CString m_BackgroundName;
// Voice for SubClass
CString m_VoiceDir;
CString m_CurrentVoice;
INT m_VoiceVolume;
// Class
CBitmap m_BkBitmap;
CDC m_BkDC;
CImage m_BkImage;
CBrush m_BrushDlg;
};
@@ -0,0 +1,629 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "EditFx.h"
////------------------------------------------------
// CEditFx
////------------------------------------------------
CEditFx::CEditFx()
{
// Control
m_X = 0;
m_Y = 0;
m_bHighContrast = FALSE;
m_bDarkMode = FALSE;
m_bDrawFrame = FALSE;
m_FrameColor = RGB(128, 128, 128);
m_RenderMode = OwnerDrawImage;
m_bMultiLine = FALSE;
m_BkColor = RGB(255, 255, 255);
// Glass
m_GlassColor = RGB(255, 255, 255);
m_GlassAlpha = 128;
// Image
m_ImageCount = 0;
m_BkDC = NULL;
m_bBkBitmapInit = FALSE;
m_bBkLoad = FALSE;
// Font
m_TextAlign = SS_LEFT;
m_TextColor = RGB(0, 0, 0);
// Margin
m_Margin.top = 0;
m_Margin.left = 0;
m_Margin.bottom = 0;
m_Margin.right = 0;
}
CEditFx::~CEditFx()
{
}
IMPLEMENT_DYNAMIC(CEditFx, CEdit)
BEGIN_MESSAGE_MAP(CEditFx, CEdit)
//{{AFX_MSG_MAP(CEditFx)
ON_WM_CTLCOLOR_REFLECT()
ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange)
ON_WM_KEYDOWN()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//------------------------------------------------
// Control
//------------------------------------------------
BOOL CEditFx::InitControl(int x, int y, int width, int height, double zoomRatio, CDC* bkDC,
LPCTSTR imagePath, int imageCount, DWORD textAlign, int renderMode, BOOL bHighContrast, BOOL bDarkMode, BOOL bDrawFrame, BOOL bMultiLine)
{
m_X = (int)(x * zoomRatio);
m_Y = (int)(y * zoomRatio);
m_CtrlSize.cx = (int)(width * zoomRatio);
m_CtrlSize.cy = (int)(height * zoomRatio);
MoveWindow(m_X, m_Y, m_CtrlSize.cx, m_CtrlSize.cy);
m_bMultiLine = bMultiLine;
m_BkDC = bkDC;
m_ImagePath = imagePath;
m_ImageCount = imageCount;
m_RenderMode = renderMode;
if (ES_LEFT <= textAlign && textAlign <= ES_RIGHT)
{
m_TextAlign = textAlign;
ModifyStyle(0, m_TextAlign);
}
if (m_ToolTip.m_hWnd != NULL)
{
if (m_ToolTip.GetToolCount() != 0)
{
m_ToolTip.DelTool(this, 1);
}
CRect rect;
GetClientRect(rect);
m_ToolTip.AddTool(this, m_ToolTipText, rect, 1);
}
m_bHighContrast = bHighContrast;
m_bDarkMode = bDarkMode;
m_bDrawFrame = bDrawFrame;
if (m_bHighContrast)
{
return TRUE;
}
else if (renderMode & SystemDraw)
{
return TRUE;
}
else
{
SetBkReload();
LoadCtrlBk(m_BkDC);
}
if (renderMode & OwnerDrawImage)
{
if (!LoadBitmap(imagePath))
{
}
}
else
{
m_ImageCount = 1;
m_CtrlImage.Destroy();
m_CtrlImage.Create(m_CtrlSize.cx, m_CtrlSize.cy * m_ImageCount, 32);
m_CtrlBitmap.Detach();
m_CtrlBitmap.Attach((HBITMAP)m_CtrlImage);
DWORD length = m_CtrlSize.cx * m_CtrlSize.cy * m_ImageCount * 4;
BYTE* bitmapBits = new BYTE[length];
m_CtrlBitmap.GetBitmapBits(length, bitmapBits);
BYTE r, g, b, a;
if (renderMode & OwnerDrawGlass)
{
r = (BYTE)GetRValue(m_GlassColor);
g = (BYTE)GetGValue(m_GlassColor);
b = (BYTE)GetBValue(m_GlassColor);
a = m_GlassAlpha;
}
else // OwnerDrawTransparent
{
r = 0;
g = 0;
b = 0;
a = 0;
}
for (int y = 0; y < (int)(m_CtrlSize.cy * m_ImageCount); y++)
{
for (int x = 0; x < m_CtrlSize.cx; x++)
{
DWORD p = (y * m_CtrlSize.cx + x) * 4;
#if _MSC_VER > 1310
#pragma warning( disable : 6386 )
#endif
bitmapBits[p + 0] = b;
bitmapBits[p + 1] = g;
bitmapBits[p + 2] = r;
bitmapBits[p + 3] = a;
#if _MSC_VER > 1310
#pragma warning( default : 6386 )
#endif
}
}
m_CtrlBitmap.SetBitmapBits(length, bitmapBits);
delete[] bitmapBits;
}
SetupControlImage(m_BkBitmap, m_CtrlBitmap);
m_BkBrush.DeleteObject();
m_BkBrush.CreatePatternBrush(&m_CtrlBitmap);
Invalidate();
return TRUE;
}
void CEditFx::SetMargin(int top, int left, int bottom, int right, double zoomRatio)
{
m_Margin.top = (int)(top * zoomRatio);
m_Margin.left = (int)(left * zoomRatio);
m_Margin.bottom = (int)(bottom * zoomRatio);
m_Margin.right = (int)(right * zoomRatio);
if (GetWindowLongPtr(m_hWnd, GWL_STYLE) & ES_MULTILINE)
{
CRect rectGet, rectSet;
GetRect(rectGet);
rectSet.top = m_Margin.top;
rectSet.bottom = rectGet.bottom - m_Margin.bottom - m_Margin.top;
rectSet.left = m_Margin.left;
rectSet.right = rectGet.right - m_Margin.right - m_Margin.left;
SetRect(rectSet);
}
else
{
SetMargins(m_Margin.left, m_Margin.right);
}
}
CSize CEditFx::GetSize(void)
{
return m_CtrlSize;
}
void CEditFx::SetDrawFrame(BOOL bDrawFrame)
{
#if _MSC_VER > 1310
if (bDrawFrame)
{
ModifyStyleEx(0, WS_EX_STATICEDGE, SWP_DRAWFRAME);
}
else
{
ModifyStyleEx(WS_EX_STATICEDGE, 0, SWP_DRAWFRAME);
}
#else
if (bDrawFrame)
{
if (IsNT3())
{
ModifyStyle(0, WS_BORDER, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
else
{
ModifyStyleEx(0, WS_EX_STATICEDGE, SWP_DRAWFRAME);
}
}
else
{
if (IsNT3())
{
ModifyStyle(WS_BORDER, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
}
else
{
ModifyStyleEx(WS_EX_STATICEDGE, 0, SWP_DRAWFRAME);
}
}
#endif
m_bDrawFrame = bDrawFrame;
}
void CEditFx::SetGlassColor(COLORREF glassColor, BYTE glassAlpha)
{
m_GlassColor = glassColor;
m_GlassAlpha = glassAlpha;
}
void CEditFx::SetBkColor(COLORREF bkColor)
{
m_BkColor = bkColor;
}
void CEditFx::Adjust()
{
CRect rectGet, rectSet;
GetRect(rectGet);
CClientDC dc(this);
HGDIOBJ oldFont = dc.SelectObject(&m_Font);
#ifdef UNICODE
CSize size = dc.GetTextExtent(L"ÁAaPpQqYy8!");
#else
CSize size = dc.GetTextExtent("AaPpQqYy8!");
#endif
dc.SelectObject(oldFont);
rectSet.top = (m_CtrlSize.cy - size.cy) / 2;
rectSet.bottom = rectSet.top + size.cy;
rectSet.left = rectGet.left;
rectSet.right = rectGet.right;
SetRect(rectSet);
}
HBRUSH CEditFx::CtlColor(CDC* pDC, UINT nCtlColor)
{
if (m_bHighContrast)
{
pDC->SetBkMode(TRANSPARENT);
return NULL;
}
else
{
#ifdef UNICODE
pDC->SetTextColor(m_TextColor);
pDC->SetBkMode(TRANSPARENT);
return m_BkBrush;
#else
pDC->SetTextColor(m_TextColor);
pDC->SetBkColor(m_BkColor);
pDC->SetBkMode(OPAQUE);
return CreateSolidBrush(m_BkColor);
#endif
}
}
//------------------------------------------------
// Image
//------------------------------------------------
BOOL CEditFx::LoadBitmap(LPCTSTR fileName)
{
if (m_bHighContrast) { return FALSE; }
if (fileName == NULL) { return FALSE; }
m_CtrlImage.Destroy();
m_CtrlImage.Load(fileName);
if (m_CtrlImage.IsNull()) { return FALSE; }
return LoadBitmap((HBITMAP)m_CtrlImage);
}
BOOL CEditFx::LoadBitmap(HBITMAP hBitmap)
{
if (m_bHighContrast) { return FALSE; }
m_CtrlBitmap.Detach();
m_CtrlBitmap.Attach(hBitmap);
return SetBitmap(m_CtrlBitmap);
}
void CEditFx::SetBkReload(void)
{
m_bBkBitmapInit = FALSE;
m_bBkLoad = FALSE;
}
BOOL CEditFx::SetBitmap(CBitmap& bitmap)
{
if (m_bHighContrast) { return FALSE; }
BITMAP bitmapInfo;
bitmap.GetBitmap(&bitmapInfo);
if (m_CtrlSize.cx != bitmapInfo.bmWidth
|| m_CtrlSize.cy != bitmapInfo.bmHeight / m_ImageCount)
{
return FALSE;
}
else
{
return TRUE;
}
}
void CEditFx::LoadCtrlBk(CDC* drawDC)
{
if (m_bHighContrast) { SetBkReload(); return; }
if (m_BkBitmap.m_hObject != NULL)
{
BITMAP bitmapInfo;
m_BkBitmap.GetBitmap(&bitmapInfo);
if (bitmapInfo.bmBitsPixel != drawDC->GetDeviceCaps(BITSPIXEL))
{
SetBkReload();
}
}
if (&m_CtrlBitmap != NULL)
{
if (!m_bBkBitmapInit)
{
m_BkBitmap.DeleteObject();
m_BkBitmap.CreateCompatibleBitmap(drawDC, m_CtrlSize.cx, m_CtrlSize.cy);
m_bBkBitmapInit = TRUE;
}
if (!m_bBkLoad)
{
CBitmap* pOldBitmap;
CDC* pMemDC = new CDC;
pMemDC->CreateCompatibleDC(drawDC);
pOldBitmap = pMemDC->SelectObject(&m_BkBitmap);
pMemDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, m_BkDC, m_X, m_Y, SRCCOPY);
pMemDC->SelectObject(pOldBitmap);
pMemDC->DeleteDC();
delete pMemDC;
m_bBkLoad = TRUE;
}
}
}
void CEditFx::SetupControlImage(CBitmap& bkBitmap, CBitmap& ctrlBitmap)
{
int color = m_BkDC->GetDeviceCaps(BITSPIXEL) * m_BkDC->GetDeviceCaps(PLANES);
if (!m_CtrlImage.IsNull())
{
if (m_CtrlImage.GetBPP() == 32)
{
CBitmap* bk32Bitmap;
CImage bk32Image;
if (color == 32)
{
bk32Bitmap = &bkBitmap;
}
else
{
bk32Image.Create(m_CtrlSize.cx, m_CtrlSize.cy, 32);
::BitBlt(bk32Image.GetDC(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, *m_BkDC, m_X, m_Y, SRCCOPY);
bk32Bitmap = CBitmap::FromHandle((HBITMAP)bk32Image);
bk32Image.ReleaseDC();
}
BITMAP CtlBmpInfo, DstBmpInfo;
bk32Bitmap->GetBitmap(&DstBmpInfo);
DWORD DstLineBytes = DstBmpInfo.bmWidthBytes;
DWORD DstMemSize = DstLineBytes * DstBmpInfo.bmHeight;
ctrlBitmap.GetBitmap(&CtlBmpInfo);
DWORD CtlLineBytes = CtlBmpInfo.bmWidthBytes;
DWORD CtlMemSize = CtlLineBytes * CtlBmpInfo.bmHeight;
if ((DstBmpInfo.bmWidthBytes != CtlBmpInfo.bmWidthBytes)
|| (DstBmpInfo.bmHeight != CtlBmpInfo.bmHeight / m_ImageCount))
{
// Error Check //
}
else
{
BYTE* DstBuffer = new BYTE[DstMemSize];
bk32Bitmap->GetBitmapBits(DstMemSize, DstBuffer);
BYTE* CtlBuffer = new BYTE[CtlMemSize];
ctrlBitmap.GetBitmapBits(CtlMemSize, CtlBuffer);
int baseY = 0;
for (LONG py = 0; py < DstBmpInfo.bmHeight; py++)
{
int dn = py * DstLineBytes;
int cn = (baseY + py) * CtlLineBytes;
for (LONG px = 0; px < DstBmpInfo.bmWidth; px++)
{
#if _MSC_VER > 1310
#pragma warning( disable : 6385 )
#pragma warning( disable : 6386 )
#endif
BYTE a = CtlBuffer[cn + 3];
BYTE na = 255 - a;
CtlBuffer[dn + 0] = (BYTE)((CtlBuffer[cn + 0] * a + DstBuffer[dn + 0] * na) / 255);
CtlBuffer[dn + 1] = (BYTE)((CtlBuffer[cn + 1] * a + DstBuffer[dn + 1] * na) / 255);
CtlBuffer[dn + 2] = (BYTE)((CtlBuffer[cn + 2] * a + DstBuffer[dn + 2] * na) / 255);
dn += (DstBmpInfo.bmBitsPixel / 8);
cn += (CtlBmpInfo.bmBitsPixel / 8);
#if _MSC_VER > 1310
#pragma warning( default : 6386 )
#pragma warning( default : 6385 )
#endif
}
}
if (color == 32)
{
ctrlBitmap.SetBitmapBits(CtlMemSize, CtlBuffer);
}
else
{
bk32Bitmap->SetBitmapBits(CtlMemSize, CtlBuffer);
m_CtrlImage.Detach();
m_CtrlImage.Attach(ctrlBitmap);
::BitBlt(m_CtrlImage.GetDC(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, bk32Image.GetDC(), 0, 0, SRCCOPY);
m_CtrlImage.ReleaseDC();
bk32Image.ReleaseDC();
ctrlBitmap.SetBitmapBits(CtlMemSize, CtlBuffer);
}
if (m_bDrawFrame)
{
HGDIOBJ oldPen;
POINT point;
CPen pen1; pen1.CreatePen(PS_SOLID, 1, RGB(0xF8, 0xF8, 0xF8));
CPen pen2; pen2.CreatePen(PS_SOLID, 1, RGB(0x98, 0x98, 0x98));
HDC hDC = m_CtrlImage.GetDC();
oldPen = SelectObject(hDC, pen1);
MoveToEx(hDC, 0, m_CtrlSize.cy - 1, &point);
LineTo(hDC, m_CtrlSize.cx - 1, m_CtrlSize.cy - 1);
LineTo(hDC, m_CtrlSize.cx - 1, 0);
LineTo(hDC, m_CtrlSize.cx - 1, m_CtrlSize.cy - 1);
SelectObject(hDC, pen2);
MoveToEx(hDC, 0, m_CtrlSize.cy - 2, &point);
LineTo(hDC, 0, 0);
LineTo(hDC, m_CtrlSize.cx - 1, 0);
SelectObject(hDC, oldPen);
pen1.DeleteObject();
pen2.DeleteObject();
m_CtrlImage.ReleaseDC();
}
delete[] DstBuffer;
delete[] CtlBuffer;
}
}
}
}
//------------------------------------------------
// Font
//------------------------------------------------
void CEditFx::SetFontEx(CString face, int size, int sizeToolTip, double zoomRatio, double fontRatio,
COLORREF textColor, LONG fontWeight, BYTE fontRender)
{
LOGFONT logFont = { 0 };
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfHeight = (LONG)(-1 * size * zoomRatio * fontRatio);
logFont.lfQuality = fontRender;
logFont.lfWeight = fontWeight;
if (face.GetLength() < 32)
{
wsprintf(logFont.lfFaceName, _T("%s"), (LPCTSTR)face);
}
else
{
wsprintf(logFont.lfFaceName, _T(""));
}
m_Font.DeleteObject();
m_Font.CreateFontIndirect(&logFont);
SetFont(&m_Font);
logFont.lfHeight = (LONG)(-1 * sizeToolTip * zoomRatio);
m_FontToolTip.DeleteObject();
m_FontToolTip.CreateFontIndirect(&logFont);
m_TextColor = textColor;
if (m_ToolTip.m_hWnd != NULL)
{
m_ToolTip.SetFont(&m_FontToolTip);
}
}
//------------------------------------------------
// Message Map
//------------------------------------------------
void CEditFx::OnEnChange()
{
Invalidate();
}
void CEditFx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == VK_RETURN && m_bMultiLine == FALSE)
{
return ;
}
else
{
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
}
}
//------------------------------------------------
// ToolTip
//------------------------------------------------
void CEditFx::SetToolTipText(LPCTSTR text)
{
if (text == NULL) { return; }
InitToolTip();
m_ToolTipText = text;
if (m_ToolTip.GetToolCount() == 0)
{
CRect rect;
GetClientRect(rect);
m_ToolTip.AddTool(this, m_ToolTipText, rect, 1);
}
else
{
m_ToolTip.UpdateTipText(m_ToolTipText, this, 1);
}
SetToolTipActivate(TRUE);
}
void CEditFx::SetToolTipActivate(BOOL bActivate)
{
if (m_ToolTip.GetToolCount() == 0) { return; }
m_ToolTip.Activate(bActivate);
}
void CEditFx::SetToolTipWindowText(LPCTSTR text)
{
SetToolTipText(text);
SetWindowText(text);
}
CString CEditFx::GetToolTipText()
{
return m_ToolTipText;
}
void CEditFx::InitToolTip()
{
if (m_ToolTip.m_hWnd == NULL)
{
m_ToolTip.Create(this, TTS_ALWAYSTIP | TTS_BALLOON | TTS_NOANIMATE | TTS_NOFADE);
m_ToolTip.Activate(FALSE);
m_ToolTip.SetFont(&m_FontToolTip);
m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, 1024);
m_ToolTip.SetDelayTime(TTDT_AUTOPOP, 8000);
m_ToolTip.SetDelayTime(TTDT_INITIAL, 500);
m_ToolTip.SetDelayTime(TTDT_RESHOW, 100);
}
}
BOOL CEditFx::PreTranslateMessage(MSG* pMsg)
{
InitToolTip();
m_ToolTip.RelayEvent(pMsg);
return CEdit::PreTranslateMessage(pMsg);
}
@@ -0,0 +1,98 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "ImageFx.h"
class CEditFx : public CEdit
{
DECLARE_DYNAMIC(CEditFx);
public:
// Constructors
CEditFx();
virtual ~CEditFx();
// Control
BOOL InitControl(int x, int y, int width, int height, double zoomRatio, CDC* bkDC, LPCTSTR imagePath,
int imageCount, DWORD textAlign, int renderMode, BOOL bHighContrast, BOOL bDarkMode, BOOL bDrawFrame, BOOL bMultiLine = FALSE);
void SetMargin(int top, int left, int bottom, int right, double zoomRatio);
CSize GetSize(void);
void SetDrawFrame(BOOL bDrawFrame);
void SetGlassColor(COLORREF glassColor, BYTE glassAlpha);
void SetBkColor(COLORREF bkColor);
void Adjust();
// Font
void SetFontEx(CString face, int size, int sizeToolTip, double zoomRatio, double fontRatio = 1.0,
COLORREF textColor = RGB(0, 0, 0), LONG fontWeight = FW_NORMAL, BYTE fontRender = CLEARTYPE_NATURAL_QUALITY);
// ToolTip
void SetToolTipText(LPCTSTR text);
void SetToolTipActivate(BOOL bActivate = TRUE);
void SetToolTipWindowText(LPCTSTR text);
CString GetToolTipText();
protected:
// Image
BOOL LoadBitmap(LPCTSTR fileName);
BOOL LoadBitmap(HBITMAP hBitmap);
void SetBkReload(void);
BOOL SetBitmap(CBitmap& bitmap);
void LoadCtrlBk(CDC* drawDC);
void SetupControlImage(CBitmap& bkBitmap, CBitmap& ctrlBitmap);
// ToolTip
void InitToolTip();
virtual BOOL PreTranslateMessage(MSG* pMsg);
// MessageMap
DECLARE_MESSAGE_MAP()
afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
afx_msg void OnEnChange();
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
protected:
// Control
int m_X;
int m_Y;
CSize m_CtrlSize;
CRect m_Margin;
int m_RenderMode;
BOOL m_bHighContrast;
BOOL m_bDarkMode;
BOOL m_bDrawFrame;
COLORREF m_FrameColor;
BOOL m_bMultiLine;
COLORREF m_BkColor;
// Glass
COLORREF m_GlassColor;
BYTE m_GlassAlpha;
// Image
CString m_ImagePath;
int m_ImageCount;
CDC* m_BkDC;
CBitmap m_BkBitmap;
CBrush m_BkBrush;
BOOL m_bBkBitmapInit;
BOOL m_bBkLoad;
CBitmap m_CtrlBitmap;
CImage m_CtrlImage;
// Font
DWORD m_TextAlign;
CFont m_Font;
CFont m_FontToolTip;
COLORREF m_TextColor;
// ToolTip
CToolTipCtrl m_ToolTip;
CString m_ToolTipText;
};
@@ -0,0 +1,134 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "FontComboBoxFx.h"
////------------------------------------------------
// CFontComboBox
////------------------------------------------------
IMPLEMENT_DYNAMIC(CFontComboBox, CComboBoxFx)
CFontComboBox::CFontComboBox()
{
m_Brush = NULL;
}
CFontComboBox::~CFontComboBox()
{
m_BkBrush.DeleteObject();
}
BEGIN_MESSAGE_MAP(CFontComboBox, CComboBoxFx)
END_MESSAGE_MAP()
void CFontComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (lpDrawItemStruct->itemID == -1) { return; }
static COLORREF textColor;
static COLORREF textColorSelected;
static COLORREF bkColor;
static COLORREF bkColorSelected;
if (m_bHighContrast)
{
textColor = GetTextColor(lpDrawItemStruct->hDC);
textColorSelected = RGB(0, 0, 0);
bkColor = GetBkColor(lpDrawItemStruct->hDC);
bkColorSelected = RGB(0, 255, 255);
if (bkColor <= RGB(0x80, 0x80, 0x80)) { textColor = RGB(255, 255, 255); }
else { textColor = RGB(0, 0, 0); }
}
else if (m_bDarkMode)
{
textColor = RGB(255, 255, 255);
textColorSelected = RGB(255, 255, 255);
bkColor = RGB(32, 32, 32);
bkColorSelected = RGB(77, 77, 77);
}
else
{
textColor = m_TextColor;
textColorSelected = m_TextColorSelected;
bkColor = m_BkColor;
bkColorSelected = m_BkColorSelected;
}
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
LoadCtrlBk(pDC);
CString title;
GetLBText(lpDrawItemStruct->itemID, title);
CFont font;
LOGFONT logfont;
memset(&logfont, 0, sizeof(logfont));
logfont.lfHeight = m_FontHeight;
logfont.lfWidth = 0;
logfont.lfWeight = FW_NORMAL;
logfont.lfQuality = m_FontRender;
logfont.lfCharSet = DEFAULT_CHARSET;
#if _MSC_VER <= 1310
_tcscpy(logfont.lfFaceName, (LPCTSTR)title);
#else
_tcscpy_s(logfont.lfFaceName, 32, (LPCTSTR)title);
#endif
font.CreateFontIndirect(&logfont);
HGDIOBJ oldFont = pDC->SelectObject(&font);
CBrush Brush;
CBrush* pOldBrush;
if (lpDrawItemStruct->rcItem.left != 0 && !m_bHighContrast)
{
DrawControl(title, pDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageNormal);
Brush.CreateSolidBrush(bkColorSelected);
pOldBrush = pDC->SelectObject(&Brush);
if (lpDrawItemStruct->itemState & ODS_SELECTED)
{
RECT rc = lpDrawItemStruct->rcItem;
// rc.top = (LONG)(rc.bottom - 2 * m_ZoomRatio);
rc.right = (LONG)(rc.left + 3 * m_ZoomRatio);
FillRect(lpDrawItemStruct->hDC, &rc, (HBRUSH)Brush);
}
DrawString(title, pDC, lpDrawItemStruct, textColor);
#if _MSC_VER <= 1310
if (IsNT3() && IsWindowEnabled())
{
DWORD oldTextAlign = m_TextAlign;
HGDIOBJ myoldFont = pDC->SelectStockObject(SYSTEM_FONT);
m_TextAlign = ES_RIGHT;
DrawString(_T("v"), pDC, lpDrawItemStruct, textColor);
m_TextAlign = oldTextAlign;
pDC->SelectObject(myoldFont);
}
#endif
}
else
{
if (lpDrawItemStruct->itemState & ODS_SELECTED)
{
Brush.CreateSolidBrush(bkColorSelected);
pOldBrush = pDC->SelectObject(&Brush);
FillRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, (HBRUSH)Brush);
DrawString(title, pDC, lpDrawItemStruct, textColorSelected);
}
else
{
Brush.CreateSolidBrush(bkColor);
pOldBrush = pDC->SelectObject(&Brush);
FillRect(lpDrawItemStruct->hDC, &lpDrawItemStruct->rcItem, (HBRUSH)Brush);
DrawString(title, pDC, lpDrawItemStruct, textColor);
}
}
pDC->SelectObject(pOldBrush);
Brush.DeleteObject();
pDC->SelectObject(oldFont);
}
@@ -0,0 +1,27 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "ComboBoxFx.h"
class CFontComboBox : public CComboBoxFx
{
DECLARE_DYNAMIC(CFontComboBox)
public:
CFontComboBox();
virtual ~CFontComboBox();
protected:
DECLARE_MESSAGE_MAP()
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
HBRUSH m_Brush;
};
@@ -0,0 +1,203 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "HeaderCtrlFx.h"
#include "OsInfoFx.h"
IMPLEMENT_DYNAMIC(CHeaderCtrlFx, CHeaderCtrl)
CHeaderCtrlFx::CHeaderCtrlFx()
{
m_X = 0;
m_Y = 0;
m_TextColor = RGB(0, 0, 0);
m_LineColor = RGB(224, 224, 224);
m_BkColor = RGB(255, 255, 255);
m_ZoomRatio = 1.0;
m_FontRatio = 1.0;
m_FontSize = 12;
m_BkDC = NULL;
m_CtrlBitmap = NULL;
m_bHighContrast = FALSE;
m_bDarkMode = FALSE;
m_RenderMode = SystemDraw;
}
CHeaderCtrlFx::~CHeaderCtrlFx()
{
}
BEGIN_MESSAGE_MAP(CHeaderCtrlFx, CHeaderCtrl)
ON_WM_PAINT()
ON_MESSAGE(HDM_LAYOUT, OnLayout)
END_MESSAGE_MAP()
void CHeaderCtrlFx::InitControl(int x, int y, double zoomRatio, CDC* bkDC, CBitmap* ctrlBitmap, COLORREF textColor, COLORREF bkColor, COLORREF lineColor, int renderMode, BOOL bHighContrast, BOOL bDarkMode)
{
m_X = (int)(x * zoomRatio);
m_Y = (int)(y * zoomRatio);
m_ZoomRatio = zoomRatio;
m_BkDC = bkDC;
m_TextColor = textColor;
m_LineColor = lineColor;
m_BkColor = bkColor;
m_CtrlBitmap = ctrlBitmap;
m_RenderMode = renderMode;
m_bHighContrast = bHighContrast;
m_bDarkMode = bDarkMode;
}
void CHeaderCtrlFx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
if (m_bHighContrast || m_RenderMode & SystemDraw)
{
return CHeaderCtrl::DrawItem(lpDrawItemStruct);
}
CDC* drawDC = CDC::FromHandle(lpDrawItemStruct->hDC);
drawDC->SetBkMode(TRANSPARENT);
drawDC->SetTextColor(m_TextColor);
CRect clientRect;
GetClientRect(&clientRect);
CDC BkDC;
BkDC.CreateCompatibleDC(m_BkDC);
BkDC.SelectObject(m_CtrlBitmap);
CRect rc = lpDrawItemStruct->rcItem;
CBrush br;
if (m_CtrlBitmap != NULL)
{
drawDC->BitBlt(rc.left, rc.top, rc.right, rc.bottom, &BkDC, rc.left, rc.top, SRCCOPY);
}
else
{
br.CreateSolidBrush(m_BkColor);
drawDC->FillRect(&rc, &br);
}
br.DeleteObject();
br.CreateSolidBrush(m_LineColor);
CRect rect = lpDrawItemStruct->rcItem;
rect.left = rect.right - 1;
drawDC->FillRect(&rect, &br);
rect = lpDrawItemStruct->rcItem;
rect.top = rect.bottom - 1;
drawDC->FillRect(&rect, &br);
HDITEM hi{};
TCHAR str[256]{};
hi.mask = HDI_TEXT | HDI_FORMAT;
hi.pszText = str;
hi.cchTextMax = 256;
GetItem(lpDrawItemStruct->itemID, &hi);
rect = (CRect)(lpDrawItemStruct->rcItem);
if (hi.fmt & HDF_CENTER)
{
drawDC->DrawText(hi.pszText, lstrlen(hi.pszText), rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
else if (hi.fmt & HDF_RIGHT)
{
rect.right -= 6;
drawDC->DrawText(hi.pszText, lstrlen(hi.pszText), rect, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
}
else
{
rect.left += 6;
drawDC->DrawText(hi.pszText, lstrlen(hi.pszText), rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
}
void CHeaderCtrlFx::OnPaint()
{
if (m_bHighContrast || m_RenderMode & SystemDraw)
{
return CHeaderCtrl::OnPaint();
}
CHeaderCtrl::OnPaint();
RECT rectRightItem;
int iItemCount = Header_GetItemCount(this->m_hWnd);
if (iItemCount > 0)
{
Header_GetItemRect(this->m_hWnd, (WPARAM)iItemCount - 1, &rectRightItem);
RECT rectClient;
GetClientRect(&rectClient);
if (rectRightItem.right < rectClient.right)
{
CDC* drawDC = GetDC();
if (m_CtrlBitmap != NULL)
{
CDC BkDC;
BkDC.CreateCompatibleDC(m_BkDC);
BkDC.SelectObject(m_CtrlBitmap);
drawDC->BitBlt(rectRightItem.right, rectClient.top, rectClient.right, rectClient.bottom, &BkDC, rectRightItem.right, rectRightItem.top, SRCCOPY);
}
else
{
CBrush br;
br.CreateSolidBrush(m_BkColor);
rectClient.left = rectRightItem.right;
drawDC->FillRect(&rectClient, &br);
}
}
}
}
LRESULT CHeaderCtrlFx::OnLayout(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = CHeaderCtrl::DefWindowProc(HDM_LAYOUT, 0, lParam);
if (IsWinXpLuna())
{
HD_LAYOUT& hdl = *(HD_LAYOUT*)lParam;
RECT* prc = hdl.prc;
WINDOWPOS* pwpos = hdl.pwpos;
int nHeight = (int)(pwpos->cy * (m_ZoomRatio * m_FontRatio));
pwpos->cy = nHeight;
prc->top = nHeight;
}
return lResult;
}
void CHeaderCtrlFx::SetFontEx(CString face, int size, double zoomRatio, double fontRatio, LONG fontWeight, BYTE fontRender)
{
m_FontSize = size;
m_ZoomRatio = zoomRatio;
m_FontRatio = fontRatio;
LOGFONT logFont = { 0 };
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfHeight = (LONG)(-1 * size * zoomRatio * fontRatio);
logFont.lfQuality = fontRender;
logFont.lfWeight = fontWeight;
if (face.GetLength() < 32)
{
wsprintf(logFont.lfFaceName, _T("%s"), (LPCTSTR)face);
}
else
{
wsprintf(logFont.lfFaceName, _T(""));
}
m_Font.DeleteObject();
m_Font.CreateFontIndirect(&logFont);
SetFont(&m_Font);
}
@@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
class CHeaderCtrlFx : public CHeaderCtrl
{
DECLARE_DYNAMIC(CHeaderCtrlFx)
public:
CHeaderCtrlFx();
virtual ~CHeaderCtrlFx();
void InitControl(int x, int y, double zoomRatio, CDC* bkDC, CBitmap* ctrlBitmap, COLORREF textColor, COLORREF bkColor, COLORREF lineColor, int renderMode, BOOL bHighContrast, BOOL bDarkMode);
void SetFontEx(CString face, int size, double zoomRatio, double fontRatio, LONG fontWeight, BYTE fontRender);
protected:
// Draw Control
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
DECLARE_MESSAGE_MAP()
afx_msg void OnPaint();
afx_msg LRESULT OnLayout(WPARAM wParam, LPARAM lParam);
int m_X;
int m_Y;
COLORREF m_TextColor;
COLORREF m_BkColor;
COLORREF m_LineColor;
double m_ZoomRatio;
double m_FontRatio;
int m_RenderMode;
BOOL m_bHighContrast;
BOOL m_bDarkMode;
CFont m_Font;
int m_FontSize;
CDC* m_BkDC;
CBitmap* m_CtrlBitmap;
};
@@ -0,0 +1,99 @@
/*---------------------------------------------------------------------------*/
// Author : Richard Yu
// Web : https://github.com/ysc3839/win32-darkmode
// License : The MIT License
// https://github.com/ysc3839/win32-darkmode/blob/master/LICENSE
/*---------------------------------------------------------------------------*/
// This file contains code from
// https://github.com/stevemk14ebr/PolyHook_2_0/blob/master/sources/IatHook.cpp
// which is licensed under the MIT License.
// See PolyHook_2_0-LICENSE for more information.
#pragma once
#include <stdint.h>
template <typename T, typename T1, typename T2>
constexpr T RVA2VA(T1 base, T2 rva)
{
return reinterpret_cast<T>(reinterpret_cast<ULONG_PTR>(base) + rva);
}
template <typename T>
constexpr T DataDirectoryFromModuleBase(void *moduleBase, size_t entryID)
{
auto dosHdr = reinterpret_cast<PIMAGE_DOS_HEADER>(moduleBase);
auto ntHdr = RVA2VA<PIMAGE_NT_HEADERS>(moduleBase, dosHdr->e_lfanew);
auto dataDir = ntHdr->OptionalHeader.DataDirectory;
return RVA2VA<T>(moduleBase, dataDir[entryID].VirtualAddress);
}
PIMAGE_THUNK_DATA FindAddressByName(void *moduleBase, PIMAGE_THUNK_DATA impName, PIMAGE_THUNK_DATA impAddr, const char *funcName)
{
for (; impName->u1.Ordinal; ++impName, ++impAddr)
{
if (IMAGE_SNAP_BY_ORDINAL(impName->u1.Ordinal))
continue;
auto import = RVA2VA<PIMAGE_IMPORT_BY_NAME>(moduleBase, impName->u1.AddressOfData);
if (strcmp(import->Name, funcName) != 0)
continue;
return impAddr;
}
return nullptr;
}
PIMAGE_THUNK_DATA FindAddressByOrdinal(void *moduleBase, PIMAGE_THUNK_DATA impName, PIMAGE_THUNK_DATA impAddr, uint16_t ordinal)
{
for (; impName->u1.Ordinal; ++impName, ++impAddr)
{
if (IMAGE_SNAP_BY_ORDINAL(impName->u1.Ordinal) && IMAGE_ORDINAL(impName->u1.Ordinal) == ordinal)
return impAddr;
}
return nullptr;
}
PIMAGE_THUNK_DATA FindIatThunkInModule(void *moduleBase, const char *dllName, const char *funcName)
{
auto imports = DataDirectoryFromModuleBase<PIMAGE_IMPORT_DESCRIPTOR>(moduleBase, IMAGE_DIRECTORY_ENTRY_IMPORT);
for (; imports->Name; ++imports)
{
if (_stricmp(RVA2VA<LPCSTR>(moduleBase, imports->Name), dllName) != 0)
continue;
auto origThunk = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->OriginalFirstThunk);
auto thunk = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->FirstThunk);
return FindAddressByName(moduleBase, origThunk, thunk, funcName);
}
return nullptr;
}
PIMAGE_THUNK_DATA FindDelayLoadThunkInModule(void *moduleBase, const char *dllName, const char *funcName)
{
auto imports = DataDirectoryFromModuleBase<PIMAGE_DELAYLOAD_DESCRIPTOR>(moduleBase, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
for (; imports->DllNameRVA; ++imports)
{
if (_stricmp(RVA2VA<LPCSTR>(moduleBase, imports->DllNameRVA), dllName) != 0)
continue;
auto impName = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->ImportNameTableRVA);
auto impAddr = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->ImportAddressTableRVA);
return FindAddressByName(moduleBase, impName, impAddr, funcName);
}
return nullptr;
}
PIMAGE_THUNK_DATA FindDelayLoadThunkInModule(void *moduleBase, const char *dllName, uint16_t ordinal)
{
auto imports = DataDirectoryFromModuleBase<PIMAGE_DELAYLOAD_DESCRIPTOR>(moduleBase, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
for (; imports->DllNameRVA; ++imports)
{
if (_stricmp(RVA2VA<LPCSTR>(moduleBase, imports->DllNameRVA), dllName) != 0)
continue;
auto impName = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->ImportNameTableRVA);
auto impAddr = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->ImportAddressTableRVA);
return FindAddressByOrdinal(moduleBase, impName, impAddr, ordinal);
}
return nullptr;
}
@@ -0,0 +1,420 @@
#pragma once
#include <windows.h>
#include <tchar.h>
#include "stb_image.h"
#include "stb_image_write.h"
class CImage
{
public:
enum
{
createAlphaChannel = 0x01
};
CImage()
{
Init();
}
~CImage()
{
Destroy();
}
operator HBITMAP() const { return m_hBitmap; }
BOOL IsNull() const { return m_hBitmap == NULL; }
int GetWidth() const { return m_width; }
int GetHeight() const { return m_height; }
int GetPitch() const { return m_pitch; }
int GetBPP() const { return 32; }
void* GetBits() const { return m_bits; }
BOOL Create(int w, int h, int bpp, DWORD flags = 0)
{
Destroy();
if (bpp != 32) return FALSE;
BITMAPINFO bmi = {};
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = w;
bmi.bmiHeader.biHeight = -h;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
void* bits = NULL;
m_hBitmap = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
if (!m_hBitmap) return FALSE;
m_bits = (BYTE*)bits;
m_width = w;
m_height = h;
m_pitch = w * 4;
m_hasAlpha = (flags & createAlphaChannel) != 0;
memset(m_bits, 0, w * h * 4);
return TRUE;
}
void Destroy()
{
ReleaseDC();
if (m_hBitmap)
{
DeleteObject(m_hBitmap);
m_hBitmap = NULL;
}
Init();
}
BOOL Load(LPCTSTR fileName)
{
Destroy();
HANDLE hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return FALSE;
}
DWORD size = GetFileSize(hFile, NULL);
BYTE* buf = (BYTE*)malloc(size);
DWORD read = 0;
if (ReadFile(hFile, buf, size, &read, NULL) == FALSE || read != size)
{
free(buf);
CloseHandle(hFile);
return FALSE;
}
BOOL result = FALSE;
if (IsPNG(buf))
{
result = LoadPNG(buf, size);
}
else if (IsBMP(buf))
{
result = LoadBMP(buf, size);
}
free(buf);
return result;
}
static void png_write_func(void* context, void* data, int size)
{
HANDLE hFile = (HANDLE)context;
DWORD written = 0;
WriteFile(hFile, data, size, &written, NULL);
}
BOOL Save(LPCTSTR fileName)
{
if (!m_bits || !fileName)
return FALSE;
if (IsPNGFileName(fileName))
return SavePNG(fileName);
if (IsBMPFileName(fileName))
return SaveBMP(fileName);
return FALSE;
}
BOOL IsPNGFileName(LPCTSTR fileName)
{
LPCTSTR ext = _tcsrchr(fileName, _T('.'));
if (!ext) return FALSE;
return _tcsicmp(ext, _T(".png")) == 0;
}
BOOL IsBMPFileName(LPCTSTR fileName)
{
LPCTSTR ext = _tcsrchr(fileName, _T('.'));
if (!ext) return FALSE;
return _tcsicmp(ext, _T(".bmp")) == 0;
}
BOOL SavePNG(LPCTSTR fileName)
{
HANDLE hFile = CreateFile(
fileName,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
size_t size = (size_t)m_width * m_height * 4;
BYTE* tmp = (BYTE*)malloc(size);
if (!tmp) {
CloseHandle(hFile);
return FALSE;
}
for (int y = 0; y < m_height; y++)
{
BYTE* src = m_bits + y * m_pitch;
BYTE* dst = tmp + y * m_width * 4;
for (int x = 0; x < m_width; x++)
{
dst[x * 4 + 0] = src[x * 4 + 2];
dst[x * 4 + 1] = src[x * 4 + 1];
dst[x * 4 + 2] = src[x * 4 + 0];
dst[x * 4 + 3] = 255;
}
}
int result = stbi_write_png_to_func(
png_write_func,
(void*)hFile,
m_width,
m_height,
4,
tmp,
m_width * 4);
free(tmp);
CloseHandle(hFile);
return result != 0;
}
BOOL SaveBMP(LPCTSTR fileName)
{
HANDLE hFile = CreateFile(
fileName,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
int rowSize = ((m_width * 3 + 3) / 4) * 4;
int dataSize = rowSize * m_height;
BITMAPFILEHEADER bf = {};
bf.bfType = 0x4D42; // 'BM'
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bf.bfSize = bf.bfOffBits + dataSize;
BITMAPINFOHEADER bi = {};
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = m_width;
bi.biHeight = m_height; // bottom-up
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biCompression = BI_RGB;
DWORD written = 0;
WriteFile(hFile, &bf, sizeof(bf), &written, NULL);
WriteFile(hFile, &bi, sizeof(bi), &written, NULL);
BYTE* line = (BYTE*)malloc(rowSize);
if (!line)
{
CloseHandle(hFile);
return FALSE;
}
for (int y = m_height - 1; y >= 0; y--)
{
BYTE* src = m_bits + y * m_pitch;
BYTE* dst = line;
memset(line, 0, rowSize);
for (int x = 0; x < m_width; x++)
{
dst[0] = src[0]; // B
dst[1] = src[1]; // G
dst[2] = src[2]; // R
src += 4;
dst += 3;
}
if (!WriteFile(hFile, line, rowSize, &written, NULL) || written != (DWORD)rowSize)
{
free(line);
CloseHandle(hFile);
return FALSE;
}
}
free(line);
CloseHandle(hFile);
return TRUE;
}
BOOL BitBlt(HDC hDest, int x, int y, DWORD rop = SRCCOPY) const
{
return BitBlt(hDest, x, y, m_width, m_height, 0, 0, rop);
}
BOOL BitBlt(HDC hDest, int x, int y, int w, int h, int sx, int sy, DWORD rop) const
{
HDC hSrc = GetDC();
BOOL r = ::BitBlt(hDest, x, y, w, h, hSrc, sx, sy, rop);
ReleaseDC();
return r;
}
COLORREF GetPixel(int x, int y) const
{
BYTE* p = m_bits + y * m_pitch + x * 4;
return RGB(p[2], p[1], p[0]);
}
HDC GetDC() const
{
if (!m_hDC)
{
m_hDC = CreateCompatibleDC(NULL);
m_hOldBitmap = (HBITMAP)SelectObject(m_hDC, m_hBitmap);
}
return m_hDC;
}
void ReleaseDC() const
{
if (m_hDC)
{
SelectObject(m_hDC, m_hOldBitmap);
DeleteDC(m_hDC);
m_hDC = NULL;
m_hOldBitmap = NULL;
}
}
void Attach(HBITMAP hBitmap)
{
Destroy();
m_hBitmap = hBitmap;
BITMAP bm;
GetObject(hBitmap, sizeof(bm), &bm);
m_width = bm.bmWidth;
m_height = bm.bmHeight;
m_pitch = bm.bmWidthBytes;
m_bits = (BYTE*)bm.bmBits;
m_hasAlpha = (bm.bmBitsPixel == 32);
}
HBITMAP Detach()
{
HBITMAP h = m_hBitmap;
Init();
return h;
}
private:
void Init()
{
m_hBitmap = NULL;
m_bits = NULL;
m_width = m_height = m_pitch = 0;
m_hDC = NULL;
m_hOldBitmap = NULL;
m_hasAlpha = false;
}
BOOL IsPNG(BYTE* p)
{
static BYTE sig[8] = { 137,80,78,71,13,10,26,10 };
return memcmp(p, sig, 8) == 0;
}
BOOL IsBMP(BYTE* p)
{
return p[0] == 'B' && p[1] == 'M';
}
BOOL LoadPNG(BYTE* data, int size)
{
int w, h, c;
unsigned char* img = stbi_load_from_memory(data, size, &w, &h, &c, 4);
if (!img) return FALSE;
Create(w, h, 32, createAlphaChannel);
for (int i = 0; i < w * h; i++)
{
BYTE r = img[i * 4 + 0];
BYTE g = img[i * 4 + 1];
BYTE b = img[i * 4 + 2];
BYTE a = img[i * 4 + 3];
m_bits[i * 4 + 0] = b;
m_bits[i * 4 + 1] = g;
m_bits[i * 4 + 2] = r;
m_bits[i * 4 + 3] = a;
}
stbi_image_free(img);
return TRUE;
}
BOOL LoadBMP(BYTE* data, int)
{
BITMAPFILEHEADER* bf = (BITMAPFILEHEADER*)data;
BITMAPINFOHEADER* bi = (BITMAPINFOHEADER*)(data + sizeof(BITMAPFILEHEADER));
BYTE* src = data + bf->bfOffBits;
Create(bi->biWidth, abs(bi->biHeight), 32);
for (int y = 0; y < m_height; y++)
{
BYTE* d = m_bits + y * m_pitch;
BYTE* s = src + (m_height - 1 - y) * ((m_width * 3 + 3) & ~3);
for (int x = 0; x < m_width; x++)
{
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
d[3] = 255;
d += 4; s += 3;
}
}
return TRUE;
}
private:
HBITMAP m_hBitmap;
BYTE* m_bits;
int m_width, m_height, m_pitch;
mutable HDC m_hDC;
mutable HBITMAP m_hOldBitmap;
bool m_hasAlpha;
};
@@ -0,0 +1,269 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "ImageToast.h"
#ifndef CMK_MIN
#define CMK_MIN(a,b) (( (a) < (b) ) ? (a) : (b))
#endif
#ifndef CMK_MAX
#define CMK_MAX(a,b) (( (a) > (b) ) ? (a) : (b))
#endif
using namespace Gdiplus;
static const UINT IDT_CLOSE = 1;
static const UINT IDT_FADE = 2;
BEGIN_MESSAGE_MAP(CImageToast, CWnd)
ON_WM_CREATE()
ON_WM_TIMER()
ON_WM_LBUTTONDOWN()
ON_WM_RBUTTONDOWN()
ON_WM_ERASEBKGND()
ON_WM_KEYDOWN()
END_MESSAGE_MAP()
CImageToast::CImageToast() {}
CImageToast::~CImageToast() {
if (m_hDib) { ::DeleteObject(m_hDib); m_hDib = nullptr; }
}
int CImageToast::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
return 0;
}
BOOL CImageToast::OnEraseBkgnd(CDC* /*pDC*/) { return TRUE; }
void CImageToast::OnLButtonDown(UINT, CPoint)
{
OpenUrlIfAny();
BeginClose(FALSE);
}
void CImageToast::OnRButtonDown(UINT, CPoint)
{
BeginClose(FALSE);
}
void CImageToast::OnKeyDown(UINT, UINT, UINT)
{
BeginClose(FALSE);
}
BOOL CImageToast::EnsureWindowCreated()
{
if (m_hWnd && ::IsWindow(m_hWnd)) return TRUE;
CString cls = AfxRegisterWndClass(0, ::LoadCursor(nullptr, IDC_HAND), 0, 0);
DWORD ex = WS_EX_TOPMOST | WS_EX_TOOLWINDOW | WS_EX_LAYERED;
DWORD st = WS_POPUP;
if (!CreateEx(ex, cls, _T(""), st, CRect(0,0,0,0), nullptr, 0))
return FALSE;
ShowWindow(SW_SHOWNOACTIVATE);
return TRUE;
}
static BOOL CreateARGBDIB(HDC hdc, int w, int h, HBITMAP& outBmp, void** outBits)
{
BITMAPINFO bi{};
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = w;
bi.bmiHeader.biHeight = -h; // top-down
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
void* bits = nullptr;
HBITMAP hbmp = CreateDIBSection(hdc, &bi, DIB_RGB_COLORS, &bits, nullptr, 0);
if (!hbmp || !bits) return FALSE;
outBmp = hbmp; *outBits = bits; return TRUE;
}
BOOL CImageToast::LoadPngToDIB(LPCWSTR path)
{
Gdiplus::Bitmap bmp(path);
if (bmp.GetLastStatus() != Gdiplus::Ok) return FALSE;
const int w = (int)bmp.GetWidth();
const int h = (int)bmp.GetHeight();
if (w <= 0 || h <= 0) return FALSE;
HDC hdcScreen = ::GetDC(nullptr);
HBITMAP hbmp = nullptr;
void* bits = nullptr;
if (!CreateARGBDIB(hdcScreen, w, h, hbmp, &bits)) {
::ReleaseDC(nullptr, hdcScreen);
return FALSE;
}
HDC hdcMem = ::CreateCompatibleDC(hdcScreen);
HGDIOBJ oldBmp = ::SelectObject(hdcMem, hbmp);
{
Gdiplus::Graphics g(hdcMem);
g.SetCompositingMode(Gdiplus::CompositingModeSourceCopy);
Gdiplus::SolidBrush clearBrush(Gdiplus::Color(0, 0, 0, 0));
g.FillRectangle(&clearBrush, 0, 0, w, h);
g.DrawImage(&bmp, 0, 0, w, h);
}
::SelectObject(hdcMem, oldBmp);
::DeleteDC(hdcMem);
::ReleaseDC(nullptr, hdcScreen);
if (m_hDib) ::DeleteObject(m_hDib);
m_hDib = hbmp;
m_bmpSize.cx = w; m_bmpSize.cy = h;
return TRUE;
}
void CImageToast::UpdateLayered()
{
if (!m_hWnd || !::IsWindow(m_hWnd) || !m_hDib) return;
HDC hdcScreen = ::GetDC(nullptr);
HDC hdcMem = ::CreateCompatibleDC(hdcScreen);
HBITMAP hOld = (HBITMAP)::SelectObject(hdcMem, m_hDib);
POINT ptSrc{ 0,0 };
SIZE sz{ m_bmpSize.cx, m_bmpSize.cy };
BLENDFUNCTION bf{};
bf.BlendOp = AC_SRC_OVER;
bf.SourceConstantAlpha = m_curAlpha;
bf.AlphaFormat = AC_SRC_ALPHA;
POINT cursor{}; ::GetCursorPos(&cursor);
HMONITOR mon = ::MonitorFromPoint(cursor, MONITOR_DEFAULTTONEAREST);
MONITORINFO mi{ sizeof(mi) }; ::GetMonitorInfo(mon, &mi);
RECT wa = mi.rcWork;
POINT ptDst{};
ptDst.x = wa.right - sz.cx - m_margin;
ptDst.y = wa.bottom - sz.cy - m_margin;
::UpdateLayeredWindow(m_hWnd, hdcScreen, &ptDst, &sz, hdcMem, &ptSrc, 0, &bf, ULW_ALPHA);
::SelectObject(hdcMem, hOld);
::DeleteDC(hdcMem);
::ReleaseDC(nullptr, hdcScreen);
}
void CImageToast::StartFadeTimer(BOOL fadeIn)
{
if (!m_enableFade) return;
m_closing = !fadeIn;
SetTimer(IDT_FADE, 16, nullptr);
}
void CImageToast::BeginClose(BOOL force)
{
if (!m_hWnd) return;
if (force || !m_enableFade) {
KillTimer(IDT_FADE);
KillTimer(IDT_CLOSE);
DestroyWindow();
return;
}
if (!m_closing) {
m_closing = TRUE;
SetTimer(IDT_FADE, 16, nullptr);
}
}
void CImageToast::OnTimer(UINT_PTR id)
{
if (id == IDT_CLOSE) {
KillTimer(IDT_CLOSE);
BeginClose(FALSE);
return;
}
if (id == IDT_FADE) {
int stepIn = CMK_MAX(1, (int)m_maxAlpha * 16 / CMK_MAX(1, m_fadeInMs));
int stepOut = CMK_MAX(1, (int)m_maxAlpha * 16 / CMK_MAX(1, m_fadeOutMs));
if (!m_closing) {
if (m_curAlpha < m_maxAlpha) {
m_curAlpha = (BYTE)CMK_MIN((int)m_maxAlpha, (int)m_curAlpha + stepIn);
UpdateLayered();
}
else {
KillTimer(IDT_FADE);
}
}
else {
if (m_curAlpha > 0) {
m_curAlpha = (BYTE)CMK_MAX(0, (int)m_curAlpha - stepOut);
UpdateLayered();
}
else {
KillTimer(IDT_FADE);
DestroyWindow();
}
}
return;
}
CWnd::OnTimer(id);
}
BOOL CImageToast::Show(LPCWSTR pngPath, UINT showMillis, BOOL enableFade, BYTE maxAlpha,
int margin, int fadeInMs, int fadeOutMs, LPCWSTR urlToOpen)
{
m_pngPath = pngPath;
m_showMillis = showMillis;
m_enableFade = enableFade;
m_maxAlpha = maxAlpha;
m_margin = margin;
m_fadeInMs = fadeInMs;
m_fadeOutMs = fadeOutMs;
m_curAlpha = enableFade ? 0 : maxAlpha;
m_closing = FALSE;
m_opened = FALSE;
m_url = (urlToOpen ? urlToOpen : L"");
if (!EnsureWindowCreated()) return FALSE;
if (!LoadPngToDIB(m_pngPath)) {
BeginClose(TRUE);
return FALSE;
}
UpdateLayered();
ShowWindow(SW_SHOWNOACTIVATE);
SetTimer(IDT_CLOSE, m_showMillis, nullptr);
if (m_enableFade) StartFadeTimer(TRUE);
return TRUE;
}
void CImageToast::SetLink(LPCWSTR urlToOpen)
{
m_url = (urlToOpen ? urlToOpen : L"");
}
void CImageToast::CloseNow()
{
BeginClose(FALSE);
}
void CImageToast::OpenUrlIfAny()
{
if (m_opened) return;
if (m_url.IsEmpty()) return;
m_opened = TRUE;
::ShellExecuteW(nullptr, _T("open"), m_url, nullptr, nullptr, SW_SHOWNORMAL);
}
@@ -0,0 +1,60 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "Shcore.lib")
class CImageToast : public CWnd
{
public:
CImageToast();
virtual ~CImageToast();
BOOL Show(LPCWSTR pngPath, UINT showMillis = 30000,
BOOL enableFade = TRUE, BYTE maxAlpha = 255,
int margin = 16, int fadeInMs = 200, int fadeOutMs = 250,
LPCWSTR urlToOpen = nullptr);
void SetLink(LPCWSTR urlToOpen);
void CloseNow();
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnRButtonDown(UINT nFlags, CPoint point);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
DECLARE_MESSAGE_MAP()
BOOL EnsureWindowCreated();
BOOL LoadPngToDIB(LPCWSTR path);
void UpdateLayered();
void BeginClose(BOOL force = FALSE);
void StartFadeTimer(BOOL fadeIn);
void OpenUrlIfAny();
private:
CString m_pngPath;
UINT m_showMillis{ 30000 };
BOOL m_enableFade{ TRUE };
BYTE m_maxAlpha{ 255 };
int m_margin{ 16 };
int m_fadeInMs{ 200 };
int m_fadeOutMs{ 250 };
CString m_url;
HBITMAP m_hDib{ nullptr };
SIZE m_bmpSize{ 0,0 };
BYTE m_curAlpha{ 0 };
BOOL m_closing{ FALSE };
BOOL m_opened{ FALSE };
};
@@ -0,0 +1,372 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "ListCtrlFx.h"
#include "OsInfoFx.h"
IMPLEMENT_DYNAMIC(CListCtrlFx, CListCtrl)
CListCtrlFx::CListCtrlFx()
{
m_X = 0;
m_Y = 0;
m_bNT6orLater = IsNT6orLater();
m_BkDC = NULL;
m_bHighContrast = FALSE;
m_RenderMode = SystemDraw;
m_bDarkMode = FALSE;
// Color
m_TextColor1 = RGB(0, 0, 0);
m_TextColor2 = RGB(0, 0, 0);
m_TextSelected = RGB(0, 0, 0);
m_BkColor1 = RGB(255, 255, 255);
m_BkColor2 = RGB(248, 248, 248);
m_BkSelected = RGB(248, 248, 255);
m_LineColor1 = RGB(224, 224, 224);
m_LineColor2 = RGB(240, 240, 240);
// Glass
m_GlassColor = RGB(255, 255, 255);
m_GlassAlpha = 128;
}
CListCtrlFx::~CListCtrlFx()
{
}
#pragma warning( disable : 26454 )
BEGIN_MESSAGE_MAP(CListCtrlFx, CListCtrl)
ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, &CListCtrlFx::OnCustomdraw)
END_MESSAGE_MAP()
#pragma warning( default : 26454 )
BOOL CListCtrlFx::InitControl(int x, int y, int width, int height, int maxWidth, int maxHeight, double zoomRatio, CDC* bkDC, int renderMode, BOOL bHighContrast, BOOL bDarkMode)
{
m_X = (int)(x * zoomRatio);
m_Y = (int)(y * zoomRatio);
m_CtrlSize.cx = (int)(width * zoomRatio);
m_CtrlSize.cy = (int)(height * zoomRatio);
MoveWindow(m_X, m_Y, m_CtrlSize.cx, m_CtrlSize.cy);
maxWidth = (int)(maxWidth * zoomRatio);
maxHeight = (int)(maxHeight * zoomRatio);
m_BkDC = bkDC;
m_RenderMode = renderMode;
m_bHighContrast = bHighContrast;
m_bDarkMode = bDarkMode;
if (m_bHighContrast)
{
SetBkImage((LPTSTR)_T(""));
}
else if (renderMode & OwnerDrawGlass || renderMode & OwnerDrawTransparent)
{
m_BkBitmap.DeleteObject();
m_BkBitmap.CreateCompatibleBitmap(m_BkDC, maxWidth, maxHeight);
CDC BkDC;
BkDC.CreateCompatibleDC(m_BkDC);
BkDC.SelectObject(m_BkBitmap);
BkDC.BitBlt(0, 0, maxWidth, maxHeight, m_BkDC, m_X + 2, m_Y + 2, SRCCOPY);
m_CtrlImage.Destroy();
m_CtrlImage.Create(maxWidth, maxHeight, 32);
RECT rect{};
rect.top = 0;
rect.left = 0;
rect.right = maxWidth;
rect.bottom = maxHeight;
m_CtrlBitmap.Detach();
m_CtrlBitmap.Attach((HBITMAP)m_CtrlImage);
DWORD length = maxWidth * maxHeight * 4;
BYTE* bitmapBits = new BYTE[length];
m_CtrlBitmap.GetBitmapBits(length, bitmapBits);
BYTE r, g, b, a;
if (renderMode & OwnerDrawGlass)
{
r = (BYTE)GetRValue(m_GlassColor);
g = (BYTE)GetGValue(m_GlassColor);
b = (BYTE)GetBValue(m_GlassColor);
a = m_GlassAlpha;
}
else // OwnerDrawTransparent
{
r = 0;
g = 0;
b = 0;
a = 0;
}
for (int y = 0; y < maxHeight; y++)
{
for (int x = 0; x < maxWidth; x++)
{
DWORD p = (y * maxWidth + x) * 4;
#pragma warning( disable : 6386 )
bitmapBits[p + 0] = b;
bitmapBits[p + 1] = g;
bitmapBits[p + 2] = r;
bitmapBits[p + 3] = a;
#pragma warning( default : 6386 )
}
}
m_CtrlBitmap.SetBitmapBits(length, bitmapBits);
delete[] bitmapBits;
SetupControlImage(m_BkBitmap, m_CtrlBitmap);
if(m_bNT6orLater)
{
SetBkImage((HBITMAP)m_CtrlBitmap);
m_Header.InitControl(x, y, zoomRatio, bkDC, &m_CtrlBitmap, m_TextColor1, m_BkColor1, m_LineColor1, m_RenderMode, m_bHighContrast, m_bDarkMode);
}
else
{
SetBkColor(m_BkColor1);
m_Header.InitControl(x, y, zoomRatio, bkDC, NULL, m_TextColor1, m_BkColor1, m_LineColor1, m_RenderMode, m_bHighContrast, m_bDarkMode);
}
}
else
{
if(m_bNT6orLater)
{
SetBkImage((LPTSTR)_T(""));
SetBkColor(m_BkColor1);
m_Header.InitControl(x, y, zoomRatio, bkDC, NULL, m_TextColor1, m_BkColor1, m_LineColor1, m_RenderMode, m_bHighContrast, m_bDarkMode);
}
else
{
SetBkColor(m_BkColor1);
m_Header.InitControl(x, y, zoomRatio, bkDC, NULL, m_TextColor1, m_BkColor1, m_LineColor1, m_RenderMode, m_bHighContrast, m_bDarkMode);
}
}
return TRUE;
}
void CListCtrlFx::SetupControlImage(CBitmap& bkBitmap, CBitmap& ctrlBitmap)
{
int color = m_BkDC->GetDeviceCaps(BITSPIXEL) * m_BkDC->GetDeviceCaps(PLANES);
CBitmap* bk32Bitmap;
CImage bk32Image;
if (color == 32)
{
bk32Bitmap = &bkBitmap;
}
else
{
bk32Image.Create(m_CtrlSize.cx, m_CtrlSize.cy, 32);
::BitBlt(bk32Image.GetDC(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, *m_BkDC, m_X, m_Y, SRCCOPY);
bk32Bitmap = CBitmap::FromHandle((HBITMAP)bk32Image);
bk32Image.ReleaseDC();
}
BITMAP CtlBmpInfo, DstBmpInfo;
bk32Bitmap->GetBitmap(&DstBmpInfo);
DWORD DstLineBytes = DstBmpInfo.bmWidthBytes;
DWORD DstMemSize = DstLineBytes * DstBmpInfo.bmHeight;
ctrlBitmap.GetBitmap(&CtlBmpInfo);
DWORD CtlLineBytes = CtlBmpInfo.bmWidthBytes;
DWORD CtlMemSize = CtlLineBytes * CtlBmpInfo.bmHeight;
BYTE* DstBuffer = new BYTE[DstMemSize];
bk32Bitmap->GetBitmapBits(DstMemSize, DstBuffer);
BYTE* CtlBuffer = new BYTE[CtlMemSize];
ctrlBitmap.GetBitmapBits(CtlMemSize, CtlBuffer);
int baseY = 0;
for (LONG py = 0; py < DstBmpInfo.bmHeight; py++)
{
int dn = py * DstLineBytes;
int cn = (baseY + py) * CtlLineBytes;
for (LONG px = 0; px < DstBmpInfo.bmWidth; px++)
{
#pragma warning( disable : 6385 )
#pragma warning( disable : 6386 )
BYTE a = CtlBuffer[cn + 3];
BYTE na = 255 - a;
CtlBuffer[dn + 0] = (BYTE)((CtlBuffer[cn + 0] * a + DstBuffer[dn + 0] * na) / 255);
CtlBuffer[dn + 1] = (BYTE)((CtlBuffer[cn + 1] * a + DstBuffer[dn + 1] * na) / 255);
CtlBuffer[dn + 2] = (BYTE)((CtlBuffer[cn + 2] * a + DstBuffer[dn + 2] * na) / 255);
dn += (DstBmpInfo.bmBitsPixel / 8);
cn += (CtlBmpInfo.bmBitsPixel / 8);
#pragma warning( default : 6386 )
#pragma warning( default : 6385 )
}
}
if (color == 32)
{
ctrlBitmap.SetBitmapBits(CtlMemSize, CtlBuffer);
}
else
{
bk32Bitmap->SetBitmapBits(CtlMemSize, CtlBuffer);
m_CtrlImage.Detach();
m_CtrlImage.Attach(ctrlBitmap);
::BitBlt(m_CtrlImage.GetDC(), 0, 0, m_CtrlSize.cx - 1, m_CtrlSize.cy - 1, bk32Image.GetDC(), 1, 1, SRCCOPY);
m_CtrlImage.ReleaseDC();
bk32Image.ReleaseDC();
}
delete[] DstBuffer;
delete[] CtlBuffer;
}
void CListCtrlFx::OnCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLVCUSTOMDRAW lpLVCustomDraw = reinterpret_cast<LPNMLVCUSTOMDRAW>(pNMHDR);
switch(lpLVCustomDraw->nmcd.dwDrawStage)
{
case CDDS_ITEMPREPAINT:
case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
if(! m_bHighContrast)
{
if(lpLVCustomDraw->nmcd.dwItemSpec % 2 == 0)
{
lpLVCustomDraw->clrText = m_TextColor1;
lpLVCustomDraw->clrTextBk = m_BkColor1;
}
else
{
lpLVCustomDraw->clrText = m_TextColor2;
lpLVCustomDraw->clrTextBk = m_BkColor2;
}
}
break;
case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
{
RECT rc{};
CBrush br1(m_LineColor1);
CBrush br2(m_LineColor2);
CHeaderCtrl* header = this->GetHeaderCtrl();
if(header != NULL)
{
int count = header->GetItemCount();
for(int i = 0; i < count; i++)
{
ListView_GetSubItemRect(m_hWnd, lpLVCustomDraw->nmcd.dwItemSpec, i, LVIR_LABEL, &rc);
LONG left = rc.left;
rc.left = rc.right - 1;
FillRect(lpLVCustomDraw->nmcd.hdc, &rc, (HBRUSH)br1.GetSafeHandle());
rc.left = left;
rc.top = rc.bottom - 1;
FillRect(lpLVCustomDraw->nmcd.hdc, &rc, (HBRUSH)br2.GetSafeHandle());
}
}
}
break;
default:
break;
}
*pResult = 0;
*pResult |= CDRF_NOTIFYPOSTPAINT;
*pResult |= CDRF_NOTIFYITEMDRAW;
*pResult |= CDRF_NOTIFYSUBITEMDRAW;
}
void CListCtrlFx::SetTextColor1(COLORREF color){m_TextColor1 = color;}
void CListCtrlFx::SetTextColor2(COLORREF color){m_TextColor2 = color;}
void CListCtrlFx::SetTextSelected(COLORREF color){m_TextSelected = color;}
void CListCtrlFx::SetBkColor1(COLORREF color){m_BkColor1 = color;}
void CListCtrlFx::SetBkColor2(COLORREF color){m_BkColor2 = color;}
void CListCtrlFx::SetBkSelected(COLORREF color){m_BkSelected = color;}
void CListCtrlFx::SetLineColor1(COLORREF color){m_LineColor1 = color;}
void CListCtrlFx::SetLineColor2(COLORREF color){m_LineColor2 = color;}
void CListCtrlFx::SetGlassColor(COLORREF glassColor, BYTE glassAlpha)
{
m_GlassColor = glassColor;
m_GlassAlpha = glassAlpha;
}
COLORREF CListCtrlFx::GetTextColor1(){return m_TextColor1;}
COLORREF CListCtrlFx::GetTextColor2(){return m_TextColor2;}
COLORREF CListCtrlFx::GetTextSelected(){return m_TextSelected;}
COLORREF CListCtrlFx::GetBkColor1(){return m_BkColor1;}
COLORREF CListCtrlFx::GetBkColor2(){return m_BkColor2;}
COLORREF CListCtrlFx::GetBkSelected(){return m_BkSelected;}
COLORREF CListCtrlFx::GetLineColor1(){return m_LineColor1;}
COLORREF CListCtrlFx::GetLineColor2(){return m_LineColor2;}
void CListCtrlFx::SetFontEx(CString face, int size, double zoomRatio, double fontRatio, LONG fontWeight, BYTE fontRender)
{
LOGFONT logFont = { 0 };
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfHeight = (LONG)(-1 * size * zoomRatio * fontRatio);
logFont.lfQuality = fontRender;
logFont.lfWeight = fontWeight;
if (face.GetLength() < 32)
{
wsprintf(logFont.lfFaceName, _T("%s"), (LPCTSTR)face);
}
else
{
wsprintf(logFont.lfFaceName, _T(""));
}
m_Font.DeleteObject();
m_Font.CreateFontIndirect(&logFont);
SetFont(&m_Font);
m_Header.SetFontEx(face, size, zoomRatio, fontRatio, fontWeight, fontRender);
}
void CListCtrlFx::PreSubclassWindow()
{
CListCtrl::PreSubclassWindow();
CHeaderCtrlFx* pHeader = (CHeaderCtrlFx*)GetHeaderCtrl();
m_Header.SubclassWindow(pHeader->GetSafeHwnd());
}
void CListCtrlFx::EnableHeaderOwnerDraw(BOOL bOwnerDraw)
{
if (m_bHighContrast)
{
HDITEM hi = { 0 };
hi.mask = HDI_FORMAT;
for (int i = 0; i < m_Header.GetItemCount(); i++)
{
m_Header.GetItem(i, &hi);
hi.fmt &= ~HDF_OWNERDRAW;
m_Header.SetItem(i, &hi);
}
return;
}
else if (m_RenderMode & OwnerDrawGlass)
{
HDITEM hi = {0};
hi.mask = HDI_FORMAT;
if (bOwnerDraw)
{
for (int i = 0; i < m_Header.GetItemCount(); i++)
{
m_Header.GetItem(i, &hi);
hi.fmt |= HDF_OWNERDRAW;
m_Header.SetItem(i, &hi);
}
}
else
{
for (int i = 0; i < m_Header.GetItemCount(); i++)
{
m_Header.GetItem(i, &hi);
hi.fmt &= ~HDF_OWNERDRAW;
m_Header.SetItem(i, &hi);
}
}
}
}
@@ -0,0 +1,85 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "HeaderCtrlFx.h"
#include "ImageFx.h"
class CListCtrlFx : public CListCtrl
{
DECLARE_DYNAMIC(CListCtrlFx)
public:
CListCtrlFx();
virtual ~CListCtrlFx();
void SetTextColor1(COLORREF color);
void SetTextColor2(COLORREF color);
void SetTextSelected(COLORREF color);
void SetBkColor1(COLORREF color);
void SetBkColor2(COLORREF color);
void SetBkSelected(COLORREF color);
void SetLineColor1(COLORREF color);
void SetLineColor2(COLORREF color);
void SetGlassColor(COLORREF glassColor, BYTE glassAlpha);
COLORREF GetTextColor1();
COLORREF GetTextColor2();
COLORREF GetTextSelected();
COLORREF GetBkColor1();
COLORREF GetBkColor2();
COLORREF GetBkSelected();
COLORREF GetLineColor1();
COLORREF GetLineColor2();
BOOL InitControl(int x, int y, int width, int height, int maxWidth, int maxHeight, double zoomRatio, CDC* bkDC, int renderMode, BOOL bHighContrast, BOOL bDarkMode);
void SetFontEx(CString face, int size, double zoomRatio, double fontRatio, LONG fontWeight, BYTE fontRender);
void EnableHeaderOwnerDraw(BOOL bOwnerDraw);
protected:
virtual void PreSubclassWindow();
void SetupControlImage(CBitmap& bkBitmap, CBitmap& ctrlBitmap);
DECLARE_MESSAGE_MAP()
afx_msg void OnCustomdraw(NMHDR* pNMHDR, LRESULT* pResult);
int m_X;
int m_Y;
BOOL m_bNT6orLater;
CSize m_CtrlSize;
CRect m_Margin;
int m_RenderMode;
BOOL m_bHighContrast;
BOOL m_bDarkMode;
CHeaderCtrlFx m_Header;
COLORREF m_TextColor1;
COLORREF m_TextColor2;
COLORREF m_TextSelected;
COLORREF m_BkColor1;
COLORREF m_BkColor2;
COLORREF m_BkSelected;
COLORREF m_LineColor1;
COLORREF m_LineColor2;
CFont m_Font;
CImageList m_Image;
CDC* m_BkDC;
// Glass
COLORREF m_GlassColor;
BYTE m_GlassAlpha;
// Image
CBitmap m_BkBitmap;
CBitmap m_CtrlBitmap;
CImage m_CtrlImage;
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,85 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "DialogFx.h"
class CMainDialogFx : public CDialogFx
{
public:
CMainDialogFx(UINT dlgResouce, CWnd* pParent = NULL);
virtual ~CMainDialogFx();
// Zoom
DWORD GetZoomType();
void SetZoomType(DWORD zoomType);
// Getter
CString GetCurrentLangPath();
CString GetDefaultLangPath();
CString GetThemeDir();
CString GetCurrentTheme();
CString GetDefaultTheme();
CString GetParentTheme1();
CString GetParentTheme2();
CString GetIniPath();
void SaveImage();
protected:
void InitMenu();
void InitThemeLang();
void ChangeTheme(CString themeName);
void SetWindowTitle(CString message);
void UpdateThemeInfo();
COLORREF GetControlColor(CString name, BYTE defaultColor, CString theme);
COLORREF GetBackgroundColor(CString name, CString theme);
BYTE GetControlAlpha(CString name, BYTE defaultAlpha, CString theme);
BYTE GetCharacterPosition(CString theme);
CString GetParentTheme(int i, CString theme);
CString GetRandomTheme();
void SaveImageDlg(CImage* image);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
virtual BOOL OnInitDialog();
virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
virtual BOOL CheckThemeEdition(CString name);
virtual CString GetDefaultFont();
virtual void SaveWindowPosition();
virtual void RestoreWindowPosition();
DECLARE_MESSAGE_MAP()
afx_msg void OnWindowPosChanging(WINDOWPOS* lpwndpos);
afx_msg void OnGetMinMaxInfo(MINMAXINFO* lpMMI);
// Common
BOOL m_bStartup;
BOOL m_bWindowMinimizeOnce;
BOOL m_bResident;
BOOL m_bResidentMinimize;
// Theme
CString m_ThemeKeyName;
CString m_RecommendTheme;
CStringArray m_MenuArrayTheme;
// Language
CStringArray m_MenuArrayLang;
#ifdef OPTION_TASK_TRAY
// Task Tray
static UINT wmTaskbarCreated;
BOOL AddTaskTray(UINT id, UINT callback, HICON icon, CString tip);
BOOL RemoveTaskTray(UINT id);
BOOL ModifyTaskTray(UINT id, HICON icon, CString tip);
BOOL ModifyTaskTrayIcon(UINT id, HICON icon);
BOOL ModifyTaskTrayTip(UINT id, CString tip);
BOOL ShowBalloon(UINT id, DWORD infoFlag, CString infoTitle, CString info);
#endif
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,242 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
////------------------------------------------------
// OS Info
////------------------------------------------------
#if _MSC_VER > 1310
BOOL IsWindowsVersionOrGreaterFx(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor = 0);
BOOL IsWindowsBuildOrGreater(DWORD build);
BOOL IsX64();
BOOL IsIa64();
BOOL IsArm32();
BOOL IsArm64();
BOOL IsWow64();
BOOL IsIe556();
BOOL IsDotNet2();
BOOL IsDotNet4();
BOOL IsDotNet48();
BOOL IsNT5();
BOOL IsNT6orLater();
BOOL IsWin2k();
BOOL IsWinXpOrLater();
BOOL IsWinXpLuna();
BOOL IsWin8orLater();
BOOL IsWin81orLater();
BOOL IsDarkModeSupport();
BOOL HasSidebar();
#endif
#if _MSC_VER <= 1310
#ifdef UNICODE
BOOL IsCurrentUserLocalAdministrator(void);
BOOL IsUserAdmin(VOID);
#endif
#endif
BOOL IsNT3();
BOOL IsNT4();
BOOL IsWin9x();
BOOL IsWin95();
BOOL IsWin95First();
BOOL IsPC98();
BOOL IsNT51orlater();
BOOL IsRunningOnWine();
DWORD GetIeVersion();
// DWORD GetWin10Version();
void GetOsName(CString& osFullName, CString& osName, CString& osVersion, CString& osArchitecture);
void GetOsNameWmi(CString& osFullName);
////------------------------------------------------
// Define
////------------------------------------------------
#define PRODUCT_UNDEFINED 0x00000000
#define PRODUCT_ULTIMATE 0x00000001
#define PRODUCT_HOME_BASIC 0x00000002
#define PRODUCT_HOME_PREMIUM 0x00000003
#define PRODUCT_ENTERPRISE 0x00000004
#define PRODUCT_HOME_BASIC_N 0x00000005
#define PRODUCT_BUSINESS 0x00000006
#define PRODUCT_STANDARD_SERVER 0x00000007
#define PRODUCT_DATACENTER_SERVER 0x00000008
#define PRODUCT_SMALLBUSINESS_SERVER 0x00000009
#define PRODUCT_ENTERPRISE_SERVER 0x0000000A
#define PRODUCT_STARTER 0x0000000B
#define PRODUCT_DATACENTER_SERVER_CORE 0x0000000C
#define PRODUCT_STANDARD_SERVER_CORE 0x0000000D
#define PRODUCT_ENTERPRISE_SERVER_CORE 0x0000000E
#define PRODUCT_ENTERPRISE_SERVER_IA64 0x0000000F
#define PRODUCT_BUSINESS_N 0x00000010
#define PRODUCT_WEB_SERVER 0x00000011
#define PRODUCT_CLUSTER_SERVER 0x00000012
#define PRODUCT_HOME_SERVER 0x00000013
#define PRODUCT_STORAGE_EXPRESS_SERVER 0x00000014
#define PRODUCT_STORAGE_STANDARD_SERVER 0x00000015
#define PRODUCT_STORAGE_WORKGROUP_SERVER 0x00000016
#define PRODUCT_STORAGE_ENTERPRISE_SERVER 0x00000017
#define PRODUCT_SERVER_FOR_SMALLBUSINESS 0x00000018
#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM 0x00000019
#define PRODUCT_HOME_PREMIUM_N 0x0000001A
#define PRODUCT_ENTERPRISE_N 0x0000001B
#define PRODUCT_ULTIMATE_N 0x0000001C
#define PRODUCT_WEB_SERVER_CORE 0x0000001D
#define PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT 0x0000001E
#define PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY 0x0000001F
#define PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING 0x00000020
#define PRODUCT_SERVER_FOUNDATION 0x00000021
#define PRODUCT_HOME_PREMIUM_SERVER 0x00000022
#define PRODUCT_SERVER_FOR_SMALLBUSINESS_V 0x00000023
#define PRODUCT_STANDARD_SERVER_V 0x00000024
#define PRODUCT_DATACENTER_SERVER_V 0x00000025
#define PRODUCT_ENTERPRISE_SERVER_V 0x00000026
#define PRODUCT_DATACENTER_SERVER_CORE_V 0x00000027
#define PRODUCT_STANDARD_SERVER_CORE_V 0x00000028
#define PRODUCT_ENTERPRISE_SERVER_CORE_V 0x00000029
#define PRODUCT_HYPERV 0x0000002A
#define PRODUCT_STORAGE_EXPRESS_SERVER_CORE 0x0000002B
#define PRODUCT_STORAGE_STANDARD_SERVER_CORE 0x0000002C
#define PRODUCT_STORAGE_WORKGROUP_SERVER_CORE 0x0000002D
#define PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE 0x0000002E
#define PRODUCT_STARTER_N 0x0000002F
#define PRODUCT_PROFESSIONAL 0x00000030
#define PRODUCT_PROFESSIONAL_N 0x00000031
#define PRODUCT_SB_SOLUTION_SERVER 0x00000032
#define PRODUCT_SERVER_FOR_SB_SOLUTIONS 0x00000033
#define PRODUCT_STANDARD_SERVER_SOLUTIONS 0x00000034
#define PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE 0x00000035
#define PRODUCT_SB_SOLUTION_SERVER_EM 0x00000036
#define PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM 0x00000037
#define PRODUCT_SOLUTION_EMBEDDEDSERVER 0x00000038
#define PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE 0x00000039
#define PRODUCT_PROFESSIONAL_EMBEDDED 0x0000003A
#define PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT 0x0000003B
#define PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL 0x0000003C
#define PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC 0x0000003D
#define PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC 0x0000003E
#define PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE 0x0000003F
#define PRODUCT_CLUSTER_SERVER_V 0x00000040
#define PRODUCT_EMBEDDED 0x00000041
#define PRODUCT_STARTER_E 0x00000042
#define PRODUCT_HOME_BASIC_E 0x00000043
#define PRODUCT_HOME_PREMIUM_E 0x00000044
#define PRODUCT_PROFESSIONAL_E 0x00000045
#define PRODUCT_ENTERPRISE_E 0x00000046
#define PRODUCT_ULTIMATE_E 0x00000047
#define PRODUCT_ENTERPRISE_EVALUATION 0x00000048
#define PRODUCT_MULTIPOINT_STANDARD_SERVER 0x0000004C
#define PRODUCT_MULTIPOINT_PREMIUM_SERVER 0x0000004D
#define PRODUCT_STANDARD_EVALUATION_SERVER 0x0000004F
#define PRODUCT_DATACENTER_EVALUATION_SERVER 0x00000050
#define PRODUCT_ENTERPRISE_N_EVALUATION 0x00000054
#define PRODUCT_EMBEDDED_AUTOMOTIVE 0x00000055
#define PRODUCT_EMBEDDED_INDUSTRY_A 0x00000056
#define PRODUCT_THINPC 0x00000057
#define PRODUCT_EMBEDDED_A 0x00000058
#define PRODUCT_EMBEDDED_INDUSTRY 0x00000059
#define PRODUCT_EMBEDDED_E 0x0000005A
#define PRODUCT_EMBEDDED_INDUSTRY_E 0x0000005B
#define PRODUCT_EMBEDDED_INDUSTRY_A_E 0x0000005C
#define PRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER 0x0000005F
#define PRODUCT_STORAGE_STANDARD_EVALUATION_SERVER 0x00000060
#define PRODUCT_CORE_ARM 0x00000061
#define PRODUCT_CORE_N 0x00000062
#define PRODUCT_CORE_COUNTRYSPECIFIC 0x00000063
#define PRODUCT_CORE_SINGLELANGUAGE 0x00000064
#define PRODUCT_CORE 0x00000065
#define PRODUCT_PROFESSIONAL_WMC 0x00000067
#define PRODUCT_EMBEDDED_INDUSTRY_EVAL 0x00000069
#define PRODUCT_EMBEDDED_INDUSTRY_E_EVAL 0x0000006A
#define PRODUCT_EMBEDDED_EVAL 0x0000006B
#define PRODUCT_EMBEDDED_E_EVAL 0x0000006C
#define PRODUCT_NANO_SERVER 0x0000006D
#define PRODUCT_CLOUD_STORAGE_SERVER 0x0000006E
#define PRODUCT_CORE_CONNECTED 0x0000006F
#define PRODUCT_PROFESSIONAL_STUDENT 0x00000070
#define PRODUCT_CORE_CONNECTED_N 0x00000071
#define PRODUCT_PROFESSIONAL_STUDENT_N 0x00000072
#define PRODUCT_CORE_CONNECTED_SINGLELANGUAGE 0x00000073
#define PRODUCT_CORE_CONNECTED_COUNTRYSPECIFIC 0x00000074
#define PRODUCT_CONNECTED_CAR 0x00000075
#define PRODUCT_INDUSTRY_HANDHELD 0x00000076
#define PRODUCT_PPI_PRO 0x00000077
#define PRODUCT_ARM64_SERVER 0x00000078
#define PRODUCT_EDUCATION 0x00000079
#define PRODUCT_EDUCATION_N 0x0000007A
#define PRODUCT_IOTUAP 0x0000007B
#define PRODUCT_CLOUD_HOST_INFRASTRUCTURE_SERVER 0x0000007C
#define PRODUCT_ENTERPRISE_S 0x0000007D
#define PRODUCT_ENTERPRISE_S_N 0x0000007E
#define PRODUCT_PROFESSIONAL_S 0x0000007F
#define PRODUCT_PROFESSIONAL_S_N 0x00000080
#define PRODUCT_ENTERPRISE_S_EVALUATION 0x00000081
#define PRODUCT_ENTERPRISE_S_N_EVALUATION 0x00000082
#define PRODUCT_HOLOGRAPHIC 0x00000087
#define PRODUCT_HOLOGRAPHIC_BUSINESS 0x00000088
#define PRODUCT_PRO_SINGLE_LANGUAGE 0x0000008A
#define PRODUCT_PRO_CHINA 0x0000008B
#define PRODUCT_ENTERPRISE_SUBSCRIPTION 0x0000008C
#define PRODUCT_ENTERPRISE_SUBSCRIPTION_N 0x0000008D
#define PRODUCT_DATACENTER_NANO_SERVER 0x0000008F
#define PRODUCT_STANDARD_NANO_SERVER 0x00000090
#define PRODUCT_DATACENTER_A_SERVER_CORE 0x00000091
#define PRODUCT_STANDARD_A_SERVER_CORE 0x00000092
#define PRODUCT_DATACENTER_WS_SERVER_CORE 0x00000093
#define PRODUCT_STANDARD_WS_SERVER_CORE 0x00000094
#define PRODUCT_UTILITY_VM 0x00000095
#define PRODUCT_DATACENTER_EVALUATION_SERVER_CORE 0x0000009F
#define PRODUCT_STANDARD_EVALUATION_SERVER_CORE 0x000000A0
#define PRODUCT_PRO_WORKSTATION 0x000000A1
#define PRODUCT_PRO_WORKSTATION_N 0x000000A2
#define PRODUCT_PRO_FOR_EDUCATION 0x000000A4
#define PRODUCT_PRO_FOR_EDUCATION_N 0x000000A5
#define PRODUCT_AZURE_SERVER_CORE 0x000000A8
#define PRODUCT_AZURE_NANO_SERVER 0x000000A9
#define PRODUCT_ENTERPRISEG 0x000000AB
#define PRODUCT_ENTERPRISEGN 0x000000AC
#define PRODUCT_SERVERRDSH 0x000000AF
#define PRODUCT_CLOUD 0x000000B2
#define PRODUCT_CLOUDN 0x000000B3
#define PRODUCT_HUBOS 0x000000B4
#define PRODUCT_ONECOREUPDATEOS 0x000000B6
#define PRODUCT_CLOUDE 0x000000B7
#define PRODUCT_IOTOS 0x000000B9
#define PRODUCT_CLOUDEN 0x000000BA
#define PRODUCT_IOTEDGEOS 0x000000BB
#define PRODUCT_IOTENTERPRISE 0x000000BC
#define PRODUCT_LITE 0x000000BD
#define PRODUCT_IOTENTERPRISES 0x000000BF
#define PRODUCT_XBOX_SYSTEMOS 0x000000C0
#define PRODUCT_XBOX_GAMEOS 0x000000C2
#define PRODUCT_XBOX_ERAOS 0x000000C3
#define PRODUCT_XBOX_DURANGOHOSTOS 0x000000C4
#define PRODUCT_XBOX_SCARLETTHOSTOS 0x000000C5
#define PRODUCT_XBOX_KEYSTONE 0x000000C6
#define PRODUCT_AZURE_SERVER_CLOUDHOST 0x000000C7
#define PRODUCT_AZURE_SERVER_CLOUDMOS 0x000000C8
#define PRODUCT_CLOUDEDITIONN 0x000000CA
#define PRODUCT_CLOUDEDITION 0x000000CB
#define PRODUCT_AZURESTACKHCI_SERVER_CORE 0x00000196
#define PRODUCT_DATACENTER_SERVER_AZURE_EDITION 0x00000197
#define PRODUCT_DATACENTER_SERVER_CORE_AZURE_EDITION 0x00000198
#define PRODUCT_UNLICENSED 0xABCDABCD
// ChatGPT...
#define PRODUCT_ENTERPRISE_G 0x00000067
#define PRODUCT_PROFESSIONAL_WORKSTATION 0x000000B5
#define PRODUCT_PROFESSIONAL_WORKSTATION_N 0x000000B6
#define SM_TABLETPC 86
#define SM_MEDIACENTER 87
#define SM_STARTER 88
#define SM_SERVERR2 89
@@ -0,0 +1,93 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : The MIT License
/*---------------------------------------------------------------------------*/
#include "../stdafx.h"
#include "ScrollBarFx.h"
#include "OsInfoFx.h"
CScrollBarFx::CScrollBarFx()
{
m_X = 0;
m_Y = 0;
m_BkDC = NULL;
m_RenderMode = SystemDraw;
m_bHighContrast = FALSE;
m_bDarkMode = FALSE;
}
CScrollBarFx::~CScrollBarFx()
{
m_BkBrush.DeleteObject();
}
IMPLEMENT_DYNAMIC(CScrollBarFx, CScrollBar)
BEGIN_MESSAGE_MAP(CScrollBarFx, CScrollBar)
//{{AFX_MSG_MAP(CScrollBarFx)
ON_WM_HSCROLL_REFLECT()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CScrollBarFx::InitControl(int x, int y, int width, int height, double zoomRatio, CDC* bkDC, int renderMode, BOOL bHighContrast, BOOL bDarkMode, int min, int max, int pos)
{
m_X = (int)(x * zoomRatio);
m_Y = (int)(y * zoomRatio);
m_CtrlSize.cx = (int)(width * zoomRatio);
m_CtrlSize.cy = (int)(height * zoomRatio);
MoveWindow(m_X, m_Y, m_CtrlSize.cx, m_CtrlSize.cy);
m_BkDC = bkDC;
m_RenderMode = renderMode;
m_bHighContrast = bHighContrast;
m_bDarkMode = bDarkMode;
// BkBrush
m_BkBrush.DeleteObject();
if (bDarkMode)
{
m_BkBrush.CreateSolidBrush(RGB(32, 32, 32));
}
else
{
m_BkBrush.CreateSolidBrush(RGB(255, 255, 255));
}
SetScrollRange(min, max, TRUE);
SetScrollPos(pos);
Invalidate();
return TRUE;
}
void CScrollBarFx::HScroll(UINT nSBCode, UINT nPos)
{
int position = GetScrollPos();
switch (nSBCode)
{
case SB_LINELEFT:
position -= 1;
break;
case SB_LINERIGHT:
position += 1;
break;
case SB_PAGELEFT:
position -= 5;
break;
case SB_PAGERIGHT:
position += 5;
break;
case SB_LEFT:
break;
case SB_RIGHT:
break;
case SB_THUMBTRACK:
position = nPos;
break;
}
SetScrollPos(position);
}
@@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : The MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "CommonFx.h"
#include <atlimage.h>
#include <gdiplus.h>
#pragma comment(lib, "Gdiplus.lib")
using namespace Gdiplus;
class CScrollBarFx : public CScrollBar
{
DECLARE_DYNAMIC(CScrollBarFx)
public:
CScrollBarFx();
virtual ~CScrollBarFx();
BOOL InitControl(int x, int y, int width, int height, double zoomRatio, CDC* bkDC, int renderMode, BOOL bHighContrast, BOOL bDarkMode, int min, int max, int pos);
BOOL m_bHighContrast;
CBrush m_BkBrush;
protected:
DECLARE_MESSAGE_MAP()
afx_msg void HScroll(UINT nSBCode, UINT nPos);
int m_X;
int m_Y;
CSize m_CtrlSize;
CRect m_Margin;
int m_RenderMode;
BOOL m_bDarkMode;
CDC* m_BkDC;
};
@@ -0,0 +1,129 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "SliderCtrlFx.h"
#include "OsInfoFx.h"
IMPLEMENT_DYNAMIC(CSliderCtrlFx, CSliderCtrl)
CSliderCtrlFx::CSliderCtrlFx()
{
m_X = 0;
m_Y = 0;
m_BkDC = NULL;
m_RenderMode = SystemDraw;
m_bHighContrast = FALSE;
m_bDarkMode = FALSE;
m_bBkBitmapInit = FALSE;
}
CSliderCtrlFx::~CSliderCtrlFx()
{
m_BkBrush.DeleteObject();
}
BEGIN_MESSAGE_MAP(CSliderCtrlFx, CSliderCtrl)
ON_WM_KEYDOWN()
END_MESSAGE_MAP()
BOOL CSliderCtrlFx::InitControl(int x, int y, int width, int height, double zoomRatio, CDC* bkDC, int renderMode, BOOL bHighContrast, BOOL bDarkMode, int min, int max, int pos)
{
m_X = (int)(x * zoomRatio);
m_Y = (int)(y * zoomRatio);
m_CtrlSize.cx = (int)(width * zoomRatio);
m_CtrlSize.cy = (int)(height * zoomRatio);
MoveWindow(m_X, m_Y, m_CtrlSize.cx, m_CtrlSize.cy);
SendMessage(TBM_SETTHUMBLENGTH, m_CtrlSize.cy, 0);
m_BkDC = bkDC;
m_RenderMode = renderMode;
m_bHighContrast = bHighContrast;
m_bDarkMode = bDarkMode;
SetBkReload();
LoadCtrlBk(bkDC);
m_BkBrush.DeleteObject();
if (bDarkMode)
{
// m_BkBrush.CreateSolidBrush(RGB(32, 32, 32));
m_BkBrush.CreatePatternBrush(&m_BkBitmap);
}
else
{
// m_BkBrush.CreateSolidBrush(RGB(255, 255, 255));
m_BkBrush.CreatePatternBrush(&m_BkBitmap);
}
// Range, Pos
SetRange(min, max, TRUE);
SetPos(pos);
Invalidate();
return TRUE;
}
void CSliderCtrlFx::SetBkReload(void)
{
m_bBkBitmapInit = FALSE;
m_bBkLoad = FALSE;
}
void CSliderCtrlFx::LoadCtrlBk(CDC* drawDC)
{
if (m_bHighContrast) { SetBkReload(); return; }
if (m_BkBitmap.m_hObject != NULL)
{
BITMAP bitmapInfo;
m_BkBitmap.GetBitmap(&bitmapInfo);
if (bitmapInfo.bmBitsPixel != drawDC->GetDeviceCaps(BITSPIXEL))
{
SetBkReload();
}
}
if (&m_CtrlBitmap != NULL)
{
if (!m_bBkBitmapInit)
{
m_BkBitmap.DeleteObject();
m_BkBitmap.CreateCompatibleBitmap(drawDC, m_CtrlSize.cx, m_CtrlSize.cy);
m_bBkBitmapInit = TRUE;
}
if (!m_bBkLoad)
{
CBitmap* pOldBitmap;
CDC* pMemDC = new CDC;
pMemDC->CreateCompatibleDC(drawDC);
pOldBitmap = pMemDC->SelectObject(&m_BkBitmap);
pMemDC->BitBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, m_BkDC, m_X, m_Y, SRCCOPY);
pMemDC->SelectObject(pOldBitmap);
pMemDC->DeleteDC();
delete pMemDC;
m_bBkLoad = TRUE;
}
}
}
void CSliderCtrlFx::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == VK_UP)
{
PostMessage(WM_KEYDOWN, VK_RIGHT, nFlags);
return;
}
else if (nChar == VK_DOWN)
{
PostMessage(WM_KEYDOWN, VK_LEFT, nFlags);
return;
}
CSliderCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
}
@@ -0,0 +1,48 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "ImageFx.h"
class CSliderCtrlFx : public CSliderCtrl
{
DECLARE_DYNAMIC(CSliderCtrlFx)
public:
CSliderCtrlFx();
virtual ~CSliderCtrlFx();
BOOL InitControl(int x, int y, int width, int height, double zoomRatio, CDC* bkDC, int renderMode, BOOL bHighContrast, BOOL bDarkMode, int min, int max, int pos);
BOOL m_bHighContrast{};
CBrush m_BkBrush;
protected:
// Message Map
DECLARE_MESSAGE_MAP()
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
// Image
void SetBkReload(void);
void LoadCtrlBk(CDC* drawDC);
int m_X{};
int m_Y{};
CSize m_CtrlSize;
CRect m_Margin;
int m_RenderMode{};
BOOL m_bDarkMode{};
// Image
CDC* m_BkDC;
CBitmap m_BkBitmap;
BOOL m_bBkBitmapInit{};
BOOL m_bBkLoad{};
CBitmap m_CtrlBitmap;
CImage m_CtrlImage;
};
@@ -0,0 +1,917 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "StaticFx.h"
#if _MSC_VER <= 1310
#define ON_WM_MOUSEHOVER() \
{ 0x2A1 /*WM_MOUSEHOVER*/, 0, 0, 0, AfxSig_vwp, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, CPoint) > (OnMouseHover)) },
#define ON_WM_MOUSELEAVE() \
{ 0x2A3 /*WM_MOUSELEAVE*/, 0, 0, 0, AfxSig_vv, \
(AFX_PMSG)(AFX_PMSGW) \
(static_cast< void (AFX_MSG_CALL CWnd::*)(void) > (OnMouseLeave)) },
#endif
////------------------------------------------------
// CStaticFx
////------------------------------------------------
CStaticFx::CStaticFx()
{
// Control
m_X = 0;
m_Y = 0;
m_RenderMode = SystemDraw;
m_bHighContrast = FALSE;
m_bDarkMode = FALSE;
m_DrawFrame = FALSE;
m_bDrawFrameEx = FALSE;
m_FrameColor = RGB(128, 128, 128);
m_hPal = NULL;
// Glass
m_GlassColor = RGB(255, 255, 255);
m_GlassAlpha = 255;
// Meter
m_bMeter = FALSE;
m_MeterRatio = 0.0;
// Image
m_ImageCount = 0;
m_BkDC = NULL;
m_bBkBitmapInit = FALSE;
m_bBkLoad = FALSE;
// Font
m_TextAlign = SS_LEFT;
m_TextColor = RGB(0, 0, 0);
// Mouse
m_bHover = FALSE;
m_bFocas = FALSE;
m_bTrackingNow = FALSE;
m_bHandCursor = FALSE;
// Text Format
m_TextFormat = 0;
m_LabelFormat = DT_LEFT | DT_TOP | DT_SINGLELINE;
m_UnitFormat = DT_RIGHT | DT_BOTTOM | DT_SINGLELINE;
// Margin
m_Margin.top = 0;
m_Margin.left = 0;
m_Margin.bottom = 0;
m_Margin.right = 0;
}
CStaticFx::~CStaticFx()
{
}
IMPLEMENT_DYNAMIC(CStaticFx, CStatic)
BEGIN_MESSAGE_MAP(CStaticFx, CStatic)
//{{AFX_MSG_MAP(CStaticFx)
ON_WM_ERASEBKGND()
ON_WM_MOUSEMOVE()
ON_WM_MOUSEHOVER()
ON_WM_MOUSELEAVE()
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
ON_WM_SETCURSOR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//------------------------------------------------
// Control
//------------------------------------------------
BOOL CStaticFx::InitControl(int x, int y, int width, int height, double zoomRatio, HPALETTE hPal, CDC* bkDC,
LPCTSTR imagePath, int imageCount, DWORD textAlign, int renderMode, BOOL bHighContrast, BOOL bDarkMode, DWORD drawFrame)
{
m_X = (int)(x * zoomRatio);
m_Y = (int)(y * zoomRatio);
m_CtrlSize.cx = (int)(width * zoomRatio);
m_CtrlSize.cy = (int)(height * zoomRatio);
MoveWindow(m_X, m_Y, m_CtrlSize.cx, m_CtrlSize.cy);
m_hPal = hPal;
m_BkDC = bkDC;
m_ImagePath = imagePath;
m_ImageCount = imageCount;
m_RenderMode = renderMode;
if (SS_LEFT <= textAlign && textAlign <= SS_RIGHT)
{
m_TextAlign = textAlign;
}
if (m_ToolTip.m_hWnd != NULL)
{
if (m_ToolTip.GetToolCount() != 0)
{
m_ToolTip.DelTool(this, 1);
}
CRect rect;
GetClientRect(rect);
m_ToolTip.AddTool(this, m_ToolTipText, rect, 1);
}
m_bHighContrast = bHighContrast;
m_bDarkMode = bDarkMode;
m_DrawFrame = drawFrame;
if (m_bHighContrast)
{
ModifyStyle(SS_OWNERDRAW, m_TextAlign | SS_CENTERIMAGE);
return TRUE;
}
else if (renderMode & SystemDraw)
{
ModifyStyle(SS_OWNERDRAW, m_TextAlign | SS_CENTERIMAGE);
return TRUE;
}
else
{
SetBkReload();
ModifyStyle(m_TextAlign | SS_CENTERIMAGE, SS_OWNERDRAW);
}
if (renderMode & OwnerDrawImage)
{
if (!LoadBitmap(imagePath))
{
ModifyStyle(SS_OWNERDRAW, m_TextAlign);
}
}
else
{
m_ImageCount = 1;
m_CtrlImage.Destroy();
m_CtrlImage.Create(m_CtrlSize.cx, m_CtrlSize.cy * m_ImageCount, 32);
m_CtrlBitmap.Detach();
m_CtrlBitmap.Attach((HBITMAP)m_CtrlImage);
DWORD length = m_CtrlSize.cx * m_CtrlSize.cy * m_ImageCount * 4;
BYTE* bitmapBits = new BYTE[length];
m_CtrlBitmap.GetBitmapBits(length, bitmapBits);
BYTE r, g, b, a;
if (renderMode & OwnerDrawGlass)
{
r = (BYTE)GetRValue(m_GlassColor);
g = (BYTE)GetGValue(m_GlassColor);
b = (BYTE)GetBValue(m_GlassColor);
a = m_GlassAlpha;
}
else // OwnerDrawTransparent
{
r = 0;
g = 0;
b = 0;
a = 0;
}
for (int y = 0; y < (int)(m_CtrlSize.cy * m_ImageCount); y++)
{
for (int x = 0; x < m_CtrlSize.cx; x++)
{
DWORD p = (y * m_CtrlSize.cx + x) * 4;
#if _MSC_VER > 1310
#pragma warning( disable : 6386 )
#endif
bitmapBits[p + 0] = b;
bitmapBits[p + 1] = g;
bitmapBits[p + 2] = r;
bitmapBits[p + 3] = a;
#if _MSC_VER > 1310
#pragma warning( default : 6386 )
#endif
}
}
m_CtrlBitmap.SetBitmapBits(length, bitmapBits);
delete[] bitmapBits;
}
Invalidate();
return TRUE;
}
void CStaticFx::SetMargin(int top, int left, int bottom, int right, double zoomRatio)
{
m_Margin.top = (int)(top * zoomRatio);
m_Margin.left = (int)(left * zoomRatio);
m_Margin.bottom = (int)(bottom * zoomRatio);
m_Margin.right = (int)(right * zoomRatio);
}
CSize CStaticFx::GetSize(void)
{
return m_CtrlSize;
}
void CStaticFx::SetDrawFrame(BOOL drawFrame)
{
if (drawFrame && m_bHighContrast)
{
ModifyStyleEx(0, WS_EX_STATICEDGE, SWP_DRAWFRAME);
}
else
{
ModifyStyleEx(WS_EX_STATICEDGE, 0, SWP_DRAWFRAME);
}
m_DrawFrame = drawFrame;
}
void CStaticFx::SetDrawFrameEx(BOOL bDrawFrameEx, COLORREF frameColor)
{
m_bDrawFrameEx = bDrawFrameEx;
m_FrameColor = frameColor;
}
void CStaticFx::SetGlassColor(COLORREF glassColor, BYTE glassAlpha)
{
m_GlassColor = glassColor;
m_GlassAlpha = glassAlpha;
}
void CStaticFx::SetMeter(BOOL bMeter, double meterRatio)
{
m_bMeter = bMeter;
if (meterRatio > 1.0)
{
m_MeterRatio = 1.0;
}
else if (meterRatio > 0)
{
m_MeterRatio = meterRatio;
}
else
{
m_MeterRatio = 0.0;
}
Invalidate();
}
void CStaticFx::SetLabelUnit(CString label, CString unit)
{
m_Label = label;
m_Unit = unit;
}
void CStaticFx::SetLabelUnitFormat(UINT labelFormat, UINT unitFormat)
{
m_LabelFormat = labelFormat;
m_UnitFormat = unitFormat;
}
void CStaticFx::SetTextFormat(UINT format)
{
m_TextFormat = format;
}
//------------------------------------------------
// Draw Control
//------------------------------------------------
void CStaticFx::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC* drawDC = CDC::FromHandle(lpDrawItemStruct->hDC);
LoadCtrlBk(drawDC);
DrawControl(drawDC, lpDrawItemStruct, m_CtrlBitmap, m_BkBitmap, ControlImageNormal);
}
void CStaticFx::DrawControl(CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, CBitmap& ctrlBitmap, CBitmap& bkBitmap, int no)
{
CDC* pMemDC = new CDC;
CBitmap* pOldMemBitmap;
if(m_hPal && drawDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( drawDC->GetSafeHdc(), m_hPal, FALSE );
drawDC->RealizePalette();
drawDC->SetStretchBltMode(HALFTONE);
}
pMemDC->CreateCompatibleDC(drawDC);
if(m_hPal && pMemDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( pMemDC->GetSafeHdc(), m_hPal, FALSE );
pMemDC->RealizePalette();
pMemDC->SetStretchBltMode(HALFTONE);
}
pOldMemBitmap = pMemDC->SelectObject(&ctrlBitmap);
CDC* pBkDC = new CDC;
CBitmap* pOldBkBitmap;
pBkDC->CreateCompatibleDC(drawDC);
if(m_hPal && pBkDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( pBkDC->GetSafeHdc(), m_hPal, FALSE );
pBkDC->RealizePalette();
pBkDC->SetStretchBltMode(HALFTONE);
}
pOldBkBitmap = pBkDC->SelectObject(&bkBitmap);
CBitmap DrawBmp;
DrawBmp.CreateCompatibleBitmap(drawDC, m_CtrlSize.cx, m_CtrlSize.cy);
CDC* pDrawBmpDC = new CDC;
CBitmap* pOldDrawBitmap;
pDrawBmpDC->CreateCompatibleDC(drawDC);
if(m_hPal && pDrawBmpDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)
{
SelectPalette( pDrawBmpDC->GetSafeHdc(), m_hPal, FALSE );
pDrawBmpDC->RealizePalette();
pDrawBmpDC->SetStretchBltMode(HALFTONE);
}
pOldDrawBitmap = pDrawBmpDC->SelectObject(&DrawBmp);
int color = drawDC->GetDeviceCaps(BITSPIXEL) * drawDC->GetDeviceCaps(PLANES);
if (!m_CtrlImage.IsNull())
{
if (m_CtrlImage.GetBPP() == 32)
{
CBitmap* bk32Bitmap;
CImage bk32Image;
if (color == 32)
{
bk32Bitmap = &bkBitmap;
}
else
{
bk32Image.Create(m_CtrlSize.cx, m_CtrlSize.cy, 32);
::StretchBlt(bk32Image.GetDC(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, *pBkDC, 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
bk32Bitmap = CBitmap::FromHandle((HBITMAP)bk32Image);
}
BITMAP CtlBmpInfo, DstBmpInfo;
bk32Bitmap->GetBitmap(&DstBmpInfo);
DWORD DstLineBytes = DstBmpInfo.bmWidthBytes;
DWORD DstMemSize = DstLineBytes * DstBmpInfo.bmHeight;
ctrlBitmap.GetBitmap(&CtlBmpInfo);
DWORD CtlLineBytes = CtlBmpInfo.bmWidthBytes;
DWORD CtlMemSize = CtlLineBytes * CtlBmpInfo.bmHeight;
if ((DstBmpInfo.bmWidthBytes != CtlBmpInfo.bmWidthBytes)
|| (DstBmpInfo.bmHeight != CtlBmpInfo.bmHeight / m_ImageCount))
{
// Error Check //
}
else
{
BYTE* DstBuffer = new BYTE[DstMemSize];
bk32Bitmap->GetBitmapBits(DstMemSize, DstBuffer);
BYTE* CtlBuffer = new BYTE[CtlMemSize];
ctrlBitmap.GetBitmapBits(CtlMemSize, CtlBuffer);
if (m_bMeter)
{
int meter = (int)(m_CtrlSize.cx * m_MeterRatio);
int baseY;
baseY = m_CtrlSize.cy;
for (LONG py = 0; py < DstBmpInfo.bmHeight; py++)
{
int dn = py * DstLineBytes;
int cn = (baseY + py) * CtlLineBytes;
for (LONG px = 0; px < meter; px++)
{
BYTE a = CtlBuffer[cn + 3];
BYTE na = 255 - a;
DstBuffer[dn + 0] = (BYTE)((CtlBuffer[cn + 0] * a + DstBuffer[dn + 0] * na) / 255);
DstBuffer[dn + 1] = (BYTE)((CtlBuffer[cn + 1] * a + DstBuffer[dn + 1] * na) / 255);
DstBuffer[dn + 2] = (BYTE)((CtlBuffer[cn + 2] * a + DstBuffer[dn + 2] * na) / 255);
DstBuffer[dn + 3] = 255;
dn += (DstBmpInfo.bmBitsPixel / 8);
cn += (CtlBmpInfo.bmBitsPixel / 8);
}
cn -= baseY * CtlLineBytes;
for (LONG px = meter; px < DstBmpInfo.bmWidth; px++)
{
BYTE a = CtlBuffer[cn + 3];
BYTE na = 255 - a;
DstBuffer[dn + 0] = (BYTE)((CtlBuffer[cn + 0] * a + DstBuffer[dn + 0] * na) / 255);
DstBuffer[dn + 1] = (BYTE)((CtlBuffer[cn + 1] * a + DstBuffer[dn + 1] * na) / 255);
DstBuffer[dn + 2] = (BYTE)((CtlBuffer[cn + 2] * a + DstBuffer[dn + 2] * na) / 255);
DstBuffer[dn + 3] = 255;
dn += (DstBmpInfo.bmBitsPixel / 8);
cn += (CtlBmpInfo.bmBitsPixel / 8);
}
}
}
else
{
int baseY = m_CtrlSize.cy * no;
for (LONG py = 0; py < DstBmpInfo.bmHeight; py++)
{
int dn = py * DstLineBytes;
int cn = (baseY + py) * CtlLineBytes;
for (LONG px = 0; px < DstBmpInfo.bmWidth; px++)
{
#if _MSC_VER > 1310
#pragma warning( disable : 6385 )
#pragma warning( disable : 6386 )
#endif
BYTE a = CtlBuffer[cn + 3];
BYTE na = 255 - a;
DstBuffer[dn + 0] = (BYTE)((CtlBuffer[cn + 0] * a + DstBuffer[dn + 0] * na) / 255);
DstBuffer[dn + 1] = (BYTE)((CtlBuffer[cn + 1] * a + DstBuffer[dn + 1] * na) / 255);
DstBuffer[dn + 2] = (BYTE)((CtlBuffer[cn + 2] * a + DstBuffer[dn + 2] * na) / 255);
DstBuffer[dn + 3] = 255;
dn += (DstBmpInfo.bmBitsPixel / 8);
cn += (CtlBmpInfo.bmBitsPixel / 8);
#if _MSC_VER > 1310
#pragma warning( default : 6386 )
#pragma warning( default : 6385 )
#endif
}
}
}
if (color == 32)
{
DrawBmp.SetBitmapBits(DstMemSize, DstBuffer);
}
else
{
bk32Bitmap->SetBitmapBits(DstMemSize, DstBuffer);
::StretchBlt(pDrawBmpDC->GetSafeHdc(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, bk32Image.GetDC(), 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
bk32Image.ReleaseDC();
}
DrawString(pDrawBmpDC, lpDrawItemStruct);
drawDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
delete[] DstBuffer;
delete[] CtlBuffer;
}
}
else
{
if (m_bMeter)
{
int meter = (int)(m_CtrlSize.cx * (m_MeterRatio));
pDrawBmpDC->StretchBlt(meter, 0, m_CtrlSize.cx - meter, m_CtrlSize.cy, pMemDC, meter, m_CtrlSize.cy * 0, m_CtrlSize.cx - meter, m_CtrlSize.cy, SRCCOPY);
pDrawBmpDC->StretchBlt(0, 0, meter, m_CtrlSize.cy, pMemDC, 0, m_CtrlSize.cy * 1, meter, m_CtrlSize.cy, SRCCOPY);
DrawString(pDrawBmpDC, lpDrawItemStruct);
drawDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
}
else
{
pDrawBmpDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pMemDC, 0, m_CtrlSize.cy* no, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
DrawString(pDrawBmpDC, lpDrawItemStruct);
drawDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
}
}
}
else
{
pDrawBmpDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pBkDC, 0, m_CtrlSize.cy* no, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
DrawString(pDrawBmpDC, lpDrawItemStruct);
drawDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, pDrawBmpDC, 0, 0, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
}
if (m_DrawFrame == Border::UNDERLINE)
{
HGDIOBJ oldPen;
POINT point;
CPen pen1;
COLORREF frameColor;
if (m_bDarkMode){frameColor = RGB(0x29, 0x2B, 0x2F);} // Windows 11 color
else{ frameColor = RGB(0xCC, 0xCC, 0xCC);}
pen1.CreatePen(PS_SOLID, 1, frameColor);
oldPen = SelectObject(drawDC->m_hDC, pen1);
MoveToEx(drawDC->m_hDC, 0, m_CtrlSize.cy - 1, &point);
LineTo(drawDC->m_hDC, m_CtrlSize.cx - 1, m_CtrlSize.cy - 1);
LineTo(drawDC->m_hDC, 0, m_CtrlSize.cy - 1);
SelectObject(drawDC->m_hDC, oldPen);
pen1.DeleteObject();
}
else if (m_DrawFrame)
{
HGDIOBJ oldPen;
POINT point;
CPen pen1; pen1.CreatePen(PS_SOLID, 1, RGB(0xF8, 0xF8, 0xF8));
CPen pen2; pen2.CreatePen(PS_SOLID, 1, RGB(0x98, 0x98, 0x98));
oldPen = SelectObject(drawDC->m_hDC, pen1);
MoveToEx(drawDC->m_hDC, 0, m_CtrlSize.cy - 1, &point);
LineTo(drawDC->m_hDC, m_CtrlSize.cx - 1, m_CtrlSize.cy - 1);
LineTo(drawDC->m_hDC, m_CtrlSize.cx - 1, 0);
LineTo(drawDC->m_hDC, m_CtrlSize.cx - 1, m_CtrlSize.cy - 1);
SelectObject(drawDC->m_hDC, pen2);
MoveToEx(drawDC->m_hDC, 0, m_CtrlSize.cy - 2, &point);
LineTo(drawDC->m_hDC, 0, 0);
LineTo(drawDC->m_hDC, m_CtrlSize.cx - 1, 0);
SelectObject(drawDC->m_hDC, oldPen);
pen1.DeleteObject();
pen2.DeleteObject();
}
pDrawBmpDC->SelectObject(&pOldDrawBitmap);
pDrawBmpDC->DeleteDC();
delete pDrawBmpDC;
pMemDC->SelectObject(&pOldMemBitmap);
pMemDC->DeleteDC();
delete pMemDC;
pBkDC->SelectObject(&pOldBkBitmap);
pBkDC->DeleteDC();
delete pBkDC;
if (m_bDrawFrameEx)
{
CBrush brush;
brush.CreateSolidBrush(m_FrameColor);
drawDC->FrameRect(&(lpDrawItemStruct->rcItem), &brush);
brush.DeleteObject();
}
}
void CStaticFx::DrawString(CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CString title;
GetWindowText(title);
if (title.IsEmpty())
{
return;
}
drawDC->SetBkMode(TRANSPARENT);
CRect rect = (CRect)(lpDrawItemStruct->rcItem);
CRect rectControl = (CRect)(lpDrawItemStruct->rcItem);
rect.top += m_Margin.top;
rect.left += m_Margin.left;
rect.bottom -= m_Margin.bottom;
rect.right -= m_Margin.right;
CRect rectI;
CSize extent;
HGDIOBJ oldFont = drawDC->SelectObject(m_Font);
if ((m_RenderMode & OwnerDrawTransparent) && m_bDarkMode)
{
SetTextColor(drawDC->m_hDC, RGB(255, 255, 255));
}
else
{
SetTextColor(drawDC->m_hDC, m_TextColor);
}
extent = drawDC->GetTextExtent(title);
if (m_bMeter && rect.Width() < extent.cx)
{
title.Replace(_T(","), _T("."));
int score = _tstoi((LPCTSTR)title);
title.Format(_T("%d"), score);
extent = drawDC->GetTextExtent(title);
}
if (m_TextFormat != 0)
{
drawDC->DrawText(title, title.GetLength(), rect, m_TextFormat);
drawDC->SelectObject(oldFont);
oldFont = drawDC->SelectObject(m_FontToolTip);
drawDC->DrawText(m_Label, m_Label.GetLength(), rect, m_LabelFormat);
drawDC->DrawText(m_Unit, m_Unit.GetLength(), rect, m_UnitFormat);
}
else if (!m_Label.IsEmpty())
{
drawDC->DrawText(title, title.GetLength(), rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
drawDC->SelectObject(oldFont);
oldFont = drawDC->SelectObject(m_FontToolTip);
drawDC->DrawText(m_Label, m_Label.GetLength(), rect, m_LabelFormat);
drawDC->DrawText(m_Unit, m_Unit.GetLength(), rect, m_UnitFormat);
}
else if (m_TextAlign == SS_LEFT)
{
drawDC->DrawText(title, title.GetLength(), rect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
}
else if (m_TextAlign == SS_RIGHT)
{
drawDC->DrawText(title, title.GetLength(), rect, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
}
else
{
drawDC->DrawText(title, title.GetLength(), rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
drawDC->SelectObject(oldFont);
}
//------------------------------------------------
// Image
//------------------------------------------------
BOOL CStaticFx::LoadBitmap(LPCTSTR fileName)
{
if (m_bHighContrast) { return FALSE; }
if (fileName == NULL) { return FALSE; }
m_CtrlImage.Destroy();
m_CtrlImage.Load(fileName);
if (m_CtrlImage.IsNull()) { return FALSE; }
return LoadBitmap((HBITMAP)m_CtrlImage);
}
BOOL CStaticFx::LoadBitmap(HBITMAP hBitmap)
{
if (m_bHighContrast) { return FALSE; }
m_CtrlBitmap.Detach();
m_CtrlBitmap.Attach(hBitmap);
return SetBitmap(m_CtrlBitmap);
}
void CStaticFx::SetBkReload(void)
{
m_bBkBitmapInit = FALSE;
m_bBkLoad = FALSE;
}
BOOL CStaticFx::SetBitmap(CBitmap& bitmap)
{
if (m_bHighContrast) { return FALSE; }
BITMAP bitmapInfo;
bitmap.GetBitmap(&bitmapInfo);
if (m_CtrlSize.cx != bitmapInfo.bmWidth
|| m_CtrlSize.cy != bitmapInfo.bmHeight / m_ImageCount)
{
ModifyStyle(SS_OWNERDRAW, 0);
return FALSE;
}
else
{
ModifyStyle(0, SS_OWNERDRAW);
return TRUE;
}
}
void CStaticFx::LoadCtrlBk(CDC* drawDC)
{
if (m_bHighContrast) { SetBkReload(); return; }
if (m_BkBitmap.m_hObject != NULL)
{
BITMAP bitmapInfo;
m_BkBitmap.GetBitmap(&bitmapInfo);
if (bitmapInfo.bmBitsPixel != drawDC->GetDeviceCaps(BITSPIXEL))
{
SetBkReload();
}
}
if (&m_CtrlBitmap != NULL)
{
if (!m_bBkBitmapInit)
{
m_BkBitmap.DeleteObject();
m_BkBitmap.CreateCompatibleBitmap(drawDC, m_CtrlSize.cx, m_CtrlSize.cy);
m_bBkBitmapInit = TRUE;
}
if (!m_bBkLoad)
{
CBitmap* pOldBitmap;
CDC* pMemDC = new CDC;
pMemDC->CreateCompatibleDC(drawDC);
pOldBitmap = pMemDC->SelectObject(&m_BkBitmap);
pMemDC->StretchBlt(0, 0, m_CtrlSize.cx, m_CtrlSize.cy, m_BkDC, m_X, m_Y, m_CtrlSize.cx, m_CtrlSize.cy, SRCCOPY);
pMemDC->SelectObject(pOldBitmap);
pMemDC->DeleteDC();
delete pMemDC;
m_bBkLoad = TRUE;
}
}
}
//------------------------------------------------
// Font
//------------------------------------------------
void CStaticFx::SetFontEx(CString face, int size, int sizeToolTip, double zoomRatio, double fontRatio,
COLORREF textColor, LONG fontWeight, BYTE fontRender)
{
LOGFONT logFont = { 0 };
logFont.lfCharSet = DEFAULT_CHARSET;
logFont.lfHeight = (LONG)(-1 * size * zoomRatio * fontRatio);
logFont.lfQuality = fontRender;
logFont.lfWeight = fontWeight;
if (face.GetLength() < 32)
{
wsprintf(logFont.lfFaceName, _T("%s"), (LPCTSTR)face);
}
else
{
wsprintf(logFont.lfFaceName, _T(""));
}
m_Font.DeleteObject();
m_Font.CreateFontIndirect(&logFont);
SetFont(&m_Font);
logFont.lfHeight = (LONG)(-1 * sizeToolTip * zoomRatio * fontRatio);
m_FontToolTip.DeleteObject();
m_FontToolTip.CreateFontIndirect(&logFont);
m_TextColor = textColor;
if (m_ToolTip.m_hWnd != NULL)
{
m_ToolTip.SetFont(&m_FontToolTip);
}
}
//------------------------------------------------
// Mouse
//------------------------------------------------
void CStaticFx::SetHandCursor(BOOL bHandCuror)
{
m_bHandCursor = bHandCuror;
}
void CStaticFx::OnMouseMove(UINT nFlags, CPoint point)
{
#if _MSC_VER <= 1310
typedef BOOL(WINAPI* Func_TrackMouseEvent)(LPTRACKMOUSEEVENT);
static Func_TrackMouseEvent p_TrackMouseEvent = NULL;
static BOOL bInit_TrackMouseEvent = FALSE;
if (bInit_TrackMouseEvent && p_TrackMouseEvent == NULL)
{
return; // TrackMouseEvent is not available
}
else
{
HMODULE hModule = GetModuleHandle(_T("user32.dll"));
if (hModule)
{
p_TrackMouseEvent = (Func_TrackMouseEvent)GetProcAddress(hModule, "TrackMouseEvent");
}
}
if (p_TrackMouseEvent != NULL)
{
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bTrackingNow = p_TrackMouseEvent(&tme);
}
bInit_TrackMouseEvent = TRUE;
#else
if (!m_bTrackingNow)
{
TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
tme.hwndTrack = m_hWnd;
tme.dwFlags = TME_LEAVE | TME_HOVER;
tme.dwHoverTime = 1;
m_bTrackingNow = _TrackMouseEvent(&tme);
}
#endif
CStatic::OnMouseMove(nFlags, point);
}
void CStaticFx::OnMouseHover(UINT nFlags, CPoint point)
{
#if _MSC_VER > 1310
CStatic::OnMouseHover(nFlags, point);
#endif
m_bHover = TRUE;
Invalidate();
}
void CStaticFx::OnMouseLeave()
{
#if _MSC_VER > 1310
CStatic::OnMouseLeave();
#endif
m_bTrackingNow = FALSE;
m_bHover = FALSE;
Invalidate();
}
void CStaticFx::OnSetfocus()
{
m_bFocas = TRUE;
Invalidate();
}
void CStaticFx::OnKillfocus()
{
m_bFocas = FALSE;
Invalidate();
}
BOOL CStaticFx::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
HCURSOR hCursor = NULL;
if (m_bHandCursor)
{
hCursor = AfxGetApp()->LoadStandardCursor(IDC_HAND);
if (hCursor)
{
::SetCursor(hCursor);
}
}
else
{
hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
if (hCursor)
{
::SetCursor(hCursor);
}
}
return TRUE;
}
//------------------------------------------------
// ToolTip
//------------------------------------------------
void CStaticFx::SetToolTipText(LPCTSTR text)
{
if (text == NULL) { return; }
InitToolTip();
m_ToolTipText = text;
if (m_ToolTip.GetToolCount() == 0)
{
CRect rect;
GetClientRect(rect);
m_ToolTip.AddTool(this, m_ToolTipText, rect, 1);
}
else
{
m_ToolTip.UpdateTipText(m_ToolTipText, this, 1);
}
SetToolTipActivate(TRUE);
}
void CStaticFx::SetToolTipActivate(BOOL bActivate)
{
if (m_ToolTip.GetToolCount() == 0) { return; }
m_ToolTip.Activate(bActivate);
}
void CStaticFx::SetToolTipWindowText(LPCTSTR pText)
{
SetToolTipText(pText);
SetWindowText(pText);
}
CString CStaticFx::GetToolTipText()
{
return m_ToolTipText;
}
void CStaticFx::InitToolTip()
{
if (m_ToolTip.m_hWnd == NULL)
{
m_ToolTip.Create(this, TTS_ALWAYSTIP | TTS_BALLOON | TTS_NOANIMATE | TTS_NOFADE);
m_ToolTip.Activate(FALSE);
m_ToolTip.SetFont(&m_FontToolTip);
m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, 1024);
m_ToolTip.SetDelayTime(TTDT_AUTOPOP, 8000);
m_ToolTip.SetDelayTime(TTDT_INITIAL, 500);
m_ToolTip.SetDelayTime(TTDT_RESHOW, 100);
}
}
BOOL CStaticFx::PreTranslateMessage(MSG* pMsg)
{
InitToolTip();
m_ToolTip.RelayEvent(pMsg);
return CStatic::PreTranslateMessage(pMsg);
}
BOOL CStaticFx::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
@@ -0,0 +1,135 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "ImageFx.h"
class CStaticFx : public CStatic
{
DECLARE_DYNAMIC(CStaticFx);
enum Border
{
NO_BORDER = 0, // FALSE
SYSTEM_BORDER = 1, // TRUE
UNDERLINE = 2,
};
public:
// Constructors
CStaticFx();
virtual ~CStaticFx();
// Control
BOOL InitControl(int x, int y, int width, int height, double zoomRatio, HPALETTE hPal, CDC* bkDC,
LPCTSTR imagePath, int imageCount, DWORD textAlign, int renderMode, BOOL bHighContrast, BOOL bDarkMode, DWORD drawFrame);
void SetMargin(int top, int left, int bottom, int right, double zoomRatio);
CSize GetSize(void);
void SetDrawFrame(BOOL bDrawFrame);
void SetDrawFrameEx(BOOL bDrawFrame, COLORREF frameColor = RGB(128, 128, 128));
void SetGlassColor(COLORREF glassColor, BYTE glassAlpha);
void SetMeter(BOOL bMeter, double meterRatio);
void SetLabelUnit(CString label, CString unit);
void SetLabelUnitFormat(UINT labelFormat, UINT unitFormat);
void SetTextFormat(UINT format);
// Font
void SetFontEx(CString face, int size, int sizeToolTip, double zoomRatio, double fontRatio = 1.0,
COLORREF textColor = RGB(0, 0, 0), LONG fontWeight = FW_NORMAL, BYTE fontRender = CLEARTYPE_NATURAL_QUALITY);
// ToolTip
void SetToolTipText(LPCTSTR pText);
void SetToolTipActivate(BOOL bActivate = TRUE);
void SetToolTipWindowText(LPCTSTR pText);
CString GetToolTipText();
// Mouse
void SetHandCursor(BOOL bHandCuror = TRUE);
protected:
// Draw Control
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
virtual void DrawControl(CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct, CBitmap& ctrlBitmap, CBitmap& bkBitmap, int no);
virtual void DrawString(CDC* drawDC, LPDRAWITEMSTRUCT lpDrawItemStruct);
// Image
BOOL LoadBitmap(LPCTSTR fileName);
BOOL LoadBitmap(HBITMAP hBitmap);
void SetBkReload(void);
BOOL SetBitmap(CBitmap& bitmap);
void LoadCtrlBk(CDC* drawDC);
// ToolTip
void InitToolTip();
virtual BOOL PreTranslateMessage(MSG* pMsg);
// Message Map
DECLARE_MESSAGE_MAP()
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg void OnMouseHover(UINT nFlags, CPoint point);
afx_msg void OnMouseLeave();
afx_msg void OnKillfocus();
afx_msg void OnSetfocus();
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
protected:
// Control
int m_X;
int m_Y;
CSize m_CtrlSize;
CRect m_Margin;
int m_RenderMode;
BOOL m_bHighContrast;
BOOL m_bDarkMode;
DWORD m_DrawFrame;
BOOL m_bDrawFrameEx;
COLORREF m_FrameColor;
HPALETTE m_hPal;
CString m_Label;
CString m_Unit;
UINT m_TextFormat;
UINT m_LabelFormat;
UINT m_UnitFormat;
// Glass
COLORREF m_GlassColor;
BYTE m_GlassAlpha;
// Meter
BOOL m_bMeter;
double m_MeterRatio;
// Image
CString m_ImagePath;
int m_ImageCount;
CDC* m_BkDC;
CBitmap m_BkBitmap;
BOOL m_bBkBitmapInit;
BOOL m_bBkLoad;
CBitmap m_CtrlBitmap;
CImage m_CtrlImage;
// Font
DWORD m_TextAlign;
CFont m_Font;
CFont m_FontToolTip;
COLORREF m_TextColor;
// ToolTip
CToolTipCtrl m_ToolTip;
CString m_ToolTipText;
// Mouse
BOOL m_bHover;
BOOL m_bFocas;
BOOL m_bTrackingNow;
BOOL m_bHandCursor;
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,30 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
//------------------------------------------------
// System Info
//------------------------------------------------
void GetCpuInfo(CString& cpuInfo, CString& cpuName, int* clock, int* cores, int* threads);
void GetGpuInfo(CString& gpuInfo);
void GetBaseBoardInfo(CString& baseBoardInfo);
void GetComputerSystemInfo(CString& computerSystemInfo);
void GetScreenInfo(CString& screenInfo, int* width, int* height, int* color, CString& smoothing);
void GetMemoryInfo(CString& screenInfo, int* size = NULL);
#if defined(_M_IX86) || defined(_M_X64)
void GetCpuid(unsigned int param, unsigned int* _eax, unsigned int* _ebx, unsigned int* _ecx, unsigned int* _edx);
void GetHypervisorVendorString(char* vendorString);
#endif
#if _MSC_VER <= 1310
/// https://www.betaarchive.com/wiki/index.php/Microsoft_KB_Archive/124207
BOOL IsCoProcessorPresent();
BOOL IsFMTOWNS();
#endif
@@ -0,0 +1,205 @@
/*---------------------------------------------------------------------------*/
// Author : adzm
// Web : https://github.com/adzm/win32-custom-menubar-aero-theme
// License : MIT License
// https://github.com/adzm/win32-custom-menubar-aero-theme/blob/main/LICENSE
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include <Uxtheme.h>
#include <vsstyle.h>
#include "UAHMenuBar.h"
#pragma comment(lib, "uxtheme.lib")
static HTHEME g_menuTheme = nullptr;
extern bool g_darkModeEnabled;
// ugly colors for illustration purposes
static HBRUSH g_brBarBackground = CreateSolidBrush(RGB(0x2C, 0x2C, 0x2C));
void UAHDrawMenuNCBottomLine(HWND hWnd)
{
MENUBARINFO mbi = { sizeof(mbi) };
if (!GetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi))
{
return;
}
RECT rcClient = { 0 };
GetClientRect(hWnd, &rcClient);
MapWindowPoints(hWnd, nullptr, (POINT*)&rcClient, 2);
RECT rcWindow = { 0 };
GetWindowRect(hWnd, &rcWindow);
OffsetRect(&rcClient, -rcWindow.left, -rcWindow.top);
// the rcBar is offset by the window rect
RECT rcAnnoyingLine = rcClient;
rcAnnoyingLine.bottom = rcAnnoyingLine.top;
rcAnnoyingLine.top--;
HDC hdc = GetWindowDC(hWnd);
FillRect(hdc, &rcAnnoyingLine, g_brBarBackground);
ReleaseDC(hWnd, hdc);
}
// processes messages related to UAH / custom menubar drawing.
// return true if handled, false to continue with normal processing in your wndproc
bool UAHWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT* lr)
{
if (! g_darkModeEnabled)
{
return false;
}
switch (message)
{
case WM_UAHDRAWMENU:
{
UAHMENU* pUDM = (UAHMENU*)lParam;
RECT rc = { 0 };
// get the menubar rect
{
MENUBARINFO mbi = { sizeof(mbi) };
GetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi);
RECT rcWindow;
GetWindowRect(hWnd, &rcWindow);
// the rcBar is offset by the window rect
rc = mbi.rcBar;
OffsetRect(&rc, -rcWindow.left, -rcWindow.top);
}
FillRect(pUDM->hdc, &rc, g_brBarBackground);
return true;
}
case WM_UAHDRAWMENUITEM:
{
typedef HRESULT(WINAPI* FuncDrawThemeTextEx)(HTHEME hTheme, HDC hdc,
int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags,
LPRECT pRect, const DTTOPTS* pOptions);
static bool bInitialized = false;
static FuncDrawThemeTextEx pDrawThemeTextEx = NULL;
if (bInitialized == false)
{
HMODULE hModule = GetModuleHandle(_T("UxTheme.dll"));
if (hModule)
{
pDrawThemeTextEx = (FuncDrawThemeTextEx)GetProcAddress(hModule, "DrawThemeTextEx");
}
bInitialized = true;
}
if (pDrawThemeTextEx == NULL)
{
return false;
}
UAHDRAWMENUITEM* pUDMI = (UAHDRAWMENUITEM*)lParam;
// ugly colors for illustration purposes
static HBRUSH g_brItemBackground = CreateSolidBrush(RGB(0x2C, 0x2C, 0x2C));
static HBRUSH g_brItemBackgroundHot = CreateSolidBrush(RGB(0x35, 0x35, 0x35));
static HBRUSH g_brItemBackgroundSelected = CreateSolidBrush(RGB(0x35, 0x35, 0x35));
HBRUSH* pbrBackground = &g_brItemBackground;
// get the menu item string
wchar_t menuString[256] = { 0 };
MENUITEMINFO mii = { sizeof(mii), MIIM_STRING };
{
mii.dwTypeData = menuString;
mii.cch = (sizeof(menuString) / 2) - 1;
GetMenuItemInfo(pUDMI->um.hmenu, pUDMI->umi.iPosition, TRUE, &mii);
}
// get the item state for drawing
DWORD dwFlags = DT_CENTER | DT_SINGLELINE | DT_VCENTER;
int iTextStateID = 0;
int iBackgroundStateID = 0;
{
if ((pUDMI->dis.itemState & ODS_INACTIVE) | (pUDMI->dis.itemState & ODS_DEFAULT)) {
// normal display
iTextStateID = MPI_NORMAL;
iBackgroundStateID = MPI_NORMAL;
}
if (pUDMI->dis.itemState & ODS_HOTLIGHT) {
// hot tracking
iTextStateID = MPI_HOT;
iBackgroundStateID = MPI_HOT;
pbrBackground = &g_brItemBackgroundHot;
}
if (pUDMI->dis.itemState & ODS_SELECTED) {
// clicked -- MENU_POPUPITEM has no state for this, though MENU_BARITEM does
iTextStateID = MPI_HOT;
iBackgroundStateID = MPI_HOT;
pbrBackground = &g_brItemBackgroundSelected;
}
if ((pUDMI->dis.itemState & ODS_GRAYED) || (pUDMI->dis.itemState & ODS_DISABLED)) {
// disabled / grey text
iTextStateID = MPI_DISABLED;
iBackgroundStateID = MPI_DISABLED;
}
if (pUDMI->dis.itemState & ODS_NOACCEL) {
dwFlags |= DT_HIDEPREFIX;
}
}
if (!g_menuTheme) {
g_menuTheme = OpenThemeData(hWnd, L"Menu");
}
DTTOPTS opts = { sizeof(opts), DTT_TEXTCOLOR | DTT_COMPOSITED | DTT_GLOWSIZE, RGB(0xFF, 0xFF, 0xFF), iTextStateID != MPI_DISABLED ? RGB(0xFF, 0xFF, 0xFF) : RGB(0xC0, 0xC0, 0xC0) };
//opts.dwFlags = ;
FillRect(pUDMI->um.hdc, &pUDMI->dis.rcItem, *pbrBackground);
pDrawThemeTextEx(g_menuTheme, pUDMI->um.hdc, MENU_BARITEM, MBI_NORMAL, menuString, mii.cch, dwFlags, &pUDMI->dis.rcItem, &opts);
return true;
}
case WM_UAHMEASUREMENUITEM:
{
UAHMEASUREMENUITEM* pMmi = (UAHMEASUREMENUITEM*)lParam;
// allow the default window procedure to handle the message
// since we don't really care about changing the width
*lr = DefWindowProc(hWnd, message, wParam, lParam);
// but we can modify it here to make it 1/3rd wider for example
//pMmi->mis.itemWidth = (pMmi->mis.itemWidth * 5) / 4;
return true;
}
case WM_THEMECHANGED:
{
if (g_menuTheme) {
CloseThemeData(g_menuTheme);
g_menuTheme = nullptr;
}
// continue processing in main wndproc
return false;
}
case WM_NCPAINT:
case WM_NCACTIVATE:
*lr = DefWindowProc(hWnd, message, wParam, lParam);
UAHDrawMenuNCBottomLine(hWnd);
return true;
break;
default:
return false;
}
}
@@ -0,0 +1,78 @@
/*---------------------------------------------------------------------------*/
// Author : adzm
// Web : https://github.com/adzm/win32-custom-menubar-aero-theme
// License : MIT License
// https://github.com/adzm/win32-custom-menubar-aero-theme/blob/main/LICENSE
/*---------------------------------------------------------------------------*/
#pragma once
// processes messages related to UAH / custom menubar drawing.
// return true if handled, false to continue with normal processing in your wndproc
bool UAHWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT* lr);
// window messages related to menu bar drawing
#define WM_UAHDESTROYWINDOW 0x0090 // handled by DefWindowProc
#define WM_UAHDRAWMENU 0x0091 // lParam is UAHMENU
#define WM_UAHDRAWMENUITEM 0x0092 // lParam is UAHDRAWMENUITEM
#define WM_UAHINITMENU 0x0093 // handled by DefWindowProc
#define WM_UAHMEASUREMENUITEM 0x0094 // lParam is UAHMEASUREMENUITEM
#define WM_UAHNCPAINTMENUPOPUP 0x0095 // handled by DefWindowProc
// describes the sizes of the menu bar or menu item
typedef union tagUAHMENUITEMMETRICS
{
// cx appears to be 14 / 0xE less than rcItem's width!
// cy 0x14 seems stable, i wonder if it is 4 less than rcItem's height which is always 24 atm
struct {
DWORD cx;
DWORD cy;
} rgsizeBar[2];
struct {
DWORD cx;
DWORD cy;
} rgsizePopup[4];
} UAHMENUITEMMETRICS;
// not really used in our case but part of the other structures
typedef struct tagUAHMENUPOPUPMETRICS
{
DWORD rgcx[4];
DWORD fUpdateMaxWidths : 2; // from kernel symbols, padded to full dword
} UAHMENUPOPUPMETRICS;
// hmenu is the main window menu; hdc is the context to draw in
typedef struct tagUAHMENU
{
HMENU hmenu;
HDC hdc;
DWORD dwFlags; // no idea what these mean, in my testing it's either 0x00000a00 or sometimes 0x00000a10
} UAHMENU;
// menu items are always referred to by iPosition here
typedef struct tagUAHMENUITEM
{
int iPosition; // 0-based position of menu item in menubar
UAHMENUITEMMETRICS umim;
UAHMENUPOPUPMETRICS umpm;
} UAHMENUITEM;
// the DRAWITEMSTRUCT contains the states of the menu items, as well as
// the position index of the item in the menu, which is duplicated in
// the UAHMENUITEM's iPosition as well
typedef struct UAHDRAWMENUITEM
{
DRAWITEMSTRUCT dis; // itemID looks uninitialized
UAHMENU um;
UAHMENUITEM umi;
} UAHDRAWMENUITEM;
// the MEASUREITEMSTRUCT is intended to be filled with the size of the item
// height appears to be ignored, but width can be modified
typedef struct tagUAHMEASUREMENUITEM
{
MEASUREITEMSTRUCT mis;
UAHMENU um;
UAHMENUITEM umi;
} UAHMEASUREMENUITEM;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,143 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
////------------------------------------------------
// Debug
////------------------------------------------------
void SetDebugMode(DWORD mode);
void DebugPrint(CString cstr);
////------------------------------------------------
// File Information
////------------------------------------------------
int GetFileVersion(const TCHAR* fileName, TCHAR* version = NULL);
void GetFileVersionEx(const TCHAR* file, CString& version);
BOOL IsFileExist(const TCHAR* fileName);
BOOL CanWriteFile(const TCHAR* fileName);
////------------------------------------------------
// Utility
////------------------------------------------------
ULONGLONG GetTickCountFx();
ULONG64 B8toB64(BYTE b0, BYTE b1 = 0, BYTE b2 = 0, BYTE b3 = 0, BYTE b4 = 0, BYTE b5 = 0, BYTE b6 = 0, BYTE b7 = 0);
DWORD B8toB32(BYTE b0, BYTE b1 = 0, BYTE b2 = 0, BYTE b3 = 0);
void SplitCString(const CString& str, const CString& delimiter, CStringArray& arr);
#if _MSC_VER > 1310
// ---------------------------------------------------------
// 20260123: Safe for unaligned/page-boundary (Using memcpy for atomic-like MOV) >>>
#ifndef NODISCARD
#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
#define NODISCARD [[nodiscard]]
#elif defined(_MSC_VER) && (_MSC_VER >= 1700)
#define NODISCARD _Check_return_
#else
#define NODISCARD
#endif
#endif
// SAL annotation support
#ifndef _In_reads_
#ifdef _MSC_VER
#include <sal.h>
#endif
//without SAL
#ifndef _In_reads_
#define _In_reads_(s)
#endif
#endif
/* 8byte(le) to ULONG64 (Safe for unaligned/page-boundary) */
NODISCARD ULONG64 B8toB64le_ptr(_In_reads_(8) const BYTE* v) noexcept;
/* 4byte(le) to DWORD (Safe for unaligned/page-boundary) */
NODISCARD DWORD B8toB32le_ptr(_In_reads_(4) const BYTE* v) noexcept;
/* 4byte(le) to INT (Controlled sign extension) */
NODISCARD INT B8toINTle_ptr(_In_reads_(4) const BYTE* v) noexcept;
/* 2byte(le) to USHORT (Safe for unaligned/page-boundary) */
NODISCARD USHORT B8toB16le_ptr(_In_reads_(2) const BYTE* v) noexcept;
/* 2byte(le) to signed SHORT (Controlled sign extension) */
NODISCARD SHORT B8toSHORTle_ptr(_In_reads_(2) const BYTE* v) noexcept;
/* 6byte(le) to ULONG64 (Safe for page-boundary) */
NODISCARD ULONG64 B8toB64le(const BYTE(&v)[6]) noexcept;
/* 6byte(le) to DWORD (Safe for page-boundary) */
NODISCARD DWORD B8toB32le(const BYTE(&v)[6]) noexcept;
/* 6byte(le) to INT (Controlled sign extension) */
NODISCARD INT B8toINTle(const BYTE(&v)[6]) noexcept;
/* 6byte(le) to USHORT (Safe for page-boundary) */
NODISCARD USHORT B8toB16le(const BYTE(&v)[6]) noexcept;
// 20260123: Safe for unaligned/page-boundary <<<
// ---------------------------------------------------------
#endif
////------------------------------------------------
// .ini support function
////------------------------------------------------
DWORD GetPrivateProfileStringFx(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString,DWORD nSize,LPCTSTR lpFileName);
UINT GetPrivateProfileIntFx(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName);
BOOL WritePrivateProfileStringFx(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName);
////------------------------------------------------
// Check CodeSign
////------------------------------------------------
#if _MSC_VER > 1310
BOOL CheckCodeSign(LPCWSTR certName, LPCWSTR filePath);
#endif
////------------------------------------------------
// Play Sound
////------------------------------------------------
BOOL AlertSound(const CString& alertSoundPath, int volume);
////------------------------------------------------
// Hash
////------------------------------------------------
CStringA MD5(const CStringA& str);
////------------------------------------------------
// Character Converter
////------------------------------------------------
CStringW UTF8toUTF16(const CStringA& utf8str);
CStringA UTF16toUTF8(const CStringW& utf16str);
CStringA URLEncode(const CStringA& str);
CStringA UE(const CStringW& utf16str);
CStringA UE(const CStringA& ansiStr);
////------------------------------------------------
// Clipboard
////------------------------------------------------
void SetClipboardText(CString clip);
////------------------------------------------------
// SHLWAPI.DLL compatible functions
////------------------------------------------------
#if _MSC_VER <= 1310
#ifdef UNICODE
#define PathRemoveFileSpecFx PathRemoveFileSpecFxW
#define PathFindFileNameFx PathFindFileNameFxW
#else
#define PathRemoveFileSpecFx PathRemoveFileSpecFxA
#define PathFindFileNameFx PathFindFileNameFxA
#endif
BOOL PathRemoveFileSpecFxA(char* path);
BOOL PathRemoveFileSpecFxW(WCHAR* path);
char* PathFindFileNameFxA(const char* path);
WCHAR* PathFindFileNameFxW(const WCHAR* path);
#endif
@@ -0,0 +1,226 @@
/*
* Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm
* and modified slightly to be functionally identical but condensed into control structures.
*/
#include "stdafx.h"
#include "md5.h"
/*
* Constants defined by the MD5 algorithm
*/
#define A 0x67452301
#define B 0xefcdab89
#define C 0x98badcfe
#define D 0x10325476
static uint32_t S[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
static uint32_t K[] = {0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391};
/*
* Padding used to make the size (in bits) of the input congruent to 448 mod 512
*/
static uint8_t PADDING[] = {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/*
* Bit-manipulation functions defined by the MD5 algorithm
*/
#define F(X, Y, Z) ((X & Y) | (~X & Z))
#define G(X, Y, Z) ((X & Z) | (Y & ~Z))
#define H(X, Y, Z) (X ^ Y ^ Z)
#define I(X, Y, Z) (Y ^ (X | ~Z))
/*
* Rotates a 32-bit word left by n bits
*/
uint32_t rotateLeft(uint32_t x, uint32_t n){
return (x << n) | (x >> (32 - n));
}
/*
* Initialize a context
*/
void md5Init(MD5Context *ctx){
ctx->size = (uint64_t)0;
ctx->buffer[0] = (uint32_t)A;
ctx->buffer[1] = (uint32_t)B;
ctx->buffer[2] = (uint32_t)C;
ctx->buffer[3] = (uint32_t)D;
}
/*
* Add some amount of input to the context
*
* If the input fills out a block of 512 bits, apply the algorithm (md5Step)
* and save the result in the buffer. Also updates the overall size.
*/
void md5Update(MD5Context *ctx, uint8_t *input_buffer, size_t input_len){
uint32_t input[16];
unsigned int offset = (unsigned int)(ctx->size % 64);
ctx->size += (uint64_t)input_len;
// Copy each byte in input_buffer into the next space in our context input
for(unsigned int i = 0; i < input_len; ++i){
ctx->input[offset++] = (uint8_t)*(input_buffer + i);
// If we've filled our context input, copy it into our local array input
// then reset the offset to 0 and fill in a new buffer.
// Every time we fill out a chunk, we run it through the algorithm
// to enable some back and forth between cpu and i/o
if(offset % 64 == 0){
for(unsigned int j = 0; j < 16; ++j){
// Convert to little-endian
// The local variable `input` our 512-bit chunk separated into 32-bit words
// we can use in calculations
input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 |
(uint32_t)(ctx->input[(j * 4) + 2]) << 16 |
(uint32_t)(ctx->input[(j * 4) + 1]) << 8 |
(uint32_t)(ctx->input[(j * 4)]);
}
md5Step(ctx->buffer, input);
offset = 0;
}
}
}
/*
* Pad the current input to get to 448 bytes, append the size in bits to the very end,
* and save the result of the final iteration into digest.
*/
void md5Finalize(MD5Context *ctx){
uint32_t input[16];
unsigned int offset = (unsigned int)(ctx->size % 64);
unsigned int padding_length = offset < 56 ? 56 - offset : (56 + 64) - offset;
// Fill in the padding and undo the changes to size that resulted from the update
md5Update(ctx, PADDING, padding_length);
ctx->size -= (uint64_t)padding_length;
// Do a final update (internal to this function)
// Last two 32-bit words are the two halves of the size (converted from bytes to bits)
for(unsigned int j = 0; j < 14; ++j){
input[j] = (uint32_t)(ctx->input[(j * 4) + 3]) << 24 |
(uint32_t)(ctx->input[(j * 4) + 2]) << 16 |
(uint32_t)(ctx->input[(j * 4) + 1]) << 8 |
(uint32_t)(ctx->input[(j * 4)]);
}
input[14] = (uint32_t)(ctx->size * 8);
input[15] = (uint32_t)((ctx->size * 8) >> 32);
md5Step(ctx->buffer, input);
// Move the result into digest (convert from little-endian)
for(unsigned int i = 0; i < 4; ++i){
ctx->digest[(i * 4) + 0] = (uint8_t)((ctx->buffer[i] & 0x000000FF));
ctx->digest[(i * 4) + 1] = (uint8_t)((ctx->buffer[i] & 0x0000FF00) >> 8);
ctx->digest[(i * 4) + 2] = (uint8_t)((ctx->buffer[i] & 0x00FF0000) >> 16);
ctx->digest[(i * 4) + 3] = (uint8_t)((ctx->buffer[i] & 0xFF000000) >> 24);
}
}
/*
* Step on 512 bits of input with the main MD5 algorithm.
*/
void md5Step(uint32_t *buffer, uint32_t *input){
uint32_t AA = buffer[0];
uint32_t BB = buffer[1];
uint32_t CC = buffer[2];
uint32_t DD = buffer[3];
uint32_t E;
unsigned int j;
for(unsigned int i = 0; i < 64; ++i){
switch(i / 16){
case 0:
E = F(BB, CC, DD);
j = i;
break;
case 1:
E = G(BB, CC, DD);
j = ((i * 5) + 1) % 16;
break;
case 2:
E = H(BB, CC, DD);
j = ((i * 3) + 5) % 16;
break;
default:
E = I(BB, CC, DD);
j = (i * 7) % 16;
break;
}
uint32_t temp = DD;
DD = CC;
CC = BB;
BB = BB + rotateLeft(AA + E + K[i] + input[j], S[i]);
AA = temp;
}
buffer[0] += AA;
buffer[1] += BB;
buffer[2] += CC;
buffer[3] += DD;
}
/*
* Functions that run the algorithm on the provided input and put the digest into result.
* result should be able to store 16 bytes.
*/
void md5String(char *input, uint8_t *result){
MD5Context ctx = {0};
md5Init(&ctx);
md5Update(&ctx, (uint8_t *)input, strlen(input));
md5Finalize(&ctx);
memcpy(result, ctx.digest, 16);
}
/*
void md5File(FILE *file, uint8_t *result){
char *input_buffer = malloc(1024);
size_t input_size = 0;
MD5Context ctx;
md5Init(&ctx);
while((input_size = fread(input_buffer, 1, 1024, file)) > 0){
md5Update(&ctx, (uint8_t *)input_buffer, input_size);
}
md5Finalize(&ctx);
free(input_buffer);
memcpy(result, ctx.digest, 16);
}
*/
@@ -0,0 +1,29 @@
#ifndef MD5_H
#define MD5_H
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef struct{
uint64_t size; // Size of input in bytes
uint32_t buffer[4]; // Current accumulation of hash
uint8_t input[64]; // Input to be used in the next step
uint8_t digest[16]; // Result of algorithm
}MD5Context;
void md5Init(MD5Context *ctx);
void md5Update(MD5Context *ctx, uint8_t *input, size_t input_len);
void md5Finalize(MD5Context *ctx);
void md5Step(uint32_t *buffer, uint32_t *input);
void md5String(char *input, uint8_t *result);
// void md5File(FILE *file, uint8_t *result);
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,17 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#define STBI_ONLY_PNG
#define STBI_NO_STDIO
#define STBI_NO_HDR
#define STBI_NO_LINEAR
#define STBI_NO_FAILURE_STRINGS
#define STBI_ASSERT(x)
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,13 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#define STBI_NO_STDIO
#define STBI_WRITE_NO_STDIO
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
@@ -0,0 +1,700 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#include "stdafx.h"
#include "DiskMark.h"
#include "DiskMarkDlg.h"
#include "SettingsDlg.h"
IMPLEMENT_DYNCREATE(CSettingsDlg, CDialog)
CSettingsDlg::CSettingsDlg(CWnd* pParent /*=NULL*/)
: CDialogFx(CSettingsDlg::IDD, pParent)
{
CMainDialogFx* p = (CMainDialogFx*)pParent;
m_ZoomType = p->GetZoomType();
m_FontScale = p->GetFontScale();
m_FontRatio = p->GetFontRatio();
m_FontFace = p->GetFontFace();
m_FontRender = p->GetFontRender();
m_CurrentLangPath = p->GetCurrentLangPath();
m_DefaultLangPath = p->GetDefaultLangPath();
m_ThemeDir = p->GetThemeDir();
m_CurrentTheme = p->GetCurrentTheme();
m_DefaultTheme = p->GetDefaultTheme();
m_Ini = p->GetIniPath();
m_Profile = ((CDiskMarkDlg*)pParent)->m_Profile;
m_MeasureTime = ((CDiskMarkDlg*)pParent)->m_MeasureTime;
m_IntervalTime = ((CDiskMarkDlg*)pParent)->m_IntervalTime;
m_TestData = ((CDiskMarkDlg*)pParent)->m_TestData;
}
CSettingsDlg::~CSettingsDlg()
{
}
void CSettingsDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogFx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LABEL_TYPE, m_LabelType);
DDX_Control(pDX, IDC_LABEL_SIZE, m_LabelSize);
DDX_Control(pDX, IDC_LABEL_QUEUES, m_LabelQueues);
DDX_Control(pDX, IDC_LABEL_THREADS, m_LabelThreads);
DDX_Control(pDX, IDC_LABEL_DEFAULT, m_LabelDefault);
DDX_Control(pDX, IDC_LABEL_PEAK, m_LabelPeak);
DDX_Control(pDX, IDC_LABEL_DEMO, m_LabelDemo);
DDX_Control(pDX, IDC_LABEL_MEASURE_TIME, m_LabelMeasureTime);
DDX_Control(pDX, IDC_LABEL_INTERVAL_TIME, m_LabelIntervalTime);
// DDX_Control(pDX, IDC_LABEL_AFFINITY, m_LabelAffinity);
// DDX_Control(pDX, IDC_LABEL_DATA, m_LabelData);
DDX_Control(pDX, IDC_SET_DEFAULT, m_ButtonSetDefault);
DDX_Control(pDX, IDC_SET_NVME_8, m_ButtonSetNVMe8);
DDX_Control(pDX, IDC_SET_FLASH_MEMORY, m_ButtonSetFlashMemory);
DDX_Control(pDX, IDC_COMBO_BENCH_TYPE_0, m_ComboBenchType0);
DDX_Control(pDX, IDC_COMBO_BENCH_TYPE_1, m_ComboBenchType1);
DDX_Control(pDX, IDC_COMBO_BENCH_TYPE_2, m_ComboBenchType2);
DDX_Control(pDX, IDC_COMBO_BENCH_TYPE_3, m_ComboBenchType3);
DDX_Control(pDX, IDC_COMBO_BENCH_TYPE_4, m_ComboBenchType4);
DDX_Control(pDX, IDC_COMBO_BENCH_TYPE_5, m_ComboBenchType5);
DDX_Control(pDX, IDC_COMBO_BENCH_TYPE_8, m_ComboBenchType8);
DDX_Control(pDX, IDC_COMBO_BENCH_SIZE_0, m_ComboBenchSize0);
DDX_Control(pDX, IDC_COMBO_BENCH_SIZE_1, m_ComboBenchSize1);
DDX_Control(pDX, IDC_COMBO_BENCH_SIZE_2, m_ComboBenchSize2);
DDX_Control(pDX, IDC_COMBO_BENCH_SIZE_3, m_ComboBenchSize3);
DDX_Control(pDX, IDC_COMBO_BENCH_SIZE_4, m_ComboBenchSize4);
DDX_Control(pDX, IDC_COMBO_BENCH_SIZE_5, m_ComboBenchSize5);
DDX_Control(pDX, IDC_COMBO_BENCH_SIZE_8, m_ComboBenchSize8);
DDX_Control(pDX, IDC_COMBO_BENCH_QUEUE_0, m_ComboBenchQueues0);
DDX_Control(pDX, IDC_COMBO_BENCH_QUEUE_1, m_ComboBenchQueues1);
DDX_Control(pDX, IDC_COMBO_BENCH_QUEUE_2, m_ComboBenchQueues2);
DDX_Control(pDX, IDC_COMBO_BENCH_QUEUE_3, m_ComboBenchQueues3);
DDX_Control(pDX, IDC_COMBO_BENCH_QUEUE_4, m_ComboBenchQueues4);
DDX_Control(pDX, IDC_COMBO_BENCH_QUEUE_5, m_ComboBenchQueues5);
DDX_Control(pDX, IDC_COMBO_BENCH_QUEUE_8, m_ComboBenchQueues8);
DDX_Control(pDX, IDC_COMBO_BENCH_THREAD_0, m_ComboBenchThreads0);
DDX_Control(pDX, IDC_COMBO_BENCH_THREAD_1, m_ComboBenchThreads1);
DDX_Control(pDX, IDC_COMBO_BENCH_THREAD_2, m_ComboBenchThreads2);
DDX_Control(pDX, IDC_COMBO_BENCH_THREAD_3, m_ComboBenchThreads3);
DDX_Control(pDX, IDC_COMBO_BENCH_THREAD_4, m_ComboBenchThreads4);
DDX_Control(pDX, IDC_COMBO_BENCH_THREAD_5, m_ComboBenchThreads5);
DDX_Control(pDX, IDC_COMBO_BENCH_THREAD_8, m_ComboBenchThreads8);
// DDX_Control(pDX, IDC_COMBO_DATA, m_ComboData);
// DDX_Control(pDX, IDC_COMBO_AFFINITY, m_ComboAffinity);
DDX_Control(pDX, IDC_COMBO_MEASURE_TIME, m_ComboMeasureTime);
DDX_Control(pDX, IDC_COMBO_INTERVAL_TIME, m_ComboIntervalTime);
DDX_Control(pDX, IDC_OK, m_ButtonOk);
}
BEGIN_MESSAGE_MAP(CSettingsDlg, CDialogFx)
ON_BN_CLICKED(IDC_SET_DEFAULT, &CSettingsDlg::OnSetDefault)
ON_BN_CLICKED(IDC_SET_NVME_8, &CSettingsDlg::OnSetNVMe8)
ON_BN_CLICKED(IDC_SET_FLASH_MEMORY, &CSettingsDlg::OnSetFlashMemory)
ON_BN_CLICKED(IDC_OK, &CSettingsDlg::OnOk)
END_MESSAGE_MAP()
void CSettingsDlg::OnSetDefault()
{
int type[9] = { 0, 0, 1, 1, 0, 1, 0, 1, 0 };
int size[9] = { 1024, 1024, 4, 4, 1024, 4, 1024, 4, 1024 };
int queues[9] = { 8, 1, 32, 1, 8, 32, 1, 1, 8 };
int threads[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
for (int i = 0; i < 9; i++)
{
m_BenchType[i] = type[i];
m_BenchSize[i] = size[i];
m_BenchQueues[i] = queues[i];
m_BenchThreads[i] = threads[i];
}
m_TestData = 0;
m_MeasureTime = 5;
m_IntervalTime = 5;
InitComboBox();
}
void CSettingsDlg::OnSetNVMe8()
{
int type[9] = { 0, 0, 1, 1, 0, 1, 0, 1, 0 };
int size[9] = { 1024, 128, 4, 4, 1024, 4, 1024, 4, 1024 };
int queues[9] = { 8, 32, 32, 1, 8, 32, 1, 1, 8 };
int threads[9] = { 1, 1, 16, 1, 1, 16, 1, 1, 1 };
for (int i = 0; i < 9; i++)
{
m_BenchType[i] = type[i];
m_BenchSize[i] = size[i];
m_BenchQueues[i] = queues[i];
m_BenchThreads[i] = threads[i];
}
m_TestData = 0;
m_MeasureTime = 5;
m_IntervalTime = 5;
InitComboBox();
}
void CSettingsDlg::OnSetFlashMemory()
{
int type[9] = { 0, 0, 1, 1, 0, 1, 0, 1, 0 };
int size[9] = { 1024, 1024, 4, 4, 1024, 4, 1024, 4, 1024 };
int queues[9] = { 8, 1, 32, 1, 8, 32, 1, 1, 8 };
int threads[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
for (int i = 0; i < 9; i++)
{
m_BenchType[i] = type[i];
m_BenchSize[i] = size[i];
m_BenchQueues[i] = queues[i];
m_BenchThreads[i] = threads[i];
}
m_TestData = 0;
m_MeasureTime = 1;
m_IntervalTime = 30;
InitComboBox();
}
BOOL CSettingsDlg::OnInitDialog()
{
CDialogFx::OnInitDialog();
CString cstr;
int type[9] = { 0, 0, 1, 1, 0, 1, 0, 1, 0 };
int size[9] = { 1024, 1024, 4, 4, 1024, 4, 1024, 4, 1024 };
int queues[9] = { 8, 1, 32, 1, 8, 32, 1, 1, 8 };
int threads[9] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 };
for (int i = 0; i < 9; i++)
{
cstr.Format(L"BenchType%d", i);
m_BenchType[i] = GetPrivateProfileInt(L"Setting", cstr, type[i], m_Ini);
if (m_BenchType[i] < 0 || m_BenchSize[i] > 1) { m_BenchSize[i] = type[i]; }
cstr.Format(L"BenchSize%d", i);
m_BenchSize[i] = GetPrivateProfileInt(L"Setting", cstr, size[i], m_Ini);
if (m_BenchSize[i] <= 0 || m_BenchSize[i] > 8192) { m_BenchSize[i] = size[i]; }
cstr.Format(L"BenchQueues%d", i);
m_BenchQueues[i] = GetPrivateProfileInt(L"Setting", cstr, queues[i], m_Ini);
if (m_BenchQueues[i] <= 0 || m_BenchQueues[i] > MAX_QUEUES) { m_BenchQueues[i] = queues[i]; }
cstr.Format(L"BenchThreads%d", i);
m_BenchThreads[i] = GetPrivateProfileInt(L"Setting", cstr, threads[i], m_Ini);
if (m_BenchThreads[i] <= 0 || m_BenchThreads[i] > MAX_THREADS) { m_BenchThreads[i] = threads[i]; }
}
m_TestData = GetPrivateProfileInt(L"Setting", L"TestData", 0, m_Ini);
if (m_TestData < 0 || m_TestData > 1)
{
m_TestData = 0;
}
InitComboBox();
m_LabelType.SetWindowTextW(i18n(L"Dialog", L"TYPE"));
m_LabelSize.SetWindowTextW(i18n(L"Dialog", L"BLOCK_SIZE"));
m_LabelQueues.SetWindowTextW(i18n(L"Dialog", L"QUEUES"));
m_LabelThreads.SetWindowTextW(i18n(L"Dialog", L"THREADS"));
m_LabelDefault.SetWindowTextW(L" " + i18n(L"Dialog", L"PROFILE_DEFAULT"));
m_LabelPeak.SetWindowTextW(L" " + i18n(L"Dialog", L"PROFILE_PEAK_PERFORMANCE"));
m_LabelDemo.SetWindowTextW(L" " + i18n(L"Dialog", L"PROFILE_DEMO"));
m_LabelMeasureTime.SetWindowTextW(L" " + i18n(L"Dialog", L"MEASURE_TIME"));
m_LabelIntervalTime.SetWindowTextW(L" " + i18n(L"Dialog", L"INTERVAL_TIME"));
m_ButtonSetDefault.SetWindowTextW(i18n(L"Dialog", L"DEFAULT"));
SetWindowTitle(i18n(L"WindowTitle", L"SETTINGS"));
UpdateDialogSize();
return TRUE;
}
void CSettingsDlg::InitComboBox()
{
m_ComboBenchType0.ResetContent();
m_ComboBenchType1.ResetContent();
m_ComboBenchType2.ResetContent();
m_ComboBenchType3.ResetContent();
m_ComboBenchType4.ResetContent();
m_ComboBenchType5.ResetContent();
m_ComboBenchType8.ResetContent();
for (int i = 0; i < 2; i++)
{
CString cstr;
if (i == 0)
{
cstr.Format(L"SEQ");
}
else
{
cstr.Format(L"RND");
}
m_ComboBenchType0.AddString(cstr); if (m_BenchType[0] == i) { m_ComboBenchType0.SetCurSel(i); }
m_ComboBenchType1.AddString(cstr); if (m_BenchType[1] == i) { m_ComboBenchType1.SetCurSel(i); }
m_ComboBenchType2.AddString(cstr); if (m_BenchType[2] == i) { m_ComboBenchType2.SetCurSel(i); }
m_ComboBenchType3.AddString(cstr); if (m_BenchType[3] == i) { m_ComboBenchType3.SetCurSel(i); }
m_ComboBenchType4.AddString(cstr); if (m_BenchType[4] == i) { m_ComboBenchType4.SetCurSel(i); }
m_ComboBenchType5.AddString(cstr); if (m_BenchType[5] == i) { m_ComboBenchType5.SetCurSel(i); }
m_ComboBenchType8.AddString(cstr); if (m_BenchType[8] == i) { m_ComboBenchType8.SetCurSel(i); }
}
m_ComboBenchSize0.ResetContent();
m_ComboBenchSize1.ResetContent();
m_ComboBenchSize2.ResetContent();
m_ComboBenchSize3.ResetContent();
m_ComboBenchSize4.ResetContent();
m_ComboBenchSize5.ResetContent();
m_ComboBenchSize8.ResetContent();
int blockSize[] = { 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
for (int i = 0; i < 12; i++)
{
CString cstr;
if (blockSize[i] >= 1024)
{
cstr.Format(L"%dMiB", blockSize[i] / 1024);
}
else
{
cstr.Format(L"%dKiB", blockSize[i]);
}
m_ComboBenchSize0.AddString(cstr); if (m_BenchSize[0] == blockSize[i]) { m_ComboBenchSize0.SetCurSel(i); }
m_ComboBenchSize1.AddString(cstr); if (m_BenchSize[1] == blockSize[i]) { m_ComboBenchSize1.SetCurSel(i); }
m_ComboBenchSize2.AddString(cstr); if (m_BenchSize[2] == blockSize[i]) { m_ComboBenchSize2.SetCurSel(i); }
m_ComboBenchSize3.AddString(cstr); if (m_BenchSize[3] == blockSize[i]) { m_ComboBenchSize3.SetCurSel(i); }
m_ComboBenchSize4.AddString(cstr); if (m_BenchSize[4] == blockSize[i]) { m_ComboBenchSize4.SetCurSel(i); }
m_ComboBenchSize5.AddString(cstr); if (m_BenchSize[5] == blockSize[i]) { m_ComboBenchSize5.SetCurSel(i); }
m_ComboBenchSize8.AddString(cstr); if (m_BenchSize[8] == blockSize[i]) { m_ComboBenchSize8.SetCurSel(i); }
}
// Queues
m_ComboBenchQueues0.ResetContent();
m_ComboBenchQueues1.ResetContent();
m_ComboBenchQueues2.ResetContent();
m_ComboBenchQueues3.ResetContent();
m_ComboBenchQueues4.ResetContent();
m_ComboBenchQueues5.ResetContent();
m_ComboBenchQueues8.ResetContent();
int queues[10] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 };
// Sequential
for (int i = 0; i < 10; i++)
{
CString cstr;
cstr.Format(L"%d", queues[i]);
m_ComboBenchQueues0.AddString(cstr); if (m_BenchQueues[0] == queues[i]) { m_ComboBenchQueues0.SetCurSel(i); }
m_ComboBenchQueues1.AddString(cstr); if (m_BenchQueues[1] == queues[i]) { m_ComboBenchQueues1.SetCurSel(i); }
m_ComboBenchQueues2.AddString(cstr); if (m_BenchQueues[2] == queues[i]) { m_ComboBenchQueues2.SetCurSel(i); }
m_ComboBenchQueues3.AddString(cstr); if (m_BenchQueues[3] == queues[i]) { m_ComboBenchQueues3.SetCurSel(i); }
m_ComboBenchQueues4.AddString(cstr); if (m_BenchQueues[4] == queues[i]) { m_ComboBenchQueues4.SetCurSel(i); }
m_ComboBenchQueues5.AddString(cstr); if (m_BenchQueues[5] == queues[i]) { m_ComboBenchQueues5.SetCurSel(i); }
m_ComboBenchQueues8.AddString(cstr); if (m_BenchQueues[8] == queues[i]) { m_ComboBenchQueues8.SetCurSel(i); }
}
// Threads
m_ComboBenchThreads0.ResetContent();
m_ComboBenchThreads1.ResetContent();
m_ComboBenchThreads2.ResetContent();
m_ComboBenchThreads3.ResetContent();
m_ComboBenchThreads4.ResetContent();
m_ComboBenchThreads5.ResetContent();
m_ComboBenchThreads8.ResetContent();
for (int i = 1; i <= 64; i++)
{
CString cstr;
cstr.Format(L"%d", i);
m_ComboBenchThreads0.AddString(cstr); if (m_BenchThreads[0] == i) { m_ComboBenchThreads0.SetCurSel(i - 1); }
m_ComboBenchThreads1.AddString(cstr); if (m_BenchThreads[1] == i) { m_ComboBenchThreads1.SetCurSel(i - 1); }
m_ComboBenchThreads2.AddString(cstr); if (m_BenchThreads[2] == i) { m_ComboBenchThreads2.SetCurSel(i - 1); }
m_ComboBenchThreads3.AddString(cstr); if (m_BenchThreads[3] == i) { m_ComboBenchThreads3.SetCurSel(i - 1); }
m_ComboBenchThreads4.AddString(cstr); if (m_BenchThreads[4] == i) { m_ComboBenchThreads4.SetCurSel(i - 1); }
m_ComboBenchThreads5.AddString(cstr); if (m_BenchThreads[5] == i) { m_ComboBenchThreads5.SetCurSel(i - 1); }
m_ComboBenchThreads8.AddString(cstr); if (m_BenchThreads[8] == i) { m_ComboBenchThreads8.SetCurSel(i - 1); }
}
m_ComboMeasureTime.ResetContent();
int measureTimes[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 60 };
for (int i = 0; i < 13; i++)
{
CString cstr;
cstr.Format(L"%d", measureTimes[i]);
m_ComboMeasureTime.AddString(cstr); if (m_MeasureTime == measureTimes[i]) { m_ComboMeasureTime.SetCurSel(i); }
}
m_ComboIntervalTime.ResetContent();
int intervalTimes[] = { 0, 1, 3, 5, 10, 30, 60, 180, 300, 600 };
for (int i = 0; i < 10; i++)
{
CString cstr;
cstr.Format(L"%d", intervalTimes[i]);
m_ComboIntervalTime.AddString(cstr); if (m_IntervalTime == intervalTimes[i]) { m_ComboIntervalTime.SetCurSel(i); }
}
}
int CSettingsDlg::GetType(CString text)
{
if (text.FindOneOf(L"SEQ") != -1)
{
return 0;
}
else
{
return 1;
}
}
int CSettingsDlg::GetBlockSize(CString text)
{
if(text.FindOneOf(L"M") != -1)
{
return _wtoi(text.GetString()) * 1024;
}
else
{
return _wtoi(text.GetString());
}
}
void CSettingsDlg::OnOk()
{
CString cstr;
m_ComboBenchType0.GetWindowTextW(cstr); cstr.Format(L"%d", GetType(cstr)); WritePrivateProfileString(L"Setting", L"BenchType0", cstr, m_Ini);
m_ComboBenchType1.GetWindowTextW(cstr); cstr.Format(L"%d", GetType(cstr)); WritePrivateProfileString(L"Setting", L"BenchType1", cstr, m_Ini);
m_ComboBenchType2.GetWindowTextW(cstr); cstr.Format(L"%d", GetType(cstr)); WritePrivateProfileString(L"Setting", L"BenchType2", cstr, m_Ini);
m_ComboBenchType3.GetWindowTextW(cstr); cstr.Format(L"%d", GetType(cstr)); WritePrivateProfileString(L"Setting", L"BenchType3", cstr, m_Ini);
m_ComboBenchType4.GetWindowTextW(cstr); cstr.Format(L"%d", GetType(cstr)); WritePrivateProfileString(L"Setting", L"BenchType4", cstr, m_Ini);
m_ComboBenchType5.GetWindowTextW(cstr); cstr.Format(L"%d", GetType(cstr)); WritePrivateProfileString(L"Setting", L"BenchType5", cstr, m_Ini);
m_ComboBenchType8.GetWindowTextW(cstr); cstr.Format(L"%d", GetType(cstr)); WritePrivateProfileString(L"Setting", L"BenchType8", cstr, m_Ini);
m_ComboBenchSize0.GetWindowTextW(cstr); cstr.Format(L"%d", GetBlockSize(cstr)); WritePrivateProfileString(L"Setting", L"BenchSize0", cstr, m_Ini);
m_ComboBenchSize1.GetWindowTextW(cstr); cstr.Format(L"%d", GetBlockSize(cstr)); WritePrivateProfileString(L"Setting", L"BenchSize1", cstr, m_Ini);
m_ComboBenchSize2.GetWindowTextW(cstr); cstr.Format(L"%d", GetBlockSize(cstr)); WritePrivateProfileString(L"Setting", L"BenchSize2", cstr, m_Ini);
m_ComboBenchSize3.GetWindowTextW(cstr); cstr.Format(L"%d", GetBlockSize(cstr)); WritePrivateProfileString(L"Setting", L"BenchSize3", cstr, m_Ini);
m_ComboBenchSize4.GetWindowTextW(cstr); cstr.Format(L"%d", GetBlockSize(cstr)); WritePrivateProfileString(L"Setting", L"BenchSize4", cstr, m_Ini);
m_ComboBenchSize5.GetWindowTextW(cstr); cstr.Format(L"%d", GetBlockSize(cstr)); WritePrivateProfileString(L"Setting", L"BenchSize5", cstr, m_Ini);
m_ComboBenchSize8.GetWindowTextW(cstr); cstr.Format(L"%d", GetBlockSize(cstr)); WritePrivateProfileString(L"Setting", L"BenchSize8", cstr, m_Ini);
m_ComboBenchQueues0.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchQueues0", cstr, m_Ini);
m_ComboBenchQueues1.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchQueues1", cstr, m_Ini);
m_ComboBenchQueues2.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchQueues2", cstr, m_Ini);
m_ComboBenchQueues3.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchQueues3", cstr, m_Ini);
m_ComboBenchQueues4.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchQueues4", cstr, m_Ini);
m_ComboBenchQueues5.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchQueues5", cstr, m_Ini);
m_ComboBenchQueues8.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchQueues8", cstr, m_Ini);
m_ComboBenchThreads0.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchThreads0", cstr, m_Ini);
m_ComboBenchThreads1.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchThreads1", cstr, m_Ini);
m_ComboBenchThreads2.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchThreads2", cstr, m_Ini);
m_ComboBenchThreads3.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchThreads3", cstr, m_Ini);
m_ComboBenchThreads4.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchThreads4", cstr, m_Ini);
m_ComboBenchThreads5.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchThreads5", cstr, m_Ini);
m_ComboBenchThreads8.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"BenchThreads8", cstr, m_Ini);
m_ComboMeasureTime.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"MeasureTime", cstr, m_Ini);
m_ComboIntervalTime.GetWindowTextW(cstr); WritePrivateProfileString(L"Setting", L"IntervalTime", cstr, m_Ini);
CDialogFx::OnCancel();
}
void CSettingsDlg::OnCancel()
{
CDialogFx::OnCancel();
}
void CSettingsDlg::UpdateDialogSize()
{
CDialogFx::UpdateDialogSize();
ChangeZoomType(m_ZoomType);
SetClientSize(SIZE_X, SIZE_Y, m_ZoomRatio);
UpdateBackground(FALSE, m_bDarkMode);
COLORREF textColor = RGB(0, 0, 0);
COLORREF textSelectedColor = RGB(0, 0, 0);
#ifdef SUISHO_SHIZUKU_SUPPORT
int fontSize = 16;
int comboHeight = 24;
#else
int fontSize = 12;
int comboHeight = 20;
#endif
m_LabelType.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelSize.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelQueues.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelThreads.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelDefault.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelPeak.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelDemo.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelMeasureTime.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_LabelIntervalTime.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
// m_LabelAffinity.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
// m_LabelData.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, RGB(0, 0, 0), FW_NORMAL, m_FontRender);
m_ComboBenchType0.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchType1.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchType2.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchType3.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchType4.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchType5.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchType8.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchSize0.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchSize1.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchSize2.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchSize3.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchSize4.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchSize5.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchSize8.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchQueues0.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchQueues1.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchQueues2.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchQueues3.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchQueues4.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchQueues5.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchQueues8.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchThreads0.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchThreads1.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchThreads2.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchThreads3.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchThreads4.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchThreads5.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboBenchThreads8.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
// m_ComboData.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
// m_ComboAffinity.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboMeasureTime.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ComboIntervalTime.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, textColor, textSelectedColor, FW_NORMAL, m_FontRender);
m_ButtonSetDefault.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, m_MeterText, FW_NORMAL, m_FontRender);
m_ButtonSetNVMe8.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, m_MeterText, FW_NORMAL, m_FontRender);
m_ButtonSetFlashMemory.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, m_MeterText, FW_NORMAL, m_FontRender);
m_ButtonOk.SetFontEx(m_FontFace, fontSize, fontSize, m_ZoomRatio, m_FontRatio, m_MeterText, FW_NORMAL, m_FontRender);
#ifdef SUISHO_SHIZUKU_SUPPORT
m_LabelType.InitControl(8, 8, 160, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelSize.InitControl(176, 8, 160, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelQueues.InitControl(344, 8, 160, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelThreads.InitControl(512, 8, 160, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelDefault.InitControl(8, 32, 664, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelPeak.InitControl(8, 172, 664, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelDemo.InitControl(8, 256, 664, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
// m_LabelData.InitControl(344, 316, 328, 24, m_ZoomRatio, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
// m_LabelAffinity.InitControl(8, 316, 328, 24, m_ZoomRatio, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelMeasureTime.InitControl(8, 316, 328, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelIntervalTime.InitControl(344, 316, 328, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_ComboBenchType0.InitControl(8, 60, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType1.InitControl(8, 88, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType2.InitControl(8, 116, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType3.InitControl(8, 144, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType4.InitControl(8, 200, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType5.InitControl(8, 228, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType8.InitControl(8, 284, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize0.InitControl(176, 60, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize1.InitControl(176, 88, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize2.InitControl(176, 116, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize3.InitControl(176, 144, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize4.InitControl(176, 200, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize5.InitControl(176, 228, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize8.InitControl(176, 284, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues0.InitControl(344, 60, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues1.InitControl(344, 88, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues2.InitControl(344, 116, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues3.InitControl(344, 144, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues4.InitControl(344, 200, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues5.InitControl(344, 228, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues8.InitControl(344, 284, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads0.InitControl(512, 60, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads1.InitControl(512, 88, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads2.InitControl(512, 116, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads3.InitControl(512, 144, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads4.InitControl(512, 200, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads5.InitControl(512, 228, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads8.InitControl(512, 284, 160, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
// m_ComboData.InitControl(352, 344, 320, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
// m_ComboAffinity.InitControl(16, 344, 320, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboMeasureTime.InitControl(8, 344, 328, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboIntervalTime.InitControl(344, 344, 328, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ButtonSetDefault.InitControl(8, 376, 160, 32, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_ButtonSetNVMe8.InitControl(176, 376, 160, 32, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_ButtonSetFlashMemory.InitControl(344, 376, 160, 32, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_ButtonOk.InitControl(512, 376, 160, 32, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
#else
m_LabelType.InitControl(8, 8, 100, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelSize.InitControl(116, 8, 100, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelQueues.InitControl(224, 8, 100, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelThreads.InitControl(332, 8, 100, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelDefault.InitControl(8, 28, 424, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelPeak.InitControl(8, 148, 424, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelDemo.InitControl(8, 220, 424, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
// m_LabelAffinity.InitControl(8, 272, 208, 20, m_ZoomRatio, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
// m_LabelData.InitControl(224, 272, 208, 20, m_ZoomRatio, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelMeasureTime.InitControl(8, 272, 208, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_LabelIntervalTime.InitControl(224, 272, 208, 20, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, SS_LEFT, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_ComboBenchType0.InitControl(8, 52, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType1.InitControl(8, 76, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType2.InitControl(8, 100, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType3.InitControl(8, 124, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType4.InitControl(8, 172, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType5.InitControl(8, 196, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchType8.InitControl(8, 244, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize0.InitControl(116, 52, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize1.InitControl(116, 76, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize2.InitControl(116, 100, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize3.InitControl(116, 124, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize4.InitControl(116, 172, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize5.InitControl(116, 196, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchSize8.InitControl(116, 244, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues0.InitControl(224, 52, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues1.InitControl(224, 76, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues2.InitControl(224, 100, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues3.InitControl(224, 124, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues4.InitControl(224, 172, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues5.InitControl(224, 196, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchQueues8.InitControl(224, 244, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads0.InitControl(332, 52, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads1.InitControl(332, 76, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads2.InitControl(332, 100, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads3.InitControl(332, 124, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads4.InitControl(332, 172, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads5.InitControl(332, 196, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboBenchThreads8.InitControl(332, 244, 100, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
// m_ComboData.InitControl(232, 296, 200, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
// m_ComboAffinity.InitControl(16, 296, 200, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboMeasureTime.InitControl(8, 296, 208, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ComboIntervalTime.InitControl(224, 296, 208, 200, m_ZoomRatio, &m_BkDC, NULL, 0, ES_LEFT, OwnerDrawTransparent, m_bHighContrast, m_bDarkMode, RGB(255, 255, 255), RGB(160, 220, 255), RGB(255, 255, 255), 0);
m_ButtonSetDefault.InitControl(8, 324, 100, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_ButtonSetNVMe8.InitControl(116, 324, 100, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_ButtonSetFlashMemory.InitControl(224, 324, 100, 24, m_ZoomRatio, m_hPal,&m_BkDC, NULL, 0, BS_CENTER, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
m_ButtonOk.InitControl(332, 324, 100, 24, m_ZoomRatio, m_hPal, &m_BkDC, NULL, 0, BS_CENTER, SystemDraw, m_bHighContrast, m_bDarkMode, FALSE);
#endif
// m_ButtonSetDefault.SetDrawFrame(TRUE);
// m_ButtonSetNVMe8.SetDrawFrame(TRUE);
// m_ButtonSetNVMe9.SetDrawFrame(TRUE);
// m_ButtonOk.SetDrawFrame(TRUE);
m_ButtonSetDefault.SetHandCursor();
m_ButtonSetNVMe8.SetHandCursor();
m_ButtonSetFlashMemory.SetHandCursor();
m_ButtonOk.SetHandCursor();
SetDarkModeControl(m_ButtonOk.GetSafeHwnd(), m_bDarkMode);
SetDarkModeControl(m_ButtonSetDefault.GetSafeHwnd(), m_bDarkMode);
SetDarkModeControl(m_ButtonSetNVMe8.GetSafeHwnd(), m_bDarkMode);
SetDarkModeControl(m_ButtonSetFlashMemory.GetSafeHwnd(), m_bDarkMode);
m_ComboBenchType0.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchType1.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchType2.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchType3.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchType4.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchType5.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchType8.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchSize0.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchSize1.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchSize2.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchSize3.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchSize4.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchSize5.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchSize8.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchQueues0.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchQueues1.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchQueues2.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchQueues3.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchQueues4.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchQueues5.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchQueues8.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchThreads0.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchThreads1.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchThreads2.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchThreads3.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchThreads4.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchThreads5.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchThreads8.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
// m_ComboData.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
// m_ComboAffinity.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboMeasureTime.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboIntervalTime.SetItemHeightAll(comboHeight, m_ZoomRatio, m_FontRatio);
m_ComboBenchType0.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchType1.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchType2.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchType3.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchType4.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchType5.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchType8.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchSize0.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchSize1.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchSize2.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchSize3.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchSize4.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchSize5.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchSize8.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchQueues0.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchQueues1.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchQueues2.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchQueues3.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchQueues4.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchQueues5.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchQueues8.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchThreads0.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchThreads1.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchThreads2.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchThreads3.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchThreads4.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchThreads5.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchThreads8.SetMargin(0, 4, 0, 0, m_ZoomRatio);
// m_ComboData.SetMargin(0, 4, 0, 0, m_ZoomRatio);
// m_ComboAffinity.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboMeasureTime.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboIntervalTime.SetMargin(0, 4, 0, 0, m_ZoomRatio);
m_ComboBenchType4.EnableWindow(FALSE);
m_ComboBenchType5.EnableWindow(FALSE);
Invalidate();
}
@@ -0,0 +1,108 @@
/*---------------------------------------------------------------------------*/
// Author : hiyohiyo
// Mail : hiyohiyo@crystalmark.info
// Web : https://crystalmark.info/
// License : MIT License
/*---------------------------------------------------------------------------*/
#pragma once
#include "DialogFx.h"
#include "StaticFx.h"
#include "ButtonFx.h"
#include "ComboBoxFx.h"
class CSettingsDlg : public CDialogFx
{
DECLARE_DYNCREATE(CSettingsDlg)
#ifdef SUISHO_SHIZUKU_SUPPORT
static const int SIZE_X = 680;
static const int SIZE_Y = 416;
#else
static const int SIZE_X = 440;
static const int SIZE_Y = 356;
#endif
public:
CSettingsDlg(CWnd* pParent = NULL);
virtual ~CSettingsDlg();
enum { IDD = IDD_SETTINGS };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
virtual BOOL OnInitDialog();
virtual void OnCancel();
void UpdateDialogSize();
int GetBlockSize(CString text);
int GetType(CString text);
CStaticFx m_LabelType;
CStaticFx m_LabelSize;
CStaticFx m_LabelQueues;
CStaticFx m_LabelThreads;
CStaticFx m_LabelDefault;
CStaticFx m_LabelPeak;
CStaticFx m_LabelDemo;
CStaticFx m_LabelMeasureTime;
CStaticFx m_LabelIntervalTime;
CComboBoxFx m_ComboBenchType0;
CComboBoxFx m_ComboBenchType1;
CComboBoxFx m_ComboBenchType2;
CComboBoxFx m_ComboBenchType3;
CComboBoxFx m_ComboBenchType4;
CComboBoxFx m_ComboBenchType5;
CComboBoxFx m_ComboBenchType8;
CComboBoxFx m_ComboBenchSize0;
CComboBoxFx m_ComboBenchSize1;
CComboBoxFx m_ComboBenchSize2;
CComboBoxFx m_ComboBenchSize3;
CComboBoxFx m_ComboBenchSize4;
CComboBoxFx m_ComboBenchSize5;
CComboBoxFx m_ComboBenchSize8;
CComboBoxFx m_ComboBenchQueues0;
CComboBoxFx m_ComboBenchQueues1;
CComboBoxFx m_ComboBenchQueues2;
CComboBoxFx m_ComboBenchQueues3;
CComboBoxFx m_ComboBenchQueues4;
CComboBoxFx m_ComboBenchQueues5;
CComboBoxFx m_ComboBenchQueues8;
CComboBoxFx m_ComboBenchThreads0;
CComboBoxFx m_ComboBenchThreads1;
CComboBoxFx m_ComboBenchThreads2;
CComboBoxFx m_ComboBenchThreads3;
CComboBoxFx m_ComboBenchThreads4;
CComboBoxFx m_ComboBenchThreads5;
CComboBoxFx m_ComboBenchThreads8;
// CComboBoxFx m_ComboAffinity;
// CComboBoxFx m_ComboData;
CComboBoxFx m_ComboMeasureTime;
CComboBoxFx m_ComboIntervalTime;
CButtonFx m_ButtonSetDefault;
CButtonFx m_ButtonSetNVMe8;
CButtonFx m_ButtonSetFlashMemory;
CButtonFx m_ButtonOk;
void OnSetDefault();
void OnSetNVMe8();
void OnSetFlashMemory();
void OnOk();
void InitComboBox();
int m_BenchType[9];
int m_BenchSize[9];
int m_BenchQueues[9];
int m_BenchThreads[9];
int m_TestData;
int m_MeasureTime;
int m_IntervalTime;
DWORD m_Profile;
DECLARE_MESSAGE_MAP()
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

@@ -0,0 +1,13 @@
//
// DiskMark.RC2 - Microsoft Visual C++ で直接編集しないリソース
//
#ifdef APSTUDIO_INVOKED
#error このファイルは、Microsoft Visual C++ で編集できません。
#endif //APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
// 手動で編集されたりソースをここに追加します...
/////////////////////////////////////////////////////////////////////////////
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

@@ -0,0 +1,17 @@
(C) 2007-2026 hiyohiyo
以下に定める条件に従い、本ソフトウェアおよび関連文書のファイル(以下「ソフトウェ
ア」)の複製を取得するすべての人に対し、ソフトウェアを無制限に扱うことを無償で許
可します。これには、ソフトウェアの複製を使用、複写、変更、結合、掲載、頒布、サブ
ライセンス、および/または販売する権利、およびソフトウェアを提供する相手に同じこ
とを許可する権利も無制限に含まれます。
上記の著作権表示および本許諾表示を、ソフトウェアのすべての複製または重要な部分に
記載するものとします。
ソフトウェアは「現状のまま」で、明示であるか暗黙であるかを問わず、何らの保証もな
く提供されます。ここでいう保証とは、商品性、特定の目的への適合性、および権利非侵
害についての保証も含みますが、それに限定されるものではありません。 作者または著
作権者は、契約行為、不法行為、またはそれ以外であろうと、ソフトウェアに起因または
関連し、あるいはソフトウェアの使用またはその他の扱いによって生じる一切の請求、損
害、その他の義務について何らの責任も負わないものとします。
@@ -0,0 +1,19 @@
(C) 2007-2026 hiyohiyo
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,19 @@
Copyright (c) 2014 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Stephen Eckels
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 adzm
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Richard Yu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,26 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Use text conventions for commonly used text extensions.
*.csv text
*.ini text
*.json text
*.txt text
*.xml text
*.ps1 text
*.ps1xml text
*.psd1 text
# Denote all files that are truly binary and should not be modified.
*.dll binary
*.exe binary
*.gz binary
*.ico binary
*.jpg binary
*.lib binary
*.pdb binary
*.pdf binary
*.png binary
*.wim binary
*.zip binary
+184
View File
@@ -0,0 +1,184 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Roslyn cache directories
*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
.vs/
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# If using the old MSBuild-Integrated Package Restore, uncomment this:
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,230 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// CmdRequestCreator.cpp : Defines the entry point for the console application.
//
#include "CmdRequestCreator.h"
#include <windows.h>
#include <stdlib.h>
#include <assert.h>
#include "common.h"
#include "errors.h"
#include "CmdLineParser.h"
#include "XmlProfileParser.h"
#include "IORequestGenerator.h"
#include "ResultParser.h"
#include "XmlResultParser.h"
/*****************************************************************************/
// global variables
static HANDLE g_hAbortEvent = NULL; // handle to the 'abort' event
// it allows stopping I/O Request Generator in the middle of its work
// the results of its work will be passed to the Results Parser
static HANDLE g_hEventStarted = NULL; // event signalled to notify that the actual (measured) test is to be started
static HANDLE g_hEventFinished = NULL; // event signalled to notify that the actual test has finished
/*****************************************************************************/
BOOL WINAPI ctrlCRoutine(DWORD dwCtrlType)
{
if( CTRL_C_EVENT == dwCtrlType )
{
printf("\n*** Interrupted by Ctrl-C. Stopping I/O Request Generator. ***\n");
if( !SetEvent(g_hAbortEvent) )
{
fprintf(stderr, "Warning: Setting abort event failed (error code: %u)\n", GetLastError());
}
SetConsoleCtrlHandler(ctrlCRoutine, FALSE);
//indicate that the signal has been handled
return TRUE;
}
else
{
return FALSE;
}
}
/*****************************************************************************/
void TestStarted()
{
if( (NULL != g_hEventStarted) && !SetEvent(g_hEventStarted) )
{
fprintf(stderr, "Warning: Setting test start notification event failed (error code: %u)\n", GetLastError());
}
}
/*****************************************************************************/
void TestFinished()
{
if( (NULL != g_hEventFinished) && !SetEvent(g_hEventFinished) )
{
fprintf(stderr, "Warning: Setting test finish notification event failed (error code: %u)\n", GetLastError());
}
}
/*****************************************************************************/
/// for CrystalDiskMark
DWORD pid = 0;
int __cdecl main(int argc, const char* argv[])
{
/// for CrystalDiskMark
int totalScore = 0;
double averageLatency = 0.0;
//
// parse cmd line parameters
//
struct Synchronization synch; //sychronization structure
synch.ulStructSize = sizeof(synch);
synch.hStopEvent = NULL;
synch.hStartEvent = NULL;
CmdLineParser cmdLineParser;
Profile profile;
if (!cmdLineParser.ParseCmdLine(argc, argv, &profile, &synch, &g_SystemInformation))
{
return ERROR_PARSE_CMD_LINE;
}
// Instantiate parsers
ResultParser resultParser;
XmlResultParser xmlResultParser;
IResultParser *pResultParser = nullptr;
if (profile.GetResultsFormat() == ResultsFormat::Xml)
{
pResultParser = &xmlResultParser;
}
else
{
pResultParser = &resultParser;
}
// Profile only? If so, complete now.
if (profile.GetProfileOnly())
{
string s = pResultParser->ParseProfile(profile);
printf("%s", s.c_str());
return 0;
}
synch.pfnCallbackTestStarted = TestStarted;
synch.pfnCallbackTestFinished = TestFinished;
//
// create abort event if stop event is not explicitly provided by the user (otherwise use the stop event)
//
if (NULL == synch.hStopEvent)
{
synch.hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if( NULL == synch.hStopEvent )
{
fprintf(stderr, "Unable to create an abort event for CTRL+C\n");
//FUTURE EXTENSION: change error code
return 1;
}
}
g_hAbortEvent = synch.hStopEvent; // set abort event to either stop event provided by user or the just created event
//
// capture ctrl+c
//
if( !SetConsoleCtrlHandler(ctrlCRoutine, TRUE) )
{
fprintf(stderr, "Unable to set CTRL+C routine\n");
//FUTURE EXTENSION: change error code
return 1;
}
TraceLoggingRegister(g_hEtwProvider);
//
// call IO request generator
//
IORequestGenerator ioGenerator;
/// for CrystalDiskMark
if (!ioGenerator.GenerateRequests(profile, *pResultParser, &synch, &totalScore, &averageLatency))
// if (!ioGenerator.GenerateRequests(profile, *pResultParser, &synch))
{
if (profile.GetResultsFormat() == ResultsFormat::Xml)
{
fprintf(stderr, "\n");
}
fprintf(stderr, "Error generating I/O requests\n");
return 1;
}
TraceLoggingUnregister(g_hEtwProvider);
if( NULL != synch.hStartEvent )
{
CloseHandle(synch.hStartEvent);
}
if( NULL != synch.hStopEvent )
{
CloseHandle(synch.hStopEvent);
}
if( g_hEventStarted )
{
CloseHandle(g_hEventStarted);
}
if( NULL != g_hEventFinished )
{
CloseHandle(g_hEventFinished);
}
/// for CrystalDiskMark
CHAR name[32];
snprintf(name, 32, "CrystalDiskMark%08X", pid);
auto size = 8;
HANDLE hSharedMemory = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, NULL, size, name);
if (hSharedMemory != NULL)
{
auto pMemory = (double*)MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, NULL, NULL, size);
if (pMemory != NULL)
{
*pMemory = averageLatency;
UnmapViewOfFile(pMemory);
CloseHandle(hSharedMemory);
}
}
printf("Score: %d\n", totalScore);
printf("averageLatency: %f\n", averageLatency);
//fprintf(stderr, "%f", averageLatency);
return totalScore;
// return 0;
}
@@ -0,0 +1,19 @@
#include <windows.h>
#include "Version.h"
DISKSPD.XSD HTML "..\\XmlProfileParser\\diskspd.xsd"
#include <ntverp.h>
#define VER_FILETYPE VFT_APP
#define VER_FILESUBTYPE VFT2_UNKNOWN
#define VER_FILEDESCRIPTION_STR "DiskSpd Storage Performance Tool"
#define VER_INTERNALNAME_STR "diskspd.exe"
#undef VER_PRODUCTVERSION
#define VER_PRODUCTVERSION DISKSPD_MAJOR,DISKSPD_MINOR,DISKSPD_BUILD,DISKSPD_QFE
#undef VER_PRODUCTVERSION_STR
#define VER_PRODUCTVERSION_STR DISKSPD_NUMERIC_VERSION_STRING
#include "common.ver"
@@ -0,0 +1,73 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include "Common.h"
namespace UnitTests { class CmdLineParserUnitTests; }
class CmdLineParser
{
public:
CmdLineParser();
~CmdLineParser();
bool ParseCmdLine(const int argc, const char *argv[], Profile *pProfile, struct Synchronization *synch, SystemInformation *pSystem = nullptr);
private:
bool _ReadParametersFromCmdLine(const int argc, const char *argv[], Profile *pProfile, struct Synchronization *synch, bool& fXMLProfile);
bool _ReadParametersFromXmlFile(const char *pszPath, Profile *pProfile, vector<Target> *pvSubstTargets);
bool _ParseETWParameter(const char *arg, Profile *pProfile);
bool _ParseFlushParameter(const char *arg, MemoryMappedIoFlushMode *FlushMode );
bool _ParseAffinity(const char *arg, TimeSpan *pTimeSpan);
bool _ParseRandomDistribution(const char *arg, vector<Target>& vTargets);
void _DisplayUsageInfo(const char *pszFilename) const;
bool _GetSizeInBytes(const char *pszSize, UINT64& ullSize, const char **pszRest) const;
bool _GetRandomDataWriteBufferData(const string& sArg, UINT64& cb, string& sPath);
static bool _IsSwitchChar(const char c) { return (c == '/' || c == '-'); }
enum class ParseState {
Unknown,
True,
False,
Bad
};
DWORD _dwBlockSize; // block size; other parameters may be stated in blocks
// so the block size is needed to process them
UINT32 _ulWriteRatio; // default percentage of write requests
HANDLE _hEventStarted; // event signalled to notify that the actual (measured) test is to be started
HANDLE _hEventFinished; // event signalled to notify that the actual test has finished
friend class UnitTests::CmdLineParserUnitTests;
};
@@ -0,0 +1,38 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include <tchar.h>
#include <stdio.h>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,330 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <map>
#include <unordered_map>
#include <string>
#include <sstream>
#include <limits>
#include <cmath>
// Plain min/max macros from common headers will interfere with std::numeric_limits
#pragma push_macro("min")
#pragma push_macro("max")
#undef min
#undef max
template<typename T>
class Histogram
{
private:
mutable std::unordered_map<T, unsigned> _data;
mutable unsigned _samples;
mutable std::map<T, unsigned> _sdata;
mutable unsigned _ssamples;
// Save most recent percentile/iterator/nth-distance query. If the next is strictly >= it allows
// an efficient forward iteration through an ascending set of queries.
mutable double _lastptile;
mutable unsigned _lastptilen;
mutable decltype(_sdata.cbegin()) _lastptilepos;
// A histogram starts writable/unsealed and automatically seals after the first read operation.
// Subsequent writes which add data restart from empty.
void _SealData() const
{
if (!_data.empty())
{
_sdata.clear();
_sdata = std::map<T, unsigned>(_data.cbegin(), _data.cend());
_ssamples = _samples;
// invalid ptile > 1; first ptile query will initialize
_lastptile = 1.1;
_data.clear();
_samples = 0;
}
}
public:
Histogram()
: _samples(0),
_ssamples(0)
{}
void Clear()
{
_data.clear();
_samples = 0;
_sdata.clear();
_ssamples = 0;
}
void Add(T v)
{
_data[v]++;
_samples++;
}
void Merge(const Histogram<T> &other)
{
for (auto i : other._data)
{
_data[ i.first ] += i.second;
}
_samples += other._samples;
}
T GetMin() const
{
_SealData();
// Default low if empty
if (!_ssamples)
{
return std::numeric_limits<T>::min();
}
return _sdata.cbegin()->first;
}
T GetMax() const
{
_SealData();
// Default low if empty
if (!_ssamples)
{
return std::numeric_limits<T>::min();
}
return _sdata.crbegin()->first;
}
unsigned GetSampleBuckets() const
{
return (unsigned) (_samples ? _data.size() : _sdata.size());
}
unsigned GetSampleSize() const
{
return _samples ? _samples : _ssamples;
}
T GetPercentile(double p) const
{
if ((p < 0.0) || (p > 1.0))
{
throw std::invalid_argument("Percentile must be >= 0 and <= 1");
}
_SealData();
// Default low if empty
if (!_ssamples)
{
return std::numeric_limits<T>::min();
}
const double target = p * _ssamples;
// Default to beginning; n is the number of samples iterated over so far
unsigned n = 0;
auto pos = _sdata.cbegin();
// Resume from last?
if (p >= _lastptile)
{
n = _lastptilen;
pos = _lastptilepos;
}
while (pos != _sdata.cend())
{
if (n + pos->second >= target)
{
// Save position. Note the pre-incremented distance through the histogram
// must be saved in case next is still in the same bucket.
_lastptile = p;
_lastptilen = n;
_lastptilepos = pos;
return pos->first;
}
n += pos->second;
++pos;
}
throw std::overflow_error("overran end trying to find percentile");
}
T GetPercentile(int p) const
{
return GetPercentile(static_cast<double>(p) / 100);
}
T GetMedian() const
{
return GetPercentile(0.5);
}
double GetStdDev() const { return GetStandardDeviation(); }
double GetAvg() const { return GetMean(); }
double GetMean() const
{
_SealData();
// Default low if empty
if (!_ssamples)
{
return std::numeric_limits<T>::min();
}
double sum(0);
for (const auto i : _sdata)
{
double bucket_val =
static_cast<double>(i.first) * i.second / _ssamples;
if (sum + bucket_val < 0)
{
throw std::overflow_error("while trying to accumulate sum");
}
sum += bucket_val;
}
return sum;
}
double GetStandardDeviation() const
{
double mean(GetMean());
double ssd(0);
for (const auto i : _sdata)
{
double dev = static_cast<double>(i.first) - mean;
double sqdev = dev * dev;
ssd += i.second * sqdev;
}
return sqrt(ssd / _ssamples);
}
std::string GetHistogramCsv(const unsigned bins) const
{
return GetHistogramCsv(bins, GetMin(), GetMax());
}
std::string GetHistogramCsv(const unsigned bins, const T LOW, const T HIGH) const
{
_SealData();
// ISSUE-REVIEW
// Currently bins are defined as strictly less-than
// their upper limit, with the exception of the last
// bin. Otherwise where would I put the max value?
const double binSize = static_cast<double>((HIGH - LOW) / bins);
double limit = static_cast<double>(LOW);
std::ostringstream os;
os.precision(std::numeric_limits<T>::digits10);
auto pos = _sdata.cbegin();
unsigned cumulative = 0;
for (unsigned bin = 1; bin <= bins; ++bin)
{
unsigned count = 0;
limit += binSize;
while (pos != _sdata.end() &&
(pos->first < limit || bin == bins))
{
count += pos->second;
++pos;
}
cumulative += count;
os << limit << "," << count << "," << cumulative << std::endl;
}
return os.str();
}
std::string GetRawCsv() const
{
_SealData();
std::ostringstream os;
os.precision(std::numeric_limits<T>::digits10);
for (const auto i : _sdata)
{
os << i.first << "," << i.second << std::endl;
}
return os.str();
}
std::string GetRaw() const
{
_SealData();
std::ostringstream os;
for (const auto i : _sdata)
{
os << i.second << " " << i.first << std::endl;
}
return os.str();
}
};
#pragma pop_macro("min")
#pragma pop_macro("max")
@@ -0,0 +1,84 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#define INITGUID //Include this #define to use SystemTraceControlGuid in Evntrace.h.
#include <Evntrace.h> //ETW
#include <Winternl.h> //ntdll.dll
void PrintError(const char *format, ...);
namespace UnitTests
{
class IORequestGeneratorUnitTests;
}
class IORequestGenerator
{
public:
IORequestGenerator() :
_hNTDLL(nullptr)
{
}
//bool GenerateRequests(Profile& profile, IResultParser& resultParser, struct Synchronization *pSynch);
/// for CrystalDiskMark
bool GenerateRequests(Profile& profile, IResultParser& resultParser, struct Synchronization* pSynch, int* totalScore, double* averageLatency);
private:
struct CreateFileParameters
{
string sPath;
UINT64 ullFileSize;
bool fZeroWriteBuffers;
};
bool _GenerateRequestsForTimeSpan(const Profile& profile, const TimeSpan& timeSpan, Results& results, struct Synchronization *pSynch);
void _AbortWorkerThreads(HANDLE hStartEvent, vector<HANDLE>& vhThreads) const;
void _CloseOpenFiles(vector<HANDLE>& vhFiles) const;
DWORD _CreateDirectoryPath(const char *path) const;
bool _CreateFile(UINT64 ullFileSize, const char *pszFilename, bool fZeroBuffers, bool fVerbose) const;
bool _GetActiveGroupsAndProcs() const;
struct ETWSessionInfo _GetResultETWSession(const EVENT_TRACE_PROPERTIES *pTraceProperties) const;
bool _GetSystemPerfInfo(vector<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION>& vSPPI, bool fVerbose) const;
void _InitializeGlobalParameters();
bool _LoadDLLs();
bool _StopETW(bool fUseETW, TRACEHANDLE hTraceSession) const;
void _TerminateWorkerThreads(vector<HANDLE>& vhThreads) const;
bool _ValidateProfile(const Profile& profile) const;
vector<struct CreateFileParameters> _GetFilesToPrecreate(const Profile& profile) const;
void _MarkFilesAsCreated(Profile& profile, const vector<struct CreateFileParameters>& vFiles) const;
bool _PrecreateFiles(Profile& profile) const;
HINSTANCE volatile _hNTDLL; //handle to ntdll.dll
friend class UnitTests::IORequestGeneratorUnitTests;
};
@@ -0,0 +1,228 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "IoBucketizer.h"
#include <stdexcept>
/*
Calculating stddev using an online algorithm:
avg = sum(1..n, a[n]) / n
stddev = sqrt(sum(1..n, (a[n] - avg)^2) / n)
= sqrt(sum(1..n, a[n]^2 - 2 * a[n] * avg + avg^2) / n)
= sqrt((sum(1..n, a[n]^2) - 2 * avg * sum(1..n, a[n]) + n * avg^2) / n)
= sqrt((sum(1..n, a[n]^2) - 2 * (sum(1..n, a[n]) / n) * sum(1..n, a[n]) + n * (sum(1..n], a[n]) / n)^2) / n)
= sqrt((sum(1..n, a[n]^2) - (2 / n) * sum(1..n, a[n])^2 + (1 / n) * sum(1..n, a[n])^2) / n)
= sqrt((sum(1..n, a[n]^2) - (1 / n) * sum(1..n, a[n])^2) / n)
So if we track n, sum(a[n]) and sum(a[n]^2) we can calculate the stddev. This
is used to calculate the stddev of the latencies below.
*/
const unsigned __int64 INVALID_BUCKET_DURATION = 0;
IoBucketizer::IoBucketizer()
: _bucketDuration(INVALID_BUCKET_DURATION),
_validBuckets(0),
_totalBuckets(0)
{}
void IoBucketizer::Initialize(unsigned __int64 bucketDuration, size_t validBuckets)
{
if (_bucketDuration != INVALID_BUCKET_DURATION)
{
throw std::runtime_error("IoBucketizer has already been initialized");
}
if (bucketDuration == INVALID_BUCKET_DURATION)
{
throw std::invalid_argument("Bucket duration must be a positive integer");
}
_bucketDuration = bucketDuration;
_validBuckets = validBuckets;
_vBuckets.resize(_validBuckets);
}
void IoBucketizer::Add(unsigned __int64 ioCompletionTime, double ioDuration)
{
if (_bucketDuration == INVALID_BUCKET_DURATION)
{
throw std::runtime_error("IoBucketizer has not been initialized");
}
size_t bucketNumber = static_cast<size_t>(ioCompletionTime / _bucketDuration);
_totalBuckets = bucketNumber + 1;
if (bucketNumber >= _validBuckets)
{
return;
}
_vBuckets[bucketNumber].lfSumDuration += ioDuration;
_vBuckets[bucketNumber].lfSumSqrDuration += ioDuration * ioDuration;
if (_vBuckets[bucketNumber].ulCount == 0 ||
ioDuration < _vBuckets[bucketNumber].lfMinDuration)
{
_vBuckets[bucketNumber].lfMinDuration = ioDuration;
}
if (_vBuckets[bucketNumber].ulCount == 0 ||
ioDuration > _vBuckets[bucketNumber].lfMaxDuration)
{
_vBuckets[bucketNumber].lfMaxDuration = ioDuration;
}
_vBuckets[bucketNumber].ulCount++;
}
size_t IoBucketizer::GetNumberOfValidBuckets() const
{
return (_totalBuckets > _validBuckets ? _validBuckets : _totalBuckets);
}
unsigned int IoBucketizer::GetIoBucketCount(size_t bucketNumber) const
{
if (bucketNumber < _validBuckets)
{
return _vBuckets[bucketNumber].ulCount;
}
return 0;
}
double IoBucketizer::GetIoBucketMinDurationUsec(size_t bucketNumber) const
{
if (bucketNumber < _validBuckets)
{
return _vBuckets[bucketNumber].lfMinDuration;
}
return 0;
}
double IoBucketizer::GetIoBucketMaxDurationUsec(size_t bucketNumber) const
{
if (bucketNumber < _validBuckets)
{
return _vBuckets[bucketNumber].lfMaxDuration;
}
return 0;
}
double IoBucketizer::GetIoBucketAvgDurationUsec(size_t bucketNumber) const
{
if (bucketNumber < _validBuckets && _vBuckets[bucketNumber].ulCount != 0)
{
return _vBuckets[bucketNumber].lfSumDuration / static_cast<double>(_vBuckets[bucketNumber].ulCount);
}
return 0;
}
double IoBucketizer::GetIoBucketDurationStdDevUsec(size_t bucketNumber) const
{
if (bucketNumber < _validBuckets && _vBuckets[bucketNumber].ulCount != 0)
{
double sum_of_squares = _vBuckets[bucketNumber].lfSumSqrDuration;
double square_of_sum = _vBuckets[bucketNumber].lfSumDuration * _vBuckets[bucketNumber].lfSumDuration;
double count = static_cast<double>(_vBuckets[bucketNumber].ulCount);
double square_stddev = (sum_of_squares - (square_of_sum / count)) / count;
return sqrt(square_stddev);
}
return 0;
}
double IoBucketizer::_GetMeanIOPS() const
{
size_t numBuckets = GetNumberOfValidBuckets();
double sum = 0;
for (size_t i = 0; i < numBuckets; i++)
{
sum += static_cast<double>(_vBuckets[i].ulCount) / numBuckets;
}
return sum;
}
double IoBucketizer::GetStandardDeviationIOPS() const
{
size_t numBuckets = GetNumberOfValidBuckets();
if(numBuckets == 0)
{
return 0.0;
}
double mean = _GetMeanIOPS();
double ssd = 0;
for (size_t i = 0; i < numBuckets; i++)
{
double dev = static_cast<double>(_vBuckets[i].ulCount) - mean;
double sqdev = dev*dev;
ssd += sqdev;
}
return sqrt(ssd / numBuckets);
}
void IoBucketizer::Merge(const IoBucketizer& other)
{
if(other._vBuckets.size() > _vBuckets.size())
{
_vBuckets.resize(other._vBuckets.size());
}
for(size_t i = 0; i < other._vBuckets.size(); i++)
{
_vBuckets[i].ulCount += other._vBuckets[i].ulCount;
_vBuckets[i].lfSumDuration += other._vBuckets[i].lfSumDuration;
_vBuckets[i].lfSumSqrDuration += other._vBuckets[i].lfSumSqrDuration;
if (i >= _validBuckets ||
other._vBuckets[i].lfMinDuration < _vBuckets[i].lfMinDuration)
{
_vBuckets[i].lfMinDuration = other._vBuckets[i].lfMinDuration;
}
if (other._vBuckets[i].lfMaxDuration > _vBuckets[i].lfMaxDuration)
{
_vBuckets[i].lfMaxDuration = other._vBuckets[i].lfMaxDuration;
}
}
if (other._validBuckets > _validBuckets)
{
_validBuckets = other._validBuckets;
}
if (other._totalBuckets > _totalBuckets)
{
_totalBuckets = other._totalBuckets;
}
}
@@ -0,0 +1,73 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <vector>
class IoBucketizer
{
public:
IoBucketizer();
void Initialize(unsigned __int64 bucketDuration, size_t validBuckets);
size_t GetNumberOfValidBuckets() const;
unsigned int GetIoBucketCount(size_t bucketNumber) const;
double GetIoBucketMinDurationUsec(size_t bucketNumber) const;
double GetIoBucketMaxDurationUsec(size_t bucketNumber) const;
double GetIoBucketAvgDurationUsec(size_t bucketNumber) const;
double GetIoBucketDurationStdDevUsec(size_t bucketNumber) const;
void Add(unsigned __int64 ioCompletionTime, double ioDuration);
double GetStandardDeviationIOPS() const;
void Merge(const IoBucketizer& other);
private:
double _GetMeanIOPS() const;
struct IoBucket {
IoBucket() :
ulCount(0),
lfMinDuration(0),
lfMaxDuration(0),
lfSumDuration(0),
lfSumSqrDuration(0)
{
}
unsigned int ulCount;
double lfMinDuration;
double lfMaxDuration;
double lfSumDuration;
double lfSumSqrDuration;
};
unsigned __int64 _bucketDuration;
size_t _validBuckets;
size_t _totalBuckets;
std::vector<IoBucket> _vBuckets;
};
@@ -0,0 +1,50 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <Windows.h>
//
// OverlappedQueue is a simple class that implements a queue for OVERLAPPED elements
//
class OverlappedQueue
{
public:
OverlappedQueue(void);
void Add(OVERLAPPED *pOverlapped);
bool IsEmpty(void) const;
OVERLAPPED * Remove(void);
size_t GetCount() const;
private:
OVERLAPPED *_pHead;
OVERLAPPED *_pTail;
size_t _cItems;
};
@@ -0,0 +1,76 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include "Common.h"
namespace UnitTests
{
class ResultParserUnitTests;
}
class ResultParser : public IResultParser
{
public:
string ParseResults(const Profile& profile, const SystemInformation& system, vector<Results> vResults);
string ParseProfile(const Profile& profile);
/// for CrystalDiskMark
int GetTotalScore();
double GetAverageLatency();
private:
void _DisplayFileSize(UINT64 fsize, UINT32 align = 0);
void _DisplayETWSessionInfo(struct ETWSessionInfo sessionInfo);
void _DisplayETW(struct ETWMask ETWMask, struct ETWEventCounters EtwEventCounters);
void _Print(const char *format, ...);
void _PrintProfile(const Profile& profile);
void _PrintSystemInfo(const SystemInformation& system);
void _PrintCpuUtilization(const Results& results, const SystemInformation& system);
enum class _SectionEnum {TOTAL, READ, WRITE};
void _PrintSectionFieldNames(const TimeSpan& timeSpan);
void _PrintSectionBorderLine(const TimeSpan& timeSpan);
void _PrintSection(_SectionEnum, const TimeSpan&, const Results&);
void _PrintLatencyPercentiles(const Results&);
void _PrintLatencyChart(const Histogram<float>& readLatencyHistogram,
const Histogram<float>& writeLatencyHistogram,
const Histogram<float>& totalLatencyHistogram);
void _PrintTimeSpan(const TimeSpan &timeSpan);
void _PrintTarget(const Target &target, bool fUseThreadsPerFile, bool fUseRequestsPerFile, bool fCompletionRoutines);
void _PrintDistribution(DistributionType dT, const vector<DistributionRange>& v, char* spc);
void _PrintEffectiveDistributions(const Results& results);
void _PrintWaitStats(const Results& result);
string _sResult;
/// for CrystalDiskMark
int _totalScore;
double _averageLatency;
friend class UnitTests::ResultParserUnitTests;
};
@@ -0,0 +1,61 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <Windows.h>
// ThroughputMeter class assists in metering out throughput over
// time. The meter is started by calling Start() with the throughput
// to be simulated. GetSleepTime() returns 0 when the next IO can be issued.
// Adjust() is called to notify the ThroughputMeter about how many bytes were read/written.
class ThroughputMeter
{
public:
ThroughputMeter(void);
bool IsRunning(void) const;
void Start(DWORD cBytesPerMillisecond, DWORD dwBlockSize, DWORD dwThinkTime, DWORD dwBurstSize);
DWORD GetSleepTime(void) const;
void Adjust(size_t cb);
private:
DWORD _GetThrottleTime(void) const;
bool _fRunning; // true = throughput monitoring is on
bool _fThrottle; // true = throttling is on
bool _fThink; // true = think time is enabled
ULONGLONG _cbCompleted; // completed IO
DWORD _cbBlockSize;
DWORD _cBytesPerMillisecond; // rate of throttling
ULONGLONG _ullStartTimestamp;
ULONGLONG _ullDelayUntil; // timestamp at which the next IO can be executed
DWORD _thinkTime; // time to sleep between burst of IOs
DWORD _burstSize; // number of IOs in a burst. meaningless if think time is zero
DWORD _cIO; // count of IOs in the current burst
};
@@ -0,0 +1,52 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// versioning material. for simplicity in consumption, please ensure that the date string
// parses via the System.Datetime constructor as follows (in Powershell):
//
// [datetime] "string"
//
// this should result in a valid System.Datetime object, rendered like:
//
// Monday, June 16, 2014 12:00:00 AM
#define DISKSPD_RELEASE_TAG ""
#define DISKSPD_REVISION ""
#define DISKSPD_MAJOR 2
#define DISKSPD_MINOR 2
#define DISKSPD_BUILD 0
#define DISKSPD_QFE 0
#define DISKSPD_MAJORMINOR_VER_STR(x,y,z) #x "." #y "." #z
#define DISKSPD_MAJORMINOR_VERSION_STRING(x,y,z) DISKSPD_MAJORMINOR_VER_STR(x,y,z)
#define DISKSPD_MAJORMINOR_VERSION_STR DISKSPD_MAJORMINOR_VERSION_STRING(DISKSPD_MAJOR, DISKSPD_MINOR, DISKSPD_BUILD)
#define DISKSPD_NUMERIC_VERSION_STRING DISKSPD_MAJORMINOR_VERSION_STR DISKSPD_REVISION DISKSPD_RELEASE_TAG
#define DISKSPD_DATE_VERSION_STRING "2024/6/3"
@@ -0,0 +1,65 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <MsXml6.h>
#include "Common.h"
class XmlProfileParser
{
public:
bool ParseFile(const char *pszPath, Profile *pProfile, vector<Target> *pvSubstTargets, HMODULE hModule);
private:
HRESULT _ParseEtw(IXMLDOMDocument2 *pXmlDoc, Profile *pProfile);
HRESULT _ParseTimeSpans(IXMLDOMDocument2 *pXmlDoc, Profile *pProfile, vector<pair<string, bool>>& vSubsts);
HRESULT _ParseTimeSpan(IXMLDOMNode *pXmlNode, TimeSpan *pTimeSpan, vector<pair<string, bool>>& vSubsts);
HRESULT _ParseTargets(IXMLDOMNode *pXmlNode, TimeSpan *pTimeSpan, vector<pair<string, bool>>& vSubsts);
HRESULT _ParseRandomDataSource(IXMLDOMNode *pXmlNode, Target *pTarget);
HRESULT _ParseWriteBufferContent(IXMLDOMNode *pXmlNode, Target *pTarget);
HRESULT _ParseTarget(IXMLDOMNode *pXmlNode, Target *pTarget);
HRESULT _ParseThreadTargets(IXMLDOMNode *pXmlNode, Target *pTarget);
HRESULT _ParseThroughput(IXMLDOMNode *pXmlNode, Target *pTarget);
HRESULT _ParseThreadTarget(IXMLDOMNode *pXmlNode, ThreadTarget *pThreadTarget);
HRESULT _ParseAffinityAssignment(IXMLDOMNode *pXmlNode, TimeSpan *pTimeSpan);
HRESULT _ParseAffinityGroupAssignment(IXMLDOMNode *pXmlNode, TimeSpan *pTimeSpan);
HRESULT _ParseDistribution(IXMLDOMNode *pXmlNode, Target *pTarget);
HRESULT _SubstTarget(Target *pTarget, vector<pair<string, bool>>& vSubsts);
HRESULT _GetString(IXMLDOMNode *pXmlNode, const char *pszQuery, string *psValue) const;
HRESULT _GetUINT32(IXMLDOMNode *pXmlNode, const char *pszQuery, UINT32 *pulValue) const;
HRESULT _GetUINT64(IXMLDOMNode *pXmlNode, const char *pszQuery, UINT64 *pullValue) const;
HRESULT _GetDWORD(IXMLDOMNode *pXmlNode, const char *pszQuery, DWORD *pdwValue) const;
HRESULT _GetBool(IXMLDOMNode *pXmlNode, const char *pszQuery, bool *pfValue) const;
HRESULT _GetUINT32Attr(IXMLDOMNode *pXmlNode, const char *pszAttr, UINT32 *pulValue) const;
HRESULT _GetVerbose(IXMLDOMDocument2 *pXmlDoc, bool *pfVerbose);
HRESULT _GetProgress(IXMLDOMDocument2 *pXmlDoc, DWORD *pdwProgress);
};
@@ -0,0 +1,61 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include "Common.h"
class XmlResultParser: public IResultParser
{
public:
string ParseResults(const Profile& profile, const SystemInformation& system, vector<Results> vResults);
string ParseProfile(const Profile& profile);
/// for CrystalDiskMark
int GetTotalScore();
double GetAverageLatency();
private:
void _PrintCpuUtilization(const Results& results, const SystemInformation& system);
void _PrintETW(struct ETWMask ETWMask, struct ETWEventCounters EtwEventCounters);
void _PrintETWSessionInfo(struct ETWSessionInfo sessionInfo);
void _PrintLatencyPercentiles(const Results& results);
void _PrintTargetResults(const TargetResults& results);
void _PrintTargetLatency(const TargetResults& results);
void _PrintTargetIops(const IoBucketizer& readBucketizer, const IoBucketizer& writeBucketizer, UINT32 bucketTimeInMs);
void _PrintOverallIops(const Results& results, UINT32 bucketTimeInMs);
void _PrintIops(const IoBucketizer& readBucketizer, const IoBucketizer& writeBucketizer, UINT32 bucketTimeInMs);
void _PrintWaitStats(const ThreadResults& threadResult);
void _PrintV(const char *format, va_list listArg);
void _Print(const char *format, ...);
void _PrintInc(const char *format, ...);
void _PrintDec(const char *format, ...);
string _sResult;
UINT32 _indent = 0;
};
@@ -0,0 +1,38 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef __DISKSPD_ERRORS_H
#define __DISKSPD_ERRORS_H
#define ERROR_LOAD_LIBRARY 1 //error during LoadLibrary call
#define ERROR_GET_PROC_ADDRESS 2 //error during GetProcAddress
#define ERROR_PARSE_CMD_LINE 3 //error parsing cmd line parameters
#define ERROR_WAIT_FOR_START_SIGNAL 4 //error waiting for a signal to start work
#endif
@@ -0,0 +1,41 @@
/*
DISKSPD
Copyright(c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once
#include <windows.h>
#include <Wmistr.h> ///WNODE_HEADER
#define INITGUID //Include this #define to use SystemTraceControlGuid in Evntrace.h.
#include <Evntrace.h> //ETW
#include "Common.h"
BOOL TraceEvents();
TRACEHANDLE StartETWSession(const Profile& profile);
PEVENT_TRACE_PROPERTIES StopETWSession(TRACEHANDLE hTraceSession);
@@ -0,0 +1,329 @@
# From Setup to Start-FleetSweep for Arc Enabled Virtual Machines in HCI clusters
This is the traditional path of setting up VMFleet to deploy Arc enabled VMs on HCI clusters and running it using your desired DiskSpd parameters/flags.
## Prerequisites
Before we begin setting up VMFleet, there are a few prerequisites that you should have ready.
Ensure an HCI cluster is setup.
Ensure that you have 1 CSV per node
Within Storage Spaces Direct, CPU usage is based on the host. Therefore, it is recommended that you split the storage load by creating as many CSVs as there are host nodes. We can go ahead and create a CSV per node in the cluster.
You may run the following:
```
Get-ClusterNode |% {
New-Volume -StoragePoolFriendlyName SU1_Pool* -FriendlyName $_ -FileSystem CSVFS_ReFS -Size <DESIRED SIZE>
}
```
Ensure that you create a “collect” volume.
You may run the following:
```
New-Volume -StoragePoolFriendlyName SU1_Pool* -FriendlyName collect -FileSystem CSVFS_ReFS -Size 200GB
```
If you have ran VMFleet in the past, please ensure that prior VMFleet directories are completely removed from existing volumes.
Retrieve or install a Server Core VHDX file. If you do not have one handy, we can create a new one by following the below instructions.
Download WS2019 Server Core ISO from the public website.
Open Hyper-V Manager.
Click “New”, then “Virtual Machine”.
Navigate through the prompts and pick a location to store your VM.
Once your VM is created, boot up the VM and follow the instructions. This is where you will decide your VM password, or what we will later call, “adminpass”.
This is important as we will use this later, so make sure you write this down.
Log out of the VM, and navigate to where you stored your VM. You should find a “Virtual Hard Disks” folder. Inside, you should find your new Server Core VHDX file.
Rename it to “Base1.vhdx”.
Copy or move the file to the cluster environment that you want to run VMFleet in.
Done!
### Deployment
1. First, we need to install the new PowerShell Module from the PowerShell Gallery and then load it into our terminal. We also need to disable cache as it is not supported currently for ArcVMs. Run the following:
```
Install-Module -Name “VMFleet”
Import-Module VMFleet
Set-ClusterStorageSpacesDirect -CacheState Disabled;
```
2. Sanity Check:
Run "Get-Module VMFleet" to confirm the module exists.
Run "Get-Command -Module VMFleet" to obtain a list of functions included in the module.
We will now set up the directory structure within the “Collect” CSV created earlier. Run "Install-Fleet"
This creates the necessary VMFleet directories which include:
* Collect/control
Contains arc.json which stores Arc configuration and the scripts that the Virtual Machines continuously monitor.
* Control.ps1: the control script the VMs use to implement the control loop (what used to be called “master.ps1”).
* Run.ps1: The VMs continuously look for the most recent version of run.ps1 and runs the newly updated script (parameters).
* Collect/flag
Location where the control script drops the “go”, “pause”, and “done” flag files. Users should not need to look at these files.
* Collect/result
Location of the output files from the VMFleet test run.
* Collect/tools
DiskSpd will be preinstalled in this folder.
3. You need to create a new or use existing Resource group under the same subscription as the Resource bridge VM is under. Set-ArcConfig will take care of creating one if not already present.
4. Setup configuration required for creating Arc enabled Virtual Machines.
```
Set-ArcConfig -ResourceGroup [ENTER_RESOURCE_GROUP] -AzureRegistrationUser [ENTER_AZURE_REGUSER] -AzureRegistrationPassword [ENTER_AZURE_REGPASS]-StoragePathCsv [ENTER_CSV_PATH] -Enabled $true -StoragePathName [ENTER_StoragePath_Name] -ImageName [ENTER_Image_Name] -ResetSalt
```
-"ResourceGroup" is the resource group where ARC VMs will be deployed.
-"AzureRegistrationUser" and "AzureRegistrationPassword" are the azure account credentials.
-"StoragePathCsv" (optional) is the csv path where storage path resource will be created. If not provided, one of the existing csvs which were created earlier will be used by default.
-"StoragePathName" (optional) is the storage path name which will be used to create gallery image. If not provided, default name will be used.
-"ImageName" (optional) is the gallery image name which will be used to create Arc-enabled virtual machines. If not provided, default name will be used. Currently, only windows gallery image is the supported image type for Arc-Enabled VMs.
-"Enabled" (optional) is set to $false by default. Set to $true if Arc-enabled virtual machines are to be created.
-"ResetSalt" (optional) is a flag used to reset salt. Salt is a random 4 character (alphanumeric) used in Arc resource names for arc enabled virtual machines (for eg: vm-group-node-salt-001). In case, user wants to regenerate the salt, they can run "Set-ArcConfig -ResetSalt" which will override existing salt with a new one in the arc.json and this will be used to create new VMs. This is useful in case of multiple clusters under same subscription using same resource group on a virtual setup. A 4 character (alphanumeric) Salt will be generated by default when user runs Set-ArcConfig the first time and stored in arc.json along with other arc configs. Within Set-ArcConfig, a quick test is done to check if atleast one vm exists with same salt in the resource group. If it does, it is regenerated.
5. By default, VMs with 2GB static memory and 1 processor count will be created.
Note: Please move the VHDX file into the collect folder. CSV Cache is also turned off by default.
We will now create our “fleet” of VMs by running:
```
New-Fleet -basevhd <PATH TO VHDX> -vms [ENTER_NUM_VMS] -adminpass [ENTER_ADMINPASS] -connectuser [ENTER_NODE_USER] -connectpass [ENTER_NODE_PASS]
```
-"adminpass" is the administrator password for the Server Core Image. This is the password you set on your Virtual Machine earlier.
-"connectuser" is a domain account with access to the cluster.
-"connectpass " is the password for the above domain account.
-"vms" is the number of VM's to create per node.
6. If "vms" parameter is not provided, the default is a 1:1 subscription ratio where the Number of VMs = Number of physical cores.
[Optional] You can consider modifying the VM hardware configuration. Run
```
Set-Fleet -ProcessorCount 1 -MemoryStartupBytes 2048mb -MemoryMaximumBytes 2048mb -MemoryMinimumBytes 2048mb
```
Note:
If you specify “MemoryMaximumBytes”, you must specify “MemoryMinimumBytes”, which implies that your VMs will have dynamic memory.
If you omit “MemoryMaximumBytes” or “MemoryMinimumBytes”, it implies that your VMs will have static memory.
If MemoryStartupBytes = MemoryMinimumBytes = MemoryMaximumBytes, that also denotes static memory.
“MemoryStartupBytes” is a mandatory parameter.
### Start Running VMFleet!
7. Open 2 PowerShell terminals. In the first one, run Watch-Cluster and in the second one, run Start-Fleet. This second function will turn on all the VMs in a “paused” state.
8. At this point you can run Start-FleetSweep [ENTER_PARAMETERS] or take this time to explore and run any of the other functions!
Here is a sample sweep command to help you get started: "Start-FleetSweep -b 4 -t 8 -o 8 -w 0 -d 300 -p r"
9. Done!
### Aftermath
Once you are done running VMFleet you can run Stop-Fleet to shut down all the virtual machines or run Remove-Fleet to completely delete all the virtual machines on your environment.
# From Setup to Measure-FleetCoreWorkload
This is a new workflow for setting up VMFleet and the predefined profile workloads (General, Peak, VDI, SQL).
## Prerequisites
Before we begin setting up VMFleet, there are a few prerequisites that you should have ready.
Ensure an HCI cluster is setup.
Ensure that you have 1 CSV per node
Within Storage Spaces Direct, CPU usage is based on the host. Therefore, it is recommended that you split the storage load by creating as many CSVs as there are host nodes. We can go ahead and create a CSV per node in the cluster.
In order to be precise about the CSV size, please use our new VMFleet command: "Get-FleetVolumeEstimate"
This will output a prescribed CSV size based on different resiliency types. We recommend you select a 2-way mirrored value or 3-way mirrored value depending on your node count.
1. You may run the following: (use the CSV size from Get-FleetVolumeEstimate)
```
Get-ClusterNode |% {
New-Volume -StoragePoolFriendlyName SU1_Pool* -FriendlyName $_ -FileSystem CSVFS_ReFS -Size <DESIRED SIZE>
}
```
Ensure that you create a “collect” volume.
2. You may run the following:
```
New-Volume -StoragePoolFriendlyName SU1_Pool* -FriendlyName collect -FileSystem CSVFS_ReFS -Size 200GB
```
3. If you have ran VMFleet in the past, please ensure that prior VMFleet directories are completely removed from existing volumes.
Retrieve or install a Server Core VHDX file. If you do not have one handy, we can create a new one by following the below instructions.
Download WS2019 Server Core ISO from the public website.
Open Hyper-V Manager.
Click “New”, then “Virtual Machine”.
Navigate through the prompts and pick a location to store your VM.
Once your VM is created, boot up the VM and follow the instructions. This is where you will decide your VM password, or what we will later call, “adminpass”.
This is important as we will use this later, so make sure you write this down.
Log out of the VM, and navigate to where you stored your VM. You should find a “Virtual Hard Disks” folder. Inside, you should find your new Server Core VHDX file.
Rename it to “Base1.vhdx”.
Copy or move the file to the cluster environment that you want to run VMFleet in.
4. Done!
## Deployment
5. Lets begin deploying VMFleet. First, we need to install the new PowerShell Module from the PowerShell Gallery and then load it into the terminal. Run the following:
```
Install-Module -Name “VMFleet”
Import-Module VMFleet
Set-ClusterStorageSpacesDirect -CacheState Disabled;
```
## Sanity Check:
6. Run "Get-Module VMFleet" to confirm the module exists.
7. Run "Get-Command -Module VMFleet" to obtain a list of commands included in the module.
8. We will now set up the directory structure within the “Collect” CSV that we created earlier. Run "Install-Fleet"
9. You need to create a new or use existing Resource group under the same subscription as the Resource bridge VM is under. Set-ArcConfig will take care of creating one if not already present.
10. Setup configuration required for creating Arc enabled Virtual Machines.
```
Set-ArcConfig -ResourceGroup [ENTER_RESOURCE_GROUP] -AzureRegistrationUser [ENTER_AZURE_REGUSER] -AzureRegistrationPassword [ENTER_AZURE_REGPASS]-StoragePathCsv [ENTER_CSV_PATH] -Enabled $true -StoragePathName [ENTER_StoragePath_Name] -ImageName [ENTER_Image_Name] -ResetSalt
```
-"ResourceGroup" is the resource group where ARC VMs will be deployed.
-"AzureRegistrationUser" and "AzureRegistrationPassword" are the azure account credentials.
-"StoragePathCsv" (optional) is the csv path where storage path resource will be created. If not provided, one of the existing csvs which were created earlier will be used by default.
-"StoragePathName" (optional) is the storage path name which will be used to create gallery image. If not provided, default name will be used.
-"ImageName" (optional) is the gallery image name which will be used to create Arc-enabled virtual machines. If not provided, default name will be used.
-"Enabled" (optional) is set to $false by default. Set to $true if Arc-enabled virtual machines are to be created.
-"ResetSalt" (optional) is a flag used to reset salt. Salt is a random 4 character (alphanumeric) used in Arc resource names for arc enabled virtual machines (for eg: vm-group-node-salt-001). In case, user wants to regenerate the salt, they can run "Set-ArcConfig -ResetSalt" which will override existing salt with a new one in the arc.json and this will be used to create new VMs. This is useful in case of multiple clusters under same subscription using same resource group on a virtual setup. A 4 character (alphanumeric) Salt will be generated by default when user runs Set-ArcConfig the first time and stored in arc.json along with other arc configs. Within Set-ArcConfig, a quick test is done to check if atleast one vm exists with same salt in the resource group. If it does, it is regenerated.
11. By default, VMs with 2GB static memory and 1 processor count will be created.
Note: Please move the VHDX file into the collect folder. CSV Cache is also turned off by default.
We will now create our “fleet” of VMs by running:
```
New-Fleet -basevhd <PATH TO VHDX> -vms [ENTER_NUM_VMS] -adminpass [ENTER_ADMINPASS] -connectuser [ENTER_NODE_USER] -connectpass [ENTER_NODE_PASS]
```
-"adminpass" is the administrator password for the Server Core Image. This is the password you set on your Virtual Machine earlier.
-"connectuser" is a domain account with access to the cluster.
-"connectpass " is the password for the above domain account.
-"vms" is the number of VM's to create per node.
12. Measure-FleetCoreWorkload also collects diagnostic data (Get-SDDCDiagnosticInfo). Therefore, before running the command, we must also install the NuGet Package if you have not previously done so. In doing so, we also need to temporairly set the PSGallery as a trusted repository source (Note: This will temporarily relax the security boundary).
```
$repo = Get-PSRepository -Name PSGallery
if ($null -eq $repo) { Write-Host "The PSGallery is not configured on this system, please address this before continuing" }
else {
if ($repo.InstallationPolicy -ne 'Trusted') {
Write-Host "Setting the PSGallery repository to Trusted, original InstallationPolicy: $($repo.InstallationPolicy)"
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
}
### Installing the pre-requisite modules
Install-PackageProvider NuGet -Force
Install-Module -Name PrivateCloud.DiagnosticInfo -Force
Install-Module -Name MSFT.Network.Diag -Force
if ($repo.InstallationPolicy -ne 'Trusted') {
Write-Host "Resetting the PSGallery repository to $($repo.InstallationPolicy)"
Set-PSRepository -Name PSGallery -InstallationPolicy $repo.InstallationPolicy
}
}
```
## Run Measure-FleetCoreWorkload!
13. We can now run Measure-FleetCoreWorkload. Running the command below will automatically run all 4 workloads (General, Peak, VDI, SQL) and place the individual outputs in the result directory. IMPORTANT: If you plan on running another test, please clear the result directory.
```
Measure-FleetCoreWorkload
```
14. Congratulations! Youre done! All you need to do is wait for the test to complete.
Note: If you ever run into an error and need to rerun Measure-FleetCoreWorkload, dont be afraid to do so! It is smart enough to pick up from where it last stopped and continue the test without starting from scratch.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,728 @@
Describe "TestModulePresent" {
BeforeAll {
$script:e = $null
}
if (Test-Path .\VMFleet.psd1)
{
It "ShouldLoad-Local" {
{ Import-Module .\VMFleet.psd1 -Force -ErrorVariable script:e } | Should Not Throw
$script:e | Should BeNullOrEmpty Because "this should be successful"
}
}
else
{
It "ModuleExists-Installed" {
Get-Module VMFleet -ListAvailable -ErrorVariable script:e | Should Not BeNullOrEmpty Because "module should be installed on system"
$script:e | Should BeNullOrEmpty Because "this should be successful"
}
It "ShouldLoad-Installed" {
{ Import-Module VMFleet -Force -ErrorVariable script:e } | Should Not Throw
$script:e | Should BeNullOrEmpty Because "this should be successful"
}
}
It "ShouldBeLoaded" {
Get-Module VMFleet -ErrorVariable script:e | Should Not BeNullOrEmpty Because "module should now be loaded"
$script:e | Should BeNullOrEmpty Because "this should be successful"
}
}
InModuleScope VMFleet {
Describe "GetDistributedShift" {
BeforeAll {
$a = @('a', 'b', 'c', 'd', 'e')
$b = @('f', 'g', 'h', 'i', 'j')
$c = @('k', 'l', 'm', 'n', 'o')
$d = @('p', 'q', 'r', 's', 't')
$bad = @('z')
$a20 = 1..20 |% { "a$_" }
$b20 = 1..20 |% { "b$_" }
$c20 = 1..20 |% { "c$_" }
$d20 = 1..20 |% { "d$_" }
}
It "ShouldRequireListOfLists" {
GetDistributedShift -Group $a -N 1 | Should Throw
}
It "ShouldRequireMoreThanOne" {
GetDistributedShift -Group @($a) -N 1 | Should Throw
}
It "ShouldRequireAllSameSize" {
GetDistributedShift -Group $a,$b,$bad -N 1 | Should Throw
}
It "ShouldRequirePositiveRotation" {
GetDistributedShift -Group $a,$b -N 0 | Should Throw
}
It "ShouldNotShiftTooMany" {
GetDistributedShift -Group $a,$b -N 6 | Should Throw
}
#
# Two group rotations
#
It "Rotate2-1" {
{ GetDistributedShift -Group $a,$b -N 1 } | Should Not Throw
$a1, $b1 = GetDistributedShift -Group $a,$b -N 1
$a1.Count | Should Be 5
$b1.Count | Should Be 5
($a1 -join '') | Should Be "abcdj"
($b1 -join '') | Should Be "fghie"
}
It "Rotate2-2" {
{ GetDistributedShift -Group $a,$b -N 2 } | Should Not Throw
$a1, $b1 = GetDistributedShift -Group $a,$b -N 2
$a1.Count | Should Be 5
$b1.Count | Should Be 5
($a1 -join '') | Should Be "abcij"
($b1 -join '') | Should Be "fghde"
}
It "Rotate2-3" {
{ GetDistributedShift -Group $a,$b -N 3 } | Should Not Throw
$a1, $b1 = GetDistributedShift -Group $a,$b -N 3
$a1.Count | Should Be 5
$b1.Count | Should Be 5
($a1 -join '') | Should Be "abhij"
($b1 -join '') | Should Be "fgcde"
}
It "Rotate2-4" {
{ GetDistributedShift -Group $a,$b -N 4 } | Should Not Throw
$a1, $b1 = GetDistributedShift -Group $a,$b -N 4
$a1.Count | Should Be 5
$b1.Count | Should Be 5
($a1 -join '') | Should Be "aghij"
($b1 -join '') | Should Be "fbcde"
}
It "Rotate2-5" {
{ GetDistributedShift -Group $a,$b -N 5 } | Should Not Throw
$a1, $b1 = GetDistributedShift -Group $a,$b -N 5
$a1.Count | Should Be 5
$b1.Count | Should Be 5
($a1 -join '') | Should Be "fghij"
($b1 -join '') | Should Be "abcde"
}
#
# Three group rotations
#
It "Rotate3-1" {
{ GetDistributedShift -Group $a,$b,$c -N 1 } | Should Not Throw
$a1, $b1, $c1 = GetDistributedShift -Group $a,$b,$c -N 1
$a1.Count | Should Be 5
$b1.Count | Should Be 5
$c1.Count | Should Be 5
($a1 -join '') | Should Be "abcdo"
($b1 -join '') | Should Be "fghie"
($c1 -join '') | Should Be "klmnj"
}
It "Rotate3-2" {
{ GetDistributedShift -Group $a,$b,$c -N 2 } | Should Not Throw
$a1, $b1, $c1 = GetDistributedShift -Group $a,$b,$c -N 2
$a1.Count | Should Be 5
$b1.Count | Should Be 5
$c1.Count | Should Be 5
($a1 -join '') | Should Be "abcio"
($b1 -join '') | Should Be "fghne"
($c1 -join '') | Should Be "klmdj"
}
It "Rotate3-3" {
{ GetDistributedShift -Group $a,$b,$c -N 3 } | Should Not Throw
$a1, $b1, $c1 = GetDistributedShift -Group $a,$b,$c -N 3
$a1.Count | Should Be 5
$b1.Count | Should Be 5
$c1.Count | Should Be 5
($a1 -join '') | Should Be "abmio"
($b1 -join '') | Should Be "fgcne"
($c1 -join '') | Should Be "klhdj"
}
It "Rotate3-4" {
{ GetDistributedShift -Group $a,$b,$c -N 4 } | Should Not Throw
$a1, $b1, $c1 = GetDistributedShift -Group $a,$b,$c -N 4
$a1.Count | Should Be 5
$b1.Count | Should Be 5
$c1.Count | Should Be 5
($a1 -join '') | Should Be "agmio"
($b1 -join '') | Should Be "flcne"
($c1 -join '') | Should Be "kbhdj"
}
It "Rotate3-5" {
{ GetDistributedShift -Group $a,$b,$c -N 5 } | Should Not Throw
$a1, $b1, $c1 = GetDistributedShift -Group $a,$b,$c -N 5
$a1.Count | Should Be 5
$b1.Count | Should Be 5
$c1.Count | Should Be 5
($a1 -join '') | Should Be "kgmio"
($b1 -join '') | Should Be "alcne"
($c1 -join '') | Should Be "fbhdj"
}
It "RotateLarge4-1" {
{ GetDistributedShift -Group $a20,$b20,$c20,$d20 -N 1 } | Should Not Throw
$g = GetDistributedShift -Group $a20,$b20,$c20,$d20 -N 1
# note last group rotates 1
$g[0] -join '' | Should Be "a1a2a3a4a5a6a7a8a9a10a11a12a13a14a15a16a17a18a19d20"
$g[1] -join '' | Should Be "b1b2b3b4b5b6b7b8b9b10b11b12b13b14b15b16b17b18b19a20"
$g[2] -join '' | Should Be "c1c2c3c4c5c6c7c8c9c10c11c12c13c14c15c16c17c18c19b20"
$g[3] -join '' | Should Be "d1d2d3d4d5d6d7d8d9d10d11d12d13d14d15d16d17d18d19c20"
}
It "RotateLarge4-2" {
{ GetDistributedShift -Group $a20,$b20,$c20,$d20 -N 2 } | Should Not Throw
$g = GetDistributedShift -Group $a20,$b20,$c20,$d20 -N 2
# note last group rotates 1, next 2
$g[0] -join '' | Should Be "a1a2a3a4a5a6a7a8a9a10a11a12a13a14a15a16a17a18c19d20"
$g[1] -join '' | Should Be "b1b2b3b4b5b6b7b8b9b10b11b12b13b14b15b16b17b18d19a20"
$g[2] -join '' | Should Be "c1c2c3c4c5c6c7c8c9c10c11c12c13c14c15c16c17c18a19b20"
$g[3] -join '' | Should Be "d1d2d3d4d5d6d7d8d9d10d11d12d13d14d15d16d17d18b19c20"
}
It "RotateLarge4-3" {
{ GetDistributedShift -Group $a20,$b20,$c20,$d20 -N 3 } | Should Not Throw
$g = GetDistributedShift -Group $a20,$b20,$c20,$d20 -N 3
# note last group rotates 1, then 2, 3
$g[0] -join '' | Should Be "a1a2a3a4a5a6a7a8a9a10a11a12a13a14a15a16a17b18c19d20"
$g[1] -join '' | Should Be "b1b2b3b4b5b6b7b8b9b10b11b12b13b14b15b16b17c18d19a20"
$g[2] -join '' | Should Be "c1c2c3c4c5c6c7c8c9c10c11c12c13c14c15c16c17d18a19b20"
$g[3] -join '' | Should Be "d1d2d3d4d5d6d7d8d9d10d11d12d13d14d15d16d17a18b19c20"
}
It "RotateLarge4-4" {
{ GetDistributedShift -Group $a20,$b20,$c20,$d20 -N 4 } | Should Not Throw
$g = GetDistributedShift -Group $a20,$b20,$c20,$d20 -N 4
# note last group rotates 1, then 2, 3, and back to 1
$g[0] -join '' | Should Be "a1a2a3a4a5a6a7a8a9a10a11a12a13a14a15a16d17b18c19d20"
$g[1] -join '' | Should Be "b1b2b3b4b5b6b7b8b9b10b11b12b13b14b15b16a17c18d19a20"
$g[2] -join '' | Should Be "c1c2c3c4c5c6c7c8c9c10c11c12c13c14c15c16b17d18a19b20"
$g[3] -join '' | Should Be "d1d2d3d4d5d6d7d8d9d10d11d12d13d14d15d16c17a18b19c20"
}
}
Describe "FilterObject" {
BeforeAll {
$o12 = [PSCustomObject]@{
K1 = 1
K2 = 2
}
$o13 = [PSCustomObject]@{
K1 = 1
K2 = 3
}
}
It "PassWithEmpty" {
$o12 | FilterObject -Filter @{} | Should Not BeNullOrEmpty
}
It "PassWithOneK" {
$o12 | FilterObject -Filter @{ K1 = 1 } | Should Not BeNullOrEmpty
}
It "PassWithTwoK" {
$o12 | FilterObject -Filter @{ K1 = 1; K2 = 2 } | Should Not BeNullOrEmpty
}
It "PassWithOneKDiffType" {
$o12 | FilterObject -Filter @{ K1 = '1' } | Should Not BeNullOrEmpty
}
It "PassWithTwoKDiffType" {
$o12 | FilterObject -Filter @{ K1 = '1'; K2 = '2' } | Should Not BeNullOrEmpty
}
It "NotPassMismatchSameType" {
$o12 | FilterObject -Filter @{ K1 = 2 } | Should BeNullOrEmpty
}
It "NotPassMismatchDiffType" {
$o12 | FilterObject -Filter @{ K1 = '2' } | Should BeNullOrEmpty
}
It "ShouldPassMultipleMatch" {
$r = @($o12,$o12 | FilterObject -Filter @{ K1 = 1 })
$r.Count | Should Be 2
}
It "ShouldPassTheMatch" {
$r = @($o12,$o13 | FilterObject -Filter @{ K2 = 2 })
$r.Count | Should Be 1
$r.K1 | Should Be 1
$r.K2 | Should Be 2
}
}
}
Describe "SetFleetProfile" {
BeforeAll {
It "ShouldBeExpectedSqlProfile" {
{ Get-FleetprofileXml -Name SQL } | Should Not Throw
$x = Get-FleetprofileXml -Name SQL
$x.Profile.TimeSpans.TimeSpan.Targets.Target[0].Throughput.InnerText | Should Be 1500
$x.Profile.TimeSpans.TimeSpan.Targets.Target[1].Throughput.InnerText | Should Be 300
}
$x = Get-FleetprofileXml -Name SQL
$oWarmup = $x.Profile.TimeSpans.TimeSpan.Warmup
$oDuration = $x.Profile.TimeSpans.TimeSpan.Duration
$oCooldown = $x.Profile.TimeSpans.TimeSpan.Cooldown
}
It "ShouldSetByParam" {
{ Set-FleetProfile -ProfileXml $x -Throughput 1000 } | Should Not Throw
$xn = Set-FleetProfile -ProfileXml $x -Throughput 1000
# original composition is 1500*4 threads + 300*1 thread = 6300
# 1000 * 6000/6300 / 4 threads = 238
# 1000 * 300/6300 / 1 thread = 48
$xn.Profile.TimeSpans.TimeSpan.Targets.Target[0].Throughput.InnerText | Should Be 238
$xn.Profile.TimeSpans.TimeSpan.Targets.Target[1].Throughput.InnerText | Should Be 48
}
It "ShouldSetByPipeline" {
{ $x | Set-FleetProfile -Throughput 1000 } | Should Not Throw
$xn = $x | Set-FleetProfile -Throughput 1000
$xn.Profile.TimeSpans.TimeSpan.Targets.Target[0].Throughput.InnerText | Should Be 238
$xn.Profile.TimeSpans.TimeSpan.Targets.Target[1].Throughput.InnerText | Should Be 48
}
It "ShouldSetUnbounded" {
{ $x | Set-FleetProfile -Throughput 0 } | Should Not Throw
$xn = $x | Set-FleetProfile -Throughput 0
$xn.Profile.TimeSpans.TimeSpan.ThreadCount | Should be 5
$xn.Profile.TimeSpans.TimeSpan.RequestCount | Should be 32
$xn.Profile.TimeSpans.SelectNodes("TimeSpan/Targets/Target/ThreadsPerFile") | Should BeNullOrEmpty
$xn.Profile.TimeSpans.SelectNodes("TimeSpan/Targets/Target/RequestCount") | Should BeNullOrEmpty
$xn.Profile.Timespans.TimeSpan.Targets.Target[1].InterlockedSequential | Should Be 'true'
}
It "ShouldSetWarmup" {
$oWarmup | Should Not Be 33
{ $x | Set-FleetProfile -Warmup 33 } | Should Not Throw
$xn = $x | Set-FleetProfile -Warmup 33
$xn.Profile.TimeSpans.TimeSpan.Warmup | Should Be 33
$xn.Profile.TimeSpans.TimeSpan.Duration | Should Be $oDuration
$xn.Profile.TimeSpans.TimeSpan.Cooldown | Should Be $oCooldown
}
It "ShouldSetDuration" {
$oDuration | Should Not Be 33
{ $x | Set-FleetProfile -Duration 33 } | Should Not Throw
$xn = $x | Set-FleetProfile -Duration 33
$xn.Profile.TimeSpans.TimeSpan.Warmup | Should Be $oWarmup
$xn.Profile.TimeSpans.TimeSpan.Duration | Should Be 33
$xn.Profile.TimeSpans.TimeSpan.Cooldown | Should Be $oCooldown
}
It "ShouldSetCooldown" {
$oCooldown | Should Not Be 33
{ $x | Set-FleetProfile -Cooldown 33 } | Should Not Throw
$xn = $x | Set-FleetProfile -Cooldown 33
$xn.Profile.TimeSpans.TimeSpan.Warmup | Should Be $oWarmup
$xn.Profile.TimeSpans.TimeSpan.Duration | Should Be $oDuration
$xn.Profile.TimeSpans.TimeSpan.Cooldown | Should Be 33
}
}
Describe "GetFleetProfileXml" {
It "HasPeak" {
{ $peak = Get-FleetProfileXml -Name Peak -BlockSize 8KB -WriteRatio 0 } | Should Not Throw
$peak = Get-FleetProfileXml -Name Peak -BlockSize 8KB -WriteRatio 0
$peak | Should Not BeNullOrEmpty
}
It "PeakDoesNotDefineBaseMax" {
$peak = Get-FleetProfileXml -Name Peak -BlockSize 8KB -WriteRatio 0
$peak.SelectNodes('Profile/TimeSpans/TimeSpan/Targets/Target/BaseFileOffset') | Should BeNullOrEmpty
$peak.SelectNodes('Profile/TimeSpans/TimeSpan/Targets/Target/MaxFileSize') | Should BeNullOrEmpty
}
It "PeakShouldAcceptBase" {
$peak = Get-FleetProfileXml -Name Peak -BlockSize 8KB -WriteRatio 0 -BaseOffset 1GB
$peak.SelectNodes('Profile/TimeSpans/TimeSpan/Targets/Target/MaxFileSize') | Should BeNullOrEmpty
$n = $peak.SelectNodes('Profile/TimeSpans/TimeSpan/Targets/Target/BaseFileOffset')
$n | Should Not BeNullOrEmpty
$n.Count | Should Be 1
$n.Item(0).InnerText | Should Be ([string] 1GB)
}
It "PeakShouldAcceptMax" {
$peak = Get-FleetProfileXml -Name Peak -BlockSize 8KB -WriteRatio 0 -MaxOffset 2GB
$peak.SelectNodes('Profile/TimeSpans/TimeSpan/Targets/Target/BaseFileOffset') | Should BeNullOrEmpty
$n = $peak.SelectNodes('Profile/TimeSpans/TimeSpan/Targets/Target/MaxFileSize')
$n | Should Not BeNullOrEmpty
$n.Count | Should Be 1
$n.Item(0).InnerText | Should Be ([string] 2GB)
}
It "PeakShouldAcceptBaseMax" {
$peak = Get-FleetProfileXml -Name Peak -BlockSize 8KB -WriteRatio 0 -BaseOffset 1GB -MaxOffset 2GB
$n = $peak.SelectNodes('Profile/TimeSpans/TimeSpan/Targets/Target/BaseFileOffset')
$n | Should Not BeNullOrEmpty
$n.Count | Should Be 1
$n.Item(0).InnerText | Should Be ([string] 1GB)
$n = $peak.SelectNodes('Profile/TimeSpans/TimeSpan/Targets/Target/MaxFileSize')
$n | Should Not BeNullOrEmpty
$n.Count | Should Be 1
$n.Item(0).InnerText | Should Be ([string] 2GB)
}
It "PeakShouldAcceptThreads" {
$peak = Get-FleetProfileXml -Name Peak -BlockSize 8KB -WriteRatio 0 -ThreadsPerTarget 2
$n = $peak.SelectNodes('Profile/TimeSpans/TimeSpan/Targets/Target/ThreadsPerFile')
$n | Should Not BeNullOrEmpty
$n.Count | Should Be 1
$n.Item(0).InnerText | Should Be ([string] 2)
}
}
InModuleScope VMFleet {
Describe "GetNextSplit" {
It "ShouldBeLargest@End" {
$o = [PSCustomObject]@{
Value = 0
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 5
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 15
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 40
CutoffType =[CutoffType]::No
}
$p1, $p2 = GetNextSplit $o 'Value' -OrderBy 'Value'
$p1.Value | Should Be 40
$p2.Value | Should Be 15
}
It "ShouldBeLargest@Begin" {
$o = [PSCustomObject]@{
Value = 40
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 5
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 15
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 0
CutoffType =[CutoffType]::No
}
$p1, $p2 = GetNextSplit $o 'Value' -OrderBy 'Value'
$p1.Value | Should Be 40
$p2.Value | Should Be 15
}
It "ShouldBeFirstOfEqual" {
$o = [PSCustomObject]@{
Value = 0
Order = 0
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 10
Order = 1
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 20
Order = 2
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 30
Order = 3
CutoffType =[CutoffType]::No
}
$p1, $p2 = GetNextSplit $o 'Value' -OrderBy 'Value'
$p1.Value | Should Be 10
$p2.Value | Should Be 0
}
It "ShouldRespectOrder" {
$o = [PSCustomObject]@{
Value = 0
Order = 0
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 10
Order = 2
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 20
Order = 3
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 30
Order = 1
CutoffType =[CutoffType]::No
}
$p1, $p2 = GetNextSplit $o 'Value' -OrderBy 'Order'
$p1.Value | Should Be 30
$p2.Value | Should Be 0
}
It "ShouldRespectCutoff" {
$o = [PSCustomObject]@{
Value = 0
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 10
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 30
CutoffType =[CutoffType]::Scale
},
[PSCustomObject]@{
Value = 60
CutoffType =[CutoffType]::Scale
}
$p1, $p2 = GetNextSplit $o 'Value' -OrderBy 'Value'
$p1.Value | Should Be 30
$p2.Value | Should Be 10
}
It "ShouldRespectCutoffOrdered" {
$o = [PSCustomObject]@{
Value = 0
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 30
CutoffType =[CutoffType]::Scale
},
[PSCustomObject]@{
Value = 10
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 60
CutoffType =[CutoffType]::Scale
}
$p1, $p2 = GetNextSplit $o 'Value' -OrderBy 'Value'
$p1.Value | Should Be 30
$p2.Value | Should Be 10
}
}
Describe "GetUpperAnchor" {
It "ShouldReturnFinalIfNotCutoff" {
$o = [PSCustomObject]@{
Value = 0
Order = 0
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 10
Order = 2
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 20
Order = 3
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 30
Order = 1
CutoffType =[CutoffType]::No
}
$p1,$p2 = GetUpperAnchor $o -OrderBy 'Order'
$p1.Value | Should Be 20
$p2.Value | Should Be 10
}
It "ShouldReturnFirstCutoff" {
$o = [PSCustomObject]@{
Value = 0
Order = 0
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 10
Order = 2
CutoffType =[CutoffType]::Scale
},
[PSCustomObject]@{
Value = 20
Order = 3
CutoffType =[CutoffType]::No
},
[PSCustomObject]@{
Value = 30
Order = 1
CutoffType =[CutoffType]::No
}
$p1,$p2 = GetUpperAnchor $o -OrderBy 'Order'
$p1.Value | Should Be 10
$p2.Value | Should Be 30
}
}
Describe "IsProfileThroughputLimited" {
It "PeakIsNot" {
$x = Get-FleetProfileXml -Name Peak -BlockSize 4KB -WriteRatio 0
IsProfileThroughputLimited -ProfileXml $x | Should Be $false
}
It "SqlIs" {
$x = Get-FleetProfileXml -Name Sql
IsProfileThroughputLimited -ProfileXml $x | Should Be $true
}
}
Describe "IsProfileSingleTimespan" {
It "PeakIs" {
$x = Get-FleetProfileXml -Name Peak -BlockSize 4KB -WriteRatio 0
IsProfileSingleTimespan -ProfileXml $x | Should Be $true
}
}
Describe "IsProfileSingleTarget" {
It "PeakIs" {
$x = Get-FleetProfileXml -Name Peak -BlockSize 4KB -WriteRatio 0
IsProfileSingleTarget -ProfileXml $x | Should Be $true
}
It "SqlIsNot" {
$x = Get-FleetProfileXml -Name Sql
IsProfileSingleTarget -ProfileXml $x | Should Be $false
}
}
Describe "GetFleetProfileFootprint" {
BeforeAll {
$sql = Get-FleetProfileXml -Name SQL
$vdi = Get-FleetProfileXml -Name VDI
}
It "CheckVDI" {
$vdi | Should Not BeNullOrEmpty
$f = GetFleetProfileFootprint -ProfileXml $vdi
$f.Count | Should Be 1
$f['*1'].BaseOffset | Should Be 0
$f['*1'].MaxOffset | Should Be (10GB)
}
It "CheckVDIRead" {
$vdi | Should Not BeNullOrEmpty
$f = GetFleetProfileFootprint -ProfileXml $vdi -Read
$f.Count | Should Be 1
$f['*1'].BaseOffset | Should Be 0
$f['*1'].MaxOffset | Should Be (8GB)
}
It "CheckSQL" {
$sql | Should Not BeNullOrEmpty
$f = GetFleetProfileFootprint -ProfileXml $sql
$f.Count | Should Be 1
$f['*1'].BaseOffset | Should Be 0
$f['*1'].MaxOffset | Should Be 0
}
It "CheckSQLRead" {
$sql | Should Not BeNullOrEmpty
$f = GetFleetProfileFootprint -ProfileXml $sql -Read
$f.Count | Should Be 1
$f['*1'].BaseOffset | Should Be (5GB)
$f['*1'].MaxOffset | Should Be 0
}
}
Describe "TimespanToString" {
BeforeAll {
$t0 = [datetime] '7/31/1996 12:00PM'
}
It "Seconds" {
TimespanToString ($t0.AddMilliseconds(1500) - $t0) | Should Be "01.5s"
}
It "Minutes" {
TimespanToString ($t0.AddMinutes(15) - $t0) | Should Be "15m:00.0s"
}
It "Hours" {
TimespanToString ($t0.AddHours(15) - $t0) | Should Be "15h:00m:00.0s"
}
It "Days" {
TimespanToString ($t0.AddDays(15) - $t0) | Should Be "15d.00h:00m:00.0s"
}
}
}

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