From 1eef6e3d63a57b5853a284621f2200bd06ccad16 Mon Sep 17 00:00:00 2001 From: driver1998 Date: Mon, 31 Aug 2020 11:03:55 +0800 Subject: [PATCH] v1.0.5 Release Broken RPIQ detection Tray Icon with temperature monitor --- PiMon.sln | 6 ++ src/PiMon.rc | 25 +++-- src/PiMon.vcxproj | 97 ++++++++++++++++++ src/PiMon.vcxproj.filters | 30 ++++++ src/listview.c | 106 +++++++++++++++++++ src/listview.h | 16 +++ src/mailbox.c | 202 ++++++++++++++++++++++++++++++++++++ src/mailbox.h | 207 ++----------------------------------- src/main.c | Bin 18498 -> 23548 bytes src/reg.c | 70 +++++++++++++ src/reg.h | 20 ++++ src/resource.h | 14 +++ src/tray.c | 102 ++++++++++++++++++ src/tray.h | 13 +++ src/utils.c | 35 +++++++ src/utils.h | 211 +------------------------------------- src/version.h | 8 ++ 17 files changed, 750 insertions(+), 412 deletions(-) create mode 100644 src/listview.c create mode 100644 src/listview.h create mode 100644 src/mailbox.c create mode 100644 src/reg.c create mode 100644 src/reg.h create mode 100644 src/resource.h create mode 100644 src/tray.c create mode 100644 src/tray.h create mode 100644 src/utils.c create mode 100644 src/version.h diff --git a/PiMon.sln b/PiMon.sln index 0b02d7c..8f8518d 100644 --- a/PiMon.sln +++ b/PiMon.sln @@ -9,18 +9,24 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM Debug|ARM64 = Debug|ARM64 + Debug|Win32 = Debug|Win32 Release|ARM = Release|ARM Release|ARM64 = Release|ARM64 + Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {4A8C24DD-C156-4607-9054-B8D43A541421}.Debug|ARM.ActiveCfg = Debug|ARM {4A8C24DD-C156-4607-9054-B8D43A541421}.Debug|ARM.Build.0 = Debug|ARM {4A8C24DD-C156-4607-9054-B8D43A541421}.Debug|ARM64.ActiveCfg = Debug|ARM64 {4A8C24DD-C156-4607-9054-B8D43A541421}.Debug|ARM64.Build.0 = Debug|ARM64 + {4A8C24DD-C156-4607-9054-B8D43A541421}.Debug|Win32.ActiveCfg = Debug|Win32 + {4A8C24DD-C156-4607-9054-B8D43A541421}.Debug|Win32.Build.0 = Debug|Win32 {4A8C24DD-C156-4607-9054-B8D43A541421}.Release|ARM.ActiveCfg = Release|ARM64 {4A8C24DD-C156-4607-9054-B8D43A541421}.Release|ARM.Build.0 = Release|ARM64 {4A8C24DD-C156-4607-9054-B8D43A541421}.Release|ARM64.ActiveCfg = Release|ARM64 {4A8C24DD-C156-4607-9054-B8D43A541421}.Release|ARM64.Build.0 = Release|ARM64 + {4A8C24DD-C156-4607-9054-B8D43A541421}.Release|Win32.ActiveCfg = Release|Win32 + {4A8C24DD-C156-4607-9054-B8D43A541421}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/PiMon.rc b/src/PiMon.rc index cb8299e..04c5355 100644 --- a/src/PiMon.rc +++ b/src/PiMon.rc @@ -1,11 +1,24 @@ #include +#include "resource.h" +#include "version.h" -10 ICON DISCARDABLE "icon.ico" +IDI_MAIN ICON "icon.ico" + +IDM_TRAY MENU +BEGIN + POPUP "TRAY_POPUP" + BEGIN + MENUITEM "Always on &Top", IDM_ALWAYS_TOP + MENUITEM "&About..." , IDM_ABOUT + MENUITEM SEPARATOR + MENUITEM "&Exit" , IDM_EXIT + END +END VS_VERSION_INFO VERSIONINFO -FILEVERSION 1,0,0,0 -PRODUCTVERSION 1,0,0,0 +FILEVERSION PIMON_FILE_VERSION +PRODUCTVERSION PIMON_FILE_VERSION FILEOS VOS_NT FILESUBTYPE VFT2_UNKNOWN FILETYPE VFT_APP @@ -16,12 +29,12 @@ BEGIN BEGIN VALUE "CompanyName", "driver1998\0" VALUE "FileDescription", "PiMon\0" - VALUE "FileVersion", "1.0\0" + VALUE "FileVersion", PIMON_VERSION "\0" VALUE "InternalName", "PiMon\0" - VALUE "LegalCopyright", "Copyright (c) 2020 driver1998\0" + VALUE "LegalCopyright", "Copyright (c) driver1998\0" VALUE "OriginalFilename", "PiMon.exe\0" VALUE "ProductName", "PiMon\0" - VALUE "ProductVersion", "1.0\0" + VALUE "ProductVersion", PIMON_VERSION "\0" END END BLOCK "VarFileInfo" diff --git a/src/PiMon.vcxproj b/src/PiMon.vcxproj index ae477bc..9099d11 100644 --- a/src/PiMon.vcxproj +++ b/src/PiMon.vcxproj @@ -9,6 +9,10 @@ Debug ARM64 + + Debug + Win32 + Release ARM @@ -17,6 +21,10 @@ Release ARM64 + + Release + Win32 + true @@ -27,9 +35,15 @@ true + + true + true + + true + 15.0 {4A8C24DD-C156-4607-9054-B8D43A541421} @@ -50,6 +64,12 @@ Unicode v142 + + Application + true + Unicode + v142 + Application false @@ -64,6 +84,13 @@ Unicode v142 + + Application + false + true + Unicode + v142 + @@ -75,12 +102,18 @@ + + + + + + true @@ -90,6 +123,10 @@ true true + + true + true + false true @@ -98,6 +135,10 @@ false true + + false + true + NotUsing @@ -140,6 +181,27 @@ PiMon.exe.manifest + + + NotUsing + Level3 + Disabled + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Windows + true + comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + false + PerMonitorHighDPIAware + PiMon.exe.manifest + + NotUsing @@ -190,13 +252,48 @@ PiMon.exe.manifest + + + NotUsing + Level3 + MaxSpeed + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + true + true + true + comctl32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + false + PerMonitorHighDPIAware + PiMon.exe.manifest + + + + + + + + + + + + diff --git a/src/PiMon.vcxproj.filters b/src/PiMon.vcxproj.filters index 6214456..a353160 100644 --- a/src/PiMon.vcxproj.filters +++ b/src/PiMon.vcxproj.filters @@ -21,14 +21,44 @@ 头文件 + + 头文件 + + + 头文件 + + + 头文件 + 头文件 + + 头文件 + + + 头文件 + 源文件 + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + diff --git a/src/listview.c b/src/listview.c new file mode 100644 index 0000000..8d8380d --- /dev/null +++ b/src/listview.c @@ -0,0 +1,106 @@ +#include +#include +#include "listview.h" + +void LVAddColumn(HWND hwnd, int pos, const wchar_t* header, int width) { + size_t len = wcslen(header) + 1; + wchar_t* str = (wchar_t*)malloc(len * sizeof(wchar_t)); + if (str == NULL) return; + wcscpy_s(str, len, header); + + LVCOLUMNW col = { 0 }; + col.mask = LVCF_TEXT | LVCF_WIDTH; + col.pszText = str; + col.cchTextMax = (int)wcslen(str); + col.cx = width; + ListView_InsertColumn(hwnd, pos, &col); + + free(str); +} + +void LVSetColumnWidth(HWND hwnd, int iCol, int width) { + LVCOLUMNW col = { 0 }; + col.mask = LVCF_WIDTH; + col.cx = width; + ListView_SetColumn(hwnd, iCol, &col); +} + +void LVSetItemText(HWND hwnd, int iItem, int iSubItem, const wchar_t* text) { + size_t len = wcslen(text) + 1; + wchar_t* str = (wchar_t*)malloc(len * sizeof(wchar_t)); + if (str == NULL) return; + wcscpy_s(str, len, text); + + LVITEMW item = { 0 }; + item.mask = LVIF_TEXT; + item.iItem = iItem; + item.iSubItem = iSubItem; + item.pszText = str; + item.cchTextMax = (int)wcslen(str); + ListView_SetItem(hwnd, &item); + + free(str); +} + +void LVSetItemGroupId(HWND hwnd, int iItem, int groupId) { + LVITEMW item = { 0 }; + item.mask = LVIF_GROUPID; + item.iItem = iItem; + item.iGroupId = groupId; + ListView_SetItem(hwnd, &item); +} + +void LVSetItemIndent(HWND hwnd, int iItem, int indent) { + LVITEMW item = { 0 }; + item.mask = LVIF_INDENT; + item.iItem = iItem; + item.iIndent = indent; + ListView_SetItem(hwnd, &item); +} + + +void LVSetItemImage(HWND hwnd, int iItem, int imageId) { + LVITEMW item = { 0 }; + item.mask = LVIF_IMAGE; + item.iItem = iItem; + item.iImage = imageId; + ListView_SetItem(hwnd, &item); +} + + +void LVAddGroup(HWND hwnd, int pos, const wchar_t* header, int id) { + size_t len = wcslen(header) + 1; + wchar_t* str = (wchar_t*)malloc(len * sizeof(wchar_t)); + if (str == NULL) return; + wcscpy_s(str, len, header); + + LVGROUP group = { 0 }; + group.cbSize = sizeof(LVGROUP); + group.mask = LVGF_HEADER | LVGF_GROUPID; + group.pszHeader = str; + group.cchHeader = (int)wcslen(str); + group.iGroupId = id; + ListView_InsertGroup(hwnd, pos, &group); + + free(str); +} + +int LVAddItem(HWND hwnd, int pos, const wchar_t* text) { + int index = 0; + if (pos < 0) pos = ListView_GetItemCount(hwnd); + + size_t len = wcslen(text) + 1; + wchar_t* str = (wchar_t*)malloc(len * sizeof(wchar_t)); + if (str == NULL) return index; + wcscpy_s(str, len, text); + + LVITEM item = { 0 }; + item.mask = LVIF_TEXT; + item.iItem = pos; + item.pszText = str; + item.cchTextMax = (int)wcslen(str); + index = ListView_InsertItem(hwnd, &item); + + free(str); + return index; +} diff --git a/src/listview.h b/src/listview.h new file mode 100644 index 0000000..46e698c --- /dev/null +++ b/src/listview.h @@ -0,0 +1,16 @@ +#ifndef LISTVIEW_H +#define LISTVIEW_H + +#include +#include + +void LVAddColumn(HWND hwnd, int pos, const wchar_t* header, int width); +void LVSetColumnWidth(HWND hwnd, int iCol, int width); +void LVSetItemText(HWND hwnd, int iItem, int iSubItem, const wchar_t* text); +void LVSetItemGroupId(HWND hwnd, int iItem, int groupId); +void LVSetItemIndent(HWND hwnd, int iItem, int indent); +void LVSetItemImage(HWND hwnd, int iItem, int imageId); +void LVAddGroup(HWND hwnd, int pos, const wchar_t* header, int id); +int LVAddItem(HWND hwnd, int pos, const wchar_t* text); + +#endif \ No newline at end of file diff --git a/src/mailbox.c b/src/mailbox.c new file mode 100644 index 0000000..2787b9d --- /dev/null +++ b/src/mailbox.c @@ -0,0 +1,202 @@ +#include +#include "rpiq.h" +#include "mailbox.h" + +ULONG GetBoardRevision() { + ULONG value = 0; + + HANDLE hDevice = CreateFileW( + RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 + ); + if (hDevice == INVALID_HANDLE_VALUE) return value; + + DWORD bytesReturned; + + MAILBOX_GET_BOARD_REVISION mailbox; + INIT_MAILBOX_GET_BOARD_REVISION(&mailbox); + BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, + (LPVOID)(&mailbox), sizeof(mailbox), + (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); + if (status) value = mailbox.BoardRevision; + + CloseHandle(hDevice); + return value; +} + +ULONG GetVoltage(int voltageId) { + ULONG value = 0; + + HANDLE hDevice = CreateFileW( + RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 + ); + if (hDevice == INVALID_HANDLE_VALUE) return value; + + DWORD bytesReturned; + + MAILBOX_GET_VOLTAGE mailbox; + INIT_MAILBOX_GET_VOLTAGE(&mailbox, voltageId); + BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, + (LPVOID)(&mailbox), sizeof(mailbox), + (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); + if (status) value = mailbox.Value; + + CloseHandle(hDevice); + return value; +} + +ULONG GetClock(int clockId) { + ULONG value = 0; + + HANDLE hDevice = CreateFileW( + RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 + ); + if (hDevice == INVALID_HANDLE_VALUE) return value; + + DWORD bytesReturned; + + MAILBOX_GET_CLOCK_RATE mailbox; + INIT_MAILBOX_GET_CLOCK_RATE(&mailbox, clockId); + BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, + (LPVOID)(&mailbox), sizeof(mailbox), + (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); + if (status) value = mailbox.Rate; + + CloseHandle(hDevice); + return value; +} + +ULONG GetTemperature() { + ULONG value = 0; + + HANDLE hDevice = CreateFileW( + RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 + ); + if (hDevice == INVALID_HANDLE_VALUE) return value; + + DWORD bytesReturned; + + MAILBOX_GET_TEMPERATURE mailbox; + INIT_MAILBOX_GET_TEMPERATURE(&mailbox); + BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, + (LPVOID)(&mailbox), sizeof(mailbox), + (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); + if (status) value = mailbox.Value; + + CloseHandle(hDevice); + return value; +} + +ULONG GetFirmwareRevision() { + ULONG value = 0; + + HANDLE hDevice = CreateFileW( + RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 + ); + if (hDevice == INVALID_HANDLE_VALUE) return value; + + DWORD bytesReturned; + + MAILBOX_GET_FIRMWARE_REVISION mailbox; + INIT_MAILBOX_GET_FIRMWARE_REVISION(&mailbox); + BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, + (LPVOID)(&mailbox), sizeof(mailbox), + (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); + if (status) value = mailbox.FirmwareRevision; + + CloseHandle(hDevice); + return value; +} + +ULONGLONG GetSerialNumber() { + ULONGLONG value = 0; + + HANDLE hDevice = CreateFileW( + RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 + ); + if (hDevice == INVALID_HANDLE_VALUE) return value; + + DWORD bytesReturned; + + MAILBOX_GET_BOARD_SERIAL mailbox; + INIT_MAILBOX_GET_BOARD_SERIAL(&mailbox); + BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, + (LPVOID)(&mailbox), sizeof(mailbox), + (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); + if (status) { + value = *(ULONGLONG*)(mailbox.BoardSerial); + } + + CloseHandle(hDevice); + return value; +} + +ULONG GetInstalledMemory(ULONG BoardRevision) { + // + // www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md + // Bits [20-22] indicate the amount of memory starting with 256MB (000b) + // and doubling in size for each value (001b = 512 MB, 010b = 1GB, etc.) + // + return 256 << ((BoardRevision >> 20) & 0x07); +} + +const wchar_t* GetProcessorName(ULONG BoardRevision) { + ULONG cpuId = (BoardRevision >> 12) & 0x0F; + + switch (cpuId) { + // www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md + case 0x00: + return L"BCM2835 (ARM11)"; + case 0x01: + return L"BCM2836 (ARM Cortex-A7)"; + case 0x02: + return L"BCM2837 (ARM Cortex-A53)"; + case 0x03: + return L"BCM2711 (ARM Cortex-A72)"; + default: + return L"Unknown"; + } +} + +const wchar_t* GetPiModelName(ULONG BoardRevision) { + ULONG modelId = (BoardRevision >> 4) & 0xFF; + + // www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md + switch (modelId) { + case 0x00: + return L"Raspberry Pi Model A"; + case 0x01: + return L"Raspberry Pi Model B"; + case 0x02: + return L"Raspberry Pi Model A+"; + case 0x03: + return L"Raspberry Pi Model B+"; + case 0x04: + return L"Raspberry Pi 2 Model B"; + case 0x06: + return L"Raspberry Pi Compute Module 1"; + case 0x08: + return L"Raspberry Pi 3 Model B"; + case 0x09: + return L"Raspberry Pi Zero"; + case 0x0A: + return L"Raspberry Pi Compute Module 3"; + case 0x0C: + return L"Raspberry Pi Zero W"; + case 0x0D: + return L"Raspberry Pi 3 Model B+"; + case 0x0E: + return L"Raspberry Pi 3 Model A+"; + case 0x10: + return L"Raspberry Pi Compute Module 3+"; + case 0x11: + return L"Raspberry Pi 4 Model B"; + default: + return L"Unknown"; + } +} \ No newline at end of file diff --git a/src/mailbox.h b/src/mailbox.h index ebfeaba..fe61718 100644 --- a/src/mailbox.h +++ b/src/mailbox.h @@ -2,204 +2,15 @@ #define MAILBOX_H #include -#include "rpiq.h" -ULONG GetBoardRevision() { - ULONG value = 0; +ULONG GetBoardRevision(); +ULONG GetVoltage(int voltageId); +ULONG GetClock(int clockId); +ULONG GetTemperature(); +ULONG GetFirmwareRevision(); +ULONGLONG GetSerialNumber(); +ULONG GetInstalledMemory(ULONG BoardRevision); +const wchar_t* GetProcessorName(ULONG BoardRevision); +const wchar_t* GetPiModelName(ULONG BoardRevision); - HANDLE hDevice = CreateFileW( - RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 - ); - if (hDevice == INVALID_HANDLE_VALUE) return value; - - DWORD bytesReturned; - - MAILBOX_GET_BOARD_REVISION mailbox; - INIT_MAILBOX_GET_BOARD_REVISION(&mailbox); - BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, - (LPVOID)(&mailbox), sizeof(mailbox), - (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); - if (status) value = mailbox.BoardRevision; - - CloseHandle(hDevice); - return value; -} - -ULONG GetVoltage(int voltageId) { - ULONG value = 0; - - HANDLE hDevice = CreateFileW( - RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 - ); - if (hDevice == INVALID_HANDLE_VALUE) return value; - - DWORD bytesReturned; - - MAILBOX_GET_VOLTAGE mailbox; - INIT_MAILBOX_GET_VOLTAGE(&mailbox, voltageId); - BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, - (LPVOID)(&mailbox), sizeof(mailbox), - (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); - if (status) value = mailbox.Value; - - CloseHandle(hDevice); - return value; -} - -ULONG GetClock(int clockId) { - ULONG value = 0; - - HANDLE hDevice = CreateFileW( - RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 - ); - if (hDevice == INVALID_HANDLE_VALUE) return value; - - DWORD bytesReturned; - - MAILBOX_GET_CLOCK_RATE mailbox; - INIT_MAILBOX_GET_CLOCK_RATE(&mailbox, clockId); - BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, - (LPVOID)(&mailbox), sizeof(mailbox), - (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); - if (status) value = mailbox.Rate; - - CloseHandle(hDevice); - return value; -} - -ULONG GetTemperature() { - ULONG value = 0; - - HANDLE hDevice = CreateFileW( - RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 - ); - if (hDevice == INVALID_HANDLE_VALUE) return value; - - DWORD bytesReturned; - - MAILBOX_GET_TEMPERATURE mailbox; - INIT_MAILBOX_GET_TEMPERATURE(&mailbox); - BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, - (LPVOID)(&mailbox), sizeof(mailbox), - (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); - if (status) value = mailbox.Value; - - CloseHandle(hDevice); - return value; -} - -ULONG GetFirmwareRevision() { - ULONG value = 0; - - HANDLE hDevice = CreateFileW( - RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 - ); - if (hDevice == INVALID_HANDLE_VALUE) return value; - - DWORD bytesReturned; - - MAILBOX_GET_FIRMWARE_REVISION mailbox; - INIT_MAILBOX_GET_FIRMWARE_REVISION(&mailbox); - BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, - (LPVOID)(&mailbox), sizeof(mailbox), - (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); - if (status) value = mailbox.FirmwareRevision; - - CloseHandle(hDevice); - return value; -} - -ULONGLONG GetSerialNumber() { - ULONGLONG value = 0; - - HANDLE hDevice = CreateFileW( - RPIQ_USERMODE_PATH, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 - ); - if (hDevice == INVALID_HANDLE_VALUE) return value; - - DWORD bytesReturned; - - MAILBOX_GET_BOARD_SERIAL mailbox; - INIT_MAILBOX_GET_BOARD_SERIAL(&mailbox); - BOOL status = DeviceIoControl(hDevice, IOCTL_MAILBOX_PROPERTY, - (LPVOID)(&mailbox), sizeof(mailbox), - (LPVOID)(&mailbox), sizeof(mailbox), &bytesReturned, 0); - if (status) { - value = *(ULONGLONG*)(mailbox.BoardSerial); - } - - CloseHandle(hDevice); - return value; -} - -ULONG GetInstalledMemory(ULONG BoardRevision) { - // - // www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md - // Bits [20-22] indicate the amount of memory starting with 256MB (000b) - // and doubling in size for each value (001b = 512 MB, 010b = 1GB, etc.) - // - return 256 << ((BoardRevision >> 20) & 0x07); -} - -const wchar_t* GetProcessorName(ULONG BoardRevision) { - ULONG cpuId = (BoardRevision >> 12) & 0x0F; - - switch (cpuId) { - // www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md - case 0x00: - return L"BCM2835 (ARM11)"; - case 0x01: - return L"BCM2836 (ARM Cortex-A7)"; - case 0x02: - return L"BCM2837 (ARM Cortex-A53)"; - case 0x03: - return L"BCM2711 (ARM Cortex-A72)"; - default: - return L"Unknown"; - } -} - -const wchar_t* GetPiModelName(ULONG BoardRevision) { - ULONG modelId = (BoardRevision >> 4) & 0xFF; - - // www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md - switch (modelId) { - case 0x00: - return L"Raspberry Pi Model A"; - case 0x01: - return L"Raspberry Pi Model B"; - case 0x02: - return L"Raspberry Pi Model A+"; - case 0x03: - return L"Raspberry Pi Model B+"; - case 0x04: - return L"Raspberry Pi 2 Model B"; - case 0x06: - return L"Raspberry Pi Compute Module 1"; - case 0x08: - return L"Raspberry Pi 3 Model B"; - case 0x09: - return L"Raspberry Pi Zero"; - case 0x0A: - return L"Raspberry Pi Compute Module 3"; - case 0x0C: - return L"Raspberry Pi Zero W"; - case 0x0D: - return L"Raspberry Pi 3 Model B+"; - case 0x0E: - return L"Raspberry Pi 3 Model A+"; - case 0x10: - return L"Raspberry Pi Compute Module 3+"; - case 0x11: - return L"Raspberry Pi 4 Model B"; - default: - return L"Unknown"; - } -} #endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index 64bbd173692281ab47d4faeb7dd496a705e3640c..39bbbe7a23c4f17251c12bd240063d2033ada7f8 100644 GIT binary patch delta 3984 zcmb_fO>7%g5FRIOgA?2~IH_yW;!Q%@gfwlMA87t<=dV%hB()t(QAOm$t`nLc6FUu| zEmp+=dO-~%acQ9-4&{P4_`ng`1GgTya6m!`?v*GK7X*lJ-g?(Rae|Q0YQ4Mf&6_v# z&Ae~M4{uxk{K|6s+lm#6P>L3}Z@Oxec!|;yt>Sr_7HN=dRJq;esBWNjicyl*XajEx z6yrk{m+dOX)-k$-@l_e&GRvv`A{m#jiWFuev?cF{mLVnTui_b_O^p3@JU|}0NE0+n z(=%AtxM z_cxtsfT9_w^k>a}S#2A{h`15PtdAP#5>RZA?YU`Sl2Ze(^DhHlrK4?dmj7_nSUmh- zsFv?)8hhPG_HRRrP`Bm^>nB?usc zczUpR7{B^g2o}xofV+;rA9Aa`o$euv#$oriSWq3H1j6wK_FKobM(gm^UMD=9>7?Ff?^J=Sgz$hWp zm5IbMM)d7fh|H}glp~vvT*jqAQg>}r?REtty8d(=ip7?7h%S^cV+Ki`+||Pgg~Jw< zZD6h76~l8KU#qypp}4t~pt{4IGzP^VNr9aJ;xsFT0hOi~AQM%F>gQFX6|9UyMuKK| zC`f6*P*A;MnvlTP8gLXxbC_MCST?s!;6e}(kT)P4g-0nPS` z45a5(AkRQ11`}c`utG(rk$I=o@iy{sH~kX!BrJ=m6&iBOi=3VY0cdm`xBhL=kWfef zvjLDtAK4Bf(HpT;atz0Uf9`Vf^HqoWW9>Qq(0-7os^(vk<03qyC%i@jxHRxj3x0PT zF~}_fXXwj(TJ_G;hN8^i(esw{c^qh+4JGv#ve_ouMxZ@{bpkXv6>|ElsZHfV0Ef|w z9nMk*I8?HuJ^R~IFyBGlxMaTItpgYx*J&ZMnio*iAu z>MY*kjGi!TJL;$~qHwG0+CKiZtI{!npe(_HB8V0LH+WC%m%wW5^49jX0OlAZ^U24j zf)&S+6Cc94Fe{kHG2+AA9M^m84$}}S2spQlTuh7k6Ua|LSX|0hOU`VJL~#|_SG3da zmNM8 z0(V$7U4C^?r6HW4SJher4Y4JNY?1B+WWk?}IjVzr%k`WnH2kCcWQ8@$Oiz04^??E; zW^rhX5CDms{Qu}^w9wZX;BWNH2{5LXCA(piQ0evs^%?vok+UcC5+Sy8)lidN@Qr|? z{3?$&;At~QI%@f~5iQmXt$MR+WJf-=2~vfv?*_UzLyw}~tQ|qvk(+5onaZ`p?Hn0u zZIfc3lMtFScHW~sZp_7O&-_Y@r8@I0pi>eg64)Zo7c<@i|Rxra2j(FPdEFcLI1^4-D8Ju5GGNdH4)HCae3;6+ajf6{lDyF4!#6_;=Jx%j&0?bbOkqVVJ# zGA0JrT*g}j=UDGa^(IpK?Igk?mE}>) Mn#V5lXl%ps4|IaW8UO$Q delta 501 zcmeyfo$=5F#tFw{gBdayQWE2{5 zW`W5L%nG``46Y1*451A1KqWp5;XpDHs5PF!A1E5n5CWtF7!(*x7z}{WaPmi1QCVai zPC)rkpemROqs=FoJ308>fo>>a@C4eN#*ojTG5NNl=HxvhA(I2-*fz(A=J9O4qnN}v z*+wH|bByW=Noiyg(cCau-oBU}DnEI?eeq@|hborI^V}9}KIR_7G&#>JU~)xJ5L`vP zx8&p+9wkl%23`g(22KXf$qRW@g$)_>fUb`LI!6gE{*}jjvJG$E +#include "reg.h" + +ULONG GetWindowsMemory() { + MEMORYSTATUSEX memStatus; + memStatus.dwLength = sizeof(MEMORYSTATUSEX); + GlobalMemoryStatusEx(&memStatus); + + return (ULONG)(memStatus.ullTotalPhys / 1048576ULL); +} + +DWORD RegQueryDword(HKEY hKey, LPCWSTR subKey, LPCWSTR valueName) { + HKEY hSubKey; + DWORD type = REG_DWORD; + + LSTATUS status = RegOpenKeyExW(hKey, subKey, 0, KEY_READ | KEY_WOW64_64KEY, &hSubKey); + if (status != ERROR_SUCCESS) return 0; + + DWORD value = 0; + DWORD size = sizeof(DWORD); + + status = RegQueryValueExW(hSubKey, valueName, NULL, &type, (LPBYTE)&value, &size); + if (status != ERROR_SUCCESS) value = 0; + + RegCloseKey(hSubKey); + return value; +} + +wchar_t* RegQueryString(HKEY hKey, LPCWSTR subKey, LPCWSTR valueName) { + HKEY hSubKey; + DWORD size = 0; + DWORD type = REG_SZ; + + LSTATUS status = RegOpenKeyExW(hKey, subKey, 0, KEY_READ | KEY_WOW64_64KEY, &hSubKey); + if (status != ERROR_SUCCESS) return NULL; + + RegQueryValueExW(hSubKey, valueName, NULL, &type, NULL, &size); + wchar_t* str = (wchar_t*)malloc(size); + + status = RegQueryValueExW(hSubKey, valueName, NULL, &type, (LPBYTE)str, &size); + if (status != ERROR_SUCCESS) { + free(str); + str = NULL; + } + + RegCloseKey(hSubKey); + return str; +} + +wchar_t* GetBiosVersion() { + return RegQueryString(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", L"BIOSVersion"); +} + +wchar_t* GetWindowsVersion() { + DWORD ubr = RegQueryDword(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"UBR"); + wchar_t* currentBuild = RegQueryString(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"CurrentBuild"); + wchar_t* productName = RegQueryString(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"ProductName"); + + // PROCESSOR_ARCHITEW6432 is the native arch when running in WOW64 + wchar_t arch[10]; + if (!GetEnvironmentVariableW(L"PROCESSOR_ARCHITEW6432", arch, 10)) + GetEnvironmentVariableW(L"PROCESSOR_ARCHITECTURE", arch, 10); + + wchar_t* str = (wchar_t*)malloc(100 * sizeof(wchar_t)); + if (str != NULL) StringCbPrintfW(str, 100, L"%ws %ws Build %ws.%d", productName, arch, currentBuild, ubr); + + free(currentBuild); + free(productName); + return str; +} diff --git a/src/reg.h b/src/reg.h new file mode 100644 index 0000000..6b34416 --- /dev/null +++ b/src/reg.h @@ -0,0 +1,20 @@ +#ifndef REG_H +#define REG_H + +#include +#include + +ULONG GetWindowsMemory(); + +DWORD RegQueryDword(HKEY hKey, LPCWSTR subKey, LPCWSTR valueName); + +// Free the string after use +wchar_t* RegQueryString(HKEY hKey, LPCWSTR subKey, LPCWSTR valueName); + +// Free the string after use +wchar_t* GetBiosVersion(); + +// Free the string after use +wchar_t* GetWindowsVersion(); + +#endif \ No newline at end of file diff --git a/src/resource.h b/src/resource.h new file mode 100644 index 0000000..31f91f2 --- /dev/null +++ b/src/resource.h @@ -0,0 +1,14 @@ +#ifndef RESOURCE_H +#define RESOURCE_H + +#define IDI_MAIN 10 + +#define IDM_TRAY 3000 +#define IDM_ALWAYS_TOP 3001 +#define IDM_ABOUT 3002 +#define IDM_EXIT 3003 + + +#define IDM_SYS_ABOUT 4001 +#define IDM_SYS_ALWAYS_TOP 4002 +#endif diff --git a/src/tray.c b/src/tray.c new file mode 100644 index 0000000..3864771 --- /dev/null +++ b/src/tray.c @@ -0,0 +1,102 @@ + +#include +#include +#include "tray.h" +#include "utils.h" + +void AddTrayIcon(HWND hwnd, UINT id, const wchar_t* desc, HICON icon, UINT msgId) { + NOTIFYICONDATAW nid = { 0 }; + nid.cbSize = sizeof(NOTIFYICONDATAW); + nid.hWnd = hwnd; + nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE; + nid.hIcon = icon; + nid.uCallbackMessage = msgId; + nid.uID = id; + wcscpy_s(nid.szTip, 128, desc); + Shell_NotifyIconW(NIM_ADD, &nid); +} + +void DeleteTrayIcon(HWND hwnd, UINT id) { + NOTIFYICONDATAW nid = { 0 }; + nid.cbSize = sizeof(NOTIFYICONDATAW); + nid.hWnd = hwnd; + nid.uFlags = 0; + nid.uID = id; + Shell_NotifyIconW(NIM_DELETE, &nid); +} + +HICON DrawTrayIcon(HWND hwnd, COLORREF bkColor, COLORREF textColor, double value) { + int dpi = GetDpiForWindow(hwnd); + int size = SCALE(16, dpi); + + // Create Memory Bitmap + HDC dc = GetDC(hwnd); + HDC memDC = CreateCompatibleDC(dc); + HBITMAP hcolor = CreateCompatibleBitmap(dc, size, size); + SelectObject(memDC, hcolor); + + // Fill Background + RECT r = { 0, 0, size, size }; + HBRUSH brush = CreateSolidBrush(bkColor); + FillRect(memDC, &r, brush); + SetBkColor(memDC, bkColor); + + // Set Text Color + SetTextColor(memDC, textColor); + + // Set Font + LOGFONTW font = { 0 }; + font.lfWeight = FW_NORMAL; + font.lfPitchAndFamily = DEFAULT_PITCH; + if (value < 100.0) + font.lfHeight = -9 * dpi / 72; + else + font.lfHeight = -8 * dpi / 72; + wcscpy_s(font.lfFaceName, size, L"Segoe UI"); + HFONT hfont = CreateFontIndirectW(&font); + SelectObject(memDC, hfont); + + // Determine a sane format + wchar_t str[5]; + const wchar_t* format; + if (value < 1.0) + format = L"%.1g"; + else if (value < 100.0) + format = L"%.2g"; + else + format = L"%.3g"; + StringCbPrintfW(str, sizeof(str), format, value); + + // Draw text + DrawTextW(memDC, str, wcslen(str), &r, DT_SINGLELINE | DT_CALCRECT); + r.left = (size - r.right) / 2; r.right += r.left; + r.top = (size - r.bottom) / 2; r.bottom += r.top; + DrawTextW(memDC, str, wcslen(str), &r, DT_SINGLELINE); + + // Create Icon + HBITMAP hmask = CreateBitmap(size, size, 1, 1, NULL); + ICONINFO ii = { TRUE, 0, 0, hmask, hcolor }; + HICON trayIcon = CreateIconIndirect(&ii); + + // Cleanup + DeleteObject(brush); + DeleteObject(hcolor); + DeleteObject(hmask); + DeleteObject(hfont); + DeleteDC(memDC); + ReleaseDC(hwnd, dc); + + return trayIcon; +} + +void UpdateTrayIcon(HWND hwnd, UINT id, HICON icon, const wchar_t* desc) { + NOTIFYICONDATAW nid = { 0 }; + nid.cbSize = sizeof(NOTIFYICONDATAW); + nid.hWnd = hwnd; + nid.uFlags = NIF_TIP | NIF_ICON; + nid.uID = id; + nid.hIcon = icon; + wcscpy_s(nid.szTip, sizeof(nid.szTip) / sizeof(wchar_t), desc); + Shell_NotifyIconW(NIM_MODIFY, &nid); +} + diff --git a/src/tray.h b/src/tray.h new file mode 100644 index 0000000..d207b6d --- /dev/null +++ b/src/tray.h @@ -0,0 +1,13 @@ +#ifndef TRAY_H +#define TRAY_H + +#include + +void AddTrayIcon(HWND hwnd, UINT id, const wchar_t* desc, HICON icon, UINT msgId); +void DeleteTrayIcon(HWND hwnd, UINT id); +void UpdateTrayIcon(HWND hwnd, UINT id, HICON icon, const wchar_t* desc); + +// Remember to destroy the icon +HICON DrawTrayIcon(HWND hwnd, COLORREF bkColor, COLORREF textColor, double value); + +#endif \ No newline at end of file diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..2a310f8 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,35 @@ +#include +#include "utils.h" + +void ResizeWindowByClientArea(HWND hwnd, int width, int height) { + UINT dpi = GetDpiForWindow(hwnd); + int w = SCALE(width, dpi) + + (GetSystemMetricsForDpi(SM_CXFRAME, dpi) + + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)) * 2; + int h = SCALE(height, dpi) + + (GetSystemMetricsForDpi(SM_CYFRAME, dpi) + + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)) * 2 + + GetSystemMetricsForDpi(SM_CYCAPTION, dpi); + SetWindowPos(hwnd, NULL, 0, 0, w, h, SWP_NOMOVE); +} + +void MoveWindowToCenterOfScreen(HWND hwnd) { + RECT rs = { 0 }; + SystemParametersInfoW(SPI_GETWORKAREA, 0, &rs, 0); + RECT r = { 0 }; + GetWindowRect(hwnd, &r); + + int x = (rs.right - (r.right - r.left)) / 2; + int y = (rs.bottom - (r.bottom - r.top)) / 2; + + SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOSIZE); +} + +int PrettyPrintUnits(double* value, const wchar_t** units, int unit_count, double unit_step) { + int unit_index = 0; + while (*value >= unit_step && unit_index < (unit_count - 1)) { + *value /= unit_step; + unit_index++; + } + return unit_index; +} diff --git a/src/utils.h b/src/utils.h index d8f7ec4..a1300f9 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,215 +2,10 @@ #define UTILS_H #include -#include #define SCALE(x, dpi) ((int)((x) * (dpi / 96.0))) - -void LVAddColumn(HWND hwnd, int pos, const wchar_t* header, int width) { - size_t len = wcslen(header) + 1; - wchar_t* str = (wchar_t*)malloc(len * sizeof(wchar_t)); - if (str == NULL) return; - wcscpy_s(str, len, header); - - LVCOLUMNW col = { 0 }; - col.mask = LVCF_TEXT | LVCF_WIDTH; - col.pszText = str; - col.cchTextMax = (int)wcslen(str); - col.cx = width; - ListView_InsertColumn(hwnd, pos, &col); - - free(str); -} - -void LVSetColumnWidth(HWND hwnd, int iCol, int width) { - LVCOLUMNW col = { 0 }; - col.mask = LVCF_WIDTH; - col.cx = width; - ListView_SetColumn(hwnd, iCol, &col); -} - -void LVSetItemText(HWND hwnd, int iItem, int iSubItem, const wchar_t* text) { - size_t len = wcslen(text) + 1; - wchar_t* str = (wchar_t*)malloc(len * sizeof(wchar_t)); - if (str == NULL) return; - wcscpy_s(str, len, text); - - LVITEMW item = { 0 }; - item.mask = LVIF_TEXT; - item.iItem = iItem; - item.iSubItem = iSubItem; - item.pszText = str; - item.cchTextMax = (int)wcslen(str); - ListView_SetItem(hwnd, &item); - - free(str); -} - -void LVSetItemGroupId(HWND hwnd, int iItem, int groupId) { - LVITEMW item = { 0 }; - item.mask = LVIF_GROUPID; - item.iItem = iItem; - item.iGroupId = groupId; - ListView_SetItem(hwnd, &item); -} - -void LVSetItemIndent(HWND hwnd, int iItem, int indent) { - LVITEMW item = { 0 }; - item.mask = LVIF_INDENT; - item.iItem = iItem; - item.iIndent = indent; - ListView_SetItem(hwnd, &item); -} - - -void LVSetItemImage(HWND hwnd, int iItem, int imageId) { - LVITEMW item = { 0 }; - item.mask = LVIF_IMAGE; - item.iItem = iItem; - item.iImage = imageId; - ListView_SetItem(hwnd, &item); -} - - -void LVAddGroup(HWND hwnd, int pos, const wchar_t* header, int id) { - size_t len = wcslen(header) + 1; - wchar_t* str = (wchar_t*)malloc(len * sizeof(wchar_t)); - if (str == NULL) return; - wcscpy_s(str, len, header); - - LVGROUP group = { 0 }; - group.cbSize = sizeof(LVGROUP); - group.mask = LVGF_HEADER | LVGF_GROUPID; - group.pszHeader = str; - group.cchHeader = (int)wcslen(str); - group.iGroupId = id; - ListView_InsertGroup(hwnd, pos, &group); - - free(str); -} - -int LVAddItem(HWND hwnd, int pos, const wchar_t* text) { - int index = 0; - if (pos < 0) pos = ListView_GetItemCount(hwnd); - - size_t len = wcslen(text) + 1; - wchar_t* str = (wchar_t*)malloc(len * sizeof(wchar_t)); - if (str == NULL) return index; - wcscpy_s(str, len, text); - - LVITEM item = { 0 }; - item.mask = LVIF_TEXT; - item.iItem = pos; - item.pszText = str; - item.cchTextMax = (int)wcslen(str); - index = ListView_InsertItem(hwnd, &item); - - free(str); - return index; -} - -ULONG GetWindowsMemory() { - MEMORYSTATUSEX memStatus; - memStatus.dwLength = sizeof(MEMORYSTATUSEX); - GlobalMemoryStatusEx(&memStatus); - - return (ULONG)(memStatus.ullTotalPhys / 1048576ULL); -} - -DWORD RegQueryDword(HKEY hKey, LPCWSTR subKey, LPCWSTR valueName) { - HKEY hSubKey; - DWORD type = REG_DWORD; - - LSTATUS status = RegOpenKeyExW(hKey, subKey, 0, KEY_READ | KEY_WOW64_64KEY, &hSubKey); - if (status != ERROR_SUCCESS) return 0; - - DWORD value = 0; - DWORD size = sizeof(DWORD); - - status = RegQueryValueExW(hSubKey, valueName, NULL, &type, (LPBYTE)&value, &size); - if (status != ERROR_SUCCESS) value = 0; - - RegCloseKey(hSubKey); - return value; -} - -// Free the string after use -wchar_t* RegQueryString(HKEY hKey, LPCWSTR subKey, LPCWSTR valueName) { - HKEY hSubKey; - DWORD size = 0; - DWORD type = REG_SZ; - - LSTATUS status = RegOpenKeyExW(hKey, subKey, 0, KEY_READ | KEY_WOW64_64KEY, &hSubKey); - if (status != ERROR_SUCCESS) return NULL; - - RegQueryValueExW(hSubKey, valueName, NULL, &type, NULL, &size); - wchar_t* str = (wchar_t*)malloc(size); - - status = RegQueryValueExW(hSubKey, valueName, NULL, &type, (LPBYTE)str, &size); - if (status != ERROR_SUCCESS) { - free(str); - str = NULL; - } - - RegCloseKey(hSubKey); - return str; -} - -// Free the string after use -wchar_t* GetBiosVersion() { - return RegQueryString(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", L"BIOSVersion"); -} - -// Free the string after use -wchar_t* GetWindowsVersion() { - DWORD ubr = RegQueryDword(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"UBR"); - wchar_t* currentBuild = RegQueryString(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"CurrentBuild"); - wchar_t* productName = RegQueryString(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"ProductName"); - - // PROCESSOR_ARCHITEW6432 is the native arch when running in WOW64 - wchar_t arch[10]; - if (!GetEnvironmentVariableW(L"PROCESSOR_ARCHITEW6432", arch, 10)) - GetEnvironmentVariableW(L"PROCESSOR_ARCHITECTURE", arch, 10); - - wchar_t* str = (wchar_t*)malloc(100 * sizeof(wchar_t)); - if (str != NULL) StringCbPrintfW(str, 100, L"%ws %ws Build %ws.%d", productName, arch, currentBuild, ubr); - - free(currentBuild); - free(productName); - return str; -} - -void ResizeWindowByClientArea(HWND hwnd, int width, int height) { - UINT dpi = GetDpiForWindow(hwnd); - int w = SCALE(width, dpi) + - (GetSystemMetricsForDpi(SM_CXFRAME, dpi) + - GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)) * 2; - int h = SCALE(height, dpi) + - (GetSystemMetricsForDpi(SM_CYFRAME, dpi) + - GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)) * 2 + - GetSystemMetricsForDpi(SM_CYCAPTION, dpi); - SetWindowPos(hwnd, NULL, 0, 0, w, h, SWP_NOMOVE); -} - -void MoveWindowToCenterOfScreen(HWND hwnd) { - RECT rs = { 0 }; - SystemParametersInfoW(SPI_GETWORKAREA, 0, &rs, 0); - RECT r = { 0 }; - GetWindowRect(hwnd, &r); - - int x = (rs.right - (r.right - r.left)) / 2; - int y = (rs.bottom - (r.bottom - r.top)) / 2; - - SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOSIZE); -} - -int PrettyPrintUnits(double* value, const wchar_t** units, int unit_count, double unit_step) { - int unit_index = 0; - while (*value >= unit_step && unit_index < (unit_count - 1)) { - *value /= unit_step; - unit_index++; - } - return unit_index; -} +void ResizeWindowByClientArea(HWND hwnd, int width, int height); +void MoveWindowToCenterOfScreen(HWND hwnd); +int PrettyPrintUnits(double* value, const wchar_t** units, int unit_count, double unit_step); #endif \ No newline at end of file diff --git a/src/version.h b/src/version.h new file mode 100644 index 0000000..07d7a21 --- /dev/null +++ b/src/version.h @@ -0,0 +1,8 @@ +#ifndef VERSION_H +#define VERSION_H + +#define PIMON_VERSION "1.0.5" +#define PIMON_VERSIONW L"1.0.5" +#define PIMON_FILE_VERSION 1,0,5,0 + +#endif