スポンサーリンク

Win32APIでIMEを使用(2)

WM_IME_COMPOSITIONはlParamによって取得できる情報を区別している。特にGCS_COMPATTRは変換中の文字列の一文字ずつの情報を扱うのでATTR_*でさらに分岐が必要。

 

#pragma warning(disable:4996)

#include <windows.h>
#include <imm.h>
#pragma comment(lib, "imm32.lib")

#include <string>

// https://learn.microsoft.com/ja-jp/windows/win32/intl/ime-composition-string-values

// 変換中の文字列 GCS_COMPSTR
void test_GCS_COMPSTR(HIMC hIMC, HDC hdc) {

    DWORD inputBytes = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
    if (inputBytes) {

        size_t U16Count = inputBytes / sizeof(wchar_t) + 1;// wchar_tでの、NULLを含んだ文字数
        wchar_t* buffer = new wchar_t[U16Count];

        // 確定した文字列を取得
        ImmGetCompositionStringW(hIMC, GCS_COMPSTR, buffer, inputBytes);
        buffer[U16Count - 1] = L'\0';

        // 確定した文字列を描画
        int inx = 0;
        int iny = 0;
        TextOutW(hdc, inx, iny, buffer, wcslen(buffer));

        delete[] buffer;

    }

}

// 変換中の文字列の属性情報 GCS_COMPATTR
void test_GCS_COMPATTR(HIMC hIMC, HDC hdc) {
    DWORD attr = ImmGetCompositionString(hIMC, GCS_COMPATTR, NULL, 0);

    BYTE* buffer = new BYTE[attr];// 変換中の文字数と同じ個数の要素を確保

    ImmGetCompositionString(hIMC, GCS_COMPATTR, buffer, attr);// 変換中の各文字ごとに状態情報が格納される

    char str[256] = {};

    for (size_t i = 0; i < 256; i++)
        str[i] = ' ';
    str[255] = '\0';
    TextOutA(hdc, 0, 30, str, strlen(str));


    size_t i;
    for (i = 0; i < attr; i++) {
        switch (buffer[i])
        {
        case ATTR_INPUT:
            str[i] = 'I';
            break;
        case ATTR_TARGET_CONVERTED:
            str[i] = 'T';
            break;
        case ATTR_CONVERTED:
            str[i] = 'C';
            break;
        case ATTR_FIXEDCONVERTED:
            str[i] = 'F';
            break;
        case ATTR_TARGET_NOTCONVERTED:
            str[i] = 'N';
            break;
        case ATTR_INPUT_ERROR:
            str[i] = 'E';
            break;
        }
	}
    str[i] = '*';
    TextOutA(hdc, 0, 30, str, strlen(str));


    delete[] buffer;
}

// 変換中の文字列内のカーソル位置  
void test_GCS_CURSORPOS(HIMC hIMC, HDC hdc) {
    LONG cursorPos = ImmGetCompositionString(hIMC, GCS_CURSORPOS, NULL, 0);

    char str[256] = {};
    sprintf(str, "cursorPos:%d", cursorPos);

    TextOutA(hdc, 0, 50, str, strlen(str));

}

// 変換開始位置 GCS_DELTASTART
void test_GCS_DELTASTART(HIMC hIMC, HDC hdc) {
    LONG deltaStart = ImmGetCompositionString(hIMC, GCS_DELTASTART, NULL, 0);

    char str[256] = {};
    sprintf(str, "deltaStart:%d", deltaStart);

    TextOutA(hdc, 0, 90, str, strlen(str));

}

// GCS_RESULTSTR
void test_GCS_RESULTSTR(HIMC hIMC,HDC hdc) {
    // GCS_RESULTSTR ... IMEの入力が確定されたフラグ

    // 確定した文字列のバイト数を取得(NULLは含まない)
    DWORD inputBytes = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
    if (inputBytes) {

        size_t U16Count = inputBytes / sizeof(wchar_t) + 1;// wchar_tでの、NULLを含んだ文字数
        wchar_t* buffer = new wchar_t[U16Count];

        // 確定した文字列を取得
        ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buffer, inputBytes);
        buffer[U16Count - 1] = L'\0';

        // 確定した文字列を描画
        int inx = 100;
        int iny = 100;
        TextOutW(hdc, inx, iny, buffer, wcslen(buffer));

        delete[] buffer;
    }
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {

    HIMC hIMC;

    int inx = 100;
    int iny = 100;
    switch (message) {
    case WM_CREATE:

        // IMEを使用可能にする
        ImmAssociateContext(hWnd, ImmCreateContext());


        break;


    case WM_IME_STARTCOMPOSITION:

        OutputDebugString(L"IME 入力開始\n");

        hIMC = ImmGetContext(hWnd);  // IMEコンテキストを取得
        if (hIMC)
        {
            // IMEのウィンドウ位置を設定
            COMPOSITIONFORM cf2;
            cf2.dwStyle = CFS_POINT;
            cf2.ptCurrentPos.x = inx;
            cf2.ptCurrentPos.y = iny;
            ImmSetCompositionWindow(hIMC, &cf2); // IMEのウィンドウ位置を設定
            ImmReleaseContext(hWnd, hIMC);
        }
        break;

    case WM_IME_COMPOSITION:

        // IMEの入力中の処理

        hIMC = ImmGetContext(hWnd);
        if (hIMC) {
            HDC hdc = GetDC(hWnd);
            if (lParam & GCS_RESULTSTR) {
                test_GCS_RESULTSTR(hIMC,hdc);
            }
            if (lParam & GCS_COMPSTR) {
                test_GCS_COMPSTR(hIMC, hdc);
            }
            if (lParam & GCS_COMPATTR) {
                test_GCS_COMPATTR(hIMC, hdc);
            }
            if (lParam & GCS_CURSORPOS)
            {
                test_GCS_CURSORPOS(hIMC, hdc);
            }
            if (lParam & GCS_DELTASTART)
            {
                test_GCS_DELTASTART(hIMC, hdc);
            }
            ReleaseDC(hWnd, hdc);
            ImmReleaseContext(hWnd, hIMC);
        }
        break;

    case WM_IME_ENDCOMPOSITION:
        OutputDebugString(L"IME 入力終了\n");
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return DefWindowProc(hWnd, message, wParam, lParam);;
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: