文字選択による結果(簡易化)

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <vector>

// 選択された文字列のインデックス
int selectedIndex = 0;

// 選択肢の文字列
std::vector<std::string> options = { "おはよう", "こんにちは", "こんばんは", "おやすみ" };

int key_mode;
void key_sel_paint(HWND hwnd);
void key_sel_keydown(HWND hwnd, WPARAM wParam);
void display_mode(int sel);

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_CREATE:
        break;
    case WM_PAINT:
        switch (key_mode) {
        case 1:
            key_sel_paint(hwnd);
            break;
        }
        break;
    case WM_KEYDOWN:
        switch (key_mode) {
        case 1:
            key_sel_keydown(hwnd, wParam);
            break;
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int main() {
    // ウィンドウクラスの登録
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 255)); // 背景色を青に設定
    wc.lpszClassName = "MyWindowClass";
    RegisterClass(&wc);

    // ウィンドウ作成
    HWND hwnd = CreateWindow("MyWindowClass", "選択してください", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, NULL, NULL, GetModuleHandle(NULL), NULL);

    // ウィンドウ表示
    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);

    display_mode(1);

    // メッセージループ
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

void display_mode(int sel) {
    switch (sel) {
    case 1:
        key_mode = 1;
        break;
    }
}

void key_sel_paint(HWND hwnd) {
    //key_mode = 0;

    PAINTSTRUCT ps;
    HDC hdc = GetDC(hwnd);
    RECT rect;
    HFONT hFont;
    GetClientRect(hwnd, &rect);
    int lineHeight = (rect.bottom - rect.top) / options.size();

    // フォントの設定
    hFont = CreateFont(20, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");
    SelectObject(hdc, hFont);

    hdc = BeginPaint(hwnd, &ps);
    for (size_t i = 0; i < options.size(); ++i) {
        // 選択された文字列と背景色を設定
        if (selectedIndex == i) {
            SetBkColor(hdc, RGB(255, 255, 0));  // 背景色を黄色に設定
            SetTextColor(hdc, RGB(0, 0, 255));  // 文字色を青色に設定
        }
        else {
            SetBkColor(hdc, RGB(0, 0, 255));     // 背景色を青色に設定
            SetTextColor(hdc, RGB(0, 255, 255)); // 文字色を水色に設定
        }
        // 選択肢の表示位置を設定
        rect.top = i * (lineHeight - 30);
        rect.bottom = (i + 1) * lineHeight;

        //InvalidateRect(hwnd, NULL, NULL);
        //UpdateWindow(hwnd);

        // 選択肢の描画
        DrawText(hdc, options[i].c_str(), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    }
    EndPaint(hwnd, &ps);
}

void key_sel_keydown(HWND hwnd,WPARAM wParam) {
    // 上キーが押されたら selectedIndex を減らし、下キーが押されたら増やして、ウィンドウを再描画
    if (wParam == VK_UP) {
        selectedIndex = (selectedIndex - 1 + options.size()) % options.size();
        InvalidateRect(hwnd, NULL, NULL);
        UpdateWindow(hwnd);
    }
    else if (wParam == VK_DOWN) {
        selectedIndex = (selectedIndex + 1) % options.size();
        InvalidateRect(hwnd, NULL, NULL);
        UpdateWindow(hwnd);
    }
    // Enterキーが押されたら選択結果を表示してウィンドウを閉じる
    else if (wParam == VK_RETURN) {
        std::cout << "選択されたのは: " << options[selectedIndex] << std::endl;
        DestroyWindow(hwnd);
    }
}

文字選択による結果表示

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <Windows.h>
#include <vector>

// 選択された文字列のインデックス
int selectedIndex = 0;

// 選択肢の文字列
std::vector<std::string> options = { "おはよう", "こんにちは", "こんばんは", "おやすみ" };

// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    PAINTSTRUCT ps;
    HDC hdc = GetDC(hwnd);
    RECT rect;
    HFONT hFont;
    GetClientRect(hwnd, &rect);
    int lineHeight = (rect.bottom - rect.top) / options.size();

    switch (msg) {
    case WM_CREATE:
        // フォントの設定
        hFont = CreateFont(20, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");
        SelectObject(hdc, hFont);
        break;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        for (size_t i = 0; i < options.size(); ++i) {
            // 選択された文字列と背景色を設定
            if (selectedIndex == i) {
                SetBkColor(hdc, RGB(255, 255, 0));  // 背景色を黄色に設定
                SetTextColor(hdc, RGB(0, 0, 255));  // 文字色を青色に設定
            }
            else {
                SetBkColor(hdc, RGB(0, 0, 255));     // 背景色を青色に設定
                SetTextColor(hdc, RGB(0, 255, 255)); // 文字色を水色に設定
            }
            // 選択肢の表示位置を設定
            rect.top = i * (lineHeight - 30);
            rect.bottom = (i + 1) * lineHeight;
            // 選択肢の描画
            DrawText(hdc, options[i].c_str(), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        }
        EndPaint(hwnd, &ps);
        break;
    case WM_KEYDOWN:
        // 上キーが押されたら selectedIndex を減らし、下キーが押されたら増やして、ウィンドウを再描画
        if (wParam == VK_UP) {
            selectedIndex = (selectedIndex - 1 + options.size()) % options.size();
            InvalidateRect(hwnd, NULL, TRUE);
        }
        else if (wParam == VK_DOWN) {
            selectedIndex = (selectedIndex + 1) % options.size();
            InvalidateRect(hwnd, NULL, TRUE);
        }
        // Enterキーが押されたら選択結果を表示してウィンドウを閉じる
        else if (wParam == VK_RETURN) {
            std::cout << "選択されたのは: " << options[selectedIndex] << std::endl;
            DestroyWindow(hwnd);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

int main() {
    // ウィンドウクラスの登録
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 255)); // 背景色を青に設定
    wc.lpszClassName = "MyWindowClass";
    RegisterClass(&wc);

    // ウィンドウ作成
    HWND hwnd = CreateWindow("MyWindowClass", "選択してください", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, NULL, NULL, GetModuleHandle(NULL), NULL);

    // ウィンドウ表示
    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);

    // メッセージループ
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

ウィンドウ背景青、水色枠

#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <chrono>
#include <ctime>
#include <thread>

constexpr int WINDOW_X = 10;
constexpr int WINDOW_Y = 10;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void DisplayCurrentDateTime(HWND hwnd, int x, int y);
void Waku(HWND hwnd);

int main() {

    // ウィンドウクラスの登録
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 255)); // 背景色を青に設定
    wc.lpszClassName = "MyWindowClass";
    RegisterClass(&wc);

    // フルスクリーンのサイズ取得
    //int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    //int screenHeight = GetSystemMetrics(SM_CYSCREEN);

    // 画面のサイズを取得
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);

    // ウィンドウのサイズ
    int windowWidth = 1000;
    int windowHeight = 800;

    // ウィンドウ位置を画面の中央に設定
    int posX = (screenWidth - windowWidth) / 2;
    int posY = (screenHeight - windowHeight) / 2;

    // ウィンドウ作成
    HWND hwnd = CreateWindow("MyWindowClass", "タイトル", WS_OVERLAPPEDWINDOW & ~(WS_SYSMENU), posX, posY, windowWidth, windowHeight, NULL, NULL, GetModuleHandle(NULL), NULL); //サイズ設定
    //HWND hwnd = CreateWindow("MyWindowClass", "My Window", WS_OVERLAPPEDWINDOW & ~(WS_SYSMENU), CW_USEDEFAULT, CW_USEDEFAULT, screenWidth, screenHeight, NULL, NULL, GetModuleHandle(NULL), NULL);    // フルサイズ


    // ウィンドウ表示
    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);

    // スレッドを起動して日時を表示
    //std::thread dateTimeThread(DisplayCurrentDateTime, hwnd, WINDOW_X, WINDOW_Y);
    //std::thread dateTimeThread(DisplayCurrentDateTime, hwnd);

    // ウィンドウの枠を表示
    Waku(hwnd);

    // カーソル非表示
    ShowCursor(FALSE);

    // メッセージループ
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);

        if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) {     //ESCキーを押すとスレッド終了
            break;
        }
    }

    // スレッドを終了
    //dateTimeThread.detach();

    return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)    // ESCキーでウィンドウを閉じる
            PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

