Grabby/GrbyCfg/GrbyCfg.c
snow flurry 69476552e8 Overhaul repository structure to add config
I wish I didn't end up doing this all at once, but ah well. Quick rundown:

- CommonCfg contains config/registry functions shared between Grabby and GrbyCfg.
- GrbyCfg provides a dialog for configuring Grabby.

git-svn-id: svn://vcs.sdm.2ki.xyz/Grabby/trunk@16 27729192-006e-004d-b9b5-06fbd0ef7001
2024-02-26 06:18:00 +00:00

272 lines
5.8 KiB
C

#include "stdafx.h"
#include "GrbyCfg.h"
#define MAX_LOADSTRING 100
#include <stdio.h>
INT_PTR CALLBACK ConfigDlgProc(HWND, UINT, WPARAM, LPARAM);
/**
* Print an error with a given context before bailing out
*/
void Die(LPTSTR lpContextMsg)
{
LPCTSTR lpszFmt = "%s: %s";
int iFullLen;
LPTSTR lpszError = NULL,
lpszFullMsg = NULL;
// The whole point of this is to print an actual message, so get the
// actual message
if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
0,
(LPTSTR) &lpszError,
0,
NULL))
{
if (lpszError != NULL) LocalFree(lpszError);
lpszError = _T("unknown error");
}
// Create our WMU_* messages
InitUserMsgs();
iFullLen = _sctprintf(lpszFmt, lpContextMsg, lpszError);
lpszFullMsg = (LPTSTR) LocalAlloc(LPTR, sizeof(TCHAR) * (iFullLen + 1));
if (lpszFullMsg == NULL) {
// I'm honestly gonna guess if we get here, we're out of memory.
// So let's print what we have and bail
MessageBox(NULL,
lpContextMsg,
_T("Catastrophic Error"),
MB_OK | MB_ICONERROR);
} else {
_sntprintf(lpszFullMsg, iFullLen, lpszFmt, lpContextMsg, lpszError);
MessageBox(NULL,
lpszFullMsg,
_T("Fatal Error"),
MB_OK | MB_ICONERROR);
}
ExitProcess(1);
}
HINSTANCE g_hInstance = NULL;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
BOOL bRet;
MSG msg;
HWND hDlg;
INITCOMMONCONTROLSEX lpInitCtrls = {0};
HRESULT hrRet;
g_hInstance = hInstance;
// Required for tab control
lpInitCtrls.dwSize = sizeof(INITCOMMONCONTROLSEX);
lpInitCtrls.dwICC = ICC_WIN95_CLASSES;
if (!InitCommonControlsEx(&lpInitCtrls)) {
MessageBox(NULL,
_T("Couldn't initialize comctl32! Not sure why..."),
_T("Ooh, rare bug!"),
MB_OK | MB_ICONERROR);
return 1;
}
// Required for folder browse dialog
hrRet = CoInitializeEx(NULL,
COINIT_APARTMENTTHREADED);
if (hrRet != S_OK) {
MessageBox(NULL,
_T("Couldn't initialize COM!?"),
_T("dot com bust u_u"),
MB_OK | MB_ICONERROR);
return 1;
}
hDlg = CreateDialog(hInstance,
MAKEINTRESOURCE(IDD_CONFIGDIALOG),
NULL,
ConfigDlgProc);
if (!hDlg) {
Die("CreateDialog failed");
}
ShowWindow(hDlg, nCmdShow);
while ((bRet = GetMessage(&msg, hDlg, 0, 0)) != FALSE) {
if (bRet == -1) {
// TODO: error handling
break;
} else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
// Helper macro to create a new text (i.e., no icon) tab for config
// items.
//
// NOTE: This is written to use <name>Tab_DlgProc for dlgProc. This
// assumes that tabs will always be valid (enough) for a function
// identifier.
#define NEW_TEXTTAB(name, res) {{ \
TCIF_TEXT, \
0, 0, \
_T(#name), \
sizeof(_T(#name)) / sizeof(TCHAR), \
0, 0 \
}, \
res, \
name##Tab_DlgProc, \
NULL \
}
INT_PTR CALLBACK
ConfigDlgProc(HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
// Define the tab metadata
static struct {
TCITEM tciTab;
int child;
DLGPROC dlgProc;
HWND hWnd;
} tabs[] = {
NEW_TEXTTAB(General,
IDD_GENCONFIG),
NEW_TEXTTAB(Upload,
IDD_UPLOADCONFIG)
};
BOOL bClose = FALSE;
const int tabCount = (sizeof(tabs) / sizeof(tabs[0]));
switch (uMsg) {
case WM_INITDIALOG: {
RECT rcTab;
int i;
HWND hTabCtrl = GetDlgItem(hWnd, IDC_TABVIEW);
if (!hTabCtrl) {
Die("Couldn't get tab control");
}
for (i = 0; i < tabCount; i++) {
int iResult = TabCtrl_InsertItem(
hTabCtrl,
i,
&tabs[i].tciTab);
if (iResult == -1) {
Die("Couldn't create tabs");
}
// Attach the child dialog
tabs[i].hWnd = CreateDialog(g_hInstance,
MAKEINTRESOURCE(tabs[i].child),
hWnd,
tabs[i].dlgProc);
if (!tabs[i].hWnd) {
Die("Couldn't create child tab");
}
}
// This has to happen after the tabs are inserted,
// or else we get the wrong client area (tabs don't
// exist yet!)
GetWindowRect(hTabCtrl, &rcTab);
MapWindowPoints(NULL, hWnd, (LPPOINT)&rcTab, 2);
TabCtrl_AdjustRect(hTabCtrl, FALSE, &rcTab);
for (i = 0; i < tabCount; i++) {
SetWindowPos(tabs[i].hWnd,
HWND_TOP,
rcTab.left,
rcTab.top,
rcTab.right - rcTab.left,
rcTab.bottom - rcTab.top,
(i == 0) ? SWP_SHOWWINDOW : 0);
}
}
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDCANCEL:
DestroyWindow(hWnd);
break;
case IDOK:
bClose = TRUE;
/* PASSTHRU */
case IDC_APPLY: {
int i;
for (i = 0; i < tabCount; i++) {
SendMessage(tabs[i].hWnd,
WMU_SAVE_CONFIG,
0, 0);
}
EnableWindow(GetDlgItem(hWnd, IDC_APPLY), FALSE);
// Handle OK button (Apply + Close)
if (bClose) SendMessage(hWnd,
WM_CLOSE,
0,
0);
}
break;
default:
// TODO: other buttons
break;
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_NOTIFY:
{
LPNMHDR pnmh = (LPNMHDR)lParam;
if (pnmh->code == TCN_SELCHANGE) {
int idx = TabCtrl_GetCurSel(pnmh->hwndFrom);
if (idx < tabCount) {
int i;
for (i = 0; i < tabCount; i++) {
if (tabs[i].hWnd) {
// If it's the child we want, show it.
// If not, hide it.
ShowWindow(tabs[i].hWnd,
(i == idx) ? SW_SHOW : SW_HIDE);
}
}
}
// If idx >= tabCount, ignore the message
}
}
break;
default:
// User-defined messages
if (uMsg == WMU_SETTING_CHANGED) {
EnableWindow(GetDlgItem(hWnd, IDC_APPLY), TRUE);
} else {
// Not our message, ignore
return FALSE;
}
}
return TRUE;
}