Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Dynamic Libraries (Windows)
#46
This is a utility that allows you to select a date from a calendar. The function returns the selected date as a string.

program need pdate.h file.

pdate.h:

Code: (Select All)
#ifndef QB64PE_PICKDATE_H
#define QB64PE_PICKDATE_H

#ifndef _WIN32
#error "pickdate.h je jen pro Windows."
#endif

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif

// kvůli některým definicím common controls
#ifndef _WIN32_IE
#define _WIN32_IE 0x0501
#endif

#include <windows.h>
#include <commctrl.h>
#include <stdio.h>

#define QB64_PICKDATE_CLASSA "QB64PE_PickDateWindow"
#define IDC_QB64_MONTHCAL  1010
#define IDC_QB64_OK        1
#define IDC_QB64_CANCEL    2

typedef BOOL (WINAPI *PFN_InitCommonControlsEx)(const INITCOMMONCONTROLSEX*);

static void qb64_pickdate_init_comctl_dateclasses(void) {
    // Bezpečně: dynamicky natáhnout comctl32 a zavolat InitCommonControlsEx (bez linkování comctl32)
    HMODULE hComctl = LoadLibraryA("comctl32.dll");
    if (!hComctl) return;

    PFN_InitCommonControlsEx pInit =
        (PFN_InitCommonControlsEx)GetProcAddress(hComctl, "InitCommonControlsEx");
    if (!pInit) return;

    INITCOMMONCONTROLSEX icc;
    ZeroMemory(&icc, sizeof(icc));
    icc.dwSize = sizeof(icc);
    icc.dwICC = ICC_DATE_CLASSES;
    pInit(&icc);
}

typedef struct qb64_pickdate_ctx_s {
    HWND hwnd;
    HWND hCal;
    SYSTEMTIME stInit;
    SYSTEMTIME stSel;
    int hasInit;
    int ok;
} qb64_pickdate_ctx;

static void qb64_pickdate_center_window(HWND hwnd) {
    RECT rc;
    GetWindowRect(hwnd, &rc);
    int w = rc.right - rc.left;
    int h = rc.bottom - rc.top;

    int sw = GetSystemMetrics(SM_CXSCREEN);
    int sh = GetSystemMetrics(SM_CYSCREEN);

    int x = (sw - w) / 2;
    int y = (sh - h) / 2;

    SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}

static void qb64_pickdate_layout(HWND hwnd, qb64_pickdate_ctx* ctx) {
    // Zjisti minimální potřebný rozměr MonthCal
    RECT r = {0,0,0,0};
    SendMessageA(ctx->hCal, MCM_GETMINREQRECT, 0, (LPARAM)&r);
    int calW = (r.right - r.left);
    int calH = (r.bottom - r.top);
    if (calW <= 0) calW = 220;
    if (calH <= 0) calH = 160;

    const int pad = 10;
    const int btnW = 90;
    const int btnH = 26;
    const int gap = 10;

    int clientW = calW + pad * 2;
    int minBtnRow = (btnW * 2 + gap) + pad * 2;
    if (clientW < minBtnRow) clientW = minBtnRow;

    int calX = pad;
    int calY = pad;

    int btnY = calY + calH + pad;

    int okX = (clientW / 2) - gap/2 - btnW;
    int cancelX = (clientW / 2) + gap/2;

    MoveWindow(ctx->hCal, calX, calY, calW, calH, TRUE);

    HWND hOk = GetDlgItem(hwnd, IDC_QB64_OK);
    HWND hCancel = GetDlgItem(hwnd, IDC_QB64_CANCEL);

    MoveWindow(hOk, okX, btnY, btnW, btnH, TRUE);
    MoveWindow(hCancel, cancelX, btnY, btnW, btnH, TRUE);

    int clientH = btnY + btnH + pad;

    // Přepočet na velikost okna podle stylu
    RECT wr = {0, 0, clientW, clientH};
    DWORD style = (DWORD)GetWindowLongPtr(hwnd, GWL_STYLE);
    DWORD exStyle = (DWORD)GetWindowLongPtr(hwnd, GWL_EXSTYLE);
    AdjustWindowRectEx(&wr, style, FALSE, exStyle);

    int winW = wr.right - wr.left;
    int winH = wr.bottom - wr.top;

    SetWindowPos(hwnd, NULL, 0, 0, winW, winH, SWP_NOZORDER | SWP_NOMOVE);
    qb64_pickdate_center_window(hwnd);
}

