-
Notifications
You must be signed in to change notification settings - Fork 236
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add for_each_window and for_each_thread_window helpers (#403)
* fix RegistryTests (warning as errors breaking on signed/unsigned comparison) * add for_each_window and for_each_thread_window helpers * . * simplify wrappers, add child window, can work w/mutable lambdas * format * only expose throwing versions when WIL_ENABLE_EXCEPTIONS is set * 'format' * . * . * unused result_t * Update include/wil/windowing.h Co-authored-by: Duncan Horn <[email protected]> * Update include/wil/windowing.h Co-authored-by: Duncan Horn <[email protected]> * pr fb --------- Co-authored-by: Duncan Horn <[email protected]>
- Loading branch information
Showing
3 changed files
with
396 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
//********************************************************* | ||
// | ||
// Copyright (c) Microsoft. All rights reserved. | ||
// This code is licensed under the MIT License. | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF | ||
// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED | ||
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A | ||
// PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
// | ||
//********************************************************* | ||
#ifndef __WIL_WINDOWING_INCLUDED | ||
#define __WIL_WINDOWING_INCLUDED | ||
|
||
#include <WinUser.h> | ||
#include <exception> | ||
|
||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) | ||
namespace wil | ||
{ | ||
namespace details | ||
{ | ||
template <typename T> | ||
struct always_false : wistd::false_type | ||
{ | ||
}; | ||
|
||
template <typename TEnumApi, typename TCallback> | ||
void DoEnumWindowsNoThrow(TEnumApi&& enumApi, TCallback&& callback) noexcept | ||
{ | ||
auto enumproc = [](HWND hwnd, LPARAM lParam) -> BOOL { | ||
auto pCallback = reinterpret_cast<TCallback*>(lParam); | ||
#ifdef __cpp_if_constexpr | ||
using result_t = decltype((*pCallback)(hwnd)); | ||
if constexpr (wistd::is_void_v<result_t>) | ||
{ | ||
(*pCallback)(hwnd); | ||
return TRUE; | ||
} | ||
else if constexpr (wistd::is_same_v<result_t, HRESULT>) | ||
{ | ||
// NB: this works for both HRESULT and NTSTATUS as both S_OK and ERROR_SUCCESS are 0 | ||
return (S_OK == (*pCallback)(hwnd)) ? TRUE : FALSE; | ||
} | ||
else if constexpr (std::is_same_v<result_t, bool>) | ||
{ | ||
return (*pCallback)(hwnd) ? TRUE : FALSE; | ||
} | ||
else | ||
{ | ||
static_assert(details::always_false<TCallback>::value, "Callback must return void, bool, or HRESULT"); | ||
} | ||
#else | ||
return (*pCallback)(hwnd); | ||
#endif | ||
}; | ||
enumApi(enumproc, reinterpret_cast<LPARAM>(&callback)); | ||
} | ||
|
||
#ifdef WIL_ENABLE_EXCEPTIONS | ||
template <typename TEnumApi, typename TCallback> | ||
void DoEnumWindows(TEnumApi&& enumApi, TCallback&& callback) | ||
{ | ||
struct | ||
{ | ||
std::exception_ptr exception; | ||
TCallback* pCallback; | ||
} callbackData = {nullptr, &callback}; | ||
auto enumproc = [](HWND hwnd, LPARAM lParam) -> BOOL { | ||
auto pCallbackData = reinterpret_cast<decltype(&callbackData)>(lParam); | ||
try | ||
{ | ||
auto pCallback = pCallbackData->pCallback; | ||
#ifdef __cpp_if_constexpr | ||
using result_t = decltype((*pCallback)(hwnd)); | ||
if constexpr (std::is_void_v<result_t>) | ||
{ | ||
(*pCallback)(hwnd); | ||
return TRUE; | ||
} | ||
else if constexpr (std::is_same_v<result_t, HRESULT>) | ||
{ | ||
// NB: this works for both HRESULT and NTSTATUS as both S_OK and ERROR_SUCCESS are 0 | ||
return (S_OK == (*pCallback)(hwnd)) ? TRUE : FALSE; | ||
} | ||
else if constexpr (std::is_same_v<result_t, bool>) | ||
{ | ||
return (*pCallback)(hwnd) ? TRUE : FALSE; | ||
} | ||
else | ||
{ | ||
static_assert(details::always_false<TCallback>::value, "Callback must return void, bool, or HRESULT"); | ||
} | ||
#else | ||
return (*pCallback)(hwnd); | ||
#endif | ||
} | ||
catch (...) | ||
{ | ||
pCallbackData->exception = std::current_exception(); | ||
return FALSE; | ||
} | ||
}; | ||
enumApi(enumproc, reinterpret_cast<LPARAM>(&callbackData)); | ||
if (callbackData.exception) | ||
{ | ||
std::rethrow_exception(callbackData.exception); | ||
} | ||
} | ||
#endif | ||
} // namespace details | ||
|
||
template <typename TCallback> | ||
void for_each_window_nothrow(TCallback&& callback) noexcept | ||
{ | ||
details::DoEnumWindowsNoThrow(&EnumWindows, wistd::forward<TCallback>(callback)); | ||
} | ||
|
||
template <typename TCallback> | ||
void for_each_thread_window_nothrow(_In_ DWORD threadId, TCallback&& callback) noexcept | ||
{ | ||
auto boundEnumThreadWindows = [threadId](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL { | ||
return EnumThreadWindows(threadId, enumproc, lParam); | ||
}; | ||
details::DoEnumWindowsNoThrow(boundEnumThreadWindows, wistd::forward<TCallback>(callback)); | ||
} | ||
|
||
template <typename TCallback> | ||
void for_each_child_window_nothrow(_In_ HWND hwndParent, TCallback&& callback) noexcept | ||
{ | ||
auto boundEnumChildWindows = [hwndParent](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL { | ||
return EnumChildWindows(hwndParent, enumproc, lParam); | ||
}; | ||
details::DoEnumWindowsNoThrow(boundEnumChildWindows, wistd::forward<TCallback>(callback)); | ||
} | ||
|
||
#ifdef WIL_ENABLE_EXCEPTIONS | ||
template <typename TCallback> | ||
void for_each_window(TCallback&& callback) | ||
{ | ||
details::DoEnumWindows(&EnumWindows, wistd::forward<TCallback>(callback)); | ||
} | ||
|
||
template <typename TCallback> | ||
void for_each_thread_window(_In_ DWORD threadId, TCallback&& callback) | ||
{ | ||
auto boundEnumThreadWindows = [threadId](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL { | ||
return EnumThreadWindows(threadId, enumproc, lParam); | ||
}; | ||
details::DoEnumWindows(boundEnumThreadWindows, wistd::forward<TCallback>(callback)); | ||
} | ||
|
||
template <typename TCallback> | ||
void for_each_child_window(_In_ HWND hwndParent, TCallback&& callback) | ||
{ | ||
auto boundEnumChildWindows = [hwndParent](WNDENUMPROC enumproc, LPARAM lParam) noexcept -> BOOL { | ||
return EnumChildWindows(hwndParent, enumproc, lParam); | ||
}; | ||
details::DoEnumWindows(boundEnumChildWindows, wistd::forward<TCallback>(callback)); | ||
} | ||
#endif | ||
|
||
} // namespace wil | ||
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) | ||
#endif // __WIL_WINDOWING_INCLUDED |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.