⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imm.c

📁 这是一个编写输入法程序的代码。演示了怎样利用输入法接口。
💻 C
字号:
#include "imesample.h"

//定义输入法要处理的键
BYTE g_bPrecess[] = {
						0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,        // 00-0F VK_BACK
                        0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,        // 10-1F VK_CAPTIAL
                        1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        // 20-2F VK_SPACE
                        1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,        // 30-3F VK_0~VK_9
                        0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,        // 40-4F
                        1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,        // 50-5F
                        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        // 60-6F
                        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        // 70-7F
                        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        // 80-8F
                        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        // 90-9F
                        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        // A0-AF
                        0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,        // B0-BF
                        1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        // C0-CF
                        0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,        // D0-DF
                        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        // E0-EF
                        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0			// F0-FF
};

//*****************************************************************
//	向HIMC发送消息
//	消息数据保存在lpIMC->dwNumMsgBuf中
//	每次发消息前需要分配消息空间
//*****************************************************************
BOOL MyGenerateMessage(HIMC hIMC, UINT msg, WPARAM wParam, LPARAM lParam)
{
	BOOL bRet=FALSE;
    LPINPUTCONTEXT lpIMC= ImmLockIMC(hIMC);
	if(lpIMC == NULL)
		return FALSE;    
    
    if (IsWindow(lpIMC->hWnd))
    {
        LPTRANSMSG lpTransMsg;
        if (!(lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf,(lpIMC->dwNumMsgBuf+1) * sizeof(TRANSMSG))))
            goto error;
		
        if (!(lpTransMsg = (LPTRANSMSG)ImmLockIMCC(lpIMC->hMsgBuf)))
            goto error;
		
        lpTransMsg += (lpIMC->dwNumMsgBuf);
        lpTransMsg->message=msg;
		lpTransMsg->wParam=wParam;
		lpTransMsg->lParam=lParam;
        lpIMC->dwNumMsgBuf++;

        ImmUnlockIMCC(lpIMC->hMsgBuf);
        ImmGenerateMessage(hIMC);//将消息发送到IME,IME再决定是自己处理还是继续发给应用程序
		bRet=TRUE;
    }
error:
	ImmUnlockIMC(hIMC); 
	return bRet;
}

//************************************************************
//	向消息缓冲区填充消息
//	LPDWORD lpdwTransKey:消息缓冲区,由系统提供,第一个双字为可用消息空间数
//	UINT *uNumTranMsgs:当前消息数
//	UINT msg,WPARAM wParam,LPARAM lParam:消息数据
//	remark:该函数只在ImeToAsciiEx中调用
//************************************************************
BOOL MyGenerateMessageToTransKey(LPDWORD lpdwTransKey,
								 UINT *uNumTranMsgs,
								 UINT msg, 
								 WPARAM wParam, 
								 LPARAM lParam) 
{
    LPTRANSMSG lpTransMsg;
	if (((*uNumTranMsgs) + 1) >= (UINT)*lpdwTransKey)
        return FALSE;
	lpTransMsg = (LPTRANSMSG)(lpdwTransKey+1+(*uNumTranMsgs)*3);
	lpTransMsg->message=msg;
	lpTransMsg->wParam=wParam;
	lpTransMsg->lParam=lParam;
	(*uNumTranMsgs)++;
    return TRUE;
}


BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo,LPTSTR lpszUIClass,LPCTSTR lpszOption)
{
    lpIMEInfo->dwPrivateDataSize = 0;//系统根据它为INPUTCONTEXT.hPrivate分配空间

    lpIMEInfo->fdwProperty = IME_PROP_KBD_CHAR_FIRST |
#ifdef _UNICODE
                             IME_PROP_UNICODE |
#endif
                             IME_PROP_IGNORE_UPKEYS |
							 IME_PROP_END_UNLOAD ;

    lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE |
								IME_CMODE_NATIVE;

    lpIMEInfo->fdwSentenceCaps = IME_SMODE_NONE;
    lpIMEInfo->fdwUICaps = UI_CAP_2700;

	lpIMEInfo->fdwSCSCaps = 0;

    lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION;

    _tcscpy(lpszUIClass,CLSNAME_UI);

    return TRUE;
}

