/*
 * Screen Dimmer - Transparent overlay dimmer for Windows
 *
 * Features:
 *   - Fullscreen transparent black overlay (click-through)
 *   - On-screen brightness popup with fade-out
 *   - System tray icon with context menu
 *   - Global hotkeys, config persistence, multi-monitor, single-instance
 *
 * Hotkeys:
 *   Ctrl+Alt+Down   Increase dim (darker)
 *   Ctrl+Alt+Up     Decrease dim (brighter)
 *   Ctrl+Alt+Space  Toggle dimming on/off
 *   Ctrl+Alt+Numpad0-9  Set darkness inversely (90%, 80%, ..., 0%)
 *
 * Tray:
 *   Right-click  = Menu (toggle, dim presets, exit)
 *   Double-click = Toggle dimming
 *
 * Config: auto-saved to dimmer.ini beside the exe
 *
 * Build (MinGW):
 *   g++ -O2 -std=c++17 -mwindows -Wall -o dimmer.exe dimmer.cpp -luser32 -lgdi32 -lshell32
 */

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif
#ifndef UNICODE
#define UNICODE
#endif
#ifndef _UNICODE
#define _UNICODE
#endif

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <shellapi.h>
#include <cstdio>
#include <cstdlib>

/* ================================================================
 * Constants
 * ================================================================ */
enum { WM_TRAY_ICON = WM_USER + 1 };

enum HotKeys {
    HK_DIM_DOWN = 1,
    HK_DIM_UP   = 2,
    HK_TOGGLE   = 3,
    HK_NUMPAD_0 = 10,
    HK_NUMPAD_1,
    HK_NUMPAD_2,
    HK_NUMPAD_3,
    HK_NUMPAD_4,
    HK_NUMPAD_5,
    HK_NUMPAD_6,
    HK_NUMPAD_7,
    HK_NUMPAD_8,
    HK_NUMPAD_9,
};

enum MenuCmds {
    IDM_TOGGLE    = 2000,
    IDM_LEVEL_0   = 2010,
    IDM_LEVEL_10  = 2011,
    IDM_LEVEL_20  = 2012,
    IDM_LEVEL_30  = 2013,
    IDM_LEVEL_40  = 2014,
    IDM_LEVEL_50  = 2015,
    IDM_LEVEL_60  = 2016,
    IDM_LEVEL_70  = 2017,
    IDM_LEVEL_80  = 2018,
    IDM_LEVEL_90  = 2019,
    IDM_LEVEL_100 = 2020,
    IDM_EXIT      = 2030,
};

static const wchar_t CLASS_OVERLAY[] = L"DimmerOverlayClass";
static const wchar_t CLASS_POPUP[]   = L"DimmerPopupClass";
static const wchar_t CLASS_MAIN[]    = L"DimmerMainClass";
static const wchar_t MUTEX_NAME[]    = L"ScreenDimmerMutex_v3";

/* ================================================================
 * Global state
 * ================================================================ */
static HINSTANCE       g_hInst     = NULL;
static HWND            g_hMain     = NULL;
static HWND            g_hOverlay  = NULL;
static HWND            g_hPopup    = NULL;
static HICON           g_hTrayIcon = NULL;
static HFONT           g_hFontLg   = NULL;
static HANDLE          g_hMutex    = NULL;
static NOTIFYICONDATAW g_nid       = {};

static BYTE  g_dimLevel = 80;
static BYTE  g_step     = 50;
static bool  g_enabled  = true;
static bool  g_running  = true;

static UINT_PTR g_fadeTimer = 0;
static int      g_fadeAlpha = 0;

static wchar_t g_iniPath[MAX_PATH] = {};

/* ================================================================
 * Helpers
 * ================================================================ */
static void clampDim() {
    if (g_dimLevel > 255) g_dimLevel = 255;
}

static int brightPct() {
    return 100 - (int)(g_dimLevel * 100.0 / 255.0 + 0.5);
}

static void initIniPath() {
    GetModuleFileNameW(NULL, g_iniPath, MAX_PATH);
    wchar_t *dot = wcsrchr(g_iniPath, L'.');
    if (dot) wcscpy(dot, L".ini");
}

