📄 dxutguiime.cpp
字号:
nCharHit = nCharBodyHit + 1;
else
nCharHit = nCharBodyHit;
switch( GetPrimaryLanguage() )
{
case LANG_JAPANESE:
// For Japanese, there are two cases. If s_nFirstTargetConv is
// -1, the comp string hasn't been converted yet, and we use
// s_nCompCaret. For any other value of s_nFirstTargetConv,
// the string has been converted, so we use clause information.
if( s_nFirstTargetConv != -1 )
{
int nClauseClicked = 0;
while( (int)s_adwCompStringClause[nClauseClicked + 1] <= nCharBodyHit )
++nClauseClicked;
int nClauseSelected = 0;
while( (int)s_adwCompStringClause[nClauseSelected + 1] <= s_nFirstTargetConv )
++nClauseSelected;
BYTE nVirtKey = nClauseClicked > nClauseSelected ? VK_RIGHT : VK_LEFT;
int nSendCount = abs( nClauseClicked - nClauseSelected );
while( nSendCount-- > 0 )
SendKey( nVirtKey );
return true;
}
// Not converted case. Fall thru to Chinese case.
case LANG_CHINESE:
{
// For Chinese, use s_nCompCaret.
BYTE nVirtKey = nCharHit > (int)ImeUi_GetImeCursorChars() ? VK_RIGHT : VK_LEFT;
int nSendCount = abs( nCharHit - (int)ImeUi_GetImeCursorChars() );
while( nSendCount-- > 0 )
SendKey( nVirtKey );
break;
}
}
return true;
}
// Check if the click is on top of the candidate window
if( ImeUi_IsShowCandListWindow() && PtInRect( &s_CandList.rcCandidate, pt ) )
{
if( ImeUi_IsVerticalCand() )
{
// Vertical candidate window
// Compute the row the click is on
int nRow = ( pt.y - s_CandList.rcCandidate.top ) / pFont->nHeight;
if( nRow < (int)ImeUi_GetCandidateCount() )
{
// nRow is a valid entry.
// Now emulate keystrokes to select the candidate at this row.
switch( GetPrimaryLanguage() )
{
case LANG_CHINESE:
case LANG_KOREAN:
// For Chinese and Korean, simply send the number keystroke.
SendKey( (BYTE) ('0' + nRow + 1) );
break;
case LANG_JAPANESE:
// For Japanese, move the selection to the target row,
// then send Right, then send Left.
BYTE nVirtKey;
if( nRow > (int)ImeUi_GetCandidateSelection() )
nVirtKey = VK_DOWN;
else
nVirtKey = VK_UP;
int nNumToHit = abs( int( nRow - ImeUi_GetCandidateSelection() ) );
for( int nStrike = 0; nStrike < nNumToHit; ++nStrike )
SendKey( nVirtKey );
// Do this to close the candidate window without ending composition.
SendKey( VK_RIGHT );
SendKey( VK_LEFT );
break;
}
}
} else
{
// Horizontal candidate window
// Determine which the character the click has hit.
int nCharHit;
int nTrail;
s_CandList.HoriCand.XtoCP( pt.x - s_CandList.rcCandidate.left, &nCharHit, &nTrail );
// Determine which candidate string the character belongs to.
int nCandidate = ImeUi_GetCandidateCount() - 1;
int nEntryStart = 0;
for( UINT i = 0; i < ImeUi_GetCandidateCount(); ++i )
{
if( nCharHit >= nEntryStart )
{
// Haven't found it.
nEntryStart += lstrlenW( ImeUi_GetCandidate( i ) ) + 1; // plus space separator
} else
{
// Found it. This entry starts at the right side of the click point,
// so the char belongs to the previous entry.
nCandidate = i - 1;
break;
}
}
// Now emulate keystrokes to select the candidate entry.
switch( GetPrimaryLanguage() )
{
case LANG_CHINESE:
case LANG_KOREAN:
// For Chinese and Korean, simply send the number keystroke.
SendKey( (BYTE) ('0' + nCandidate + 1) );
break;
}
}
return true;
}
}
}
// If we didn't care for the msg, let the parent process it.
return CDXUTEditBox::HandleMouse( uMsg, pt, wParam, lParam );
}
//--------------------------------------------------------------------------------------
bool CDXUTIMEEditBox::MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
{
if( !m_bEnabled || !m_bVisible )
return false;
#if defined(DEBUG) || defined(_DEBUG)
// DXUT.cpp used to call CDXUTIMEEditBox::StaticMsgProc() so that, but now
// this is the application's responsiblity. To do this, call
// CDXUTDialogResourceManager::MsgProc() before calling this function.
assert( m_bIMEStaticMsgProcCalled && L"To fix, call CDXUTDialogResourceManager::MsgProc() first" );
#endif
switch (uMsg) {
case WM_DESTROY:
ImeUi_Uninitialize();
break;
}
bool trappedData;
bool *trapped = &trappedData;
*trapped = false;
if( !ImeUi_IsEnabled() )
return CDXUTEditBox::MsgProc( uMsg, wParam, lParam );
ImeUi_ProcessMessage( DXUTGetHWND(), uMsg, wParam, lParam, trapped);
if ( *trapped == false )
CDXUTEditBox::MsgProc( uMsg, wParam, lParam );
return *trapped;
}
//--------------------------------------------------------------------------------------
void CDXUTIMEEditBox::RenderCandidateReadingWindow( float fElapsedTime, bool bReading )
{
RECT rc;
UINT nNumEntries = bReading ? 4 : MAX_CANDLIST;
D3DCOLOR TextColor, TextBkColor, SelTextColor, SelBkColor;
int nX, nXFirst, nXComp;
m_Buffer.CPtoX( m_nCaret, FALSE, &nX );
m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nXFirst );
if( bReading )
{
TextColor = m_ReadingColor;
TextBkColor = m_ReadingWinColor;
SelTextColor = m_ReadingSelColor;
SelBkColor = m_ReadingSelBkColor;
} else
{
TextColor = m_CandidateColor;
TextBkColor = m_CandidateWinColor;
SelTextColor = m_CandidateSelColor;
SelBkColor = m_CandidateSelBkColor;
}
// For Japanese IME, align the window with the first target converted character.
// For all other IMEs, align with the caret. This is because the caret
// does not move for Japanese IME.
if ( GetLanguage() == MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL) && !GetImeId() )
nXComp = 0;
else
if( GetPrimaryLanguage() == LANG_JAPANESE )
s_CompString.CPtoX( s_nFirstTargetConv, FALSE, &nXComp );
else
s_CompString.CPtoX( ImeUi_GetImeCursorChars(), FALSE, &nXComp );
// Compute the size of the candidate window
int nWidthRequired = 0;
int nHeightRequired = 0;
int nSingleLineHeight = 0;
if( ( ImeUi_IsVerticalCand() && !bReading ) ||
( !ImeUi_IsHorizontalReading() && bReading ) )
{
// Vertical window
for( UINT i = 0; i < nNumEntries; ++i )
{
if( *(ImeUi_GetCandidate( i ) ) == L'\0' )
break;
SetRect( &rc, 0, 0, 0, 0 );
m_pDialog->CalcTextRect( ImeUi_GetCandidate( i ), m_Elements.GetAt( 1 ), &rc );
nWidthRequired = __max( nWidthRequired, rc.right - rc.left );
nSingleLineHeight = __max( nSingleLineHeight, rc.bottom - rc.top );
}
nHeightRequired = nSingleLineHeight * nNumEntries;
} else
{
// Horizontal window
SetRect( &rc, 0, 0, 0, 0 );
if( bReading )
m_pDialog->CalcTextRect( s_wszReadingString, m_Elements.GetAt( 1 ), &rc );
else
{
WCHAR wszCand[256] = L"";
s_CandList.nFirstSelected = 0;
s_CandList.nHoriSelectedLen = 0;
for( UINT i = 0; i < MAX_CANDLIST; ++i )
{
if( *ImeUi_GetCandidate(i) == L'\0' )
break;
WCHAR wszEntry[32];
StringCchPrintf( wszEntry, 32, L"%s ", ImeUi_GetCandidate(i) );
// If this is the selected entry, mark its char position.
if( ImeUi_GetCandidateSelection() == i )
{
s_CandList.nFirstSelected = lstrlen( wszCand );
s_CandList.nHoriSelectedLen = lstrlen( wszEntry ) - 1; // Minus space
}
StringCchCat( wszCand, 256, wszEntry );
}
wszCand[lstrlen(wszCand) - 1] = L'\0'; // Remove the last space
s_CandList.HoriCand.SetText( wszCand );
m_pDialog->CalcTextRect( s_CandList.HoriCand.GetBuffer(), m_Elements.GetAt( 1 ), &rc );
}
nWidthRequired = rc.right - rc.left;
nSingleLineHeight = nHeightRequired = rc.bottom - rc.top;
}
// Now that we have the dimension, calculate the location for the candidate window.
// We attempt to fit the window in this order:
// bottom, top, right, left.
bool bHasPosition = false;
// Bottom
SetRect( &rc, s_ptCompString.x + nXComp, s_ptCompString.y + m_rcText.bottom - m_rcText.top,
s_ptCompString.x + nXComp + nWidthRequired, s_ptCompString.y + m_rcText.bottom - m_rcText.top + nHeightRequired );
// if the right edge is cut off, move it left.
if( rc.right > m_pDialog->GetWidth() )
{
rc.left -= rc.right - m_pDialog->GetWidth();
rc.right = m_pDialog->GetWidth();
}
if( rc.bottom <= m_pDialog->GetHeight() )
bHasPosition = true;
// Top
if( !bHasPosition )
{
SetRect( &rc, s_ptCompString.x + nXComp, s_ptCompString.y - nHeightRequired,
s_ptCompString.x + nXComp + nWidthRequired, s_ptCompString.y );
// if the right edge is cut off, move it left.
if( rc.right > m_pDialog->GetWidth() )
{
rc.left -= rc.right - m_pDialog->GetWidth();
rc.right = m_pDialog->GetWidth();
}
if( rc.top >= 0 )
bHasPosition = true;
}
// Right
if( !bHasPosition )
{
int nXCompTrail;
s_CompString.CPtoX( ImeUi_GetImeCursorChars(), TRUE, &nXCompTrail );
SetRect( &rc, s_ptCompString.x + nXCompTrail, 0,
s_ptCompString.x + nXCompTrail + nWidthRequired, nHeightRequired );
if( rc.right <= m_pDialog->GetWidth() )
bHasPosition = true;
}
// Left
if( !bHasPosition )
{
SetRect( &rc, s_ptCompString.x + nXComp - nWidthRequired, 0,
s_ptCompString.x + nXComp, nHeightRequired );
if( rc.right >= 0 )
bHasPosition = true;
}
if( !bHasPosition )
{
// The dialog is too small for the candidate window.
// Fall back to render at 0, 0. Some part of the window
// will be cut off.
rc.left = 0;
rc.right = nWidthRequired;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -