In the wil/winrt.h
and wil/wrl.h
header files,WIL provides helpers to facilitate consumption of Windows Runtime APIsat the ABI (unprojected) layer:
#include <wil/winrt.h>#include <wil/wrl.h>
These helpers work well together with the smart pointers and other WinRT and COM wrappers inwil/com.h
.
Note: These helpers have been superseded by theC++/WinRT projection.You should prefer C++/WinRT in new code, perhaps along withWIL's integration with C++/WinRT.
The time helpers require that <time.h>
be included before including wil/winrt.h
.
SecondsToStartOf1970
long long const SecondsToStartOf1970 = 0x2b6109100;
The number of seconds from the Windows Runtime epoch to January 1, 1970. The Windows Runtime epoch is January 1, 1601.
HundredNanoSecondsInSecond
long long const HundredNanoSecondsInSecond = 10000000LL;
The number of Windows Runtime time units per second. One Windows Runtime time unit is 100ns.
DateTime_to_time_t
__time64_t DateTime_to_time_t(DateTime dateTime);
Converts a Windows Runtime DateTime
to a 64-bit C runtime (Unix-style) time value. The 64-bit C runtime time format has a larger range than the Windows Runtime DateTime
format, but cannot represent fractional seconds. Fractional seconds are discarded in the conversion.
The C++/WinRT equivalent iswinrt::clock::to_time_t()
.
time_t_to_DateTime
DateTime time_t_to_DateTime(__time64_t timeT);
Converts a 64-bit C runtime (Unix-style) time value to a Windows Runtime DateTime
.
The result is undefined if the 64-bit C runtime time value represents a point in time that cannot be represented by a DateTime
(approximate range 27,400 B.C.E to 29,000 C.E.).
The C++/WinRT equivalent iswinrt::clock::from_time_t()
.
HasEmbeddedNull
bool HasEmbeddedNull(_In_opt_ HSTRING value);
Returns true
if the string contains an embedded null character.
The C++/WinRT equivalent is winrt::embedded_null(hstring const&)
.
TwoPhaseHStringConstructor
The TwoPhaseHStringConstructor
is a helper class for constructing HSTRING
objects. It is movable but not copyable.
The C++/WinRT equivalent is to construct the stringusing std::wstring
or any other convenient string container,then construct an hstring
from it.
Usage
// Preallocate space for a string of a specific length.// The length does not include the null terminator.auto stringConstructor = wil::TwoPhaseHStringConstructor::Preallocate(length);RETURN_IF_NULL_ALLOC(stringConstructor.Get());// Fill the buffer with exactly length characters.RETURN_IF_FAILED(stream->Read(stringConstructor.Get(), stringConstructor.ByteSize(), &bytesRead));// Validate stream contents: Sizes must match, and// preallocated null terminator must still be present.RETURN_IF_FAILED(stringConstructor.Validate(bytesRead));Microsoft::WRL::Wrappers::HString string;string.Attach(stringConstructor.Promote());
Details
Constructors
static TwoPhaseHStringConstructor TwoPhaseHStringConstructor::Preallocate(UINT32 characterLength)
(factory)
Create a newTwoPhaseHStringConstructor
that will eventually holda string ofcharacterLength
characters (not counting the null terminator).TwoPhaseHStringConstructor(TwoPhaseHStringConstructor&& other)
(move constructor)
Transfer the state of aTwoPhaseHStringConstructor
to a new object.
Destructor
~TwoPhaseHStringConstructor
It is acceptable to destruct the object without callingPromote
.In that case, the construction of theHSTRING
is abandoned.
Methods
wchar_t* Get()
Returns a pointer to the buffer into which the string should be generated.ULONG ByteSize() const
Returns the size of the buffer in bytes.HRESULT Validate(ULONG bytesRead) const
Validates that the number of bytes is equal to the size of the buffer,not including the null terminator.Also validates that the buffer's null terminator has not been corrupted.Calling
Validate()
is optional.HSTRING Promote()
Construct the Windows RuntimeHSTRING
object from the informationin the buffer. The caller is responsible for the lifetime of the resultingHSTRING
. It is typically placed into an RAII type such aswil::unique_hstring
.Once the string is promoted, the only thing you can do with the objectis destruct it.The
Promote()
method fails fast on usage error,such as if the null terminator has been corrupted,or if you attempt toPromote()
twice.
Operators
operator PCWSTR() const
Returns the buffer into which the string was generated.
hstring_less and hstring_insensitive_less
The hstring_less
and hstring_insensitive_less
structures performcase-sensitive or case-insensitive (respectively) ordinal string comparisonson HSTRING
objects.
They aretransparentcomparatorswhich permit more efficient use of HSTRING
s as keys in associativecontainers such as std::set
and std::map
.Transparency permits looking up items usingany of the following:
HSTRING
const Microsoft::WRL::Wrappers::HString&
const Microsoft::WRL::Wrappers::HStringReference&
const wil::unique_hstring&
const wchar_t*
(null-terminated string, null pointer treated as empty string)const std::string&
(if exceptions are enabled)
Note that the const wchar_t*
version cannot be used to search forstrings with embedded nulls, because the embedded null will betreated as a string terminator.
The hstring_less
structure is used as the default std::less
comparator for Microsoft::WRL::HString
andwil::unique_hstring
.
Examples:
std::map<Microsoft::WRL::HString, int, wil::hstring_less> map;Microsoft::WRL::HString str = ...;wil::unique_hstring uniqueStr = ...;wchar_t buffer[...];map.find(str); // Traditional lookup via Microsoft::WRL::HStringmap.find(str.Get()); // Transparent lookup accepts HSTRINGmap.find(uniqueStr); // Transparent lookup accepts wil::unique_hstringmap.find(L"literal"); // Transparent lookup accepts const wchar_t*map.find(buffer); // Transparent lookup accepts wchar_t*map.find(std::wstring(buffer)); // Transparent lookup accepts std::wstring
The get_range
adapters permit use ofrange-based for loopsto iterate over Windows Runtime collections.
Adapter | Error model |
---|---|
get_range | Exceptions |
get_range_nothrow | Error codes |
get_range_failfast | Fail fast |
C++/WinRT does not require an adapter.Range-based for loops are natively supported over C++/WinRT collections(anything that supports Windows.Foundation.IIterable<T>
).
See Ad-hoc range helpers for other iterator helpers.
Examples
// assume collection is IVector<T>*, IVectorView<T>*, or IIterable<T>*for (auto const& element : wil::get_range(collection)) ...for (auto const& element : wil::get_range_failfast(collection)) ...for (auto const& element : wil::get_range_nothrow(collection)) ...for (auto const& element : wil::get_range_nothrow(collection, &hr)) ...
In the case of get_range_nothrow
, an optional HRESULT*
parameterreceives the HRESULT
that caused the iteration to stop.If the iterator ran to completion successfully,or if the loop was explicitly exited with a break
statement,then the value will be S_OK
.
Warnings
- It is the caller's responsibility to ensure that thecollection lifetime extends to the completion of the
for
loop. - The collection's lifetime must encompass theuse of the iterators you obtain from the
get_range
functions. - The iterators obtained from
get_range
andget_range_failfast
arebidirectional iteratorswhich also support constant-time bidirectional advance. - The iterators obtained from
get_range_nothrow
functionareinput iteratorswhich also support constant-time bidirectional advance.However, only one iterator may be dereferenced.
extern Microsoft::WRL::ComPtr<IVector<T>> GetCollection();// WRONG! The smart pointer returned by GetCollection() is temporary// and will be destructed before the loop body runs.for (auto const& element : wil::get_range(GetCollection().Get())) ...// FIXED! Explicitly extend the lifetime of the collection.auto collection = GetCollection();for (auto const& element : wil::get_range(collection.Get())) ...// WRONG! The smart pointer returned by GetCollections() is temporary// and will be destructed while there are still active iterators.auto range = wil::get_range(GetCollection().Get());auto it = std::lower_bound(range.begin(), range.end(), value);// FIXED! Explicitly extend the lifetime of the collection.auto collection = GetCollection();auto range = wil::get_range(collection.Get());auto it = std::lower_bound(range.begin(), range.end(), value);// WRONG! The iterators produced by get_range_nothrow// are not forward iterators.auto collection = GetCollection();auto range = wil::get_range_nothrow(collection.Get());auto it = std::adjacent_find(range.begin(), range.end());
These functions permit basic operations with Windows Runtimeasynchronous operations,but they have been superseded byC++/WinRT.
For all the asynchronous operation helpers,the operation
can be
- An "action", which has no result:
IAsyncAction*
orIAsyncActionWithProgress<TProgress>*
- An "operation":
IAsyncOperation<TResult>*
orIAsyncOperationWithProgress<TResult, TProgress>*
Running code when an asynchronous operation completes
These functions have been superseded byC++/WinRT.Prefer to use C++/WinRT and co_await
to consume asynchronous operations.
Function | Error model |
---|---|
run_when_complete | Exceptions |
run_when_complete_nothrow | Error codes |
(no fail fast version) |
The general shape of the run_when_complete
family of functions is
template<typename TAgility>run_when_complete(operation, functor)
The TAgility
can be explicitly specified as Microsoft::WRL::FtmBase
to specify that the functor can be called on any thread.By default, the functor will be called back in the same apartment.
The functor's operator()
can take one of the following forms:
- For an action:
HRESULT func(HRESULT hr);
void func(HRESULT hr);
- For an operation whose result is an interface type
HRESULT func(HRESULT hr, TResult* result);
void func(HRESULT hr, TResult* result);
- For an operation whose result is a value type
HRESULT func(HRESULT hr, TResult result);
void func(HRESULT hr, TResult result);
The hr
reports whether the asynchronous operation completed successfully.
The result
is the result of the asynchronous operation.If the asynchronous operation failed, then result
is meaningless.
If the functor returns an HRESULT
, then that HRESULT
is the return valueof the continuation.
If the functor returns void
, then exceptions thrown by THROW_IF_FAILED
are caught and treated as the return value of the continuation.
The run_when_complete
function throws an exception if the continuationcannot be scheduled.
The run_when_complete_nothrow
function returns an HRESULT
specifyingwhether the continuation was successfully scheduled.
template<typename TAgility = IUnknown, typename TFunc>void run_when_complete(IAsyncAction* operation, TFunc&& func);template<typename TAgility = IUnknown, typename TProgress, typename TFunc>void run_when_complete(IAsyncActionWithProgress<TProgress>* operation, TFunc&& func);template<typename TAgility = IUnknown, typename TResult, typename TFunc>void run_when_complete(IAsyncOperation<TResult>* operation, TFunc&& func);template<typename TAgility = IUnknown, typename TResult, typename TProgress, typename TFunc>void run_when_complete(IAsyncOperationWithProgress<TResult, TProgress>* operation, TFunc&& func);template<typename TAgility = IUnknown, typename TFunc>HRESULT run_when_complete_nothrow(IAsyncAction* operation, TFunc&& func) noexcept;template<typename TAgility = IUnknown, typename TProgress, typename TFunc>HRESULT run_when_complete_nothrow(IAsyncActionWithProgress<TProgress>* operation, TFunc&& func) noexcept;template<typename TAgility = IUnknown, typename TResult, typename TFunc>HRESULT run_when_complete_nothrow(IAsyncOperation<TResult>* operation, TFunc&& func) noexcept;template<typename TAgility = IUnknown, typename TResult, typename TProgress, typename TFunc>HRESULT run_when_complete_nothrow(IAsyncOperationWithProgress<TResult, TProgress>* operation, TFunc&& func) noexcept;
Examples:
void CopyToParentFolderFireAndForget(IStorageFile* file){ Microsoft::WRL::ComPtr<IAsyncOperation<StorageFolder>> fileOperation; THROW_iF_FAILED(file->GetParentAsync(&fileOperation)); // Must extend lifetime of "file" into the lambda. run_when_complete(fileOperation.Get(), [file = wil::com_ptr<IStorageFile>(file)](HRESULT result, IStorageFolder* folder) { THROW_IF_FAILED(result); Microsoft::WRL::ComPtr<IAsyncOperation<StorageFolder>> copyOperation; THROW_IF_FAILED(file->CopyAsync(folder, ©Operation)); run_when_complete(copyOperation.Get(), [](HRESULT result, IStorageFile* /* copiedFile */) { THROW_IF_FAILED(result); }); });}// To permit the continuation to run in any thread, use FtmBase.run_when_complete<FtmBase>(fileOperation.Get(), [](HRESULT result, IStorageFile* file){ THROW_IF_FAILED(result); DoSomethingWith(file);});
Note that the lambda must extend the lifetimes of any objects it needs,because its execution is deferred until the completion of the asynchronous operation.In particular, it must not capture by reference.
Preferred C++/WinRT alternative:
// "file" parameter is non-const because we use it in the continuation.winrt::fire_and_forget CopyToParentFolder(StorageFile file){ auto folder = co_await file.GetParentAsync(); co_await file.CopyAsync(folder);}
Waiting for an asynchronous operation to complete
These functions have been superseded byC++/WinRT.Prefer to use C++/WinRT and get()
to consume asynchronous operations synchronously.
Function | Error model |
---|---|
wait_for_completion | Exceptions |
wait_for_completion_nothrow | Error codes |
(no fail fast version) | |
wait_for_completion_or_timeout_nothrow | Error codes |
call_and_wait_for_completion | Exceptions |
These functions wait for an asynchronous operation to complete or be canceled.Use them to wait synchronously from background threads.Do not use them from UI threads or STA threads as reentrancy will result.
The general shape of the wait_for_completion
family of functions is
HRESULT hr = wait_for_completion_nothrow(operation, &result);auto result = wait_for_completion(operation);
If the operation
is an action, then wait_for_completion_nothrow
has no result
parameter, and wait_for_completion
returns void
.
An optional final parameter of type COWAIT_FLAGS
can be provided to customize how the thread waitsfor the operation to complete.The default is COWAIT_DISPATCH_CALLS
.
If the function is unable to wait for the operation,or if the operation does not complete successfully,the error code is thrown (wait_for_completion
)or returned (wait_for_completion_nothrow
).No value is placed into result
.
void wait_for_completion(IAsyncAction* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);void wait_for_completion(IAsyncActionWithProgress<TProgress>* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);details::MapToSmartType<TResult> wait_for_completion(IAsyncOperation<TResult>* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);details::MapToSmartType<TResult> wait_for_completion(IAsyncOperationWithProgress<TResult, TProgress>* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS);HRESULT wait_for_completion_nothrow( IAsyncAction* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_nothrow( IAsyncActionWithProgress<TProgress>* operation, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_nothrow( IAsyncOperation<TResult>* operation, details::MapAsyncOpResultType<TResult>::type* result, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_nothrow( IAsyncOperationWithProgress<TResult, TProgress>* operation, details::MapAsyncOpResultType<TResult>::type* result, COWAIT_FLAGS flags = COWAIT_DISPATCH_CALLS) noexcept;
details::MapToSmartType<TResult>
depends on the nature of TResult
:
- If
TResult
isHSTRING
, thendetails::MapToSmartType<TResult>
isMicrosoft::WRL::Wrappers::HString
, with an additional methodReleaseAndGetAddressOf
. - If
TResult
is an interface type, thendetails::MapToSmartType<TResult>
isMicrosoft::WRL::ComPtr<TResult>
. - If
TResult
is a value type, thendetails::MapToSmartType<TResult>
isa custom type which behaves similarly toMicrosoft::WRL::ComPtr
.operator TResult() const
(conversion operator)
returns the wrapped value.TResult Get() const
returns the wrapped value.TResult&& Get()
returns the wrapped value as an rvalue reference.HRESULT CopyTo(TResult* result) const
copies the wrapped value, always returnsS_OK
.TResult* GetAddressOf()
returns the address of the wrapped value.TResult* ReleaseAndGetAddressOf()
returns the address of the wrapped value.TResult* operator&()
returns the address of the wrapped value.
details::MapAsyncOpResultType<TResult>::type
also depends on the nature of TResult
:
- If
TResult
is an interface type, thendetails::MapAsyncOpResultType<TResult>::type
isTResult*
. - Otherwise,
details::MapAsyncOpResultType<TResult>::type
isTResult
.
Waiting for completion with a timeout is done with thewait_for_completion_or_timeout_nothrow
function:
HRESULT hr = wait_for_completion_or_timeout_nothrow(operation, &result, timeout, &timedOut);
Again the result
is omitted if the operation
is an action.
The timeout is expressed in milliseconds.If the operation fails to complete before the timeout elapses,the wait_for_completion_or_timeout_nothrow
functionreturns S_OK
and sets timedOut
to true
.In all other cases, timedOut
is false
.
Aside from the timeout,the function behaves the same as wait_for_completion_nothrow
.
HRESULT wait_for_completion_or_timeout_nothrow( IAsyncAction* operation, DWORD timeout, bool* timedOut, flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_or_timeout_nothrow( IAsyncActionWithProgress<TProgress>* operation, DWORD timeout, bool* timedOut, flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_or_timeout_nothrow( IAsyncOperation<TResult>* operation, details::MapAsyncOpResultType<TResult>::type* result, DWORD timeout, bool* timedOut, flags = COWAIT_DISPATCH_CALLS) noexcept;HRESULT wait_for_completion_or_timeout_nothrow( IAsyncOperationWithProgress<TResult, TProgress>* operation, details::MapAsyncOpResultType<TResult>::type* result, DWORD timeout, bool* timedOut, flags = COWAIT_DISPATCH_CALLS) noexcept;
The call_and_wait_for_completion
variantuses the following pattern:
auto result = call_and_wait_for_completion(object, &Object::Method, args...);
It invokes the method on the object with the args...
,and then performs a wait_for_completion
on the operation.
template<typename I, typename ...P, typename ...Args>auto call_and_wait_for_completion(I* object, HRESULT(STDMETHODCALLTYPE I::*func)(P...), Args&&... args);
Examples:
IAsyncAction* action = ...;IAsyncOperation<int> intOperation = ...;IAsyncOperation<IInspectable> inspectableOperation = ...;// Waits for the action to complete, or throws if the action fails.wait_for_completion(action);// Waits for the operation to complete and returns the result.auto intResult = wait_for_completion(intOperation).Get();auto result = wait_for_completion(inspectableOperation);IInspectable* inspectable = result.Get(); // lifetime controlled by "result"// Call an asynchronous method and wait for the result.Microsoft::WRL::ComPtr<ILauncherStatics> launcherStatics = ...;auto result = call_and_wait_for_completion( launcherStatics.Get(), &ILauncherStatics::LaunchUriAsync, uri.Get());bool succeeded = result.Get();
Preferred C++/WinRT alternative:
IAsyncAction action = ...;IAsyncOperation<int32_t> intOperation = ...;IAsyncOperation<IInspectable> inspectableOperation = ...;// Waits for the action to complete, or throws if the action fails.action.get();// Waits for the operation to complete and returns the result.auto intResult = intOperation.get();IInspectable inspectable = inspectableOperation.get();// Call an asynchronous method and wait for the result.bool succeeded = winrt::Windows::System::Launcher::LaunchUriAsync(uri).get();
Creating already-completed asynchronous operations
These functions have been superseded byC++/WinRT.Prefer to use C++/WinRT and co_return
to produce asynchronous operations.
The make_synchronous_async_...
functionscreate asynchronous operations which have already completedwith a particular result.They are primarily intended for testing and mocking purposes.
Function | Error model |
---|---|
make_synchronous_async_action | Exceptions |
make_synchronous_async_operation | Exceptions |
make_synchronous_async_action_nothrow | Error codes |
make_synchronous_async_operation_nothrow | Error codes |
(no fail fast version) |
void make_synchronous_async_action(IAsyncAction** result);void make_synchronous_async_operation(IAsyncOperation<TResult>** result, const TResult& value);HRESULT make_synchronous_async_action_nothrow(IAsyncAction** result);HRESULT make_synchronous_async_operation_nothrow(IAsyncOperation<TResult>** result, const TResult& value);
The make_synchronous_async_action
andmake_synchronous_async_action_nothrow
functions createan already-completed IAsyncAction
.
The make_synchronous_async_operation
andmake_synchronous_async_operation_nothrow
functions createan already-completed IAsyncOperation<TResult>
,with the specified value as the completion result.
These functions have been superseded byC++/WinRT.Prefer to use C++/WinRT to access static methodsand construct objects.
GetActivationFactory
template<typename TInterface>com_ptr<TInterface> GetActivationFactory(PCWSTR runtimeClass);
The GetActivationFactory
function gets the activation factoryfor the named Windows Runtime class.
The TInterface
is the desired factory interface,usually a ISomethingStatics
interface.
If the factory could not be obtained,or the factory does not support the specified interface,then an exception is thrown.
Example:
// Invoking a static method.using namespace ABI::Windows::Security::Cryptography;auto statics = wil::GetActivationFactory<ICryptographicBufferStatics>( RuntimeClass_Windows_Security_Cryptography_CryptographicBuffer);uint32_t number;THROW_IF_FAILED(statics->GenerateRandomNumber(&number));// Constructing with parameters.using namespace ABI::Windows::Security::Credentials;auto factory = wil::GetActivationFactory<IPasswordCredentialFactory>( RuntimeClass_Windows_Security_Credentials_PasswordCredential);wil::unique_hstring resource = ...;wil::unique_hstring userName = ...;wil::unique_hstring password = ...;wil::com_ptr<IPasswordCredential> credential;THROW_IF_FAILED(factory->CreatePasswordCredential( resource.get(), userName.get(), password.get(), &credential));
Preferred C++/WinRT alternative:
// Invoking a static method.using namespace winrt::Windows::Security::Cryptography;uint32_t number = CryptographicBuffer::GenerateRandomNumber();// Constructing with parameters.using namespace winrt::Windows::Security::Credentials;winrt::hstring resource = ...;winrt::hstring userName = ...;winrt::hstring password = ...;PasswordCredential credential{ resource, userName, password };
ActivateInstance
template <typename TInterface>com_ptr<TInterface> ActivateInstance(PCWSTR runtimeClass);
The ActivateInstance
function activates an instanceof the named Windows Runtime classwith no parameters.In projected languages, this is equivalent toinvoking the default constructor.
The TInterface
is the desired interface on theresulting object.It is usually the object's default interface.
If the object could not be activated,or the object does not support the specified interface,then an exception is thrown.
Example:
using namespace ABI::Windows::Security::Credentials;wil::com_ptr<IPasswordCredential> credential = wil::ActivationInstance<IPasswordCredential>();
Preferred C++/WinRT alternative:
using namespace winrt::Windows::Security::Credentials;PasswordCredential credential;
These macros have been superseded byC++/WinRT.Prefer to use C++/WinRT to consume Windows Runtime events.
The unique_winrt_event_token
RAII typesmanage the EventRegistrationToken
for Windows Runtime eventsand unregister the event handler at destruction.
These types are often used in member variables.
The unique_winrt_event_token
types maintain a weak reference to theevent source.The WI_MakeUniqueWinrtEventToken
macros will fail if the event sourcedoes not support weak references.
WI_MakeUniqueWinRtEventToken(EventName, eventSource, handler, &token)
Registers for theeventSource::EventName
event with the specified handler.The token is stored in aunique_winrt_event_token<Source>
.Throws an exception on failure.WI_MakeUniqueWinRtEventTokenFailFast(EventName, eventSource, handler, &token)
Registers for theeventSource::EventName
event with the specified handler.The token is stored in aunique_winrt_event_token<Source>
.Fails fast on failure.WI_MakeUniqueWinRtEventTokenNoThrow(EventName, eventSource, handler, &token)
Registers for theeventSource::EventName
event with the specified handler.The token is stored in aunique_winrt_event_token<Source>
.Returns anHRESULT
to indicate whether the operation succeeded.WI_MakeUniqueWinRtEventTokenCx(EventName, eventSource, handler)
Registers for theeventSource::EventName
event with the specified handler.The token is returned as aunique_winrt_event_token_cx<Source>
.Throws an exception on failure.WI_MakeUniqueWinRtStaticEventTokenCx(EventName, Source, handler)
Registers for the staticSource::EventName
event with the specified handler.The token is returned as aunique_winrt_event_token_cx<Source>
.Throws an exception on failure.
Note that only WI_MakeUniqueWinRtStaticEventTokenCx
supports static events.
Usage
Example of ABI usage:
wil::com_ptr<Widget> widget = ...;wil::com_ptr<TypedEventHandler<Widget, WidgetClosedEventArgs>> handler = ...;wil::unique_winrt_event_token<Widget> token;// Using exceptions.WI_MakeUniqueWinRtEventToken(Closed, widget.get(), handler.get(), &token);// Using fail-fast.WI_MakeUniqueWinRtEventTokenFailFast(Closed, widget.get(), handler.get(), &token);// Using HRESULTs.RETURN_IF_FAILED(WI_MakeUniqueWinRtEventTokenNoThrow(Closed, widget.get(), handler.get(), &token));
Example of C++/CX usage:
Widget^ widget = ...;TypedEventHandler<Widget, WidgetClosedEventArgs>^ handler = ...;// Register an instance event, throws on failure.wil::unique_winrt_event_token_cx<Widget> token = WI_MakeUniqueWinRtEventTokenCx(Closed, widget, handler);// Register a static event, throws on failure.EventHandler<WidgetAddedEventArgs>^ handler = ...;wil::unique_winrt_event_token_cx<Widget> token = WI_MakeUniqueWinRtStaticEventTokenCx(WidgetAdded, Widget, handler);
The C++/WinRT equivalent is winrt::event_revoker
.