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

📄 imeui.cpp

📁 声音和图片的加载功能,不过运行起来有点卡
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//--------------------------------------------------------------------------------------
// File: ImeUi.cpp
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include "dxut.h"
#include "ImeUi.h"
#include <math.h>
#include <msctf.h>
#include <malloc.h>
#include <strsafe.h>

// Ignore typecast warnings
#pragma warning( disable : 4312 ) 
#pragma warning( disable : 4244 ) 
#pragma warning( disable : 4311 ) 


#define MAX_CANDIDATE_LENGTH 256
#define COUNTOF(a) ( sizeof( a ) / sizeof( ( a )[0] ) )
#define POSITION_UNINITIALIZED	((DWORD)-1)

#define LANG_CHT	MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
#define LANG_CHS	MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)

#define MAKEIMEVERSION(major,minor) ( (DWORD)( ( (BYTE)( major ) << 24 ) | ( (BYTE)( minor ) << 16 ) ) )
#define IMEID_VER(dwId)		( ( dwId ) & 0xffff0000 )
#define IMEID_LANG(dwId)	( ( dwId ) & 0x0000ffff )

#define _CHT_HKL_DAYI				( (HKL)0xE0060404 )	// DaYi
#define _CHT_HKL_NEW_PHONETIC		( (HKL)0xE0080404 )	// New Phonetic
#define _CHT_HKL_NEW_CHANG_JIE		( (HKL)0xE0090404 )	// New Chang Jie
#define _CHT_HKL_NEW_QUICK			( (HKL)0xE00A0404 )	// New Quick
#define _CHT_HKL_HK_CANTONESE		( (HKL)0xE00B0404 )	// Hong Kong Cantonese
#define _CHT_IMEFILENAME	"TINTLGNT.IME"	// New Phonetic
#define _CHT_IMEFILENAME2	"CINTLGNT.IME"	// New Chang Jie
#define _CHT_IMEFILENAME3	"MSTCIPHA.IME"	// Phonetic 5.1
#define IMEID_CHT_VER42 ( LANG_CHT | MAKEIMEVERSION( 4, 2 ) )	// New(Phonetic/ChanJie)IME98  : 4.2.x.x // Win98
#define IMEID_CHT_VER43 ( LANG_CHT | MAKEIMEVERSION( 4, 3 ) )	// New(Phonetic/ChanJie)IME98a : 4.3.x.x // Win2k
#define IMEID_CHT_VER44 ( LANG_CHT | MAKEIMEVERSION( 4, 4 ) )	// New ChanJie IME98b          : 4.4.x.x // WinXP
#define IMEID_CHT_VER50 ( LANG_CHT | MAKEIMEVERSION( 5, 0 ) )	// New(Phonetic/ChanJie)IME5.0 : 5.0.x.x // WinME
#define IMEID_CHT_VER51 ( LANG_CHT | MAKEIMEVERSION( 5, 1 ) )	// New(Phonetic/ChanJie)IME5.1 : 5.1.x.x // IME2002(w/OfficeXP)
#define IMEID_CHT_VER52 ( LANG_CHT | MAKEIMEVERSION( 5, 2 ) )	// New(Phonetic/ChanJie)IME5.2 : 5.2.x.x // IME2002a(w/WinXP)
#define IMEID_CHT_VER60 ( LANG_CHT | MAKEIMEVERSION( 6, 0 ) )	// New(Phonetic/ChanJie)IME6.0 : 6.0.x.x // New IME 6.0(web download)
#define IMEID_CHT_VER_VISTA ( LANG_CHT | MAKEIMEVERSION( 7, 0 ) )	// All TSF TIP under Cicero UI-less mode: a hack to make GetImeId() return non-zero value

