将TTextEdit更改为从右到左的语言不会更改插入符号

时间:2013-06-25 13:42:32

标签: delphi devexpress right-to-left caret

我正在Delphi XE3中编写一个支持英语和希伯来语的应用程序。

当我更改当前语言(使用 Alt + Shift )时,在某些文本编辑器(TEdit等)的编辑模式下,插入符号(文本光标)图标不会像在其他已知应用程序(Office,Chrome等)中的编辑器那样改变新的方向 对于那些不了解不同插入符号图标的人,这里有他们的图像:
Left-to-right (English) caret iconRight-to-left (Hebrew) caret icon

只有当我将焦点更改为另一个组件,然后在编辑模式下返回上一个编辑器时,它才会显示与当前语言方向对应的正确插入符号图标。

在使用Delphi XE3之前,我使用过Delphi 7,它运行良好。 此外,我尝试过DevExpress文本编辑器,他们也有同样的问题。

2 个答案:

答案 0 :(得分:0)

我不确定过去可能有什么用处或可能有什么改变,但下面的内容应该有效。似乎WM_INPUTLANGCHANGE是一个滑溜的信息,几乎不可能通过覆盖WndProc或甚至使用Application.HookMainWindow挂钩来可靠地捕捉(有一篇关于它的好文章here)。另请注意,这只是希伯来语键盘的一个示例 - 它不会捕获所有从右到左的键盘(如果需要,您显然需要添加它们)。

const HEBREW_KEYBOARD = $40D0000;
var gLangHook: HHOOK = 0;

function LangHookProc(Code: Integer; wParam: WPARAM; 
                                     lParam: LPARAM): LRESULT; stdcall;
begin
  if (Code = HC_ACTION) and 
     (PCWPStruct(lParam)^.message = WM_INPUTLANGCHANGE) then
  begin
    if (PCWPStruct(lParam)^.lParam and $FFFF0000) = HEBREW_KEYBOARD then
       Application.BiDiMode := bdRightToLeft
    else
       Application.BiDiMode := bdLeftToRight;
  end;
  Result := CallNextHookEx(gLangHook, Code, wParam, lParam);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  gLangHook := SetWindowsHookEx(WH_CALLWNDPROC, @LangHookProc, HInstance,
                                                            GetCurrentThreadId);
  if gLangHook = 0 then
    RaiseLastOSError;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if gLangHook <> 0 then
  begin
    UnhookWindowsHookEx(gLangHook);
    gLangHook := 0;
  end;
end;

这里我设置了应用程序的BiDiMode - 如果所有孩子都有ParentBiDiMode := true,那么所有控件都应该切换到从右到左模式。当然,你可以随心所欲地处理这个 - 我认为这是困难的部分。

答案 1 :(得分:0)

是否是像@J ...建议的Delphi XE3错误,或者机器特定的错误,我还是遇到了它。
我没有找到一个明确的解决方案,而是一个很好的解决方法 注意:此解决方案仅适用于DevExpress编辑器,因为事件被TWinControl后代捕获。

这是代码:

procedure OnChangeLanguageEvent(var Msg: TMessage); message CM_INPUTLANGCHANGE;

procedure TForm1.OnChangeLanguageEvent(var Msg: TMessage);
begin
  Screen.ActiveControl.Perform(WM_KILLFOCUS,0,0);
  Screen.ActiveControl.Perform(WM_SETFOCUS,0,0);
  inherited;
end;

在这个程序中,我抓住了事件CM_INPUTLANGCHANGE,当我这样做时,我会暂时失去焦点并重新获得当前活动控件的焦点。这模拟了我之前所说的,只有当我将焦点更改为另一个组件,然后在编辑模式下返回上一个编辑器时,它才会显示正确的插入符号。

我真的不喜欢这个解决方案,因为它并没有真正解决任何问题,但它对我的需求很好。 欢迎您提出其他想法:)