static LRESULT CALLBACK qb64_pickdate_wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    qb64_pickdate_ctx* ctx = (qb64_pickdate_ctx*)GetWindowLongPtr(hwnd, GWLP_USERDATA);

    switch (msg) {
    case WM_NCCREATE: {
        CREATESTRUCTA* cs = (CREATESTRUCTA*)lParam;
        SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams);
        return TRUE;
    }
    case WM_CREATE: {
        ctx = (qb64_pickdate_ctx*)GetWindowLongPtr(hwnd, GWLP_USERDATA);

        ctx->hCal = CreateWindowExA(
            0,
            MONTHCAL_CLASSA, "",
            WS_CHILD | WS_VISIBLE | WS_BORDER,
            10, 10, 220, 160,
            hwnd, (HMENU)(INT_PTR)IDC_QB64_MONTHCAL,
            GetModuleHandleA(NULL), NULL
        );

        CreateWindowExA(
            0, "BUTTON", "OK",
            WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
            10, 180, 90, 26,
            hwnd, (HMENU)(INT_PTR)IDC_QB64_OK,
            GetModuleHandleA(NULL), NULL
        );

        CreateWindowExA(
            0, "BUTTON", "Storno",
            WS_CHILD | WS_VISIBLE,
            110, 180, 90, 26,
            hwnd, (HMENU)(INT_PTR)IDC_QB64_CANCEL,
            GetModuleHandleA(NULL), NULL
        );

        if (ctx->hasInit) {
            SendMessageA(ctx->hCal, MCM_SETCURSEL, 0, (LPARAM)&ctx->stInit);
        }

        qb64_pickdate_layout(hwnd, ctx);
        return 0;
    }
    case WM_COMMAND: {
        int id = LOWORD(wParam);

        if (id == IDC_QB64_OK) {
            SYSTEMTIME st;
            ZeroMemory(&st, sizeof(st));
            SendMessageA(ctx->hCal, MCM_GETCURSEL, 0, (LPARAM)&st);
            ctx->stSel = st;
            ctx->ok = 1;
            DestroyWindow(hwnd);
            return 0;
        }

        if (id == IDC_QB64_CANCEL) {
            ctx->ok = 0;
            DestroyWindow(hwnd);
            return 0;
        }

        return 0;
    }
    case WM_CLOSE:
        if (ctx) ctx->ok = 0;
        DestroyWindow(hwnd);
        return 0;
    }

    return DefWindowProcA(hwnd, msg, wParam, lParam);
}

static ATOM qb64_pickdate_register_class(void) {
    static ATOM atom = 0;
    if (atom) return atom;

    WNDCLASSEXA wc;
    ZeroMemory(&wc, sizeof(wc));
    wc.cbSize = sizeof(wc);
    wc.lpfnWndProc = qb64_pickdate_wndproc;
    wc.hInstance = GetModuleHandleA(NULL);
    wc.lpszClassName = QB64_PICKDATE_CLASSA;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

    atom = RegisterClassExA(&wc);
    return atom;
}

// Exportovaná funkce pro QB64PE:
// outISO = buffer (STRING proměnná), outISOBytes = velikost bufferu, initialISO = "YYYY-MM-DD\0" nebo ""\0
// Return: 1=OK, 0=storno/chyba
int qb64_pickdate(char* outISO, int outISOBytes, const char* initialISO) {
    if (!outISO || outISOBytes <= 0) return 0;
    outISO[0] = 0;

    qb64_pickdate_init_comctl_dateclasses();
    if (!qb64_pickdate_register_class()) return 0;

    qb64_pickdate_ctx ctx;
    ZeroMemory(&ctx, sizeof(ctx));

    // default: dnešní datum
    GetLocalTime(&ctx.stInit);
    ctx.hasInit = 1;

    // pokud je initialISO zadáno jako YYYY-MM-DD, použij ho
    if (initialISO && initialISO[0]) {
        int y=0, m=0, d=0;
        if (sscanf(initialISO, "%d-%d-%d", &y, &m, &d) == 3) {
            if (y >= 1601 && m >= 1 && m <= 12 && d >= 1 && d <= 31) {
                ctx.stInit.wYear  = (WORD)y;
                ctx.stInit.wMonth = (WORD)m;
                ctx.stInit.wDay  = (WORD)d;
            }
        }
    }

    HWND hwnd = CreateWindowExA(
        WS_EX_DLGMODALFRAME,
        QB64_PICKDATE_CLASSA,
        "Vyber datum",
        WS_CAPTION | WS_SYSMENU,
        CW_USEDEFAULT, CW_USEDEFAULT, 300, 260,
        NULL, NULL,
        GetModuleHandleA(NULL),
        &ctx
    );

    if (!hwnd) return 0;

    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);

    // modal-ish smyčka: pumpuje zprávy, dokud okno existuje
    MSG msg;
    while (IsWindow(hwnd) && GetMessageA(&msg, NULL, 0, 0) > 0) {
        TranslateMessage(&msg);
        DispatchMessageA(&msg);
    }

    if (!ctx.ok) return 0;

    // Zapiš výsledek
    int n = snprintf(outISO, (size_t)outISOBytes, "%04u-%02u-%02u",
                    (unsigned)ctx.stSel.wYear, (unsigned)ctx.stSel.wMonth, (unsigned)ctx.stSel.wDay);

    // pojistka NUL
    outISO[outISOBytes - 1] = 0;

    return (n > 0) ? 1 : 0;
}

