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

C++빌더 Q&A
C++Builder Programming Q&A
[69632] Re:Re:Re:Re: 지나가다님 답변이 정확한거 같네요
진호 [] 2369 읽음    2013-06-11 19:08
제가 본 글중에는 포커스 관련 메세지가 문자완성 메세지 보다 먼저 뜨는 Windows 버그라고
문제를 윈도우 버그로 돌리면서 그럴싸하게 엉뚱한 답변을 늘어 놓는 사람도 보았고
장성호님과 비슷한 생각을 해보기도 했지만 원인은 VCL 버그 때문이었군요.

지나다가님이 답변해주신 글 보고 코드패치해서 테스트해보니까 문제가 싹 사라졌습니다.
쪽집게 처럼 VCL 버그 짚어내는 분들이 없는데 대단하시네요.


지나다가 님이 쓰신 글 :
: RAD 2010 VCL 라이브러리 소스를 보면
:
:
: function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
: var
:   Handled: Boolean;
:   Unicode: Boolean;
:   MsgExists: Boolean;
: begin
:   Result := False;
: 
:   MsgExists := PeekMessage(Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE);
: 
:   if MsgExists or PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
:   begin
:     Unicode := (Msg.hwnd = 0) or IsWindowUnicode(Msg.hwnd);
: 
:     if not MsgExists then
:     begin
:       if Unicode then
:         MsgExists := PeekMessageW(Msg, 0, 0, 0, PM_REMOVE)
:       else
:         MsgExists := PeekMessageA(Msg, 0, 0, 0, PM_REMOVE);
:     end;
: 
:     if MsgExists then
:     begin
:       Result := True;
:       if Msg.Message <> WM_QUIT then
:       begin
:         Handled := False;
:         if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
:         if not IsPreProcessMessage(Msg) and not IsHintMsg(Msg) and
:           not Handled and not IsMDIMsg(Msg) and
:           not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
:         begin
:           TranslateMessage(Msg);
:           if Unicode then
:             DispatchMessageW(Msg)
:           else
:             DispatchMessageA(Msg);
:         end;
:       end
:       else
:       begin
:   {$IF DEFINED(CLR)}
:         if Assigned(FOnShutDown) then FOnShutDown(self);
:         DoneApplication;
:   {$IFEND}
:         FTerminate := True;
:       end;
:     end;
:   end;
: end;
: 

:
: 위와 같이 되어있는데,
:
: IME 와 Edit Control은 서로 별개의 윈도우 이기 때문에, Edit 콘트롤이 Focus Out 되는 것을 IME 윈도우 쪽에서는
: 알수 없어서, IME Completion 과정에서 발생하는 메세지 셋이 라우팅 될수 있도록 Message Dispatch 루틴을
: 만들 때 그런 부분을 고려했어야 하는데
:
: VCL 라이브러리 소스를 보면 마우스 이벤트에 대해 선행처리 한답시고 닭짓을 하고 있기 때문에 문제가 발생하는 것임.
:
:     if MsgExists then
:
: 윗부분의 코드를 걷어내고 다음과 같이 작성했더라면 전혀 질문에 언급된 문제가 발생하지 않았을 것임.
:
:
: function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
: var
:   Handled: Boolean;
:   Unicode: Boolean;
:   MsgExists: Boolean;
: begin
:   Result := False;
: 
:   if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
:   begin
:     Unicode := (Msg.hwnd = 0) or IsWindowUnicode(Msg.hwnd);
:     if Unicode then
:       MsgExists := PeekMessageW(Msg, 0, 0, 0, PM_REMOVE)
:     else
:       MsgExists := PeekMessageA(Msg, 0, 0, 0, PM_REMOVE);
: 
:     if MsgExists then
:     begin
:       Result := True;
:       if Msg.Message <> WM_QUIT then
:       begin
:         Handled := False;
:         if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
:         if not IsPreProcessMessage(Msg) and not IsHintMsg(Msg) and
:           not Handled and not IsMDIMsg(Msg) and
:           not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
:         begin
:           TranslateMessage(Msg);
:           if Unicode then
:             DispatchMessageW(Msg)
:           else
:             DispatchMessageA(Msg);
:         end;
:       end
:       else
:       begin
: // 이하 생략
: 

:
: VCL 라이브러리 소스코드를 수정해서 사용하는 게 불편 하면
:
:
: void __fastcall TForm1::Edit1Exit(TObject *Sender)
: {
:          Application->ProcessMessages();
: }
: 

:
: 위와 같이 작성하면 됨.
:
:
:
:
:
:
: : 장성호 님이 쓰신 글 :
: : : Edit에 입력중에
: : : 코딩으로 강제로 Focus를 옮기며, 곧바로 입력중이던 Edit의 값을 읽어오면
: : : 그런현상이 발생합니다.
: : :
: : : [문제 원인]
: : : Edit1에 입력중인데..
: : :
: : :
: : :  Edit2->SetFocus(); 
: : :  String str=Edit1->Text;
: : :  // 이때 str에 내용은 아직 완성이 안된 문자열이 될수 있습니다
: : : 

