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

📄 im.cpp

📁 Windows Mobile平台的日文输入法
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
/*++

	THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
	ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
	PARTICULAR PURPOSE.

	Module Name:  

	im.cpp

--*/


#include <windows.h>
#include <commctrl.h>
#ifndef	UNDER_CE
#include "wchar.h"
#endif
#include "resource.h"
#include "dllmain.h"
#include "im.h"

#include "multibox.h"
#include "recog.h"

// Globals.

IIMCallback	   *g_pIMCallback;
IIMCallbackEx   *g_pIMCallbackEx;

// Privates

static int				g_nDown;
static HIMAGELIST		g_hImagelistWide = NULL;
static HIMAGELIST		g_hImagelistNarrow;
static const TCHAR		szHwxPadClass[] = TEXT("HWXPad");
static const TCHAR		szWPadClass[] = TEXT("WPad");

static BOOL		v_bNumLock;

static TCHAR const gpwszRegKey[] = TEXT("CLSID\\{0CBEA010-F68E-11D1-8C63-0060977B4593}");
static TCHAR const gpwszTimeout[] = TEXT("Timeout");

HANDLE		g_hFontFix;

extern "C" 
{
HWND		g_hwndMain;
HWND		g_hwndWPad;
HWND		g_hwndHelp;
HWXGLOBAL	glob;
BOOL		gbTimeout;
int			gnTimeout;
int			giMode;
int			giSuji;

HANDLE			vhThread;
DWORD			v_rThreadID;
HINSTANCE		v_hModDll;	// DLL Instance
HBITMAP 		v_hbmCtrl;	// Control bitmaps
HDC				g_hdcCtrl;	// Off screen DC for control bitmaps

BOOL CALLBACK HelpDlgProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
}

// Main window procedure.

LRESULT WINAPI
ImWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg )
	{
		case WM_COMMAND: 
			if (g_hwndHelp)
				PostMessage(g_hwndHelp, HELP_WM_COMMAND, wParam, 0);
			else
			{
				// Now do per button processing after syncronizing.
				switch (wParam) {
					case IDC_RECOG:
						SendMessage(g_hwndWPad, PAD_WM_DETERMINE, 0, 0);
						break;

					case IDC_BACKSP :	// Backspace button
						SendMessage(g_hwndWPad, PAD_WM_DETERMINE, 0, 0);
						PostThreadMessage(v_rThreadID, THRDMSG_CHAR, VK_BACK, 0);
						break;

					case IDC_ENTER :	// Return button
						SendMessage(g_hwndWPad, PAD_WM_DETERMINE, 0, 0);
						PostThreadMessage(v_rThreadID, THRDMSG_CHAR, VK_RETURN, 0);
						break;

					case IDC_CONVERT:  	// convert button
						SendMessage(g_hwndWPad, PAD_WM_DETERMINE, 0, 0);
						PostThreadMessage(v_rThreadID, THRDMSG_CHAR, VK_CONVERT, 0);
						break;

					case IDC_SPACE:		// space button
						SendMessage(g_hwndWPad, PAD_WM_DETERMINE, 0, 0);
						PostThreadMessage(v_rThreadID, THRDMSG_CHAR, VK_SPACE, 0);
						break;

					case IDC_ESCAPE:	// escape button
						SendMessage(g_hwndWPad, PAD_WM_DETERMINE, 0, 0);
						PostThreadMessage(v_rThreadID, THRDMSG_CHAR, VK_ESCAPE, 0);
						break;

					case IDC_WIDTH:		// Half/Full width button
						SendMessage(g_hwndWPad, PAD_WM_DETERMINE, 0, 0);
						PostThreadMessage(v_rThreadID, THRDMSG_CHAR, VK_KANA, 1 - giMode);
						giMode = 1 - giMode;
						break;

					case IDC_SUJI:		// Numeric button
						SendMessage(g_hwndWPad, PAD_WM_DETERMINE, 0, 0);
						PostThreadMessage(v_rThreadID, THRDMSG_CHAR, VK_NUMLOCK, 1 - giSuji);
						giSuji = 1 - giSuji;
						break;

					case IDC_QUERY:
						SendMessage(g_hwndWPad, PAD_WM_DETERMINE, 0, 0);
						g_hwndHelp = CreateDialog(g_hInstDll, MAKEINTRESOURCE(IDD_HELP), (HWND) NULL, HelpDlgProc);
						PostMessage(g_hwndHelp, HELP_WM_START, 0, 0);
						break;
				}
			}

			break;

		case HELP_WM_QUIT:
			DestroyWindow(g_hwndHelp);
			g_hwndHelp = (HWND) NULL;
			break;

	} // switch( message )

	return DefWindowProc( hwnd, msg, wParam, lParam );
}



