虽然cef4delphi在GTK3可以使用中文输入,但lazarus支持GTK3不完善,且还要安装GTK3才能使用。为尽量可能利用已有的gtk2环境,在网上没有相关资料可以参考的情况下,经多日研究,今天(2025-01-22)终于修复了cef4delphi(lazarus)的SimpleOSRBrowser for GTK2不能输入中文的问题。
我这个方法不是最优,但可以暂时解决中文输入存在的困扰,如果你有更好的方法也请与我分享,谢谢!
2025-02-03重要提醒:
实现这个方法的前提要按https://www.cnblogs.com/qiufeng2014/p/15722762.html修复linux中文输入的Bug,否则不会响应LM_IM_COMPOSITION消息,无法实现中文输入。
注意:本方法适用于CEF OSR模式。
2025-01-23:
输入框显示在鼠标的位置
2025-01-22 21:45更新:
早上代码贴少了,现已补充完成,请重新测试。
测试环境:
操作系统:Linux raspberrypi 6.6.62+rpt-rpi-2712 #1 SMP PREEMPT Debian 1:6.6.62-1+rpt1 (2024-11-25) aarch64 GNU/Linux(树莓派 64位)/GTK2
CPU:aarch64
cef4delphi版本:131.3.5
lazarus 4.0RC2 /fpc 3.3.1
修改后的CEF4Delphi-131.3.5下载:
链接: https://pan.baidu.com/s/1VcWBn-zEpBQ0lOiJA9Ik2w?pwd=gd6k 提取码: gd6k
压缩包里不包含CEF各平台的二进制文件,可根据需要自行下载:
https://github.com/salvadordf/CEF4Delphi/tree/131.0.6778.265
一、TBufferPanel增加
1、WMIMComposition--处理中文
2、FOnIMETextChange: TNotifyEvent--当中文输入时通知应用文字有变化
3、FIMContext_string---保存变化的文字
uCEFBufferPanel.pas
interface uses {$IFDEF DELPHI16_UP} {$IFDEF MSWINDOWS}Winapi.Windows, Winapi.Messages, Vcl.ExtCtrls, Vcl.Controls, Vcl.Graphics, WinApi.Imm, {$ENDIF} System.Classes, System.SyncObjs, System.SysUtils, Vcl.Forms, {$ELSE} {$IFDEF MSWINDOWS}Windows, imm, {$ENDIF} Classes, Forms, Controls, Graphics, {$IFDEF FPC} Dialogs, {$ifdef LCLgtk2} gdk2,Gtk2Globals, Messages, {$endif} LCLProc, LCLType, LCLIntf, LResources, LMessages, InterfaceBase,{$IFDEF MSWINDOWS}Win32Extra,{$ENDIF} {$ELSE} Messages, {$ENDIF} ExtCtrls, SyncObjs, SysUtils,
TBufferPanel = class(TCustomPanel) protected {$ifdef LCLGTK2} FIMContext_string :string; FOnIMETextChange : TNotifyEvent; {$endif} FScanlineSize : integer; FTransparent : boolean;
{$ELSE} FSyncObj : TCriticalSection; {$ENDIF} {$ifdef LCLGTK2} procedure Change; virtual; procedure WMIMComposition(var Message: TMessage); message LM_IM_COMPOSITION; {$endif} procedure CreateSyncObj;
procedure Paint; override; {$ifdef LCLGTK2} procedure SetIMContext_string(aValue : String); {$endif} {$IFDEF MSWINDOWS} procedure CreateParams(var Params: TCreateParams); override;
procedure DrawOrigPopupBuffer(const aSrcRect, aDstRect : TRect); {$ifdef LCLGTK2} property IMContext_string :string read FIMContext_string write SetIMContext_string; {$endif} /// <summary> /// Returns the scanline size. /// </summary> property ScanlineSize : integer read FScanlineSize;
property OnPointerUpdate : TOnHandledMessageEvent read FOnPointerUpdate write FOnPointerUpdate; {$ENDIF} /// <summary> /// Event triggered before the AlphaBlend call that transfer the web contents from the /// bitmap buffer to the panel when the Transparent property is True. /// </summary> property OnPaintParentBkg : TNotifyEvent read FOnPaintParentBkg write FOnPaintParentBkg; {$ifdef LCLGTK2} property OnIMETextChange : TNotifyEvent read FOnIMETextChange write FOnIMETextChange; {$endif} /// <summary>
{$ifdef LCLGTK2} procedure TBufferPanel.SetIMContext_string(aValue : String); begin if (FIMContext_string <> aValue) then begin FIMContext_string := aValue; end; end; procedure TBufferPanel.Change; begin Changed; if Assigned(FOnIMETextChange) then FOnIMETextChange(Self); end; procedure TBufferPanel.WMIMComposition(var Message: TMessage); var IMStr:string; begin if Message.WParam=GTK_IM_FLAG_COMMIT then begin FIMContext_string:=''; IMStr:=UTF8Decode(pchar(Message.LParam)); //输入的字符 if IMStr<>'' then begin FIMContext_string:= IMStr; Change; end; end; im_context_use:=false; inherited; end; {$endif} procedure TBufferPanel.CreateSyncObj; begin {$IFDEF MSWINDOWS} FSyncObj := CreateMutex(nil, False, nil); {$ELSE} FSyncObj := TCriticalSection.Create; {$ENDIF} end;
二、uSimpleOSRBrowser
1、uses增加Gtk2Globalsunit uSimpleOSRBrowser; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, LCLType, ComCtrls, Types, SyncObjs, LMessages,Messages, pango,// Gtk2Globals, uCEFChromium, uCEFTypes, uCEFInterfaces, uCEFConstants, uCEFBufferPanel, uCEFChromiumEvents; type { TForm1 }
procedure AddressEdtEnter(Sender: TObject); private protected FRMouseEvent : TCefMouseEvent; FPopUpRect : TRect;
2、改变function GTKKeyPress(Widget: PGtkWidget; Event: PGdkEventKey; Data: gPointer) 的行为:
function GTKKeyPress(Widget: PGtkWidget; Event: PGdkEventKey; Data: gPointer) : GBoolean; cdecl; var TempCefEvent : TCefKeyEvent; EventString: PChar; // GTK1 and GTK2 workaround pr: TGdkRectangle; begin //设置输入框弹出位置 pr.height:=0; pr.width:=0; pr.x:=form1.FRMouseEvent.x; pr.y:=form1.FRMouseEvent.y;// form1.AddressEdt.Height; gtk_im_context_focus_in(IM_Context);//设置焦点-激活输入法---重点 gtk_im_context_set_cursor_location(IM_Context, @pr);//设置输入框位置--重点 gdk_event_key_get_string(Event, EventString{%H-}); //取输入的字符 TempCefEvent.windows_key_code:=GdkEventToWindowsKeyCode(Event); TempCefEvent.native_key_code:=Event^.hardware_keycode; TempCefEvent.modifiers:=Event^.state; TempCefEvent.character:=EventString^; if (Event^._type = GDK_KEY_PRESS) then begin TempCefEvent.kind := KEYEVENT_RAWKEYDOWN; Form1.Chromium1.SendKeyEvent(@TempCefEvent); TempCefEvent.kind := KEYEVENT_CHAR; Form1.Chromium1.SendKeyEvent(@TempCefEvent); end else begin TempCefEvent.kind := KEYEVENT_KEYUP; Form1.Chromium1.SendKeyEvent(@TempCefEvent); end; Result := true; end;
procedure TForm1.Panel1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); var TempEvent : TCefMouseEvent; begin FRMouseEvent.x:=x; FRMouseEvent.y:=y; TempEvent.x := x; TempEvent.y := y; TempEvent.modifiers := getModifiers(Shift); DeviceToLogical(TempEvent, Panel1.ScreenScale); Chromium1.SendMouseMoveEvent(@TempEvent, False); end;
3、添加Panel1IMETextChange(Sender: TObject)
将中文推送到当前的输入框
procedure TForm1.Panel1IMETextChange(Sender: TObject); var i:integer; ims:widestring; TempCefEvent : TCefKeyEvent; begin ims:=Panel1.imcontext_string; for i:=1 to length(ims) do begin TempCefEvent.character:=ims[i];//取中文字符 TempCefEvent.kind := KEYEVENT_RAWKEYDOWN; Chromium1.SendKeyEvent(@TempCefEvent); TempCefEvent.kind := KEYEVENT_CHAR; Chromium1.SendKeyEvent(@TempCefEvent);//推送单个中文字符到cef当前输入框 end; Panel1.imcontext_string:=''; end;
按以上修改后重新编译cef4delphi控件及应用就可以输入中文。
存在问题:中文输入法在窗口左上角。
修复后的中文输入截图:
新修正的可以在鼠标的位置显示输入框:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)