aboutsummaryrefslogtreecommitdiff
path: root/c/main.cpp
diff options
context:
space:
mode:
authorJohn Ankarström <john@ankarstrom.se>2022-09-07 00:40:26 +0200
committerJohn Ankarström <john@ankarstrom.se>2022-09-07 00:40:26 +0200
commit2f7b69d6d4cf18ca9ca04d9a44aaa6871ce51160 (patch)
treed016a9456621b91ca902f0c1caf48468e899a553 /c/main.cpp
parent5b1a07607ba593050e37598f731f833b6faabee4 (diff)
downloadEpisodeBrowser-2f7b69d6d4cf18ca9ca04d9a44aaa6871ce51160.tar.gz
Improve error handling.
Diffstat (limited to 'c/main.cpp')
-rw-r--r--c/main.cpp127
1 files changed, 72 insertions, 55 deletions
diff --git a/c/main.cpp b/c/main.cpp
index f9d4a42..236b6d3 100644
--- a/c/main.cpp
+++ b/c/main.cpp
@@ -2,6 +2,7 @@
#include <stdexcept>
#include <windows.h>
#include <commctrl.h>
+#include <shlobj.h>
#include <libxml/xmlversion.h>
#include "datalistview.h"
@@ -40,8 +41,8 @@ BOOL (__stdcall *IsThemeActive)();
HRESULT (__stdcall *SetWindowTheme)(HWND, const wchar_t*, const wchar_t*);
/* Initialize important global state on parent window creation. */
-static void InitializeMainWindow(HWND) noexcept;
-/* Process parent window commands. */
+static void InitializeMainWindow(HWND);
+/* Process main window commands. */
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
/* Handle messages to Help > About dialog. */
static INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
@@ -54,8 +55,7 @@ int WINAPI WinMain(
_In_ char* const,
_In_ const int nCmdShow)
{
- /* Exit gracefully on uncaught exception. */
- SET_TERMINATE;
+ std::set_terminate(OnTerminate);
setbuf(stdout, nullptr);
LIBXML_TEST_VERSION;
@@ -63,12 +63,16 @@ int WINAPI WinMain(
INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(icc);
icc.dwICC = ICC_WIN95_CLASSES;
- Require(InitCommonControlsEx(&icc));
+ if (!InitCommonControlsEx(&icc))
+ throw Err(WINDOWS, L"Common controls could not be initialized: %s");
+
+ if (CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED) != S_OK)
+ throw Err(GENERIC, L"COM library could not be initialized");
WNDCLASSEX wc;
memset(&wc, 0, sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
- wc.lpfnWndProc = WndProc;
+ wc.lpfnWndProc = Except<WndProc>;
wc.hInstance = hInstance;
wc.hIcon = LoadIconW(nullptr, IDI_APPLICATION);
wc.hCursor = g_hcArrow;
@@ -76,27 +80,31 @@ int WINAPI WinMain(
wc.lpszMenuName = MAKEINTRESOURCEW(IDR_MENU);
wc.lpszClassName = L"Episode Browser";
wc.hIconSm = LoadIconW(nullptr, IDI_APPLICATION);
- Require(RegisterClassExW(&wc));
+ if (!RegisterClassExW(&wc))
+ throw Err(WINDOWS, L"Window class could not be registered: %s");
/* InitializeMainWindow is called before the first message is
* sent to WndProc. This is important, as it initializes
* global state on which WndProc relies. */
- WithNextWindow(InitializeMainWindow);
- const HWND hWnd = Require(CreateWindowExW(
+ WithNextWindow(Noexcept<InitializeMainWindow>);
+ HWND hWnd;
+ if (!(hWnd = CreateWindowExW(
0,
L"Episode Browser",
L"Episode Browser",
WS_OVERLAPPEDWINDOW|WS_CLIPCHILDREN,
XMAIN, YMAIN, 0, 0,
- nullptr, nullptr, hInstance, nullptr));
+ nullptr, nullptr, hInstance, nullptr)))
+ throw Err(WINDOWS, L"Main window could not be created: %s");
- g_window->hWndStatus = Require(CreateWindowExW(
+ if (!(g_window->hWndStatus = CreateWindowExW(
0,
STATUSCLASSNAME,
nullptr,
WS_CHILD|WS_VISIBLE|SBARS_SIZEGRIP,
0, 0, 0, 0,
- hWnd, reinterpret_cast<HMENU>(IDR_STATUS), hInstance, nullptr));
+ hWnd, reinterpret_cast<HMENU>(IDR_STATUS), hInstance, nullptr)))
+ throw Err(WINDOWS, L"Status bar could not be created: %s");
ShowWindow(hWnd, nCmdShow);
@@ -119,7 +127,7 @@ int WINAPI WinMain(
return 0;
}
-static void InitializeMainWindow_(const HWND hWnd)
+static void InitializeMainWindow(const HWND hWnd)
{
/* This code is run ONCE, at the creation of the top-level
* window -- before WndProc! This is important, as it
@@ -139,17 +147,22 @@ static void InitializeMainWindow_(const HWND hWnd)
m.cbSize -= 4;
#endif
- Require(SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSW), &m, 0));
- g_hfNormal = Require(CreateFontIndirectW(&m.lfMessageFont));
+ if (!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSW), &m, 0))
+ throw Err(WINDOWS, L"Non-client metrics could not be queried: %s");
+ if (!(g_hfNormal = CreateFontIndirectW(&m.lfMessageFont)))
+ throw Err(WINDOWS, L"System message font could not be loaded: %s");
} else
- g_hfNormal = static_cast<HFONT>(Require(GetStockObject(DEFAULT_GUI_FONT)));
+ if (!(g_hfNormal = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT))))
+ throw Err(WINDOWS, L"System GUI font could not be loaded: %s");
/* Load bold font. */
{
LOGFONTW lf;
- Require(GetObjectW(g_hfNormal, sizeof(LOGFONTW), &lf));
+ if (!GetObjectW(g_hfNormal, sizeof(LOGFONTW), &lf))
+ throw Err(WINDOWS, L"Logical system font could not be loaded: %s");
lf.lfWeight = FW_BOLD;
- g_hfBold = Require(CreateFontIndirectW(&lf));
+ if (!(g_hfBold = CreateFontIndirectW(&lf)))
+ throw Err(WINDOWS, L"Bold font could not be loaded: %s");
}
/* Load theme functions, if available. */
@@ -161,36 +174,21 @@ static void InitializeMainWindow_(const HWND hWnd)
g_window = new Window(hWnd);
}
-void InitializeMainWindow(const HWND hWnd) noexcept
-{
- try {
- InitializeMainWindow_(hWnd);
- } catch (...) {
- EBMessageBox(What(), L"Initialization Error", MB_ICONERROR);
- exit(1);
- }
-}
-
LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
{
- try {
- return g_window->WndProc(hWnd, uMsg, wParam, lParam);
- } catch (...) {
- EBMessageBox(What(), L"Error");
- }
- return DefWindowProc(hWnd, uMsg, wParam, lParam);
+ return g_window->WndProc(hWnd, uMsg, wParam, lParam);
}
INT_PTR CALLBACK AboutDlgProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM)
{
switch (uMsg) {
case WM_CLOSE:
- EndDialog(hWnd, IDOK);
+ EndDialog(hWnd, IDCANCEL);
return TRUE;
case WM_COMMAND:
- if (LOWORD(wParam) == IDOK)
- EndDialog(hWnd, IDOK);
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
+ EndDialog(hWnd, LOWORD(wParam));
return TRUE;
default:
@@ -200,19 +198,33 @@ INT_PTR CALLBACK AboutDlgProc(const HWND hWnd, const UINT uMsg, const WPARAM wPa
INT_PTR CALLBACK PreferencesDlgProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM)
{
- switch (uMsg) {
- case WM_CLOSE:
- EndDialog(hWnd, IDOK);
+ if (uMsg == WM_CLOSE) {
+ EndDialog(hWnd, IDCANCEL);
return TRUE;
-
- case WM_COMMAND:
- if (LOWORD(wParam) == IDOK)
- EndDialog(hWnd, IDOK);
+ } else if (uMsg == WM_COMMAND) {
+ switch (LOWORD(wParam)) {
+ case IDOK:
+ case IDCANCEL:
+ EndDialog(hWnd, LOWORD(wParam));
+ return TRUE;
+ case IDC_BROWSE:
+ {
+ wchar_t path[MAX_PATH];
+ BROWSEINFOW bi = {hWnd, nullptr, path,
+ L"Episode Browser will look for local episode files in the"
+ L" chosen directory and its subdirectories.",
+ BIF_EDITBOX|BIF_NEWDIALOGSTYLE|BIF_NONEWFOLDERBUTTON};
+ if (auto pidl = SHBrowseForFolderW(&bi)) {
+ if (!SHGetPathFromIDListW(pidl, path))
+ throw Err(GENERIC, L"Invalid path selected.");
+ EBMessageBox(path, L"You Chose");
+ }
+ return TRUE;
+ }
+ }
return TRUE;
-
- default:
+ } else
return FALSE;
- }
}
LRESULT CALLBACK Window::WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam)
@@ -265,11 +277,12 @@ LRESULT CALLBACK Window::WndProc(const HWND hWnd, const UINT uMsg, const WPARAM
/* Get new window position/size. */
{
const RECT* const r = reinterpret_cast<RECT*>(lParam);
- Prefer(SetWindowPos(hWnd, nullptr,
+ if (!SetWindowPos(hWnd, nullptr,
r->left, r->top,
r->right-r->left,
r->bottom-r->top,
- SWP_NOZORDER|SWP_NOACTIVATE));
+ SWP_NOZORDER|SWP_NOACTIVATE))
+ throw Err(WINDOWS, L"");
UpdateLayout(r->right-r->left, r->bottom-r->top);
}
return 0;
@@ -395,7 +408,7 @@ void Window::HandleMainMenu(const HWND hWnd, const WORD command)
GetModuleHandle(nullptr),
MAKEINTRESOURCE(IDD_PREFERENCES),
hWnd,
- PreferencesDlgProc);
+ Except<PreferencesDlgProc>);
break;
case IDM_FILE_FETCH_DATA:
@@ -417,7 +430,7 @@ void Window::HandleMainMenu(const HWND hWnd, const WORD command)
GetModuleHandle(nullptr),
MAKEINTRESOURCE(IDD_ABOUT),
hWnd,
- AboutDlgProc);
+ Except<AboutDlgProc>);
break;
case IDM_VIEW_WATCHED:
@@ -465,16 +478,20 @@ void Window::UpdateLayout(int w, int h)
RECT rc, rrStatus;
if (w && h) rc = {0, 0, w, h};
- else Require(GetClientRect(hWnd, &rc));
- Require(GetRelativeRect(hWndStatus, &rrStatus));
+ else if (!GetClientRect(hWnd, &rc))
+ throw Err(WINDOWS, L"Window rectangle could not be retrieved: %s");
+ if (!GetRelativeRect(hWndStatus, &rrStatus))
+ throw Err(WINDOWS, L"Status bar rectangle could not be retrieved: %s");
SendMessageW(hWnd, WM_SETREDRAW, FALSE, 0);
/* Resize list views. */
const long pad = EBIsThemeActive()? Dpi(6): 0; /* Add padding in modern themes. */
const long cyDlv = rrStatus.top-dlv.Height()-pad;
- Require(SetWindowRect(dlv.hWnd, pad, cyDlv, rc.right-pad, rrStatus.top-pad));
- Require(SetWindowRect(elv.hWnd, pad, pad, rc.right-pad, cyDlv-pad));
+ if (!SetWindowRect(dlv.hWnd, pad, cyDlv, rc.right-pad, rrStatus.top-pad))
+ throw Err(WINDOWS, L"Data list view rectangle could not be updated: %s");
+ if (!SetWindowRect(elv.hWnd, pad, pad, rc.right-pad, cyDlv-pad))
+ throw Err(WINDOWS, L"Episode list view rectangle could not be updated: %s");
dlv.ResizeColumns(rc.right-pad-pad);
elv.ResizeColumns(rc.right-pad-pad);