//
// IInputMethod implementation.
//


//
// Ctor, Dtor.
//

CInputMethod::CInputMethod( IUnknown *pUnkOuter, HINSTANCE hInstance )
{
	m_cRef = 0;
    g_dwObjectCount++;

	if( !pUnkOuter ) {
		m_pUnkOuter = this;
	} else {
		m_pUnkOuter = pUnkOuter;
	}

	return;
}

CInputMethod::~CInputMethod()
{
   g_dwObjectCount--;
   return;
}

void ReadRegistry()
{
	long retval;
	DWORD dwData;
	DWORD dwType;
	DWORD cbData;
	HKEY hKey;

    retval = RegCreateKeyEx(HKEY_CLASSES_ROOT, gpwszRegKey, 0, NULL, 
                            REG_OPTION_NON_VOLATILE, 
                            (REGSAM) NULL, NULL, &hKey, &dwData);

	cbData = 4;
	dwType = REG_DWORD;

    if (retval == ERROR_SUCCESS)
    {
		RegQueryValueEx(hKey,
						gpwszTimeout,
						0,
						&dwType, 
						(BYTE *) &dwData,
						&cbData);

		gnTimeout = ((int) dwData) * 1000;
		if (gnTimeout <= 0)
		{
			gbTimeout = FALSE;
			gnTimeout = -gnTimeout;
		}
		else
			gbTimeout = TRUE;

		RegCloseKey(hKey);
	}
}

void WriteRegistry()
{
    long retval;
    DWORD dwDisp;
    HKEY hKey;
	DWORD dwData = gbTimeout ? (DWORD) (gnTimeout / 1000) : (DWORD) (-gnTimeout / 1000);

//	RETAILMSG(1, (TEXT("Multibox: WriteRegistry writing data 0x%08x\r\n"), dwData));

    retval = RegCreateKeyEx(HKEY_CLASSES_ROOT, gpwszRegKey, 0, NULL, 
                            REG_OPTION_NON_VOLATILE, 
                            (REGSAM) NULL, NULL, &hKey, &dwDisp);
        	
	if (retval == ERROR_SUCCESS)
	{
		RegSetValueEx(hKey, 
					  gpwszTimeout,
					  0, 
					  REG_DWORD, 
					  (CONST BYTE *)&dwData, 
					  sizeof(DWORD));
		RegCloseKey(hKey);
	}
}


BOOL CALLBACK OptionsDlg(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	BOOL fRetVal = TRUE;
	CInputMethod *pIM;
	WCHAR			awc[10];
	WCHAR			fwc[10];

	switch (msg)
	{
		case WM_INITDIALOG:
			ReadRegistry();
			wsprintf(awc, TEXT("%d"), gnTimeout / 1000);
			SendDlgItemMessage(hDlg, IDC_TIMEOUT, WM_SETTEXT, 0, (LPARAM) awc);
			SendDlgItemMessage(hDlg, IDC_ENABLE, BM_SETCHECK, gbTimeout ? BST_CHECKED : BST_UNCHECKED, 0);
			SetWindowLong(hDlg, GWL_USERDATA, lParam);
			break;

		case WM_COMMAND:
			switch (LOWORD(wParam))
			{
				case IDOK:
					pIM = (CInputMethod *) GetWindowLong(hDlg, GWL_USERDATA);
					if (pIM)
					{
						SendDlgItemMessage(hDlg, IDC_TIMEOUT, WM_GETTEXT, 10, (LPARAM) awc);
						FoldString(MAP_FOLDCZONE, awc, -1, fwc, 10);
						gnTimeout = wcstol(fwc, NULL, 10) * 1000;
						gbTimeout = (BST_CHECKED == SendDlgItemMessage(hDlg, IDC_ENABLE, BM_GETCHECK, 0, 0));
    					WriteRegistry();
					}

				case IDCANCEL:
					EndDialog(hDlg, TRUE);
					fRetVal = TRUE;
					break;

				default:
					break;
			}
			break;

		default:
			fRetVal = FALSE;
			break;
	}

    return fRetVal;
}

//
// IInputMethod methods.
//