#define _CHS_HKL		( (HKL)0xE00E0804 )	// MSPY
#define _CHS_IMEFILENAME	"PINTLGNT.IME"	// MSPY1.5/2/3
#define _CHS_IMEFILENAME2	"MSSCIPYA.IME"	// MSPY3 for OfficeXP
#define IMEID_CHS_VER41	( LANG_CHS | MAKEIMEVERSION( 4, 1 ) )	// MSPY1.5	// SCIME97 or MSPY1.5 (w/Win98, Office97)
#define IMEID_CHS_VER42	( LANG_CHS | MAKEIMEVERSION( 4, 2 ) )	// MSPY2	// Win2k/WinME
#define IMEID_CHS_VER53	( LANG_CHS | MAKEIMEVERSION( 5, 3 ) )	// MSPY3	// WinXP

static CHAR	signature[] = "%%%IMEUILIB:070111%%%";

static IMEUI_APPEARANCE gSkinIME = {
	0,			// symbolColor;
	0x404040,   // symbolColorOff;
	0xff000000,	// symbolColorText;
	24,			// symbolHeight;
	0xa0,		// symbolTranslucence;
	0,			// symbolPlacement;
	NULL,		// symbolFont;
	0xffffffff,	// candColorBase;
	0xff000000,	// candColorBorder;
	0,			// candColorText;
	0x00ffff00,	// compColorInput;
	0x000000ff,	// compColorTargetConv;
	0x0000ff00,	// compColorConverted;
	0x00ff0000,	// compColorTargetNotConv;
	0x00ff0000,	// compColorInputErr;
	0x80,		// compTranslucence;
	0,			// compColorText;
	2,			// caretWidth;
	1,			// caretYMargin;
};

struct _SkinCompStr
{
	DWORD	colorInput;
	DWORD	colorTargetConv;
	DWORD	colorConverted;
	DWORD	colorTargetNotConv;
	DWORD	colorInputErr;
};

_SkinCompStr gSkinCompStr;

// Definition from Win98DDK version of IMM.H
typedef struct tagINPUTCONTEXT2 {
    HWND                hWnd;                           
    BOOL                fOpen;                          
    POINT               ptStatusWndPos;                 
    POINT               ptSoftKbdPos;                   
    DWORD               fdwConversion;                  
    DWORD               fdwSentence;                    
    union   {                                           
        LOGFONTA        A;                              
        LOGFONTW        W;                              
    } lfFont;                                           
    COMPOSITIONFORM     cfCompForm;                     
    CANDIDATEFORM       cfCandForm[4];                  
    HIMCC               hCompStr;                       
    HIMCC               hCandInfo;                      
    HIMCC               hGuideLine;                     
    HIMCC               hPrivate;                       
    DWORD               dwNumMsgBuf;                    
    HIMCC               hMsgBuf;                        
    DWORD               fdwInit;                        
    DWORD               dwReserve[3];                   
} INPUTCONTEXT2, *PINPUTCONTEXT2, NEAR *NPINPUTCONTEXT2, FAR *LPINPUTCONTEXT2;  


// Class to disable Cicero in case ImmDisableTextFrameService() doesn't disable it completely
class CDisableCicero
{
public:
	CDisableCicero() : m_ptim( NULL ), m_bComInit( false )
	{
	}
	~CDisableCicero()
	{
		Uninitialize();
	}
	void Initialize()
	{
		if ( m_bComInit )
		{
			return;
		}
		HRESULT hr;
		hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
	    if ( SUCCEEDED( hr ) )
		{
			m_bComInit = true;
			hr = CoCreateInstance( CLSID_TF_ThreadMgr,
				NULL,
				CLSCTX_INPROC_SERVER,
				__uuidof(ITfThreadMgr),
				(void**)&m_ptim );
		}
	}
	void Uninitialize()
	{
		if ( m_ptim )
		{
			m_ptim->Release();
			m_ptim = NULL;
		}
		if ( m_bComInit )
			CoUninitialize();
		m_bComInit = false;
	}

	void DisableCiceroOnThisWnd( HWND hwnd )
	{
		if ( m_ptim == NULL )
			return;
		ITfDocumentMgr* pdimPrev; // the dim that is associated previously.
		// Associate NULL dim to the window.
		// When this window gets the focus, Cicero does not work and IMM32 IME
		// will be activated.
		if ( SUCCEEDED( m_ptim->AssociateFocus( hwnd, NULL, &pdimPrev ) ) )
		{
			if ( pdimPrev )
				pdimPrev->Release();
		}
	}
private:
	ITfThreadMgr* m_ptim;
	bool m_bComInit;
};
static CDisableCicero g_disableCicero;

