RadStudio의 FireMonkey를 사용하여 안드로이드 어플리케이션을 개발하려고 학습 중에 Delphi 예제("나의 도서관 앱" 개발 따라하기 - (1) 사용자화면 만들기와 기능 구현하기)를 C++ Builder로 옴기는 뻘짓을 하는 중에 발생할 애러이다.
발생 애러
[bcc32 Error] MainForm.cpp(135): E2034 Cannot convert 'TControl' to 'TControl *'
Full parser context
MainForm.cpp(127): parsing: void TForm1::UpdateKBBounds()
원본 소스 (Delphi)
procedure TForm1.UpdateKBBounds;
var
LFocused : TControl;
LFocusRect: TRectF;
begin
FNeedOffset := False;
if Assigned(Focused) then
begin
LFocused := TControl(Focused.GetObject);
LFocusRect := LFocused.AbsoluteRect;
LFocusRect.Offset(vsbEditFocus.ViewportPosition);
if (LFocusRect.IntersectsWith(TRectF.Create(FKBBounds))) and
(LFocusRect.Bottom > FKBBounds.Top) then
begin
FNeedOffset := True;
lytContentsNew.Align := TAlignLayout.Horizontal;
vsbEditFocus.RealignContent;
Application.ProcessMessages;
vsbEditFocus.ViewportPosition := PointF(vsbEditFocus.ViewportPosition.X,
LFocusRect.Bottom - FKBBounds.Top);
end;
end;
if not FNeedOffset then
RestorePosition;
end;
애러 발생 지점 (C++ Builder)
void TForm1::UpdateKBBounds(void)
{
TControl *LFocused;
TRectF LFocusRect;
FNeedOffset = false;
if( Focused )
{
LFocused = TControl( Focused->GetObject() );
LFocusRect = LFocused->AbsoluteRect;
LFocusRect.Offset( vsbEditFocus->ViewportPosition.X, vsbEditFocus->ViewportPosition.Y );
if( ( LFocusRect.IntersectsWith( (const TRectF &)FKBBounds ) )
&& ( LFocusRect.Bottom > FKBBounds->Top ) )
{
FNeedOffset = true;
lytContentsNew->Align = TAlignLayout::Horizontal;
vsbEditFocus->RealignContent();
Application->ProcessMessages();
vsbEditFocus->ViewportPosition = PointF( vsbEditFocus->ViewportPosition.X ,
LFocusRect.Bottom - FKBBounds->Top );
}
}
else if( FNeedOffset )
{
RestorePosition();
}
}
문제 해결 (C++ Builder)
void TForm1::UpdateKBBounds(void)
{
TControl *LFocused;
TRectF LFocusRect;
FNeedOffset = false;
if( Focused )
{
LFocused = (TControl*)(IControl*)Focused;
//LFocused = (TControl*)(Focused->GetObject());
LFocusRect = LFocused->AbsoluteRect;
LFocusRect.Offset( vsbEditFocus->ViewportPosition.X, vsbEditFocus->ViewportPosition.Y );
if( ( LFocusRect.IntersectsWith( (const TRectF &)FKBBounds ) )
&& ( LFocusRect.Bottom > FKBBounds->Top ) )
{
FNeedOffset = true;
lytContentsNew->Align = TAlignLayout::Horizontal;
vsbEditFocus->RealignContent();
Application->ProcessMessages();
vsbEditFocus->ViewportPosition = PointF( vsbEditFocus->ViewportPosition.X ,
LFocusRect.Bottom - FKBBounds->Top );
}
}
else if( FNeedOffset )
{
RestorePosition();
}
}
개인적인 정리
처음엔 TControl로 convert 할 수 있는 TControl()도 존재하고, Focused가 속한 class인 TCommonCustomForm에 GetObject() 메소드가 있으므로 별 문제 없어 보였으나 막상 컴파일 하니 Convert를 못한다고 하였다. 그래서 "LFocused = (TControl*)(IControl*)Focused;" 하여 포인터를 넘길 때 TControl의 포인터로 강제 형 변환시켰다. 문제는 이게 소뒷걸음치다 잡은 문제라는 것이고, 사실 다른 더 좋은 방법이 있었다는 것이다. 아무튼 해결한 방법은 Focused에서 ->의 지시자를 하면 선택 가능한 메소드?들이 검색되질 않는다. 그래서 여기서부터 뻘짓을 시작하였다. Focused를 일종의 배열 같은 것으로 판단하였고, 하위에 메소드같은 것을 받은 것이 없으므로 검색되지 않는다고 생각했다. 그래서 Focused 자체를 가지고 Object를 알아 내는 방법을 찾았는데. 일단 TControl로 안된다고 하여 "LFocused = (TControl*)&Focused;"로 포인터를 강제형변환 시키도록 수정하였다. 그런데 문제는 이게 컴파일은 통과를 했는데 런타임에러가 발생했다.

여기서부터 어떻게 해결해야 할지 몰라서 정신줄 놓고 검색을 계속하다 이것이 Delphi에서 변환된 녀석이고 따라서 IControld의 형태로 변환된 녀석임을 알게 되어서 "LFocused = (TControl*)(IControl*)Focused;" 이렇게 변환을 2번 하는 코드를 만들게 되었다. 그 결과 제대로 되었는데....................
지금 막 이 정리를 하면서 "LFocused = (TControl*)(Focused->GetObject());"로 소스를 넣고 컴파일 하니 컴파일도 되고 제대로 동작을 한다;;; 여기서 의문인것은 왜 "Focused->"하면 메소드나 변수을 선택하는 팝업이 안 뜨냐는 것인데, C++도 잘 못할 뿐더러 RadStudio를 처음 쓰기에 잘 모르겠다. 이거은 차근히 풀어 나가야 할듯 하다.
참고 사이트
http://blog.hjf.pe.kr/255