static void loadConfig() {
    initIniPath();
    g_dimLevel = (BYTE)GetPrivateProfileIntW(L"Dimmer", L"Level", 80, g_iniPath);
    clampDim();
    g_enabled = GetPrivateProfileIntW(L"Dimmer", L"Enabled", 1, g_iniPath) != 0;
    g_step = (BYTE)GetPrivateProfileIntW(L"Dimmer", L"Step", 50, g_iniPath);
    // if (g_step < 5)  g_step = 5;
    // if (g_step > 50) g_step = 50;
}

static void saveConfig() {
    wchar_t buf[16];
    _itow(g_dimLevel, buf, 10);
    WritePrivateProfileStringW(L"Dimmer", L"Level", buf, g_iniPath);
    WritePrivateProfileStringW(L"Dimmer", L"Enabled", g_enabled ? L"1" : L"0", g_iniPath);
    _itow(g_step, buf, 10);
    WritePrivateProfileStringW(L"Dimmer", L"Step", buf, g_iniPath);
}

/* ================================================================
 * Programmatic tray icon
 * ================================================================ */
static HICON createTrayIcon() {
    HICON hIcon = NULL;
    HDC hdc = GetDC(NULL);

    HDC cdc = CreateCompatibleDC(hdc);
    HBITMAP hbC = CreateCompatibleBitmap(hdc, 16, 16);
    HBITMAP obC = (HBITMAP)SelectObject(cdc, hbC);
    {
        HBRUSH bg = CreateSolidBrush(RGB(60, 90, 180));
        RECT r = { 0, 0, 16, 16 };
        FillRect(cdc, &r, bg);
        DeleteObject(bg);
    }
    SelectObject(cdc, obC);
    DeleteDC(cdc);

    HDC mdc = CreateCompatibleDC(hdc);
    HBITMAP hbM = CreateBitmap(16, 16, 1, 1, NULL);
    HBITMAP obM = (HBITMAP)SelectObject(mdc, hbM);
    SelectObject(mdc, GetStockObject(WHITE_BRUSH));
    PatBlt(mdc, 0, 0, 16, 16, PATCOPY);
    SelectObject(mdc, GetStockObject(BLACK_BRUSH));
    Ellipse(mdc, 1, 0, 15, 15);
    SelectObject(mdc, obM);
    DeleteDC(mdc);

    ReleaseDC(NULL, hdc);

    ICONINFO ii = {};
    ii.fIcon    = TRUE;
    ii.hbmMask  = hbM;
    ii.hbmColor = hbC;
    hIcon = CreateIconIndirect(&ii);
    DeleteObject(hbM);
    DeleteObject(hbC);
    return hIcon;
}

/* ================================================================
 * Overlay
 * ================================================================ */
