之前写了一个简易输入框: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;
}
运行效果