You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1382 lines
38 KiB
1382 lines
38 KiB
/**************************************************************************\
|
|
* Module Name: softkbdimx.cpp
|
|
*
|
|
* Copyright (c) 1985 - 2000, Microsoft Corporation
|
|
*
|
|
* Implement TIP interface for Soft Keyboard Input.
|
|
*
|
|
* History:
|
|
* 28-March-2000 weibz Created
|
|
\**************************************************************************/
|
|
|
|
#include "private.h"
|
|
#include "softkbdimx.h"
|
|
#include "globals.h"
|
|
#include "immxutil.h"
|
|
#include "proputil.h"
|
|
#include "funcprv.h"
|
|
#include "helpers.h"
|
|
#include "editcb.h"
|
|
#include "dispattr.h"
|
|
#include "computil.h"
|
|
#include "timsink.h"
|
|
#include "ats.h"
|
|
#include "lpns.h"
|
|
#include "regsvr.h"
|
|
|
|
#include "softkbdes.h"
|
|
|
|
#include "mui.h"
|
|
#include "regimx.h"
|
|
#include "xstring.h"
|
|
#include "cregkey.h"
|
|
|
|
extern REGTIPLANGPROFILE c_rgProf[];
|
|
|
|
// Implementation of CSoftkbdRegistry.
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CSoftkbdRegistry::CSoftkbdRegistry()
|
|
{
|
|
extern void DllAddRef(void);
|
|
|
|
m_fInitialized = FALSE;
|
|
|
|
DllAddRef( );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CSoftkbdRegistry::~CSoftkbdRegistry()
|
|
{
|
|
extern void DllRelease(void);
|
|
|
|
if (m_rgLang.Count())
|
|
m_rgLang.Clear();
|
|
|
|
DllRelease();
|
|
}
|
|
|
|
// Generate the Current Lang Profile List from registry.
|
|
|
|
HRESULT CSoftkbdRegistry::_GenerateCurrentLangProfileList( )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CComPtr<IEnumTfLanguageProfiles> cpEnumTfLangProf;
|
|
|
|
if ( m_fInitialized == FALSE)
|
|
{
|
|
hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ITfInputProcessorProfilesEx, (void**)&m_cpInputProcessorProfiles);
|
|
|
|
// Load profile name from resource.
|
|
LoadStringWrapW(g_hInst, IDS_SFTKBD_STANDARD_PROFILE, m_pwszStandard, 128);
|
|
LoadStringWrapW(g_hInst, IDS_SFTKBD_SYMBOL_PROFILE, m_pwszSymbol, 128);
|
|
|
|
char szFilePath[MAX_PATH];
|
|
GetModuleFileName(g_hInst, szFilePath, ARRAYSIZE(szFilePath));
|
|
StringCchCopyW(m_pwszIconFile, ARRAYSIZE(m_pwszIconFile), AtoW(szFilePath));
|
|
|
|
if ( hr == S_OK )
|
|
m_fInitialized = TRUE;
|
|
}
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
LONG lret = ERROR_SUCCESS;
|
|
CMyRegKey regkey;
|
|
|
|
if (m_rgLang.Count())
|
|
m_rgLang.Clear();
|
|
|
|
// Get the Language profile list for all languages.
|
|
|
|
char szSoftkbdLangProfKey[MAX_PATH];
|
|
char szClsidStr[64];
|
|
|
|
StringCchCopyA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), c_szCTFTIPKey);
|
|
CLSIDToStringA(CLSID_SoftkbdIMX, szClsidStr);
|
|
StringCchCatA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), szClsidStr);
|
|
StringCchCatA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), "\\");
|
|
StringCchCatA(szSoftkbdLangProfKey, ARRAYSIZE(szSoftkbdLangProfKey), c_szLanguageProfileKey);
|
|
|
|
lret = regkey.Open(HKEY_LOCAL_MACHINE,
|
|
szSoftkbdLangProfKey,
|
|
KEY_READ);
|
|
|
|
if ( ERROR_SUCCESS == lret )
|
|
{
|
|
char szProfileName[MAX_PATH];
|
|
char szLangIdName[MAX_PATH];
|
|
DWORD dwIndex = 0;
|
|
LANGID langid;
|
|
BOOL fStandExist = FALSE;
|
|
BOOL fSymExist = FALSE;
|
|
TCHAR achClsidStd[CLSID_STRLEN+1];
|
|
TCHAR achClsidSym[CLSID_STRLEN+1];
|
|
CMyRegKey regLangKey;
|
|
ULONG ulCount = 0;
|
|
|
|
CLSIDToStringA(c_guidProfile, achClsidStd);
|
|
CLSIDToStringA(c_guidProfileSym, achClsidSym);
|
|
|
|
// Enum the subkey for langid.
|
|
|
|
while ( ERROR_SUCCESS == regkey.EnumKey(dwIndex, szLangIdName, ARRAYSIZE(szLangIdName)))
|
|
{
|
|
|
|
lret = regLangKey.Open(regkey.m_hKey,
|
|
szLangIdName,
|
|
KEY_READ);
|
|
|
|
if ( ERROR_SUCCESS == lret )
|
|
{
|
|
char *pLangStr;
|
|
int iLangLen;
|
|
DWORD dwProfIndex;
|
|
|
|
pLangStr = szLangIdName;
|
|
|
|
if ( (tolower(pLangStr[0]) == '0') && (tolower(pLangStr[1]) == 'x'))
|
|
pLangStr += 2;
|
|
|
|
iLangLen = strlen(pLangStr);
|
|
langid = 0;
|
|
for ( int i=0; i<iLangLen; i++)
|
|
{
|
|
WORD wVchar;
|
|
char cLower;
|
|
|
|
cLower = (char)tolower(pLangStr[i]);
|
|
|
|
wVchar = 0;
|
|
if ((cLower <= '9') && (cLower >= '0'))
|
|
wVchar = cLower - '0';
|
|
|
|
if ((cLower <= 'f') && (cLower >= 'a' ))
|
|
wVchar = cLower - 'a' + 10;
|
|
|
|
langid = langid * 16 + wVchar;
|
|
}
|
|
|
|
fStandExist = fSymExist = FALSE;
|
|
|
|
dwProfIndex = 0;
|
|
|
|
while (!(fStandExist && fSymExist)
|
|
&& ERROR_SUCCESS == regLangKey.EnumKey(dwProfIndex, szProfileName, ARRAYSIZE(szProfileName)))
|
|
{
|
|
|
|
if ( !_stricmp(szProfileName, achClsidStd) )
|
|
fStandExist = TRUE;
|
|
else if ( !_stricmp(szProfileName, achClsidSym) )
|
|
fSymExist = TRUE;
|
|
|
|
dwProfIndex++;
|
|
}
|
|
|
|
if ( fStandExist && fSymExist )
|
|
{
|
|
LANGID *pLang;
|
|
m_rgLang.Append(1);
|
|
|
|
pLang = m_rgLang.GetPtr(ulCount);
|
|
if ( pLang )
|
|
{
|
|
ulCount ++;
|
|
*pLang = langid;
|
|
}
|
|
}
|
|
regLangKey.Close( );
|
|
}
|
|
dwIndex ++;
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Add or Remove Language profile
|
|
HRESULT CSoftkbdRegistry::_SetSoftkbdTIP(LANGID langid, BOOL fEnable )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG ulCount;
|
|
BOOL fAllLangExist = FALSE;
|
|
BOOL fLangExist = FALSE;
|
|
LANGID *pLangId = NULL;
|
|
|
|
hr = _GenerateCurrentLangProfileList( );
|
|
if ( hr != S_OK ) return hr;
|
|
|
|
ulCount = m_rgLang.Count();
|
|
|
|
if ( langid == 0 || langid == (LANGID)0xffff )
|
|
{
|
|
// Remove all the Profiles first.
|
|
for (ULONG i=0; i<ulCount; i++)
|
|
{
|
|
pLangId = m_rgLang.GetPtr(i);
|
|
if ( pLangId )
|
|
{
|
|
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
|
|
*pLangId,
|
|
c_guidProfile);
|
|
|
|
if (S_OK == hr)
|
|
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
|
|
*pLangId,
|
|
c_guidProfileSym);
|
|
}
|
|
}
|
|
|
|
if ( fEnable && hr == S_OK) // Add this profile for all languages.
|
|
{
|
|
hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
|
|
(LANGID)0xffff,
|
|
c_guidProfile,
|
|
m_pwszStandard,
|
|
wcslen(m_pwszStandard),
|
|
m_pwszIconFile,
|
|
wcslen(m_pwszIconFile),
|
|
0);
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
// Set DisplayName for MUI supporting
|
|
hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
|
|
(LANGID)0xffff,
|
|
c_guidProfile,
|
|
m_pwszIconFile,
|
|
wcslen(m_pwszIconFile),
|
|
IDS_SFTKBD_STANDARD_PROFILE );
|
|
}
|
|
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
|
|
(LANGID)0xffff,
|
|
c_guidProfileSym,
|
|
m_pwszSymbol,
|
|
wcslen(m_pwszSymbol),
|
|
m_pwszIconFile,
|
|
wcslen(m_pwszIconFile),
|
|
1);
|
|
}
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
// Set DisplayName for MUI supporting
|
|
hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
|
|
(LANGID)0xffff,
|
|
c_guidProfileSym,
|
|
m_pwszIconFile,
|
|
wcslen(m_pwszIconFile),
|
|
IDS_SFTKBD_SYMBOL_PROFILE );
|
|
}
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Check to see if this profile is already there
|
|
for (ULONG i=0; i<ulCount; i++)
|
|
{
|
|
if ( fAllLangExist && fLangExist )
|
|
break;
|
|
|
|
pLangId = m_rgLang.GetPtr(i);
|
|
if ( pLangId )
|
|
{
|
|
if ( *pLangId == (LANGID)0xffff)
|
|
fAllLangExist = TRUE;
|
|
|
|
if ( *pLangId == langid )
|
|
fLangExist = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( fEnable )
|
|
{
|
|
if ( !fAllLangExist && !fLangExist )
|
|
{
|
|
hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
|
|
langid,
|
|
c_guidProfile,
|
|
m_pwszStandard,
|
|
wcslen(m_pwszStandard),
|
|
m_pwszIconFile,
|
|
wcslen(m_pwszIconFile),
|
|
0);
|
|
if ( hr == S_OK )
|
|
{
|
|
// Set DisplayName for MUI supporting
|
|
hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
|
|
langid,
|
|
c_guidProfile,
|
|
m_pwszIconFile,
|
|
wcslen(m_pwszIconFile),
|
|
IDS_SFTKBD_STANDARD_PROFILE );
|
|
}
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
hr = m_cpInputProcessorProfiles->AddLanguageProfile(CLSID_SoftkbdIMX,
|
|
langid,
|
|
c_guidProfileSym,
|
|
m_pwszSymbol,
|
|
wcslen(m_pwszSymbol),
|
|
m_pwszIconFile,
|
|
wcslen(m_pwszIconFile),
|
|
1);
|
|
}
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
// Set DisplayName for MUI supporting
|
|
hr = m_cpInputProcessorProfiles->SetLanguageProfileDisplayName(CLSID_SoftkbdIMX,
|
|
langid,
|
|
c_guidProfileSym,
|
|
m_pwszIconFile,
|
|
wcslen(m_pwszIconFile),
|
|
IDS_SFTKBD_SYMBOL_PROFILE );
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Remove the specified or all Profiles.
|
|
for (ULONG i=0; i<ulCount; i++)
|
|
{
|
|
pLangId = m_rgLang.GetPtr(i);
|
|
if ( pLangId )
|
|
{
|
|
if ( fAllLangExist )
|
|
{
|
|
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
|
|
*pLangId,
|
|
c_guidProfile);
|
|
|
|
if ( S_OK == hr )
|
|
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
|
|
*pLangId,
|
|
c_guidProfileSym);
|
|
}
|
|
else if ( fLangExist )
|
|
{
|
|
if ( *pLangId == langid )
|
|
{
|
|
|
|
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
|
|
langid,
|
|
c_guidProfile);
|
|
if ( S_OK == hr )
|
|
hr = m_cpInputProcessorProfiles->RemoveLanguageProfile(CLSID_SoftkbdIMX,
|
|
langid,
|
|
c_guidProfileSym);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CSoftkbdRegistry::EnableSoftkbd(LANGID langid )
|
|
{
|
|
return _SetSoftkbdTIP(langid, TRUE);
|
|
|
|
}
|
|
|
|
HRESULT CSoftkbdRegistry::DisableSoftkbd(LANGID langid )
|
|
{
|
|
return _SetSoftkbdTIP(langid, FALSE);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CSoftkbdIMX::CSoftkbdIMX()
|
|
{
|
|
extern void DllAddRef(void);
|
|
|
|
_fInitialized = FALSE;
|
|
_SoftKbd = NULL;
|
|
|
|
_CurKbdType = KBDTYPE_NONE;
|
|
_CurLayout = NON_LAYOUT;
|
|
|
|
_tim = NULL;
|
|
_dim = NULL;
|
|
|
|
_pCes = NULL;
|
|
|
|
DllAddRef();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CSoftkbdIMX::~CSoftkbdIMX()
|
|
{
|
|
extern void DllRelease(void);
|
|
|
|
if ( _SoftKbd != NULL )
|
|
{
|
|
|
|
_SoftKbd->DestroySoftKeyboardWindow( );
|
|
}
|
|
|
|
if ( _hOwnerWnd != NULL )
|
|
DestroyWindow(_hOwnerWnd);
|
|
|
|
_fInitialized = FALSE;
|
|
|
|
if ( _SoftKbd != NULL )
|
|
{
|
|
if ( _KbdSymbol.pskbdes != NULL )
|
|
{
|
|
|
|
_SoftKbd->UnadviseSoftKeyboardEventSink(_KbdSymbol.dwSkbdESCookie);
|
|
_SoftKbd->UnadviseSoftKeyboardEventSink(_dwsftkbdwndesCookie);
|
|
|
|
delete _psftkbdwndes;
|
|
|
|
delete _KbdSymbol.pskbdes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( _pCes != NULL )
|
|
{
|
|
_fOnOffSave = FALSE;
|
|
|
|
_pCes->_Unadvise();
|
|
SafeReleaseClear(_pCes);
|
|
}
|
|
|
|
SafeRelease(_SoftKbd);
|
|
SafeRelease(_pFuncPrv);
|
|
|
|
DllRelease();
|
|
}
|
|
|
|
|
|
//
|
|
// Only when GUID_COMPARTMENT_HANDWRITING_OPENCLOSE is set TRUE at the first
|
|
// time, this Initiliaze( ) could be called by the compartment event sink.
|
|
//
|
|
|
|
HRESULT CSoftkbdIMX::Initialize( )
|
|
{
|
|
|
|
HRESULT hr;
|
|
WCHAR *lpSymXMLResStr = L"IDSKD_SYMLAYOUT";
|
|
WCHAR wszModuleFile[MAX_PATH];
|
|
CHAR szModuleFile[MAX_PATH];
|
|
DWORD dwFileLen;
|
|
WNDCLASSEX wndclass;
|
|
INT wScreenWidth, wScreenHeight;
|
|
INT left, top, width, height;
|
|
RECT rcWork;
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
if ( _fInitialized == TRUE )
|
|
{
|
|
// Initialization is already done.
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
if ( GetClassInfoEx( g_hInst, c_szIMXOwnerWndClass, &wndclass) == 0 )
|
|
{
|
|
memset(&wndclass, 0, sizeof(wndclass));
|
|
wndclass.cbSize = sizeof(wndclass);
|
|
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
|
|
wndclass.hInstance = g_hInst;
|
|
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
wndclass.lpfnWndProc = _OwnerWndProc;
|
|
wndclass.lpszClassName = c_szIMXOwnerWndClass;
|
|
RegisterClassEx(&wndclass);
|
|
}
|
|
|
|
_hOwnerWnd = CreateWindowEx(0, c_szIMXOwnerWndClass, TEXT(""), WS_DISABLED, 0, 0, 0, 0, NULL, 0, g_hInst, 0);
|
|
|
|
// PerfConsider: use a static ctor instead of ole32/class factory/etc.
|
|
hr=CoCreateInstance(CLSID_SoftKbd, NULL, CLSCTX_INPROC_SERVER, IID_ISoftKbd, (void**)&_SoftKbd);
|
|
|
|
|
|
if (FAILED(hr) )
|
|
{
|
|
// assert(0);
|
|
return hr;
|
|
}
|
|
|
|
_SoftKbd->Initialize( );
|
|
|
|
// initialize Standard soft layout and Symbol Soft Layout.
|
|
|
|
_KbdStandard.dwSoftKbdLayout = SOFTKBD_US_STANDARD;
|
|
_KbdStandard.fStandard = TRUE;
|
|
_KbdStandard.dwNumLabels = 0; // for standard, this field is not really used.
|
|
_KbdStandard.dwCurLabel = 0;
|
|
_KbdStandard.pskbdes = NULL; // standard layout doesn't supply sftkbd event sink.
|
|
_KbdStandard.dwSkbdESCookie = 0;
|
|
|
|
_KbdSymbol.fStandard = FALSE;
|
|
_KbdSymbol.dwNumLabels = 2;
|
|
_KbdSymbol.dwCurLabel = 0;
|
|
|
|
dwFileLen = GetModuleFileNameA(g_hInst, szModuleFile, MAX_PATH);
|
|
|
|
if ( dwFileLen == 0 )
|
|
{
|
|
hr = E_FAIL;
|
|
goto CleanUp;
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, szModuleFile, -1,
|
|
wszModuleFile, MAX_PATH);
|
|
|
|
hr = _SoftKbd->CreateSoftKeyboardLayoutFromResource(wszModuleFile, L"SKDFILE", lpSymXMLResStr,
|
|
&(_KbdSymbol.dwSoftKbdLayout) );
|
|
|
|
CHECKHR(hr);
|
|
|
|
|
|
_KbdSymbol.pskbdes = new CSoftKeyboardEventSink(this, _KbdSymbol.dwSoftKbdLayout);
|
|
|
|
if ( _KbdSymbol.pskbdes == NULL )
|
|
{
|
|
|
|
hr = E_FAIL;
|
|
goto CleanUp;
|
|
}
|
|
|
|
hr = _SoftKbd->AdviseSoftKeyboardEventSink(_KbdSymbol.dwSoftKbdLayout,
|
|
IID_ISoftKeyboardEventSink,
|
|
_KbdSymbol.pskbdes,
|
|
&(_KbdSymbol.dwSkbdESCookie) );
|
|
|
|
|
|
CHECKHR(hr);
|
|
|
|
_psftkbdwndes = new CSoftKbdWindowEventSink(this);
|
|
|
|
if ( _psftkbdwndes == NULL )
|
|
{
|
|
|
|
hr=E_FAIL;
|
|
goto CleanUp;
|
|
}
|
|
|
|
CHECKHR(_SoftKbd->AdviseSoftKeyboardEventSink(0,IID_ISoftKbdWindowEventSink,_psftkbdwndes, &(_dwsftkbdwndesCookie)) );
|
|
|
|
_CurLayout = _KbdStandard.dwSoftKbdLayout;
|
|
|
|
width = 400;
|
|
height = 172;
|
|
|
|
if ( S_OK != GetSoftKBDPosition( &left, &top ) )
|
|
{
|
|
// the compartment is not initialize.
|
|
SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0 );
|
|
wScreenWidth = (INT)(rcWork.right - rcWork.left + 1);
|
|
wScreenHeight = (INT)(rcWork.bottom - rcWork.top + 1);
|
|
left = wScreenWidth - width -2;
|
|
top = wScreenHeight - height - 1;
|
|
}
|
|
|
|
CHECKHR(_SoftKbd->CreateSoftKeyboardWindow(_hOwnerWnd,TITLEBAR_GRIPPER_BUTTON, left,top,width,height));
|
|
|
|
SetSoftKBDPosition(left, top );
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
LOGFONTW lfTextFont;
|
|
int iDpi;
|
|
int iPoint;
|
|
|
|
iDpi = 96;
|
|
iPoint = 9;
|
|
HDC hdc;
|
|
|
|
hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
|
|
|
|
if (hdc)
|
|
{
|
|
iDpi = GetDeviceCaps(hdc, LOGPIXELSY);
|
|
DeleteDC(hdc);
|
|
|
|
memset(&lfTextFont, 0, sizeof(LOGFONTW) );
|
|
lfTextFont.lfHeight = -iPoint * iDpi / 72;
|
|
|
|
lfTextFont.lfWeight = 400;
|
|
lfTextFont.lfOutPrecision = OUT_TT_ONLY_PRECIS;
|
|
|
|
wcsncpy(lfTextFont.lfFaceName, L"Arial", ARRAYSIZE(lfTextFont.lfFaceName));
|
|
lfTextFont.lfCharSet = 0;
|
|
|
|
hr = _SoftKbd->SetSoftKeyboardTextFont(&lfTextFont);
|
|
}
|
|
}
|
|
|
|
_fInitialized = TRUE;
|
|
|
|
// or get the current layout from previous saved one.
|
|
|
|
CleanUp:
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnSetThreadFocus
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CSoftkbdIMX::OnSetThreadFocus()
|
|
{
|
|
|
|
// Restore the ON/OFF status before KillThreadFocus( )
|
|
|
|
if ( _SoftKbd != NULL )
|
|
{
|
|
|
|
if ( _fOnOffSave )
|
|
{
|
|
// adjust the window position.
|
|
int xWnd, yWnd;
|
|
WORD width=0, height=0;
|
|
POINT OldPoint;
|
|
HRESULT hr;
|
|
|
|
_SoftKbd->GetSoftKeyboardPosSize(&OldPoint, &width, &height);
|
|
hr = GetSoftKBDPosition(&xWnd, &yWnd);
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
if ( (xWnd != OldPoint.x) || (yWnd != OldPoint.y) )
|
|
{
|
|
POINT NewPoint;
|
|
|
|
NewPoint.x = xWnd;
|
|
NewPoint.y = yWnd;
|
|
_SoftKbd->SetSoftKeyboardPosSize(NewPoint, width, height);
|
|
}
|
|
}
|
|
|
|
_ShowSoftKBDWindow(TRUE);
|
|
}
|
|
else
|
|
_SoftKbd->ShowSoftKeyboard(FALSE);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// OnKillThreadFocus
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CSoftkbdIMX::OnKillThreadFocus()
|
|
{
|
|
|
|
|
|
// keep the ON/OFF status so that OnSetThreadFocus( ) can restore it later
|
|
|
|
_fOnOffSave = GetSoftKBDOnOff( );
|
|
|
|
if ( _SoftKbd != NULL )
|
|
{
|
|
_SoftKbd->ShowSoftKeyboard( FALSE );
|
|
}
|
|
|
|
// release all the modifier keys except lock keys. that is , Shift, Alt, Ctrl,
|
|
keybd_event((BYTE)VK_SHIFT, (BYTE)KID_LSHFT, (DWORD)KEYEVENTF_KEYUP, 0);
|
|
keybd_event((BYTE)VK_MENU, (BYTE)KID_ALT, (DWORD)KEYEVENTF_KEYUP, 0);
|
|
keybd_event((BYTE)VK_LMENU, (BYTE)KID_ALT, (DWORD)KEYEVENTF_KEYUP, 0);
|
|
keybd_event((BYTE)VK_RMENU, (BYTE)KID_RALT, (DWORD)KEYEVENTF_KEYUP, 0);
|
|
keybd_event((BYTE)VK_CONTROL, (BYTE)KID_CTRL, (DWORD)KEYEVENTF_KEYUP, 0);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Activate
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CSoftkbdIMX::Activate(ITfThreadMgr *ptim, TfClientId tid)
|
|
{
|
|
ITfSource *source;
|
|
ITfLangBarItemMgr *plbim = NULL;
|
|
HRESULT hr;
|
|
|
|
Assert(_tim == NULL);
|
|
_tim = ptim;
|
|
_tim->AddRef();
|
|
|
|
_tid = tid;
|
|
|
|
|
|
_pProfile = NULL;
|
|
|
|
if (_tim->QueryInterface(IID_ITfSource, (void **)&source) == S_OK)
|
|
{
|
|
source->AdviseSink(IID_ITfThreadFocusSink, (ITfThreadFocusSink *)this, &_dwThreadFocusCookie);
|
|
source->Release();
|
|
}
|
|
|
|
//
|
|
// Add SoftKeyboard activate button into LangBarItemMgr.
|
|
//
|
|
if (FAILED(hr = GetService(_tim, IID_ITfLangBarItemMgr, (IUnknown **)&plbim)))
|
|
{
|
|
hr = E_FAIL;
|
|
goto CleanUp;
|
|
}
|
|
|
|
if (!(_plbi = new CLBarItem(this)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto CleanUp;
|
|
}
|
|
|
|
plbim->AddItem(_plbi);
|
|
|
|
|
|
//
|
|
// get language ID.
|
|
//
|
|
_InitLangID();
|
|
|
|
if ( (_timActiveLangSink = new CActiveLanguageProfileNotifySink(_AlsCallback, this)) == NULL )
|
|
{
|
|
Assert(0);
|
|
hr = E_FAIL;
|
|
goto CleanUp;
|
|
}
|
|
|
|
_timActiveLangSink->_Advise(_tim);
|
|
|
|
if ( (_timLangSink = new CLanguageProfileNotifySink(_LsCallback, this)) == NULL )
|
|
{
|
|
Assert(0);
|
|
hr = E_FAIL;
|
|
goto CleanUp;
|
|
}
|
|
|
|
_timLangSink->_Advise(_pProfile);
|
|
|
|
_pFuncPrv = new CFunctionProvider(this);
|
|
|
|
if ( _pFuncPrv != NULL)
|
|
_pFuncPrv->_Advise(_tim);
|
|
|
|
|
|
// defaultly, hide the soft keyboard window.
|
|
|
|
_fOnOffSave = FALSE;
|
|
|
|
if (!(_pCes = new CCompartmentEventSink(_CompEventSinkCallback, this)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
CHECKHR(hr);
|
|
}
|
|
|
|
CHECKHR(_pCes->_Advise(_tim, GUID_COMPARTMENT_HANDWRITING_OPENCLOSE, FALSE));
|
|
CHECKHR(_pCes->_Advise(_tim, GUID_COMPARTMENT_SOFTKBD_KBDLAYOUT, FALSE));
|
|
|
|
#if 0
|
|
|
|
if (_tim->IsThreadFocus(&fThreadFocus) == S_OK && fThreadFocus)
|
|
{
|
|
// init any UI
|
|
OnSetThreadFocus();
|
|
}
|
|
|
|
#endif
|
|
|
|
hr = S_OK;
|
|
|
|
CleanUp:
|
|
SafeRelease(plbim);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Deactivate
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CSoftkbdIMX::Deactivate()
|
|
{
|
|
ITfSource *source;
|
|
ITfLangBarItemMgr *plbim = NULL;
|
|
// BOOL fThreadFocus;
|
|
HRESULT hr;
|
|
|
|
|
|
if (_tim->QueryInterface(IID_ITfSource, (void **)&source) == S_OK)
|
|
{
|
|
source->UnadviseSink(_dwThreadFocusCookie);
|
|
source->Release();
|
|
}
|
|
|
|
//
|
|
// Clean up SoftKeyboard activate button into LangBarItemMgr.
|
|
//
|
|
if (SUCCEEDED(hr = GetService(_tim, IID_ITfLangBarItemMgr, (IUnknown **)&plbim)))
|
|
{
|
|
plbim->RemoveItem(_plbi);
|
|
SafeReleaseClear(_plbi);
|
|
SafeReleaseClear(plbim);
|
|
}
|
|
|
|
|
|
|
|
if ( _timActiveLangSink != NULL )
|
|
{
|
|
_timActiveLangSink->_Unadvise( );
|
|
SafeReleaseClear(_timActiveLangSink);
|
|
}
|
|
|
|
if ( _timLangSink != NULL )
|
|
{
|
|
_timLangSink->_Unadvise( );
|
|
SafeReleaseClear(_timLangSink);
|
|
}
|
|
|
|
if ( _pFuncPrv != NULL )
|
|
{
|
|
_pFuncPrv->_Unadvise(_tim);
|
|
SafeReleaseClear(_pFuncPrv);
|
|
}
|
|
|
|
if ( _pCes != NULL )
|
|
{
|
|
|
|
if ( _SoftKbd != NULL )
|
|
_SoftKbd->ShowSoftKeyboard(FALSE);
|
|
_fOnOffSave = FALSE;
|
|
_pCes->_Unadvise();
|
|
SafeReleaseClear(_pCes);
|
|
}
|
|
|
|
SafeReleaseClear(_pProfile);
|
|
|
|
SafeReleaseClear(_tim);
|
|
|
|
TFUninitLib_Thread(&_libTLS);
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetIC
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
ITfContext *CSoftkbdIMX::GetIC()
|
|
{
|
|
ITfContext *pic = NULL;
|
|
|
|
if (!_tim)
|
|
{
|
|
Assert(0);
|
|
return NULL;
|
|
}
|
|
|
|
ITfDocumentMgr *pdim;
|
|
if (SUCCEEDED(_tim->GetFocus(&pdim)) && pdim)
|
|
{
|
|
// otherwise grab the top of the stack
|
|
pdim->GetTop(&pic);
|
|
pdim->Release();
|
|
}
|
|
|
|
return pic;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _OnOffToggle
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CSoftkbdIMX::_OnOffToggle( )
|
|
{
|
|
|
|
BOOL fOn = GetSoftKBDOnOff( );
|
|
|
|
SetSoftKBDOnOff(!fOn);
|
|
|
|
_UpdateUI();
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _EditSessionCallback
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSoftkbdIMX::_InputKeyLabel(TfEditCookie ec, ITfContext *pic, WCHAR *lpszLabel, UINT nLabLen)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ITfRange *pRange, *pSelection;
|
|
|
|
if ( pic )
|
|
{
|
|
TF_STATUS ts;
|
|
hr = pic->GetStatus(&ts);
|
|
if ( (S_OK == hr) && (TF_SD_READONLY & ts.dwDynamicFlags) )
|
|
{
|
|
// Readonly Doc, just return here!
|
|
return hr;
|
|
}
|
|
|
|
if (GetSelectionSimple(ec, pic, &pSelection) == S_OK)
|
|
{
|
|
if (SUCCEEDED(pSelection->Clone(&pRange)))
|
|
{
|
|
BOOL fInsertOk = FALSE;
|
|
hr = pRange->AdjustForInsert(ec, nLabLen, &fInsertOk);
|
|
if (S_OK == hr && fInsertOk)
|
|
{
|
|
SetTextAndProperty(&_libTLS, ec, pic, pRange, lpszLabel, nLabLen, _langid, NULL);
|
|
|
|
_MySetSelectionSimple(ec, pic, pRange);
|
|
}
|
|
|
|
pRange->Release();
|
|
}
|
|
|
|
pSelection->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CSoftkbdIMX::_EditSessionCallback(TfEditCookie ec, CEditSession *pes)
|
|
{
|
|
CSoftkbdIMX *_this;
|
|
HRESULT hr;
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
switch (pes->_state.u)
|
|
{
|
|
|
|
case ESCB_KEYLABEL :
|
|
|
|
{
|
|
WCHAR *lpszLabel;
|
|
UINT nLabLen;
|
|
|
|
lpszLabel = (WCHAR *)(pes->_state.lParam);
|
|
|
|
if ( lpszLabel == NULL )
|
|
{
|
|
hr = E_FAIL;
|
|
return hr;
|
|
}
|
|
|
|
nLabLen = wcslen(lpszLabel);
|
|
|
|
_this = (CSoftkbdIMX *)pes->_state.pv;
|
|
hr = _this->_InputKeyLabel(ec,
|
|
pes->_state.pic,
|
|
lpszLabel,
|
|
nLabLen);
|
|
|
|
SafeFreePointer(lpszLabel);
|
|
|
|
break;
|
|
}
|
|
|
|
default :
|
|
break;
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Show or Hide the soft keyboard window based on current setting.
|
|
//
|
|
|
|
HRESULT CSoftkbdIMX::_ShowSoftKBDWindow( BOOL fShow )
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
if ( fShow && ( _fInitialized == FALSE ) )
|
|
// call the initialize function
|
|
// to get the ISoftKbd.
|
|
{
|
|
Initialize( );
|
|
|
|
}
|
|
|
|
if ( _SoftKbd == NULL )
|
|
{
|
|
hr = E_FAIL;
|
|
return hr;
|
|
}
|
|
|
|
if ( fShow ) {
|
|
|
|
DWORD dwSoftLayout;
|
|
|
|
if ( _CurKbdType == KBDTYPE_STANDARD )
|
|
{
|
|
// Standard soft kbd was selected.
|
|
WORD prmlangid;
|
|
|
|
prmlangid = PRIMARYLANGID(_langid);
|
|
|
|
switch ( prmlangid ) {
|
|
|
|
case LANG_JAPANESE :
|
|
// Lang JPN is activated.
|
|
// select the standard layout to J 106-k.
|
|
_KbdStandard.dwSoftKbdLayout = SOFTKBD_JPN_STANDARD;
|
|
break;
|
|
|
|
case LANG_AZERI :
|
|
case LANG_BELARUSIAN :
|
|
case LANG_CHINESE :
|
|
case LANG_KOREAN :
|
|
case LANG_RUSSIAN :
|
|
case LANG_THAI :
|
|
case LANG_URDU :
|
|
case LANG_UZBEK :
|
|
_KbdStandard.dwSoftKbdLayout = SOFTKBD_US_STANDARD;
|
|
break;
|
|
|
|
case LANG_ENGLISH :
|
|
if ( SUBLANGID(_langid) != SUBLANG_ENGLISH_US )
|
|
_KbdStandard.dwSoftKbdLayout = SOFTKBD_EURO_STANDARD;
|
|
else
|
|
_KbdStandard.dwSoftKbdLayout = SOFTKBD_US_STANDARD;
|
|
break;
|
|
|
|
default :
|
|
_KbdStandard.dwSoftKbdLayout = SOFTKBD_EURO_STANDARD;
|
|
break;
|
|
}
|
|
|
|
// the current layout is standard layout.
|
|
// we need to set the correct standard layout id based on current lang profile.
|
|
|
|
dwSoftLayout = _KbdStandard.dwSoftKbdLayout;
|
|
_CurLayout = dwSoftLayout;
|
|
|
|
CHECKHR(_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
|
|
CHECKHR(_SoftKbd->SetKeyboardLabelText(GetKeyboardLayout(0)));
|
|
}
|
|
else if ( _CurKbdType == KBDTYPE_SYMBOL)
|
|
{
|
|
// This is symbol soft keyboard layout
|
|
//
|
|
DWORD dwCurLabel;
|
|
dwSoftLayout = _KbdSymbol.dwSoftKbdLayout;
|
|
dwCurLabel = _KbdSymbol.dwCurLabel;
|
|
CHECKHR(_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
|
|
CHECKHR(_SoftKbd->SetKeyboardLabelTextCombination(dwCurLabel));
|
|
|
|
}
|
|
|
|
// TIP is ON, so we need to show soft keyboard.
|
|
CHECKHR(_SoftKbd->ShowSoftKeyboard(TRUE));
|
|
}
|
|
else
|
|
{
|
|
// TIP is going to close.
|
|
// close the soft keyboard window also.
|
|
CHECKHR(_SoftKbd->ShowSoftKeyboard(FALSE));
|
|
}
|
|
|
|
CleanUp:
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _CompEventSinkCallback
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSoftkbdIMX::_CompEventSinkCallback(void *pv, REFGUID rguid)
|
|
{
|
|
CSoftkbdIMX *_this = (CSoftkbdIMX *)pv;
|
|
BOOL fOn;
|
|
HRESULT hr;
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
if ( IsEqualGUID(rguid, GUID_COMPARTMENT_HANDWRITING_OPENCLOSE) )
|
|
{
|
|
|
|
fOn = _this->GetSoftKBDOnOff( );
|
|
|
|
CHECKHR(_this->_ShowSoftKBDWindow(fOn));
|
|
|
|
//
|
|
// Open/Close status was updated, we need to update Langbar button's
|
|
// toggle state.
|
|
//
|
|
_this->_plbi->UpdateToggle();
|
|
|
|
}
|
|
|
|
else if ( IsEqualGUID(rguid, GUID_COMPARTMENT_SOFTKBD_KBDLAYOUT) )
|
|
{
|
|
|
|
DWORD dwSoftLayout;
|
|
|
|
if ( _this->_SoftKbd == NULL )
|
|
{
|
|
hr = E_FAIL;
|
|
return hr;
|
|
}
|
|
|
|
dwSoftLayout = _this->GetSoftKBDLayout( );
|
|
|
|
|
|
_this->_CurLayout = dwSoftLayout;
|
|
|
|
if ( dwSoftLayout == (_this->_KbdStandard).dwSoftKbdLayout )
|
|
{
|
|
// this is standard layout.
|
|
|
|
_this->_CurKbdType = KBDTYPE_STANDARD;
|
|
|
|
CHECKHR(_this->_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
|
|
|
|
CHECKHR(_this->_SoftKbd->SetKeyboardLabelText(GetKeyboardLayout(0)));
|
|
|
|
}
|
|
else if ( dwSoftLayout == (_this->_KbdSymbol).dwSoftKbdLayout )
|
|
{
|
|
// this is symbol layout.
|
|
|
|
DWORD dwCurLabel;
|
|
|
|
_this->_CurKbdType = KBDTYPE_SYMBOL;
|
|
|
|
dwCurLabel = (_this->_KbdSymbol).dwCurLabel;
|
|
|
|
CHECKHR(_this->_SoftKbd->SelectSoftKeyboard(dwSoftLayout));
|
|
|
|
CHECKHR(_this->_SoftKbd->SetKeyboardLabelTextCombination(dwCurLabel));
|
|
|
|
}
|
|
|
|
if ( _this->GetSoftKBDOnOff( ) )
|
|
CHECKHR(_this->_SoftKbd->ShowSoftKeyboard(TRUE));
|
|
|
|
|
|
}
|
|
|
|
_this->_UpdateUI();
|
|
|
|
CleanUp:
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _UpdateUI
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CSoftkbdIMX::_UpdateUI()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _MySetSelectionSimple
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CSoftkbdIMX::_MySetSelectionSimple(TfEditCookie ec, ITfContext *pic, ITfRange *range)
|
|
{
|
|
TF_SELECTION sel;
|
|
|
|
sel.range = range;
|
|
sel.style.ase = TF_AE_NONE;
|
|
sel.style.fInterimChar = FALSE;
|
|
|
|
range->Collapse(ec, TF_ANCHOR_END);
|
|
|
|
return pic->SetSelection(ec, 1, &sel);
|
|
}
|
|
|
|
HRESULT CSoftkbdIMX::_LsCallback(BOOL fChanged, LANGID langid, BOOL *pfAccept, void *pv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
GUID guidProfile;
|
|
LANGID lang;
|
|
|
|
TraceMsg(TF_GENERAL, "CSoftkbdIMX::_LsCallback is called, langid=%x fChanged=%d", langid, fChanged);
|
|
|
|
CSoftkbdIMX *_this = (CSoftkbdIMX *)pv;
|
|
|
|
if (!fChanged)
|
|
{
|
|
if ( pfAccept )
|
|
*pfAccept = TRUE;
|
|
return hr;
|
|
}
|
|
|
|
hr = _this->_pProfile->GetActiveLanguageProfile(CLSID_SoftkbdIMX, &lang, &guidProfile);
|
|
|
|
if ( hr == S_OK )
|
|
{
|
|
_this->_langid = lang;
|
|
|
|
if ( IsEqualGUID(guidProfile, c_guidProfile) )
|
|
{
|
|
// Standard soft kbd is selected.
|
|
TraceMsg(TF_GENERAL, "Standard Softkbd is selected");
|
|
_this->_CurKbdType = KBDTYPE_STANDARD;
|
|
}
|
|
else if ( IsEqualGUID(guidProfile, c_guidProfileSym) )
|
|
{
|
|
// This is symbol soft keyboard layout
|
|
//
|
|
TraceMsg(TF_GENERAL, "Symbol Softkbd is selected");
|
|
_this->_CurKbdType = KBDTYPE_SYMBOL;
|
|
}
|
|
|
|
if ( (_this->GetSoftKBDOnOff( ) == TRUE) )
|
|
_this->_ShowSoftKBDWindow(TRUE);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CSoftkbdIMX::_AlsCallback(REFCLSID clsid, REFGUID guidProfile, BOOL fActivated, void *pv)
|
|
{
|
|
|
|
HRESULT hr;
|
|
ITfInputProcessorProfiles *pProfile = NULL;
|
|
|
|
hr = S_OK;
|
|
|
|
CSoftkbdIMX *_this = (CSoftkbdIMX *)pv;
|
|
|
|
|
|
// if this is not for SoftKbdIMX TIP,
|
|
// we just ignore it.
|
|
|
|
if (IsEqualGUID(clsid, CLSID_SoftkbdIMX))
|
|
{
|
|
// if this is not for our registered profile guid, just ignore it.
|
|
|
|
if ( !IsEqualGUID(guidProfile, c_guidProfile) && !IsEqualGUID(guidProfile, c_guidProfileSym) )
|
|
return hr;
|
|
|
|
TraceMsg(TF_GENERAL, "CSoftkbdIMX::_AlsCallback is called for this tip fActivated=%d", fActivated);
|
|
|
|
if ( fActivated == FALSE )
|
|
{
|
|
if ( _this->GetSoftKBDOnOff( ) )
|
|
{
|
|
if ( _this->_SoftKbd != NULL )
|
|
(_this->_SoftKbd)->ShowSoftKeyboard(FALSE);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
if ( IsEqualGUID(guidProfile, c_guidProfile) )
|
|
{
|
|
// Standard soft kbd is selected.
|
|
|
|
TraceMsg(TF_GENERAL, "Standard Softkbd is selected");
|
|
|
|
_this->_CurKbdType = KBDTYPE_STANDARD;
|
|
|
|
}
|
|
|
|
else if ( IsEqualGUID(guidProfile, c_guidProfileSym) )
|
|
{
|
|
// This is symbol soft keyboard layout
|
|
//
|
|
|
|
TraceMsg(TF_GENERAL, "Symbol Softkbd is selected");
|
|
_this->_CurKbdType = KBDTYPE_SYMBOL;
|
|
|
|
}
|
|
|
|
if ( (_this->GetSoftKBDOnOff( ) == TRUE) )
|
|
_this->_ShowSoftKBDWindow(TRUE);
|
|
}
|
|
else if (IsEqualGUID(clsid, GUID_NULL))
|
|
{
|
|
// This is keyboard layout change without language change.
|
|
if ( _this->GetSoftKBDOnOff( ) && fActivated)
|
|
{
|
|
_this->_ShowSoftKBDWindow(fActivated);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|