引数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 でバックアッププログラムが使用されていた時代に、ファイルがバックアップされるべきかどうかを追跡するために使用されました。

C++ RS-232C通信制御プログラム(パート2)

<RS232C.cpp>

#include <iostream>
#include "SerialPort.h" // シリアルポートクラスのヘッダーファイルをインクルード
int main() {
    // シリアルポート設定(ポート、データビット長、パリティチェック、ストップビッチ長)
    SerialPort serial(TEXT("COM1"), CBR_9600, 8, EVENPARITY, ONESTOPBIT);
    // シリアルポートが正常に開かれたか確認
    if (!serial.isConnected()) {
        //std::cerr <<  << std::endl;
        printf("Cannot Initialize SIO port [%s].\n","COM1");
        return 1;
    }
    // メッセージの送信
    std::string message = "Hello, Serial Port!";
    serial.TxCommand(message.c_str(), message.size());
    // データの受信
    char incomingData[256] = { 0 };
    serial.RxCommand(incomingData, sizeof(incomingData));
    // 受信したデータを表示
    std::cout << "Received data: " << incomingData << std::endl;
    return 0;
}

<COM.cpp>

#include "SerialPort.h"
#include <iostream>
#include <windows.h>
// シリアルポートのオープン
SerialPort::SerialPort(const TCHAR* portName, DWORD baudRate, BYTE byteSize, BYTE parity, BYTE stopBits) {
    hSerial = CreateFile(
        portName,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL
    );
    // シリアルポートの設定
    if (hSerial != INVALID_HANDLE_VALUE) {
        DCB dcbSerialParams = { 0 };
        dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
        GetCommState(hSerial, &dcbSerialParams);
        dcbSerialParams.BaudRate = baudRate;
        dcbSerialParams.ByteSize = byteSize;
        dcbSerialParams.Parity = parity;
        dcbSerialParams.StopBits = stopBits;
        SetCommState(hSerial, &dcbSerialParams);
        connected = true;
    }
    else {
        std::cerr << "Error: Unable to open COM port." << std::endl;
        connected = false;
    }
}
SerialPort::~SerialPort() {
    if (hSerial != INVALID_HANDLE_VALUE) {
        CloseHandle(hSerial);
    }
}
bool SerialPort::TxCommand(const char* buffer, unsigned int bufferSize) {
    DWORD bytesWritten;
    if (!WriteFile(hSerial, (void*)buffer, bufferSize, &bytesWritten, NULL)) {
        std::cerr << "Error: Unable to write to COM port." << std::endl;
        return false;
    }
    return true;
}
bool SerialPort::RxCommand(char* buffer, unsigned int bufferSize) {
    DWORD bytesRead;
    if (!ReadFile(hSerial, buffer, bufferSize, &bytesRead, NULL)) {
        std::cerr << "Error: Unable to read from COM port." << std::endl;
        return false;
    }
    return true;
}
bool SerialPort::isConnected() {
    return connected;
}

<SerialPort.h>

#include <Windows.h>
class SerialPort {
public:
    // コンストラク
    SerialPort(const TCHAR* portName, DWORD baudRate, BYTE byteSize, BYTE parity, BYTE stopBits);
    // デストラク
    ~SerialPort();
    // データ送信
    bool TxCommand(const char* buffer, unsigned int bufferSize);
    // データ受信
    bool RxCommand(char* buffer, unsigned int bufferSize);
    // 接続確認
    bool isConnected();
private:
    HANDLE hSerial;
    bool connected;
};

C++ dos_getftime(),fread()に関して

#include <iostream>
#include <Windows.h>
#include <ctime>
//fopen関数を使用できるためのおまじない
#pragma warning(disable: 4996)
#define NUM_ALPHA  256
int main() {
    FILE *fp;
    char buffer[NUM_ALPHA + 1];
    int num;
    const int BUFFER_SIZE = 100;
    // File path
    const char* filePath = "C:\\Users\\sannp\\Desktop\\SAMC1\\free\\file.txt";
    if *1 != NULL) {
        num = fread(buffer, sizeof(char), 1, fp);
        std::cout << num << std::endl;
    }

    FILETIME ftLastWrite;
    SYSTEMTIME stUTC, stLocal;
    // ファイルの最終更新日時を取得
    HANDLE hFile = CreateFileA(
        filePath,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );
    if (hFile != INVALID_HANDLE_VALUE) {
        if (GetFileTime(hFile, NULL, NULL, &ftLastWrite)) {
            // ファイルタイムをUTCからローカル時刻に変換
            FileTimeToSystemTime(&ftLastWrite, &stUTC);
            SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);
            // ファイルの最終更新日時を表示
            std::cout << "ファイルの最終更新日時: "
                << stLocal.wYear << "/" << stLocal.wMonth << "/" << stLocal.wDay << " "
                << stLocal.wHour << ":" << stLocal.wMinute << ":" << stLocal.wSecond << std::endl;
        }
        else {
            std::cerr << "ファイルの最終更新日時の取得に失敗しました。エラーコード: " << GetLastError() << std::endl;
        }
        CloseHandle(hFile);
    }
    else {
        std::cerr << "ファイルを開くことができませんでした。エラーコード: " << GetLastError() << std::endl;
    }
 
    return 0;
}

