Home » U++ Library support » U++ Libraries and TheIDE: i18n, Unicode and Internationalization » Japanese IME test code
Japanese IME test code [message #15099] |
Mon, 31 March 2008 09:58  |
mobilehunter
Messages: 87 Registered: November 2006
|
Member |
|
|
Hope Mirek and other can check these code
case WM_IME_STARTCOMPOSITION:
{
HWND hwnd =GetHWND();
POINT pt;
GetCaretPos(&pt);// I don't know the properway to get this in UPP way.
HIMC hIMC = ImmGetContext(hwnd);
COMPOSITIONFORM cf;
/*These lines up to us to make ime font match to current font, or just the font size.
FontInfo fi = Draw::GetStdFont().Info();
LOGFONT lf;
HFONT hfont = fi.GetHFONT(); //i'm sorry to add this function manually to Draw.h, since i don't know how to get HFONT
GetObject(hfont, sizeof(LOGFONT), &lf);
ImmSetCompositionFont(hIMC, &lf);
cf.dwStyle = CFS_POINT;
cf.ptCurrentPos.x = pt.x;
cf.ptCurrentPos.y = pt.y;
ImmSetCompositionWindow(hIMC, &cf);
ImmReleaseContext(hwnd, hIMC);
}
break;
Above code will make IME window position start at current caret position.
Please fix above codes, since i don't have deep understanding of UPP codes.
Test with GUI17a sample and UWord
[Updated on: Mon, 31 March 2008 10:00] Report message to a moderator
|
|
|
Re: Japanese IME test code [message #15163 is a reply to message #15099] |
Sun, 06 April 2008 08:14   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
mobilehunter wrote on Mon, 31 March 2008 03:58 | Hope Mirek and other can check these code
case WM_IME_STARTCOMPOSITION:
{
HWND hwnd =GetHWND();
POINT pt;
GetCaretPos(&pt);// I don't know the properway to get this in UPP way.
HIMC hIMC = ImmGetContext(hwnd);
COMPOSITIONFORM cf;
/*These lines up to us to make ime font match to current font, or just the font size.
FontInfo fi = Draw::GetStdFont().Info();
LOGFONT lf;
HFONT hfont = fi.GetHFONT(); //i'm sorry to add this function manually to Draw.h, since i don't know how to get HFONT
GetObject(hfont, sizeof(LOGFONT), &lf);
ImmSetCompositionFont(hIMC, &lf);
cf.dwStyle = CFS_POINT;
cf.ptCurrentPos.x = pt.x;
cf.ptCurrentPos.y = pt.y;
ImmSetCompositionWindow(hIMC, &cf);
ImmReleaseContext(hwnd, hIMC);
}
break;
Above code will make IME window position start at current caret position.
Please fix above codes, since i don't have deep understanding of UPP codes.
Test with GUI17a sample and UWord
|
Looks OK to me, but I cannot check it 
If this gets approval from any other CJK user, I will paste it in gladly 
Mirek
|
|
|
Re: Japanese IME test code [message #15170 is a reply to message #15163] |
Mon, 07 April 2008 03:10   |
mobilehunter
Messages: 87 Registered: November 2006
|
Member |
|
|
Hi Mirek,
Thanks for the reply.
I change the code for displaying the IME window to controls such as RichEdit and EditField, since as my understanding those controls know their font and caret position better. And add a virtual function DisplayIMEWindow() to those controls.
So the implementation inside Win32Proc.cpp:
case WM_IME_STARTCOMPOSITION:
{
Ctrl*f=GetFocusChild();
if(f)
f->DisplayIMEWindow();
}
break;
And below are the implementation inside EditField control
void EditField::DisplayIMEWindow()
{
HWND hwnd =this->GetParent()->GetHWND();
POINT pt;
FontInfo fi = font.Info();
GetCaretPos(&pt);
HIMC hIMC = ImmGetContext(hwnd);
COMPOSITIONFORM cf;
LOGFONT lf;
HFONT hfont = fi.GetHFONT();
GetObject(hfont, sizeof(LOGFONT), &lf);
ImmSetCompositionFont(hIMC, &lf);
cf.dwStyle = CFS_POINT;
cf.ptCurrentPos.x = pt.x;
cf.ptCurrentPos.y = pt.y;
ImmSetCompositionWindow(hIMC, &cf);
ImmReleaseContext(hwnd, hIMC);
}
And below inside RichEdit control (kbd.cpp):
void RichEdit::DisplayIMEWindow()
{
HWND hwnd = this->GetParent()->GetHWND();
POINT pt;
FontInfo fi = formatinfo.Info();
GetCaretPos(&pt);
HIMC hIMC = ImmGetContext(hwnd);
COMPOSITIONFORM cf;
LOGFONT lf;
HFONT hfont = fi.GetHFONT();
::GetObject(hfont, sizeof(LOGFONT), &lf);
ImmSetCompositionFont(hIMC, &lf);
cf.dwStyle = CFS_POINT;
cf.ptCurrentPos.x = pt.x;
cf.ptCurrentPos.y = pt.y;
ImmSetCompositionWindow(hIMC, &cf);
ImmReleaseContext(hwnd, hIMC);
}
I still have problem with the font size for IME window.
And have problem debugging the codes. The IDE will hang if i press F10 key after a break point.
|
|
|
Re: Japanese IME test code [message #15220 is a reply to message #15170] |
Thu, 10 April 2008 05:27   |
mobilehunter
Messages: 87 Registered: November 2006
|
Member |
|
|
Another update for RichEdit control, to make the font size of IME window follows RichEdit's font size.
void RichEdit::DisplayIMEWindow()
{
HWND hwnd = this->GetParent()->GetHWND();
POINT pt;
COMPOSITIONFORM cf;
LOGFONT lf;
HIMC hIMC = ImmGetContext(hwnd);
GetCaretPos(&pt);
int zoomHeight = GetZoom() * tabs(formatinfo.GetHeight());
ImmGetCompositionFont(hIMC,&lf);
lf.lfHeight = -zoomHeight;
ImmSetCompositionFont(hIMC, &lf);
cf.dwStyle = CFS_POINT;
cf.ptCurrentPos.x = pt.x;
cf.ptCurrentPos.y = pt.y;
ImmSetCompositionWindow(hIMC, &cf);
ImmReleaseContext(hwnd, hIMC);
}
And for EditField.
void EditField::DisplayIMEWindow()
{
HWND hwnd = this->GetParent()->GetHWND();
POINT pt;
COMPOSITIONFORM cf;
LOGFONT lf;
HIMC hIMC = ImmGetContext(hwnd);
GetCaretPos(&pt);
Size sz = GetSize();
int yy = GetTy();
ImmGetCompositionFont(hIMC,&lf);
lf.lfHeight = font.Info().GetHeight()+yy;
ImmSetCompositionFont(hIMC, &lf);
cf.dwStyle = CFS_POINT;
cf.ptCurrentPos.x = pt.x;
cf.ptCurrentPos.y = pt.y-yy;
ImmSetCompositionWindow(hIMC, &cf);
ImmReleaseContext(hwnd, hIMC);
}
[Updated on: Thu, 10 April 2008 05:59] Report message to a moderator
|
|
|
|
Re: Japanese IME test code [message #15400 is a reply to message #15290] |
Mon, 21 April 2008 06:33   |
mobilehunter
Messages: 87 Registered: November 2006
|
Member |
|
|
Changed the codes.
All the functions declared as virtual
RichEdit control:
#ifdef PLATFORM_WIN32
Font RichEdit::GetIMEFont()
{
Font imeFont(formatinfo);
int zoomHeight = GetZoom() * tabs(formatinfo.GetHeight());
imeFont.Height(zoomHeight);
return imeFont;
}
void RichEdit::DisplayIMEWindow()
{
HWND hwnd = this->GetParent()->GetHWND();
POINT pt;
COMPOSITIONFORM cf;
LOGFONT lf;
GetCaretPos(&pt);
Font imeFont = GetIMEFont();
cf.dwStyle = CFS_POINT;
cf.ptCurrentPos.x = pt.x;
cf.ptCurrentPos.y = pt.y;
HIMC hIMC = ImmGetContext(hwnd);
ImmGetCompositionFont(hIMC,&lf);
lf.lfHeight = -imeFont.GetHeight();
ImmSetCompositionFont(hIMC, &lf);
ImmSetCompositionWindow(hIMC, &cf);
ImmReleaseContext(hwnd, hIMC);
}
#endif PLATFORM_WIN32
And for editfield control:
#ifdef PLATFORM_WIN32
Font EditField::GetIMEFont()
{
Font imeFont(font);
imeFont.Height(font.Info().GetHeight());
return imeFont;
}
void EditField::DisplayIMEWindow()
{
HWND hwnd = this->GetParent()->GetHWND();
POINT pt;
COMPOSITIONFORM cf;
LOGFONT lf;
GetCaretPos(&pt);
int yy = GetTy();
Font imeFont = GetIMEFont();
cf.dwStyle = CFS_POINT;
cf.ptCurrentPos.x = pt.x;
cf.ptCurrentPos.y = pt.y-yy;//to make the ime window to appear inside editfield
HIMC hIMC = ImmGetContext(hwnd);
ImmGetCompositionFont(hIMC,&lf);
lf.lfHeight = -(imeFont.GetHeight());
ImmSetCompositionFont(hIMC, &lf);
ImmSetCompositionWindow(hIMC, &cf);
ImmReleaseContext(hwnd, hIMC);
}
#endif
[Updated on: Mon, 21 April 2008 06:34] Report message to a moderator
|
|
|
|
Re: Japanese IME test code [message #15462 is a reply to message #15417] |
Fri, 25 April 2008 07:15   |
mobilehunter
Messages: 87 Registered: November 2006
|
Member |
|
|
luzr wrote on Wed, 23 April 2008 17:02 | Ah, sorry, looks like I was not specific enough 
DisplayIMEWindow are now the same, are not they? So with GetIMEFont, we can gladly move them into CtrlCore and not be bothered reimplementing it for each individual class.
In the same time, we can implement base Ctrl::GetIMEFont to return StdFont and get this working well for all widgets.
What do you think?
Mirek
|
DisplayIMEWindow are almost the same, the differences are at font height and coordinate of IME window.
The font height of IME window should follow the font height of it's parent, also should fit nicely inside the parent.
That's why i implemented at RichEdit and EditField ctrl, since i don't know how to get current font height of each control, and to layout nicely in generic way.
Moving to CtrlCore would be the best.
|
|
|
|
|
|
|
|
|
|
|
|
|
Re: Japanese IME test code [message #15810 is a reply to message #15745] |
Thu, 08 May 2008 08:04   |
mobilehunter
Messages: 87 Registered: November 2006
|
Member |
|
|
I change my codes to support "on-the-spot" mode of IME for Windows, i also tried playing with XIM for linux, tested againt SCIM (this will come later sometime:)).
I still have problem with caret, and many behaviours not supported.
For this mode i tested with EditField control (i have to modify it's Paint function).
Here are my codes:
At CtrlCore.h
//Added for CJK
public:
virtual bool ImeIsInPreEditMode() { return imeIsInPreEditMode;}
virtual Font ImePreEditFont();
virtual Point ImePreEditStartPoint();
virtual void ImePreEditSetText(const WString & text);
virtual int ImePreEditGetTextCx(const wchar *txt, int n, bool password, Font fnt);
virtual void ImePreEditStart();
virtual void ImePreEditEnd();
virtual void ImePreEditSyncCaret();
virtual int ImePreEditPaint(Draw &w,int fcy, Color ink, Color paper, Font fnt);
private:
Font imeFont;
bool imeIsInPreEditMode;
Point imePreEditPoint;
int imePreEditCursor;
WString imePreEditString;
//End of CJK
At Ctrl.cpp
//Added for CJK
Font Ctrl::ImePreEditFont()
{
return StdFont();
}
Point Ctrl::ImePreEditStartPoint()
{
return Point(caretx,carety);
}
void Ctrl::ImePreEditSetText(const WString& text)
{
imePreEditString = text;
Refresh();
}
void Ctrl::ImePreEditSyncCaret()
{
int x = ImePreEditGetTextCx(imePreEditString,imePreEditCursor,false,imeFont);
FontInfo fi = imeFont.Info();
int ty = (GetSize().cy + 1 - fi.GetHeight()) / 2;
caretx=imePreEditPoint.x + x + 2 - fi.GetRightSpace('o') + fi.GetLeftSpace('o');
carety=ty;
caretcx=1;
caretcy=min(GetSize().cy - 2 * ty, fi.GetHeight());
}
int Ctrl::ImePreEditGetTextCx(const wchar *txt, int n, bool password, Font fnt)
{
FontInfo fi = fnt.Info();
if(password)
return n * fi['*'];
const wchar *s = txt;
int x = 0;
while(n--)
x += fi[*s++];
return x;
}
void Ctrl::ImePreEditStart()
{
imePreEditPoint = ImePreEditStartPoint();
imeIsInPreEditMode = true;
imePreEditCursor=0;
imePreEditString="";
imeFont = ImePreEditFont();
}
void Ctrl::ImePreEditEnd()
{
imeIsInPreEditMode = true;
imePreEditCursor=0;
imePreEditString="";
Refresh();
}
int Ctrl::ImePreEditPaint(Draw &w,int fcy, Color ink, Color paper, Font fnt)
{
int n=imePreEditString.GetLength();
if(n < 0) return 0;
const wchar * imtxt=imePreEditString;
int cx = ImePreEditGetTextCx(imePreEditString,n,false,imeFont);
w.DrawRect(imePreEditPoint.x, 0, cx, fcy, paper);
w.DrawText(imePreEditPoint.x, 0, imtxt, fnt, ink, n);
//draw feedback
w.DrawLine(imePreEditPoint.x,fcy,imePreEditPoint.x+cx,fcy,1);
return cx;
}
//End of CJK
At Win32Proc.cpp
case WM_IME_STARTCOMPOSITION:
{
Ctrl*f=GetFocusChild();
f->ImePreEditStart();
CANDIDATEFORM cf;
cf.dwStyle = CFS_CANDIDATEPOS;
cf.ptCurrentPos.x = f->imePreEditPoint.x;
cf.ptCurrentPos.y = f->imePreEditPoint.y;
HIMC hIMC = ImmGetContext(hwnd);
ImmSetCandidateWindow(hIMC, &cf);
ImmReleaseContext(hwnd, hIMC);
return 0L;
}
case WM_IME_ENDCOMPOSITION:
{
Ctrl*f=GetFocusChild();
f->ImePreEditEnd();
return 0L;
}
case WM_IME_COMPOSITION:
{
Ctrl*f=GetFocusChild();
if(lParam & GCS_COMPSTR)
{
HWND hWnd =GetHWND();
HIMC hIMC = ImmGetContext(hwnd);
long dwSize = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
wchar temp[1024];
wchar attribute[10];
if(lParam & GCS_COMPATTR)
{
int attrLen=ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
ImmGetCompositionStringW(hIMC, GCS_COMPATTR, attribute, attrLen);
LOGHEXDUMP(attribute,attrLen);
}
ImmGetCompositionStringW(hIMC, GCS_COMPSTR, temp, dwSize);
if(lParam & GCS_CURSORPOS)
{
int cursor = ImmGetCompositionString(hIMC, GCS_CURSORPOS, NULL, 0);
DUMP(cursor);
if(attribute[0] != ATTR_TARGET_CONVERTED)
f->imePreEditCursor = cursor/2;
}
ImmReleaseContext(hWnd, hIMC);
f->ImePreEditSetText(WString(temp,dwSize/2));
if(attribute[0] != ATTR_TARGET_CONVERTED)
{
f->ImePreEditSyncCaret();
SyncCaret();
}
return 0L;
}
break;
}
And at EditField.cpp
if(GetSelection(l, h)) {
Paints(w, x, fcy, txt, ink, paper, l, password, font);
Paints(w, x, fcy, txt, enabled ? st->selectedtext : paper,
enabled ? st->selected : ink, h - l, password, font);
Paints(w, x, fcy, txt, ink, paper, text.GetLength() - h, password, font);
}
else
{
if(!ImeIsInPreEditMode())
Paints(w, x, fcy, txt, ink, paper, text.GetLength(), password, font);
else
{
Paints(w, x, fcy, txt, ink, paper, cursor, password, font);
x+=ImePreEditPaint(w,fcy,ink,paper,font);
Paints(w, x, fcy, txt, ink, paper,text.GetLength() - cursor , password, font);
}
}
|
|
|
Re: Japanese IME test code [message #15811 is a reply to message #15810] |
Thu, 08 May 2008 09:52   |
 |
mirek
Messages: 14257 Registered: November 2005
|
Ultimate Member |
|
|
mobilehunter wrote on Thu, 08 May 2008 02:04 | I change my codes to support "on-the-spot" mode of IME for Windows, i also tried playing with XIM for linux, tested againt SCIM (this will come later sometime:)).
I still have problem with caret, and many behaviours not supported.
For this mode i tested with EditField control (i have to modify it's Paint function).
Here are my codes:
At CtrlCore.h
//Added for CJK
public:
virtual bool ImeIsInPreEditMode() { return imeIsInPreEditMode;}
virtual Font ImePreEditFont();
virtual Point ImePreEditStartPoint();
virtual void ImePreEditSetText(const WString & text);
virtual int ImePreEditGetTextCx(const wchar *txt, int n, bool password, Font fnt);
virtual void ImePreEditStart();
virtual void ImePreEditEnd();
virtual void ImePreEditSyncCaret();
virtual int ImePreEditPaint(Draw &w,int fcy, Color ink, Color paper, Font fnt);
private:
Font imeFont;
bool imeIsInPreEditMode;
Point imePreEditPoint;
int imePreEditCursor;
WString imePreEditString;
//End of CJK
At Ctrl.cpp
//Added for CJK
Font Ctrl::ImePreEditFont()
{
return StdFont();
}
Point Ctrl::ImePreEditStartPoint()
{
return Point(caretx,carety);
}
void Ctrl::ImePreEditSetText(const WString& text)
{
imePreEditString = text;
Refresh();
}
void Ctrl::ImePreEditSyncCaret()
{
int x = ImePreEditGetTextCx(imePreEditString,imePreEditCursor,false,imeFont);
FontInfo fi = imeFont.Info();
int ty = (GetSize().cy + 1 - fi.GetHeight()) / 2;
caretx=imePreEditPoint.x + x + 2 - fi.GetRightSpace('o') + fi.GetLeftSpace('o');
carety=ty;
caretcx=1;
caretcy=min(GetSize().cy - 2 * ty, fi.GetHeight());
}
int Ctrl::ImePreEditGetTextCx(const wchar *txt, int n, bool password, Font fnt)
{
FontInfo fi = fnt.Info();
if(password)
return n * fi['*'];
const wchar *s = txt;
int x = 0;
while(n--)
x += fi[*s++];
return x;
}
void Ctrl::ImePreEditStart()
{
imePreEditPoint = ImePreEditStartPoint();
imeIsInPreEditMode = true;
imePreEditCursor=0;
imePreEditString="";
imeFont = ImePreEditFont();
}
void Ctrl::ImePreEditEnd()
{
imeIsInPreEditMode = true;
imePreEditCursor=0;
imePreEditString="";
Refresh();
}
int Ctrl::ImePreEditPaint(Draw &w,int fcy, Color ink, Color paper, Font fnt)
{
int n=imePreEditString.GetLength();
if(n < 0) return 0;
const wchar * imtxt=imePreEditString;
int cx = ImePreEditGetTextCx(imePreEditString,n,false,imeFont);
w.DrawRect(imePreEditPoint.x, 0, cx, fcy, paper);
w.DrawText(imePreEditPoint.x, 0, imtxt, fnt, ink, n);
//draw feedback
w.DrawLine(imePreEditPoint.x,fcy,imePreEditPoint.x+cx,fcy,1);
return cx;
}
//End of CJK
At Win32Proc.cpp
case WM_IME_STARTCOMPOSITION:
{
Ctrl*f=GetFocusChild();
f->ImePreEditStart();
CANDIDATEFORM cf;
cf.dwStyle = CFS_CANDIDATEPOS;
cf.ptCurrentPos.x = f->imePreEditPoint.x;
cf.ptCurrentPos.y = f->imePreEditPoint.y;
HIMC hIMC = ImmGetContext(hwnd);
ImmSetCandidateWindow(hIMC, &cf);
ImmReleaseContext(hwnd, hIMC);
return 0L;
}
case WM_IME_ENDCOMPOSITION:
{
Ctrl*f=GetFocusChild();
f->ImePreEditEnd();
return 0L;
}
case WM_IME_COMPOSITION:
{
Ctrl*f=GetFocusChild();
if(lParam & GCS_COMPSTR)
{
HWND hWnd =GetHWND();
HIMC hIMC = ImmGetContext(hwnd);
long dwSize = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
wchar temp[1024];
wchar attribute[10];
if(lParam & GCS_COMPATTR)
{
int attrLen=ImmGetCompositionStringW(hIMC, GCS_COMPATTR, NULL, 0);
ImmGetCompositionStringW(hIMC, GCS_COMPATTR, attribute, attrLen);
LOGHEXDUMP(attribute,attrLen);
}
ImmGetCompositionStringW(hIMC, GCS_COMPSTR, temp, dwSize);
if(lParam & GCS_CURSORPOS)
{
int cursor = ImmGetCompositionString(hIMC, GCS_CURSORPOS, NULL, 0);
DUMP(cursor);
if(attribute[0] != ATTR_TARGET_CONVERTED)
f->imePreEditCursor = cursor/2;
}
ImmReleaseContext(hWnd, hIMC);
f->ImePreEditSetText(WString(temp,dwSize/2));
if(attribute[0] != ATTR_TARGET_CONVERTED)
{
f->ImePreEditSyncCaret();
SyncCaret();
}
return 0L;
}
break;
}
And at EditField.cpp
if(GetSelection(l, h)) {
Paints(w, x, fcy, txt, ink, paper, l, password, font);
Paints(w, x, fcy, txt, enabled ? st->selectedtext : paper,
enabled ? st->selected : ink, h - l, password, font);
Paints(w, x, fcy, txt, ink, paper, text.GetLength() - h, password, font);
}
else
{
if(!ImeIsInPreEditMode())
Paints(w, x, fcy, txt, ink, paper, text.GetLength(), password, font);
else
{
Paints(w, x, fcy, txt, ink, paper, cursor, password, font);
x+=ImePreEditPaint(w,fcy,ink,paper,font);
Paints(w, x, fcy, txt, ink, paper,text.GetLength() - cursor , password, font);
}
}
|
Uh, what is "on-the-spot" mode?
The number of new virtual functions is staggering....
BTW, for now I would like to add the mode from previous posts, where we were ok with just
virtual Font GetIMEFont();
virtual Point GetIMEPoint();
The only thing I am missing there is change so that GetIMEPoint returns view-relative Point, not top window relative.
Mirek
|
|
|
Goto Forum:
Current Time: Sun May 11 22:18:17 CEST 2025
Total time taken to generate the page: 0.02463 seconds
|