unicode版本软件在编辑框中如何输入中文?

iamluda 2009-06-17 10:18:27
开发unicode版本的软件,在应用程序中对输入法编辑器的初始化代码如下,
HINSTANCE hInstUser;
if (hInstUser = LoadLibrary("USER32.DLL"))
{
m_pToUnicodeEx = reinterpret_cast<int (*)(UINT,UINT,CONST PBYTE,LPWSTR,int,UINT,HKL)>
(GetProcAddress(hInstUser, "ToUnicodeEx"));
FreeLibrary(hInstUser);
}

碰到的问题是:编辑框控件接收到的文字不是中文,而是乱码呢。如果直接给编辑框的文字赋值,却可以正确显示。
用拷贝的汉字粘贴到编辑框也可以正确显示。

碰到这种情况该如何处理呢?
...全文
199 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
iamluda 2009-06-17
  • 打赏
  • 举报
回复
针对自己写的窗口过程,键盘处理代码如下:
//IME消息处理
bool ev_Win32Keyboard::onIMEChar(AV_View * pView,HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
WCHAR b = wParam;

// 2nd byte of MBCS is in high byte of word
if (!m_bIsUnicodeInput && (wParam & 0xff00))
b = ((BYTE)(wParam >> 8)) | ((BYTE)wParam << 8);

_emitChar(pView,hWnd,iMsg,wParam,lParam,b,0);
return true;
}

/*处理 WM_CHAR 消息*/
bool ev_Win32Keyboard::onChar(AV_View * pView, HWND hWnd, UINT iMsg, WPARAM nVirtKey, LPARAM keyData)
{
EV_EditModifierState ems = _getModifierState();

/*
If the key is NOT processed as an Abiword command
we follow their path and need to emit the char
*/
if (m_bWasAnAbiCommand)
{
#ifdef _WIN32KEY_DEBUG
UT_DEBUGMSG(("WIN32KEY_DEBUG->onChar return\n"));
#endif

// reset the command flag; see bug 8928
m_bWasAnAbiCommand = false;
return true;
}

// Process the key
_emitChar(pView,hWnd,iMsg,nVirtKey,keyData,nVirtKey,0);
return true;
}


//
void ev_Win32Keyboard::_emitChar(AV_View * pView,HWND hWnd, UINT iMsg, WPARAM nVirtKey, LPARAM keyData,
UT_uint32 b, EV_EditModifierState ems)
{
// do the dirty work of pumping this character thru the state machine.

UT_UCSChar charData[2];
size_t ret;
if( m_iconv != UT_ICONV_INVALID )
{
// convert to 8bit string and null terminate
size_t len_in, len_out;
const char *In = (const char *)&b;
char *Out = (char *)&charData;

// 2 bytes for Unicode and MBCS(多字节字符集)
// 4 bytes for UNICHAR msg WM_UNICHAR使用了UTF-32格式
if(iMsg == WM_UNICHAR)
len_in = 4;
else if(m_bIsUnicodeInput || (nVirtKey & 0xff00))
len_in = 2;
else
len_in = 1;

len_out = sizeof(charData);

//执行转换 m_iconv为转换描诉符 在WIN32平台为UCS-4-INTERAL
//即在程序内部使用UCS-4-INTERAL编码
if ((ret = UT_iconv( m_iconv, &In, &len_in, &Out, &len_out )) == -1)
UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
if (Out == (char *)charData)
{
// m_iconv is waiting for a combination keystroke. Flush the buffer
if ((ret = UT_iconv( m_iconv, NULL, &len_in, &Out, &len_out )) == -1)
UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
}
}
else
{
charData[0] = b;
charData[1] = 0;
}

EV_EditMethod * pEM;
EV_EditEventMapperResult result = m_pEEM->Keystroke(EV_EKP_PRESS|ems|charData[0],&pEM);

switch (result)
{
case EV_EEMR_BOGUS_START:
//UT_DEBUGMSG((" Unbound StartChar: %c\n",b));
break;

case EV_EEMR_BOGUS_CONT:
//UT_DEBUGMSG((" Unbound ContChar: %c\n",b));
break;

case EV_EEMR_COMPLETE:
UT_ASSERT(pEM);
invokeKeyboardMethod(pView,pEM,charData,1);
break;

case EV_EEMR_INCOMPLETE:
//MSG(keyData,((" Non-Terminal-Char: %c\n",b)));
break;

default:
UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
break;
}

return;
}

对于标准控件,其窗口过程控件自己处理了. 由于键盘的输入是unicode ,所以编辑控件碰到汉字输入,显示成乱吗了.

这种情况该如何处理?
iamluda 2009-06-17
  • 打赏
  • 举报
回复
我的程序是 纯C++的程序,UNICODE版本,
在文档的窗口过程中,我可以对汉字消息(IME输入法)进行处理,但对于WINDOWS标准控件 我该如何处理呢?
「已注销」 2009-06-17
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 iamluda 的回复:]
引用 2 楼 Loaden 的回复:
文本也是Unicode,使用SetWindowTextW或Get...W

多谢您 多次的帮助.

这次碰到的问题是,键盘输入不正确 ,如果直接给编辑框的文字赋值(SetWindowTextW),却可以正确显示。

