我需要将 IRandomAccessStream 放到没有选择器的文件中。
但是,我坚持使用 IStorageFile 或 IRandomAccessStreamReference 并且找不到从其中任何一个获取 IRandomAccessStream 的方法。
我用 C++(没有 /ZW)编写代码,但我认为在这种情况下并不重要。
请帮忙,摩西
我需要将 IRandomAccessStream 放到没有选择器的文件中。
但是,我坚持使用 IStorageFile 或 IRandomAccessStreamReference 并且找不到从其中任何一个获取 IRandomAccessStream 的方法。
我用 C++(没有 /ZW)编写代码,但我认为在这种情况下并不重要。
请帮忙,摩西
我设法使用 StorageFile 的 OpenReadAsync 做我想做的事。但这涉及 2 个异步调用并且很麻烦。我想知道是否有更短更优雅的方式。相关示例代码如下:
IFACEMETHODIMP MyClass::BeginCreateObject(
//... rest of parameters
_In_ IMFAsyncCallback *pCallback,
_In_ IUnknown *punkState)
{
OutputDebugStringW(__FUNCTIONW__);
HRESULT hr;
HString hstrStorageFile;
hstrStorageFile.Set(RuntimeClass_Windows_Storage_StorageFile);
// Get the Activation Factory
ComPtr<IActivationFactory> pStorageFileActivationFactory;
hr = GetActivationFactory(hstrStorageFile.Get(), &pStorageFileActivationFactory);
if (FAILED(hr))
{
::Microsoft::WRL::Details::RaiseException(hr);
}
// QI for StorageFileStatics
ComPtr<IStorageFileStatics> pStorageFileStatics;
hr = pStorageFileActivationFactory.As(&pStorageFileStatics);
if (FAILED(hr))
{
::Microsoft::WRL::Details::RaiseException(hr);
}
HString hstrFileName;
hstrFileName.Set(L"My_Cool_Movie.ts");
// Call CreateFileAsync
__FIAsyncOperation_1_Windows__CStorage__CStorageFile * operation;
hr = pStorageFileStatics->GetFileFromPathAsync(hstrFileName.Get(),
&operation
);
if (FAILED(hr))
{
::Microsoft::WRL::Details::RaiseException(hr);
}
typedef IAsyncOperationCompletedHandler<StorageFile*> HandlerDoneType;
ComPtr<HandlerDoneType> handler(Callback<HandlerDoneType>(
this, &MyClass::FileOpenCompletionHandler));
hr = operation->put_Completed(handler.Get());
ComPtr<IMFAsyncResult> spResult;
//maybe I should pass some data in the first parameter?
hr = MFCreateAsyncResult(nullptr, pCallback, punkState, &_spOpenResult);
//the further processing will be done in the completion handler
return hr;
}
IFACEMETHODIMP MyClass::EndCreateObject(
_In_ IMFAsyncResult *pResult,
_Out_ MF_OBJECT_TYPE *pObjectType,
_Out_ IUnknown **ppObject)
{
OutputDebugStringW(__FUNCTIONW__);
if (pResult == nullptr || pObjectType == nullptr || ppObject == nullptr)
{
return E_INVALIDARG;
}
HRESULT hr = S_OK;
//get a random access stream
if(!_spFile)
{
return E_FAIL;
}
ComPtr<IRandomAccessStream> streamHandle;
hr = _spStream.As(&streamHandle);
if (FAILED(hr))
{
::Microsoft::WRL::Details::RaiseException(hr);
}
//Do what you need with IRandomAccessStream!
//...
return S_OK;
}
IFACEMETHODIMP MyClass::CancelObjectCreation(
_In_ IUnknown *pIUnknownCancelCookie)
{
return E_NOTIMPL;
}
HRESULT MyClass::FileOpenCompletionHandler( IAsyncOperation<StorageFile*>* async, AsyncStatus status)
{
//file is open, call the invoke to carry one
if (status == Completed) {
HRESULT hr = async->GetResults(_spFile.GetAddressOf());
if (_spFile) {
ComPtr<IRandomAccessStreamReference> streamReference;
hr = _spFile.As(&streamReference);
if (FAILED(hr))
{
::Microsoft::WRL::Details::RaiseException(hr);
}
__FIAsyncOperation_1_Windows__CStorage__CStreams__CIRandomAccessStreamWithContentType * operation;
hr = streamReference->OpenReadAsync(&operation);
if (FAILED(hr))
{
::Microsoft::WRL::Details::RaiseException(hr);
}
typedef IAsyncOperationCompletedHandler<IRandomAccessStreamWithContentType*> OpenReadAsyncHandlerDoneType;
ComPtr<OpenReadAsyncHandlerDoneType> handler(Callback<OpenReadAsyncHandlerDoneType>(
this, &MyClass::FileOpenReadCompletionHandler));
hr = operation->put_Completed(handler.Get());
}
return hr;
}
else {
OutputDebugStringW(L"Unexpected async status\n");
return E_FAIL;
}
return S_OK;
}
HRESULT MyClass::FileOpenReadCompletionHandler( IAsyncOperation<IRandomAccessStreamWithContentType*>* async, AsyncStatus status)
{
if (status == Completed) {
HRESULT hr = async->GetResults(_spStream.GetAddressOf());
if (_spStream) {
_spOpenResult->SetStatus(S_OK);
hr = MFInvokeCallback(_spOpenResult.Get());
_spOpenResult.ReleaseAndGetAddressOf();
}
return hr;
}
else {
OutputDebugStringW(L"Unexpected async status\n");
return E_FAIL;
}
return S_OK;
}