2011-04-01 2 views
2

나는 UserControl을 사용하는 Vb6로 작성된 프로젝트를 가지고 있는데, ocx가 등록되었을 때 프로젝트는 잘 실행되지만, 사이드 바이 사이드 매니페스트와 같은 프로젝트를 실행하면 잘 실행됩니다. 컨트롤을 정적으로로드 한 상태에서 (폼에 추가 된) 컨트롤을 사용할 수 있지만 새 컨트롤 (속성 또는 메서드)을 사용하여 폼에 동적 컨트롤을 추가하면이 오류가 발생합니다. " 받는 사람 해봐요 : 가 VB6에서 OCX 프로젝트를 1 작성 2 사용자 컨트롤을 추가 3이 방법의 예를 추가 : 개체가이 속성 또는이 오류는이 방법을 재현 할 수이상한 경우 SXS가있는 기존 vb6 응용 프로그램이 누락 된 경우 = "개체가이 속성 또는 메서드를 지원하지 않습니다."

방법 "을 지원하지 않습니다 컨트롤 4- exe 프로젝트 만들기 5- 컨트롤 추가 예 : UserControl1 6- 이벤트 콜에서 DoSomething 7- 동적으로로드

Dim y As Control 
UserControl1.DoSomething   '<-------- CASE(1) THIS IS ALLRIGHT!' 
Set y = Controls.Add("Project1.UserControl1", "y") 
y.DoSomething '<---- (CASE 2) THIS WILL FAIL USING SXS' 

WinDbg에서 오류를 추적하여 IDispatch :: GetIDsOfNames로 돌아가서 두 번째 경우에 호출하면 실패합니다.

어떤 아이디어?!

편집 : 내 나쁜, 여기에 명단입니다.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 

<assemblyIdentity name="client.exe" version="1.0.0.0" type="win32" processorArchitecture="x86"/> 

<file name="Project1.ocx"> 
<comClass 
    clsid="{C8CF7991-A8F2-4360-9404-03C9A052C245}" 
    description="Project1.UserControl1" 
    tlbid="{47853CCC-7BE6-4377-9C82-38A0B7755F65}" 
    threadingModel="apartment" 
    miscStatusContent="recomposeonresize,cantlinkinside,insideout,activatewhenvisible,setclientsitefirst" 
    progid="Project1.UserControl1"/> 
<typelib 
    tlbid="{47853CCC-7BE6-4377-9C82-38A0B7755F65}" 
    version="1.0" 
    helpdir="" 
    flags="control,hasdiskimage"/> 
</file> 

<comInterfaceExternalProxyStub 
    iid="{0E4F313E-7EF3-4FE6-9591-9F7D2D819AEE}" 
    name="UserControl1" 
    proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"/> 
<comInterfaceExternalProxyStub 
    iid="{53307849-4F14-4A59-B0CA-DE4950CE499D}" 
    name="UserControl1" 
    proxyStubClsid32="{00020420-0000-0000-C000-000000000046}"/> 

</assembly> 
+1

글쎄, 매니페스트가 잘못되었습니다. 여기에서 볼 수 없습니다. –

+0

이것은 실제로 "나란히"(여러 어셈블리를 의미 함)가 아니라 reg-free COM입니다. 귀하의 매니 페스트가 중요한 정보 (이 경우에는 ProgID)가 누락 된 것 같습니다. – Bob77

+0

동의하지만 문제가 변경되지 않습니다. 여기에 매니페스트가 있습니다. 나는 ProgID가 괜찮을 것이라고 확신한다. – Mehran

답변

2

짧은 대답 : 이것은 VB6의 알려진 문제입니다. "Controls.Add"문은 나란히 작동하지 않습니다. "Load"문을 대신 사용해보십시오.

긴 대답 : VB6에서는 ProgID를 사용하여 컨트롤을 만들더라도 실행 파일에 컨트롤의 CLSID를 컴파일합니다. "Control.Add"를 실행하면 CLSID가 동일한 지 확인합니다. 이유는 묻지 마세요, 이건 더 이상 다루지 않는 신비입니다. 동시에 win32가 나란히 (.Net side-by-side - 다른 주제와는 반대로) 하나 이상의 매니페스트에서 사용되는 동일한 ProgID를 처리 할 준비가되어 있어야합니다 (활성화 컨텍스트 사이에서 플립 플롭 할 때 예를 들어, 이렇게) 내부적으로 ProgID마다 새로운 임시 CLSID를 생성합니다. 결국 CLSIDFromProgID를 호출하면 임시 CLSID가 표시됩니다. 그런 다음 CoCreateInstance를 호출하면 정상적으로 작동합니다. - sxs는 CLSID를 따릅니다. 그러나 CLSID를 찾는 곳이라면 (레지스트리, 내부 테이블) CLSID를 찾을 수 없습니다. VB6 프로그램은 CLSIDFromProgID를 호출하여 CLSID가 내부 테이블에 있는지 여부를 확인합니다. 실패.

