-1

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

当我更改当前语言(使用Alt+ Shift)时,在某些文本编辑器(TEdit 等)的编辑模式下,插入符号(文本光标)图标不会像在其他已知应用程序(Office 、铬等)。
对于那些不知道可能的不同插入符号图标的人,这里是它们的图像:
从左到右(英语)插入符号图标从右到左(希伯来语)插入符号图标

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

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

4

2 回答 2

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,当我捕捉到事件时,我随后失去焦点并重新获得当前活动控件的焦点。这模拟了我之前所说的,只有当我将焦点更改为另一个组件,然后在编辑模式下返回到上一个编辑器时,它才会显示正确的插入符号图标。

我不太喜欢这个解决方案,因为它并不能真正解决任何问题,但它可以满足我的需求。欢迎您提出其他想法:)

于 2013-06-26T14:40:57.523 回答
0

我不确定过去可能会起作用或可能发生了什么变化,但是像下面这样的东西应该起作用。这似乎WM_INPUTLANGCHANGE是一条很容易出错的消息,几乎不可能通过覆盖WndProc甚至挂钩 using来可靠地捕获(这里Application.HookMainWindow有一篇关于它的不错的文章)。另请注意,这只是希伯来语键盘的一个示例 - 它不会捕获所有从右到左的键盘(如果需要,您显然需要添加它们)。

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那么所有控件都应该切换到从右到左模式。当然,你可以随心所欲地处理这个问题——我认为这是最难的部分。

于 2013-06-25T16:38:06.923 回答