解决方案

输入法编程之 光标跟随

seo靠我 2023-09-26 06:42:49

光标跟随是输入法系统最常见的特性。要实现这一特性,需要获取IME支持程序(最常见如word,notepad等)中插入符号caret的坐标位置。在Windows的IME环境中,可以通过使用IME核心数据SEO靠我结构INPUTCONTEXT的cfCompForm成员来获取IME宿主程序中文本光标位置。cfCompForm具有如下结构:

typedef tagCANDIDATEFORM { //列表窗口信息

//由SEO靠我IMC_GETCANDIDATEPOS和IMC_SETCANDIDATEPOS消息处理

DWORD dwIndex; //列表窗口序号

DWORD dwStyle; //属性:

//=CFS_CANDIDASEO靠我TEPOS 指定显示位置

//=CFS_EXCLUDE 不可显示

//=CFS_DEFAULT 根据需要显示

POINT ptCurrentPos; //坐标位置

REC rcArea; //不可显示区

} CSEO靠我ANDIDATEFORM;

其中ptCurrentPos就是我们需要的光标位置,不过因为这是客户区的坐标,需要转化为屏幕坐标才能使用。要使得输入法上下文结构INPUTCONTEXT中已经填入了正确的坐标SEO靠我位置,需要实现WM_IME_NOTIFY消息响应事件。在WM_IME_NOTIFY消息的子消息IMN_SETCOMPOSITIONWINDOW(设置编码窗口消息)被触发时,系统会返回正确的坐标位置。WSEO靠我M_IME_NOTIFY消息响应函数类似如下形式:

/*

 * IMENotifyHandle():                                              

 *                                                                   

 * Handle WM_IME_NOTIFY messages.                                    

 */

LONG IMENotifyHandSEO靠我le(HIMC hUICurIMC, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

  LONG lRet = 0L;

LPINPUTCONTSEO靠我EXT lpIMC;

  if (!(lpIMC = ImmLockIMC(hUICurIMC)))

      return 0L;

  switch (wParam)

  {

case IMN_CLOSESTATUSWINDOW:SEO靠我

   TRACE("UIWnd:WM_IME_NOTIFY:IMN_CLOSESTATUSWINDOW/n");

   /// hide the status window

   g_pStatus->Hide();  

breSEO靠我ak;

  case IMN_OPENSTATUSWINDOW:

   TRACE("UIWnd:WM_IME_NOTIFY:IMN_OPENSTATUSWINDOW/n");

/// create the statSEO靠我us window, but dont show

   g_pStatus->Create(hWnd);

   break;

  case IMN_OPENCANDIDATE:

TRACE("UIWnd:WM_IME_NOTSEO靠我IFY:IMN_OPENCANDIDATE/n");

   break;

  case IMN_CHANGECANDIDATE:

TRACE("UIWnd:WM_IME_NOTIFY:IMN_CHANGECANDIDSEO靠我ATE/n");

   break;

  case IMN_CLOSECANDIDATE:

   TRACE("UIWnd:WM_IME_NOTIFY:IMN_CLOSECANDIDATE/n");

   break;

case ISEO靠我MN_SETCONVERSIONMODE:

   TRACE("UIWnd:WM_IME_NOTIFY:IMN_SETCONVERSIONMODE/n");

/// repaint the status winSEO靠我dow

   g_pStatus->Repaint();

   break;

  case IMN_SETSENTENCEMODE:

TRACE("UIWnd:WM_IME_NOTIFY:IMN_SETSENTENCEMODSEO靠我E/n");

   break;

  case IMN_SETOPENSTATUS:

   TRACE("UIWnd:WM_IME_NOTIFY:IMN_SETOPENSTATUS/n"); 

/// repaint the SEO靠我status window

   g_pStatus->Repaint();

   break;

  case IMN_SETCANDIDATEPOS:

TRACE("UIWnd:WM_IME_NOTIFY:IMN_SETCSEO靠我ANDIDATEPOS/n");

   break;

  case IMN_SETCOMPOSITIONFONT:

TRACE("UIWnd:WM_IME_NOTIFY:IMN_SETCOMPOSITIONFONT/SEO靠我n");

   break;

  case IMN_SETCOMPOSITIONWINDOW:

   TRACE("UIWnd:WM_IME_NOTIFY:IMN_SETCOMPOSITIONWINDOW/n");

/// SEO靠我adjust the postion of comp and cand windows

   POINT ptSrc;

   SIZE szOffset;

   HDC hDC; 

ptSrc = lpIMC->cfCompFoSEO靠我rm.ptCurrentPos;

   ClientToScreen(lpIMC->hWnd, &ptSrc);

   hDC = GetDC(lpIMC->hWnd);  

GetTextExtentPoint(hDC,SEO靠我"A",1,&szOffset);

   ReleaseDC(lpIMC->hWnd,hDC);

   g_ptTopLeft.x = ptSrc.x + szOffset.cx;

g_ptTopLeft.y = ptSEO靠我Src.y + szOffset.cy;

   break;

  case IMN_GUIDELINE:

   TRACE("UIWnd:WM_IME_NOTIFY:IMN_GUIDELINE/n");

   break;

caseSEO靠我 IMN_SETSTATUSWINDOWPOS:

   TRACE("UIWnd:WM_IME_NOTIFY:IMN_SETSTATUSWINDOWPOS/n");

   break;

case IMN_PRIVATESEO靠我:

   TRACE("UIWnd:WM_IME_NOTIFY:IMN_PRIVATE/n");

   break;

  default:

   break;

  }

  ImmUnlockIMC(hUICurIMC);

return lRetSEO靠我;

}

其中,需要注意的是要确保获取正确的位置,必须有先发送过WM_IME_STARTCOMPOSITION消息,这个消息一般在刚开始输入新拼音时候发送!关于IME消息处理可以看MSDN相关文档。

即便如此SEO靠我,仍然不能保证在所有程序中,输入法都能正确地体现光标跟随,我遇到的情况是在UtraEdit中,上述代码毫无作用,IMN_SETCOMPOSITIONWINDOW根本就没有被系统触发,这时我只好通过GeSEO靠我tCaretPos来侥幸地获取光标位置。

 
“SEO靠我”的新闻页面文章、图片、音频、视频等稿件均为自媒体人、第三方机构发布或转载。如稿件涉及版权等问题,请与 我们联系删除或处理,客服邮箱:html5sh@163.com,稿件内容仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同 其观点或证实其内容的真实性。

网站备案号:浙ICP备17034767号-2