diff options
-rw-r--r-- | c/common.cpp | 8 | ||||
-rw-r--r-- | c/common.h | 24 | ||||
-rw-r--r-- | c/episodelistview.cpp | 6 | ||||
-rw-r--r-- | c/listview.cpp | 5 | ||||
-rw-r--r-- | c/main.cpp | 58 |
5 files changed, 60 insertions, 41 deletions
diff --git a/c/common.cpp b/c/common.cpp index ba6593b..b85be49 100644 --- a/c/common.cpp +++ b/c/common.cpp @@ -61,7 +61,7 @@ Library::~Library() } /* Move message box to center of main window. */ -static LRESULT CALLBACK CBTProc(const int nCode, const WPARAM wParam, const LPARAM lParam) +static LRESULT CALLBACK CBTProc(const int nCode, const WPARAM wParam, const LPARAM lParam) noexcept { extern HWND g_hWnd; if (!g_hWnd || nCode < 0 || nCode != HCBT_ACTIVATE) @@ -87,10 +87,8 @@ static LRESULT CALLBACK CBTProc(const int nCode, const WPARAM wParam, const LPAR int EBMessageBox(const TCHAR* const tszText, const TCHAR* const tszCaption, const unsigned uType) { extern HWND g_hWnd; - HHOOK hHook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId()); - if (!hHook) return 0; + HHOOK hHook = throw_nil<SetWindowsHookEx>(WH_CBT, CBTProc, (HINSTANCE)NULL, GetCurrentThreadId()); int r = MessageBox(g_hWnd, tszText, tszCaption, uType); - UnhookWindowsHookEx(hHook); - if (!hHook) throw Win32Error(GetLastError()); + throw_nil<UnhookWindowsHookEx>(hHook); return r; } @@ -44,7 +44,7 @@ T* Library::GetProcAddress(const char* const szProc) * return nothing. The returned value must be checked before being * used, as dereferencing is undefined if the value is empty. */ template <class C, typename ...T> -std::optional<C> try_make(T ...args) +std::optional<C> maybe_make(T ...args) { try { return C(args...); @@ -53,6 +53,28 @@ std::optional<C> try_make(T ...args) } } +/* Call Windows API function and throw error if NULL is returned. */ +template <auto f, typename ...T> +inline auto throw_nil(T ...args) +{ + auto r = f(args...); + if (!r) throw Win32Error(GetLastError()); + return r; +} + +/* Call Windows API function and show a warning if NULL is returned. */ +template <auto f, typename ...T> +inline auto warn_nil(T ...args) +{ + decltype(f(args...)) r; + try { + r = throw_nil<f>(args...); + } catch (Win32Error& e) { + EBMessageBox(e.twhat(), TEXT("System Error"), MB_ICONWARNING); + } + return r; +} + /* Return integer scaled for current DPI. */ inline int Dpi(const int i) { diff --git a/c/episodelistview.cpp b/c/episodelistview.cpp index c08e6f8..e70cc06 100644 --- a/c/episodelistview.cpp +++ b/c/episodelistview.cpp @@ -90,7 +90,7 @@ LRESULT EpisodeListView::HandleNotify(const LPARAM lParam) { extern HFONT g_hfBold; if (!Pl("track_episodes","watched",pLvCd->nmcd.lItemlParam)) { - SelectObject(pLvCd->nmcd.hdc, g_hfBold); + throw_nil<SelectObject>(pLvCd->nmcd.hdc, g_hfBold); return CDRF_NEWFONT; } break; @@ -125,9 +125,9 @@ LRESULT EpisodeListView::HandleNotify(const LPARAM lParam) { extern HMENU g_hPopupMenu; const DWORD dwPos = GetMessagePos(); - TrackPopupMenu(g_hPopupMenu, TPM_RIGHTBUTTON, + throw_nil<TrackPopupMenu>(g_hPopupMenu, TPM_RIGHTBUTTON, LOWORD(dwPos), HIWORD(dwPos), 0, - m_hWndParent, NULL); + m_hWndParent, (const RECT*)NULL); break; } } diff --git a/c/listview.cpp b/c/listview.cpp index 8f5da65..fa99793 100644 --- a/c/listview.cpp +++ b/c/listview.cpp @@ -13,16 +13,15 @@ ListView::ListView(const HWND hWndParent, const HMENU hMenu, const DWORD dwStyle { m_hWndParent = hWndParent; m_bHeader = !(dwStyle & LVS_NOCOLUMNHEADER); - hWnd = CreateWindowEx( + hWnd = throw_nil<CreateWindowEx>( WS_EX_CLIENTEDGE, WC_LISTVIEW, TEXT(""), dwStyle|WS_CHILD|WS_VISIBLE|WS_VSCROLL|WS_TABSTOP|LVS_REPORT|LVS_SHOWSELALWAYS, 0, 0, 0, 0, m_hWndParent, hMenu, GetModuleHandle(NULL), this); - if (!hWnd) throw Win32Error(GetLastError()); - if (SetProp(hWnd, TEXT("this"), (HANDLE)this)) + if (throw_nil<SetProp>(hWnd, TEXT("this"), (HANDLE)this)) m_prevProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)::WndProc); @@ -45,7 +45,7 @@ static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); static INT_PTR CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM); static void UpdateTheme(); -void OnTerminate() +void OnTerminate() noexcept { try { std::rethrow_exception(std::current_exception()); @@ -89,10 +89,10 @@ int WINAPI WinMain(const HINSTANCE hInstance, const HINSTANCE, char* const, cons INITCOMMONCONTROLSEX icc; icc.dwSize = sizeof(icc); icc.dwICC = ICC_WIN95_CLASSES; - if (!InitCommonControlsEx(&icc)) throw Win32Error(GetLastError()); + throw_nil<InitCommonControlsEx>(&icc); - g_hPopupMenu = LoadMenu(NULL, MAKEINTRESOURCE(IDR_POPUPMENU)); - g_hPopupMenu = GetSubMenu(g_hPopupMenu, 0); + g_hPopupMenu = throw_nil<LoadMenu>((HINSTANCE)NULL, MAKEINTRESOURCE(IDR_POPUPMENU)); + g_hPopupMenu = throw_nil<GetSubMenu>(g_hPopupMenu, 0); WNDCLASSEX wc; memset(&wc, 0, sizeof(WNDCLASSEX)); @@ -105,31 +105,29 @@ int WINAPI WinMain(const HINSTANCE hInstance, const HINSTANCE, char* const, cons wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); wc.lpszClassName = TEXT("Episode Browser"); wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); - if (!RegisterClassEx(&wc)) throw Win32Error(GetLastError()); + throw_nil<RegisterClassEx>(&wc); /* Create window. A CBT hook is used to initialize important * global variables before any messages are sent to the new * window. It is vital that the hook is set up correctly. */ - const HHOOK hHook = SetWindowsHookEx(WH_CBT, CBTProc, 0, GetCurrentThreadId()); - if (!hHook) throw Win32Error(GetLastError()); - const HWND hWnd = CreateWindowEx( + const HHOOK hHook = throw_nil<SetWindowsHookEx>(WH_CBT, CBTProc, + (HINSTANCE)NULL, GetCurrentThreadId()); + const HWND hWnd = throw_nil<CreateWindowEx>( 0, TEXT("Episode Browser"), TEXT("Episode Browser"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, - NULL, NULL, hInstance, NULL); - if (!hHook) throw Win32Error(GetLastError()); - if (!hWnd) throw Win32Error(GetLastError()); - UnhookWindowsHookEx(hHook); + (HWND)NULL, (HMENU)NULL, hInstance, (void*)NULL); + throw_nil<UnhookWindowsHookEx>(hHook); - g_hWndStatus = CreateWindowEx( + g_hWndStatus = throw_nil<CreateWindowEx>( 0, STATUSCLASSNAME, (const TCHAR*)NULL, WS_CHILD|WS_VISIBLE|SBARS_SIZEGRIP, 0, 0, 0, 0, - hWnd, (HMENU)ID_STATUS, hInstance, NULL); + hWnd, (HMENU)ID_STATUS, hInstance, (void*)NULL); ShowWindow(hWnd, nCmdShow); @@ -161,27 +159,29 @@ static LRESULT CALLBACK CBTProc(const int nCode, const WPARAM wParam, const LPAR g_hWnd = (HWND)wParam; /* Look up constants. */ - if (auto opLib = try_make<Library>(TEXT("User32.dll"))) + if (auto opLib = maybe_make<Library>(TEXT("User32.dll"))) if (auto GetDpiForWindow = opLib->GetProcAddress<UINT(HWND)>("GetDpiForWindow")) g_iDPI = GetDpiForWindow(g_hWnd); - if (auto opLib = try_make<Library>(TEXT("uxtheme.dll"))) + if (auto opLib = maybe_make<Library>(TEXT("uxtheme.dll"))) if (opLib->GetProcAddress<void>("SetWindowTheme")) g_bThemes = 1; - LOGFONT lf; - if (auto opLib = try_make<Library>(TEXT("User32.dll"))) { + if (auto opLib = maybe_make<Library>(TEXT("User32.dll"))) { if (opLib->GetProcAddress<void>("SystemParametersInfo" WA)) { NONCLIENTMETRICS m; m.cbSize = sizeof(NONCLIENTMETRICS); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &m, 0); - g_hfNormal = CreateFontIndirect(&m.lfMessageFont); + throw_nil<SystemParametersInfo>(SPI_GETNONCLIENTMETRICS, + sizeof(NONCLIENTMETRICS), &m, 0); + g_hfNormal = throw_nil<CreateFontIndirect>(&m.lfMessageFont); } } else - g_hfNormal = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT)); - GetObject(g_hfNormal, sizeof(LOGFONT), &lf); + g_hfNormal = static_cast<HFONT>(throw_nil<GetStockObject>(DEFAULT_GUI_FONT)); + + LOGFONT lf; + throw_nil<GetObject>(g_hfNormal, sizeof(LOGFONT), &lf); lf.lfWeight = FW_BOLD; - g_hfBold = CreateFontIndirect(&lf); + g_hfBold = throw_nil<CreateFontIndirect>(&lf); /* Create child windows. */ g_pDlv = new DataListView(g_hWnd); @@ -237,7 +237,7 @@ LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, { const RECT* const lpr = (RECT*)lParam; g_iDPI = HIWORD(wParam); - SetWindowPos(hWnd, NULL, + warn_nil<SetWindowPos>(hWnd, (HWND)NULL, lpr->left, lpr->top, lpr->right-lpr->left, lpr->bottom-lpr->top, @@ -280,7 +280,7 @@ LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, TEXT(""))); } else { i = 0; - KillTimer(hWnd, IDT_TIMER); + warn_nil<KillTimer>(hWnd, IDT_TIMER); g_pElv->Update(); } break; @@ -302,8 +302,8 @@ LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, case IDM_FILE_FETCH_SCREENWRITERS: if (g_bThread) break; Pl("episode_data","thread_create","update_screenwriters",&g_aThread); - t: KillTimer(hWnd, IDT_TIMER); - SetTimer(hWnd, IDT_TIMER, 500, NULL); + t: warn_nil<KillTimer>(hWnd, IDT_TIMER); + if (!SetTimer(hWnd, IDT_TIMER, 500, (TIMERPROC)NULL)) break; SendMessage(g_hWndStatus, SB_SETTEXT, MAKEWPARAM(1,0), (LPARAM)TEXT(".")); g_bThread = 1; break; @@ -514,14 +514,14 @@ void UpdateLayout() /* Resize data list view. */ cyDlv = rc.bottom-yStatus-g_pDlv->Height(); - MoveWindow(g_pDlv->hWnd, 0, cyDlv, rc.right, rc.bottom-yStatus-cyDlv, TRUE); + throw_nil<MoveWindow>(g_pDlv->hWnd, 0, cyDlv, rc.right, rc.bottom-yStatus-cyDlv, TRUE); ListView_SetColumnWidth(g_pDlv->hWnd, DLVSIKEY, LVSCW_AUTOSIZE); cxColumn = ListView_GetColumnWidth(g_pDlv->hWnd, 0)+4; ListView_SetColumnWidth(g_pDlv->hWnd, DLVSIKEY, cxColumn); ListView_SetColumnWidth(g_pDlv->hWnd, DLVSIVALUE, rc.right-cxColumn-cxVScroll-4); /* Resize episode list view. */ - MoveWindow(g_pElv->hWnd, 0, 0, rc.right, cyDlv+1, TRUE); + throw_nil<MoveWindow>(g_pElv->hWnd, 0, 0, rc.right, cyDlv+1, TRUE); ListView_SetColumnWidth(g_pElv->hWnd, ELVSIEPISODE, LVSCW_AUTOSIZE); cxColumn = ListView_GetColumnWidth(g_pElv->hWnd, ELVSIEPISODE)+4; ListView_SetColumnWidth(g_pElv->hWnd, ELVSIEPISODE, cxColumn); |