2026-08-10 23:13:58 +08:00
|
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#pragma comment(lib, "winmm.lib")
|
|
|
|
|
|
|
|
|
|
#define IDI_MAIN 1
|
|
|
|
|
#define ID_GEN 101
|
|
|
|
|
#define ID_PREV 102
|
|
|
|
|
#define ID_NEW 103
|
|
|
|
|
#define ID_ENV 104
|
|
|
|
|
|
|
|
|
|
static HFONT hfTitle, hfBody, hfMono;
|
|
|
|
|
static HBRUSH hbrDark, hbrDarker, hbrAccent;
|
|
|
|
|
static HWND hEnvCheck;
|
|
|
|
|
|
|
|
|
|
static void ReadProtk(char* buf, int sz)
|
|
|
|
|
{
|
|
|
|
|
buf[0] = 0;
|
|
|
|
|
FILE* f = fopen("protk.dat", "r");
|
|
|
|
|
if (!f) { snprintf(buf, sz, "protk.dat not found in current directory"); return; }
|
|
|
|
|
int total = 0; char ln[512];
|
|
|
|
|
while (fgets(ln, sizeof(ln), f) && total < sz - 4) {
|
|
|
|
|
int len = (int)strlen(ln);
|
|
|
|
|
memcpy(buf + total, ln, len); total += len;
|
|
|
|
|
}
|
|
|
|
|
fclose(f); buf[total] = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void GetExeDir(char* buf, int sz)
|
|
|
|
|
{
|
|
|
|
|
GetModuleFileNameA(NULL, buf, sz);
|
|
|
|
|
char* slash = strrchr(buf, '\\');
|
|
|
|
|
if (slash) *slash = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void GenerateProtk(char* buf, int sz)
|
|
|
|
|
{
|
|
|
|
|
char dir[MAX_PATH]; GetExeDir(dir, sizeof(dir));
|
|
|
|
|
snprintf(buf, sz,
|
|
|
|
|
"NAME Resource_Library\r\n"
|
2026-09-09 21:00:40 +08:00
|
|
|
"EXEC_FILE %s\\Res_center.dll\r\n"
|
2026-08-10 23:13:58 +08:00
|
|
|
"TEXT_DIR %s\\text\r\n"
|
|
|
|
|
"STARTUP dll\r\n"
|
2026-09-09 21:00:40 +08:00
|
|
|
"REVISION 18\r\n"
|
2026-08-10 23:13:58 +08:00
|
|
|
"END\r\n",
|
|
|
|
|
dir, dir);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void SetEnvVar(const char* name, const char* value)
|
|
|
|
|
{
|
|
|
|
|
HKEY hKey;
|
|
|
|
|
if (RegCreateKeyExA(HKEY_CURRENT_USER,
|
|
|
|
|
"Environment", 0, NULL, REG_OPTION_NON_VOLATILE,
|
|
|
|
|
KEY_SET_VALUE, NULL, &hKey, NULL) == ERROR_SUCCESS) {
|
|
|
|
|
RegSetValueExA(hKey, name, 0, REG_SZ,
|
|
|
|
|
(const BYTE*)value, (DWORD)(strlen(value) + 1));
|
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
|
SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE,
|
|
|
|
|
0, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void DeleteEnvVar(const char* name)
|
|
|
|
|
{
|
|
|
|
|
HKEY hKey;
|
|
|
|
|
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Environment", 0,
|
|
|
|
|
KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
|
|
|
|
|
RegDeleteValueA(hKey, name);
|
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
|
SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE,
|
|
|
|
|
0, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void InitTheme(void)
|
|
|
|
|
{
|
|
|
|
|
hbrDark = CreateSolidBrush(RGB(32, 32, 32));
|
|
|
|
|
hbrDarker = CreateSolidBrush(RGB(22, 22, 22));
|
|
|
|
|
hbrAccent = CreateSolidBrush(RGB(0, 120, 212));
|
|
|
|
|
NONCLIENTMETRICSW nm = {sizeof(nm)};
|
|
|
|
|
SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(nm), &nm, 0);
|
|
|
|
|
nm.lfMenuFont.lfHeight = -22; nm.lfMenuFont.lfWeight = FW_SEMIBOLD;
|
|
|
|
|
hfTitle = CreateFontIndirectW(&nm.lfMenuFont);
|
|
|
|
|
nm.lfMenuFont.lfHeight = -14; nm.lfMenuFont.lfWeight = FW_NORMAL;
|
|
|
|
|
hfBody = CreateFontIndirectW(&nm.lfMenuFont);
|
|
|
|
|
nm.lfMenuFont.lfHeight = -13;
|
|
|
|
|
nm.lfMenuFont.lfPitchAndFamily = FIXED_PITCH;
|
|
|
|
|
hfMono = CreateFontIndirectW(&nm.lfMenuFont);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void DrawMetroButton(HWND hBtn, LPDRAWITEMSTRUCT dis)
|
|
|
|
|
{
|
|
|
|
|
wchar_t txt[64]; GetWindowTextW(hBtn, txt, 64);
|
|
|
|
|
int pressed = (dis->itemState & ODS_SELECTED);
|
|
|
|
|
int hot = (dis->itemState & ODS_HOTLIGHT);
|
|
|
|
|
HBRUSH br = pressed ? CreateSolidBrush(RGB(0, 90, 170))
|
|
|
|
|
: hot ? CreateSolidBrush(RGB(0, 105, 190)) : hbrAccent;
|
|
|
|
|
FillRect(dis->hDC, &dis->rcItem, br);
|
|
|
|
|
if (!pressed && !hot) DeleteObject(br);
|
|
|
|
|
SetBkMode(dis->hDC, TRANSPARENT);
|
|
|
|
|
SetTextColor(dis->hDC, RGB(255,255,255));
|
|
|
|
|
SelectObject(dis->hDC, hfTitle);
|
|
|
|
|
DrawTextW(dis->hDC, txt, -1, &dis->rcItem, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM w, LPARAM l)
|
|
|
|
|
{
|
|
|
|
|
static HWND hPrev, hNew, hGen;
|
|
|
|
|
switch (msg) {
|
|
|
|
|
case WM_CREATE: {
|
|
|
|
|
InitTheme();
|
|
|
|
|
SetClassLongPtrW(hWnd, GCLP_HBRBACKGROUND, (LONG_PTR)hbrDark);
|
|
|
|
|
|
|
|
|
|
HWND h = CreateWindowW(L"STATIC", L"Protk.dat Configurator",
|
|
|
|
|
WS_CHILD|WS_VISIBLE|SS_CENTER, 10, 8, 580, 28, hWnd, NULL, NULL, NULL);
|
|
|
|
|
SendMessageW(h, WM_SETFONT, (WPARAM)hfTitle, 1);
|
|
|
|
|
|
|
|
|
|
CreateWindowW(L"STATIC", L"Current protk.dat:",
|
|
|
|
|
WS_CHILD|WS_VISIBLE, 15, 48, 150, 20, hWnd, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
hPrev = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"",
|
|
|
|
|
WS_CHILD|WS_VISIBLE|WS_BORDER|ES_MULTILINE|ES_READONLY|
|
|
|
|
|
ES_AUTOVSCROLL|WS_VSCROLL,
|
|
|
|
|
15, 68, 570, 100, hWnd, (HMENU)ID_PREV, NULL, NULL);
|
|
|
|
|
SendMessageW(hPrev, WM_SETFONT, (WPARAM)hfMono, 1);
|
|
|
|
|
|
|
|
|
|
CreateWindowW(L"STATIC", L"New protk.dat (auto-detected):",
|
|
|
|
|
WS_CHILD|WS_VISIBLE, 15, 178, 250, 20, hWnd, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
hNew = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"",
|
|
|
|
|
WS_CHILD|WS_VISIBLE|WS_BORDER|ES_MULTILINE|ES_READONLY|
|
|
|
|
|
ES_AUTOVSCROLL|WS_VSCROLL,
|
|
|
|
|
15, 198, 570, 120, hWnd, (HMENU)ID_NEW, NULL, NULL);
|
|
|
|
|
SendMessageW(hNew, WM_SETFONT, (WPARAM)hfMono, 1);
|
|
|
|
|
|
|
|
|
|
/* Checkbox for env var */
|
|
|
|
|
hEnvCheck = CreateWindowW(L"BUTTON",
|
|
|
|
|
L"Set RES_CENTER_DIR to current path",
|
|
|
|
|
WS_CHILD|WS_VISIBLE|BS_AUTOCHECKBOX,
|
|
|
|
|
15, 328, 300, 22, hWnd, (HMENU)ID_ENV, NULL, NULL);
|
|
|
|
|
SendMessageW(hEnvCheck, WM_SETFONT, (WPARAM)hfBody, 1);
|
|
|
|
|
SendMessageW(hEnvCheck, BM_SETCHECK, BST_CHECKED, 0);
|
|
|
|
|
|
|
|
|
|
hGen = CreateWindowW(L"BUTTON", L"GENERATE protk.dat",
|
|
|
|
|
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_FLAT|BS_OWNERDRAW,
|
|
|
|
|
150, 360, 300, 36, hWnd, (HMENU)ID_GEN, NULL, NULL);
|
|
|
|
|
|
|
|
|
|
char old[4096] = {0}; ReadProtk(old, sizeof(old));
|
|
|
|
|
SetWindowTextA(hPrev, old);
|
|
|
|
|
char newp[4096] = {0}; GenerateProtk(newp, sizeof(newp));
|
|
|
|
|
SetWindowTextA(hNew, newp);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
case WM_DRAWITEM:
|
|
|
|
|
if (w == ID_GEN) DrawMetroButton(hGen, (LPDRAWITEMSTRUCT)l);
|
|
|
|
|
return 0;
|
|
|
|
|
case WM_COMMAND:
|
|
|
|
|
if (LOWORD(w) == ID_GEN) {
|
|
|
|
|
char newp[4096] = {0}; GenerateProtk(newp, sizeof(newp));
|
|
|
|
|
FILE* f = fopen("protk.dat", "wb");
|
|
|
|
|
if (f) {
|
|
|
|
|
fputs(newp, f); fclose(f);
|
|
|
|
|
SetWindowTextA(hPrev, newp);
|
|
|
|
|
|
|
|
|
|
/* handle env var */
|
|
|
|
|
if (SendMessageW(hEnvCheck, BM_GETCHECK, 0, 0) == BST_CHECKED) {
|
|
|
|
|
char dir[MAX_PATH]; GetExeDir(dir, sizeof(dir));
|
|
|
|
|
SetEnvVar("RES_CENTER_DIR", dir);
|
|
|
|
|
SetWindowTextW(hNew, L"protk.dat written.\r\nRES_CENTER_DIR set.\r\nRestart Creo.");
|
|
|
|
|
} else {
|
|
|
|
|
DeleteEnvVar("RES_CENTER_DIR");
|
|
|
|
|
SetWindowTextW(hNew, L"protk.dat written.\r\nRES_CENTER_DIR removed.\r\nRestart Creo.");
|
|
|
|
|
}
|
|
|
|
|
FlashWindow(hWnd, TRUE);
|
|
|
|
|
} else {
|
|
|
|
|
SetWindowTextW(hNew, L"ERROR: Cannot write.\r\nClose Creo if running.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
case WM_CTLCOLORSTATIC:
|
|
|
|
|
case WM_CTLCOLOREDIT:
|
|
|
|
|
SetBkColor((HDC)w, RGB(45, 45, 45));
|
|
|
|
|
SetTextColor((HDC)w, RGB(255, 255, 255));
|
|
|
|
|
return (LRESULT)hbrDarker;
|
|
|
|
|
case WM_DESTROY:
|
|
|
|
|
if (hfTitle) DeleteObject(hfTitle);
|
|
|
|
|
if (hfBody) DeleteObject(hfBody);
|
|
|
|
|
if (hfMono) DeleteObject(hfMono);
|
|
|
|
|
if (hbrDark) DeleteObject(hbrDark);
|
|
|
|
|
if (hbrDarker) DeleteObject(hbrDarker);
|
|
|
|
|
if (hbrAccent) DeleteObject(hbrAccent);
|
|
|
|
|
PostQuitMessage(0);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return DefWindowProcW(hWnd, msg, w, l);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int WINAPI WinMain(HINSTANCE hi, HINSTANCE hp, LPSTR cmd, int show)
|
|
|
|
|
{
|
|
|
|
|
(void)hp; (void)cmd; (void)show;
|
|
|
|
|
WNDCLASSW wc = {0};
|
|
|
|
|
wc.lpfnWndProc = WndProc; wc.hInstance = hi;
|
|
|
|
|
wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
|
|
|
|
|
wc.hbrBackground = CreateSolidBrush(RGB(32, 32, 32));
|
|
|
|
|
wc.lpszClassName = L"RCConfigen"; wc.hIcon = LoadIconW(hi, MAKEINTRESOURCEW(IDI_MAIN));
|
|
|
|
|
wc.style = CS_HREDRAW|CS_VREDRAW;
|
|
|
|
|
RegisterClassW(&wc);
|
|
|
|
|
|
|
|
|
|
int sw = GetSystemMetrics(SM_CXSCREEN), sh = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
|
int ww = 620, wh = 440;
|
|
|
|
|
HWND hWnd = CreateWindowExW(0, L"RCConfigen", L"Protk.dat Configurator",
|
|
|
|
|
WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_VISIBLE,
|
|
|
|
|
(sw-ww)/2, (sh-wh)/2, ww, wh, NULL, NULL, hi, NULL);
|
|
|
|
|
|
|
|
|
|
BOOL dark = TRUE;
|
|
|
|
|
DwmSetWindowAttribute(hWnd, 19, &dark, sizeof(dark));
|
|
|
|
|
DwmSetWindowAttribute(hWnd, 20, &dark, sizeof(dark));
|
|
|
|
|
|
|
|
|
|
MSG msg;
|
|
|
|
|
while (GetMessageW(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); }
|
|
|
|
|
return 0;
|
|
|
|
|
}
|