// IMN_CHANGECANDIDATE: BOOL CImeView::ChangeCandidate(LONG CandList) { LPCANDIDATELIST lpCandList = NULL; DWORD dwIndex; DWORD dwBufLen; LPSTR lpStr; DWORD i = 1; RECT rect; int max_width = 0; DWORD dwPreferNumPerPage; if (!Enter()) return FALSE; for (dwIndex = 0; dwIndex < MAX_LISTCAND; dwIndex++) { if (CandList & i) break; else i <<= 1; } if (dwIndex == MAX_LISTCAND) goto exit_changecand; if (!(dwBufLen = ImmGetCandidateList(m_hIMC, dwIndex, lpCandList, 0))) { goto exit_changecand; } delete m_CandList[dwIndex]; m_CandList[dwIndex] = lpCandList = (LPCANDIDATELIST)new char[dwBufLen]; ImmGetCandidateList(m_hIMC, dwIndex, lpCandList, dwBufLen); dwPreferNumPerPage = (!lpCandList->dwPageSize ) ? DEFAULT_CAND_NUM_PER_PAGE : lpCandList->dwPageSize; for( i = 0; i < lpCandList->dwCount; i++ ) { lpStr = (LPSTR)lpCandList + lpCandList->dwOffset[i]; max_width = (max_width < lstrlen(lpStr)) ? lstrlen(lpStr) : max_width; } ::GetWindowRect(m_hwndCand[dwIndex], (LPRECT) &rect); ::SetWindowPos(m_hwndCand[dwIndex], m_hWnd, rect.left, rect.top, (max_width + 3) * m_charWidth + 4, (int)(dwPreferNumPerPage) * m_charHeight + 5, SWP_NOZORDER | SWP_NOACTIVATE ); DisplayCandStrings(m_hwndCand[dwIndex], lpCandList); exit_changecand: Leave(); return TRUE; }
void Mint::OpenCandidateList(void) { // Candidate List ¾ò¾î³»±â HIMC hImc = ImmGetContext(GetInstance()->GetHWND()); if(hImc==NULL) return; m_nCandidateListSize = ImmGetCandidateList(hImc, 0, NULL, 0); if(m_pCandidateList!=NULL) delete[] m_pCandidateList; m_pCandidateList = new unsigned char[m_nCandidateListSize]; if(m_nCandidateListSize>0) { ImmGetCandidateList(hImc, 0, (LPCANDIDATELIST)m_pCandidateList, m_nCandidateListSize); } ImmReleaseContext(GetInstance()->GetHWND(), hImc); }
static bool handleCandidates(HWND hwnd) { /* Obtain IME context */ HIMC imc = ImmGetContext(hwnd); if (!imc) return false; /* Make sure there is at least one candidate list */ DWORD count = 0; DWORD len = ImmGetCandidateListCountW(imc, &count); if (!count) { ImmReleaseContext(hwnd, imc); return false; } candidateIMEWindow=hwnd; /* Read first candidate list */ CANDIDATELIST* list = (CANDIDATELIST*)malloc(len); ImmGetCandidateList(imc, 0, list, len); ImmReleaseContext(hwnd, imc); /* Determine candidates currently being shown */ DWORD pageEnd = list->dwPageStart + list->dwPageSize; DWORD selection=list->dwSelection-list->dwPageStart; if (list->dwPageSize == 0) { pageEnd = list->dwCount; } else if (pageEnd > list->dwCount) { pageEnd = list->dwCount; } /* Concatenate currently shown candidates into a string */ WCHAR* cand_str = (WCHAR*)malloc(len); WCHAR* ptr = cand_str; for (DWORD n = list->dwPageStart, count = 0; n < pageEnd; ++n) { DWORD offset = list->dwOffset[n]; WCHAR* cand = (WCHAR*)(((char*)list) + offset); size_t clen = wcslen(cand); if (!clen) continue; CopyMemory(ptr, cand, (clen + 1) * sizeof(WCHAR)); if ((n + 1) < pageEnd) ptr[clen] = '\n'; ptr += (clen + 1); ++count; } HKL kbd_layout = GetKeyboardLayout(0); WCHAR filename[MAX_PATH + 1]={0}; ImmGetIMEFileNameW(kbd_layout, filename, MAX_PATH); if(cand_str&&wcslen(cand_str)>0) { nvdaControllerInternal_inputCandidateListUpdate(cand_str,selection,filename); } /* Clean up */ free(cand_str); free(list); return (count > 0); }
bool CIme::OnWM_IME_NOTIFY( HWND hWnd, WPARAM wParam ){ HIMC hIMC; DWORD dwSize; DWORD dwConversion, dwSentence; switch( wParam ){ case IMN_SETCONVERSIONMODE://全角/半角,中/英文标点改变 hIMC = ImmGetContext( hWnd ); ImmGetConversionStatus( hIMC, &dwConversion, &dwSentence ); m_bImeSharp = ( dwConversion & IME_CMODE_FULLSHAPE )? true : false; m_bImeSymbol = ( dwConversion & IME_CMODE_SYMBOL )? true : false; ImmReleaseContext( hWnd, hIMC ); break; case IMN_OPENCANDIDATE://进入选字状态 case IMN_CHANGECANDIDATE://选字表翻页 hIMC = ImmGetContext( hWnd ); if( m_lpCandList ){ GlobalFree( (HANDLE)m_lpCandList ); m_lpCandList = NULL; }//释放以前的选字表 if( dwSize = ImmGetCandidateList( hIMC, 0, NULL, 0 )){ m_lpCandList = (LPCANDIDATELIST)GlobalAlloc( GPTR, dwSize ); if( m_lpCandList ) ImmGetCandidateList( hIMC, 0, m_lpCandList, dwSize ); }//得到新的选字表 ImmReleaseContext( hWnd, hIMC ); if( m_lpCandList )ConvertCandList( m_lpCandList, m_szCandList );//选字表整理成串 break; case IMN_CLOSECANDIDATE://关闭选字表 if( m_lpCandList ){ GlobalFree( (HANDLE)m_lpCandList ); m_lpCandList = NULL; }//释放 m_szCandList[ 0 ] = 0; break; } return true;//总是返回true,防止ime窗口打开 }
// IMN_OPENCANDIDATE: BOOL CImeView::OpenCandidate(LONG lParam) { LPCANDIDATELIST lpCandList = NULL; // Storage for LP to candidate list. DWORD dwBufLen; // Storage for candidate strings. LPSTR lpStr; // Storage for LP to a string. int max_width = 0; // Storage for width of listCand int CurNumCandList = 0; // Storage for number of cand. lists. DWORD dwPreferNumPerPage; // Storage for PreferNumPerPage // POINT point; // Storage for caret position. if (!Enter()) return FALSE; // SetWindowText(hwnd, (LPSTR)TITLE_CAND); for (int i = 0; i < MAX_LISTCAND; i++ ) { if (m_hwndCand[i]) CurNumCandList++; } for (int index = 0; index < MAX_LISTCAND; index++ ) { if (lParam & (1 << index)) { if (!(dwBufLen = ImmGetCandidateList(m_hIMC, index, lpCandList, 0))) goto exit_opencand; if( !(m_CandList[index] = (LPCANDIDATELIST)new char[dwBufLen])) goto exit_opencand; lpCandList = m_CandList[index]; ImmGetCandidateList(m_hIMC, index, lpCandList, dwBufLen); POINT pt ; GetCaretPos(&pt); ClientToScreen(m_hWnd,&pt); dwPreferNumPerPage = ( !lpCandList->dwPageSize ) ? DEFAULT_CAND_NUM_PER_PAGE : lpCandList->dwPageSize; // get the longest string length for (int i = 0; i < (int)lpCandList->dwCount; i++ ) { lpStr = (LPSTR)lpCandList + lpCandList->dwOffset[i]; max_width = (max_width < lstrlen(lpStr)) ? lstrlen(lpStr) : max_width; } m_hwndCand[index] = CreateWindow( "HanjaCandidate", "CandWindow", WS_BORDER | WS_POPUP | WS_DISABLED, CurNumCandList * m_charWidth + pt.x, pt.y + m_charHeight + 2, (max_width + 3) * m_charWidth + 4, (int)dwPreferNumPerPage * m_charHeight + 5, m_hWnd, (HMENU)NULL, (HINSTANCE)GetWindowLong(m_hWnd, GWL_HINSTANCE ), (LPVOID)NULL ); if (m_hwndCand[index] == NULL) { delete m_CandList[index]; m_CandList[index] = NULL; goto exit_opencand; } SetWindowLong(m_hwndCand[index], 0, (LONG)this); ::ShowWindow(m_hwndCand[index], SW_SHOWNOACTIVATE); DisplayCandStrings(m_hwndCand[index], lpCandList); CurNumCandList++; } } m_nState |= IME_IN_CHOSECAND; exit_opencand: Leave(); return TRUE; }
//********************************************************************** // // void ImeUIChangeCandidate() // // This handles WM_IME_NOTIFY message with wParam = IMN_CHANGECANDIDATE. // //********************************************************************** void ImeUIChangeCandidate( HWND hwnd, LPARAM CandList ) { HIMC hIMC; LPCANDIDATELIST lpCandList = NULL; DWORD dwIndex; DWORD bufLen; LPSTR lpStr; DWORD i; RECT rect = {0}; int width = 0; DWORD dwPreferNumPerPage; // // If fail to get input context, do nothing. // if ( !( hIMC = ImmGetContext( hwnd ) ) ) return; // // Determine which candidate list should be updated. // for ( dwIndex = 0; dwIndex < MAX_LISTCAND; dwIndex++ ) if ( CandList & ( 1 << dwIndex ) ) break; // // If dwIndex == MAX_LISTCAND, then something wrong, do nothing. // if ( dwIndex == MAX_LISTCAND ) return; // // Determines how much memory space should be allocated to read in the // corresponding candidate list. // if ( !( bufLen = ImmGetCandidateList( hIMC, dwIndex, lpCandList, 0 ) ) ) goto exit2; // // Relocate memory space. // if ( !( gImeUIData.hListCandMem[ dwIndex ] = GlobalReAlloc( gImeUIData.hListCandMem[ dwIndex ], (int)bufLen, LPTR ) ) ) { goto exit2; } if ( !( lpStr = (LPSTR)GlobalLock( gImeUIData.hListCandMem[ dwIndex ] ) ) ) { GlobalFree( gImeUIData.hListCandMem[ dwIndex ] ); gImeUIData.hListCandMem[ dwIndex ] = NULL; goto exit2; } lpCandList = (LPCANDIDATELIST) lpStr; // // Reads in the corresponding candidate list. // ImmGetCandidateList( hIMC, dwIndex, lpCandList, bufLen ); // // Determines how many candidate strings per page. // dwPreferNumPerPage = ( !lpCandList->dwPageSize ) ? DEFAULT_CAND_NUM_PER_PAGE : lpCandList->dwPageSize; // // Determining maximum character length the list box // will display by loopping through all candidate strings. // for( i = 0; i < lpCandList->dwCount; i++ ) { // // Get the pointer to i-th candidate string. // lpStr = (LPSTR)lpCandList + lpCandList->dwOffset[ i ]; width = ( width < lstrlen( lpStr ) ) ? lstrlen( lpStr ) : width; } GetWindowRect( gImeUIData.hListCand[ dwIndex ] , &rect); SetWindowPos( gImeUIData.hListCand[ dwIndex ], hwnd, rect.left, rect.top, ( width ) * cxMetrics + 10, (int)(dwPreferNumPerPage) * cyMetrics + 5, SWP_NOZORDER | SWP_NOACTIVATE ); DisplayCandStrings( gImeUIData.hListCand[ dwIndex ], lpCandList ); GlobalUnlock( gImeUIData.hListCandMem[ dwIndex ] ); exit2: return; }
//********************************************************************** // // void ImeUIOpenCandidate() // // This handles WM_IME_NOTIFY message with wParam = IMN_OPENCANDIDATE. // //********************************************************************** void ImeUIOpenCandidate( HWND hwnd, LPARAM CandList ) { HIMC hIMC; // Input context handle. LPCANDIDATELIST lpCandList; // Storage for LP to candidate list. CANDIDATELIST tempCandList; // Storage for LP to candidate list. DWORD bufLen; // Storage for candidate strings. LPSTR lpStr; // Storage for LP to a string. DWORD dwIndex; // Storage for index of ListCand array DWORD i; // Loop count. int width = 0; // Storage for width of listCand int CurNumCandList = 0; // Storage for number of cand. lists. DWORD dwPreferNumPerPage; // Storage for PreferNumPerPage POINT point; // Storage for caret position. // // If fail to get input context handle, do nothing. // if ( ! (hIMC = ImmGetContext( hwnd ) ) ) return; // // Change caption title to DBCS candidate mode. // SetWindowText( hwnd, szSteCandTitle ); // // Find out how many candidate windows have already been opened. // for( i = 0; i < MAX_LISTCAND; i++ ) { if ( gImeUIData.hListCand[ i ] ) { CurNumCandList++; } } // // Check which candidate lists should be displayed by loopping // through all possible candidate lists. // for( dwIndex = 0; dwIndex < MAX_LISTCAND ; dwIndex ++ ) { if ( CandList & ( 1 << dwIndex ) ) { // // The dwIndex-th candidate list contains candidate strings. // So here we want to display them. // // // Determines how musch memory space should be allocated to // read in the corresponding candidate list . // if ( ! ( bufLen = ImmGetCandidateList( hIMC, dwIndex, &tempCandList, 0 ) ) ) goto exit2; // // Allocate memory space. // if( !( gImeUIData.hListCandMem[ dwIndex ] = GlobalAlloc( LPTR, (int)bufLen ) ) ) goto exit2; if( !( lpStr = (LPSTR)GlobalLock( gImeUIData.hListCandMem[ dwIndex ] ) ) ) { GlobalFree( gImeUIData.hListCandMem[ dwIndex ] ); gImeUIData.hListCandMem[ dwIndex ] = NULL; goto exit2; } lpCandList = (LPCANDIDATELIST) lpStr; // // Reads in the corresponding candidate list. // ImmGetCandidateList( hIMC, dwIndex, lpCandList, bufLen ); // // Get current caret position. // GetCaretPos( (POINT *)&point ); ClientToScreen( hwnd, &point ); // // Determines how many candidate strings per page. // dwPreferNumPerPage = ( !lpCandList->dwPageSize ) ? DEFAULT_CAND_NUM_PER_PAGE : lpCandList->dwPageSize; // // Determining maximum character length the list box // will display by loopping through all candidate strings. // for( i = 0; i < lpCandList->dwCount; i++ ) { // // Get the pointer to i-th candidate string. // lpStr = (LPSTR)lpCandList + lpCandList->dwOffset[ i ]; width = ( width < lstrlen( lpStr ) ) ? lstrlen( lpStr ) : width; } // // Create a candidate window for the candidate list. // gImeUIData.hListCand[ dwIndex ] = CreateWindow( szCandClass, NULL, WS_BORDER | WS_POPUP | WS_DISABLED, CurNumCandList * X_INDENT + point.x, CurNumCandList * Y_INDENT + point.y + cyMetrics, ( width ) * cxMetrics + 10, (int)(dwPreferNumPerPage) * cyMetrics + 5, hwnd, NULL, (HINSTANCE)GetWindowLongPtr( hwnd, GWLP_HINSTANCE ), NULL ); // // If fail to create the candidate window then do nothing. // if ( gImeUIData.hListCand[ dwIndex ] < 0 ) { GlobalUnlock( gImeUIData.hListCandMem[ dwIndex ] ); GlobalFree( gImeUIData.hListCandMem[ dwIndex ] ); goto exit2; } // // Show candidate window. // ShowWindow( gImeUIData.hListCand[ dwIndex ], SW_SHOWNOACTIVATE ); // // Display candidate strings. // DisplayCandStrings( gImeUIData.hListCand[ dwIndex ], lpCandList ); GlobalUnlock( gImeUIData.hListCandMem[ dwIndex ] ); CurNumCandList++; } } // // Reset IME state. // gImeUIData.ImeState |= IME_IN_CHOSECAND; exit2: ImmReleaseContext( hwnd, hIMC ); }
LRESULT HandleNotify(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HIMC hIMC = NULL; BOOL fOpen = FALSE; DWORD dwConvMode, dwSentMode; switch (wParam) { case IMN_OPENSTATUSWINDOW: /* fall-through */ case IMN_CLOSESTATUSWINDOW: break; case IMN_SETOPENSTATUS: SetStatusItems(hWnd); hIMC = ImmGetContext(hWnd); fOpen = ImmGetOpenStatus(hIMC); UpdateShowOpenStatusButton(fOpen); ImmReleaseContext(hWnd,hIMC); break; case IMN_SETCONVERSIONMODE: hIMC = ImmGetContext(hWnd); fOpen = ImmGetOpenStatus(hIMC); ImmGetConversionStatus(hIMC,&dwConvMode,&dwSentMode); if (fOpen) { SetConvModeParts(dwConvMode); UpdateModeButton(dwConvMode); } else { ClearConvModeParts(); } ImmReleaseContext(hWnd,hIMC); break; case IMN_OPENCANDIDATE: if (!fShowCand || (lParam != 0x01)) { if (fdwProperty & IME_PROP_SPECIAL_UI) { // Normally, we only need to set the composition window // position for a special UI IME } else if (fdwProperty & IME_PROP_AT_CARET) { CANDIDATEFORM cdf; HIMC hIMC; hIMC = ImmGetContext(hWnd); cdf.dwIndex = 0; cdf.dwStyle = CFS_CANDIDATEPOS; cdf.ptCurrentPos.x = ptImeUIPos.x; cdf.ptCurrentPos.y = ptImeUIPos.y; ImmSetCandidateWindow(hIMC,&cdf); ImmReleaseContext(hWnd,hIMC); } else { // Normally, we only need to set the composition window // position for a near caret IME } return (DefWindowProc(hWnd, message, wParam, lParam)); } case IMN_CHANGECANDIDATE: #ifdef _DEBUG { TCHAR szDev[80]; DWORD dwSize; LPCANDIDATELIST lpC; hIMC = ImmGetContext(hWnd); if (dwSize = ImmGetCandidateList(hIMC,0x0,NULL,0)) { lpC = (LPCANDIDATELIST)GlobalAlloc(GPTR,dwSize); ImmGetCandidateList(hIMC,0x0,lpC,dwSize); OutputDebugString(TEXT("DumpCandList!!!\r\n")); StringCchPrintf((LPTSTR)szDev,ARRAYSIZE(szDev),TEXT("dwCount %d\r\n"),lpC->dwCount); OutputDebugString((LPTSTR)szDev); StringCchPrintf((LPTSTR)szDev,ARRAYSIZE(szDev),TEXT("dwSelection %d\r\n"),lpC->dwSelection); OutputDebugString((LPTSTR)szDev); StringCchPrintf((LPTSTR)szDev,ARRAYSIZE(szDev),TEXT("dwPageStart %d\r\n"),lpC->dwPageStart); OutputDebugString((LPTSTR)szDev); StringCchPrintf((LPTSTR)szDev,ARRAYSIZE(szDev),TEXT("dwPageSize %d\r\n"),lpC->dwPageSize); OutputDebugString((LPTSTR)szDev); GlobalFree((HANDLE)lpC); } } #endif if (fShowCand && (lParam == 0x01)) { DWORD dwSize; if (!lpCandList) lpCandList = (LPCANDIDATELIST)GlobalAlloc(GPTR,sizeof(CANDIDATELIST)); hIMC = ImmGetContext(hWnd); if (dwSize = ImmGetCandidateList(hIMC,0x0,NULL,0)) { GlobalFree((HANDLE)lpCandList); lpCandList = (LPCANDIDATELIST)GlobalAlloc(GPTR,dwSize); ImmGetCandidateList(hIMC,0x0,lpCandList,dwSize); } else { memset(lpCandList, 0, sizeof(CANDIDATELIST)); } InvalidateRect(hWndCandList,NULL,TRUE); UpdateWindow(hWndCandList); ImmReleaseContext(hWnd,hIMC); } else { return (DefWindowProc(hWnd, message, wParam, lParam)); } break; case IMN_CLOSECANDIDATE: if (fShowCand && (lParam == 0x01)) { if (!lpCandList) { lpCandList = (LPCANDIDATELIST)GlobalAlloc(GPTR,sizeof(CANDIDATELIST)); } memset(lpCandList, 0, sizeof(CANDIDATELIST)); InvalidateRect(hWndCandList,NULL,TRUE); UpdateWindow(hWndCandList); } else { return (DefWindowProc(hWnd, message, wParam, lParam)); } break; default: return (DefWindowProc(hWnd, message, wParam, lParam)); } return 0; }
LRESULT CALLBACK g_NewProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { if(!g_mgui_candraw) return CallWindowProc(g_OldProc, hWnd, message, wParam, lParam); switch (message) { case WM_CHAR: { char *pText = MGUI_FindFocusTextEntryText(); if (pText) { if (wParam == VK_BACK) { int len = strlen(pText); if (pText[len - 1] < 0) pText[len - 2] = '\0'; else pText[len - 1] = '\0'; } else if(wParam != VK_RETURN) { int len = strlen(pText); pText[len] = wParam; pText[len + 1] = '\0'; } else { MGUI_SetFocusTextEntryDisabled(); } return 1; } break; } case WM_IME_CHAR: { char *pText = MGUI_FindFocusTextEntryText(); if (pText) { char buf[3]; buf[0] = wParam >> 8; buf[1] = (byte)wParam; buf[2] = '\0'; strcat(pText, buf); return 1; } break; } case WM_IME_NOTIFY: { HIMC hImc = ImmGetContext(hWnd); if(!hImc) break; if(wParam == IMN_CHANGECANDIDATE) { DWORD dwSize; dwSize = ImmGetCandidateList(hImc,0,NULL,0); if(dwSize > 0) { CandidateList = (LPCANDIDATELIST)GlobalAlloc( GPTR, dwSize ); g_bDrawIme = true; ImmGetCandidateList(hImc,0,CandidateList,dwSize); } else memset(CandidateList,0,sizeof(CandidateList)); } else if(wParam == IMN_CLOSECANDIDATE) { g_bDrawIme = false; } ImmReleaseContext( hWnd, hImc ); } } return CallWindowProc(g_OldProc, hWnd, message, wParam, lParam); }
LRESULT HandleConvertCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) { HIMC hIMC = ImmGetContext(hWndCompStr); DWORD dwSel; DWORD dwSize; LPCANDIDATELIST lpCL = NULL; switch(wParam) { case IDM_CONVERT: ImmNotifyIME(hIMC,NI_COMPOSITIONSTR,CPS_CONVERT,0); break; case IDM_CANCEL: ImmNotifyIME(hIMC,NI_COMPOSITIONSTR,CPS_CANCEL,0); break; case IDM_REVERT: ImmNotifyIME(hIMC,NI_COMPOSITIONSTR,CPS_REVERT,0); break; case IDM_COMPLETE: ImmNotifyIME(hIMC,NI_COMPOSITIONSTR,CPS_COMPLETE,0); break; case IDM_OPENCAND: ImmNotifyIME(hIMC,NI_OPENCANDIDATE,0,0); break; case IDM_CLOSECAND: ImmNotifyIME(hIMC,NI_CLOSECANDIDATE,0,0); break; case IDM_NEXTCAND: /* fall-through */ case IDM_PREVCAND: if (dwSize = ImmGetCandidateList(hIMC,0x0,NULL,0)) { lpCL = (LPCANDIDATELIST)GlobalAlloc(GPTR,dwSize); ImmGetCandidateList(hIMC,0x0,lpCL,dwSize); dwSel = lpCL->dwSelection; if (wParam == IDM_NEXTCAND) { if (++dwSel >= lpCL->dwCount) { dwSel = 0; } } else { if (dwSel) { dwSel--; } else { dwSel = lpCL->dwCount - 1; } } GlobalFree((HANDLE)lpCL); ImmNotifyIME(hIMC,NI_SELECTCANDIDATESTR,0,dwSel); } break; } ImmReleaseContext(hWndCompStr,hIMC); return 1; }