/* re-assert HWND_TOPMOST without activating the window */
static void forceOverlayOnTop() {
    if (!g_hOverlay) return;
    if (g_enabled && g_dimLevel > 0 && IsWindowVisible(g_hOverlay)) {
        SetWindowPos(g_hOverlay, HWND_TOPMOST, 0, 0, 0, 0,
                     SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
    }
}

static void refreshOverlay() {
    if (!g_hOverlay) return;

    if (g_enabled && g_dimLevel > 0) {
        int x  = GetSystemMetrics(SM_XVIRTUALSCREEN);
        int y  = GetSystemMetrics(SM_YVIRTUALSCREEN);
        int cx = GetSystemMetrics(SM_CXVIRTUALSCREEN);
        int cy = GetSystemMetrics(SM_CYVIRTUALSCREEN);
        /* SetWindowPos with HWND_TOPMOST re-asserts Z-order explicitly;
         * ShowWindow alone does not re-push the window to top of the topmost layer */
        SetWindowPos(g_hOverlay, HWND_TOPMOST, x, y, cx, cy,
                     SWP_NOACTIVATE | SWP_SHOWWINDOW);
        SetLayeredWindowAttributes(g_hOverlay, 0, g_dimLevel, LWA_ALPHA);
    } else {
        ShowWindow(g_hOverlay, SW_HIDE);
    }

    /* tray tooltip */
    int dimP = (int)(g_dimLevel * 100.0 / 255.0 + 0.5);
    _snwprintf(g_nid.szTip, 128,
               L"Screen Dimmer  |  Brightness %d%%  |  Dim %d%%",
               brightPct(), dimP);
    Shell_NotifyIconW(NIM_MODIFY, &g_nid);

    saveConfig();
}

/* ================================================================
 * On-screen popup (shows briefly on hotkey change)
 * ================================================================ */
static void showPopup() {
    if (!g_hPopup) return;

    wchar_t text[64];
    _snwprintf(text, 64, L"Brightness %d%%", brightPct());
    SetWindowTextW(g_hPopup, text);

    HDC hdc = GetDC(g_hPopup);
    HFONT oldF = (HFONT)SelectObject(hdc, g_hFontLg);
    SIZE sz = {};
    GetTextExtentPoint32W(hdc, text, (int)wcslen(text), &sz);
    SelectObject(hdc, oldF);
    ReleaseDC(g_hPopup, hdc);

    int w = sz.cx + 52;
    int h = 62;
    int sw = GetSystemMetrics(SM_CXSCREEN);
    int sh = GetSystemMetrics(SM_CYSCREEN);
    MoveWindow(g_hPopup, (sw - w) / 2, sh - 110 - h, w, h, TRUE);

    g_fadeAlpha = 230;
    SetLayeredWindowAttributes(g_hPopup, 0, (BYTE)g_fadeAlpha, LWA_ALPHA);
    ShowWindow(g_hPopup, SW_SHOWNA);
    InvalidateRect(g_hPopup, NULL, TRUE);

    if (g_fadeTimer) KillTimer(g_hMain, g_fadeTimer);
    g_fadeTimer = SetTimer(g_hMain, 1, 40, NULL);
}

static void hidePopup() {
    if (g_hPopup) ShowWindow(g_hPopup, SW_HIDE);
    if (g_fadeTimer) { KillTimer(g_hMain, g_fadeTimer); g_fadeTimer = 0; }
}

/* ================================================================
 * Tray context menu
 * ================================================================ */
static HMENU buildTrayMenu() {
    HMENU menu = CreatePopupMenu();

    UINT chk = g_enabled ? MF_CHECKED : MF_UNCHECKED;
    AppendMenuW(menu, MF_STRING | chk, IDM_TOGGLE,
                g_enabled ? L"  Dimming ON" : L"  Dimming OFF");

    HMENU levels = CreatePopupMenu();
    for (int i = 0; i <= 10; i++) {
        int pct = i * 10;
        BYTE lvl = (BYTE)(pct * 255 / 100);
        if (i == 0)  lvl = 0;
        if (i == 10) lvl = 255;

        wchar_t label[32];
        _snwprintf(label, 32, L"  %3d%%", pct);
        UINT flags = MF_STRING;
        if (g_dimLevel >= lvl - 6 && g_dimLevel <= lvl + 6) flags |= MF_CHECKED;
        AppendMenuW(levels, flags, IDM_LEVEL_0 + i, label);
    }
    AppendMenuW(menu, MF_POPUP, (UINT_PTR)levels, L"Dim Level");

    AppendMenuW(menu, MF_SEPARATOR, 0, NULL);
    AppendMenuW(menu, MF_STRING, IDM_EXIT, L"Exit");
    return menu;
}

/* ================================================================
 * Window procedures
 * ================================================================ */

/* --- Overlay (black, fullscreen, click-through) --- */
static LRESULT CALLBACK OverlayProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {
    case WM_ERASEBKGND: return 1;
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        RECT rc;
        GetClientRect(hwnd, &rc);
        FillRect(hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH));
        EndPaint(hwnd, &ps);
        return 0;
    }
    case WM_DISPLAYCHANGE:
        PostMessage(g_hMain, WM_DISPLAYCHANGE, wp, lp);
        return 0;
    default:
        return DefWindowProcW(hwnd, msg, wp, lp);
    }
}