#define _IsLeadByte(x) ( LeadByteTable[(BYTE)( x )] )
static void _PumpMessage();
static BYTE LeadByteTable[256];
#define _ImmGetContext	ImmGetContext
#define _ImmReleaseContext	ImmReleaseContext
#define _ImmAssociateContext	ImmAssociateContext
static LONG (WINAPI* _ImmGetCompositionString)( HIMC himc, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen );
#define _ImmGetOpenStatus	ImmGetOpenStatus
#define _ImmSetOpenStatus	ImmSetOpenStatus
#define _ImmGetConversionStatus	ImmGetConversionStatus
static DWORD (WINAPI* _ImmGetCandidateList)( HIMC himc, DWORD deIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen );
static LPINPUTCONTEXT2 (WINAPI* _ImmLockIMC)(HIMC hIMC);
static BOOL (WINAPI* _ImmUnlockIMC)(HIMC hIMC);
static LPVOID (WINAPI* _ImmLockIMCC)(HIMCC hIMCC);
static BOOL (WINAPI* _ImmUnlockIMCC)(HIMCC hIMCC);
#define _ImmGetDefaultIMEWnd	ImmGetDefaultIMEWnd
#define _ImmGetIMEFileNameA	ImmGetIMEFileNameA
#define _ImmGetVirtualKey	ImmGetVirtualKey
#define _ImmNotifyIME	ImmNotifyIME
#define _ImmSetConversionStatus	ImmSetConversionStatus
#define _ImmSimulateHotKey	ImmSimulateHotKey
#define _ImmIsIME	ImmIsIME

// private API provided by CHT IME. Available on version 6.0 or later.
UINT (WINAPI*_GetReadingString)(HIMC himc, UINT uReadingBufLen, LPWSTR lpwReadingBuf, PINT pnErrorIndex, BOOL* pfIsVertical, PUINT puMaxReadingLen);
BOOL (WINAPI*_ShowReadingWindow)(HIMC himc, BOOL bShow);

// Callbacks
void (CALLBACK *ImeUiCallback_DrawRect)( int x1, int y1, int x2, int y2, DWORD color );
void (CALLBACK *ImeUiCallback_DrawFans)(const IMEUI_VERTEX* paVertex, UINT uNum);
void* (__cdecl *ImeUiCallback_Malloc)( size_t bytes );
void (__cdecl *ImeUiCallback_Free)( void* ptr );
void (CALLBACK *ImeUiCallback_OnChar)( WCHAR wc );

static void (*_SendCompString)();
static LRESULT (WINAPI* _SendMessage)(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) = SendMessageA;
static DWORD (* _GetCandidateList)(HIMC himc, DWORD dwIndex, LPCANDIDATELIST* ppCandList);

static HWND g_hwndMain;
static HWND g_hwndCurr;
static HIMC g_himcOrg;
static bool g_bImeEnabled = false;
static TCHAR g_szCompositionString[256];
static BYTE  g_szCompAttrString[256];
static DWORD g_IMECursorBytes = 0;
static DWORD g_IMECursorChars = 0;
static TCHAR g_szCandidate[MAX_CANDLIST][MAX_CANDIDATE_LENGTH];
static DWORD g_dwSelection, g_dwCount;
static UINT g_uCandPageSize;
static DWORD g_bDisableImeCompletely = false;
static DWORD g_dwIMELevel;
static DWORD g_dwIMELevelSaved;
static TCHAR g_szMultiLineCompString[ 256 * ( 3 - sizeof(TCHAR) ) ];
static bool g_bReadingWindow = false;
static bool g_bHorizontalReading = false;
static bool g_bVerticalCand = true;
static UINT g_uCaretBlinkTime = 0;
static UINT g_uCaretBlinkLast = 0;
static bool g_bCaretDraw = false;
static bool g_bChineseIME;
static bool g_bInsertMode = true;
static TCHAR g_szReadingString[32];	// Used only in case of horizontal reading window
static int g_iReadingError;	// Used only in case of horizontal reading window
static UINT g_screenWidth, g_screenHeight;
static DWORD g_dwPrevFloat;
static bool bIsSendingKeyMessage = false;
static OSVERSIONINFOA g_osi;
static bool g_bInitialized = false;
static bool g_bCandList = false;
static DWORD g_dwCandX, g_dwCandY;
static DWORD g_dwCaretX, g_dwCaretY;
static DWORD g_hCompChar;
static int g_iCandListIndexBase;
static DWORD g_dwImeUiFlags = IMEUI_FLAG_SUPPORT_CARET;
static bool g_bUILessMode = false;
static HMODULE g_hImmDll = NULL;