这样该如何处理呢?
[/Quote]
不管哪个输入法都这样吗?
iamluda 2009-06-17
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 Loaden 的回复:]
文本也是Unicode,使用SetWindowTextW或Get...W
[/Quote]

多谢您 多次的帮助.

这次碰到的问题是,键盘输入不正确 ,如果直接给编辑框的文字赋值(SetWindowTextW),却可以正确显示。

这样该如何处理呢?
「已注销」 2009-06-17
  • 打赏
  • 举报
回复
楼主看看这个:
外挂输入法编程构思
外挂输入法编程构思

看到别人编制的外挂输入法,好是羡慕,自认为从编程上不会太难,但是经过一翻琢磨和修炼,实际搞得还差一半。谈一些感受及编程方面的东西,分享及讨教。

先谈谈做外挂输入法的基本构思

外挂输入法必需要有钩子HOOK,并且应当是系统全局性质的钩子。而一般认为要做全局的系统钩子,就应建立动态联接库DLL。但是,也可以用:
WH_KEYBROAD_LL 底层键盘钩子
WH_MOUSE_LL 底层键盘钩子
WH_JOURNALRECORD 日志钩子
这三种钩子建立非DLL的可直接执行的钩子程序.exe。

当完成系统钩子建立之后,应当考虑怎么做成托盘图标程序Systrayicon。在这一步中应当隐藏主窗口,并把图标放置到系统托盘。由此使得整个程序运行起来时,仅在任务栏右下角显示一个系统托盘图标。
主要是:
void CIconDlg::ToTray(void)
{
nid.cbSize=(DWORD)sizeof(NOTIFYICONDATA);
nid.hWnd=this->m_hWnd;
nid.uID=IDR_MAINFRAME;
nid.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP ;
nid.uCallbackMessage=WM_SHOWTASK;
nid.hIcon=LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_MAINFRAME));
lstrcpy(nid.szTip,_T("XXX 1.0");
Shell_NotifyIcon(NIM_ADD,&nid);
ShowWindow(SW_SHOWMINIMIZED|SW_SHOWNOACTIVATE);
ShowWindow(SW_HIDE);
}

用钩子截取键盘输入,是要实现输入变换的。

从酷极输入平台作者coolvv了解到的关键代码:

coolvv

发表于:2009-04-17 14:28:2111楼 得分:90

安装键盘底层钩子,取得输入窗口的句柄,也就是当前光标所在窗口句柄,然后向该句柄发送字符消息。框架如下:
void Insert::writeIn(wxString str)
{
DWORD threadId = GetWindowThreadProcessId(_tarWnd, NULL);
DWORD curId = GetCurrentThreadId();
AttachThreadInput(threadId, curId, true);
for (size_t i = 0; i < str.Length(); i++)
{
if (str.at(i) == '\n ')
PostMessage(_focusWnd, WM_KEYDOWN, VK_RETURN, 0);
else
PostMessage(_focusWnd, WM_CHAR, (WPARAM)str.at(i), 0);
}

// PostMessage(_focusWnd, WM_KEYDOWN, VK_LEFT, 0);
PostMessage(_focusWnd, WM_KEYDOWN, VK_ESCAPE, 0);

AttachThreadInput(threadId, curId, false);
}


下面是我已经成功转换的关键代码:
////////////////////////////////////////////////////////////////////////////
// 钩子函数HookProc(int,WPARAM,LPARAM)
LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT) lParam;
//获取应用程序自身窗口句柄
my_AppWnd=(HWND)AfxGetMainWnd();
//当nCode=0(即HC_ACTION)时,wParam和lParam才包含相应的键盘信息
if (nCode == HC_ACTION) {
int vKey=LOBYTE(p->vkCode);
switch (wParam)
{ case WM_KEYDOWN:
{
//线程挂接
AttachThreadInput(GetWindowThreadProcessId(::GetForegroundWindow (), NULL),GetCurrentThreadId(), TRUE);
TargetFocusWnd = ::GetFocus (); //取得输入焦点句柄
if (TargetFocusWnd){ //将所有按键转换成汉字
WCHAR* strA= {L"转换成汉字!"};
TCHAR* p = strA;
while (*p){ //把汉字串“转换成汉字”发送到输入焦点窗口
:ostMessage (TargetFocusWnd,WM_CHAR,*p,0);
p++;
}
}
//线程分离
AttachThreadInput(GetWindowThreadProcessId(::GetForegroundWindow (), NULL),GetCurrentThreadId(), FALSE);
} //end of case
} //end of switch
} //end of if
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
////////////////////////////////////////////////////////////////////////////

创见窗口(CompWindow及CandWindow);

装入码表,进行查询,显示及候选上屏。

原来曾经认为做外挂输入法可能也需要#include <immdev.h>,很可能不需要这个
「已注销」 2009-06-17
  • 打赏
  • 举报
回复
哦,明白楼主的意思了。
你是SendMessage吧,
把要发送的CHAR & 0x2
梅文海 2009-06-17
  • 打赏
  • 举报
回复
在 IME 的消息处理里面把文本转换成 ANSI 看看行不行
「已注销」 2009-06-17
  • 打赏
  • 举报
回复
文本也是Unicode,使用SetWindowTextW或Get...W
光宇广贞 2009-06-17
  • 打赏
  • 举报
回复
从哪里接收到的文字?
很可能内容发送方不是UNICODE编码的,而是ANSI,所以出来是乱码。

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