BOOL WINAPI AboutDialogProc(HWND hWnd ,	UINT message ,WPARAM wParam ,LPARAM lParam );

BOOL WINAPI ImeConfigure(HKL hKL,HWND hWnd, DWORD dwMode, LPVOID lpData)
{
	//DebugLog(1,(DebugLogFile,"ImeConfigure\n"));
    switch (dwMode) {
    case IME_CONFIG_GENERAL:
        DialogBox(g_hInst, MAKEINTRESOURCE(IDD_ABOUT), (HWND)hWnd, (DLGPROC)AboutDialogProc);
        break;
    default:
        return (FALSE);
        break;
    }
    return (TRUE);
}

/**********************************************************************/
/* ClearCompStr()                                                     */
/* Return Value:                                                      */
/*      TRUE - successful, FALSE - failure                            */
/**********************************************************************/
BOOL PASCAL ClearCompStr(
    LPINPUTCONTEXT lpIMC)
{
    HIMCC               hMem;
    LPCOMPOSITIONSTRING lpCompStr;
    DWORD               dwSize;

    if(!lpIMC) {
        return (FALSE);
    }

    dwSize = sizeof(COMPOSITIONSTRING) + (MAX_PRIVATEDATA);

    if (!lpIMC->hCompStr) {
        // it maybe free by other IME, init it
        lpIMC->hCompStr = ImmCreateIMCC(dwSize);
    } else if (hMem = ImmReSizeIMCC(lpIMC->hCompStr, dwSize)) {
        lpIMC->hCompStr = hMem;
    } else {
        ImmDestroyIMCC(lpIMC->hCompStr);
        lpIMC->hCompStr = ImmCreateIMCC(dwSize);
        return (FALSE);
    }

    lpCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
    if (!lpCompStr) {
        ImmDestroyIMCC(lpIMC->hCompStr);
        lpIMC->hCompStr = ImmCreateIMCC(dwSize);
        return (FALSE);
    }
	memset(lpCompStr,0,dwSize);
    lpCompStr->dwSize = dwSize;
	lpCompStr->dwCompStrOffset = sizeof(COMPOSITIONSTRING);
	lpCompStr->dwCompStrLen = 0;
	lpCompStr->dwResultStrOffset = sizeof(COMPOSITIONSTRING);
	lpCompStr->dwResultStrLen = 0;
	
    ImmUnlockIMCC(lpIMC->hCompStr);
    return (TRUE);
}


/**********************************************************************/
/* ImeSelect()                                                        */
/* Return Value:                                                      */
/*      TRUE - successful, FALSE - failure                            */
/**********************************************************************/
BOOL WINAPI ImeSelect(
    HIMC hIMC,
    BOOL fSelect)
{
    LPINPUTCONTEXT lpIMC;
	BOOL bRet=FALSE;
    if (!hIMC) {
        return (FALSE);
    }

    lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
    if (!lpIMC) {
        return (FALSE);
    }
	lpIMC->fOpen=fSelect;
	if(fSelect) bRet=ClearCompStr(lpIMC);
    ImmUnlockIMC(hIMC);
    return bRet;
}

/*
使一个输入上下文激活或者失活,并通知输入法最新的输入上下文,可以在此做一些初始化工作
HIMC hIMC :输入上下文
BOOL fFlag : TRUE if activated, FALSE if deactivated. 
Returns TRUE if successful, FALSE otherwise. 
*/
BOOL WINAPI ImeSetActiveContext(HIMC hIMC,BOOL fFlag)
{
	//通过IME消息来实现窗口状态变化
	MyGenerateMessage(hIMC,WM_IME_NOTIFY,fFlag?IMN_OPENSTATUSWINDOW:IMN_CLOSESTATUSWINDOW,0);
    return TRUE;
}

