W32 Calender

TextBox から記念日をタイプして曜日と経過日数を計算します。

前田稔の超初心者のプログラム入門

プログラムの説明

  1. [Windows デスクトップ アプリケーション] はメッセージループで描画する Win32 API に準じるプラットホームです。
    但し、文字コードは ASCII(Shift-JIS) では無く Unicode(UTF-16) が使われています。
    EditControl を貼り付けて、曜日と経過日数を計算します。
    Visual Studio で [C++ Windows デスクトップ] のプロジェクトを作成します。
    プロジェクトの作成は W32 Hello を参照して下さい。
  2. 曜日と経過日数を計算する Calender Class をプロジェクトに組み込みます。
    Calender.h と Calender.cpp を utf-8 でタイプして[プロジェクト][既存の項目の追加]からプロジェクトに加えます。
  3. Calender.h のソースコードです。
    Compute() が記念日を渡して、曜日と経過日数を計算する関数です。
    ToDay は西暦1年1月1日から今日までの通算日数を格納する領域です。
    WCHAR Count[8] は経過日数を文字列で格納する領域です。
    WCHAR Yobi[4] は記念日の曜日を格納する領域です。
    //★ Calender Header File  前田 稔
    #include <windows.h>
    
    class Calender
    { protected:
        int     MTBL[12]=  { 0,31,59,90,120,151,181,212,243,273,304,334 };
        WCHAR   WTBL[7][4]= { L"日曜日",L"月曜日",L"火曜日",L"水曜日",L"木曜日",L"金曜日",L"土曜日" };
        SYSTEMTIME  st;
    
      public:
        Calender();     //Constructor
        void  Compute(wchar_t str[]);
        bool  Uruu(int year);
        int   Days(int yy, int mm, int dd);
        void  Split(wchar_t str[]);
    
        int  YYMMDD[3];
        int  ToDay;
        WCHAR  Count[8], Yobi[4];
    };
    
  4. Calender.cpp のソースコードです。
    Constructor() 関数で西暦1年1月1日から今日までの通算日数(ToDay)を計算します。
    Split() 関数が '/' で区切られた文字列を数値に変換して YYMMDD[3] に格納する関数です。
    //★ Calender Program File  前田 稔
    #include "Calender.h"
    
    // Constructor
    Calender::Calender()
    {   GetLocalTime(&st);
        ToDay = Days(st.wYear,st.wMonth,st.wDay);
    }
    
    // 曜日と経過日数を計算する
    void Calender::Compute(wchar_t str[])
    {
        int wk,ans;
        Split(str);
        wk= Days(YYMMDD[0], YYMMDD[1], YYMMDD[2]);
        ans= ToDay-wk+1;
        wsprintf(Count, L"%d", ans);
        wk= wk%7;
        wsprintf(Yobi, L"%s", WTBL[wk]);
    }
    
    // 閏年を調べる関数
    bool  Calender::Uruu(int year)
    {   if (year%400==0)    return(true);
        if (year%100==0)    return(false);
        if (year%4==0)      return(true);
        return(false);
    }
    
    // 西暦1年1月1日からの通算日数を調べる関数
    int  Calender::Days(int yy, int mm, int dd)
    {   int w;
        w = (yy-1)*365;     //年*365
        w = w + (yy/4 - yy/100 + yy/400 + MTBL[mm-1] + dd);
        if (mm<3 && Uruu(yy))  w--;
        return(w);
    }
    
    // '/' で区切られた文字列を数値に変換して YYMMDD[3] に格納
    void Calender::Split(wchar_t str[])
    {
        wchar_t *s;
        int     i;
        s = str;
        OutputDebugString(s);
        for(i=0; i<3; i++)
        {
            YYMMDD[i] = _wtoi(s);
            for(; *s!=L'/' && *s!=0; s++);
            s++;
        }
    }
    
  5. WindowsProject1.cpp で "Calender.h" を #include して、Control の領域と作業領域を定義します。
    XAML が使えないので Control(Edit, Button, Static, etc) の数が多くなると結構面倒です。
    続いて後位参照が起こらないように Debug() 関数を定義します。
    #include "Calender.h"
    
    #define MAX_LOADSTRING 100
    
    // グローバル変数:
    HINSTANCE hInst;                                // 現在のインターフェイス
    WCHAR szTitle[MAX_LOADSTRING];                  // タイトル バーのテキスト
    WCHAR szWindowClass[MAX_LOADSTRING];            // メイン ウィンドウ クラス名
    HWND    g_hEdit1;           // EditControl
    HWND    g_hEdit2;
    HWND    g_hEdit3;
    HWND    g_hButton1;         // ボタン
    HWND    g_hStatic1;         // 見出し
    HWND    g_hStatic2;
    HWND    g_hStatic3;
    
    Calender* Cls = NULL;
    WCHAR   str[80];            // 作業領域
    
    void Debug(LPWSTR msg, int val)
    {
        wchar_t str[80];
        swprintf(str, 80, L"**%s: %d\r\n", msg, val);
        OutputDebugString(str);
    }
    
  6. WndProc() の WM_CREATE: でウインドウに Control を貼り付けます。
    L"STATIC" が見出しで、L"EDIT" が EditControl で、L"BUTTON" がボタンです。
    ページ先頭の画像を参考にして下さい。
    次に Calender Class を生成して Debug() 関数で ToDay の値を確認しています。
        case WM_CREATE:
            g_hStatic1 = CreateWindow(L"STATIC", NULL, WS_CHILD | WS_VISIBLE,
                40, 40, 60, 24, hWnd, NULL, hInst, NULL);
            SetWindowText(g_hStatic1, L"記念日");
            g_hStatic2 = CreateWindow(L"STATIC", NULL, WS_CHILD | WS_VISIBLE,
                260, 40, 40, 24, hWnd, NULL, hInst, NULL);
            SetWindowText(g_hStatic2, L"曜日");
            g_hStatic3 = CreateWindow(L"STATIC", NULL, WS_CHILD | WS_VISIBLE,
                360, 40, 80, 24, hWnd, NULL, hInst, NULL);
            SetWindowText(g_hStatic3, L"経過日数");
    
            g_hEdit1 = CreateWindow(L"EDIT", NULL, (WS_CHILD | WS_VISIBLE | WS_BORDER),
                20, 80, 120, 32, hWnd, NULL, hInst, NULL);
            SetWindowText(g_hEdit1, L"YYYY/MM/DD");
            g_hEdit2 = CreateWindow(L"EDIT", NULL, (WS_CHILD | WS_VISIBLE | WS_BORDER),
                240, 80, 100, 32, hWnd, NULL, hInst, NULL);
            g_hEdit3 = CreateWindow(L"EDIT", NULL, (WS_CHILD | WS_VISIBLE | WS_BORDER),
                360, 80, 80, 32, hWnd, NULL, hInst, NULL);
            g_hButton1 = CreateWindow(L"BUTTON", NULL, WS_CHILD | WS_VISIBLE,
                160, 80, 60, 32, hWnd, (HMENU)IDOK, hInst, NULL);
            SetWindowText(g_hButton1, L"計算");
    
            Cls = new Calender();
            Debug((wchar_t *)L"ToDay", Cls->ToDay);
            break;
    
  7. IDOK: で EditControl にタイプされた文字列(記念日)を取得して曜日と経過日数を計算して表示します。
    GetWindowText() が EditControl から TEXT を取得するコードで SetWindowText() が設定するコードです。
                switch (wmId)
                {
                case IDOK:
                    GetWindowText(g_hEdit1,str,80);
                    Cls->Compute(str);
                    SetWindowText(g_hEdit2, Cls->Yobi);
                    SetWindowText(g_hEdit3, Cls->Count);
                    break;
    
  8. x64 または x86 を選んで、右三角矢印(または F5 キー)でコンパイルします。
    "記念日"に年月日をタイプして"計算"をクリックすると曜日と経過日数が表示されます。
    Windows デスクトップ アプリケーションは UWP のように自動的にメニューに登録されることは無いようです。
    プログラムは Win32 API に準じるようです。詳細は[超初心者のプログラム入門(C言語 Windows)]を参照して下さい。

超初心者のプログラム入門(C/C++)

超初心者のプログラム入門(C言語 Windows)