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

📄 winime.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
字号:
////////////////////////////////////////////////////////////////////////////////////
//platformIME.h 平台输入法,李亦编写.2005.11.18
///	由于微软拼音实现了很多自己的东西,PlatformIME和它的兼容性有些问题
///	1、在函数 PlatformIME::ConvertCandList 中所说的选字表的问题
///	2、函数 PlatformIME::GetIMEInput 返回的 szCompReadStr 显然经过了加工而不是最初的键盘输入
///   它的每个可组合的输入占以空格补足的8byte,且新的不可组合的输入存为0xa1
///   我们可以在输入法名字中有子串"微软拼音"时,只显示末尾的一组8byte,如果有0xa1就什么都不显示,也可以直接用TextOut显示所有的


//#include "platform/platform.h"
//#include <windows.h>
#include "platformWin32/platformWin32.h"
//#include "rpg/RPGTextParse.h"
#include "platform/platformIME.h"
#include "gui/utility/guiIMECtrl.h"
#include "gui/core/guiCanvas.h"
#include "gui/controls/guiMLTextCtrl.h"
#include <imm.h>


#pragma comment ( lib, "imm32.lib" )
/////////////////////////////////////////////////////////////////////////////////////////

#define COMPOS_SEP		'\n'

CANDIDATELIST	*g_lpCandList = NULL;		///> 存储标准的选字表

class CandListMan
{
public:
	//RPG::RPGTextParse	m_textParse;

public:
	CandListMan(){}
	~CandListMan();
	void ConvertCandList( CANDIDATELIST *pCandList/*, char *pszCandList*/ );
};


CandListMan	g_CandListMan;


CandListMan::~CandListMan()
{
	if( g_lpCandList )
	{
		GlobalFree( (HANDLE)g_lpCandList );
		g_lpCandList = NULL;
	}
}


/// 转换CandidateList到一个串,COMPOS_SEP分隔每一项
void CandListMan::ConvertCandList( CANDIDATELIST *pCandList/*, char *pszCandList*/ )
{
	U32	i;
	S32	nNum;
	S8		cIndex;

	if(g_pIME == NULL)
		return;

	g_pIME->m_textParse.BeginParse();

	if( pCandList->dwCount < pCandList->dwSelection )
	{
		//pszCandList[ 0 ] = 0;
		return;
	}


	//g_pIME->m_textParse << Con::getVariable("$RPG::IMEStyle");

	//待选字序号超出总数,微软拼音第二次到选字表最后一页后再按PageDown会出现这种情况,
	//并且会退出选字状态,开始一个新的输入
	//但微软拼音自己的ime窗口可以解决这个问题,估计微软拼音实现了更多的接口,所以使用了这种不太标准的数据
	//我现在无法解决这个问题,而且实际使用中也很少遇到这种事,而且其它标准输入法不会引起这种bug
	//非标准输入法估计实现的接口比较少,所以应该也不会引起这种bug

	nNum = getMin((U32)(pCandList->dwCount - pCandList->dwSelection), (U32)pCandList->dwPageSize);

	for( i = 0;  i <nNum ; i++ )
	{
		cIndex = ( i % 10 != 9 )? i % 10 + '1' : '0';
		g_pIME->m_textParse << cIndex;//每项对应的数字键
		g_pIME->m_textParse << (S8)'.'; 
		g_pIME->m_textParse << (char*)pCandList + pCandList->dwOffset[ pCandList->dwSelection + i ]; 

		if(i < nNum -1)
			g_pIME->m_textParse << "\n"; 
	}



	//for( i = 0; ( i < pCandList->dwCount - pCandList->dwSelection )&&( i < pCandList->dwPageSize ); i++ )
	//{
	//	*pszCandList++ = ( i % 10 != 9 )? i % 10 + '1' : '0';//每项对应的数字键
	//	// *pszCandList++ = '.';//用'.'分隔
	//	strcpy( pszCandList, (char*)pCandList
	//		+ pCandList->dwOffset[ pCandList->dwSelection + i ] );//每项实际的内容
	//	pszCandList += strlen( pszCandList );
	//	*pszCandList++ = COMPOS_SEP;//项之间以'\t'分隔
	//}
	//*( pszCandList - 1 )= 0;//串尾,并覆盖最后一个'\t'
}





void PlatformIME::NextIME()
{
	if( m_bIME)
		ActivateKeyboardLayout(( HKL )HKL_NEXT, 0 );
}

void PlatformIME::SharpIME( )
{
	if(m_bIME)
		ImmSimulateHotKey( (HWND)m_hWnd, IME_CHOTKEY_SHAPE_TOGGLE );
}

void PlatformIME::SymbolIME( )
{
	if(m_bIME)
		ImmSimulateHotKey( (HWND)m_hWnd, IME_CHOTKEY_SYMBOL_TOGGLE );
}


void PlatformIME::DisableIME()
{
	m_bIME = false;//先关闭IME功能
	HideIME();
}


