2016-06-04 4 views
2

는 다음 PSDK documentation 내가 (나중에 의심 처음으로 발견 된 것) HIMAGELISTIImageList 유형 사이을 캐스팅 할 수없는거야 무슨 말 포함 겉으로는 간단 (하지만 실제로는 매우 명확하지). 그래서, 나는 다음과 같은 코드를 작성 :SHGetImageList를 올바르게 호출하려면 어떻게해야합니까? 그것과 함께 HIMAGELIST를 검색 할 수 있습니까? 내가 쉘의 공유 이미지 목록을 검사하려고했다

procedure TForm1.FormCreate(Sender: TObject); 
const 
    IID_IImageList: TGUID = '{46EB5926-582E-4017-9FDF-E8998DAA0950}'; 
    IID_IImageList2: TGUID = '{192B9D83-50FC-457B-90A0-2B82A8B5DAE1}'; 
var 
    himl: HIMAGELIST; 
begin 
    CoInitialize(nil); 

    OleCheck(SHGetImageList(SHIL_LARGE, IID_IImageList, Pointer(himl))); 
    ImageList1.Handle := himl; 
end; 

을하지만 아주 제대로 작동 : API 호출이 HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) 반환 한 후 응용 프로그램과 라이브러리 사이에 진 모순을 제안, 다중 접속 위반으로 충돌합니다. 그러나, 나는이 사용했던 기능의 주식 델파이 가져 오기 올바른 같습니다

function SHGetImageList(iImageList: Integer; const riid: TGUID; 
    var ppvObj: Pointer): HResult; 
function SHGetImageList; external shell32 name 'SHGetImageList' delayed; 

나는이 문서에서 혼란 발견이 무엇 riid 매개 변수 설명 목록은 하나의 가능한 값이 두 번째입니다 - IID_IImageList 검색 내 의도와 일치하지 않을 수 있습니다 핸들 유형.

그래서 어떻게 SHGetImageList를 제대로 호출 할 수 있습니까? 그리고 HIMAGELIST을 검색 할 수 있습니까?

답변

8

문제는 ShellAPI 단위 델파이의 주식 선언이다. stdcall 호출 규칙이 없습니다. 그 해결하려면, 당신은 당신의 자신의 코드에 수동 기능을 선언 할 수

function SHGetImageList(iImageList: Integer; const riid: TGUID; 
    var ppvObj: Pointer): HResult; stdcall; external shell32; 

procedure TTestForm.Button1Click(Sender: TObject); 
const 
    IID_IImageList: TGUID = '{46EB5926-582E-4017-9FDF-E8998DAA0950}'; 
var 
    himl: HIMAGELIST; 
begin 
    //CoInitialize(nil); 
    OleCheck(SHGetImageList(SHIL_LARGE, IID_IImageList, Pointer(himl))); 
    ImageList1.Handle := himl; 
end; 

참고 : 프로젝트 소스에 Application.Initialize 호출을 제거하지 않으면 VCL 애플리케이션이 이미 CoInitialize를 호출합니다.

+0

오, 나는 이것을 간과했다고 믿을 수 없다! 감사! –

1

그래서 어떻게 SHGetImageList를 제대로 호출합니까?

함수 출력 인터페이스입니다, 그래서 당신은 인터페이스 변수를 선언 할 필요가 : 그것으로 HIMAGELIST를 검색 할

procedure TForm1.FormCreate(Sender: TObject); 
var 
    iml: IImageList; 
begin 
    CoInitialize(nil); 
    OleCheck(SHGetImageList(SHIL_LARGE, IImageList, Pointer(iml))); 
end; 

을 그리고 그것은 가능하다? 당

documentation :

같은 PPV 매개 변수에 반환과 IImageList 포인터 유형, 필요에 따라 HIMAGELIST으로 캐스팅 될 수있다 예를 들어, 목록보기에서 사용할 수 있습니다. 반대로, HIMAGELIST는 IImageList에 대한 포인터로 형변환 될 수 있습니다.

procedure TForm1.FormCreate(Sender: TObject); 
var 
    iml: IImageList; 
begin 
    CoInitialize(nil); 
    OleCheck(SHGetImageList(SHIL_LARGE, IImageList, Pointer(iml))); 
    ImageList1.Handle := HIMAGELIST(iml); // or HIMAGELIST(Pointer(iml)); 
end; 
+0

여전히 작동하지 않으며, 'HRESULT_FROM_WIN32 (ERROR_INVALID_PARAMETER)'및 그 다음 지속될 수없는 예외입니다. –

+0

캐스트는 콜 사이트에서 만들 수 있습니다. '쉘라피'의 선언이 잘못되었습니다. –

+0

@SertacAkyuz 호출 사이트에서 캐스트가 작성되면 반환 된 인터페이스의 참조가 올바르게 관리되지 않습니다. 이 함수는 해제해야하는 인터페이스를 반환합니다. 그리고 기술적으로 델파이 선언은 잘못이 아닙니다. –

관련 문제