• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #pragma once
2 
3 namespace rxcpp { namespace windows_user {
4 
5     struct rx_messages
6     {
7         struct Result
8         {
9             LRESULT lres = 0;
10             bool handled = false;
11         };
12 
13         struct Message
14         {
15             template<UINT WM>
isrx_messages::Message16             static auto is() { return [](Message m){ return m.message == WM; }; }
17 
18             HWND hWnd;
19             UINT message;
20             WPARAM wParam;
21             LPARAM lParam;
22             Result* result;
23 
handledrx_messages::Message24             void handled() { result->handled = true; }
lresultrx_messages::Message25             void lresult(LRESULT lres) {result->lres = lres; }
26 
27             template<class T>
wparam_castrx_messages::Message28             T wparam_cast(){
29                 return *reinterpret_cast<T*>(std::addressof(wParam));
30             }
31 
32             template<class T>
lparam_castrx_messages::Message33             T lparam_cast(){
34                 return *reinterpret_cast<T*>(std::addressof(lParam));
35             }
36         };
37 
38         template<class WPARAM_t = WPARAM, class LPARAM_t = LPARAM>
39         struct TypedMessage
40         {
asrx_messages::TypedMessage41             static auto as() { return [](Message m){return TypedMessage{m}; }; }
42 
TypedMessagerx_messages::TypedMessage43             TypedMessage(Message m)
44                 : hWnd(m.hWnd)
45                 , message(m.message)
46                 , wParam(m.wparam_cast<WPARAM_t>())
47                 , lParam(m.lparam_cast<LPARAM_t>())
48                 , result(m.result)
49             {}
50 
51             HWND hWnd;
52             UINT message;
53             WPARAM_t wParam;
54             LPARAM_t lParam;
55             Result* result;
56 
handledrx_messages::TypedMessage57             void handled() { result->handled = true; }
lresultrx_messages::TypedMessage58             void lresult(LRESULT lres) {result->lres = lres; }
59         };
60 
61         subjects::subject<Message> subject;
62         subscriber<Message> sub;
63 
~rx_messagesrx_messages64         ~rx_messages() {
65             sub.on_completed();
66         }
rx_messagesrx_messages67         rx_messages() : sub(subject.get_subscriber()) {}
68 
messagerx_messages69         std::tuple<bool, LRESULT> message(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
70             Result result;
71             auto m = Message{hWnd, message, wParam, lParam, &result};
72             try {
73                 sub.on_next(m);
74             } catch(...) {
75                 sub.on_error(std::current_exception());
76             }
77             return std::make_tuple(result.handled, result.lres);
78         }
79 
messagesrx_messages80         observable<Message> messages() {
81             return subject.get_observable();
82         }
83 
84         template<UINT WM>
messagesrx_messages85         observable<Message> messages() {
86             return messages().filter(Message::is<WM>());
87         }
88 
89         template<UINT WM, class WPARAM_t, class LPARAM_t = LPARAM>
messagesrx_messages90         observable<TypedMessage<WPARAM_t, LPARAM_t>> messages() {
91             return messages<WM>().map(TypedMessage<WPARAM_t, LPARAM_t>::as());
92         }
93 
94     };
95 
96     template<class Derived, UINT WM>
97     struct enable_send_call
98     {
send_callenable_send_call99         static LRESULT send_call(HWND w, std::function<LRESULT(Derived&)> f) {
100             auto fp = reinterpret_cast<LPARAM>(std::addressof(f));
101             return SendMessage(w, WM, 0, fp);
102         }
103 
OnSendCallenable_send_call104         void OnSendCall() {
105             auto derived = static_cast<Derived*>(this);
106             derived->messages<WM, WPARAM, std::function<LRESULT(Derived&)>*>().
107                 subscribe([=](auto m) {
108                     m.handled(); // skip DefWindowProc
109                     m.lresult((*m.lParam)(*derived));
110                 });
111         }
112 
enable_send_callenable_send_call113         enable_send_call() {
114             OnSendCall();
115         }
116     };
117 } }
118