// リアルタイム日時
void DisplayCurrentDateTime(HWND hwnd, int x, int y) {
    while (true) {

        HDC hdc = GetDC(hwnd);
        RECT rect = { x, y, x + 200, y + 100 }; // 文字の表示位置(left, top, right ,bottom)

        // フォント作成 高さ, 幅, 傾き(反時計回り), 文字の向き, 太字サイズ, Italic,  下線,  打消し線
        HFONT hFont = CreateFont(24, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_OUTLINE_PRECIS,
            CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial");
 
        HFONT hOldFont = (HFONT)SelectObject(hdc, hFont);

        SetBkColor(hdc, RGB(0, 0, 255));        // 文字の背景色
        SetTextColor(hdc, RGB(0, 255, 255));    // 文字色

        time_t now = time(nullptr);
        struct tm* localTime = localtime(&now);
        char timeStr[128];
        strftime(timeStr, sizeof(timeStr), "%Y/%m/%d %H:%M:%S", localTime);

        InvalidateRect(hwnd, NULL, TRUE);
        UpdateWindow(hwnd);


        DrawTextA(hdc, timeStr, -1, &rect, DT_LEFT | DT_TOP | DT_SINGLELINE);   // 日時を描画
        ReleaseDC(hwnd, hdc);

        // 1秒待機
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

// 枠の描画
void Waku(HWND hwnd) {
    HDC hdc = GetDC(hwnd);
    RECT rect;
    GetClientRect(hwnd, &rect);

    // 太く水色の線枠を描画
    HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 255));       // 枠の背景色
    HPEN hPen = CreatePen(PS_SOLID, 3, RGB(0, 255, 255));   // 太い枠線
    HBRUSH hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
    HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);

    Rectangle(hdc, 4, 4, 780, 40);
    Rectangle(hdc, 4, 44, 780, 386);
    Rectangle(hdc, 4, 390, 780, 430);

    // 枠の描画
    FrameRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));

    ReleaseDC(hwnd, hdc);
}

