머리말
지난 몇 주 동안 작업하면서 골치아픈 문제로 고민을 했습니다. 즉, VB6으로 작성한 ActiveX 컨트롤이 델파이 환경에서 이상한 문제가 많다는 것입니다. 우여곡절 끝에 거의 모든 포럼과 정보를 검색해 보았습니다. , 다양한 Delphi 버전에서 발생하는 문제에 대한 솔루션을 찾았습니다.
Delphi5의 설명할 수 없는 치명적인 예외 중 하나
먼저 Delphi5에서 VB로 작성된 ActiveX 컨트롤의 이상한 동작을 살펴보겠습니다.
예를 들면 다음과 같습니다. VB를 사용하여 UserTest 컨트롤(단순화를 위해 하나의 클래스인 사용자 컨트롤만 내보냅니다), TestName 속성 및 TestMethod 메서드를 작성했습니다. 그런 다음 ActiveX 컨트롤로 컴파일하고 등록한 후 Delphi5 개발 환경으로 가져옵니다. (위 단계에서 불분명한 점이 있으면 다양한 참조 자료를 확인하세요. 표준 답변이 있어야 합니다.) 지금까지는 모든 것이 정상인 것 같습니다.
그런 다음 컨트롤을 양식에 끌어다 놓고 크기를 조정하고 속성 창에서 속성에 값을 할당하는 데 익숙합니다. 코드에서도 마찬가지입니다. 그러나 여기서 문제가 발생합니다. 열정적으로 TestMethod를 호출하면 "OleError800a01a9"라는 이상한 예외가 발생하고 프로그램이 종료됩니다. 불행하게도 VB나 Delphi에서는 이 예외를 추적할 수 없습니다. 물론 VB에서는 어셈블리에 능숙하다면 델파이 디버깅 창을 단계별로 따라갈 수 있습니다.
처음 이 문제를 접했을 때 마이크로소프트나 볼랜드 모두 해당 오류에 대한 설명이나 찾을 수 있는 정보가 없었기 때문에 화가 날 뻔했습니다. 제가 자주 방문하는 여러 포럼을 방문해야 했는데, 물론 가장 중요한 것은 CSDN이었고, VB 버전과 Delphi 버전에서 비슷한 질문을 검색했지만 안타깝게도 비슷한 질문만 있었지만 답변이 없었습니다. 도구, Windows(데스크톱 및 WEB 포함)에서 거의 모든 개발 도구와 개발 환경을 테스트한 후 Delphi를 잊어버렸습니다.
남은 이틀 동안 전 세계를 돌아다니며 친구들에게 전화를 걸어 델파이 전문가들이 이 상황을 알고 있는지 물어봤습니다. 마침내 구글에서 링크를 찾았는데, 지금은 그 링크의 정확한 위치를 잊어버렸습니다. , 그러나 거의 Magic 방법을 얻었습니다(발견자가 이를 그렇게 부릅니다).
VBActiveX 컨트롤을 가져온 후 Delphi에서 생성된 프록시 유형 라이브러리 XXX_TLB.PAS(XXX는 컨트롤의 클래스 이름을 나타냄) 파일을 수동으로 수정하는 방법으로 이 문제를 해결할 수 있습니다. 예:
VB로 작성된 컨트롤 UserControl1이 있습니다. 이를 Delphi로 가져온 후 두 개의 파일이 생성됩니다. 그 중 하나인 UserControl1_TLB.PAS가 수정하려는 파일입니다.
파일에서 이와 유사한 것을 찾으십시오.
FintF:_UserControl1;
FunctionGetControlInterface:_UserControl1;
그리고
PRertyControlInterface:_UserControl1readGetControlInterface;
GetControlInterface;
게다가
절차TUserControl1.CreateControl;
절차DoCreate;
시작하다
Finf:=IUnknown(OleObject)as_UserControl1;
끝;
시작하다
IfFinf=nilthenDoCreate;
끝;
FunctionTUserControl1.GetControl1Interface:_UserControl1;
시작하다
CreateControl;
결과:=Finfl;
끝;
참고: 여기에 빨간색으로 표시된 모든 _UserControl1을 _UserControl1Disp로 바꿔야 합니다. 컴파일에 실패하면 컴파일 경고에 보고된 모든 _UserControl1을 _UserControl1Disp로 바꾸고 이 방법으로 컴파일하면 위의 치명적인 오류가 발생하지 않습니다. 발생하다.
이 훌륭한 발견에 감사드립니다. 이렇게만 설명할 수 있습니다. 그렇지 않으면 여전히 이 서클에 갇혀 있거나 이 컨트롤을 다시 개발하기 위해 다른 도구를 사용해야 할 것입니다(이 작업이 얼마나 될지 상상할 수 없습니다) 또는 다른 호환성 문제가 있을 수 있습니다).
Delphi5 설명할 수 없는 치명적인 예외 2
그러나 델파이는 이 제한을 우회한 후에도 나를 놓아주지 않았고, 곧 고객은 개발 환경에서 런타임에 컨트롤이 포함된 폼이 닫힐 때마다 예외가 발생하는 또 다른 귀찮은 문제를 발견했습니다. 컴파일된 애플리케이션에서는 발생하지 않습니다. 최종 사용자의 사용에는 영향을 미치지 않지만 개발자에게는 큰 문제입니다. 그런 다음 위의 예를 사용하여 시도했지만 이 질문은 발생하지 않았습니다. (당시 정신이 없었습니다. 아마도 코드의 일부 호환되지 않는 사용법 때문이었을 것입니다. 하루에 수만 줄의 코드가 규칙적인지 확인하는 것은 매우 무서웠습니다.) 나는 화가 나서 제어를 차단했습니다. 모든 코드를 제어하고 사용자 인터페이스 자체만 남겨두고 이상한 일이 발생하여 코드를 작성하지 않았습니다. 내 컨트롤을 로드할 때 이 오류가 계속 발생하는데, 이는 나를 기쁘고 놀라게 합니다. 행복한 점은 이 문제가 내 코드와 관련이 없으므로 찾기가 훨씬 쉬울 것이라는 점입니다. VB에서 몇 가지 표준을 삭제하면 실제로 그러한 끔찍한 오류가 발생할 수 있습니다. Delphi5와 VB6 사이의 충돌은 실제로 그렇게 깊지 않습니다. 다음 2시간 동안 나는 이 치명적인 예외를 일으킨 사람이 누구인지 테스트하기 위해 인터페이스에서 컨트롤을 계속 삭제했습니다.
2시간 후, 나는 안도의 한숨을 쉬었고, 근본적인 문제는 다음과 같습니다.
VB 사용자 컨트롤에서 Frame 및 PictureBox(내부에 다른 컨트롤을 포함할 수 있음)와 같은 컨테이너 컨트롤을 사용하는 경우 Label, Line 및 Image와 같은 windowLess 컨트롤을 이러한 컨트롤에 추가할 수 없습니다. 런타임 중에 실시간으로 VB에 의해 그려집니다. 그렇지 않으면 위와 같은 오류 보고서를 받게 됩니다.
Delphi6 및 7의 숨겨진 ActiveX 컨트롤
바로 Delphi 5에서의 끔찍한 경험 때문에 Delphi 6과 7에서도 동일한 문제가 존재하는지 테스트하는 것이 여전히 필요하다는 것을 알았습니다(이전 버전은 사용자가 거의 없기 때문에 더 이상 필요하지 않으며 Delphi 8은 공식적으로 출시되지 않았습니다). 아직은 이용할 수 없으므로 고려하지 않습니다. 결과는 다음과 같습니다. ... 몇 번이나 로드하더라도 ActiveX 바에서 오랫동안 기다려온 작은 아이콘을 찾을 수 없습니다. 물론 이 결과는 테스트가 정상인지 아닌지는 말할 것도 없고 로드할 수도 없습니다.
마찬가지로 다양한 포럼과 웹사이트를 검색해 보니 CSDN에서 비슷한 질문을 하는 사람들이 더 많이 발견되었지만 여전히 대답은 0이었습니다. 필사적으로 Delphi6과 7 각각에서 옵션을 조정해야 했습니다.
3시간 15분 54초 후에 나는 이 빌어먹을 문제의 원인, 해결책을 찾았습니다. (그렇게 말한 것을 용서해주세요. 참을 수가 없었습니다.) 사실은 매우 간단합니다.
이제 저를 따라오십시오. Tools 메뉴->EnvironmentOptions->TypeLibrary 페이지를 클릭하면 IgnorespecialCoClassFlagsWhenImporting 항목을 찾아서 선택한 다음 CanCreate 항목을 선택합니다. 이제 해당 ActiveX 컨트롤을 가져와 보겠습니다. 한 번 가져온 경우 생성된 두 파일인 .dcr 및 .pas 파일을 삭제하십시오. 그렇지 않으면 새로 고쳐지지 않습니다. 이번에도 ActiveX 열에서 컨트롤을 찾을 수 없다면 Microsoft나 Borland에 전화해서 언제 결혼할 수 있는지 물어봐야 합니다. 하하!
(또한 Delphi5에서 나타났던 위의 오류는 Delphi6, 7에서는 발견되지 않았습니다.)
내 테스트 환경은 다음과 같습니다.
Win2K
델파이5업데이트1
델파이6업데이트2
델파이7