/* --- Popup indicator (text + bar, click-through, auto-fade) --- */
static LRESULT CALLBACK PopupProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {
    case WM_ERASEBKGND: return 1;
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        RECT rc;
        GetClientRect(hwnd, &rc);

        HPEN   pen  = CreatePen(PS_SOLID, 1, RGB(55, 55, 65));
        HPEN   oPen = (HPEN)SelectObject(hdc, pen);
        HBRUSH bg   = CreateSolidBrush(RGB(30, 30, 38));
        HBRUSH oBg  = (HBRUSH)SelectObject(hdc, bg);
        RoundRect(hdc, rc.left, rc.top, rc.right, rc.bottom, 10, 10);
        SelectObject(hdc, oBg);
        SelectObject(hdc, oPen);
        DeleteObject(pen);
        DeleteObject(bg);

        int len = GetWindowTextLengthW(hwnd);
        if (len > 0) {
            wchar_t *buf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
            if (buf) {
                GetWindowTextW(hwnd, buf, len + 1);
                SetBkMode(hdc, TRANSPARENT);
                SetTextColor(hdc, RGB(220, 220, 230));
                HFONT oF = (HFONT)SelectObject(hdc, g_hFontLg);
                RECT tr = { rc.left + 4, rc.top, rc.right - 4, rc.bottom - 16 };
                DrawTextW(hdc, buf, len, &tr, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
                SelectObject(hdc, oF);
                free(buf);
            }
        }

        int pad  = 20;
        int barX = rc.left + pad;
        int barY = rc.bottom - 10;
        int barW = rc.right - rc.left - pad * 2;
        int barH = 4;
        if (barW > 0) {
            RECT barRc = { barX, barY, barX + barW, barY + barH };
            HBRUSH barBg = CreateSolidBrush(RGB(55, 55, 65));
            FillRect(hdc, &barRc, barBg);
            DeleteObject(barBg);

            int fillW = (int)(barW * (1.0 - g_dimLevel / 255.0));
            if (fillW > 0) {
                RECT fillRc = { barX, barY, barX + fillW, barY + barH };
                HBRUSH barFg = CreateSolidBrush(RGB(170, 175, 200));
                FillRect(hdc, &fillRc, barFg);
                DeleteObject(barFg);
            }
        }

        EndPaint(hwnd, &ps);
        return 0;
    }
    default:
        return DefWindowProcW(hwnd, msg, wp, lp);
    }
}