C++ウィンドウ表示など

#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <chrono>
#include <ctime>
#include <thread>

constexpr int WINDOW_X = 10;
constexpr int WINDOW_Y = 10;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void DisplayCurrentDateTime(HWND hwnd, int x, int y);
void Waku(HWND hwnd);


int main() {

    // 画面のサイズを取得
    int screenWidth = GetSystemMetrics(SM_CXSCREEN);
    int screenHeight = GetSystemMetrics(SM_CYSCREEN);

    // ウィンドウのサイズ
    int windowWidth = 800;
    int windowHeight = 800;

    // ウィンドウ位置を画面の中央に設定
    int posX = (screenWidth - windowWidth) / 2;
    int posY = (screenHeight - windowHeight) / 2;

    // ウィンドウクラスの登録
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = GetModuleHandle(NULL);
    wc.lpszClassName = "MyWindowClass";
    RegisterClass(&wc);

    // ウィンドウ作成
    //HWND hwnd = CreateWindow("MyWindowClass", "My Window", WS_OVERLAPPEDWINDOW, WINDOW_X, WINDOW_Y, 400, 300, NULL, NULL, GetModuleHandle(NULL), NULL);
    HWND hwnd = CreateWindow("MyWindowClass", "タイトル", WS_OVERLAPPEDWINDOW, posX, posY, windowWidth, windowHeight, NULL, NULL, GetModuleHandle(NULL), NULL);

    // ウィンドウ表示
    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);

    // ウィンドウの枠を表示
    Waku(hwnd);

    // スレッドを起動して日時を表示
    std::thread dateTimeThread(DisplayCurrentDateTime, hwnd, WINDOW_X, WINDOW_Y);
    //displayThread.detach();

    // メッセージループ
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);

        if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) {     //ESCキーを押すとスレッド終了
            break;
        }
    }

    // スレッドを終了
    dateTimeThread.detach();

    return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
            PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

// リアルタイム日時
void DisplayCurrentDateTime(HWND hwnd, int x, int y) {
    while (true) {

        HDC hdc = GetDC(hwnd);
        RECT rect = { x, y, x + 200, y + 100 };

        SetTextColor(hdc, RGB(255, 0, 0));

        time_t now = time(nullptr);
        struct tm* localTime = localtime(&now);
        char timeStr[128];
        strftime(timeStr, sizeof(timeStr), "%Y/%m/%d %H:%M:%S", localTime);

        InvalidateRect(hwnd, NULL, TRUE);
        UpdateWindow(hwnd);


        DrawTextA(hdc, timeStr, -1, &rect, DT_LEFT | DT_TOP | DT_SINGLELINE);   // 日時を描画
        ReleaseDC(hwnd, hdc);

        // 1秒待機
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}

// 枠の描画
void Waku(HWND hwnd) {
    HDC hdc = GetDC(hwnd);
    RECT rect;
    GetClientRect(hwnd, &rect);

    Rectangle(hdc, 50, 50, 600, 150);
    Rectangle(hdc, 50, 170, 600, 270);
    Rectangle(hdc, 50, 290, 600, 390);

    // 枠の描画
    FrameRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));

    ReleaseDC(hwnd, hdc);
}