: : :
: : : Edit1입력중에 다른 Control로 Focus를 강제로 옮기면
: : : Edit1에 Char완성메세지(WM_CHAR) 와 화면갱신메세지(WM_PAINT)가 발생하게 되는데..
: : : 님께서 Edit1의 Text를 읽어온것은 해당 메세지가 Edit1의 WindowProc에서 처리하기 전에 가져온것입니다.
: : :
: : :
: : : [해결방안]
: : : 다음과 같이
: : : Edit1의 Text를 읽기전 Edit1에서 처리해야할 메세지를 처리하고  Text를 읽으시면 됩니다.
: : : VCL함수중에 Application->ProcessMessages(); 메소드가
: : : 현재 어플리케이션  GUI 쓰레드의 메세지큐에 있는 메세지를 가져와서 처리해주는 함수 입니다.
: : :
: : :
: : : void __fastcall TForm8::Timer1Timer(TObject *Sender)
: : : {
: : : 	Edit2->SetFocus();
: : : 	Application->ProcessMessages(); //Edit1의 TEXT를 읽지전 Edit1에 발생되는 메세지를 처리 
: : : 	String str=Edit1->Text;
: : : 	Edit2->Text=str;
: : : }
: : : 

: : :
: : :
: : : 다른 방법
: : : 원리는 같은데요
: : : Application->ProcessMessages();  메소드는
: : : Edit1뿐만 아니라 모든 어플에서 발생하는 메세지가 처리됩니다.
: : : Edit1에 해상되는 메세지만 처리하고 싶다면 다음과 같이 해보세요
: : :
: : :
: : : void __fastcall MessageProcess(TWinControl *pCtrl)
: : : {
: : : 	TMsg Msg;
: : : 	bool MsgExists = PeekMessageW(&Msg, pCtrl->Handle, 0, 0, PM_REMOVE);
: : : 	while(MsgExists)
: : : 	{
: : : 		TranslateMessage(&Msg);
: : : 		DispatchMessageW(&Msg);
: : : 		MsgExists = PeekMessageW(&Msg, pCtrl->Handle, 0, 0, PM_REMOVE);
: : : 	}
: : : }
: : : //--------------------------------------------------------------------------
: : : void __fastcall TForm8::Timer1Timer(TObject *Sender)
: : : {
: : : 	Timer1->Enabled=false;
: : : 	Edit2->SetFocus();
: : : 	MessageProcess(Edit1); //Edit1에 발생하는 WM_CHAR메세지 처리 
: : : 	String str=Edit1->Text;
: : : 	Edit2->Text=str;
: : : }
: : : 

: : :
: : : 두번째 방법은 직접 메세지큐에서 메세지를 가져와서 처리하므로
: : : Application객체에서 발생하는 OnMessage등의 이벤트들이  발생하지 않습니다.
: : : 관련사항을 유의하시고 사용하셔야 합니다.
: : :
: : :
: : : 이상입니다.
: : :
: : : 그럼..
: : :
: : : 서치포림 님이 쓰신 글 :
: : : : 안녕하세요.
: : : :
: : : : 현재 C++Builder 2010 버전을 사용하고 있습니다.
: : : : 그런데 TEdit 에 텍스트를 넣고 마우스로 다른 컨트롤을 클릭하여 포커스를 이동하면 TEdit에 입력한 문자 중 마지막 글자가 사라집니다.
: : : : Edit 박스에는 마지막 글짜까지 표시되어 있는데 코딩으로 읽어보면 마지막 글자는 나타나지 않습니다.
: : : :
: : : : 예를들면, Edit1 에 "학용품" 라고 입력한 후에 마우스로 다른 컨트롤을 클릭하여 포커스를 이동한 후 코딩으로
: : : :
: : : : AnsiString sText = Edit1->Text;
: : : :
: : : : 위와 같이 하면,  sText 에는 "학용" 이라고 나옵니다.
: : : :
: : : : 즉 마지막 글자 입력 중에 포커스를 다른 데로 옮기면 조합중인 글자가 사라지는 문제가 발생합니다.
: : : :
: : : : 그런데 Edit1에는 원래 입력한 대로 "학용품"이라고 표시되어 있고, 포커스를 다시 Edit1으로 옮겼다가 다른 컨트롤로 옮기면 이번에는 정상으로 나옵니다.
: : : :
: : : : 그리고 포커스를 옮길 때 <Tab> 키를 쳐서 이동하면 괜찮은데, 마우스로 다른 컨트롤을 클릭하여 이동하면 이런 문제가 발생합니다.
: : : :
: : : : 이런 경우에 어떻게 해결해야 하나요?
: : : :
: : : : 코딩으로 Edit 박스를 빠져나갈 때 End 키나 Right 키를 강제로 입력하여 마지막 글자가 사라지는 문제를 해결할 수 있을까요?
: : : : 기초가 많이 부족하여 해결하기가 어렵네요.
: : : : 가능하면 방법 좀 부탁드립니다.

+ -

관련 글 리스트
69627 TEdit 에 한글 텍스트를 넣고 포커스를 다른 컨트롤로 이동시 텍스트가 잘리는 문제? 서치포림 2937 2013/06/11
69628     Re:TEdit 에 한글 텍스트를 넣고 포커스를 다른 컨트롤로 이동시 텍스트가 잘리는 문제? 장성호 2630 2013/06/11
69629         Re:Re:TEdit 에 한글 텍스트를 넣고 포커스를 다른 컨트롤로 이동시 텍스트가 잘리는 문제? 서치포림 2278 2013/06/11
69630             Re:Re:Re: 이 또한 VCL 라이브러리를 멍청하게 만들어서 생긴 오류임 지나다가 2845 2013/06/11
69632                 Re:Re:Re:Re: 지나가다님 답변이 정확한거 같네요 진호 2369 2013/06/11
69631                 Re:Re:Re:Re: 오호 지나다가님. 신기하게 잘됩니다 aa 2466 2013/06/11
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.