#define IsNT() (g_osi.dwPlatformId == VER_PLATFORM_WIN32_NT)

struct CompStringAttribute
{
	UINT			caretX;
	UINT			caretY;
	CImeUiFont_Base* pFont;
	DWORD			colorComp;
	DWORD			colorCand;
	RECT			margins;
};

static CompStringAttribute g_CaretInfo;
static DWORD g_dwState = IMEUI_STATE_OFF;
static DWORD swirl = 0;
static double lastSwirl;

#define INDICATOR_NON_IME	0
#define INDICATOR_CHS		1
#define INDICATOR_CHT		2
#define INDICATOR_KOREAN	3
#define INDICATOR_JAPANESE	4

#define GETLANG()		LOWORD(g_hklCurrent)
#define GETPRIMLANG()	((WORD)PRIMARYLANGID(GETLANG()))
#define GETSUBLANG()	SUBLANGID(GETLANG())

#define LANG_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
#define LANG_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)

static HKL g_hklCurrent = 0;
static UINT g_uCodePage = 0;
static LPTSTR g_aszIndicator[] =
{
		TEXT("A"),
#ifdef UNICODE
		L"\x7B80",
		L"\x7E41",
		L"\xac00",
		L"\x3042",
#else
		"\xd6\xd0",
		"\xa4\xa4",
		"\xb0\xa1",
		"\x82\xa0",
#endif
};
static LPTSTR g_pszIndicatior = g_aszIndicator[0];

static void GetReadingString(HWND hWnd);
static DWORD GetImeId( UINT uIndex = 0 );
static void CheckToggleState();
static void DrawImeIndicator();
static void DrawCandidateList();
static void DrawCompositionString( bool bDrawCompAttr );
static void GetReadingWindowOrientation( DWORD dwId );
static void OnInputLangChangeWorker();
static void OnInputLangChange();
static void SetImeApi();
static void CheckInputLocale();
static void SetSupportLevel( DWORD dwImeLevel );
void ImeUi_SetSupportLevel(DWORD dwImeLevel);


//
//	local helper functions
//
inline LRESULT SendKeyMsg(HWND hwnd, UINT msg, WPARAM wp)
{
	bIsSendingKeyMessage = true;
	LRESULT lRc = _SendMessage(hwnd, msg, wp, 1);
	bIsSendingKeyMessage = false;
	return lRc;
}
#define SendKeyMsg_DOWN(hwnd,vk)	SendKeyMsg(hwnd, WM_KEYDOWN, vk)
#define SendKeyMsg_UP(hwnd,vk)		SendKeyMsg(hwnd, WM_KEYUP, vk)

///////////////////////////////////////////////////////////////////////////////
//
//  CTsfUiLessMode
//      Handles IME events using Text Service Framework (TSF). Before Vista,
//      IMM (Input Method Manager) API has been used to handle IME events and
//      inqueries. Some IMM functions lose backward compatibility due to design
//      of TSF, so we have to use new TSF interfaces.
//
///////////////////////////////////////////////////////////////////////////////
class CTsfUiLessMode
{
protected:
	// Sink receives event notifications
	class CUIElementSink : public ITfUIElementSink, public ITfInputProcessorProfileActivationSink, public ITfCompartmentEventSink
	{
	public:
		CUIElementSink();
		~CUIElementSink();

