First commit.
This commit is contained in:
commit
7b83802bb2
103 files changed
+19016
No files matched your search
+635
@@ -0,0 +1,635 @@
|
||||
// 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.
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
|
||||
#include "Private.h"
|
||||
#include "Globals.h"
|
||||
#include "EditSession.h"
|
||||
#include "SampleIME.h"
|
||||
#include "CandidateListUIPresenter.h"
|
||||
#include "CompositionProcessorEngine.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CSampleIME class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _IsRangeCovered
|
||||
//
|
||||
// Returns TRUE if pRangeTest is entirely contained within pRangeCover.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
BOOL CSampleIME::_IsRangeCovered(TfEditCookie ec, _In_ ITfRange *pRangeTest, _In_ ITfRange *pRangeCover)
|
||||
{
|
||||
LONG lResult = 0;;
|
||||
|
||||
if (FAILED(pRangeCover->CompareStart(ec, pRangeTest, TF_ANCHOR_START, &lResult))
|
||||
|| (lResult > 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (FAILED(pRangeCover->CompareEnd(ec, pRangeTest, TF_ANCHOR_END, &lResult))
|
||||
|| (lResult < 0))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _DeleteCandidateList
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
VOID CSampleIME::_DeleteCandidateList(BOOL isForce, _In_opt_ ITfContext *pContext)
|
||||
{
|
||||
isForce;pContext;
|
||||
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
pCompositionProcessorEngine->PurgeVirtualKey();
|
||||
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
_pCandidateListUIPresenter->_EndCandidateList();
|
||||
|
||||
_candidateMode = CANDIDATE_NONE;
|
||||
_isCandidateWithWildcard = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleComplete
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleComplete(TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
_DeleteCandidateList(FALSE, pContext);
|
||||
|
||||
// just terminate the composition
|
||||
_TerminateComposition(ec, pContext);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCancel
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCancel(TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
_RemoveDummyCompositionForComposing(ec, _pComposition);
|
||||
|
||||
_DeleteCandidateList(FALSE, pContext);
|
||||
|
||||
_TerminateComposition(ec, pContext);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionInput
|
||||
//
|
||||
// If the keystroke happens within a composition, eat the key and return S_OK.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionInput(TfEditCookie ec, _In_ ITfContext *pContext, WCHAR wch)
|
||||
{
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
TF_SELECTION tfSelection;
|
||||
ULONG fetched = 0;
|
||||
BOOL isCovered = TRUE;
|
||||
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
|
||||
if ((_pCandidateListUIPresenter != nullptr) && (_candidateMode != CANDIDATE_INCREMENTAL))
|
||||
{
|
||||
_HandleCompositionFinalize(ec, pContext, FALSE);
|
||||
}
|
||||
|
||||
// Start the new (std::nothrow) compositon if there is no composition.
|
||||
if (!_IsComposing())
|
||||
{
|
||||
_StartComposition(pContext);
|
||||
}
|
||||
|
||||
// first, test where a keystroke would go in the document if we did an insert
|
||||
if (pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched) != S_OK || fetched != 1)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// is the insertion point covered by a composition?
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
isCovered = _IsRangeCovered(ec, tfSelection.range, pRangeComposition);
|
||||
|
||||
pRangeComposition->Release();
|
||||
|
||||
if (!isCovered)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Add virtual key to composition processor engine
|
||||
pCompositionProcessorEngine->AddVirtualKey(wch);
|
||||
|
||||
_HandleCompositionInputWorker(pCompositionProcessorEngine, ec, pContext);
|
||||
|
||||
Exit:
|
||||
tfSelection.range->Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionInputWorker
|
||||
//
|
||||
// If the keystroke happens within a composition, eat the key and return S_OK.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionInputWorker(_In_ CCompositionProcessorEngine *pCompositionProcessorEngine, TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
CSampleImeArray<CStringRange> readingStrings;
|
||||
BOOL isWildcardIncluded = TRUE;
|
||||
|
||||
//
|
||||
// Get reading string from composition processor engine
|
||||
//
|
||||
pCompositionProcessorEngine->GetReadingStrings(&readingStrings, &isWildcardIncluded);
|
||||
|
||||
for (UINT index = 0; index < readingStrings.Count(); index++)
|
||||
{
|
||||
hr = _AddComposingAndChar(ec, pContext, readingStrings.GetAt(index));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Get candidate string from composition processor engine
|
||||
//
|
||||
CSampleImeArray<CCandidateListItem> candidateList;
|
||||
|
||||
pCompositionProcessorEngine->GetCandidateList(&candidateList, TRUE, FALSE);
|
||||
|
||||
if ((candidateList.Count()))
|
||||
{
|
||||
hr = _CreateAndStartCandidate(pCompositionProcessorEngine, ec, pContext);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_pCandidateListUIPresenter->_ClearList();
|
||||
_pCandidateListUIPresenter->_SetText(&candidateList, TRUE);
|
||||
}
|
||||
}
|
||||
else if (_pCandidateListUIPresenter)
|
||||
{
|
||||
_pCandidateListUIPresenter->_ClearList();
|
||||
}
|
||||
else if (readingStrings.Count() && isWildcardIncluded)
|
||||
{
|
||||
hr = _CreateAndStartCandidate(pCompositionProcessorEngine, ec, pContext);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_pCandidateListUIPresenter->_ClearList();
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _CreateAndStartCandidate
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_CreateAndStartCandidate(_In_ CCompositionProcessorEngine *pCompositionProcessorEngine, TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (((_candidateMode == CANDIDATE_PHRASE) && (_pCandidateListUIPresenter))
|
||||
|| ((_candidateMode == CANDIDATE_NONE) && (_pCandidateListUIPresenter)))
|
||||
{
|
||||
// Recreate candidate list
|
||||
_pCandidateListUIPresenter->_EndCandidateList();
|
||||
delete _pCandidateListUIPresenter;
|
||||
_pCandidateListUIPresenter = nullptr;
|
||||
|
||||
_candidateMode = CANDIDATE_NONE;
|
||||
_isCandidateWithWildcard = FALSE;
|
||||
}
|
||||
|
||||
if (_pCandidateListUIPresenter == nullptr)
|
||||
{
|
||||
_pCandidateListUIPresenter = new (std::nothrow) CCandidateListUIPresenter(this, Global::AtomCandidateWindow,
|
||||
CATEGORY_CANDIDATE,
|
||||
pCompositionProcessorEngine->GetCandidateListIndexRange(),
|
||||
FALSE);
|
||||
if (!_pCandidateListUIPresenter)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
_candidateMode = CANDIDATE_INCREMENTAL;
|
||||
_isCandidateWithWildcard = FALSE;
|
||||
|
||||
// we don't cache the document manager object. So get it from pContext.
|
||||
ITfDocumentMgr* pDocumentMgr = nullptr;
|
||||
if (SUCCEEDED(pContext->GetDocumentMgr(&pDocumentMgr)))
|
||||
{
|
||||
// get the composition range.
|
||||
ITfRange* pRange = nullptr;
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRange)))
|
||||
{
|
||||
hr = _pCandidateListUIPresenter->_StartCandidateList(_tfClientId, pDocumentMgr, pContext, ec, pRange, pCompositionProcessorEngine->GetCandidateWindowWidth());
|
||||
pRange->Release();
|
||||
}
|
||||
pDocumentMgr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionFinalize
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionFinalize(TfEditCookie ec, _In_ ITfContext *pContext, BOOL isCandidateList)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (isCandidateList && _pCandidateListUIPresenter)
|
||||
{
|
||||
// Finalize selected candidate string from CCandidateListUIPresenter
|
||||
DWORD_PTR candidateLen = 0;
|
||||
const WCHAR *pCandidateString = nullptr;
|
||||
|
||||
candidateLen = _pCandidateListUIPresenter->_GetSelectedCandidateString(&pCandidateString);
|
||||
|
||||
CStringRange candidateString;
|
||||
candidateString.Set(pCandidateString, candidateLen);
|
||||
|
||||
if (candidateLen)
|
||||
{
|
||||
// Finalize character
|
||||
hr = _AddCharAndFinalize(ec, pContext, &candidateString);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Finalize current text store strings
|
||||
if (_IsComposing())
|
||||
{
|
||||
ULONG fetched = 0;
|
||||
TF_SELECTION tfSelection;
|
||||
|
||||
if (FAILED(pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched)) || fetched != 1)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
if (_IsRangeCovered(ec, tfSelection.range, pRangeComposition))
|
||||
{
|
||||
_EndComposition(pContext);
|
||||
}
|
||||
|
||||
pRangeComposition->Release();
|
||||
}
|
||||
|
||||
tfSelection.range->Release();
|
||||
}
|
||||
}
|
||||
|
||||
_HandleCancel(ec, pContext);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionConvert
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionConvert(TfEditCookie ec, _In_ ITfContext *pContext, BOOL isWildcardSearch)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
CSampleImeArray<CCandidateListItem> candidateList;
|
||||
|
||||
//
|
||||
// Get candidate string from composition processor engine
|
||||
//
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
pCompositionProcessorEngine->GetCandidateList(&candidateList, FALSE, isWildcardSearch);
|
||||
|
||||
// If there is no candlidate listin the current reading string, we don't do anything. Just wait for
|
||||
// next char to be ready for the conversion with it.
|
||||
int nCount = candidateList.Count();
|
||||
if (nCount)
|
||||
{
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
_pCandidateListUIPresenter->_EndCandidateList();
|
||||
delete _pCandidateListUIPresenter;
|
||||
_pCandidateListUIPresenter = nullptr;
|
||||
|
||||
_candidateMode = CANDIDATE_NONE;
|
||||
_isCandidateWithWildcard = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// create an instance of the candidate list class.
|
||||
//
|
||||
if (_pCandidateListUIPresenter == nullptr)
|
||||
{
|
||||
_pCandidateListUIPresenter = new (std::nothrow) CCandidateListUIPresenter(this, Global::AtomCandidateWindow,
|
||||
CATEGORY_CANDIDATE,
|
||||
pCompositionProcessorEngine->GetCandidateListIndexRange(),
|
||||
FALSE);
|
||||
if (!_pCandidateListUIPresenter)
|
||||
{
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
_candidateMode = CANDIDATE_ORIGINAL;
|
||||
}
|
||||
|
||||
_isCandidateWithWildcard = isWildcardSearch;
|
||||
|
||||
// we don't cache the document manager object. So get it from pContext.
|
||||
ITfDocumentMgr* pDocumentMgr = nullptr;
|
||||
if (SUCCEEDED(pContext->GetDocumentMgr(&pDocumentMgr)))
|
||||
{
|
||||
// get the composition range.
|
||||
ITfRange* pRange = nullptr;
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRange)))
|
||||
{
|
||||
hr = _pCandidateListUIPresenter->_StartCandidateList(_tfClientId, pDocumentMgr, pContext, ec, pRange, pCompositionProcessorEngine->GetCandidateWindowWidth());
|
||||
pRange->Release();
|
||||
}
|
||||
pDocumentMgr->Release();
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_pCandidateListUIPresenter->_SetText(&candidateList, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionBackspace
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionBackspace(TfEditCookie ec, _In_ ITfContext *pContext)
|
||||
{
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
TF_SELECTION tfSelection;
|
||||
ULONG fetched = 0;
|
||||
BOOL isCovered = TRUE;
|
||||
|
||||
// Start the new (std::nothrow) compositon if there is no composition.
|
||||
if (!_IsComposing())
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// first, test where a keystroke would go in the document if we did an insert
|
||||
if (FAILED(pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched)) || fetched != 1)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// is the insertion point covered by a composition?
|
||||
if (SUCCEEDED(_pComposition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
isCovered = _IsRangeCovered(ec, tfSelection.range, pRangeComposition);
|
||||
|
||||
pRangeComposition->Release();
|
||||
|
||||
if (!isCovered)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Add virtual key to composition processor engine
|
||||
//
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
|
||||
DWORD_PTR vKeyLen = pCompositionProcessorEngine->GetVirtualKeyLength();
|
||||
|
||||
if (vKeyLen)
|
||||
{
|
||||
pCompositionProcessorEngine->RemoveVirtualKey(vKeyLen - 1);
|
||||
|
||||
if (pCompositionProcessorEngine->GetVirtualKeyLength())
|
||||
{
|
||||
_HandleCompositionInputWorker(pCompositionProcessorEngine, ec, pContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
_HandleCancel(ec, pContext);
|
||||
}
|
||||
}
|
||||
|
||||
Exit:
|
||||
tfSelection.range->Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionArrowKey
|
||||
//
|
||||
// Update the selection within a composition.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionArrowKey(TfEditCookie ec, _In_ ITfContext *pContext, KEYSTROKE_FUNCTION keyFunction)
|
||||
{
|
||||
ITfRange* pRangeComposition = nullptr;
|
||||
TF_SELECTION tfSelection;
|
||||
ULONG fetched = 0;
|
||||
|
||||
// get the selection
|
||||
if (FAILED(pContext->GetSelection(ec, TF_DEFAULT_SELECTION, 1, &tfSelection, &fetched))
|
||||
|| fetched != 1)
|
||||
{
|
||||
// no selection, eat the keystroke
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// get the composition range
|
||||
if (FAILED(_pComposition->GetRange(&pRangeComposition)))
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// For incremental candidate list
|
||||
if (_pCandidateListUIPresenter)
|
||||
{
|
||||
_pCandidateListUIPresenter->AdviseUIChangedByArrowKey(keyFunction);
|
||||
}
|
||||
|
||||
pContext->SetSelection(ec, 1, &tfSelection);
|
||||
|
||||
pRangeComposition->Release();
|
||||
|
||||
Exit:
|
||||
tfSelection.range->Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionPunctuation
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionPunctuation(TfEditCookie ec, _In_ ITfContext *pContext, WCHAR wch)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (_candidateMode != CANDIDATE_NONE && _pCandidateListUIPresenter)
|
||||
{
|
||||
DWORD_PTR candidateLen = 0;
|
||||
const WCHAR* pCandidateString = nullptr;
|
||||
|
||||
candidateLen = _pCandidateListUIPresenter->_GetSelectedCandidateString(&pCandidateString);
|
||||
|
||||
CStringRange candidateString;
|
||||
candidateString.Set(pCandidateString, candidateLen);
|
||||
|
||||
if (candidateLen)
|
||||
{
|
||||
_AddComposingAndChar(ec, pContext, &candidateString);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Get punctuation char from composition processor engine
|
||||
//
|
||||
CCompositionProcessorEngine* pCompositionProcessorEngine = nullptr;
|
||||
pCompositionProcessorEngine = _pCompositionProcessorEngine;
|
||||
|
||||
WCHAR punctuation = pCompositionProcessorEngine->GetPunctuation(wch);
|
||||
|
||||
CStringRange punctuationString;
|
||||
punctuationString.Set(&punctuation, 1);
|
||||
|
||||
// Finalize character
|
||||
hr = _AddCharAndFinalize(ec, pContext, &punctuationString);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
_HandleCancel(ec, pContext);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _HandleCompositionDoubleSingleByte
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_HandleCompositionDoubleSingleByte(TfEditCookie ec, _In_ ITfContext *pContext, WCHAR wch)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
WCHAR fullWidth = Global::FullWidthCharTable[wch - 0x20];
|
||||
|
||||
CStringRange fullWidthString;
|
||||
fullWidthString.Set(&fullWidth, 1);
|
||||
|
||||
// Finalize character
|
||||
hr = _AddCharAndFinalize(ec, pContext, &fullWidthString);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
_HandleCancel(ec, pContext);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//+---------------------------------------------------------------------------
|
||||
//
|
||||
// _InvokeKeyHandler
|
||||
//
|
||||
// This text service is interested in handling keystrokes to demonstrate the
|
||||
// use the compositions. Some apps will cancel compositions if they receive
|
||||
// keystrokes while a compositions is ongoing.
|
||||
//
|
||||
// param
|
||||
// [in] uCode - virtual key code of WM_KEYDOWN wParam
|
||||
// [in] dwFlags - WM_KEYDOWN lParam
|
||||
// [in] dwKeyFunction - Function regarding virtual key
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
HRESULT CSampleIME::_InvokeKeyHandler(_In_ ITfContext *pContext, UINT code, WCHAR wch, DWORD flags, _KEYSTROKE_STATE keyState)
|
||||
{
|
||||
flags;
|
||||
|
||||
CKeyHandlerEditSession* pEditSession = nullptr;
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
// we'll insert a char ourselves in place of this keystroke
|
||||
pEditSession = new (std::nothrow) CKeyHandlerEditSession(this, pContext, code, wch, keyState);
|
||||
if (pEditSession == nullptr)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Call CKeyHandlerEditSession::DoEditSession().
|
||||
//
|
||||
// Do not specify TF_ES_SYNC so edit session is not invoked on WinWord
|
||||
//
|
||||
hr = pContext->RequestEditSession(_tfClientId, pEditSession, TF_ES_ASYNCDONTCARE | TF_ES_READWRITE, &hr);
|
||||
|
||||
pEditSession->Release();
|
||||
|
||||
Exit:
|
||||
return hr;
|
||||
}
|
||||
Reference in new issue
Block a user