get_message_iterator
なんとなくWindowsのメッセージループを反復子にするアイデアを思いついたので書いてみました。
役に立つかは不明です。
以下、コード。
#include <boost/iterator/iterator_facade.hpp> #include <stdexcept> #include <windows.h> // A/W切り分け用 template<class CharT> struct window_message_traits; template<> struct window_message_traits<char> { static ::BOOL get_message( ::MSG& msg, ::HWND hwnd, ::UINT min_msg, ::UINT max_msg) { return ::GetMessageA(&msg, hwnd, min_msg, max_msg); } static ::LRESULT dispatch_message(const ::MSG& msg) { return ::DispatchMessageA(&msg); } }; template<> struct window_message_traits<wchar_t> { static ::BOOL get_message( ::MSG& msg, ::HWND hwnd, ::UINT min_msg, ::UINT max_msg) { return ::GetMessageW(&msg, hwnd, min_msg, max_msg); } static ::LRESULT dispatch_message(const ::MSG& msg) { return ::DispatchMessageW(&msg); } }; // GetMessage()する反復子 template<class CharT=char> class get_message_iterator : public boost::iterator_facade< get_message_iterator<CharT>, const ::MSG, boost::single_pass_traversal_tag > { friend class boost::iterator_core_access; public: get_message_iterator() : hwnd_(0), min_(0), max_(0) { msg_.message = WM_QUIT; } explicit get_message_iterator(::HWND hwnd) : hwnd_(hwnd), min_(0), max_(0) { increment(); } get_message_iterator(::HWND hwnd, ::UINT min_msg, ::UINT max_msg) : hwnd_(hwnd), min_(min_msg), max_(max_msg) { increment(); } private: ::MSG msg_; ::HWND hwnd_; ::UINT min_; ::UINT max_; const ::MSG& dereference() const { return msg_; } void increment() { typedef window_message_traits<CharT> traits; ::BOOL res = traits::get_message(msg_, hwnd_, min_, max_); if (res == -1) throw std::runtime_error("GetMessage() failed"); } bool equal(const get_message_iterator& rhs) const { return msg_.message == rhs.msg_.message; } }; // DispatchMessage()する反復子 template <class CharT=char> struct dispatch_message_iterator : public std::iterator<std::output_iterator_tag,void,void,void,void> { dispatch_message_iterator() { } dispatch_message_iterator& operator=(const ::MSG& msg) { typedef window_message_traits<CharT> traits; traits::dispatch_message(msg); return *this; } dispatch_message_iterator& operator*() { return *this; } dispatch_message_iterator& operator++() { return *this; } dispatch_message_iterator& operator++(int) { return *this; } }; // TranslateMessage()して、素通しするファンクタ struct translate_message { ::MSG operator()(const ::MSG& msg) const { ::TranslateMessage(&msg); return msg; } }; // お試し #include <algorithm> #include <iostream> int main() { try { ::PostQuitMessage(0); std::transform( get_message_iterator<>(0), get_message_iterator<>(), dispatch_message_iterator<>(), translate_message() ); } catch (const std::exception& e) { std::cout << e.what() << std::endl; } }