x
Yes
No
Do you want to visit DriveHQ English website?
首页
产品服务
价格
免费试用
下载客户端
关于我们
云文件服务
|
云备份服务
|
FTP服务
|
企业邮箱服务
|
网站托管
|
客户端软件
云文件服务
云备份服务
FTP服务
企业级邮箱服务
网站托管
客户端软件
DXUTguiIME.cpp - Hosted on DriveHQ Cloud IT Platform
返回上层目录
上传
下载
共享
发布
新建文件夹
新建文件
复制
剪切
删除
粘贴
评论
升级服务
路径: \\game3dprogramming\materials\DarkPuzzle\DXUT\Optional\DXUTguiIME.cpp
旋转
特效
属性
历史版本
//-------------------------------------------------------------------------------------- // File: DXUTguiIME.cpp // // Copyright (c) Microsoft Corporation. All rights reserved. //-------------------------------------------------------------------------------------- #include "DXUT.h" #include "DXUTgui.h" #include "DXUTsettingsDlg.h" #include "DXUTres.h" #include "DXUTgui.h" #include "DXUTguiIME.h" #undef min // use __min instead #undef max // use __max instead #define DXUT_NEAR_BUTTON_DEPTH 0.6f //-------------------------------------------------------------------------------------- // CDXUTIMEEditBox class //-------------------------------------------------------------------------------------- // IME constants POINT CDXUTIMEEditBox::s_ptCompString; // Composition string position. Updated every frame. int CDXUTIMEEditBox::s_nFirstTargetConv; // Index of the first target converted char in comp string. If none, -1. CUniBuffer CDXUTIMEEditBox::s_CompString = CUniBuffer( 0 ); DWORD CDXUTIMEEditBox::s_adwCompStringClause[MAX_COMPSTRING_SIZE]; WCHAR CDXUTIMEEditBox::s_wszReadingString[32]; CDXUTIMEEditBox::CCandList CDXUTIMEEditBox::s_CandList; // Data relevant to the candidate list bool CDXUTIMEEditBox::s_bImeFlag = true; #if defined(DEBUG) || defined(_DEBUG) bool CDXUTIMEEditBox::m_bIMEStaticMsgProcCalled = false; #endif //-------------------------------------------------------------------------------------- HRESULT CDXUTIMEEditBox::CreateIMEEditBox( CDXUTDialog *pDialog, int ID, LPCWSTR strText, int x, int y, int width, int height, bool bIsDefault, CDXUTIMEEditBox** ppCreated ) { CDXUTIMEEditBox *pEditBox = new CDXUTIMEEditBox( pDialog ); if( ppCreated != NULL ) *ppCreated = pEditBox; if( pEditBox == NULL ) return E_OUTOFMEMORY; // Set the ID and position pEditBox->SetID( ID ); pEditBox->SetLocation( x, y ); pEditBox->SetSize( width, height ); pEditBox->m_bIsDefault = bIsDefault; if( strText ) pEditBox->SetText( strText ); return S_OK; } //-------------------------------------------------------------------------------------- void CDXUTIMEEditBox::InitDefaultElements( CDXUTDialog *pDialog ) { //------------------------------------- // CDXUTIMEEditBox //------------------------------------- CDXUTElement Element; RECT rcTexture; Element.SetFont( 0, D3DCOLOR_ARGB( 255, 0, 0, 0 ), DT_LEFT | DT_TOP ); // Assign the style SetRect( &rcTexture, 14, 90, 241, 113 ); Element.SetTexture( 0, &rcTexture ); pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 0, &Element ); SetRect( &rcTexture, 8, 82, 14, 90 ); Element.SetTexture( 0, &rcTexture ); pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 1, &Element ); SetRect( &rcTexture, 14, 82, 241, 90 ); Element.SetTexture( 0, &rcTexture ); pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 2, &Element ); SetRect( &rcTexture, 241, 82, 246, 90 ); Element.SetTexture( 0, &rcTexture ); pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 3, &Element ); SetRect( &rcTexture, 8, 90, 14, 113 ); Element.SetTexture( 0, &rcTexture ); pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 4, &Element ); SetRect( &rcTexture, 241, 90, 246, 113 ); Element.SetTexture( 0, &rcTexture ); pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 5, &Element ); SetRect( &rcTexture, 8, 113, 14, 121 ); Element.SetTexture( 0, &rcTexture ); pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 6, &Element ); SetRect( &rcTexture, 14, 113, 241, 121 ); Element.SetTexture( 0, &rcTexture ); pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 7, &Element ); SetRect( &rcTexture, 241, 113, 246, 121 ); Element.SetTexture( 0, &rcTexture ); pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 8, &Element ); // Element 9 for IME text, and indicator button SetRect( &rcTexture, 0, 0, 136, 54 ); Element.SetTexture( 0, &rcTexture ); Element.SetFont( 0, D3DCOLOR_ARGB( 255, 0, 0, 0 ), DT_CENTER | DT_VCENTER ); pDialog->SetDefaultElement( DXUT_CONTROL_IMEEDITBOX, 9, &Element ); } //-------------------------------------------------------------------------------------- CDXUTIMEEditBox::CDXUTIMEEditBox( CDXUTDialog *pDialog ) { m_Type = DXUT_CONTROL_IMEEDITBOX; m_pDialog = pDialog; m_nIndicatorWidth = 0; m_ReadingColor = D3DCOLOR_ARGB( 188, 255, 255, 255 ); m_ReadingWinColor = D3DCOLOR_ARGB( 128, 0, 0, 0 ); m_ReadingSelColor = D3DCOLOR_ARGB( 255, 255, 0, 0 ); m_ReadingSelBkColor = D3DCOLOR_ARGB( 128, 80, 80, 80 ); m_CandidateColor = D3DCOLOR_ARGB( 255, 200, 200, 200 ); m_CandidateWinColor = D3DCOLOR_ARGB( 128, 0, 0, 0 ); m_CandidateSelColor = D3DCOLOR_ARGB( 255, 255, 255, 255 ); m_CandidateSelBkColor = D3DCOLOR_ARGB( 128, 158, 158, 158 ); m_CompColor = D3DCOLOR_ARGB( 255, 200, 200, 255 ); m_CompWinColor = D3DCOLOR_ARGB( 198, 0, 0, 0 ); m_CompCaretColor = D3DCOLOR_ARGB( 255, 255, 255, 255 ); m_CompTargetColor = D3DCOLOR_ARGB( 255, 255, 255, 255 ); m_CompTargetBkColor = D3DCOLOR_ARGB( 255, 150, 150, 150 ); m_CompTargetNonColor = D3DCOLOR_ARGB( 255, 255, 255, 0 ); m_CompTargetNonBkColor = D3DCOLOR_ARGB( 255, 150, 150, 150 ); m_IndicatorImeColor = D3DCOLOR_ARGB( 255, 255, 255, 255 ); m_IndicatorEngColor = D3DCOLOR_ARGB( 255, 0, 0, 0 ); m_IndicatorBkColor = D3DCOLOR_ARGB( 255, 128, 128, 128 ); } //-------------------------------------------------------------------------------------- CDXUTIMEEditBox::~CDXUTIMEEditBox() { } //-------------------------------------------------------------------------------------- void CDXUTIMEEditBox::SendKey( BYTE nVirtKey ) { keybd_event( nVirtKey, 0, 0, 0 ); keybd_event( nVirtKey, 0, KEYEVENTF_KEYUP, 0 ); } //-------------------------------------------------------------------------------------- void CDXUTIMEEditBox::UpdateRects() { // Temporary adjust m_width so that CDXUTEditBox can compute // the correct rects for its rendering since we need to make space // for the indicator button int nWidth = m_width; m_width -= m_nIndicatorWidth + m_nBorder * 2; // Make room for the indicator button CDXUTEditBox::UpdateRects(); m_width = nWidth; // Restore // Compute the indicator button rectangle SetRect( &m_rcIndicator, m_rcBoundingBox.right, m_rcBoundingBox.top, m_x + m_width, m_rcBoundingBox.bottom ); // InflateRect( &m_rcIndicator, -m_nBorder, -m_nBorder ); m_rcBoundingBox.right = m_rcBoundingBox.left + m_width; } //-------------------------------------------------------------------------------------- // GetImeId( UINT uIndex ) // returns // returned value: // 0: In the following cases // - Non Chinese IME input locale // - Older Chinese IME // - Other error cases // // Othewise: // When uIndex is 0 (default) // bit 31-24: Major version // bit 23-16: Minor version // bit 15-0: Language ID // When uIndex is 1 // pVerFixedInfo->dwFileVersionLS // // Use IMEID_VER and IMEID_LANG macro to extract version and language information. // // We define the locale-invariant ID ourselves since it doesn't exist prior to WinXP // For more information, see the CompareString() reference. #define LCID_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT) //-------------------------------------------------------------------------------------- // Enable/disable the entire IME system. When disabled, the default IME handling // kicks in. void CDXUTIMEEditBox::EnableImeSystem( bool bEnable ) { ImeUi_EnableIme( bEnable ); } //-------------------------------------------------------------------------------------- // Resets the composition string. void CDXUTIMEEditBox::ResetCompositionString() { s_CompString.SetText( L"" ); } //-------------------------------------------------------------------------------------- // This function is used only briefly in CHT IME handling, // so accelerator isn't processed. void CDXUTIMEEditBox::PumpMessage() { MSG msg; while( PeekMessageW( &msg, NULL, 0, 0, PM_NOREMOVE ) ) { if( !GetMessageW( &msg, NULL, 0, 0 ) ) { PostQuitMessage( (int)msg.wParam ); return; } TranslateMessage( &msg ); DispatchMessageA( &msg ); } } //-------------------------------------------------------------------------------------- void CDXUTIMEEditBox::OnFocusIn() { ImeUi_EnableIme( s_bImeFlag ); CDXUTEditBox::OnFocusIn(); } //-------------------------------------------------------------------------------------- void CDXUTIMEEditBox::OnFocusOut() { ImeUi_FinalizeString(); ImeUi_EnableIme( false ); CDXUTEditBox::OnFocusOut(); } //-------------------------------------------------------------------------------------- bool CDXUTIMEEditBox::StaticMsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { if( !ImeUi_IsEnabled() ) return false; #if defined(DEBUG) || defined(_DEBUG) m_bIMEStaticMsgProcCalled = true; #endif switch( uMsg ) { case WM_INPUTLANGCHANGE: DXUTTRACE( L"WM_INPUTLANGCHANGE\n" ); { } return true; case WM_IME_SETCONTEXT: DXUTTRACE( L"WM_IME_SETCONTEXT\n" ); // // We don't want anything to display, so we have to clear this // lParam = 0; return false; // Handle WM_IME_STARTCOMPOSITION here since // we do not want the default IME handler to see // this when our fullscreen app is running. case WM_IME_STARTCOMPOSITION: DXUTTRACE( L"WM_IME_STARTCOMPOSITION\n" ); ResetCompositionString(); // Since the composition string has its own caret, we don't render // the edit control's own caret to avoid double carets on screen. s_bHideCaret = true; return true; case WM_IME_ENDCOMPOSITION: DXUTTRACE( L"WM_IME_ENDCOMPOSITION\n" ); s_bHideCaret = false; return false; case WM_IME_COMPOSITION: DXUTTRACE( L"WM_IME_COMPOSITION\n" ); return false; } return false; } //-------------------------------------------------------------------------------------- bool CDXUTIMEEditBox::HandleMouse( UINT uMsg, POINT pt, WPARAM wParam, LPARAM lParam ) { if( !m_bEnabled || !m_bVisible ) return false; switch( uMsg ) { case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: { DXUTFontNode* pFont = m_pDialog->GetFont( m_Elements.GetAt( 9 )->iFont ); // Check if this click is on top of the composition string int nCompStrWidth; s_CompString.CPtoX( s_CompString.GetTextSize() , FALSE, &nCompStrWidth ); if( s_ptCompString.x <= pt.x && s_ptCompString.y <= pt.y && s_ptCompString.x + nCompStrWidth > pt.x && s_ptCompString.y + pFont->nHeight > pt.y ) { int nCharBodyHit, nCharHit; int nTrail; // Determine the character clicked on. s_CompString.XtoCP( pt.x - s_ptCompString.x, &nCharBodyHit, &nTrail ); if( nTrail && nCharBodyHit < s_CompString.GetTextSize() ) 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; } // If we are rendering the candidate window, save the position // so that mouse clicks are checked properly. if( !bReading ) s_CandList.rcCandidate = rc; // Render the elements m_pDialog->DrawRect( &rc, TextBkColor ); if( ( ImeUi_IsVerticalCand() && !bReading ) || ( !ImeUi_IsHorizontalReading() && bReading ) ) { // Vertical candidate window for( UINT i = 0; i < nNumEntries; ++i ) { // Here we are rendering one line at a time rc.bottom = rc.top + nSingleLineHeight; // Use a different color for the selected string if( ImeUi_GetCandidateSelection() == i ) { m_pDialog->DrawRect( &rc, SelBkColor ); m_Elements.GetAt( 1 )->FontColor.Current = SelTextColor; } else m_Elements.GetAt( 1 )->FontColor.Current = TextColor; m_pDialog->DrawText( ImeUi_GetCandidate( i ), m_Elements.GetAt( 1 ), &rc ); rc.top += nSingleLineHeight; } } else { // Horizontal candidate window m_Elements.GetAt( 1 )->FontColor.Current = TextColor; if( bReading ) m_pDialog->DrawText( s_wszReadingString, m_Elements.GetAt( 1 ), &rc ); else m_pDialog->DrawText( s_CandList.HoriCand.GetBuffer(), m_Elements.GetAt( 1 ), &rc ); // Render the selected entry differently if( !bReading ) { int nXLeft, nXRight; s_CandList.HoriCand.CPtoX( s_CandList.nFirstSelected, FALSE, &nXLeft ); s_CandList.HoriCand.CPtoX( s_CandList.nFirstSelected + s_CandList.nHoriSelectedLen, FALSE, &nXRight ); rc.right = rc.left + nXRight; rc.left += nXLeft; m_pDialog->DrawRect( &rc, SelBkColor ); m_Elements.GetAt( 1 )->FontColor.Current = SelTextColor; m_pDialog->DrawText( s_CandList.HoriCand.GetBuffer() + s_CandList.nFirstSelected, m_Elements.GetAt( 1 ), &rc, false, s_CandList.nHoriSelectedLen ); } } } //-------------------------------------------------------------------------------------- void CDXUTIMEEditBox::RenderComposition( float fElapsedTime ) { s_CompString.SetText( ImeUi_GetCompositionString() ); RECT rcCaret = { 0, 0, 0, 0 }; int nX, nXFirst; m_Buffer.CPtoX( m_nCaret, FALSE, &nX ); m_Buffer.CPtoX( m_nFirstVisible, FALSE, &nXFirst ); CDXUTElement *pElement = m_Elements.GetAt( 1 ); // Get the required width RECT rc = { m_rcText.left + nX - nXFirst, m_rcText.top, m_rcText.left + nX - nXFirst, m_rcText.bottom }; m_pDialog->CalcTextRect( s_CompString.GetBuffer(), pElement, &rc ); // If the composition string is too long to fit within // the text area, move it to below the current line. // This matches the behavior of the default IME. if( rc.right > m_rcText.right ) OffsetRect( &rc, m_rcText.left - rc.left, rc.bottom - rc.top ); // Save the rectangle position for processing highlighted text. RECT rcFirst = rc; // Update s_ptCompString for RenderCandidateReadingWindow(). s_ptCompString.x = rc.left; s_ptCompString.y = rc.top; D3DCOLOR TextColor = m_CompColor; // Render the window and string. // If the string is too long, we must wrap the line. pElement->FontColor.Current = TextColor; const WCHAR *pwszComp = s_CompString.GetBuffer(); int nCharLeft = s_CompString.GetTextSize() ; for( ; ; ) { // Find the last character that can be drawn on the same line. int nLastInLine; int bTrail; s_CompString.XtoCP( m_rcText.right - rc.left, &nLastInLine, &bTrail ); int nNumCharToDraw = __min( nCharLeft, nLastInLine ); m_pDialog->CalcTextRect( pwszComp, pElement, &rc, nNumCharToDraw ); // Draw the background // For Korean IME, blink the composition window background as if it // is a cursor. if( GetPrimaryLanguage() == LANG_KOREAN ) { if( m_bCaretOn ) { m_pDialog->DrawRect( &rc, m_CompWinColor ); } else { // Not drawing composition string background. We // use the editbox's text color for composition // string text. TextColor = m_Elements.GetAt(0)->FontColor.States[DXUT_STATE_NORMAL]; } } else { // Non-Korean IME. Always draw composition background. m_pDialog->DrawRect( &rc, m_CompWinColor ); } // Draw the text pElement->FontColor.Current = TextColor; m_pDialog->DrawText( pwszComp, pElement, &rc, false, nNumCharToDraw ); // Advance pointer and counter nCharLeft -= nNumCharToDraw; pwszComp += nNumCharToDraw; if( nCharLeft <= 0 ) break; // Advance rectangle coordinates to beginning of next line OffsetRect( &rc, m_rcText.left - rc.left, rc.bottom - rc.top ); } // Load the rect for the first line again. rc = rcFirst; // Inspect each character in the comp string. // For target-converted and target-non-converted characters, // we display a different background color so they appear highlighted. int nCharFirst = 0; nXFirst = 0; s_nFirstTargetConv = -1; BYTE *pAttr; const WCHAR *pcComp; for( pcComp = s_CompString.GetBuffer(), pAttr = ImeUi_GetCompStringAttr(); *pcComp != L'\0'; ++pcComp, ++pAttr ) { D3DCOLOR bkColor; // Render a different background for this character int nXLeft, nXRight; s_CompString.CPtoX( int(pcComp - s_CompString.GetBuffer() ), FALSE, &nXLeft ); s_CompString.CPtoX( int(pcComp - s_CompString.GetBuffer() ), TRUE, &nXRight ); // Check if this character is off the right edge and should // be wrapped to the next line. if( nXRight - nXFirst > m_rcText.right - rc.left ) { // Advance rectangle coordinates to beginning of next line OffsetRect( &rc, m_rcText.left - rc.left, rc.bottom - rc.top ); // Update the line's first character information nCharFirst = int( pcComp - s_CompString.GetBuffer() ); s_CompString.CPtoX( nCharFirst, FALSE, &nXFirst ); } // If the caret is on this character, save the coordinates // for drawing the caret later. if( ImeUi_GetImeCursorChars() == (DWORD)(pcComp - s_CompString.GetBuffer() ) ) { rcCaret = rc; rcCaret.left += nXLeft - nXFirst - 1; rcCaret.right = rcCaret.left + 2; } // Set up color based on the character attribute if( *pAttr == ATTR_TARGET_CONVERTED ) { pElement->FontColor.Current = m_CompTargetColor; bkColor = m_CompTargetBkColor; } else if( *pAttr == ATTR_TARGET_NOTCONVERTED ) { pElement->FontColor.Current = m_CompTargetNonColor; bkColor = m_CompTargetNonBkColor; } else { continue; } RECT rcTarget = { rc.left + nXLeft - nXFirst, rc.top, rc.left + nXRight - nXFirst, rc.bottom }; m_pDialog->DrawRect( &rcTarget, bkColor ); m_pDialog->DrawText( pcComp, pElement, &rcTarget, false, 1 ); // Record the first target converted character's index if( -1 == s_nFirstTargetConv ) s_nFirstTargetConv = int(pAttr - ImeUi_GetCompStringAttr() ); } // Render the composition caret if( m_bCaretOn ) { // If the caret is at the very end, its position would not have // been computed in the above loop. We compute it here. if( ImeUi_GetImeCursorChars() == (DWORD)s_CompString.GetTextSize() ) { s_CompString.CPtoX( ImeUi_GetImeCursorChars(), FALSE, &nX ); rcCaret = rc; rcCaret.left += nX - nXFirst - 1; rcCaret.right = rcCaret.left + 2; } m_pDialog->DrawRect( &rcCaret, m_CompCaretColor ); } } //-------------------------------------------------------------------------------------- void CDXUTIMEEditBox::RenderIndicator( float fElapsedTime ) { CDXUTElement *pElement = m_Elements.GetAt( 9 ); pElement->TextureColor.Blend( DXUT_STATE_NORMAL, fElapsedTime ); m_pDialog->DrawSprite( pElement, &m_rcIndicator, DXUT_NEAR_BUTTON_DEPTH ); RECT rc = m_rcIndicator; InflateRect( &rc, -m_nSpacing, -m_nSpacing ); pElement->FontColor.Current = m_IndicatorImeColor; RECT rcCalc = { 0, 0, 0, 0 }; // If IME system is off, draw English indicator. WCHAR *pwszIndicator = ImeUi_IsEnabled() ? ImeUi_GetIndicatior() : L"En"; m_pDialog->CalcTextRect( pwszIndicator, pElement, &rcCalc ); m_pDialog->DrawText( pwszIndicator, pElement, &rc ); } //-------------------------------------------------------------------------------------- void CDXUTIMEEditBox::Render( float fElapsedTime ) { if( m_bVisible == false ) return; // If we have not computed the indicator symbol width, // do it. if( !m_nIndicatorWidth ) { RECT rc = { 0, 0, 0, 0 }; m_pDialog->CalcTextRect( L"En", m_Elements.GetAt( 9 ), &rc ); m_nIndicatorWidth = rc.right - rc.left; // Update the rectangles now that we have the indicator's width UpdateRects(); } // Let the parent render first (edit control) CDXUTEditBox::Render( fElapsedTime ); CDXUTElement* pElement = GetElement( 1 ); if( pElement ) { s_CompString.SetFontNode( m_pDialog->GetFont( pElement->iFont ) ); s_CandList.HoriCand.SetFontNode( m_pDialog->GetFont( pElement->iFont ) ); } // // Now render the IME elements // ImeUi_RenderUI(); if( m_bHasFocus ) { // Render the input locale indicator RenderIndicator( fElapsedTime ); // Display the composition string. // This method should also update s_ptCompString // for RenderCandidateReadingWindow. RenderComposition( fElapsedTime ); // Display the reading/candidate window. RenderCandidateReadingWindow() // uses s_ptCompString to position itself. s_ptCompString must have // been filled in by RenderComposition(). if( ImeUi_IsShowReadingWindow() ) // Reading window RenderCandidateReadingWindow( fElapsedTime, true ); else if( ImeUi_IsShowCandListWindow() ) // Candidate list window RenderCandidateReadingWindow( fElapsedTime, false ); } } //-------------------------------------------------------------------------------------- void CDXUTIMEEditBox::SetImeEnableFlag(bool bFlag) { s_bImeFlag = bFlag; } //-------------------------------------------------------------------------------------- void CDXUTIMEEditBox::Initialize( HWND hWnd ) { ImeUiCallback_DrawRect = NULL; ImeUiCallback_Malloc = malloc; ImeUiCallback_Free = free; ImeUiCallback_DrawFans = NULL; ImeUi_Initialize( hWnd ); s_CompString.SetBufferSize( MAX_COMPSTRING_SIZE ); ImeUi_EnableIme( true ); }
DXUTguiIME.cpp
网页地址
文件地址
上一页
6/29
下一页
下载
( 35 KB )
Comments
Total ratings:
0
Average rating:
无评论
of 10
Would you like to comment?
Join now
, or
Logon
if you are already a member.