void PlatformIME::HideIME()
{
	while( ImmIsIME( GetKeyboardLayout( 0 )))
		ActivateKeyboardLayout(( HKL )HKL_NEXT, 0 );//如果ime打开通过循环切换到下一个关闭

	m_szIMEName[ 0 ]		= 0;
	m_szCompStr[ 0 ]		= 0;
	m_szCompReadStr[ 0 ]	= 0;
	m_szCandList[ 0 ]		= 0;
	m_nIMECursor			= 0;
	m_textParse.ClearParse();

	//if(m_pIMECtrl)
	//	m_pIMECtrl->OnInputLangChange(false);
}



bool PlatformIME::OnWM_INPUTLANGCHANGE( UWND hWnd )
{

	if(!m_bIME)
		return false;
	m_hWnd = hWnd;
	//ime改变
	HKL hKL = GetKeyboardLayout( 0 );
	if( ImmIsIME( hKL ))
	{
		HIMC hIMC = ImmGetContext( (HWND)hWnd );
		ImmEscape( hKL, hIMC, IME_ESC_IME_NAME, m_szIMEName );//取得新输入法名字
		DWORD dwConversion, dwSentence;
		ImmGetConversionStatus( hIMC, &dwConversion, &dwSentence );
		m_bIMESharp = ( dwConversion & IME_CMODE_FULLSHAPE )? true : false;//取得全角标志
		m_bIMESymbol = ( dwConversion & IME_CMODE_SYMBOL )? true : false;//取得中文标点标志
		ImmReleaseContext( (HWND)hWnd, hIMC );
	}
	else//英文输入
		m_szIMEName[ 0 ] = 0;

	//{
	//	m_pIMECtrl = new GuiIMECtrl();
	//	m_pIMECtrl->InitDefaultIME();
	//}

	//if(m_pIMECtrl)
	if(m_pIMECtrl == NULL)
	{
		Con::printf("需要建立GuiIMECtrl面板");
		return true;
	}
	m_pIMECtrl->OnInputLangChange(m_szIMEName[ 0 ] != 0);

	return false;//总是返回false,因为需要窗口函数调用DefWindowProc继续处理
}


bool PlatformIME::OnWM_IME_NOTIFY( UWND hWnd, U32 wParam )
{
	if(!m_bIME)
		return true;
	HIMC hIMC;
	DWORD dwSize;
	DWORD dwConversion, dwSentence;
	m_hWnd = hWnd;

	switch( wParam )
	{
		case IMN_SETCONVERSIONMODE://全角/半角,中/英文标点改变
			hIMC = ImmGetContext( (HWND)hWnd );
			ImmGetConversionStatus( hIMC, &dwConversion, &dwSentence );
			m_bIMESharp = ( dwConversion & IME_CMODE_FULLSHAPE )? true : false;
			m_bIMESymbol = ( dwConversion & IME_CMODE_SYMBOL )? true : false;
			ImmReleaseContext( (HWND)hWnd, hIMC );
			break;

		case IMN_OPENCANDIDATE://进入选字状态
		case IMN_CHANGECANDIDATE://选字表翻页
			hIMC = ImmGetContext( (HWND)hWnd );
			if( g_lpCandList )
			{
				GlobalFree( (HANDLE)g_lpCandList );
				g_lpCandList = NULL;
			}//释放以前的选字表

			if( dwSize = ImmGetCandidateList( hIMC, 0, NULL, 0 ))
			{
				g_lpCandList = (LPCANDIDATELIST)GlobalAlloc( GPTR, dwSize );
				if( g_lpCandList )
					ImmGetCandidateList( hIMC, 0, g_lpCandList, dwSize );
			}//得到新的选字表

			ImmReleaseContext( (HWND)hWnd, hIMC );
			if( g_lpCandList )
				g_CandListMan.ConvertCandList( g_lpCandList/*, m_szCandList*/ );//选字表整理成串
			break;

		case IMN_CLOSECANDIDATE://关闭选字表
			if( g_lpCandList )
			{
				GlobalFree( (HANDLE)g_lpCandList );
				g_lpCandList = NULL;
			}//释放
			m_szCandList[ 0 ] = 0;
			m_textParse.ClearParse();
			//HideIME();
			break;
	}

	if(m_pIMECtrl == NULL)
	{
		Con::printf("需要建立GuiIMECtrl面板");
		return false;
	}
	m_pIMECtrl->OnIMENotify(wParam);

	return true;//总是返回true,防止ime窗口打开
}


