DriveHQ Start Menu
Cloud Drive Mapping
Folder Sync
Cloud Backup
True Drop Box
FTP/SFTP Hosting
Group Account
DriveHQ Start Menu
Online File Server
My Storage
|
Manage Shares
|
Publishes
|
Drop Boxes
|
Group Account
WebDAV Drive Mapping
Cloud Drive Home
|
WebDAV Guide
|
Drive Mapping Tool
|
Drive Mapping URL
Complete Data Backup
Backup Guide
|
Online Backup Tool
|
Cloud-to-Cloud Backup
FTP, Email & Web Service
FTP Home
|
FTP Hosting FAQ
|
Email Hosting
|
EmailManager
|
Web Hosting
Help & Resources
About
|
Enterprise Service
|
Partnership
|
Comparisons
|
Support
Quick Links
Security and Privacy
Download Software
Service Manual
Use Cases
Group Account
Online Help
Blog
Contact
Cloud Surveillance
Sign Up
Login
Features
Business Features
Online File Server
FTP Hosting
Cloud Drive Mapping
Cloud File Backup
Email Backup & Hosting
Cloud File Sharing
Folder Synchronization
Group Management
True Drop Box
Full-text Search
AD Integration/SSO
Mobile Access
IP Camera & DVR Solution
More...
Personal Features
Personal Cloud Drive
Backup All Devices
Mobile APPs
Personal Web Hosting
Sub-Account (for Kids)
Home/PC/Kids Monitoring
More...
Software
DriveHQ Drive Mapping Tool
DriveHQ FileManager
DriveHQ Online Backup
DriveHQ Mobile Apps
Pricing
Business Plans & Pricing
Personal Plans & Pricing
Price Comparison with Others
Feature Comparison with Others
Install Mobile App
Sign up
Creating account...
Invalid character in username! Only 0-9, a-z, A-Z, _, -, . allowed.
Username is required!
Invalid email address!
E-mail is required!
Password is required!
Password is invalid!
Password and confirmation do not match.
Confirm password is required!
I accept
Membership Agreement
Please read the Membership Agreement and check "I accept"!
Free Quick Sign-up
Sign-up Page
Log in
Signing in...
Username or e-mail address is required!
Password is required!
Keep me logged in
Quick Login
Forgot Password
Up
Upload
Download
Share
Publish
New Folder
New File
Copy
Cut
Delete
Paste
Rate
Upgrade
Rotate
Effect
Edit
Slide
History
//-------------------------------------------------------------------------------------- // 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
Page URL
File URL
Prev
6/29
Next
Download
( 35 KB )
Note: The DriveHQ service banners will NOT be displayed if the file owner is a paid member.
Comments
Total ratings:
0
Average rating:
Not Rated
Would you like to comment?
Join DriveHQ
for a free account, or
Logon
if you are already a member.