diff options
Diffstat (limited to 'Rx/v2/examples/win_text')
-rw-r--r-- | Rx/v2/examples/win_text/CMakeLists.txt | 54 | ||||
-rw-r--r-- | Rx/v2/examples/win_text/main.cpp | 244 | ||||
-rw-r--r-- | Rx/v2/examples/win_text/rx_windows_user.h | 117 | ||||
-rw-r--r-- | Rx/v2/examples/win_text/unwinder.h | 54 | ||||
-rw-r--r-- | Rx/v2/examples/win_text/windows_user.h | 118 |
5 files changed, 0 insertions, 587 deletions
diff --git a/Rx/v2/examples/win_text/CMakeLists.txt b/Rx/v2/examples/win_text/CMakeLists.txt deleted file mode 100644 index 8aabd25..0000000 --- a/Rx/v2/examples/win_text/CMakeLists.txt +++ /dev/null @@ -1,54 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -get_filename_component(SAMPLE_PROJECT "${CMAKE_CURRENT_SOURCE_DIR}" NAME) - -project(${SAMPLE_PROJECT}) - -FIND_PACKAGE(Threads) - -MESSAGE( STATUS "CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID} ) -if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - MESSAGE( STATUS "using clang settings" ) - add_compile_options( -Wall -Wextra -Werror ) - add_compile_options( -std=c++11 -stdlib=libc++ ) - add_compile_options( -ftemplate-depth=1024 ) # sometimes you just do what the compiler tells you -elseif (CMAKE_CXX_COMPILER_ID MATCHES "GNU") - MESSAGE( STATUS "using gnu settings" ) - add_compile_options( -Wall -Wextra -Werror ) - add_compile_options( -std=c++11 ) -elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") - MESSAGE( STATUS "using msvc settings" ) - add_compile_options( /W4 /WX ) - add_compile_options( /wd4503 ) # truncated symbol - add_compile_options( /wd4702 ) # unreachable code - add_compile_options( /wd4091 ) # typedef ignored on left when no variable is declared - add_compile_options( /bigobj ) - add_definitions( /DUNICODE /D_UNICODE ) # it is a new millenium -endif() - - -# define some folders -get_filename_component(RXCPP_DIR "${CMAKE_CURRENT_SOURCE_DIR}" PATH) -get_filename_component(RXCPP_DIR "${RXCPP_DIR}" PATH) -get_filename_component(RXCPP_DIR "${RXCPP_DIR}" PATH) -get_filename_component(RXCPP_DIR "${RXCPP_DIR}" PATH) - -MESSAGE( STATUS "RXCPP_DIR: " ${RXCPP_DIR} ) - -include_directories(SYSTEM ${RXCPP_DIR}/ext/catch/include) -include_directories(${RXCPP_DIR}/Ix/CPP/src ${RXCPP_DIR}/Rx/v2/src) - -# define the sources -set(SAMPLE_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp -) -add_executable(${SAMPLE_PROJECT} WIN32 ${SAMPLE_SOURCES}) -TARGET_LINK_LIBRARIES(${SAMPLE_PROJECT} ${CMAKE_THREAD_LIBS_INIT}) - -# configure unit tests via CTest -enable_testing() -set(CTEST_CONFIGURATION_TYPE "${JOB_BUILD_CONFIGURATION}") - -add_test(NAME RunTests - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" - COMMAND ${SAMPLE_PROJECT} ${TEST_ARGS})
\ No newline at end of file diff --git a/Rx/v2/examples/win_text/main.cpp b/Rx/v2/examples/win_text/main.cpp deleted file mode 100644 index 709cc2f..0000000 --- a/Rx/v2/examples/win_text/main.cpp +++ /dev/null @@ -1,244 +0,0 @@ - -// win_text.cpp : Defines the entry point for the application. -// -// - -#define STRICT -#define WIN32_LEAN_AND_MEAN -#define NOMINMAX - -#include <windows.h> -#include <windowsx.h> -#include <ole2.h> -#include <commctrl.h> -#include <shlwapi.h> -#include <shlobj.h> -#include <shellapi.h> - -#pragma comment(lib, "user32.lib") -#pragma comment(lib, "gdi32.lib") -#pragma comment(lib, "Comctl32.lib") -#pragma comment(lib, "Ole32.lib") - -#include <new> -#include <utility> -#include <memory> -#include <type_traits> -#include <tuple> -#include <list> - -#include "rxcpp/rx.hpp" -// create alias' to simplify code -// these are owned by the user so that -// conflicts can be managed by the user. -namespace rx=rxcpp; -namespace rxsub=rxcpp::subjects; -namespace rxu=rxcpp::util; - -// At this time, RxCpp will fail to compile if the contents -// of the std namespace are merged into the global namespace -// DO NOT USE: 'using namespace std;' - -#include "unwinder.h" - -#include "windows_user.h" -namespace wu = windows_user; - -#include "rx_windows_user.h" -namespace rxwu = rxcpp::windows_user; - -struct RootWindow : public rxwu::rx_messages, public rxwu::enable_send_call<RootWindow, WM_USER+1> -{ - // window class - using window_class = wu::window_class<RootWindow>; - static LPCWSTR class_name() {return L"Scratch";} - static void change_class(WNDCLASSEX&) {} - - // createstruct parameter type - using param_type = std::wstring; - - // public methods - - // static methods use a window message per call - - static LRESULT set_title(HWND w, const std::wstring& t) { - return send_call(w, [&](RootWindow& r){ - r.set_title(t); - return 0; - }); - } - static std::wstring get_title(HWND w) { - std::wstring t; - send_call(w, [&](RootWindow& r){ - t = r.get_title(); - return 0; - }); - return t; - } - - // instance methods are accessed using static send_call(hwnd, [](RootWindow& r){. . .}); - // send_call uses one window message, the lambda can call many instance methods. - - void set_title(const std::wstring& t) { - title = t; - } - const std::wstring& get_title() { - return title; - } - - // lifetime - - // called during WM_NCDESTROY - ~RootWindow() { - PostQuitMessage(0); - } - - // called during WM_NCCREATE - RootWindow(HWND w, LPCREATESTRUCT, param_type* title) - : window(w) - , title(title ? *title : L"RootWindow") - , position{40, 10} { - // listen for the following messages - OnPaint(); - OnPrintClient(); - OnKeyDown(); - OnMovesWhileLButtonDown(); - } - -private: - // implementation - - HWND window; - std::wstring title; - POINTS position; - - void PaintContent(PAINTSTRUCT& ps) { - RECT rect; - GetClientRect (window, &rect) ; - SetTextColor(ps.hdc, 0x00000000); - SetBkMode(ps.hdc,TRANSPARENT); - rect.left=position.x; - rect.top=position.y; - DrawText( ps.hdc, title.c_str(), -1, &rect, DT_SINGLELINE | DT_NOCLIP ) ; - } - - void OnKeyDown() { - messages<WM_KEYDOWN>(). - subscribe([this](auto m) { - m.handled(); // skip DefWindowProc - - MessageBox(window, L"KeyDown", L"RootWindow", MB_OK); - // NOTE: MessageBox pumps messages, but this subscription only - // receives messages if it is suspended by 'for await', so any - // WM_KEYDOWN arriving while the message box is up is not delivered. - // the other subscriptions will receive messages. - }); - } - - void OnMovesWhileLButtonDown() { - - auto moves_while_lbutton_down = messages<WM_LBUTTONDOWN>(). - map( - [this](auto m) { - m.handled(); // skip DefWindowProc - - return this->messages<WM_MOUSEMOVE>(). - take_until(this->messages<WM_LBUTTONUP>()); - }). - merge(); - - moves_while_lbutton_down. - subscribe([this](auto m) { - m.handled(); // skip DefWindowProc - - position = MAKEPOINTS(m.lParam); - InvalidateRect(window, nullptr, true); - }); - } - - void OnPaint() { - messages<WM_PAINT>(). - subscribe([this](auto m) { - m.handled(); // skip DefWindowProc - - PAINTSTRUCT ps; - BeginPaint(window, &ps); - PaintContent(ps); - EndPaint(window, &ps); - }); - } - - void OnPrintClient() { - messages<WM_PRINTCLIENT, HDC>(). - subscribe([this](auto m) { - m.handled(); // skip DefWindowProc - - PAINTSTRUCT ps; - ps.hdc = m.wParam; - GetClientRect(window, &ps.rcPaint); - PaintContent(ps); - }); - } -}; - -int PASCAL -wWinMain(HINSTANCE hinst, HINSTANCE, LPWSTR, int nShowCmd) -{ - HRESULT hr = S_OK; - - hr = CoInitialize(NULL); - if (FAILED(hr)) - { - return FALSE; - } - ON_UNWIND_AUTO([&]{CoUninitialize();}); - - InitCommonControls(); - - RootWindow::window_class::Register(); - - LONG winerror = ERROR_SUCCESS; - - std::wstring title{L"Scratch App - RootWindow"}; - - // normal create window call, just takes the class name and optional create parameters - HWND window = CreateWindow( - RootWindow::window_class::Name(), title.c_str(), - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - NULL, NULL, - hinst, - &title); - if (!window) {winerror = GetLastError();} - - if (!!winerror || !window) - { - return winerror; - } - - ShowWindow(window, nShowCmd); - - // interact with window safely on the UI thread from another thread - auto settitle = std::async([window](){ - - // by static method (two SendMessage) - RootWindow::set_title(window, L"SET_TITLE! " + RootWindow::get_title(window)); - - // or multiple instance methods (one SendMessage) - RootWindow::send_call(window, [](RootWindow& r){ - r.set_title(L"SEND_CALL! " + r.get_title()); - return 0; - }); - }); - - MSG msg = {}; - while (GetMessage(&msg, NULL, 0, 0)) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - settitle.get(); - - return 0; -} diff --git a/Rx/v2/examples/win_text/rx_windows_user.h b/Rx/v2/examples/win_text/rx_windows_user.h deleted file mode 100644 index 708eaf6..0000000 --- a/Rx/v2/examples/win_text/rx_windows_user.h +++ /dev/null @@ -1,117 +0,0 @@ -#pragma once - -namespace rxcpp { namespace windows_user { - - struct rx_messages - { - struct Result - { - LRESULT lres = 0; - bool handled = false; - }; - - struct Message - { - template<UINT WM> - static auto is() { return [](Message m){ return m.message == WM; }; } - - HWND hWnd; - UINT message; - WPARAM wParam; - LPARAM lParam; - Result* result; - - void handled() { result->handled = true; } - void lresult(LRESULT lres) {result->lres = lres; } - - template<class T> - T wparam_cast(){ - return *reinterpret_cast<T*>(std::addressof(wParam)); - } - - template<class T> - T lparam_cast(){ - return *reinterpret_cast<T*>(std::addressof(lParam)); - } - }; - - template<class WPARAM_t = WPARAM, class LPARAM_t = LPARAM> - struct TypedMessage - { - static auto as() { return [](Message m){return TypedMessage{m}; }; } - - TypedMessage(Message m) - : hWnd(m.hWnd) - , message(m.message) - , wParam(m.wparam_cast<WPARAM_t>()) - , lParam(m.lparam_cast<LPARAM_t>()) - , result(m.result) - {} - - HWND hWnd; - UINT message; - WPARAM_t wParam; - LPARAM_t lParam; - Result* result; - - void handled() { result->handled = true; } - void lresult(LRESULT lres) {result->lres = lres; } - }; - - subjects::subject<Message> subject; - subscriber<Message> sub; - - ~rx_messages() { - sub.on_completed(); - } - rx_messages() : sub(subject.get_subscriber()) {} - - std::tuple<bool, LRESULT> message(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - Result result; - auto m = Message{hWnd, message, wParam, lParam, &result}; - try { - sub.on_next(m); - } catch(...) { - sub.on_error(std::current_exception()); - } - return std::make_tuple(result.handled, result.lres); - } - - observable<Message> messages() { - return subject.get_observable(); - } - - template<UINT WM> - observable<Message> messages() { - return messages().filter(Message::is<WM>()); - } - - template<UINT WM, class WPARAM_t, class LPARAM_t = LPARAM> - observable<TypedMessage<WPARAM_t, LPARAM_t>> messages() { - return messages<WM>().map(TypedMessage<WPARAM_t, LPARAM_t>::as()); - } - - }; - - template<class Derived, UINT WM> - struct enable_send_call - { - static LRESULT send_call(HWND w, std::function<LRESULT(Derived&)> f) { - auto fp = reinterpret_cast<LPARAM>(std::addressof(f)); - return SendMessage(w, WM, 0, fp); - } - - void OnSendCall() { - auto derived = static_cast<Derived*>(this); - derived->messages<WM, WPARAM, std::function<LRESULT(Derived&)>*>(). - subscribe([=](auto m) { - m.handled(); // skip DefWindowProc - m.lresult((*m.lParam)(*derived)); - }); - } - - enable_send_call() { - OnSendCall(); - } - }; -} } diff --git a/Rx/v2/examples/win_text/unwinder.h b/Rx/v2/examples/win_text/unwinder.h deleted file mode 100644 index a01a170..0000000 --- a/Rx/v2/examples/win_text/unwinder.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -namespace unwinder { namespace detail { - - template<typename Function> - class unwinder - { - public: - ~unwinder() noexcept - { - if (!!function) - { - (*function)(); - } - } - - explicit unwinder(Function* functionArg) - : function(functionArg) - { - } - - void dismiss() - { - function = nullptr; - } - - unwinder& operator=(nullptr_t) { - dismiss(); - return *this; - } - - private: - unwinder(); - unwinder(const unwinder&); - unwinder& operator=(const unwinder&); - - Function* function; - }; -} } - -#define UNWIND_MAKE_IDENTIFIER_EXPLICIT_PASTER(Prefix, Suffix) Prefix ## Suffix -#define UNWIND_MAKE_IDENTIFIER_EXPLICIT(Prefix, Suffix) UNWIND_MAKE_IDENTIFIER_EXPLICIT_PASTER(Prefix, Suffix) - -#define UNWIND_MAKE_IDENTIFIER(Prefix) UNWIND_MAKE_IDENTIFIER_EXPLICIT(Prefix, __LINE__) - -#define ON_UNWIND(Name, Function) \ - ON_UNWIND_EXPLICIT(uwfunc_ ## Name, Name, Function) - -#define ON_UNWIND_AUTO(Function) \ - ON_UNWIND_EXPLICIT(UNWIND_MAKE_IDENTIFIER(uwfunc_), UNWIND_MAKE_IDENTIFIER(unwind_), Function) - -#define ON_UNWIND_EXPLICIT(FunctionName, UnwinderName, Function) \ - auto FunctionName = (Function); \ - ::unwinder::detail::unwinder<decltype(FunctionName)> UnwinderName(std::addressof(FunctionName)) diff --git a/Rx/v2/examples/win_text/windows_user.h b/Rx/v2/examples/win_text/windows_user.h deleted file mode 100644 index 418f73f..0000000 --- a/Rx/v2/examples/win_text/windows_user.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once - -namespace windows_user { - - EXTERN_C IMAGE_DOS_HEADER __ImageBase; - inline HINSTANCE GetCurrentInstance(){ return ((HINSTANCE)&__ImageBase); } - - template<typename Type> - LRESULT CALLBACK WindowCallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) noexcept; - - template<typename Type> - class window_class - { - public: - static LPCWSTR Name() { - return Type::class_name(); - } - - static ATOM Register() { - WNDCLASSEX wcex = {}; - wcex.cbSize = sizeof(WNDCLASSEX); - - // defaults that can be overriden - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.hInstance = GetCurrentInstance(); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.style = 0; - wcex.hIcon = NULL; - wcex.hCursor = LoadCursor(NULL, IDC_ARROW); - wcex.lpszMenuName = NULL; - - Type::change_class(wcex); - - // not overridable - wcex.lpszClassName = Name(); - wcex.lpfnWndProc = WindowCallback<Type>; - - return RegisterClassEx(&wcex); - } - - private: - ~window_class(); - window_class(); - window_class(window_class&); - window_class& operator=(window_class&); - }; - - namespace detail { - template<typename Type> - std::unique_ptr<Type> find(HWND hwnd) { - return std::unique_ptr<Type>(reinterpret_cast<Type*>(GetWindowLongPtr(hwnd, GWLP_USERDATA))); - } - - void erase(HWND hwnd) { - SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); - } - - template<typename Type> - std::unique_ptr<Type> insert(HWND hwnd, std::unique_ptr<Type> type) { - if (!type) { - return nullptr; - } - - SetLastError(0); - - ON_UNWIND(unwind_userdata, [&](){erase(hwnd);}); - auto result = SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(type.get())); - - LONG winerror = !result ? GetLastError() : ERROR_SUCCESS; - - if (!!winerror || !!result) { - return nullptr; - } - - unwind_userdata.dismiss(); - return type; - } - } - - template<typename Type> - LRESULT CALLBACK WindowCallback(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) noexcept { - auto type = detail::find<Type>(hWnd); - // don't delete type - ON_UNWIND(unwind_type, [&](){type.release();}); - - if (message == WM_NCCREATE) { - if (type) { - // the slot where we would store our type instance is full. abort. - return FALSE; - } - auto cs = reinterpret_cast<LPCREATESTRUCT>(lParam); - auto param = reinterpret_cast<Type::param_type*>(cs->lpCreateParams); - type = detail::insert(hWnd, std::unique_ptr<Type>(new (std::nothrow) Type(hWnd, cs, param))); - if (!type) { - return FALSE; - } - } - - LRESULT lResult = 0; - bool handled = false; - - if (type) { - std::tie(handled, lResult) = type->message(hWnd, message, wParam, lParam); - } - - if (!handled) { - lResult = DefWindowProc(hWnd, message, wParam, lParam); - } - - if (message == WM_NCDESTROY) { - detail::erase(hWnd); - // let type destruct - unwind_type.dismiss(); - } - - return lResult; - } -} |