huidong

首页 | 会员登录 | 关于
搜索文章


之前写了一个简易输入框:http://huidong.xyz/index.php?mode=2&id=261


昨天看到 BestAns 发布的文章(https://codebus.cn/bestans/textbox-sample )也是一个输入框


可惜还没有实现输入法跟随和鼠标交互操作,我只有周末一点时间,鼠标交互写起来比较耗时,所以先把输入法跟随实现了。


由于我之前写的那个输入框已经有了输入法锁定,现在只需要改成输入法跟随即可,还是比较简单的。


在尝试的过程中我还发现:当时六月份写这个输入框的时候用的是 easyx 2021.1.12,这个版本可以直接用 _getwch() 函数获取中文输入。


但是现在我换成了 EasyX 20210730,已经不支持用 _getwch() 了,必须用 ExMessage 相关函数获取 EM_CHAR 消息。


所以这里也改成了使用 peekmessage 函数来获取按键输入。需要注意的是,这个函数获取的换行消息只有 '\r' 而没有 '\n'。


代码:

#include <stdio.h>
#include <easyx.h>
#include <string>
#include <conio.h>
#include <time.h>
using namespace std;

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

WNDPROC OldProc;

int x, y;

LRESULT CALLBACK NewProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_IME_COMPOSITION:
    {
        HIMC hIMC = ImmGetContext(GetHWnd());    // 获取HIMC
        if (hIMC)
        {
            // Set composition window position near caret position
            POINT point;
            GetCaretPos(&point);//获取输入光标位置,存入point结构体

            COMPOSITIONFORM Composition;
            Composition.dwStyle = CFS_POINT;
            Composition.ptCurrentPos.x = x;
            Composition.ptCurrentPos.y = y;
            ImmSetCompositionWindow(hIMC, &Composition);//设置

            ImmReleaseContext(GetHWnd(), hIMC);//释放
        }
    }
    default:
        return CallWindowProc(OldProc, hWnd, message, wParam, lParam);
    }
}

int GetImmX(wstring str)
{
    wstring line;
    for (int i = str.size() - 1; i >= 0; i--)
    {
        if (str[i] == L'\n')
        {
            break;
        }

        line += str[i];
    }

    return textwidth(line.c_str());
}

int GetImmY(wstring str)
{
    RECT r = { 0 };
    int h = drawtext(str.c_str(), &r, DT_NOCLIP | DT_LEFT | DT_TOP);
    h -= textheight('T');
    return h >= 0 ? h : 0;
}

int main()
{
    initgraph(640, 480);
    setbkcolor(WHITE);
    settextcolor(BLACK);
    BeginBatchDraw();
    cleardevice();
    FlushBatchDraw();

    OldProc = (WNDPROC)GetWindowLong(GetHWnd(), GWL_WNDPROC);
    SetWindowLong(GetHWnd(), GWL_WNDPROC, (LONG)NewProc);

    RECT rct = { 0,0,getwidth(),getheight() };

    wstring strText = L"EasyX " + (wstring)GetEasyXVer() + L"\n在此输入文字:";

    int nTimeTag = 0;

    int width = 0;
    int height = 0;

    ExMessage msg;

    while (true)
    {
        int nTimeUnit = clock() / 800;

        if (peekmessage(&msg, EM_CHAR))
        {
            wchar_t word = msg.ch;

            // 规范为 \n
            if(word == L'\r')
            {
                word = L'\n';
            }

            if (word == L'\b')
            {
                if (strText.length())
                {
                    strText = strText.substr(0, strText.size() - 1);
                }
            }
            else
            {
                strText += word;
            }

            // 更新 Imm 位置
            x = GetImmX(strText);
            y = GetImmY(strText);
        }

        cleardevice();
        drawtext((strText + L"_").c_str(), &rct, DT_LEFT | DT_TOP);
        FlushBatchDraw();
    }

    EndBatchDraw();
    closegraph();
    return 0;
}



运行效果



返回首页


Copyright (C) 2018-2021 huidong