/*
系统调用这个接口来判断IME是否处理当前键盘输入
HIMC hIMC:输入上下文
UINT uKey:键值
LPARAM lKeyData: unknown
CONST LPBYTE lpbKeyState:键盘状态,包含256键的状态
return : TRUE-IME处理,FALSE-系统处理
系统则调用ImeToAsciiEx,否则直接将键盘消息发到应用程序
*/
BOOL WINAPI ImeProcessKey(HIMC hIMC,UINT uKey,LPARAM lKeyData,CONST LPBYTE lpbKeyState)
{
	LPINPUTCONTEXT lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
	BOOL bRet=g_bPrecess[uKey];
	if(lpIMC)
	{
		LPCOMPOSITIONSTRING lpCompStr=(LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
		if(lpCompStr)
		{
			if(uKey==VK_BACK && lpCompStr->dwCompStrLen==0) 
			{//没有编码输入,告诉IME关闭输入窗口
				MyGenerateMessage(hIMC,WM_IME_ENDCOMPOSITION,0,0);
				bRet=FALSE;
			}
			ImmUnlockIMCC(lpIMC->hCompStr);
		}else
		{
			bRet=FALSE;
		}
		ImmUnlockIMC(hIMC);
	}else
	{
		bRet=FALSE;
	}
	return bRet;
}

/*
应用程序调用这个接口来进行输入上下文的转换,输入法程序在这个接口中转换用户的输入
UINT uVKey:键值,如果在ImeInquire接口中为fdwProperty设置了属性IME_PROP_KBD_CHAR_FIRST,则高字节是输入键值
UINT uScanCode:按键的扫描码,有时两个键有同样的键值,这时需要使用uScanCode来区分
CONST LPBYTE lpbKeyState:键盘状态,包含256键的状态
LPDWORD lpdwTransKey:消息缓冲区,用来保存IME要发给应用程序的消息,第一个双字是缓冲区可以容纳的最大消息条数
UINT fuState:Active menu flag(come from msdn)
HIMC hIMC:输入上下文
return : 返回保存在消息缓冲区lpdwTransKey中的消息个数
*/
UINT WINAPI ImeToAsciiEx (UINT uVKey,UINT uScanCode,CONST LPBYTE lpbKeyState,LPDWORD lpdwTransKey,UINT fuState,HIMC hIMC)
{
	LPINPUTCONTEXT lpIMC = (LPINPUTCONTEXT)ImmLockIMC(hIMC);
	UINT uMsgCount=0;
	if(lpIMC)
	{
		BYTE byInput=HIBYTE(uVKey);
		LPCOMPOSITIONSTRING lpCompStr=(LPCOMPOSITIONSTRING)ImmLockIMCC(lpIMC->hCompStr);
		if(lpCompStr)
		{
			LPBYTE pComp=GETLPCOMPSTR(lpCompStr);
			if(lpCompStr->dwCompStrLen==0)
			{//开始编码输入
				//生成开始编码消息以获取光标跟随时输入窗口的坐标
				MyGenerateMessageToTransKey(lpdwTransKey,&uMsgCount,WM_IME_STARTCOMPOSITION,0,0);
			}
			if(byInput==VK_BACK)
			{
				if(lpCompStr->dwCompStrLen>0) lpCompStr->dwCompStrLen--;
			}else
			{
				pComp[lpCompStr->dwCompStrLen++]=byInput;
			}
			
			if(lpCompStr->dwCompStrLen==9)
			{//结束编码输入,通过编码转换获得用户输入,将输入信息发到应用程序
				static char szSample[]="启程软件 http://setoutsoft.id666.com";
				LPTSTR pResult=GETLPRESULTSTR(lpCompStr);
				strcpy(pResult,szSample);
				lpCompStr->dwResultStrLen=strlen(szSample);
				lpCompStr->dwCompStrLen=0;
				//通知应用程序接收数据
				MyGenerateMessageToTransKey(lpdwTransKey,&uMsgCount,WM_IME_COMPOSITION,0,GCS_RESULTSTR|GCS_COMPSTR);
				//告诉IME关闭输入窗口
				MyGenerateMessageToTransKey(lpdwTransKey,&uMsgCount,WM_IME_ENDCOMPOSITION,0,0);
			}else
			{//正在输入编码
				MyGenerateMessageToTransKey(lpdwTransKey,&uMsgCount,WM_IME_COMPOSITION,0,GCS_COMPSTR);
			}
			ImmUnlockIMCC(lpIMC->hCompStr);
		}
		ImmUnlockIMC(hIMC);
	}
    return (uMsgCount);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -