FireMonkey Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
FireMonkey 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

FireMonkey Q&A
[202] Re:Re: 안드로이드 FMX IME 문자조합 질문이죠?
100jk [] 1536 읽음    2019-09-12 23:35
빌더(TWx) 님이 쓰신 글 :
: 100jk 님이 쓰신 글 :
: : 구글검색 중에 나오는 팁들은 전부 윈도우 기반이네요
: :
: : FMX에서 IME조합중인 문자를 가져오는 방법은 없을까요?
:
:
:
: 답변:
:
:
: Java로 프로그래밍 하면...
: 안드로이드 Input Method 클래스나, 키보드 Connection 클래스를 바인드해서
: 간단하게 처리할 수 있지만...
:
: FMX 파이어몽키로 처리하려면 삽질을 해야 합니다.
:
: FMX 프레임웍이 만들어질 때... 기존 윈도우즈 플렛폼에서의 VCL 프레임웍 랜더링을
: DirectX로 대신하는 구조로 설계됐던 건데...
:
: VCL 프레임웍의 TEdit, TListBox, TMemo 와 같은 상위 레이어 컴포넌트를 베이스로 해서
: 안드로이드, Mac, iOS, 윈도우즈... 각기 플렛폼을 one source multi platform을 지원한답시고
:
: legacy 아키텍쳐에 온갖 프록시 클래스를 섞어 놓아서...
: 지금의 멀티디바이스 FMX 프레임웍이 만들어졌기 때문에 프레임웍이 복잡하고 지져분하게 구성되어 있기 때문 입니다.
:
:
:
: 델파이 컴파일러가 FMX 프레임웍을 만들면서 ARC로 닭짓을 해놨기 때문에...
: FMX 프레임웍 ARC 레벨에서 C++ 컴파일러를 이용해서 작업할 수 없어서
: 코드는 파스칼로 구현하는 거로 대신 합니다.
:
: rad studio 10.3.2 기준으로 구현. (10.3 으로 넘어 오면서 FMX 프록시 클래스 구조가 또 바꼈음.)
:
: C++ 컴파일러로 작업할려면 델파이 FMX 프레임웍 ARC 메모리 모델이 폐기 되어야 함.
:
: <델파이 FMX ARC 메모리 모델의 문제점>
: http://delphi.borlandforum.com/impboard/impboard.dll?action=read&db=del_qna&no=16034
:
:
:
: unit Unit2;
: 
: interface
: 
: implementation
: 
: uses
:   FMX.Forms, FMX.Platform.Android, FMX.Platform,
: 
:   FMX.Controls, FMX.Controls.Presentation,
:   FMX.Presentation.Android.Style, FMX.Text,
:   AndroidApi.Helpers, System.Messaging,
: 
:   System.SysUtils, System.Types,
:   Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Embarcadero,
:   FMX.Types, FMX.VirtualKeyboard, Androidapi.JNIBridge,
:   Androidapi.JNI.JavaTypes;
: 
: 
: type
:   KeyboardAndroidEx = class;
: 
:   VKListener = class(TJavaLocal, JOnKeyboardStateChangedListener)
:   private
:     [weak] FKeyboardService: KeyboardAndroidEx;
:     FNeedNotify: Boolean;
: 
:   public
:     constructor Create(Svc: KeyboardAndroidEx);
:     procedure onVirtualKeyboardFrameChanged(newFrame: JRect); cdecl;
:     procedure onVirtualKeyboardWillShown; cdecl;
:     procedure onVirtualKeyboardWillHidden; cdecl;
:   end;
: 
:   FMXListenerEx = class(TJavaLocal, JFMXTextListener)
:   strict private
:     FProcessed: boolean;
:   public
:     constructor Create(const Service: KeyboardAndroidEx); overload;
:     procedure onEditorAction(aCode: Integer); cdecl;
:     procedure onTextUpdated(cs: JCharSequence; pos: Integer); cdecl;
:     procedure onComposingText(bPos: Integer; ePos: Integer); cdecl;
:     procedure onSkipKeyEvent(event: JKeyEvent); cdecl;
: 
:   end;
: 
:   KeyboardAndroidEx = class(TInterfacedObject, IFMXVirtualKeyboardService)
:   private
:     FVKListener: VKListener;
:     FTransient: Boolean;
:     FTextListener: FMXListenerEx;
: 
:     function IsAutoShow: Boolean;
:     procedure Register;
:   public
:     constructor Create;
:     destructor Destroy; override;
: 
:   protected
:     function DefineView(const AObject: TFmxObject): JView;
:     procedure NotificationKeyboardEvent(const AVKRect: TRect);
: 
:     function ShowVirtualKeyboard(const AControl: TFmxObject): Boolean;
:     function HideVirtualKeyboard: Boolean;
:     function GetVirtualKeyBoardState: TVirtualKeyBoardStates;
:     procedure SetTransientState(Value: Boolean);
:     property VirtualKeyBoardState: TVirtualKeyBoardStates read GetVirtualKeyBoardState;
:   end;
: 
: 
: constructor KeyboardAndroidEx.Create;
: begin
:   inherited Create;
: end;
: 
: destructor KeyboardAndroidEx.Destroy;
: begin
:   inherited;
: end;
: 
: function KeyboardAndroidEx.DefineView(const AObject: TFmxObject): JView;
: 
:   function IsControl: Boolean;
:   begin
:     Result := (AObject is TPresentedControl) and (TPresentedControl(AObject).ControlType = TControlType.Platform);
:   end;
: 
:   function GetView: JView;
:   begin
:     Result := JView(TPresentedControl(AObject).PresentationProxy.NativeObject);
:   end;
: 
:   function GetFormView: JView;
:   begin
:     Result := WindowHandleToPlatform(TCommonCustomForm(TControl(AObject).Root.GetObject).Handle).View;
:   end;
: 
:   function IsStyledControl: Boolean;
:   begin
:     Result := (AObject is TPresentedControl) and (TPresentedControl(AObject).Presentation is TAndroidStyledPresentation);
:   end;
: 
:   function IsAvailable: Boolean;
:   begin
:     Result := (AObject is TControl) and (TControl(AObject).Root <> nil) and
:               TCommonCustomForm(TControl(AObject).Root.GetObject).IsHandleAllocated;
:   end;
: 
: begin
:   if IsStyledControl and IsAvailable then
:     Result := GetFormView
:   else if IsControl then
:     Result := GetView
:   else if Supports(AObject, ITextInput) then
:     Result := MainActivity.getEditText
:   else if IsAvailable then
:     Result := GetFormView
:   else
:     Result := nil;
: end;
: 
: function KeyboardAndroidEx.IsAutoShow: Boolean;
: begin
:   Result := VKAutoShowMode in [TVKAutoShowMode.Always, TVKAutoShowMode.DefinedBySystem];
: end;
: 
: procedure KeyboardAndroidEx.Register;
: begin
:   if not Assigned(FVKListener) then
:   begin
:     FVKListener := VKListener.Create(Self);
:     MainActivity.getVirtualKeyboard.addOnKeyboardStateChangedListener(FVKListener);
:   end;
: end;
: 
: function KeyboardAndroidEx.GetVirtualKeyBoardState: TVirtualKeyBoardStates;
: begin
:   Result := [];
:   if IsAutoShow then
:     Include(Result, TVirtualKeyboardState.AutoShow);
:   if FTransient then
:     Include(Result, TVirtualKeyboardState.Transient);
:   if MainActivity.getVirtualKeyboard.isVirtualKeyboardShown then
:     Include(Result, TVirtualKeyboardState.Visible);
: 
: end;
: 
: function KeyboardAndroidEx.HideVirtualKeyboard: Boolean;
: begin
:   Result := False;
:   try
:     if not FTransient then
:     begin
:       Register;
:       MainActivity.getEditText().removeTextListener(FTextListener);
:       Result := MainActivity.getVirtualKeyboard.hide;
:     end;
:   except
:     Application.HandleException(Screen.ActiveForm);
:   end;
: end;
: 
: 
: procedure KeyboardAndroidEx.NotificationKeyboardEvent(const AVKRect: TRect);
: var
:   M: TVKStateChangeMessage;
: begin
:   M := TVKStateChangeMessage.Create(TVirtualKeyboardState.Visible in VirtualKeyboardState, AVKRect);
:   TMessageManager.DefaultManager.SendMessage(Self, M, True);
: end;
: 
: function KeyboardAndroidEx.ShowVirtualKeyboard(const AControl: TFmxObject): Boolean;
:   function IsNotFocused(const AControl: TFmxObject): Boolean;
:   begin
:     Result := (AControl is TControl) and not TControl(AControl).IsFocused;
:   end;
: 
: begin
:   if IsNotFocused(AControl) then
:     TControl(AControl).SetFocus;
:   Register;
:   if not Assigned(FTextListener) then
:     FTextListener := FMXListenerEx.Create(Self);
: 
:   MainActivity.getEditText().addTextListener(FTextListener);
:   Result := MainActivity.getVirtualKeyboard.showFor(DefineView(AControl));
: end;
: 
: 
: procedure KeyboardAndroidEx.SetTransientState(Value: Boolean);
: begin
:   FTransient := Value;
: end;
: 
: 
: constructor VKListener.Create(Svc: KeyboardAndroidEx);
: begin
:   inherited Create;
:   FKeyboardService := Svc;
: end;
: 
: procedure VKListener.onVirtualKeyboardFrameChanged(newFrame: JRect);
: begin
: end;
: 
: procedure VKListener.onVirtualKeyboardWillShown;
: begin
:   FNeedNotify := FNeedNotify or
:      not (TVirtualKeyboardState.Visible in FKeyboardService.VirtualKeyboardState);
: end;
: 
: procedure VKListener.onVirtualKeyboardWillHidden;
: begin
:   FNeedNotify := FNeedNotify or
:      (TVirtualKeyboardState.Visible in FKeyboardService.VirtualKeyboardState);
: end;
: 
: 
: 
: constructor FMXListenerEx.Create(const Service: KeyboardAndroidEx);
: begin
:   inherited Create;
: end;
: 
: procedure FMXListenerEx.onComposingText(bPos, ePos: Integer);
: begin
: end;
: 
: procedure FMXListenerEx.onSkipKeyEvent(event: JKeyEvent);
: begin
: end;
: 
: procedure FMXListenerEx.onTextUpdated(cs: JCharSequence; pos: Integer);
: begin
:   if pos = 0 then
:     Exit;
: 
:   if not FProcessed then
:   begin
:     // 디버깅덤프. 문자조합과정 출력
:     Log.d(Format('%s', [JCharSequenceToStr(cs)[pos-1]]));
:     FProcessed := True;
:   end
:   else
:     FProcessed := False;
: end;
: 
: procedure FMXListenerEx.onEditorAction(aCode: Integer);
: begin
: end;
: 
: 
: var
:   FKeyboardAndroidEx: KeyboardAndroidEx = nil;
:   FVKService: IFMXVirtualKeyboardService = nil;
: 
: initialization
:   FKeyboardAndroidEx := KeyboardAndroidEx.Create;
:   FVKService := IFMXVirtualKeyboardService(TPlatformServices.Current.GetPlatformService(IFMXVirtualKeyboardService));
:   if FVKService <> nil then
:     TPlatformServices.Current.RemovePlatformService(IFMXVirtualKeyboardService);
:   TPlatformServices.Current.AddPlatformService(IFMXVirtualKeyboardService, FKeyboardAndroidEx);
: 
: end.
: 
: 

:
:
:
:
:
: 메인폼에 TEdit 올려놓고...
: 위의 Unit2를 메인 유닛의 implementaion 섹션의 uses 에 포함해서 컴파일만 하면 됌.
:
: 컴파일 후... TEdit에 "국가"를 입력하면 아래 캡쳐 화면과 같이...
: LogCat을 통해서 문자조합 과정이 출력될 겁니다. (LogCat을 이용한 디버깅 덤프방법은 생략함)
:
:
:
:
:
:
: 간단한가요?
:
: one source multi platform은 초보자들 꼬득이기 위한 상술에 불과한 거고...
: Java와 Android sdk 프레임웍 구조 모르면... 기술적인 문제에 부딛혔을 때... 아무것도 손 못댑니다.
:
: Java와 Android sdk 프레임웍 구조부터 마스터 하세요.
: 이걸 마스터 해놔야...
:
: Android 프레임웍과 비슷한 구조로 만들어져 있는 C# Xamarin도 마음대로 요리할 수 있게 됍니다.
:
: C# Xamarin으로 작성된 코드는 델파이 보다 느리다는 황당한 궤변을 늘어놓는 사람들도 있던데...
: 아마도 이런 사람들은 Android 프레임웍 구조도 모르고, C# 도 디테일하게 잘 모르고 있으면서
: 어설프게 델파이 하나만 맹신적으로 사용하고 있는 사람일 겁니다.
:
:
:
:

답변 정말 감사드립니다.

파이어몽키에도 빨리 리치에디터나 씬에디터같은 좋은 에디터가 나오면 좋겠습니다.

+ -

관련 글 리스트
200 IME 조합중인 문자가져오는법?? 100jk 1267 2019/08/31
201     Re: 안드로이드 FMX IME 문자조합 질문이죠? 빌더(TWx) 1877 2019/09/05
202         Re:Re: 안드로이드 FMX IME 문자조합 질문이죠? 100jk 1536 2019/09/12
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.