STDMETHODIMP CInputMethod::Select( HWND hwndSip )
{
	static const LOGFONT	lf	= {
		16,	// ??? EditHeight - 2
		0,
		0,
		0, 
		FW_NORMAL,
		FALSE,
		FALSE,
		FALSE,
		DEFAULT_CHARSET,
		0,
		0,
		0,
		0,
		TEXT("Courier New")
	};

	WNDCLASS wc;

	vhThread = CreateThread( NULL, 0, RecogThreadFn, NULL, 0, &v_rThreadID);

	// If we return here, the caller should be able to retrieve the error
	// by calling GetLastError() and get the error code set by CreateThread.
	//
	if(!vhThread)
		return E_FAIL;

	ZeroMemory( &wc, sizeof(wc) );
	wc.lpfnWndProc		= ImWndProc;
	wc.hInstance		= g_hInstDll;
	wc.hbrBackground	= (HBRUSH) GetStockObject(LTGRAY_BRUSH);
	wc.hCursor 			= LoadCursor(NULL, IDC_ARROW);
	wc.lpszClassName	= szHwxPadClass;
	RegisterClass( &wc );

	wc.lpfnWndProc		= WPadWndProc;
	wc.lpszClassName	= szWPadClass;
	RegisterClass( &wc );

	// Create the main window.
	g_hwndMain = CreateWindow(
		szHwxPadClass,
		TEXT(""),
		WS_CHILD,
		0,
		0,
		DisplayWidth,
		DisplayHeight,
		hwndSip,
		(HMENU)NULL,
		g_hInstDll,
		NULL
	);

	// Load the bitmaps for the buttons
	v_hbmCtrl = LoadBitmap(g_hInstDll, MAKEINTRESOURCE(IDB_CONTROLS));
	if (v_hbmCtrl == (HBITMAP) NULL)
		return E_FAIL;

	// Create the offscreen DCs, make it compatible with the display

	HDC	hdc = GetDC(g_hwndMain);

	g_hdcCtrl	= CreateCompatibleDC(hdc);

	ReleaseDC(g_hwndMain, hdc);

	if (g_hdcCtrl == (HDC) NULL) 
	{
		// JRB: Should clean up!!
		return E_FAIL;
	}

	// Read the registry for the timeout value

	ReadRegistry();

	// Select the controls into the offscreen bitmap, and the same for scroll buttons

	v_hbmCtrl	= (HBITMAP) SelectObject(g_hdcCtrl, v_hbmCtrl);

	// Create the window that actually accepts the ink

	g_hwndWPad = CreateWindowEx( 0,
		szWPadClass,
		TEXT(""),
		WS_CHILD | WS_VISIBLE,
		PadWindX, PadWindY,
		PadWindWidth, PadWindHeight,
		g_hwndMain,
		NULL,
		g_hInstDll,
		NULL
	);

	ShowWindow( g_hwndMain, SW_SHOWNOACTIVATE );

// Turn the IME on
	if ( !ImmGetOpenStatus(NULL) )
	{
		DWORD dwConversion, dwSentence;
		ImmGetConversionStatus(NULL, &dwConversion, &dwSentence);
		if (dwConversion != 0x19)
			ImmSetOpenStatus(NULL,TRUE);
	}

// Last, but not least, set the ALC for recognition

	PostThreadMessage(v_rThreadID, THRDMSG_SETMASK, (WPARAM) ALC_JPN_COMMON, 0);

	return NOERROR;
}


STDMETHODIMP CInputMethod::Deselect( void )
{
// Politely ask the other thread to exit.

	SendMessage(g_hwndWPad, PAD_WM_ERASE, 0, 0);

	PostThreadMessage(v_rThreadID, THRDMSG_EXIT, 0, 0);

	// Give the auxillary thread 50ms to terminate before brutally murdering it.
	if (WaitForSingleObject(vhThread, 50) == WAIT_TIMEOUT)
		if (TerminateThread(vhThread, 0))
			CloseHandle(vhThread);

//	SendMessage(g_hwndWPad, PAD_WM_CLEAR, 0, 0);
	SendMessage(g_hwndMain, HELP_WM_QUIT, 0, 0);
	glob.bInked = FALSE;
	DestroyWindow( g_hwndMain );

	// Should we destroy the other windows???
	UnregisterClass( szHwxPadClass, g_hInstDll );
	UnregisterClass( szWPadClass, g_hInstDll );

	// Release the bitmaps, DCs, and imagelists

    ImageList_Destroy( g_hImagelistWide );
    ImageList_Destroy( g_hImagelistNarrow );
    g_hImagelistWide = NULL;
	g_hImagelistNarrow = NULL;

	if (g_hdcCtrl != (HDC) NULL)
		v_hbmCtrl = (HBITMAP) SelectObject(g_hdcCtrl, v_hbmCtrl);

	if (g_hdcCtrl)
		DeleteDC(g_hdcCtrl);

	if (v_hbmCtrl)
		DeleteObject(v_hbmCtrl);

	return NOERROR;
}


