关于键盘输入和输入法的记录

Posted on 2005-12-19 15:10 Raistlin 阅读(5137) 评论(0)  编辑 收藏 引用 所属分类: C++
关于光标的一些函数
BOOL CreateCaret(HWND hWnd,HBITMAP hBitmap,int nWidth,int nHeight);为窗口创建光标
BOOL DestroyCaret();销毁光标
UINT GetCaretBlinkTime();光标闪烁间隔时间
BOOL GetCaretPos(LPPOINT lpPoint);光标在当前窗口的client位置
BOOL HideCaret(HWND hWnd);隐藏
BOOL SetCaretBlinkTime(UINT uMSeconds);光标闪烁间隔时间
BOOL SetCaretPos(int X,int Y);位置
BOOL ShowCaret(HWND hWnd);显示

CWnd::CreateCaret
CWnd::CreateSolidCaret
CWnd::CreateGrayCaret
CWnd::GetCaretPos
CWnd::SetCaretPos
CWnd::HideCaret
CWnd::ShowCaret

为其它进程模拟输入字符:
摘自http://www.pcbookcn.com/article/1113.htm
  首先要知道在Windows系统中与键盘按键相关的消息有:WM_KEYDOWN、WM_KEYUP、 WM_SYSKEYDOWN、WM_SYSKEYUP、WM_CHAR等。其中,WM_KEYDOWN为键按下,WM_KEYUP为键弹起,WM_SYSKEYDOWN为系统键按下,WM_SYSKEYUP为系统键弹起,WM_CHAR为按键对应的字符。
  要模拟键盘产生键盘消息,我们就发送一条键盘消息给指定窗口。比如要模拟一个字母键“A”,可以这样:PostMessage(hWnd, WM_CHAR, 'A', 0); 模拟按一个回车:PostMessage(hWnd, WM_KEYDOWN, VK_RETURN, 0)。这里的关键问题是要确定窗口句柄(hWnd),使用GetFocus()函数可以得到键盘光标所在窗口句柄,但该函数只能得到当前进程内的窗口句柄。
  如果要得到其他应用程序的键盘光标所在窗口句柄,需要调用 AttachThreadInput()函数。该函数的作用就是将其他窗口线程的输入附加到本窗口线程的输入操作中,这样就可以调用GetFocus()函数得到其他窗口的句柄了。

AttachThreadInput()函数的原形如下:
BOOL AttachThreadInput( 
DWORD idAttach, 
// 需要附加的线程ID 
DWORD idAttachTo, // 附加到的线程ID 
BOOL fAttach // true 附加 false 取消 
); 
函数使用的过程大致如下:
HWND hWnd; 
hWnd 
= GetForegroundWindow(); // 得到当前窗口 
if (hWnd == Form1->Handle) return// 排除程序本身的窗口 
DWORD FormThreadID = GetCurrentThreadId(); // 本程序的线程ID 
// 当前窗口的线程ID 
DWORD CWndThreadID = GetWindowThreadProcessId(hWnd, NULL); 
// 附加输入线程 
AttachThreadInput(CWndThreadID, FormThreadID, true); 
// 得到当前键盘光标所在的窗口 
hWnd = GetFocus(); 
// 取消附加的输入线程 
AttachThreadInput(CWndThreadID, FormThreadID, false); 
hWnd就是当前键盘光标所在的窗口句柄。另外,经过测试发现,在Windows2000系统下发送字符消息(WM_CHAR)时,如果字符是一个汉字,则该字符对应的虚拟键盘码高位不为0,这样得到的字符就不正确。解决办法是做一个“与”运算: ch & 0xFF就可以了。


输入法的切换:
WM_INPUTLANGCHANGE
platform sdk=>User Interface Servic=>windowing=>windows=>window reference =>Messages

关于输入法:
platform sdk=>Windows Base Services=>International Features=>Input Method Editor


自己处理键盘输入要做的事:
如果你要自己处理键盘和输入法的输入而不用Eidt或richedit等控件的话,至少需要做以下处理以下消息WM_IME_STARTCOMPOSITION;WM_IME_ENDCOMPOSITION;WM_IME_COMPOSITION;
LRESULT CCaretStudyView::OnImeStartComposition(WPARAM wParam, LPARAM lParam)
{
    HIMC hIMC 
= ::ImmGetContext(m_hWnd);
    COMPOSITIONFORM CompForm;
    CompForm.dwStyle 
= CFS_POINT;
    CompForm.ptCurrentPos.x 
= 10;//用实际的值代替
    CompForm.ptCurrentPos.y = 10;//用实际的值代替
    ::ImmSetCompositionWindow(hIMC, &CompForm);
    
//DropCaret();可在此处隐藏光标,在OnImeEndComposition消息处理中再显示光标
    ::ImmReleaseContext(m_hWnd, hIMC);
    
return ::DefWindowProc(m_hWnd, WM_IME_STARTCOMPOSITION, wParam, lParam);
}


LRESULT CCaretStudyView::OnImeEndComposition() 
{
    
//ShowCaretAtCurrentPosition();
    return Default();
}


LRESULT CCaretStudyView::OnImeComposition(WPARAM wParam, LPARAM lParam)
{
    
if (lParam & GCS_RESULTSTR) {
        
//get result text
        HIMC hIMC = ::ImmGetContext(m_hWnd);
        
if (hIMC) {
            
const int maxLenInputIME = 200;
            wchar_t wcs[maxLenInputIME];
            LONG bytes 
= ::ImmGetCompositionStringW(hIMC,
                    GCS_RESULTSTR, wcs, (maxLenInputIME
-1)*2);
            
//
            
// Set new position after converted
            CPoint pos = GetCurrentPos();
            COMPOSITIONFORM CompForm;
            CompForm.dwStyle 
= CFS_POINT;
            CompForm.ptCurrentPos.x 
= pos.x;
            CompForm.ptCurrentPos.y 
= pos.y;
            ::ImmSetCompositionWindow(hIMC, 
&CompForm);
            ::ImmReleaseContext(m_hWnd, hIMC);
        }

        
return 0;
    }

    
return Default();
}
以上三个消息是不做处理也可以,只不过不会支持如微软拼音输入法的跟随功能。

并WM_IME_CHAR和WM_CHAR添加字符。在WM_KEYDOWN中处理特殊字符,如VK_BACK VK_DELTE
只有注册用户登录后才能发表评论。

posts - 49, comments - 14, trackbacks - 0, articles - 0

Copyright © Raistlin