#include "stdafx.h" #include "GrbyCfg.h" #define MAX_LOADSTRING 100 #include 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 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; }