STDMETHODIMP CInputMethod::Showing( void )
{
	if(!glob.pstrk){
		glob.bInked = FALSE;
	}

	return NOERROR;
}


STDMETHODIMP CInputMethod::Hiding( void )
{
	SendMessage(g_hwndMain, HELP_WM_QUIT, 0, 0);

	return NOERROR;
}


STDMETHODIMP CInputMethod::GetInfo( IMINFO *pimi )
{
	HBITMAP hbmp;
	if( !g_hImagelistWide )
	{
		g_hImagelistWide = ImageList_Create(
							32,
							16,
							ILC_COLOR | ILC_MASK,
							1,
							1 );
		g_hImagelistNarrow = ImageList_Create(
							16,
							16,
							ILC_COLOR | ILC_MASK,
							1,
							1 );
		hbmp = LoadBitmap( g_hInstDll, MAKEINTRESOURCE(IDB_WIDE) );
		ImageList_AddMasked(
			g_hImagelistWide,
			hbmp,
			RGB(192,192,192) );
		DeleteObject(hbmp);

		hbmp = LoadBitmap( g_hInstDll, MAKEINTRESOURCE(IDB_NARROW) );
		ImageList_AddMasked(
			g_hImagelistNarrow,
			hbmp,
			RGB(192,192,192) );
		DeleteObject(hbmp);

	}

	pimi->fdwFlags = SIPF_DOCKED;
	pimi->hImageNarrow = (HANDLE)g_hImagelistNarrow;
	pimi->hImageWide = (HANDLE)g_hImagelistWide;
	pimi->iNarrow = pimi->iWide = 0;
	pimi->rcSipRect.left = pimi->rcSipRect.top = 0;
	pimi->rcSipRect.right = DisplayWidth;
	pimi->rcSipRect.bottom = DisplayHeight;

	return NOERROR;
}


STDMETHODIMP CInputMethod::ReceiveSipInfo( SIPINFO *psi )
{
	MoveWindow(
		g_hwndMain,
		0,
		0,
		psi->rcSipRect.right - psi->rcSipRect.left,
		psi->rcSipRect.bottom - psi->rcSipRect.top,
		FALSE );

	return NOERROR;
}


STDMETHODIMP CInputMethod::RegisterCallback( IIMCallback *pIMCallback )
{
	g_pIMCallback = pIMCallback;
	return NOERROR;
}


STDMETHODIMP CInputMethod::GetImData( DWORD dwSize, void *pvImData )
{
	return E_NOTIMPL;
}


STDMETHODIMP CInputMethod::SetImData( DWORD dwSize, void *pvImData )
{
	return E_NOTIMPL;
}


STDMETHODIMP CInputMethod::UserOptionsDlg( HWND hwndParent )
{
    DialogBoxParam(g_hInstDll, 
              MAKEINTRESOURCE(IDD_OPTIONS), 
              hwndParent, 
              OptionsDlg,
			  (LPARAM) this);

    return NOERROR;
}

// IInputMethodEx methods

STDMETHODIMP CInputMethod::RegisterCallbackEx( IIMCallbackEx *pIMCallbackEx )
{
	g_pIMCallbackEx = pIMCallbackEx;
	return NOERROR;
}

STDMETHODIMP CInputMethod::SetIMMActiveContext(HWND hwnd,BOOL bOpen,DWORD dwConversion,DWORD dwSentence,DWORD hkl)
{
	// Not implemented for this IM.
    return NOERROR;
}

//
// IUnknown methods.
//

STDMETHODIMP CInputMethod::QueryInterface( REFIID riid, LPVOID FAR* ppobj )
{
	if( IID_IUnknown == riid || IID_IInputMethod == riid || IID_IInputMethodEx == riid) 
	{
		*ppobj = this;
		AddRef();
		return NOERROR;
	} 
	return E_NOINTERFACE;
}

STDMETHODIMP_(ULONG) CInputMethod::AddRef( void )
{
	return ++m_cRef;
}

STDMETHODIMP_(ULONG) CInputMethod::Release( void )
{
	if( --m_cRef ) {
		return m_cRef;
	}
	delete this;
	return 0;
}

⌨️ 快捷键说明

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