		// IUnknown
		STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj);
		STDMETHODIMP_(ULONG) AddRef(void);
		STDMETHODIMP_(ULONG) Release(void);

		// ITfUIElementSink
		//   Notifications for Reading Window events. We could process candidate as well, but we'll use IMM for simplicity sake.
		STDMETHODIMP BeginUIElement(DWORD dwUIElementId, BOOL *pbShow);
		STDMETHODIMP UpdateUIElement(DWORD dwUIElementId);
		STDMETHODIMP EndUIElement(DWORD dwUIElementId);

		// ITfInputProcessorProfileActivationSink
		//   Notification for keyboard input locale change
		STDMETHODIMP OnActivated(DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid,
			REFGUID guidProfile, HKL hkl, DWORD dwFlags);

		// ITfCompartmentEventSink
		//    Notification for open mode (toggle state) change
		STDMETHODIMP OnChange(REFGUID rguid);

	private:
		LONG _cRef;
	};

	static void MakeReadingInformationString(ITfReadingInformationUIElement* preading);
	static void MakeCandidateStrings(ITfCandidateListUIElement* pcandidate);
	static ITfUIElement* GetUIElement(DWORD dwUIElementId);
	static BOOL GetCompartments( ITfCompartmentMgr** ppcm, ITfCompartment** ppTfOpenMode, ITfCompartment** ppTfConvMode );
	static BOOL SetupCompartmentSinks( BOOL bResetOnly = FALSE, ITfCompartment* pTfOpenMode = NULL, ITfCompartment* ppTfConvMode = NULL );

	static ITfThreadMgrEx* m_tm;
	static DWORD m_dwUIElementSinkCookie;
	static DWORD m_dwAlpnSinkCookie;
	static DWORD m_dwOpenModeSinkCookie;
	static DWORD m_dwConvModeSinkCookie;
	static CUIElementSink *m_TsfSink;
	static int m_nCandidateRefCount;	// Some IME shows multiple candidate lists but the Library doesn't support multiple candidate list. 
										// So track open / close events to make sure the candidate list opened last is shown.
	CTsfUiLessMode() {}	// this class can't be instanciated

public:
	static BOOL SetupSinks();
	static void ReleaseSinks();
	static BOOL CurrentInputLocaleIsIme();
	static void UpdateImeState(BOOL bResetCompartmentEventSink = FALSE);
	static void EnableUiUpdates(bool bEnable);
};

ITfThreadMgrEx* CTsfUiLessMode::m_tm;
DWORD CTsfUiLessMode::m_dwUIElementSinkCookie = TF_INVALID_COOKIE;
DWORD CTsfUiLessMode::m_dwAlpnSinkCookie = TF_INVALID_COOKIE;
DWORD CTsfUiLessMode::m_dwOpenModeSinkCookie = TF_INVALID_COOKIE;
DWORD CTsfUiLessMode::m_dwConvModeSinkCookie = TF_INVALID_COOKIE;
CTsfUiLessMode::CUIElementSink* CTsfUiLessMode::m_TsfSink = NULL;
int CTsfUiLessMode::m_nCandidateRefCount = NULL;

static unsigned long _strtoul( LPCSTR psz, LPTSTR*, int )
{
	if ( !psz )
		return 0;

	ULONG ulRet = 0;
	if ( psz[0] == '0' && ( psz[1] == 'x' || psz[1] == 'X' ) )
	{
		psz += 2;
		ULONG ul = 0;
		while ( *psz )
		{
			if ( '0' <= *psz && *psz <= '9' )
				ul = *psz - '0';
			else if ( 'A' <= *psz && *psz <= 'F' )
				ul = *psz - 'A' + 10;
			else if ( 'a' <= *psz && *psz <= 'f' )
				ul = *psz - 'a' + 10;
			else
				break;
			ulRet = ulRet * 16 + ul;
			psz++;
		}

⌨️ 快捷键说明

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