#endif // QB64PE_PICKDATE_H
pdate.bas:

Code: (Select All)


$Console

Declare CustomType Library "pdate"
    Function PickDate% Alias qb64_pickdate (outISO As String, ByVal outISOBytes As Long, initialISO As String)
End Declare

Dim out$, init$
out$ = Space$(32) ' buffer for "YYYY-MM-DD" + NUL
init$ = ""
ok% = PickDate(out$, Len(out$), init$ + Chr$(0))

If ok% Then
    p = InStr(out$, Chr$(0))
    If p > 0 Then out$ = Left$(out$, p - 1)
    Print "Date selected: "; out$
Else
    Print "Storno or fail."
End If

Sleep
End


Reply


Messages In This Thread
Dynamic Libraries (Windows) - by Petr - 12-08-2025, 06:48 PM
RE: Dynamic Libraries - by Petr - 12-08-2025, 07:12 PM
RE: Dynamic Libraries - by Petr - 12-08-2025, 07:52 PM
RE: Dynamic Libraries - by Jack - 12-08-2025, 08:41 PM
RE: Dynamic Libraries - by Petr - 12-09-2025, 07:21 PM
RE: Dynamic Libraries - by Petr - 12-11-2025, 04:19 PM
RE: Dynamic Libraries - by Petr - 12-12-2025, 10:00 PM
RE: Dynamic Libraries - by Petr - 12-13-2025, 05:56 PM
RE: Dynamic Libraries - by 2112 - 12-13-2025, 07:06 PM
RE: Dynamic Libraries - by ahenry3068 - 12-13-2025, 07:47 PM
RE: Dynamic Libraries - by Petr - 12-13-2025, 07:41 PM
RE: Dynamic Libraries - by 2112 - 12-13-2025, 08:23 PM
RE: Dynamic Libraries - by Petr - 12-13-2025, 08:36 PM
RE: Dynamic Libraries - by Petr - 12-13-2025, 09:03 PM
RE: Dynamic Libraries - by ahenry3068 - 12-13-2025, 11:16 PM
RE: Dynamic Libraries - by Petr - 12-14-2025, 12:15 AM
RE: Dynamic Libraries - by Petr - 12-15-2025, 08:22 AM
RE: Dynamic Libraries (Windows) - by Petr - 12-15-2025, 06:30 PM
RE: Dynamic Libraries (Windows) - by Mad Axeman - 12-19-2025, 02:37 PM
RE: Dynamic Libraries (Windows) - by Pete - 12-18-2025, 07:45 PM
RE: Dynamic Libraries (Windows) - by Steffan-68 - 12-18-2025, 08:31 PM
RE: Dynamic Libraries (Windows) - by Pete - 12-18-2025, 08:55 PM
RE: Dynamic Libraries (Windows) - by Steffan-68 - 12-18-2025, 09:48 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-18-2025, 09:32 PM
RE: Dynamic Libraries (Windows) - by Pete - 12-18-2025, 11:53 PM
RE: Dynamic Libraries (Windows) - by Pete - 12-19-2025, 06:40 AM
RE: Dynamic Libraries (Windows) - by Petr - 12-19-2025, 03:08 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-19-2025, 10:35 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-19-2025, 10:54 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-19-2025, 11:20 PM
RE: Dynamic Libraries (Windows) - by Pete - 12-19-2025, 11:37 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-20-2025, 10:22 PM
RE: Dynamic Libraries (Windows) - by SMcNeill - 12-20-2025, 11:03 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-21-2025, 05:40 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-22-2025, 08:23 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-23-2025, 09:06 AM
RE: Dynamic Libraries (Windows) - by Petr - 12-24-2025, 09:54 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-25-2025, 10:02 AM
RE: Dynamic Libraries (Windows) - by Petr - 12-26-2025, 11:14 PM
RE: Dynamic Libraries (Windows) - by Petr - 12-27-2025, 01:35 PM
RE: Dynamic Libraries (Windows) - by MasterGy - 12-27-2025, 07:23 PM
RE: Dynamic Libraries (Windows) - by Petr - 01-07-2026, 06:31 PM
RE: Dynamic Libraries (Windows) - by Petr - 01-07-2026, 09:13 PM
RE: Dynamic Libraries (Windows) - by Petr - 02-24-2026, 06:38 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  Dynamic Libraries (Linux) Petr 19 1,155 12-29-2025, 09:52 PM
Last Post: Petr

Forum Jump:


Users browsing this thread: 1 Guest(s)