引数LPCWSTR型によるビルドエラー対策

そのエラーはconst wchar_t*型を渡すべきところに、const char*を渡しているというエラーです。
Windows APIはワイド文字モードでビルドすると、多くの文字列はconst wchar_t*で受け取ります。
マルチ・バイト文字モードでビルドするか、文字列をL"xxx"のようにしてワイド文字の文字列にするなどの対策があります。

 

プロジェクト->プロパティ->構成プロパティ->全般 の中にある
文字セットを[Unicode 文字セットを使用する]から[マルチバイト文字セットを使用する]に変更することで可能です。

_dos_finefirst()の代替関数(確定)

#include <io.h>
#include <cstring>

int main() {
    struct _finddata_t fileinfo;
    intptr_t handle;

    const char* filespec = "C:\\Users\\sannp\\Desktop\\SAMC1\\DAT\\data\\data?.dat"; // 検索するファイル名のパターンを指定

    // 検索を開始
    handle = _findfirst(filespec, &fileinfo);
    if (handle == -1) {
        std::cerr << "ファイルが見つかりませんでした。" << std::endl;
        return 1;
    }

    // 検索結果を出力
    do {
        if (fileinfo.attrib & _A_ARCH) {
            std::cout << "ファイル: " << fileinfo.name << std::endl;
        }
    } while (_findnext(handle, &fileinfo) == 0);

    // ハンドルを閉じる
    _findclose(handle);

    return 0;
}

_dos_findfirst 関数について

_dos_findfirst 関数は、DOS ファイルシステム上のファイルやディレクトリを検索するための関数です。dos.h ヘッダーファイルで提供され、DOS プログラミング環境で使用されましたが、現代の Windows プログラミングには推奨されません。

以下は _dos_findfirst 関数のプロトタイプです:

int _dos_findfirst(const char* filespec, unsigned int attribute, struct find_t* fileinfo);

この関数は、3つの引数を受け取ります:

  1. filespec:検索するファイルやディレクトリのパスおよびパターンを指定します。
  2. attribute:検索するファイルの属性を指定します。これは、ファイルが持つ属性に基づいて検索を絞り込むために使用されます。
  3. fileinfo:検索結果を格納する find_t 構造体へのポインタです。

_dos_findfirst 関数は、指定されたパスとパターンに一致する最初のファイルまたはディレクトリを検索します。検索結果は fileinfo 引数に格納されます。検索に成功した場合、この関数は0を返します。それ以外の場合はエラーコードが返されます。

注意点として、_dos_findfirst および関連する関数は、現代の Windows プログラミングでは非推奨であり、代わりに標準の C++ ファイル操作関数や、Windows API の関数を使用することが推奨されます。

 

_A_ARCH は、C ランタイムライブラリで定義されているファイル属性の一つです。これはファイルのアーカイブ属性を示します。アーカイブ属性は、ファイルがバックアップされる必要があることを示します。

以下は _A_ARCH の値と意味です:

  • _A_ARCH:ファイルがアーカイブされたことを示します。
  • アーカイブファイル」は複数のファイルがひとつにまとめられたファイル

C ランタイムのドキュメントによれば、_A_ARCH の値は 0x0020 です。これは2進数で 0000 0000 0010 0000 に対応します。つまり、5番目のビットがセットされています。このビットがセットされている場合、ファイルはアーカイブされたことを示します。

アーカイブ属性は、ファイルがバックアップされる必要があるかどうかを示すだけであり、ファイルがアーカイブされる方法やバックアップの詳細に関する情報は提供しません。これは、古いバージョンの Windows でバックアッププログラムが使用されていた時代に、ファイルがバックアップされるべきかどうかを追跡するために使用されました。