bool PlatformIME::OnWM_IME_COMPOSITION( UWND hWnd, U32 lParam )
{//输入改变
	if(!m_bIME)
		return true;
	HIMC hIMC;
	DWORD dwSize;
	hIMC = ImmGetContext( (HWND)hWnd );

	m_hWnd = hWnd;

	if( lParam & GCS_COMPSTR )
	{
		dwSize = ImmGetCompositionString( hIMC, GCS_COMPSTR, (void*)m_szCompStr, sizeof( m_szCompStr ));
		m_szCompStr[ dwSize ] = 0;
	}//取得szCompStr

	if( lParam & GCS_COMPREADSTR )
	{
		dwSize = ImmGetCompositionString( hIMC, GCS_COMPREADSTR, (void*)m_szCompReadStr, sizeof( m_szCompReadStr ));
		m_szCompReadStr[ dwSize ] = 0;
	}//取得szCompReadStr

	if( lParam & GCS_CURSORPOS )
	{
		m_nIMECursor = 0xffff & ImmGetCompositionString( hIMC, GCS_CURSORPOS, NULL, 0 );
	}//取得nIMECursor
	if( lParam & GCS_RESULTSTR )
	{
		unsigned char str[ MAX_PATH ];
		dwSize = ImmGetCompositionString( hIMC, GCS_RESULTSTR, (void*)str, sizeof( str ));//取得汉字输入串
		str[ dwSize ] = 0;
		unsigned char *p = str;
		while( *p )
			PostMessage( (HWND)hWnd, WM_CHAR, (WPARAM)(*p++), 1 );//转成WM_CHAR消息
	}
	ImmReleaseContext( (HWND)hWnd, hIMC );


	if(m_pIMECtrl == NULL)
	{
		Con::printf("需要建立GuiIMECtrl面板");
		return false;
	}
		m_pIMECtrl->OnIMEComposition(lParam);

	return true;//总是返回true,防止ime窗口打开
}



void PlatformIME::GetIMEInput( char **pszCompStr, char **pszCompReadStr, int *pnIMECursor, char **pszCandList )
{
	if(!m_bIME)
		return;
	if( pszCompStr )
		*pszCompStr = m_szCompStr;
	if( pszCompReadStr )
		*pszCompReadStr = m_szCompReadStr;
	if( pnIMECursor )
		*pnIMECursor = m_nIMECursor;
	if( pszCandList )
	{	
		*pszCandList = (char*)g_pIME->m_textParse.GetParseText();
		//*pszCandList = m_szCandList;
	}
}





void GuiIMECtrl::OnInputLangChange(bool bOpen)
{
	if(bOpen)
	{
		setText(g_pIME->GetIMEName());
		Canvas->PushIMEControl(this);//m_pContainer);
		//Canvas->pushDialogControl(m_pContainer,0);
	}
	else
	{
		Canvas->PopIMEControl();
		//Canvas->popDialogControl(m_pContainer);
	}
	setVisible(bOpen);
}


void GuiIMECtrl::OnIMENotify(U32 uCode)
{
	//以下为默认处理
	switch( uCode )
	{
		case IMN_SETCONVERSIONMODE://全角/半角,中/英文标点改变
			if(m_bDefault)
			{
				ToggleCtrl(E_SHARP,g_pIME->m_bIMESharp);
				ToggleCtrl(E_SYMBOL,g_pIME->m_bIMESymbol);
			}
			break;
		case IMN_OPENCANDIDATE://进入选字状态
		case IMN_CHANGECANDIDATE://选字表翻页
		case IMN_CLOSECANDIDATE://关闭选字表
				SetIMEText(E_LIST, g_pIME->m_textParse.GetParseText());
				//static_cast<GuiMLTextCtrl*>(m_arCtrls[E_LIST])->setText(g_pIME->m_szCandList,-1);
				//static_cast<GuiTextCtrl*>(m_arCtrls[E_LIST])->setText(g_pIME->m_szCandList);
			break;
	}

}


void GuiIMECtrl::OnIMEComposition(U32 uFlag)
{
	if( uFlag & GCS_COMPSTR )
	{
		SetIMEText(E_INPUT, g_pIME->m_szCompStr);
		//if(m_arCtrls[E_INPUT])
		//	static_cast<GuiMLTextCtrl*>(m_arCtrls[E_INPUT])->setText(g_pIME->m_szCompStr,-1);
			//static_cast<GuiTextCtrl*>(m_arCtrls[E_INPUT])->setText(g_pIME->m_szCompStr);
			//m_arCtrls[E_INPUT]->setField("text",g_pIME->m_szCompStr);
	}//取得szCompStr

	if( uFlag & GCS_COMPREADSTR )
	{
		SetIMEText(E_INPUT2, g_pIME->m_szCompReadStr);
		//if(m_arCtrls[E_INPUT2])
		//	static_cast<GuiMLTextCtrl*>(m_arCtrls[E_INPUT2])->setText(g_pIME->m_szCompReadStr,-1);
			//static_cast<GuiTextCtrl*>(m_arCtrls[E_INPUT2])->setText(g_pIME->m_szCompReadStr);
	}//取得szCompReadStr

	if( uFlag & GCS_CURSORPOS )
	{
		FitPosByCursor(g_pIME->GetCursorPos());
	}//取得nIMECursor

	if( uFlag & GCS_RESULTSTR )
	{
	}

}




⌨️ 快捷键说明

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