/* --- Main (message-only: hotkeys, tray, timer) --- */
static LRESULT CALLBACK MainProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {

    /* ---- Hotkeys ---- */
    case WM_HOTKEY:
        switch (LOWORD(wp)) {
        case HK_DIM_DOWN:
            if (g_dimLevel < 255) {
                g_dimLevel = (BYTE)((g_dimLevel + g_step > 255) ? 255 : g_dimLevel + g_step);
                clampDim();
                refreshOverlay();
                showPopup();
            }
            break;
        case HK_DIM_UP:
            if (g_dimLevel > 0) {
                g_dimLevel = (BYTE)((g_dimLevel < g_step) ? 0 : g_dimLevel - g_step);
                clampDim();
                refreshOverlay();
                showPopup();
            }
            break;
        case HK_TOGGLE:
            g_enabled = !g_enabled;
            refreshOverlay();
            break;
        default:
            /* Numpad 0-9: inverse darkness — 0=90% (darkest), 9=0% (off) */
            if (wp >= HK_NUMPAD_0 && wp <= HK_NUMPAD_9) {
                int idx = (int)(wp - HK_NUMPAD_0);
                int inv = 9 - idx;
                g_dimLevel = (BYTE)(inv * 255 / 10);
                if (inv == 0) g_dimLevel = 0;
                g_enabled = (g_dimLevel > 0);
                clampDim();
                refreshOverlay();
                showPopup();
            }
            break;
        }
        return 0;

    /* ---- Tray icon messages ---- */
    case WM_TRAY_ICON:
        switch (LOWORD(lp)) {
        case WM_RBUTTONUP:
        case WM_CONTEXTMENU: {
            POINT pt;
            GetCursorPos(&pt);
            SetForegroundWindow(hwnd);
            HMENU menu = buildTrayMenu();
            int cmd = TrackPopupMenu(menu, TPM_RETURNCMD | TPM_NONOTIFY,
                                     pt.x, pt.y, 0, hwnd, NULL);
            DestroyMenu(menu);
            PostMessage(hwnd, WM_NULL, 0, 0);

            switch (cmd) {
            case IDM_TOGGLE:
                g_enabled = !g_enabled;
                refreshOverlay();
                break;
            case IDM_EXIT:
                g_running = false;
                DestroyWindow(hwnd);
                break;
            default:
                if (cmd >= IDM_LEVEL_0 && cmd <= IDM_LEVEL_100) {
                    int idx = cmd - IDM_LEVEL_0;
                    g_dimLevel = (BYTE)(idx * 255 / 10);
                    if (idx == 0)  g_dimLevel = 0;
                    if (idx == 10) g_dimLevel = 255;
                    clampDim();
                    refreshOverlay();
                    showPopup();
                }
                break;
            }
            return 0;
        }
        case WM_LBUTTONDBLCLK:
            g_enabled = !g_enabled;
            refreshOverlay();
            return 0;
        }
        return 0;

    /* ---- Fade-out timer (ID=1) / Z-order re-assert timer (ID=2) ---- */
    case WM_TIMER:
        if ((UINT_PTR)wp == 1 && g_fadeTimer) {
            g_fadeAlpha -= 5;
            if (g_fadeAlpha <= 0) {
                hidePopup();
            } else if (g_hPopup) {
                SetLayeredWindowAttributes(g_hPopup, 0, (BYTE)g_fadeAlpha, LWA_ALPHA);
            }
        } else if ((UINT_PTR)wp == 2) {
            /* periodically re-assert HWND_TOPMOST so floating apps can't steal Z-order */
            forceOverlayOnTop();
        }
        return 0;

    case WM_DISPLAYCHANGE:
        refreshOverlay();
        return 0;

    case WM_DESTROY:
        hidePopup();
        if (g_hOverlay) DestroyWindow(g_hOverlay);
        if (g_hPopup)   DestroyWindow(g_hPopup);
        Shell_NotifyIconW(NIM_DELETE, &g_nid);
        PostQuitMessage(0);
        return 0;

    default:
        return DefWindowProcW(hwnd, msg, wp, lp);
    }
}

/* ================================================================
 * Initialisation helpers
 * ================================================================ */
static bool registerClasses() {
    WNDCLASSEXW wc = {};

    /* overlay */
    wc.cbSize        = sizeof(wc);
    wc.lpfnWndProc   = OverlayProc;
    wc.hInstance      = g_hInst;
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.lpszClassName  = CLASS_OVERLAY;
    if (!RegisterClassExW(&wc)) return false;

    /* popup */
    wc = {};
    wc.cbSize        = sizeof(wc);
    wc.lpfnWndProc   = PopupProc;
    wc.hInstance      = g_hInst;
    wc.lpszClassName  = CLASS_POPUP;
    if (!RegisterClassExW(&wc)) return false;

    /* main (message-only) */
    wc = {};
    wc.cbSize        = sizeof(wc);
    wc.lpfnWndProc   = MainProc;
    wc.hInstance      = g_hInst;
    wc.lpszClassName  = CLASS_MAIN;
    if (!RegisterClassExW(&wc)) return false;

    return true;
}

static bool createWindows() {
    /* message-only window */
    g_hMain = CreateWindowW(CLASS_MAIN, L"Dimmer", 0,
                             0, 0, 0, 0, HWND_MESSAGE, NULL, g_hInst, NULL);
    if (!g_hMain) return false;

    /* fullscreen overlay */
    g_hOverlay = CreateWindowExW(
        WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TRANSPARENT |
        WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE,
        CLASS_OVERLAY, L"", WS_POPUP,
        0, 0, 0, 0, NULL, NULL, g_hInst, NULL);
    if (!g_hOverlay) return false;

    /* on-screen indicator */
    g_hPopup = CreateWindowExW(
        WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TRANSPARENT |
        WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE,
        CLASS_POPUP, L"", WS_POPUP,
        0, 0, 0, 0, NULL, NULL, g_hInst, NULL);
    if (!g_hPopup) return false;

    return true;
}

