keygendr32/Keygender32/Dialog.c
2024-03-20 23:09:10 -07:00

391 lines
8.8 KiB
C

#include "stdafx.h"
#include "Nfo.h"
#include "BGM.h"
#include "Debug.h"
#include "Dialog.h"
#include "Generator.h"
#include "Nfo.h"
#include "resource.h"
#include "Starfield.h"
#include <shlwapi.h>
#define TIMER_SBANIM 0x1
#define PAUSE_TEXT _T("Pause")
#define PLAY_TEXT _T("Play")
#define WINE_USER_TEXT _T("Hey Wine user! Press F1 for more info.")
static LPCTSTR PLACEHOLDER_TEXT = _T("they/them, she/her, he/him, etc.");
static LPCTSTR szStatusBarText = _T("Now Playing: Space Debris - Captain");
static BOOL bEditFocused = FALSE;
static WNDPROC OldEditWndProc;
LPCTSTR szBannedWords[] = {
_T("helicopter"),
};
static BOOL
UserIsRunningWine(void)
{
HMODULE hNtdll = GetModuleHandle(_T("ntdll.dll"));
if (hNtdll) {
LPVOID lpWineGetVersion = GetProcAddress(hNtdll, _T("wine_get_version"));
return (lpWineGetVersion != NULL);
}
return FALSE;
}
static LRESULT CALLBACK
EditWndProc(HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
/* Oho, this one feels *cursed*.
*
* Here's the general theory: Windows XP provides EM_SETCUEBANNER,
* meaning Windows 2000/Me and below don't have placeholder text.
* Additionally, if your Windows XP is set to a CJK locale, no
* placeholder text for you.
*
* So, let's work around it by implementing our own placeholder!
* What could go wrong?
*/
switch (uMsg) {
case WM_PAINT:
// Let the original proc paint as needed
CallWindowProc(OldEditWndProc, hWnd, uMsg, wParam, lParam);
{
HDC hDC = GetDC(hWnd);
COLORREF crNormal;
TCHAR szInput[8] = {7,0};
// I don't know if it's okay to just call a WndProc like
// this, but they won't know, right?
LRESULT lResult = CallWindowProc(
OldEditWndProc,
hWnd,
EM_GETLINE,
0,
(LPARAM)szInput);
if (!lResult && !bEditFocused) {
RECT rcArea = {0};
// Get the control font
HFONT hFont = (HFONT)CallWindowProc(
OldEditWndProc,
hWnd,
WM_GETFONT,
0,
0),
hOldFont;
hOldFont = SelectObject(hDC, hFont);
// Get the selection rect, so the placeholder text lines up
CallWindowProc(
OldEditWndProc,
hWnd,
EM_GETRECT,
0,
(LPARAM)&rcArea);
// TODO: is GRAYTEXT the correct color?
crNormal = SetTextColor(hDC,
GetSysColor(COLOR_GRAYTEXT));
DrawText(hDC,
PLACEHOLDER_TEXT,
(int)_tcslen(PLACEHOLDER_TEXT),
&rcArea,
DT_VCENTER | DT_SINGLELINE);
SelectObject(hDC, hOldFont);
SetTextColor(hDC, crNormal);
}
DeleteDC(hDC);
return 0;
}
break;
default:
return CallWindowProc(OldEditWndProc, hWnd, uMsg, wParam, lParam);
}
return 0;
}
INT_PTR CALLBACK
MainDlgProc(HWND hDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
static int iParts[2];
static HCURSOR hPointer = NULL;
static BgmState bgmState = NULL;
static LPTSTR szToggleText = NULL;
static RECT rcDialog = {0};
static COLORREF crLink = 0;
TCHAR szInput[65] = {0};
static OSVERSIONINFO osver = {sizeof(OSVERSIONINFO),0};
switch (uMsg) {
case WM_INITDIALOG:
{
// At least *try* to support Windows <2000
if (GetVersionEx(&osver)) {
if (osver.dwMajorVersion >= 5) {
// COLOR_HOTLIGHT is only supported in 2k+
crLink = GetSysColor(26);
} else {
HWND hStarfield = GetDlgItem(
hDlg,
IDC_STARFIELD);
// Borrowing the link color from HTML5 spec
crLink = RGB(0, 0, 0xee);
// Win98 also seems grumpy about the amount of GDI
// rendering, so slow it down a bit
SendMessage(hStarfield,
WMU_FRAMERATE,
30,
0);
}
}
}
{
// Wine doesn't always (ever?) show the [?] button. Give the
// user another way to access it.
if (UserIsRunningWine()) {
szStatusBarText = WINE_USER_TEXT;
}
}
// initialize static vars
hPointer = LoadCursor(NULL, MAKEINTRESOURCE(32649));
bgmState = (BgmState)lParam;
szToggleText = PAUSE_TEXT;
OldEditWndProc = (WNDPROC)SetWindowLong(
GetDlgItem(hDlg, IDC_PNTYPE),
GWL_WNDPROC,
(LONG)EditWndProc);
{
// Set up status bar parts
LONG lDlgWidth = LOWORD(GetDialogBaseUnits()),
lRightWidth = (lDlgWidth * 6);
GetClientRect(hDlg, &rcDialog);
iParts[0] = rcDialog.right - lRightWidth;
iParts[1] = -1;
SendDlgItemMessage(hDlg,
IDC_STATUSBAR,
SB_SETPARTS,
2,
(LPARAM)iParts);
}
SendDlgItemMessage(hDlg,
IDC_STATUSBAR,
SB_SETTEXT,
SBT_OWNERDRAW | 0,
0);
SendDlgItemMessage(hDlg,
IDC_STATUSBAR,
SB_SETTEXT,
SBT_OWNERDRAW | 1,
0);
break;
case WM_SYSCOMMAND:
if (wParam == SC_CONTEXTHELP) {
DialogBox(
GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_ABOUT),
hDlg,
NfoDlgProc);
return TRUE;
} else {
return FALSE;
}
break;
case WM_HELP:
DialogBox(
GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_ABOUT),
hDlg,
NfoDlgProc);
return TRUE;
case WM_DRAWITEM:
if (wParam == IDC_STATUSBAR) {
LPDRAWITEMSTRUCT lpDraw = (LPDRAWITEMSTRUCT)lParam;
HFONT hFont = (HFONT)SendMessage(
lpDraw->hwndItem,
WM_GETFONT,
(WPARAM)0,
(LPARAM)0);
int iOldBkMode = SetBkMode(lpDraw->hDC, TRANSPARENT);
if (lpDraw->itemID == 0) {
// Draw the status bar text
DrawText(
lpDraw->hDC,
szStatusBarText,
-1,
&lpDraw->rcItem,
DT_VCENTER | DT_SINGLELINE);
} else if (lpDraw->itemID == 1) {
// Draw the Play/Pause "link"
HFONT hLinkFont, hOldFont;
LOGFONT lf;
COLORREF crOldColor;
GetObject(hFont, sizeof(lf), &lf);
lf.lfUnderline = TRUE;
hLinkFont = CreateFontIndirect(&lf);
hOldFont = SelectObject(lpDraw->hDC, hLinkFont);
crOldColor = SetTextColor(lpDraw->hDC, crLink);
DrawText(lpDraw->hDC,
szToggleText,
-1,
&lpDraw->rcItem,
DT_CENTER | DT_VCENTER | DT_SINGLELINE);
// put everything back how we found it
SelectObject(lpDraw->hDC, hOldFont);
SetTextColor(lpDraw->hDC, crOldColor);
DeleteObject(hLinkFont);
}
SetBkMode(lpDraw->hDC, iOldBkMode);
}
break;
case WM_NOTIFY:
if (wParam == IDC_STATUSBAR) {
LPNMMOUSE lpnm = (LPNMMOUSE)lParam;
if (lpnm->hdr.code == NM_CLICK &&
lpnm->dwItemSpec == 1) {
// Play/Pause "link"
switch (TogglePlayPause(bgmState)) {
case 0:
szToggleText = PAUSE_TEXT;
break;
case 1:
szToggleText = PLAY_TEXT;
break;
}
SendDlgItemMessage(hDlg,
IDC_STATUSBAR,
SB_SETTEXT,
SBT_OWNERDRAW | 1,
0);
// Make the border dynamic, like the original
iParts[0] = (rcDialog.right - rcDialog.left) -
(LOWORD(GetDialogBaseUnits()) * (int)_tcslen(szToggleText));
SendDlgItemMessage(hDlg,
IDC_STATUSBAR,
SB_SETPARTS,
2,
(LPARAM)iParts);
}
}
break;
case WM_SETCURSOR:
if ((HWND)wParam == GetDlgItem(hDlg, IDC_STATUSBAR)) {
// Make the Play/Pause link act like a link
POINT ptCur;
GetCursorPos(&ptCur);
if (ScreenToClient(hDlg, &ptCur) &&
ptCur.x >= iParts[0]) {
SetCursor(hPointer);
SetWindowLong(hDlg, DWL_MSGRESULT, TRUE);
return TRUE;
}
}
break;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK) {
// Generate button pressed
LRESULT lResult;
TCHAR szKeyOut[19] = {0};
szInput[0] = 64;
lResult = SendDlgItemMessage(
hDlg,
IDC_PNTYPE,
EM_GETLINE,
0,
(LPARAM)szInput);
if (!lResult) break;
if (GenerateKey(szInput, szKeyOut)) {
SendDlgItemMessage(hDlg,
IDC_KEYDATA,
WM_SETTEXT,
0,
(LPARAM)szKeyOut);
}
} else if (LOWORD(wParam) == IDC_PNTYPE) {
// Pro Nouns edition edit control
if (HIWORD(wParam) == EN_UPDATE) {
int i;
BOOL bEnable = TRUE;
LRESULT lResult;
szInput[0] = 64;
lResult = SendDlgItemMessage(
hDlg,
IDC_PNTYPE,
EM_GETLINE,
0,
(LPARAM)szInput);
if (!lResult) {
bEnable = FALSE;
} else {
// Handle word validation
for (i = 0; i < (sizeof(szBannedWords) / sizeof(szBannedWords[0])); i++) {
int j, x = 0, iWordLen = (int)_tcslen(szBannedWords[i]);
for (j = 0; j < (int)_tcslen(szInput); j++) {
if (iswalpha(szInput[j]) && (towlower(szInput[j]) == szBannedWords[i][x])) {
if (++x >= iWordLen) {
bEnable = FALSE;
break;
}
}
}
}
}
EnableWindow(GetDlgItem(hDlg, IDOK), bEnable);
} else if (HIWORD(wParam) == EN_SETFOCUS) {
// edit control focused, don't show the placeholder
bEditFocused = TRUE;
} else if (HIWORD(wParam) == EN_KILLFOCUS) {
bEditFocused = FALSE;
}
}
break;
case WM_CLOSE:
EndDialog(hDlg, 0);
break;
default:
return FALSE;
}
return TRUE;
}