*1:fp = fopen(filePath, "rb"

C++

古い_dos_getftime()関数は、DOS時代のファイルの最終更新日時を取得する関数でしたが、Windowsでその代替となる関数は標準的なC++Windows APIには存在しません。代わりに、Windowsでファイルの属性を取得するには、Windows APIGetFileAttributes() 関数や GetFileTime() 関数を使用します。以下はその例です。

#include <iostream>
#include <windows.h>
int main() {
    const char* filePath = "example.txt"; // ファイルのパスを設定
    // ファイルの属性を取得
    WIN32_FILE_ATTRIBUTE_DATA fileInfo;
    if (!GetFileAttributesEx(filePath, GetFileExInfoStandard, &fileInfo)) {
        std::cerr << "Failed to get file attributes." << std::endl;
        return 1;
    }
    // ファイルの最終更新日時を取得
    FILETIME lastWriteTime = fileInfo.ftLastWriteTime;
    // FILETIMEをSYSTEMTIMEに変換
    SYSTEMTIME systemTime;
    if (!FileTimeToSystemTime(&lastWriteTime, &systemTime)) {
        std::cerr << "Failed to convert file time to system time." << std::endl;
        return 1;
    }
    // 最終更新日時を表示
    std::cout << "Last modified time: ";
    std::cout << systemTime.wYear << "-" << systemTime.wMonth << "-" << systemTime.wDay;
    std::cout << " " << systemTime.wHour << ":" << systemTime.wMinute << ":" << systemTime.wSecond << std::endl;
    return 0;
}

このコードでは、GetFileAttributesEx() 関数を使用してファイルの属性を取得し、ftLastWriteTime メンバーから最終更新日時を取得します。そして、FileTimeToSystemTime() 関数を使用して、ファイルの最終更新日時をSYSTEMTIME構造体に変換して表示しています。

C++API

12個のボタンを描画して、1個目のボタンを押すと「Hallo!」のメッセージが表示される

#include <Windows.h>
#include <vector>

// グローバル変数
std::vector<HWND> g_buttons; // ボタンウィンドウのハンドルを格納するベクター

// ボタンクリック時の処理
void OnButtonClick(int index) {
    MessageBox(NULL, TEXT("Hallo!"), TEXT("Message"), MB_OK | MB_ICONINFORMATION);
}

// ウィンドウプロシージャ
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CLOSE:
            PostQuitMessage(0);
            break;

        case WM_COMMAND:
            for (size_t i = 0; i < g_buttons.size(); ++i) {
                if *1 {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

****************************

直線を描画(\斜め線)

#include <Windows.h>

// ウィンドウプロシージャ
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CLOSE:
            PostQuitMessage(0);
            break;

        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hwnd, &ps);

                // 直線を描画
                MoveToEx(hdc, 50, 50, NULL); // 始点の設定
                LineTo(hdc, 200, 200); // 終点の設定

                EndPaint(hwnd, &ps);
            }
            break;

        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

// エントリーポイント
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // ウィンドウクラスの定義
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = TEXT("WindowClass");

    // ウィンドウクラスの登録
    RegisterClass(&wc);

    // ウィンドウの作成
    HWND hwnd = CreateWindowEx(
        0,
        TEXT("WindowClass"),
        TEXT("Line Window"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
        NULL,
        NULL,
        hInstance,
        NULL
    );

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

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

    return 0;
}

****************************

以下は、Visual C++のWindowsAPIを使用して、黒い背景のウィンドウを作成し、青色のテキストで「Hallo!」を表示するプログラムの例です。

#include <Windows.h>

// ウィンドウプロシージャ
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CLOSE:
            PostQuitMessage(0);
            break;

        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hwnd, &ps);

                // 文字列を描画
                SetTextColor(hdc, RGB(0, 0, 255)); // 色を青色に設定
                SetBkColor(hdc, RGB(0, 0, 0)); // 背景色を黒に設定
                TextOut(hdc, 20, 20, TEXT("Hallo!"), 6);

                EndPaint(hwnd, &ps);
            }
            break;

        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

// エントリーポイント
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // ウィンドウクラスの定義
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = TEXT("WindowClass");

    // ウィンドウクラスの登録
    RegisterClass(&wc);

    // ウィンドウの作成
    HWND hwnd = CreateWindowEx(
        0,
        TEXT("WindowClass"),
        TEXT("Text Window"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
        NULL,
        NULL,
        hInstance,
        NULL
    );

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

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

    return 0;
}

****************************

黒い背景のウィンドウを作成するプログラム

#include <Windows.h>

// ウィンドウプロシージャ
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CLOSE:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

// エントリーポイント
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // ウィンドウクラスの定義
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = TEXT("WindowClass");
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // 背景色を黒に設定

    // ウィンドウクラスの登録
    RegisterClass(&wc);

    // ウィンドウの作成
    HWND hwnd = CreateWindowEx(
        0,
        TEXT("WindowClass"),
        TEXT("Black Window"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
        NULL,
        NULL,
        hInstance,
        NULL
    );

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

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

    return 0;
}

*1:HWND)lParam == g_buttons[i]) {
                    OnButtonClick(i);
                    break;
                }
            }
            break;

        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

// エントリーポイント
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // ウィンドウクラスの定義
    WNDCLASS wc = {};
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = TEXT("WindowClass");

    // ウィンドウクラスの登録
    RegisterClass(&wc);

    // ウィンドウの作成
    HWND hwnd = CreateWindowEx(
        0,
        TEXT("WindowClass"),
        TEXT("Button Window"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 400, 300,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    // ボタンの作成
    const int buttonWidth = 100;
    const int buttonHeight = 30;
    const int buttonSpacing = 10;
    const int buttonCount = 12;
    const int buttonStartX = (400 - (buttonWidth * buttonCount + buttonSpacing * (buttonCount - 1))) / 2;
    const int buttonY = 230;

    for (int i = 0; i < buttonCount; ++i) {
        HWND button = CreateWindow(
            TEXT("BUTTON"),
            TEXT("Button"),
            WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
            buttonStartX + (buttonWidth + buttonSpacing) * i, buttonY, buttonWidth, buttonHeight,
            hwnd,
            NULL,
            hInstance,
            NULL
        );
        g_buttons.push_back(button);
    }

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

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