1

이것은 매니 페스트와 호환되지 않는 VB 마술의 경우입니다. 이 문제는 사용자 정의 컨트롤 참조에 대한 VB의 동작에 기인합니다. 변수 As UserControl을 강력하게 희미하더라도이 참조에서 메서드/속성에 액세스하는 것은 늦게 바인딩됩니다! VB는 각각의 참조 된 사용자 정의 컨트롤에 공통 메서드 (예 : SetFocus, Move 등)를 표시하도록 확장 클래스를 만듭니다. As UserControl이 클래스는 UserControl의 컨트롤 형식 라이브러리에서 참조가 아닌 VBControlExtender 상속 클래스로 컴파일됩니다. 어떤 경우에는 UserControl에 자동으로 생성 된 래퍼가 있습니다.

Curland's Advanced Visual Basic 6 사용자 컨트롤의 장을 발견 한 이후로 VB에서 랩퍼를 사용하지 않도록 지정하는 사용자 지정 Direct User Controls typelib을 만드는 것이 었습니다. 기본적으로 다음과 같이 보입니다 :

[ 
    uuid(GUIDHERE-0000-1111-2222-2B5E1A72D6BF), 
    version(1.0), 
    helpstring("Direct User Controls Typelib 1.0") 
] 
library <<mytypelib>> 
{ 
    importlib("stdole2.tlb"); 
    importlib("C:\\WINDOWS\\system32\\COMCTL32.ocx"); 
    importlib("C:\\WINDOWS\\system32\\COMCT232.ocx"); 
    importlib("C:\\WINDOWS\\system32\\shdocvw.dll"); 
    ... 

    typedef [public] ComctlLib.ImageList    DirectImageList; 
    typedef [public] ComctlLib.ListView     DirectListView; 
    typedef [public] ComctlLib.ProgressBar    DirectProgressBar; 
    typedef [public] ComctlLib.Slider     DirectSlider; 
    typedef [public] ComctlLib.StatusBar    DirectStatusBar; 
    typedef [public] ComctlLib.TabStrip     DirectTabStrip; 
    typedef [public] ComctlLib.Toolbar     DirectToolbar; 
    typedef [public] ComctlLib.TreeView     DirectTreeView; 

    typedef [public] ComCtl2.Animation     DirectAnimation; 
    typedef [public] ComCtl2.UpDown      DirectUpDown; 

    typedef [public] SHDocVw.WebBrowser     DirectWebBrowser; 
    ... 
} 

내 프로젝트에서는 "직접"참조를 유지하고 초기 바인딩 메소드를 호출합니다. 컨트롤을 사용합니다.VBIDE에 등록 된 컨트롤 및 등록 무료 컨트롤 : 도우미를 캐스팅하는 것은 세 가지 경우에 예상대로이 조각 작품이

Private Function pvCastVBControlExtender(oCtl As VBControlExtender) As VBControlExtender 
    Set pvCastVBControlExtender = oCtl 
End Function 

같은이 곳

Dim oCtl As DirectXxx 
Set oCtl = pvCastVBControlExtender(Controls.Add(PROGID_Xxx, sName)).Object 

처럼 추가합니다.

+0

거기에 여전히 하드 코어 VB 개발자가 있다는 것을 알아두면 좋지만 솔루션은 훌륭하지만 잠시 동안 내 문제를 해결하는 쉬운 방법을 찾았습니다. http://support.microsoft.com/kb/190670 VBControlExtender에 설명 된대로 Interface에는 실제 유형의 멤버에 액세스 할 수있게 해주는 Object 속성이 있으므로 제 경우 UserControl.Object.DoSomething을 호출하면 문제가 해결됩니다. – Mehran

+0

'Object' 속성에서'DoSomething'을 호출하면 늦게 호출하는 것이 더 분명합니다. 이러한 'UserControl'이 "Object"속성을 사용하여 "un-wrapped"참조에 액세스하는 프로젝트의 일부일 때 문제가 발생합니다. – wqw

+0

개체 속성이 늦은 바운드가 아니어도 어쨌든이 경우에도 호출이 완벽하게 작동합니다. 나는 vb 개발자가 아니며, 늦은 시각 여부를 어떻게 확인할 수 있습니까? – Mehran

관련 문제