static void setupTray() {
    g_hTrayIcon = createTrayIcon();
    if (!g_hTrayIcon) g_hTrayIcon = LoadIconW(NULL, IDI_APPLICATION);

    ZeroMemory(&g_nid, sizeof(g_nid));
    g_nid.cbSize           = sizeof(NOTIFYICONDATAW);
    g_nid.hWnd             = g_hMain;
    g_nid.uID              = 1;
    g_nid.uFlags           = NIF_ICON | NIF_TIP | NIF_MESSAGE;
    g_nid.uCallbackMessage = WM_TRAY_ICON;
    g_nid.hIcon            = g_hTrayIcon;
    wcscpy(g_nid.szTip, L"Screen Dimmer");
    Shell_NotifyIconW(NIM_ADD, &g_nid);
}

static void registerHotkeys() {
    RegisterHotKey(g_hMain, HK_DIM_DOWN, MOD_CONTROL | MOD_ALT, VK_DOWN);
    RegisterHotKey(g_hMain, HK_DIM_UP,   MOD_CONTROL | MOD_ALT, VK_UP);
    RegisterHotKey(g_hMain, HK_TOGGLE,   MOD_CONTROL | MOD_ALT, VK_SPACE);

    /* Numpad 0-9: direct darkness presets (0%=0, 10%, 20%, ..., 90%) */
    for (int i = 0; i <= 9; i++) {
        RegisterHotKey(g_hMain, HK_NUMPAD_0 + i, MOD_CONTROL | MOD_ALT,
                       VK_NUMPAD0 + i);
    }
}

static void createFonts() {
    g_hFontLg = CreateFontW(22, 0, 0, 0, FW_SEMIBOLD,
                            FALSE, FALSE, FALSE, DEFAULT_CHARSET,
                            0, 0, CLEARTYPE_QUALITY, 0, L"Segoe UI");
}

/* ================================================================
 * Entry point
 * ================================================================ */
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int) {
    /* single instance */
    g_hMutex = CreateMutexW(NULL, TRUE, MUTEX_NAME);
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        CloseHandle(g_hMutex);
        MessageBoxW(NULL,
                   L"Screen Dimmer is already running.",
                   L"Screen Dimmer",
                   MB_OK | MB_ICONINFORMATION);
        return 0;
    }

    SetProcessDPIAware();

    g_hInst = hInst;
    loadConfig();

    if (!registerClasses()) {
        MessageBoxW(NULL, L"Failed to register window classes.",
                    L"Screen Dimmer", MB_ICONERROR);
        return 1;
    }
    if (!createWindows()) {
        MessageBoxW(NULL, L"Failed to create windows.",
                    L"Screen Dimmer", MB_ICONERROR);
        return 1;
    }

    createFonts();
    setupTray();
    registerHotkeys();
    refreshOverlay();
    /* start periodic Z-order re-assert timer (every 500ms) */
    SetTimer(g_hMain, 2, 500, NULL);

    MSG msg;
    while (g_running && GetMessageW(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }

    /* cleanup */
    KillTimer(g_hMain, 2);
    UnregisterHotKey(g_hMain, HK_DIM_DOWN);
    UnregisterHotKey(g_hMain, HK_DIM_UP);
    UnregisterHotKey(g_hMain, HK_TOGGLE);
    for (int i = 0; i <= 9; i++)
        UnregisterHotKey(g_hMain, HK_NUMPAD_0 + i);

    if (g_hFontLg)   DeleteObject(g_hFontLg);
    if (g_hTrayIcon) DestroyIcon(g_hTrayIcon);
    if (g_hMutex)    CloseHandle(g_hMutex);

    return 0;
}
