alien_fx_fiend

Analog Clock (Win32) Fixed Escape Key To Close Calendar Popup!!

Mar 31st, 2025
21
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.96 KB | Source Code | 0 0
  1. ==++ Here's the full source code for (file 1/1) "main.cpp"::: ++==
  2. ```main.cpp
  3. #include <windows.h>
  4. #include <gdiplus.h>
  5. #include <time.h>
  6. #include <math.h>
  7. #include <stdio.h>
  8. #include <commctrl.h>
  9. #include <tchar.h>
  10. #include <strsafe.h>
  11. #include "resource.h"  // Add this with your other includes
  12. #pragma comment(lib, "Msimg32.lib")
  13. #pragma comment(lib, "comctl32.lib")
  14. #pragma comment(lib, "gdiplus.lib")
  15. #define ID_TIMER 1
  16. #define SIZE 475
  17. #define CLOCK_MARGIN 20
  18. #define ID_STATUSBAR 100
  19. //SIZE 425
  20. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  21. void DrawClock(HDC, int, int, int);
  22. void DrawHand(HDC hdc, int x, int y, double angle, int length, COLORREF color, bool drawLineToCenter = true);
  23. void UpdateStatusBar(HWND, SYSTEMTIME);
  24. LRESULT CALLBACK StatusBarProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
  25. // Declare gdiplusToken as a global variable
  26. ULONG_PTR gdiplusToken;
  27.  
  28. LRESULT CALLBACK CalendarSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
  29.    UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
  30.    if (uMsg == WM_KEYDOWN && wParam == VK_ESCAPE) {
  31.        DestroyWindow(hWnd);
  32.        return 0;
  33.    }
  34.    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
  35. }
  36.  
  37. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {
  38.    // Add this to WinMain before the window creation:
  39.    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
  40.    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
  41.    static TCHAR szAppName[] = TEXT("My Clock");
  42.    HWND hwnd;
  43.    MSG msg;
  44.    WNDCLASS wndclass;
  45.    wndclass.style = CS_HREDRAW | CS_VREDRAW;
  46.    wndclass.lpfnWndProc = WndProc;
  47.    wndclass.cbClsExtra = 0;
  48.    wndclass.cbWndExtra = 0;
  49.    wndclass.hInstance = hInstance;
  50.    wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
  51.    //wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  52.    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  53.    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  54.    wndclass.lpszMenuName = NULL;
  55.    wndclass.lpszClassName = szAppName;
  56.    if (!RegisterClass(&wndclass)) {
  57.        MessageBox(NULL, TEXT("Program requires Windows NT!"), szAppName, MB_ICONERROR);
  58.        return 0;
  59.    }
  60.    RECT rect = { 0, 0, SIZE + 2 * CLOCK_MARGIN, SIZE + 2 * CLOCK_MARGIN + 30 };
  61.    AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
  62.  
  63.    // Get screen dimensions
  64.    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
  65.    int screenHeight = GetSystemMetrics(SM_CYSCREEN);
  66.  
  67.    // Calculate centered position
  68.    int windowWidth = rect.right - rect.left;
  69.    int windowHeight = rect.bottom - rect.top;
  70.    int xPos = (screenWidth - windowWidth) / 2;
  71.    int yPos = (screenHeight - windowHeight) / 2;
  72.  
  73.    hwnd = CreateWindowEx(WS_EX_TOPMOST, // Make the window always on top
  74.        szAppName, TEXT("Time is Meaningless The Insurgency is Live & Well (F1=About F2=Calendar)"),
  75.        WS_OVERLAPPEDWINDOW, xPos, yPos,
  76.        windowWidth, windowHeight,
  77.        NULL, NULL, hInstance, NULL);
  78.  
  79.    ShowWindow(hwnd, iCmdShow);
  80.    UpdateWindow(hwnd);
  81.  
  82.    while (GetMessage(&msg, NULL, 0, 0)) {
  83.        TranslateMessage(&msg);
  84.        DispatchMessage(&msg);
  85.    }
  86.    return (int)msg.wParam;
  87. }
  88.  
  89. LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
  90.    static HWND hwndStatus;
  91.    static HBITMAP hBitmap;
  92.    static int cxClient, cyClient;
  93.    HDC hdc, memDC;
  94.    PAINTSTRUCT ps;
  95.    SYSTEMTIME st;
  96.    RECT rect;
  97.    int centerX, centerY;
  98.  
  99.    // Moved the declaration outside the switch
  100.    int statwidths[] = { -1 };
  101.  
  102.    switch (message) {
  103.    case WM_CREATE:
  104.        // Enable double buffering
  105.        SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_CLIPCHILDREN);
  106.  
  107.        hwndStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL,
  108.            WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, 0, 0, 0, 0,
  109.            hwnd, (HMENU)ID_STATUSBAR, GetModuleHandle(NULL), NULL);
  110.  
  111.        SendMessage(hwndStatus, SB_SETPARTS, 1, (LPARAM)statwidths);
  112.        SendMessage(hwndStatus, SB_SETTEXT, 0, (LPARAM)TEXT(""));
  113.        SetWindowSubclass(hwndStatus, StatusBarProc, 0, 0);
  114.        SetTimer(hwnd, ID_TIMER, 1000, NULL);
  115.        return 0;
  116.    case WM_KEYDOWN:
  117.        if (wParam == VK_ESCAPE) {
  118.            PostQuitMessage(0);
  119.            return 0;
  120.        }
  121.        // Add this new code block
  122.        else if (wParam == VK_F1) {
  123.            MessageBox(hwnd, TEXT("Analog Clock (incorporates SubClassing Controls) Programmed in C++ Win32 API (395 lines of code) by Entisoft Software (c) Evans Thorpemorton"), TEXT("Information"), MB_OK | MB_ICONINFORMATION);
  124.            return 0;
  125.        }
  126.        else if (wParam == VK_F2) {
  127.            HINSTANCE hInst = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
  128.            int calWidth = 350, calHeight = 300;
  129.            int screenWidth = GetSystemMetrics(SM_CXSCREEN);
  130.            int screenHeight = GetSystemMetrics(SM_CYSCREEN);
  131.            int xPos = (screenWidth - calWidth) / 2;
  132.            int yPos = (screenHeight - calHeight) / 2;
  133.            HWND hCal = CreateWindowEx(WS_EX_TOPMOST, MONTHCAL_CLASS, NULL,
  134.                WS_POPUP | WS_BORDER,
  135.                xPos, yPos, calWidth, calHeight, hwnd, NULL, hInst, NULL);
  136.            if (hCal) {
  137.                SendMessage(hCal, MCM_SETFIRSTDAYOFWEEK, (WPARAM)1, 0);
  138.                ShowWindow(hCal, SW_SHOW);
  139.                // Subclass the calendar to intercept the Escape key
  140.                SetWindowSubclass(hCal, CalendarSubclassProc, 0, 0);
  141.            }
  142.            return 0;
  143.        }
  144.        break;
  145.    case WM_SIZE:
  146.        cxClient = LOWORD(lParam);
  147.        cyClient = HIWORD(lParam);
  148.        if (hBitmap) {
  149.            DeleteObject(hBitmap);
  150.        }
  151.        hdc = GetDC(hwnd);
  152.        hBitmap = CreateCompatibleBitmap(hdc, cxClient, cyClient);
  153.        ReleaseDC(hwnd, hdc);
  154.        SendMessage(hwndStatus, WM_SIZE, 0, 0);
  155.        return 0;
  156.    case WM_PAINT:
  157.        hdc = BeginPaint(hwnd, &ps);
  158.        memDC = CreateCompatibleDC(hdc);
  159.        SelectObject(memDC, hBitmap);
  160.        GetClientRect(hwnd, &rect);
  161.        centerX = (rect.right - rect.left) / 2;
  162.        centerY = ((rect.bottom - rect.top) - 20) / 2;
  163.        FillRect(memDC, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
  164.        DrawClock(memDC, centerX, centerY, min(centerX, centerY) - CLOCK_MARGIN);
  165.        BitBlt(hdc, 0, 0, cxClient, cyClient, memDC, 0, 0, SRCCOPY);
  166.        DeleteDC(memDC);
  167.        EndPaint(hwnd, &ps);
  168.        return 0;
  169.    case WM_TIMER:
  170.        GetLocalTime(&st);
  171.        UpdateStatusBar(hwndStatus, st);
  172.        InvalidateRect(hwnd, NULL, FALSE);
  173.        return 0;
  174.    case WM_DESTROY:
  175.        KillTimer(hwnd, ID_TIMER);
  176.        if (hBitmap) DeleteObject(hBitmap);
  177.        // Add this to WM_DESTROY handler:
  178.        Gdiplus::GdiplusShutdown(gdiplusToken);
  179.        PostQuitMessage(0);
  180.        return 0;
  181.    }
  182.    return DefWindowProc(hwnd, message, wParam, lParam);
  183. }
  184.  
  185. void DrawClock(HDC hdc, int x, int y, int r) {
  186.    SYSTEMTIME st;
  187.    GetLocalTime(&st);
  188.  
  189.    // Create memory DC for double buffering
  190.    HDC memDC = CreateCompatibleDC(hdc);
  191.    HBITMAP hBitmap = CreateCompatibleBitmap(hdc, 2 * r, 2 * r);
  192.    HBITMAP hOldBitmap = (HBITMAP)SelectObject(memDC, hBitmap);
  193.  
  194.    // Calculate center point for the memory DC
  195.    int centerX = r;  // Center X in memory DC coordinates
  196.    int centerY = r;  // Center Y in memory DC coordinates
  197.  
  198.    // Draw gradient background
  199.    TRIVERTEX vertex[2];
  200.    vertex[0].x = 0;
  201.    vertex[0].y = 0;
  202.    vertex[0].Red = 0xc000;
  203.    vertex[0].Green = 0xc000;
  204.    vertex[0].Blue = 0xc000;
  205.    vertex[0].Alpha = 0x0000;
  206.    vertex[1].x = 2 * r;
  207.    vertex[1].y = 2 * r;
  208.    vertex[1].Red = 0x4000;
  209.    vertex[1].Green = 0x4000;
  210.    vertex[1].Blue = 0x4000;
  211.    vertex[1].Alpha = 0x0000;
  212.    GRADIENT_RECT gRect = { 0, 1 };
  213.    GradientFill(memDC, vertex, 2, &gRect, 1, GRADIENT_FILL_RECT_H);
  214.  
  215.    // Draw clock outline
  216.    HPEN hPen = CreatePen(PS_SOLID, 8, RGB(128, 128, 128));
  217.    HPEN hOldPen = (HPEN)SelectObject(memDC, hPen);
  218.    Ellipse(memDC, 0, 0, 2 * r, 2 * r);
  219.  
  220.    // Draw hour numbers
  221.    HFONT hFont = CreateFont(12, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
  222.        ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  223.        DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, TEXT("Segoe UI"));
  224.    HFONT hOldFont = (HFONT)SelectObject(memDC, hFont);
  225.    SetTextColor(memDC, RGB(112, 128, 144));
  226.    SetTextAlign(memDC, TA_CENTER | TA_BASELINE);
  227.    SetBkMode(memDC, TRANSPARENT);
  228.  
  229.    for (int i = 1; i <= 12; i++) {
  230.        double angle = (i * 30 - 90) * (3.14159265358979323846 / 180);
  231.        int numX = centerX + (int)(cos(angle) * (r - 25));
  232.        int numY = centerY + (int)(sin(angle) * (r - 25));
  233.        WCHAR numStr[3];
  234.        wsprintf(numStr, L"%d", i);
  235.        TextOut(memDC, numX, numY, numStr, lstrlen(numStr));
  236.    }
  237.  
  238.    // Draw markers
  239.    for (int i = 0; i < 60; i++) {
  240.        if (i % 5 == 0) {
  241.            DrawHand(memDC, centerX, centerY, i * 6, r - 10, RGB(0, 0, 0), false);
  242.        }
  243.        else {
  244.            DrawHand(memDC, centerX, centerY, i * 6, r - 5, RGB(0, 0, 0), false);
  245.        }
  246.    }
  247.  
  248.    // Draw clock hands
  249.    DrawHand(memDC, centerX, centerY, st.wSecond * 6, r - 30, RGB(255, 0, 0));
  250.    DrawHand(memDC, centerX, centerY, (st.wMinute * 6) + (st.wSecond / 10.0), r - 60, RGB(0, 0, 0));
  251.    DrawHand(memDC, centerX, centerY, (st.wHour * 30) + (st.wMinute / 2.0), r - 90, RGB(0, 0, 255));
  252.  
  253.    // Draw center white circle
  254.    HBRUSH whiteBrush = CreateSolidBrush(RGB(255, 255, 255));
  255.    HBRUSH oldBrush = (HBRUSH)SelectObject(memDC, whiteBrush);
  256.    Ellipse(memDC, centerX - 10, centerY - 10, centerX + 10, centerY + 10);
  257.    SelectObject(memDC, oldBrush);
  258.    DeleteObject(whiteBrush);
  259.  
  260.    // Add AM/PM text
  261.    SelectObject(memDC, hOldFont);
  262.    DeleteObject(hFont);
  263.  
  264.    hFont = CreateFont(18, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
  265.        ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
  266.        DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, TEXT("Segoe UI"));
  267.    SelectObject(memDC, hFont);
  268.    SetTextColor(memDC, RGB(128, 128, 128));
  269.    TextOut(memDC, centerX, centerY + (r - 70), st.wHour < 12 ? TEXT("AM") : TEXT("PM"), 2);
  270.  
  271.    // Copy the final result to the screen
  272.    BitBlt(hdc, x - r, y - r, 2 * r, 2 * r, memDC, 0, 0, SRCCOPY);
  273.  
  274.    // Final cleanup
  275.    SelectObject(memDC, hOldFont);
  276.    SelectObject(memDC, hOldPen);
  277.    SelectObject(memDC, hOldBitmap);
  278.    DeleteObject(hFont);
  279.    DeleteObject(hPen);
  280.    DeleteObject(hBitmap);
  281.    DeleteDC(memDC);
  282. }
  283.  
  284. void DrawHand(HDC hdc, int x, int y, double angle, int length, COLORREF color, bool drawLineToCenter) {
  285.    double radian = (angle - 90) * (3.14159265358979323846 / 180);
  286.    int extensionLength = length * 0.1;
  287.  
  288.    // Create GDI+ Graphics object
  289.    Gdiplus::Graphics graphics(hdc);
  290.    graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
  291.  
  292.    if (drawLineToCenter) {
  293.        if (color == RGB(255, 0, 0)) {  // Second hand
  294.            Gdiplus::Point pts[3];
  295.            
  296.            // Calculate points
  297.            pts[0].X = x + (int)(cos(radian) * length);
  298.            pts[0].Y = y + (int)(sin(radian) * length);
  299.  
  300.            double perpRadian = radian + 3.14159265358979323846 / 2;
  301.            int baseWidth = 8;
  302.            pts[1].X = x - (int)(cos(radian) * extensionLength) + (int)(cos(perpRadian) * baseWidth);
  303.            pts[1].Y = y - (int)(sin(radian) * extensionLength) + (int)(sin(perpRadian) * baseWidth);
  304.            pts[2].X = x - (int)(cos(radian) * extensionLength) - (int)(cos(perpRadian) * baseWidth);
  305.            pts[2].Y = y - (int)(sin(radian) * extensionLength) - (int)(sin(perpRadian) * baseWidth);
  306.  
  307.            // Create brush and pen
  308.            Gdiplus::SolidBrush brush(Gdiplus::Color(255, GetRValue(color), GetGValue(color), GetBValue(color)));
  309.            graphics.FillPolygon(&brush, pts, 3);
  310.        }
  311.        else {
  312.            // Hour and minute hands
  313.            int penThickness = (color == RGB(0, 0, 255)) ? 6 : 4;
  314.            Gdiplus::Pen pen(Gdiplus::Color(255, GetRValue(color), GetGValue(color), GetBValue(color)),
  315.                            (Gdiplus::REAL)penThickness);
  316.            
  317.            int endX = x + (int)(cos(radian) * length);
  318.            int endY = y + (int)(sin(radian) * length);
  319.            int startX = x - (int)(cos(radian) * extensionLength);
  320.            int startY = y - (int)(sin(radian) * extensionLength);
  321.  
  322.            graphics.DrawLine(&pen, startX, startY, endX, endY);
  323.        }
  324.    }
  325.    else {
  326.        // Markers
  327.        int markerThickness = ((int)angle % 30 == 0) ? 4 : 2;
  328.        int markerLength = ((int)angle % 30 == 0) ? 15 : 10; // Longer markers for hours
  329.  
  330.        Gdiplus::Pen pen(Gdiplus::Color(255, GetRValue(color), GetGValue(color), GetBValue(color)),
  331.                        (Gdiplus::REAL)markerThickness);
  332.  
  333.        int endX = x + (int)(cos(radian) * length);
  334.        int endY = y + (int)(sin(radian) * length);
  335.        int startX = endX + (int)(cos(radian) * markerLength);
  336.        int startY = endY + (int)(sin(radian) * markerLength);
  337.  
  338.        graphics.DrawLine(&pen, endX, endY, startX, startY);
  339.    }
  340. }
  341.  
  342. void UpdateStatusBar(HWND hwndStatus, SYSTEMTIME st) {
  343.    TCHAR szStatus[256];
  344.    TCHAR szDayOfWeek[32], szMonth[32];
  345.    TCHAR szSuffix[3];
  346.    int weekNumber;
  347.  
  348.    GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, TEXT("dddd"), szDayOfWeek, sizeof(szDayOfWeek) / sizeof(TCHAR));
  349.    GetDateFormat(LOCALE_USER_DEFAULT, 0, &st, TEXT("MMMM"), szMonth, sizeof(szMonth) / sizeof(TCHAR));
  350.  
  351.    SYSTEMTIME newYearDay = { st.wYear, 1, 0, 1 };
  352.    FILETIME ftNewYearDay, ftCurrentDay;
  353.    SystemTimeToFileTime(&newYearDay, &ftNewYearDay);
  354.    SystemTimeToFileTime(&st, &ftCurrentDay);
  355.    ULARGE_INTEGER uliNewYearDay, uliCurrentDay;
  356.    uliNewYearDay.LowPart = ftNewYearDay.dwLowDateTime;
  357.    uliNewYearDay.HighPart = ftNewYearDay.dwHighDateTime;
  358.    uliCurrentDay.LowPart = ftCurrentDay.dwLowDateTime;
  359.    uliCurrentDay.HighPart = ftCurrentDay.dwHighDateTime;
  360.    weekNumber = (int)(((uliCurrentDay.QuadPart - uliNewYearDay.QuadPart) / (7 * 24 * 60 * 60 * 10000000ULL)) + 1);
  361.  
  362.    if (st.wDay == 1 || st.wDay == 21 || st.wDay == 31)
  363.        _tcscpy_s(szSuffix, _T("st"));
  364.    else if (st.wDay == 2 || st.wDay == 22)
  365.        _tcscpy_s(szSuffix, _T("nd"));
  366.    else if (st.wDay == 3 || st.wDay == 23)
  367.        _tcscpy_s(szSuffix, _T("rd"));
  368.    else
  369.        _tcscpy_s(szSuffix, _T("th"));
  370.  
  371.    // Get time zone information
  372.    TIME_ZONE_INFORMATION tzi;
  373.    GetTimeZoneInformation(&tzi);
  374.    int bias = -(tzi.Bias); // Negative because Bias is in opposite direction
  375.    int hours = bias / 60;
  376.    int minutes = abs(bias % 60);
  377.  
  378.    StringCbPrintf(szStatus, sizeof(szStatus),
  379.        TEXT("%s %d%s %s %d #%d %d/%02d/%04d %02d:%02d:%02d %s GMT%s%d:%02d"),
  380.        szDayOfWeek, st.wDay, szSuffix, szMonth, st.wYear, weekNumber,
  381.        st.wDay, st.wMonth, st.wYear,
  382.        (st.wHour == 0 || st.wHour == 12) ? 12 : st.wHour % 12,
  383.        st.wMinute, st.wSecond,
  384.        st.wHour < 12 ? TEXT("AM") : TEXT("PM"),
  385.        (hours >= 0) ? TEXT("+") : TEXT(""),
  386.        hours,
  387.        minutes);
  388.  
  389.    SendMessage(hwndStatus, SB_SETTEXT, 0, (LPARAM)szStatus);
  390.    InvalidateRect(hwndStatus, NULL, TRUE);
  391. }
  392.  
  393. LRESULT CALLBACK StatusBarProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
  394.    if (uMsg == WM_PAINT) {
  395.        PAINTSTRUCT ps;
  396.        HDC hdc = BeginPaint(hWnd, &ps);
  397.  
  398.        RECT rc;
  399.        GetClientRect(hWnd, &rc);
  400.  
  401.        TCHAR szText[256];
  402.        int len = SendMessage(hWnd, SB_GETTEXT, 0, (LPARAM)szText);
  403.  
  404.        SetBkMode(hdc, TRANSPARENT);
  405.        SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));
  406.  
  407.        DrawText(hdc, szText, len, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  408.  
  409.        EndPaint(hWnd, &ps);
  410.        return 0;
  411.    }
  412.  
  413.    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
  414. }
  415. ```
Add Comment
Please, Sign In to add comment