├── .travis.yml ├── CMakeLists.txt ├── COPYING ├── Doxyfile.in ├── README.md ├── WasherConfig.cmake.in ├── cmake ├── HunterGate.cmake ├── i686-w64-mingw32.cmake └── max_warnings.cmake ├── include └── washer │ ├── clipboard.hpp │ ├── com │ ├── catch.hpp │ ├── object.hpp │ └── ole_window.hpp │ ├── detail │ ├── path_traits.hpp │ └── remove_calling_convention.hpp │ ├── dynamic_link.hpp │ ├── error.hpp │ ├── filesystem.hpp │ ├── global_lock.hpp │ ├── gui │ ├── commands.hpp │ ├── hwnd.hpp │ ├── icon │ │ └── icon.hpp │ ├── menu │ │ ├── basic_menu.hpp │ │ ├── button │ │ │ ├── bitmap_button.hpp │ │ │ ├── bitmap_button_description.hpp │ │ │ ├── button.hpp │ │ │ ├── button_description.hpp │ │ │ ├── owner_drawn_button.hpp │ │ │ ├── owner_drawn_button_description.hpp │ │ │ ├── string_button.hpp │ │ │ └── string_button_description.hpp │ │ ├── detail │ │ │ ├── item_common.hpp │ │ │ ├── item_iterator.hpp │ │ │ ├── item_position.hpp │ │ │ ├── menu.hpp │ │ │ └── menu_win32.hpp │ │ ├── item │ │ │ ├── command_item.hpp │ │ │ ├── command_item_description.hpp │ │ │ ├── item.hpp │ │ │ ├── item_description.hpp │ │ │ ├── item_state.hpp │ │ │ ├── selectable_item.hpp │ │ │ ├── selectable_item_description.hpp │ │ │ ├── separator_item.hpp │ │ │ ├── separator_item_description.hpp │ │ │ ├── sub_menu_item.hpp │ │ │ └── sub_menu_item_description.hpp │ │ ├── menu.hpp │ │ ├── menu_handle.hpp │ │ └── visitor.hpp │ ├── message_box.hpp │ ├── messages.hpp │ ├── progress.hpp │ └── task_dialog.hpp │ ├── hook.hpp │ ├── message.hpp │ ├── object_with_site.hpp │ ├── shell │ ├── folder_error_adapters.hpp │ ├── folder_interfaces.hpp │ ├── format.hpp │ ├── pidl.hpp │ ├── pidl_array.hpp │ ├── pidl_iterator.hpp │ ├── property_key.hpp │ ├── services.hpp │ ├── shell.hpp │ └── shell_item.hpp │ ├── trace.hpp │ └── window │ ├── detail │ ├── window.hpp │ └── window_win32.hpp │ ├── dialog.hpp │ ├── icon.hpp │ ├── window.hpp │ └── window_handle.hpp └── test ├── CMakeLists.txt ├── button_test_visitors.hpp ├── dynamic_link_test.cpp ├── filesystem_test.cpp ├── fixture_permutator.hpp ├── folder_error_adapter_test.cpp ├── format_test.cpp ├── global_lock_test.cpp ├── hook_test.cpp ├── icon_test.cpp ├── item_test_visitors.hpp ├── load_test_dll ├── load_test_dll.cpp ├── load_test_dll.def └── load_test_dll.h ├── menu_button_visitor_test.cpp ├── menu_fixtures.hpp ├── menu_item_extraction_test.cpp ├── menu_item_test.cpp ├── menu_item_visitor_test.cpp ├── menu_test.cpp ├── module.cpp ├── pidl_iterator_test.cpp ├── pidl_test.cpp ├── progress_test.cpp ├── sandbox_fixture.hpp ├── shell_item_test.cpp ├── shell_test.cpp ├── task_dialog_test.cpp ├── wchar_output.hpp └── window_test.cpp /.travis.yml: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Copyright (C) 2013 Daniel Pfeifer 3 | # Copyright (C) 2013 Alexander Lamaison 4 | # 5 | # Distributed under the Boost Software License, Version 1.0. 6 | # See accompanying file LICENSE_1_0.txt or copy at 7 | # http://www.boost.org/LICENSE_1_0.txt 8 | #============================================================================= 9 | 10 | language: cpp 11 | 12 | compiler: 13 | - gcc 14 | 15 | env: 16 | global: 17 | - OPTIONS="-DCMAKE_TOOLCHAIN_FILE=../cmake/i686-w64-mingw32.cmake" 18 | - DEPENDS="binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686 wine" 19 | matrix: 20 | - BUILD_TYPE=Debug 21 | - BUILD_TYPE=Release 22 | 23 | before_install: 24 | - curl -L http://www.cmake.org/files/v3.2/cmake-3.2.2-Linux-x86_64.tar.gz | tar -xz 25 | - export PATH="`pwd`/cmake-3.2.2-Linux-x86_64/bin:${PATH}" 26 | - which cmake 27 | - cmake --version 28 | - sudo apt-get update -qq 29 | - sudo apt-get install -qq --no-install-recommends $DEPENDS 30 | 31 | script: 32 | - mkdir _build 33 | - cd _build 34 | - cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE $OPTIONS .. && cmake --build .. && cmake --build .. --target RUN_TESTS -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Washer: a lightweight C++ wrapper for the Windows API 2 | ======================================================== 3 | 4 | > **IMPORTANT**: You do **not** have to build this library before 5 | > using it. It is a header-only library. Many modern C++ libraries 6 | > are developed this way and it makes them much easier to reuse - 7 | > something we _really_ want to encourage. 8 | 9 | What is Washer? 10 | --------------- 11 | 12 | The Microsoft Windows API, aka Win32, is large and written in a 13 | way that suits C programmers but doesn't really fit with the modern 14 | C++ way of working. Washer aims to wrap parts of it to be easier to 15 | use for any programmer familiar with the C++ standard library (aka the 16 | STL). 17 | 18 | ### The Win32 API is huge. Surely you can't have wrapped it all? 19 | 20 | Not even close! So far we have only wrapped a tiny part of the 21 | Windows API, mostly the parts we needed for our own projects, but we 22 | encourage you to use this library where you can and submit patches 23 | back to use when you have had to wrap part of it yourself. We hope 24 | that, this way, we can begin to build up a substantial library to make 25 | Windows development in C++ much more fun than it sometimes is. 26 | 27 | Dependencies 28 | ------------ 29 | 30 | Inevitably, in a world where we are trying to encourage code reuse, 31 | Washer depends on some third-party libraries. 32 | 33 | * [Boost] is fast becoming essential to any modern C++ development 34 | and Washer uses it heavily. Any recent version should do although 35 | building the test suite requires version 1.40 or above as previous 36 | versions lack Boost.Test. 37 | 38 | * [Comet] is a very clever, portable C++ library for Microsoft COM 39 | development. COM is used for parts of the Windows API so we use 40 | Comet to wrap those bits. 41 | 42 | [Boost]: http://www.boost.org 43 | [Comet]: http://github.com/alamaison/comet 44 | 45 | Usage 46 | ----- 47 | 48 | Just download the dependencies, add `washer/include` to your 49 | compiler's include path and you are ready to go. The library is 50 | documented inline and you can use [Doxygen] to generate documentation 51 | for it if you want. 52 | 53 | [Doxygen]: http://www.doxygen.org/ 54 | 55 | Licensing 56 | --------- 57 | 58 | This program is free software: you can redistribute it and/or modify 59 | it under the terms of the GNU General Public License as published by 60 | the Free Software Foundation, either version 3 of the License, or (at 61 | your option) any later version. 62 | 63 | This program is distributed in the hope that it will be useful, but 64 | WITHOUT ANY WARRANTY; without even the implied warranty of 65 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 66 | General Public License for more details. 67 | 68 | You should have received a copy of the GNU General Public License 69 | along with this program. If not, see . 70 | 71 | If you modify this Program, or any covered work, by linking or 72 | combining it with the OpenSSL project's OpenSSL library (or a modified 73 | version of that library), containing parts covered by the terms of the 74 | OpenSSL or SSLeay licenses, the licensors of this Program grant you 75 | additional permission to convey the resulting work. 76 | 77 | ### Why have an exception for OpenSSL? 78 | 79 | The [OpenSSL] library is incompatible with the GPL license because it 80 | contains an advertising clause. However lots of useful, open source 81 | software (including our own projects) need to use it and currently the 82 | alternatives aren't quite up to scratch. As we want these projects to 83 | be able to reuse Washer, we have added this exception to the GPL - a 84 | common technique used by other projects such as [wget]. 85 | 86 | If [GnuTLS] improves to the point where OpenSSL is no longer 87 | necessary, we may remove this exception. 88 | 89 | [OpenSSL]: http://www.openssl.org/ 90 | [wget]: http://www.gnu.org/software/wget/ 91 | [GnuTLS]: http://www.gnu.org/software/gnutls/ 92 | -------------------------------------------------------------------------------- /WasherConfig.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | find_package(Comet 4.0.0 REQUIRED CONFIG) 4 | 5 | set(Boost_USE_STATIC_LIBS TRUE) 6 | find_package( 7 | Boost 1.40 REQUIRED 8 | COMPONENTS filesystem system thread date_time) 9 | 10 | include("${CMAKE_CURRENT_LIST_DIR}/WasherTargets.cmake") 11 | 12 | check_required_components(Washer) 13 | -------------------------------------------------------------------------------- /cmake/i686-w64-mingw32.cmake: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Copyright (C) 2013 Daniel Pfeifer 3 | # 4 | # Distributed under the Boost Software License, Version 1.0. 5 | # See accompanying file LICENSE_1_0.txt or copy at 6 | # http://www.boost.org/LICENSE_1_0.txt 7 | #============================================================================= 8 | 9 | set(CMAKE_SYSTEM_NAME Windows) 10 | set(CMAKE_C_COMPILER i686-w64-mingw32-gcc) 11 | set(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) 12 | set(CMAKE_RC_COMPILER i686-w64-mingw32-windres) 13 | set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) 14 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 15 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 16 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 17 | -------------------------------------------------------------------------------- /cmake/max_warnings.cmake: -------------------------------------------------------------------------------- 1 | 2 | if(CMAKE_BUILD_TOOL MATCHES "(msdev|devenv|nmake)") 3 | # Use the highest warning level for visual studio. 4 | if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") 5 | string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") 6 | else() 7 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4") 8 | endif() 9 | if(CMAKE_C_FLAGS MATCHES "/W[0-4]") 10 | string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") 11 | else() 12 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4") 13 | endif() 14 | endif() 15 | 16 | if(CMAKE_BUILD_TOOL MATCHES "make") 17 | if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall") 18 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 19 | endif() 20 | if(NOT CMAKE_C_FLAGS MATCHES "-Wall") 21 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") 22 | endif() 23 | endif() 24 | -------------------------------------------------------------------------------- /include/washer/clipboard.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Clipboard functions. 5 | 6 | @if license 7 | 8 | Copyright (C) 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_CLIPBOARD_HPP 33 | #define WASHER_CLIPBOARD_HPP 34 | #pragma once 35 | 36 | #include "error.hpp" // last_error 37 | 38 | #include // errinfo 39 | #include // errinfo_api_function 40 | #include // BOOST_THROW_EXCEPTION 41 | 42 | #include // RegisterClipboardFormat 43 | 44 | namespace washer { 45 | namespace clipboard { 46 | 47 | namespace detail { 48 | 49 | template 50 | inline UINT register_format_(const T* format_name); 51 | 52 | template<> 53 | inline UINT register_format_(const char* format_name) 54 | { 55 | return ::RegisterClipboardFormatA(format_name); 56 | } 57 | 58 | template<> 59 | inline UINT register_format_(const wchar_t* format_name) 60 | { 61 | return ::RegisterClipboardFormatW(format_name); 62 | } 63 | 64 | template 65 | inline CLIPFORMAT register_format(const T* format_name) 66 | { 67 | UINT format_id = detail::register_format_(format_name); 68 | if (format_id == 0) 69 | BOOST_THROW_EXCEPTION( 70 | boost::enable_error_info(washer::last_error()) << 71 | boost::errinfo_api_function("RegisterClipboardFormat")); 72 | 73 | return static_cast(format_id); 74 | } 75 | } 76 | 77 | /** 78 | * Register new clipboard format. 79 | */ 80 | inline CLIPFORMAT register_format(const wchar_t* format_name) 81 | { 82 | return detail::register_format(format_name); 83 | } 84 | 85 | /** 86 | * Register new clipboard format (ANSI version). 87 | */ 88 | inline CLIPFORMAT register_format(const char* format_name) 89 | { 90 | return detail::register_format(format_name); 91 | } 92 | 93 | }} // namespace washer::clipboard 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /include/washer/com/catch.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | C++ exception to COM error translator. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_COM_CATCH_HPP 33 | #define WASHER_COM_CATCH_HPP 34 | #pragma once 35 | 36 | #include // BOOST_CURRENT_FUNCTION 37 | 38 | #include // comet_exception_handler, source_info_t 39 | #include // uuid_t 40 | 41 | namespace washer { 42 | namespace com { 43 | 44 | inline HRESULT rethrow( 45 | const char* function, const char* /*file*/, int /*line*/, 46 | const comet::uuid_t& iid=comet::uuid_t(), 47 | const comet::uuid_t& /*clsid*/=comet::uuid_t()) 48 | { 49 | return comet::comet_exception_handler::rethrow( 50 | comet::source_info_t(function, iid)); 51 | } 52 | 53 | }} // namespace washer::com 54 | 55 | /** 56 | * COM exception catcher. 57 | * 58 | * Catches all exceptions and converts them into a COM HRESULT. 59 | */ 60 | #define WASHER_COM_CATCH() \ 61 | catch (...) \ 62 | { \ 63 | return ::washer::com::rethrow( \ 64 | BOOST_CURRENT_FUNCTION, __FILE__, __LINE__); \ 65 | } 66 | 67 | /** 68 | * COM-interface boundary exception catcher. 69 | * 70 | * Catches all exceptions and converts them into a COM HRESULT. Sets last 71 | * ErrorInfo to include the given interface in its information. 72 | * 73 | * This variant (rather than WASHER_COM_CATCH_AUTO_INTERFACE) is needed 74 | * when interface_is is ambiguous. 75 | * 76 | * A comtype for the interface must be in scope. 77 | */ 78 | #define WASHER_COM_CATCH_INTERFACE(Itf) \ 79 | catch (...) \ 80 | { \ 81 | return ::washer::com::rethrow( \ 82 | BOOST_CURRENT_FUNCTION, __FILE__, __LINE__, \ 83 | ::comet::comtype::uuid()); \ 84 | } 85 | 86 | /** 87 | * COM-interface boundary exception catcher that infers IID from interface_is. 88 | * 89 | * Catches all exceptions and converts them into a COM HRESULT. Sets last 90 | * ErrorInfo to include the enclosing object's interface its in information. 91 | * 92 | * This should be used in a class implementing an interface and having a 93 | * typedef @c interface_is giving the IID of the interface the current method 94 | * is part of. A comtype for the interface must also be in scope. 95 | */ 96 | #define WASHER_COM_CATCH_AUTO_INTERFACE() \ 97 | WASHER_COM_CATCH_INTERFACE(interface_is) 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /include/washer/com/object.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | COM object creators. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_COM_OBJECT_HPP 33 | #define WASHER_COM_OBJECT_HPP 34 | #pragma once 35 | 36 | #include // com_error 37 | #include // com_ptr 38 | 39 | #include // errinfo_api_function 40 | #include // errinfo 41 | #include // BOOST_THROW_EXCEPTION 42 | 43 | #include 44 | 45 | #include // CreateBindCtx, MkParseDisplayName 46 | #include // IBindCtx, IMoniker 47 | 48 | template<> struct comet::comtype 49 | { 50 | static const IID& uuid() throw() { return IID_IBindCtx; } 51 | typedef IUnknown base; 52 | }; 53 | 54 | template<> struct comet::comtype 55 | { 56 | static const IID& uuid() throw() { return IID_IMoniker; } 57 | typedef IPersistStream base; 58 | }; 59 | 60 | namespace washer { 61 | namespace com { 62 | 63 | /** 64 | * Instance of default system IBindCtx implementation. 65 | * 66 | * Corresponds to CreateBindCtx Windows API function. 67 | */ 68 | inline comet::com_ptr create_bind_context() 69 | { 70 | comet::com_ptr bind_context; 71 | HRESULT hr = ::CreateBindCtx(0, bind_context.out()); 72 | if (FAILED(hr)) 73 | BOOST_THROW_EXCEPTION( 74 | boost::enable_error_info(comet::com_error(hr)) << 75 | boost::errinfo_api_function("CreateBindCtx")); 76 | 77 | return bind_context; 78 | } 79 | 80 | typedef boost::error_info 81 | errinfo_display_name; 82 | 83 | /** 84 | * Get an object instance by its moniker display name. 85 | * 86 | * Corresponds to CoGetObject Windows API function but allows a custom bind 87 | * context. 88 | * 89 | * We have reimplemented CoGetObject rather than calling the Windows API 90 | * version as there is no other way to specify a bind context. CoGetObject 91 | * only lets the caller specify a limited set of properties in a BIND_OPTS 92 | * structure. Some tasks, such as setting a custom IBindStatusCallback 93 | * require a full-blown IBindCtx. 94 | */ 95 | template 96 | inline comet::com_ptr object_from_moniker_name( 97 | const std::wstring& display_name, comet::com_ptr bind_context) 98 | { 99 | comet::com_ptr moniker; 100 | ULONG eaten = 0; 101 | HRESULT hr = ::MkParseDisplayName( 102 | bind_context.get(), display_name.c_str(), &eaten, moniker.out()); 103 | if (FAILED(hr)) 104 | BOOST_THROW_EXCEPTION( 105 | boost::enable_error_info(comet::com_error(hr)) << 106 | boost::errinfo_api_function("MkParseDisplayName") << 107 | errinfo_display_name(display_name)); 108 | 109 | comet::com_ptr object; 110 | hr = moniker->BindToObject( 111 | bind_context.get(), NULL, object.iid(), 112 | reinterpret_cast(object.out())); 113 | if (FAILED(hr)) 114 | BOOST_THROW_EXCEPTION(comet::com_error_from_interface(moniker, hr)); 115 | 116 | return object; 117 | } 118 | 119 | /** 120 | * Get an object instance by its moniker display name. 121 | * 122 | * Corresponds to CoGetObject Windows API function. BIND_OPTS parameter, 123 | * @a bind_options, can also be an instance of BIND_OPTS2 or BIND_OPTS3. 124 | */ 125 | template 126 | inline comet::com_ptr object_from_moniker_name( 127 | const std::wstring& display_name, BIND_OPTS& bind_options) 128 | { 129 | comet::com_ptr bind_context = create_bind_context(); 130 | HRESULT hr = bind_context->SetBindOptions(&bind_options); 131 | if (FAILED(hr)) 132 | BOOST_THROW_EXCEPTION( 133 | comet::com_error_from_interface(bind_context, hr)); 134 | 135 | return object_from_moniker_name(display_name, bind_context); 136 | } 137 | 138 | /** 139 | * Get an object instance by its moniker display name. 140 | * 141 | * Corresponds to CoGetObject Windows API function with default BIND_OPTS. 142 | */ 143 | template 144 | inline comet::com_ptr object_from_moniker_name( 145 | const std::wstring& display_name) 146 | { 147 | return object_from_moniker_name(display_name, create_bind_context()); 148 | } 149 | 150 | }} // namespace washer::com 151 | 152 | #endif 153 | -------------------------------------------------------------------------------- /include/washer/com/ole_window.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | OLE Window. 5 | 6 | @if license 7 | 8 | Copyright (C) 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_COM_OLE_WINDOW_HPP 33 | #define WASHER_COM_OLE_WINDOW_HPP 34 | 35 | #include 36 | 37 | #include 38 | 39 | #include // com_ptr 40 | 41 | #include // IOleWindow, IOleInPlaceFrame 42 | #include // IShellView 43 | 44 | template<> struct comet::comtype 45 | { 46 | static const IID& uuid() throw() { return IID_IOleWindow; } 47 | typedef IUnknown base; 48 | }; 49 | 50 | template<> struct comet::comtype 51 | { 52 | static const IID& uuid() throw() { return IID_IOleInPlaceFrame; } 53 | typedef IOleInPlaceUIWindow base; 54 | }; 55 | 56 | template<> struct comet::comtype 57 | { 58 | static const IID& uuid() throw() { return IID_IShellView; } 59 | typedef IOleWindow base; 60 | }; 61 | 62 | 63 | namespace washer { 64 | namespace com { 65 | 66 | /** 67 | * Ask windowed OLE container for its window handle. 68 | * 69 | * There are different types of OLE object with which could support this 70 | * operation. Try them in turn until one works. 71 | * 72 | * @todo Add more supported OLE object types. 73 | */ 74 | inline boost::optional< washer::window::window > window_from_ole_window( 75 | comet::com_ptr ole_window) 76 | { 77 | HWND hwnd = NULL; 78 | 79 | if (comet::com_ptr window = com_cast(ole_window)) 80 | { 81 | window->GetWindow(&hwnd); 82 | } 83 | else if (comet::com_ptr view = com_cast(ole_window)) 84 | { 85 | view->GetWindow(&hwnd); 86 | } 87 | 88 | if (hwnd) 89 | return washer::window::window( 90 | washer::window::window_handle::foster_handle(hwnd)); 91 | else 92 | return boost::optional< washer::window::window >(); 93 | } 94 | 95 | }} // namespace washer::com 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /include/washer/detail/path_traits.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Traits-helper for writing generic path-related code. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_DETAIL_PATH_TRAITS_HPP 33 | #define WASHER_DETAIL_PATH_TRAITS_HPP 34 | #pragma once 35 | 36 | #include // path_traits, basic_path 37 | 38 | namespace washer { 39 | namespace detail { 40 | 41 | #if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION < 3 42 | 43 | /** 44 | * Helper to work around lack of genericity in path/wpath selection. 45 | */ 46 | template 47 | struct path_traits_chooser; 48 | 49 | template<> struct path_traits_chooser 50 | { 51 | typedef boost::filesystem::path_traits trait; 52 | }; 53 | 54 | template<> struct path_traits_chooser 55 | { 56 | typedef boost::filesystem::wpath_traits trait; 57 | }; 58 | 59 | #endif 60 | 61 | /** 62 | * Templated typedef shrink path-choosing declaration. 63 | * 64 | * e.g use: 65 | * typename choose_path::type 66 | * instead of: 67 | * boost::filesystem::basic_path< 68 | * std::basic_string, 69 | * typename detail::path_traits_chooser::trait> 70 | */ 71 | template 72 | struct choose_path 73 | { 74 | 75 | #if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION < 3 76 | typedef boost::filesystem::basic_path< 77 | std::basic_string, typename path_traits_chooser::trait> type; 78 | #else 79 | typedef boost::filesystem::path type; 80 | #endif 81 | }; 82 | 83 | }} // namespace washer::detail 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /include/washer/detail/remove_calling_convention.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Calling convention meta-programming. 5 | 6 | @if license 7 | 8 | Copyright (C) 2014 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_DETAIL_REMOVE_CALLING_CONVENTION_HPP 33 | #define WASHER_DETAIL_REMOVE_CALLING_CONVENTION_HPP 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #define WASHER_CALLING_CONVENTION_MAX_ARGS 10 40 | 41 | namespace washer { 42 | namespace detail { 43 | 44 | template 45 | struct remove_calling_convention; 46 | 47 | // Turns function _value_ type with specific calling convention into function 48 | // value type with the default calling convention 49 | 50 | // TODO: Do this for function pointers/references as well 51 | // TODO: Test with GCC and add __attribute__((stdcall)) if necessary 52 | 53 | #define WASHER_REMOVE_CALLING_CONVENTION_TEMPLATE(z, n, convention) \ 54 | template \ 55 | struct remove_calling_convention \ 56 | { \ 57 | typedef R (type)(BOOST_PP_ENUM_PARAMS(n, P)); \ 58 | }; 59 | 60 | #if defined(__i386) || defined(_M_IX86) 61 | 62 | BOOST_PP_REPEAT( 63 | WASHER_CALLING_CONVENTION_MAX_ARGS, 64 | WASHER_REMOVE_CALLING_CONVENTION_TEMPLATE, __cdecl); 65 | 66 | BOOST_PP_REPEAT( 67 | WASHER_CALLING_CONVENTION_MAX_ARGS, 68 | WASHER_REMOVE_CALLING_CONVENTION_TEMPLATE, __fastcall); 69 | 70 | BOOST_PP_REPEAT( 71 | WASHER_CALLING_CONVENTION_MAX_ARGS, 72 | WASHER_REMOVE_CALLING_CONVENTION_TEMPLATE, __stdcall); 73 | 74 | #elif defined(__x86_64__) || defined(_M_X64) 75 | 76 | // Only one calling convention on x64 77 | 78 | BOOST_PP_REPEAT( 79 | WASHER_CALLING_CONVENTION_MAX_ARGS, 80 | WASHER_REMOVE_CALLING_CONVENTION_TEMPLATE, ); 81 | 82 | #endif 83 | 84 | 85 | }} // namespace washer::detail 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /include/washer/error.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | System errors. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_ERROR_HPP 33 | #define WASHER_ERROR_HPP 34 | #pragma once 35 | 36 | #include // system_error, get_system_category 37 | 38 | #include // GetLastError 39 | 40 | namespace washer { 41 | 42 | inline boost::system::system_error last_error() 43 | { 44 | return boost::system::system_error( 45 | ::GetLastError(), boost::system::get_system_category()); 46 | } 47 | 48 | } // namespace washer 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/washer/filesystem.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | File and directory functions. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_FILESYSTEM_HPP 33 | #define WASHER_FILESYSTEM_HPP 34 | #pragma once 35 | 36 | #include "washer/detail/path_traits.hpp" // choose_path 37 | 38 | #include "washer/error.hpp" // last_error 39 | 40 | #include // errinfo 41 | #include // errinfo_file_name 42 | #include // errinfo_api_function 43 | #include // numeric_cast 44 | #include // basic_path 45 | #include // system_error, get_system_category 46 | #include // BOOST_THROW_EXCEPTION 47 | #include // uuid, random_generator 48 | #include // uuid << 49 | 50 | #include // basic_stringstream 51 | #include 52 | 53 | #include 54 | 55 | namespace washer { 56 | namespace filesystem { 57 | 58 | namespace detail { 59 | 60 | inline DWORD get_temp_path(DWORD buffer_length, char* buffer) 61 | { 62 | return ::GetTempPathA(buffer_length, buffer); 63 | } 64 | 65 | inline DWORD get_temp_path(DWORD buffer_length, wchar_t* buffer) 66 | { 67 | return ::GetTempPathW(buffer_length, buffer); 68 | } 69 | 70 | } 71 | 72 | /** 73 | * Returns the absolute path to the system temporary directory. 74 | */ 75 | template 76 | inline typename ::washer::detail::choose_path::type 77 | temporary_directory_path() 78 | { 79 | T* null = 0; 80 | DWORD required_len = detail::get_temp_path(0, null); 81 | if (required_len == 0) 82 | BOOST_THROW_EXCEPTION( 83 | boost::enable_error_info(washer::last_error()) << 84 | boost::errinfo_api_function("GetTempPath")); 85 | 86 | std::vector buffer(required_len); 87 | DWORD len = detail::get_temp_path( 88 | boost::numeric_cast(buffer.size()), &buffer[0]); 89 | if (len == 0) 90 | BOOST_THROW_EXCEPTION( 91 | boost::enable_error_info(washer::last_error()) << 92 | boost::errinfo_api_function("GetTempPath")); 93 | 94 | return typename ::washer::detail::choose_path::type( 95 | buffer.begin(), buffer.begin() + len); 96 | } 97 | 98 | /** 99 | * Return a name to use to create a new file or directory that is 100 | * sufficiently random never to collide. 101 | * 102 | * This is not an absolute path so may often need to be combined with the 103 | * result of temporary_directory_path(). 104 | */ 105 | template 106 | inline typename ::washer::detail::choose_path::type unique_path() 107 | { 108 | boost::uuids::uuid name = boost::uuids::random_generator()(); 109 | 110 | std::basic_stringstream< T, std::char_traits, std::allocator > out; 111 | out << name; 112 | return out.str(); 113 | } 114 | 115 | }} 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /include/washer/global_lock.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Manage Windows global memory locks. 5 | 6 | @if license 7 | 8 | Copyright (C) 2009 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GLOBAL_LOCK_HPP 33 | #define WASHER_GLOBAL_LOCK_HPP 34 | #pragma once 35 | 36 | #include // last_error 37 | 38 | #include // errinfo_api_function 39 | #include // errinfo 40 | #include // BOOST_THROW_EXCEPTION 41 | 42 | #include // GlobalLock/Unlock, HGLOBAL, GetLastError 43 | 44 | namespace washer { 45 | 46 | /** 47 | * Resource-management (RAII) container handling locking on an HGLOBAL. 48 | * 49 | * @tparam Type of object the HGLOBAL points to. The get() method 50 | * returns a pointer to an object of this type. 51 | */ 52 | template 53 | class global_lock 54 | { 55 | public: 56 | 57 | /** 58 | * Lock the given HGLOBAL. 59 | * 60 | * The HGLOBAL remains locked for the lifetime of the object. 61 | * 62 | * @throws system_error if locking fails. 63 | */ 64 | explicit global_lock(HGLOBAL hglobal) : 65 | m_hglobal(hglobal), m_mem(::GlobalLock(hglobal)) 66 | { 67 | if (!m_mem) 68 | BOOST_THROW_EXCEPTION( 69 | boost::enable_error_info(last_error()) << 70 | boost::errinfo_api_function("GlobalLock")); 71 | } 72 | 73 | /** 74 | * Unlock the HGLOBAL. 75 | * 76 | * As the global lock functions maintain a lock-count for each 77 | * HGLOBAL, our HGLOBAL may remain locked after this object is 78 | * destroyed if it has been locked elsewhere. For example, if the 79 | * global_lock is copied, that will increment the lock-count. 80 | */ 81 | ~global_lock() throw() 82 | { 83 | m_mem = NULL; 84 | if (m_hglobal) 85 | { 86 | BOOL result = ::GlobalUnlock(m_hglobal); 87 | (void) result; 88 | assert(result || ::GetLastError() == NO_ERROR); // Too many unlocks 89 | } 90 | m_hglobal = NULL; 91 | } 92 | 93 | /** 94 | * Copy the lock. 95 | * 96 | * Global locking is maintains a lock-count per HGLOBAL that holds the 97 | * number of outstanding locks. It increases every time the HGLOBAL 98 | * is locked and decreases on each call the GlobalUnlock(). When it 99 | * reaches zero, the global memory is actually unlocked and free to be 100 | * moved. 101 | * 102 | * Instances of the global_lock object can be copied safely as the 103 | * operation increments the lock count and so destruction of one 104 | * global_lock instance can't accidentally unlock the memory held by 105 | * another. 106 | * 107 | * @throws system_error if locking fails. 108 | */ 109 | global_lock(const global_lock& lock) : 110 | m_hglobal(lock.m_hglobal), m_mem(::GlobalLock(m_hglobal)) 111 | { 112 | if (!m_mem) 113 | BOOST_THROW_EXCEPTION( 114 | boost::enable_error_info(last_error()) << 115 | boost::errinfo_api_function("GlobalLock")); 116 | } 117 | 118 | /** 119 | * Copy-assign one lock to another. 120 | * 121 | * @see the copy constructor for more info on copying locks. 122 | */ 123 | global_lock& operator=(global_lock lock) throw() 124 | { 125 | swap(*this, lock); 126 | return *this; 127 | } 128 | 129 | /** 130 | * Return a pointer to the item held in the HGLOBAL. 131 | */ 132 | T* get() const 133 | { 134 | return static_cast(m_mem); 135 | } 136 | 137 | private: 138 | HGLOBAL m_hglobal; 139 | void* m_mem; 140 | 141 | /** 142 | * Swap two global_lock instances. 143 | * 144 | * This operation cannot fail and offers the strong guarantee. 145 | */ 146 | template 147 | inline friend void swap(global_lock& lhs, global_lock& rhs) throw() 148 | { 149 | std::swap(lhs.m_hglobal, rhs.m_hglobal); 150 | std::swap(lhs.m_mem, rhs.m_mem); 151 | } 152 | }; 153 | 154 | } 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /include/washer/gui/commands.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Windows message crackers. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_COMMANDS_HPP 33 | #define WASHER_GUI_COMMANDS_HPP 34 | #pragma once 35 | 36 | #include "messages.hpp" // message 37 | 38 | namespace washer { 39 | namespace gui { 40 | 41 | /** 42 | * Generic command. 43 | * 44 | * Base of all command and generaly used to indicate a message whose ID 45 | * was not found in a message map in order to invoke default handling. 46 | * 47 | * message could be used insteam but this intermediate class 48 | * explicitly indicates that the command is to be treated as a command 49 | * rather than as a message. The handling may be different in these cases. 50 | */ 51 | class command_base : public message 52 | { 53 | public: 54 | command_base(WPARAM wparam, LPARAM lparam) 55 | : message(wparam, lparam) {} 56 | }; 57 | 58 | /** 59 | * Command with specific ID. 60 | * 61 | * All commands are cracked the same where so there is only once command 62 | * template in contrast to messages which have individual template 63 | * specialisations for each message type. 64 | */ 65 | template 66 | class command : public message 67 | { 68 | public: 69 | command(WPARAM wparam, LPARAM lparam) 70 | : message(wparam, lparam) {} 71 | }; 72 | 73 | }} // namespace washer::gui 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /include/washer/gui/hwnd.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Window functions working on HWNDs. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011, 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_HWND_HPP 33 | #define WASHER_GUI_HWND_HPP 34 | #pragma once 35 | 36 | #include // last_error 37 | 38 | #include // errinfo_api_function 39 | #include // errinfo 40 | #include // BOOST_THROW_EXCEPTION 41 | 42 | #include // assert 43 | 44 | #include // SetWindowLongPtr, GetWindowLongPtr, GetWindowTextLength 45 | // GetWindowText, SetWindowText 46 | namespace washer { 47 | namespace gui { 48 | 49 | namespace detail { 50 | 51 | namespace native { 52 | 53 | /// @name SetWindowLongPtr 54 | // @{ 55 | template 56 | inline LONG_PTR set_window_long_ptr( 57 | HWND hwnd, int index, LONG_PTR new_long); 58 | 59 | template<> inline LONG_PTR set_window_long_ptr( 60 | HWND hwnd, int index, LONG_PTR new_long) 61 | { return ::SetWindowLongPtrA(hwnd, index, new_long); } 62 | 63 | template<> inline LONG_PTR set_window_long_ptr( 64 | HWND hwnd, int index, LONG_PTR new_long) 65 | { return ::SetWindowLongPtrW(hwnd, index, new_long); } 66 | // @} 67 | 68 | /// @name GetWindowLongPtr 69 | // @{ 70 | template 71 | inline LONG_PTR get_window_long_ptr(HWND hwnd, int index); 72 | 73 | template<> inline LONG_PTR get_window_long_ptr( 74 | HWND hwnd, int index) 75 | { return ::GetWindowLongPtrA(hwnd, index); } 76 | 77 | template<> inline LONG_PTR get_window_long_ptr( 78 | HWND hwnd, int index) 79 | { return ::GetWindowLongPtrW(hwnd, index); } 80 | // @} 81 | 82 | 83 | } 84 | 85 | } 86 | 87 | /** 88 | * Store a value in the given field of the window descriptor. 89 | * 90 | * The value type must be no bigger than a LONG_PTR. 91 | * 92 | * @param hwnd Window handle whose data we are setting. 93 | * @param field Which data field are we storing this data in. 94 | * @param value Data to store. 95 | * 96 | * @return The previous value. 97 | */ 98 | template 99 | inline U set_window_field(HWND hwnd, int field, const U& value) 100 | { 101 | BOOST_STATIC_ASSERT(sizeof(U) <= sizeof(LONG_PTR)); 102 | 103 | ::SetLastError(0); 104 | 105 | LONG_PTR previous = detail::native::set_window_long_ptr( 106 | hwnd, field, reinterpret_cast(value)); 107 | 108 | if (previous == 0 && ::GetLastError() != 0) 109 | BOOST_THROW_EXCEPTION( 110 | boost::enable_error_info(washer::last_error()) << 111 | boost::errinfo_api_function("SetWindowLongPtr")); 112 | 113 | return reinterpret_cast(previous); 114 | } 115 | 116 | /** 117 | * Get a value previously stored in the window descriptor. 118 | * 119 | * The value type must be no bigger than a LONG_PTR. 120 | * 121 | * @param hwnd Window handle whose data we are getting. 122 | * @param field Which data field are we getting the value of. 123 | * @param no_throw Controls whether this function can throw. 124 | * 125 | * @throws A system_error if `no_throw` is `false` and there is an 126 | * error or if no value has yet been stored. If no_throw is true 127 | * it returns 0 instead. 128 | * 129 | * @note Storing 0 will count as not having a previous value so will 130 | * throw an exception unless `no_throw` is `true`. 131 | */ 132 | template 133 | inline U window_field(HWND hwnd, int field, bool no_throw=false) 134 | { 135 | BOOST_STATIC_ASSERT(sizeof(U) <= sizeof(LONG_PTR)); 136 | 137 | LONG_PTR value = detail::native::get_window_long_ptr(hwnd, field); 138 | if (value == 0 && !no_throw) 139 | BOOST_THROW_EXCEPTION( 140 | boost::enable_error_info(washer::last_error()) << 141 | boost::errinfo_api_function("GetWindowLongPtr")); 142 | 143 | return reinterpret_cast(value); 144 | } 145 | 146 | }} // namespace washer::gui 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /include/washer/gui/menu/button/bitmap_button.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Whole-button bitmap button. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_BUTTON_BITMAP_BUTTON_HPP 33 | #define WASHER_GUI_MENU_BUTTON_BITMAP_BUTTON_HPP 34 | #pragma once 35 | 36 | #include 37 | 38 | #include 39 | 40 | #include // MENUITEMINFO, HBITMAP 41 | 42 | namespace washer { 43 | namespace gui { 44 | namespace menu { 45 | 46 | /** 47 | * Menu button whose entire clickable target area is a picture. 48 | */ 49 | class bitmap_button : private boost::noncopyable 50 | { 51 | friend class button; 52 | 53 | public: 54 | 55 | HBITMAP bitmap() const 56 | { 57 | // Old-style whole-button bitmap specified through dwTypeData and 58 | // MFT_BITMAP (MF_BITMAP) requires MIIM_TYPE rather than MIIM_FTYPE 59 | MENUITEMINFOW info = m_item.get_menuiteminfo(MIIM_TYPE); 60 | 61 | return reinterpret_cast(info.dwTypeData); 62 | } 63 | 64 | void bitmap(HBITMAP bitmap) 65 | { 66 | MENUITEMINFOW info = m_item.get_menuiteminfo(MIIM_TYPE); 67 | info.dwTypeData = reinterpret_cast(bitmap); 68 | m_item.set_menuiteminfo(info); 69 | } 70 | 71 | private: 72 | 73 | explicit bitmap_button(const detail::item_position& item) : m_item(item) {} 74 | 75 | detail::item_position m_item; 76 | }; 77 | 78 | }}} // namespace washer::gui::menu 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/washer/gui/menu/button/bitmap_button_description.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Whole-button menu button builder. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_BUTTON_BITMAP_BUTTON_DESCRIPTION_HPP 33 | #define WASHER_GUI_MENU_BUTTON_BITMAP_BUTTON_DESCRIPTION_HPP 34 | #pragma once 35 | 36 | #include 37 | 38 | #include // assert 39 | #include // invalid_argument 40 | 41 | #include // MENUITEMINFO, HBITMAP 42 | 43 | namespace washer { 44 | namespace gui { 45 | namespace menu { 46 | 47 | /** 48 | * Creates a button whose entire clickable target area is a picture. 49 | */ 50 | class bitmap_button_description : public button_description 51 | { 52 | public: 53 | 54 | /** 55 | * @param bitmap the bitmap which must not be null 56 | */ 57 | explicit bitmap_button_description(HBITMAP bitmap) : m_bitmap(bitmap) 58 | { 59 | // We cannot allow NULL bitmaps as, bizzarrely, Windows converts bitmap 60 | // items with a NULL bitmap to separators when they are inserted! 61 | if (!bitmap) 62 | BOOST_THROW_EXCEPTION(std::invalid_argument("Bitmap required")); 63 | } 64 | 65 | private: 66 | 67 | virtual MENUITEMINFOW as_menuiteminfo() const 68 | { 69 | MENUITEMINFOW info = MENUITEMINFOW(); 70 | info.cbSize = sizeof(MENUITEMINFOW); 71 | 72 | // Old-style whole-button bitmap specified through dwTypeData and 73 | // MFT_BITMAP (MF_BITMAP) requires MIIM_TYPE rather than MIIM_FTYPE 74 | info.fMask = MIIM_TYPE; 75 | 76 | assert (m_bitmap != NULL); 77 | info.fType = MFT_BITMAP; 78 | info.dwTypeData = 79 | reinterpret_cast(const_cast(m_bitmap)); 80 | 81 | return info; 82 | } 83 | 84 | virtual bitmap_button_description* do_clone() const 85 | { 86 | return new bitmap_button_description(*this); 87 | } 88 | 89 | HBITMAP m_bitmap; 90 | }; 91 | 92 | }}} // namespace washer::gui::menu 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /include/washer/gui/menu/button/button.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Clickable area of a menu item. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_BUTTON_BUTTON_HPP 33 | #define WASHER_GUI_MENU_BUTTON_BUTTON_HPP 34 | #pragma once 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | namespace washer { 42 | namespace gui { 43 | namespace menu { 44 | 45 | class bitmap_button; 46 | class string_button; 47 | class owner_drawn_button; 48 | 49 | /** 50 | * Menu item button. 51 | * 52 | * Purpose: to separate the button-appearance aspects of menus from other 53 | * orthogonal aspects which are muddled in with it in the Win32 API. 54 | * 55 | * Command items and submenu items have buttons and separator items do not. 56 | * The button type is independent of the other appearance properties such as 57 | * whether an item is enabled or checked. 58 | * 59 | * Buttons come in several different flavours and this can vary at runtime so 60 | * this class provides the `accept` method that takes a visitor so that code 61 | * operating on specific types of button can do so in a type-safe manner. 62 | * 63 | * Changes made using the specific button instance exposed by the visitor 64 | * are reflected in the appearance of the menu item's clickable area in the 65 | * menu. 66 | */ 67 | class button 68 | { 69 | public: 70 | 71 | /** 72 | * Accept a visitor to access type-safe, mutable view of the button. 73 | * 74 | * Visitors passed to this method must provide at least one 75 | * implementation of `operator()` that can accept arguments of types 76 | * `bitmap_button&`, `string_button&` and `owner_drawn_button&` as well 77 | * as a `result_type` type. 78 | */ 79 | template 80 | typename Visitor::result_type accept(Visitor visitor) 81 | { 82 | // Should really be MIIM_FTYPE here but using MIIM_TYPE for 83 | // backward compatibility 84 | UINT button_type_flag = m_item.get_menuiteminfo(MIIM_TYPE).fType; 85 | 86 | if (button_type_flag & MFT_BITMAP) 87 | { 88 | bitmap_button button_view(m_item); 89 | return visitor(button_view); 90 | } 91 | else if (button_type_flag & MFT_OWNERDRAW) 92 | { 93 | // MSDN doesn't say that MFT_OWNERDRAWN is part of the 94 | // mutually exclusive set of flags but I don't see how it couldn't 95 | // be. These flags specify the meaning of dwTypeData and cch which 96 | // MFT_OWNERDRAWN gives a user-defined meaning. 97 | owner_drawn_button button_view(m_item); 98 | return visitor(button_view); 99 | } 100 | else 101 | { 102 | // MFT_STRING which is zero so can only be detected by elimination 103 | string_button button_view(m_item); 104 | return visitor(button_view); 105 | } 106 | } 107 | 108 | explicit button(const detail::item_position& item) : m_item(item) {} 109 | 110 | private: 111 | 112 | detail::item_position m_item; 113 | }; 114 | 115 | }}} // namespace washer::gui::menu 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /include/washer/gui/menu/button/button_description.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Interface of menu button builders. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_BUTTON_BUTTON_DESCRIPTION_HPP 33 | #define WASHER_GUI_MENU_BUTTON_BUTTON_DESCRIPTION_HPP 34 | #pragma once 35 | 36 | #include // assert 37 | 38 | #include // MENUITEMINFO 39 | 40 | namespace washer { 41 | namespace gui { 42 | namespace menu { 43 | 44 | /** 45 | * Interface to objects that describe (but aren't) menu item buttons. 46 | * 47 | * Purpose: to separate the specification of a menu item we are about to 48 | * create, from its identity once it exists in the menu. 49 | * 50 | * Command items and submenu items have buttons and separator items do not. 51 | * The button type is independent of the other appearance properties such as 52 | * whether an item is enabled or checked. 53 | */ 54 | class button_description 55 | { 56 | friend class command_item_description; 57 | friend class sub_menu_item_description; 58 | 59 | public: 60 | 61 | virtual ~button_description() {} 62 | 63 | button_description* clone() const 64 | { 65 | button_description* item = do_clone(); 66 | assert(typeid(*this) == typeid(*item) && "do_clone() sliced object!"); 67 | return item; 68 | } 69 | 70 | private: 71 | 72 | /** 73 | * Win32 representation of the button as a partially-completed MENUITEMINFO. 74 | * 75 | * Classes that implement menu buttons expose themselves to the menu 76 | * classes that use them through this method. 77 | */ 78 | virtual MENUITEMINFOW as_menuiteminfo() const = 0; 79 | 80 | virtual button_description* do_clone() const = 0; 81 | }; 82 | 83 | }}} // namespace washer::gui::menu 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /include/washer/gui/menu/button/owner_drawn_button.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Menu item button drawn by window. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_BUTTON_OWNER_DRAWN_BUTTON_HPP 33 | #define WASHER_GUI_MENU_BUTTON_OWNER_DRAWN_BUTTON_HPP 34 | #pragma once 35 | 36 | #include 37 | 38 | #include 39 | 40 | #include // MIIM_TYPE 41 | 42 | namespace washer { 43 | namespace gui { 44 | namespace menu { 45 | 46 | /** 47 | * Menu button whose clickable area is rendered by the window that owns the 48 | * menu. 49 | * 50 | * The constructor optionally takes a pointer to user-defined data which the 51 | * window can use to draw the button. 52 | */ 53 | class owner_drawn_button : private boost::noncopyable 54 | { 55 | friend class button; 56 | 57 | public: 58 | 59 | void* user_defined_data() const 60 | { 61 | return reinterpret_cast( 62 | m_item.get_menuiteminfo(MIIM_TYPE).dwTypeData); 63 | } 64 | 65 | void user_defined_data(void* new_data) 66 | { 67 | MENUITEMINFOW info = m_item.get_menuiteminfo(MIIM_TYPE); 68 | 69 | assert(info.fType == MFT_OWNERDRAW); 70 | 71 | info.dwTypeData = static_cast(new_data); 72 | } 73 | 74 | private: 75 | 76 | explicit owner_drawn_button(const detail::item_position& item) 77 | : m_item(item) {} 78 | 79 | detail::item_position m_item; 80 | }; 81 | 82 | }}} // namespace washer::gui::menu 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /include/washer/gui/menu/button/owner_drawn_button_description.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Clickable menu buttons types. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_BUTTON_OWNER_DRAWN_BUTTON_DESCRIPTION_HPP 33 | #define WASHER_GUI_MENU_BUTTON_OWNER_DRAWN_BUTTON_DESCRIPTION_HPP 34 | #pragma once 35 | 36 | #include // assert 37 | 38 | #include // MENUITEMINFO 39 | 40 | namespace washer { 41 | namespace gui { 42 | namespace menu { 43 | 44 | /** 45 | * Creates a menu button whose clickable area is rendered by the window that 46 | * owns the menu. 47 | * 48 | * The constructor optionally takes a pointer to user-defined data which the 49 | * window can use to draw the button. 50 | */ 51 | class owner_drawn_button_description : public button_description 52 | { 53 | public: 54 | 55 | explicit owner_drawn_button_description(void* user_defined_data = NULL) 56 | : m_user_defined_data(user_defined_data) {} 57 | 58 | private: 59 | 60 | virtual MENUITEMINFOW as_menuiteminfo() const 61 | { 62 | MENUITEMINFOW info = MENUITEMINFOW(); 63 | info.cbSize = sizeof(MENUITEMINFOW); 64 | 65 | // TYPE rather than FTYPE as we use dwTypeData 66 | // The MSDN docs are hopelessly rubbish. Once again, no idea if this 67 | // is the right thing to do. 68 | info.fMask = MIIM_TYPE; 69 | info.fType = MFT_OWNERDRAW; 70 | info.dwTypeData = static_cast(m_user_defined_data); 71 | 72 | return info; 73 | } 74 | 75 | virtual owner_drawn_button_description* do_clone() const 76 | { 77 | return new owner_drawn_button_description(*this); 78 | } 79 | 80 | void* m_user_defined_data; 81 | }; 82 | 83 | }}} // namespace washer::gui::menu 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /include/washer/gui/menu/button/string_button.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Menu button with simple string caption. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_BUTTON_STRING_BUTTON_HPP 33 | #define WASHER_GUI_MENU_BUTTON_STRING_BUTTON_HPP 34 | #pragma once 35 | 36 | #include 37 | 38 | #include 39 | #include // numeric_cast 40 | 41 | #include 42 | 43 | namespace washer { 44 | namespace gui { 45 | namespace menu { 46 | 47 | /** 48 | * Standard menu button whose clickable target area is a text string. 49 | * 50 | * @todo Extract accelerator combo (after tab character). 51 | */ 52 | class string_button : private boost::noncopyable 53 | { 54 | friend class button; 55 | 56 | public: 57 | 58 | /** 59 | * The text displayed on the button. 60 | */ 61 | std::wstring caption() const 62 | { 63 | return m_item.get_caption(); 64 | } 65 | 66 | void caption(const std::wstring& new_caption) 67 | { 68 | // Using MIIM_TYPE instead of MIIM_STRING for backward compatibility 69 | // with Win 98. When we allow side-bitmaps on string items, 70 | // this will need to change back again. 71 | // 72 | // Old comment: 73 | // MIIM_STRING might be all that's needed but specifying MIIM_FTYPE as 74 | // we do set fType and MFT_STRING just in case. 75 | // The MSDN docs are hopelessly rubbish. No idea if this is the right 76 | // thing to do. 77 | //MENUITEMINFOW info = m_item.get_menuiteminfo(MIIM_FTYPE | MIIM_STRING); 78 | MENUITEMINFOW info = m_item.get_menuiteminfo(MIIM_TYPE); 79 | 80 | assert(info.fType == MFT_STRING); 81 | 82 | info.dwTypeData = const_cast(new_caption.c_str()); 83 | // doesn't seem to be necessary but better safe than sorry: 84 | info.cch = boost::numeric_cast(new_caption.size()); 85 | 86 | m_item.set_menuiteminfo(info); 87 | } 88 | 89 | private: 90 | 91 | explicit string_button(const detail::item_position& item) : m_item(item) {} 92 | 93 | detail::item_position m_item; 94 | }; 95 | 96 | }}} // namespace washer::gui::menu 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /include/washer/gui/menu/button/string_button_description.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Builder for caption-based menu button. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_BUTTON_BUTTON_STRING_BUTTON_DESCRIPTION_HPP 33 | #define WASHER_GUI_MENU_BUTTON_BUTTON_STRING_BUTTON_DESCRIPTION_HPP 34 | #pragma once 35 | 36 | #include 37 | 38 | #include // numeric_cast 39 | 40 | #include 41 | 42 | #include // MENUITEMINFO 43 | 44 | namespace washer { 45 | namespace gui { 46 | namespace menu { 47 | 48 | /** 49 | * Creates a standard menu button whose clickable target area is a text string. 50 | * 51 | * @todo Separate accelerator combo (after tab character). 52 | */ 53 | class string_button_description : public button_description 54 | { 55 | public: 56 | 57 | explicit string_button_description(const std::wstring& caption) 58 | : m_caption(caption) {} 59 | 60 | private: 61 | 62 | virtual MENUITEMINFOW as_menuiteminfo() const 63 | { 64 | MENUITEMINFOW info = MENUITEMINFOW(); 65 | info.cbSize = sizeof(MENUITEMINFOW); 66 | 67 | // Using MIIM_TYPE instead of MIIM_STRING for backward compatibility 68 | // with Win 98. When we allow side-bitmaps on string items, 69 | // this will need to change back again. 70 | // 71 | // Old comment: 72 | // MIIM_STRING might be all that's needed but specifying MIIM_FTYPE as 73 | // we do set fType and MFT_STRING just in case. 74 | // The MSDN docs are hopelessly rubbish. No idea if this is the right 75 | // thing to do. 76 | //info.fMask = MIIM_FTYPE | MIIM_STRING; 77 | info.fMask = MIIM_TYPE; 78 | info.fType = MFT_STRING; 79 | info.dwTypeData = const_cast(m_caption.c_str()); 80 | // doesn't seem to be necessary but better safe than sorry: 81 | info.cch = boost::numeric_cast(m_caption.size()); 82 | 83 | return info; 84 | } 85 | 86 | virtual string_button_description* do_clone() const 87 | { 88 | return new string_button_description(*this); 89 | } 90 | 91 | std::wstring m_caption; 92 | }; 93 | 94 | }}} // namespace washer::gui::menu 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /include/washer/gui/menu/detail/item_common.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Menu item implementation details. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_DETAIL_ITEM_COMMON_HPP 33 | #define WASHER_GUI_MENU_DETAIL_ITEM_COMMON_HPP 34 | #pragma once 35 | 36 | #include 37 | #include 38 | #include // selectability, check_mark, 39 | // highlighting 40 | 41 | #include 42 | 43 | #include // MENUITEMINFO 44 | 45 | namespace washer { 46 | namespace gui { 47 | namespace menu { 48 | namespace detail { 49 | 50 | class selectable_item_core 51 | { 52 | public: 53 | 54 | explicit selectable_item_core(const item_position& item) : m_item(item) {} 55 | 56 | /** 57 | * The ID of the item. 58 | * 59 | * Used to find an item in a menu even if its position changes. 60 | */ 61 | UINT id() const 62 | { 63 | return m_item.get_menuiteminfo(MIIM_ID).wID; 64 | } 65 | 66 | void button_state(BOOST_SCOPED_ENUM(selectability) state) 67 | { 68 | MENUITEMINFOW info = m_item.get_menuiteminfo(MIIM_STATE); 69 | detail::adjust_selectability(state, info); 70 | m_item.set_menuiteminfo(info); 71 | } 72 | 73 | void check_mark(BOOST_SCOPED_ENUM(check_mark) state) 74 | { 75 | MENUITEMINFOW info = m_item.get_menuiteminfo(MIIM_STATE); 76 | detail::adjust_checkedness(state, info); 77 | m_item.set_menuiteminfo(info); 78 | } 79 | 80 | ::washer::gui::menu::button button() const 81 | { 82 | return ::washer::gui::menu::button(m_item); 83 | } 84 | 85 | bool is_selectable() const 86 | { 87 | return !(m_item.get_menuiteminfo(MIIM_STATE).fState & MFS_DISABLED); 88 | } 89 | 90 | bool check_mark_is_visible() const 91 | { 92 | return (m_item.get_menuiteminfo(MIIM_STATE).fState & MFS_CHECKED) != 0; 93 | } 94 | 95 | bool is_highlighted() const 96 | { 97 | return (m_item.get_menuiteminfo(MIIM_STATE).fState & MFS_HILITE) != 0; 98 | } 99 | 100 | MENUITEMINFOW get_menuiteminfo(UINT mask) const 101 | { 102 | return m_item.get_menuiteminfo(mask); 103 | } 104 | 105 | private: 106 | 107 | item_position m_item; 108 | }; 109 | 110 | 111 | }}}} // namespace washer::gui::menu::detail 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /include/washer/gui/menu/detail/item_iterator.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Menu iterator. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_DETAIL_ITEM_ITERATOR_HPP 33 | #define WASHER_GUI_DETAIL_ITEM_ITERATOR_HPP 34 | #pragma once 35 | 36 | #include // random_access_traversal_tag 37 | #include 38 | #include // BOOST_THROW_EXCEPTION 39 | 40 | #include // assert 41 | 42 | namespace washer { 43 | namespace gui { 44 | namespace menu { 45 | 46 | namespace detail { 47 | 48 | template 49 | class item_iterator : 50 | public boost::iterator_facade< 51 | item_iterator, Item, 52 | boost::random_access_traversal_tag, Item> // reference = value_type 53 | // using boost tag to allow non-& reference 54 | { 55 | friend class boost::iterator_core_access; 56 | // Enables conversion constructor to work: 57 | template friend class item_iterator; 58 | 59 | // For some reason GCC doesn't see the iterator_facade_ typedef that 60 | // we're supposed to inherit 61 | typedef boost::iterator_facade< 62 | item_iterator, Item, boost::random_access_traversal_tag, Item> 63 | iterator_facade_; 64 | 65 | public: 66 | 67 | explicit item_iterator(const Menu& menu) : m_menu(menu), m_pos(0) {} 68 | 69 | /** 70 | * Copy conversion constructor. 71 | * 72 | * Purpose: to allow mutable iterators to be converted to const iterators. 73 | */ 74 | template 75 | item_iterator(const item_iterator& other) 76 | : m_menu(other.m_menu), m_pos(other.m_pos) {} 77 | 78 | static item_iterator end(const Menu& menu) 79 | { 80 | return item_iterator(menu, end_tag()); 81 | } 82 | 83 | private: 84 | 85 | class end_tag {}; 86 | 87 | item_iterator(const Menu& menu, const end_tag&) 88 | : m_menu(menu), m_pos(m_menu.size()) {} 89 | 90 | bool equal(item_iterator const& other) const 91 | { 92 | return m_menu == other.m_menu && this->m_pos == other.m_pos; 93 | } 94 | 95 | typename iterator_facade_::reference dereference() const 96 | { 97 | if (m_pos >= m_menu.size()) 98 | BOOST_THROW_EXCEPTION( 99 | std::logic_error("Dereferencing past the end of the menu")); 100 | 101 | return m_menu[m_pos]; 102 | } 103 | 104 | void increment() 105 | { 106 | advance(1); 107 | } 108 | 109 | void decrement() 110 | { 111 | advance(-1); 112 | } 113 | 114 | void advance(typename iterator_facade_::difference_type step) 115 | { 116 | if (step + m_pos < 0) // leaves iterator unchanged 117 | { 118 | BOOST_THROW_EXCEPTION( 119 | std::range_error("Cannot decrement past beginning of the menu")); 120 | } 121 | 122 | if (step + m_pos > m_menu.size()) // leaves iterator unchanged 123 | { 124 | BOOST_THROW_EXCEPTION( 125 | std::range_error("Cannot increment past end of the menu")); 126 | } 127 | 128 | m_pos += step; // iterator changed from here 129 | } 130 | 131 | typename iterator_facade_::difference_type distance_to( 132 | const item_iterator& other) const 133 | { 134 | return other.m_pos - m_pos; 135 | } 136 | 137 | Menu m_menu; 138 | size_t m_pos; 139 | }; 140 | 141 | }}}} // namespace washer::gui::menu::detail 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /include/washer/gui/menu/detail/item_position.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Internal representation of a position in a menu. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_DETAIL_ITEM_POSITION_HPP 33 | #define WASHER_GUI_MENU_DETAIL_ITEM_POSITION_HPP 34 | #pragma once 35 | 36 | #include // get_menu_item_info 37 | #include 38 | 39 | #include // numeric_cast 40 | #include // assert 41 | #include 42 | #include 43 | 44 | #include // MENUITEMINFO 45 | 46 | namespace washer { 47 | namespace gui { 48 | namespace menu { 49 | namespace detail { 50 | 51 | /** 52 | * Combines a menu and a menu position. 53 | * 54 | * Purpose: to abstract the notion of an item (whose type we do not know 55 | * yet) at a particular point in a menu. 56 | * 57 | * Encapsulates the operations that only make sense when a menu and 58 | * a menu item position exist in unison. 59 | */ 60 | class item_position 61 | { 62 | public: 63 | 64 | item_position(const menu_handle& menu, UINT position) 65 | : m_handle(menu), m_position(position) {} 66 | 67 | MENUITEMINFOW get_menuiteminfo(UINT fMask) const 68 | { 69 | MENUITEMINFOW info = MENUITEMINFOW(); 70 | info.cbSize = sizeof(MENUITEMINFOW); 71 | 72 | info.fMask = fMask; 73 | detail::win32::get_menu_item_info( 74 | m_handle.get(), m_position, TRUE, &info); 75 | 76 | return info; 77 | } 78 | 79 | /** 80 | * Getting the string from a MENUITEMINFO gets its own special method 81 | * because of the double-call semantics and buffer ownership. 82 | */ 83 | std::wstring get_caption() const 84 | { 85 | // Using MIIM_TYPE instead of MIIM_STRING for backward compatibility 86 | // with Win 98. When we allow side-bitmaps on string items, 87 | // this will need to change back again. 88 | //MENUITEMINFOW info = get_menuiteminfo(MIIM_FTYPE | MIIM_STRING); 89 | MENUITEMINFOW info = get_menuiteminfo(MIIM_TYPE); 90 | 91 | assert( 92 | (info.fType & (MFT_BITMAP | MFT_OWNERDRAW | MFT_SEPARATOR)) 93 | == 0); 94 | 95 | std::vector buffer(info.cch + 1); 96 | info.cch = boost::numeric_cast(buffer.size()); 97 | info.dwTypeData = (!buffer.empty()) ? &buffer[0] : NULL; 98 | detail::win32::get_menu_item_info( 99 | m_handle.get(), m_position, TRUE, &info); 100 | 101 | if (info.cch > 0) 102 | { 103 | assert(info.dwTypeData); 104 | return std::wstring(info.dwTypeData, info.cch); 105 | } 106 | else 107 | { 108 | return std::wstring(); 109 | } 110 | } 111 | 112 | void set_menuiteminfo(const MENUITEMINFOW& info) 113 | { 114 | detail::win32::set_menu_item_info( 115 | m_handle.get(), m_position, TRUE, &info); 116 | } 117 | 118 | private: 119 | 120 | menu_handle m_handle; 121 | UINT m_position; 122 | }; 123 | 124 | }}}} // namespace washer::gui::menu::detail 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /include/washer/gui/menu/detail/menu.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Menu wrapper implementation details. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_DETAIL_MENU_HPP 33 | #define WASHER_GUI_MENU_DETAIL_MENU_HPP 34 | #pragma once 35 | 36 | #include 37 | // create_popup_menu, create_menu, destroy_menu 38 | #include 39 | 40 | namespace washer { 41 | namespace gui { 42 | namespace menu { 43 | namespace detail { 44 | 45 | inline void safe_destroy_menu(HMENU hmenu) 46 | { 47 | try 48 | { 49 | win32::destroy_menu(hmenu); 50 | } 51 | catch (const std::exception& e) 52 | { 53 | washer::trace("Exception while destroying menu: %s") % e.what(); 54 | } 55 | } 56 | 57 | inline void no_destroy_menu(HMENU) 58 | { 59 | } 60 | 61 | struct menu_handle_creator 62 | { 63 | HMENU operator()() 64 | { 65 | return win32::create_popup_menu(); 66 | } 67 | }; 68 | 69 | struct menu_bar_handle_creator 70 | { 71 | HMENU operator()() 72 | { 73 | return win32::create_menu(); 74 | } 75 | }; 76 | 77 | }}}} // namespace washer::gui::menu::detail 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /include/washer/gui/menu/item/command_item.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Command item extracted from underlying HMENU. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_ITEM_COMMAND_ITEM_HPP 33 | #define WASHER_GUI_MENU_ITEM_COMMAND_ITEM_HPP 34 | #pragma once 35 | 36 | #include 37 | #include // selectable_item_core 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | #include 44 | 45 | namespace washer { 46 | namespace gui { 47 | namespace menu { 48 | 49 | /** 50 | * Simple button menu entry with an associated command ID. 51 | * 52 | * The ID is used when informing the program that the user clicked a menu item. 53 | * The type of button is passed as an argument to the constructor. 54 | */ 55 | class command_item : public selectable_item, private boost::noncopyable 56 | { 57 | public: 58 | 59 | /** 60 | * The ID sent to the owner windows when this command on the menu is 61 | * selected. 62 | */ 63 | UINT id() const 64 | { 65 | return m_core.id(); 66 | } 67 | 68 | virtual command_item& selectability(BOOST_SCOPED_ENUM(washer::gui::menu::selectability) state) 69 | { 70 | m_core.button_state(state); 71 | return *this; 72 | } 73 | 74 | virtual command_item& check_mark_visibility( 75 | BOOST_SCOPED_ENUM(check_mark) state) 76 | { 77 | m_core.check_mark(state); 78 | return *this; 79 | } 80 | 81 | virtual ::washer::gui::menu::button button() const 82 | { 83 | return m_core.button(); 84 | } 85 | 86 | virtual bool is_selectable() const 87 | { 88 | return m_core.is_selectable(); 89 | } 90 | 91 | virtual bool check_mark_is_visible() const 92 | { 93 | return m_core.check_mark_is_visible(); 94 | } 95 | 96 | virtual bool is_highlighted() const 97 | { 98 | return m_core.is_highlighted(); 99 | } 100 | 101 | explicit command_item(const detail::item_position& item) : m_core(item) {} 102 | 103 | private: 104 | 105 | detail::selectable_item_core m_core; 106 | }; 107 | 108 | namespace detail { 109 | 110 | template 111 | inline typename Visitor::result_type do_command_item_accept( 112 | const item_position& item, Visitor& visitor) 113 | { 114 | command_item item_view(item); 115 | return visitor(item_view); 116 | } 117 | 118 | template 119 | inline typename Visitor::result_type do_const_command_item_accept( 120 | const item_position& item, Visitor& visitor) 121 | { 122 | const command_item item_view(item); 123 | return visitor(item_view); 124 | } 125 | 126 | } 127 | 128 | }}} // namespace washer::gui::menu 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /include/washer/gui/menu/item/command_item_description.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Builder for item with a command ID. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012, 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_ITEM_COMMAND_ITEM_DESCRIPTION_HPP 33 | #define WASHER_GUI_MENU_ITEM_COMMAND_ITEM_DESCRIPTION_HPP 34 | #pragma once 35 | 36 | #include 37 | #include 38 | #include 39 | #include // adjust_selectability, 40 | // adjust_checkedness 41 | #include 42 | 43 | #include // MENUITEMINFO 44 | 45 | namespace washer { 46 | namespace gui { 47 | namespace menu { 48 | 49 | /** 50 | * Simple button menu entry with an associated command ID. 51 | * 52 | * The ID is used when informing the program that the user clicked a menu item. 53 | * The type of button is passed as an argument to the constructor. 54 | */ 55 | class command_item_description : public selectable_item_description 56 | { 57 | public: 58 | 59 | command_item_description(const button_description& button, UINT command_id) 60 | : 61 | m_button(button.clone()), 62 | m_command_id(command_id), 63 | m_selectability(selectability::default_state), 64 | m_checkedness(check_mark::default_state) {} 65 | 66 | virtual command_item_description& id(UINT new_id) 67 | { 68 | m_command_id = new_id; 69 | return *this; 70 | } 71 | 72 | virtual command_item_description& selectability( 73 | BOOST_SCOPED_ENUM(washer::gui::menu::selectability) state) 74 | { 75 | m_selectability = state; 76 | return *this; 77 | } 78 | 79 | virtual command_item_description& check_mark_visibility( 80 | BOOST_SCOPED_ENUM(check_mark) state) 81 | { 82 | m_checkedness = state; 83 | return *this; 84 | }; 85 | 86 | private: 87 | 88 | virtual void do_insertion_and_relinquish_resources( 89 | const boost::function& inserter) const 90 | { 91 | inserter(as_menuiteminfo()); 92 | // No resources to release 93 | } 94 | 95 | virtual command_item_description* do_clone() const 96 | { 97 | return new command_item_description(*this); 98 | } 99 | 100 | MENUITEMINFOW as_menuiteminfo() const 101 | { 102 | MENUITEMINFOW info = m_button->as_menuiteminfo(); 103 | 104 | info.fMask |= MIIM_ID; 105 | info.wID = m_command_id; 106 | 107 | if (m_selectability != selectability::default_state || 108 | m_checkedness != check_mark::default_state) 109 | { 110 | info.fMask |= MIIM_STATE; 111 | } 112 | 113 | detail::adjust_selectability(m_selectability, info); 114 | detail::adjust_checkedness(m_checkedness, info); 115 | 116 | return info; 117 | } 118 | 119 | boost::shared_ptr m_button; 120 | UINT m_command_id; 121 | BOOST_SCOPED_ENUM(washer::gui::menu::selectability) m_selectability; 122 | BOOST_SCOPED_ENUM(check_mark) m_checkedness; 123 | }; 124 | 125 | }}} // namespace washer::gui::menu 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /include/washer/gui/menu/item/item_description.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Interface to objects describing menu items. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012, 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_ITEM_ITEM_DESCRIPTION_HPP 33 | #define WASHER_GUI_MENU_ITEM_ITEM_DESCRIPTION_HPP 34 | #pragma once 35 | 36 | #include 37 | 38 | #include // assert 39 | 40 | #include // MENUITEMINFO 41 | 42 | namespace washer { 43 | namespace gui { 44 | namespace menu { 45 | 46 | /** 47 | * Interface to objects that describe (but aren't) menu items. 48 | * 49 | * Purpose: to separate the specification of a menu item we are about to 50 | * create, from its identity once it exists in the menu. The latter 51 | * may have properties that only exist once it is created so cannot 52 | * be represented by the former. 53 | * 54 | * Reason for having separate classes: menu items could have been created by 55 | * passing the properties directly to methods of the menu which would create the 56 | * menu item object as it inserts it. But making the descriptions also objects 57 | * means they can be created by factories more easily or created preemptively 58 | * and not used. 59 | * 60 | * This is similar to a Builder design pattern except that the built object 61 | * is extracted as a Win32 MENUITEMINFO struct by the menu when passed to its 62 | * `insert` method. 63 | */ 64 | class item_description 65 | { 66 | // To allow basic_menu to be the only class that can see our 67 | // underlying Win32 representation 68 | template friend class basic_menu; 69 | 70 | public: 71 | 72 | virtual ~item_description() {} 73 | 74 | /** 75 | * Optional item ID. 76 | * 77 | * All items have an optional ID which can be used to identify the item 78 | * in a menu even if its position has changed. 79 | * 80 | * @note For command menu items, this ID is required as it is fundamental 81 | * to dispatching a command to a window. 82 | */ 83 | virtual item_description& id(UINT new_id) = 0; 84 | 85 | item_description* clone() const 86 | { 87 | item_description* item = do_clone(); 88 | assert(typeid(*this) == typeid(*item) && "do_clone() sliced object!"); 89 | return item; 90 | } 91 | 92 | private: 93 | 94 | /** 95 | * Transfers ownership of the underlying item to a parent menu. 96 | * 97 | * Classes that implement menu items expose themselves to the menu class 98 | * through this method. If they own resources that the menu takes control 99 | * of, such as submenus, they must also take care to release their 100 | * ownership of these resources before returning. 101 | */ 102 | virtual void do_insertion_and_relinquish_resources( 103 | const boost::function& inserter) const = 0; 104 | 105 | virtual item_description* do_clone() const = 0; 106 | }; 107 | 108 | inline item_description* new_clone(const item_description& item) 109 | { 110 | return item.clone(); 111 | } 112 | 113 | }}} // namespace washer::gui::menu 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /include/washer/gui/menu/item/item_state.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Menu item appearance and behaviour properties. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_ITEM_STATE_HPP 33 | #define WASHER_GUI_MENU_ITEM_STATE_HPP 34 | #pragma once 35 | 36 | #include // BOOST_SCOPED_ENUM 37 | #include // BOOST_THROW_EXCEPTION 38 | 39 | #include // logic_error 40 | 41 | #include // MENUITEMINFO 42 | 43 | namespace washer { 44 | namespace gui { 45 | namespace menu { 46 | 47 | BOOST_SCOPED_ENUM_START(selectability) 48 | { 49 | enabled, 50 | disabled, 51 | default_state 52 | }; 53 | BOOST_SCOPED_ENUM_END; 54 | 55 | BOOST_SCOPED_ENUM_START(check_mark) 56 | { 57 | visible, 58 | invisible, 59 | default_state 60 | }; 61 | BOOST_SCOPED_ENUM_END; 62 | 63 | namespace detail { 64 | 65 | // If C++ had Java-style enums, these would be methods of the enums above 66 | 67 | inline void adjust_selectability( 68 | BOOST_SCOPED_ENUM(selectability) state, MENUITEMINFOW& info) 69 | { 70 | switch (state) 71 | { 72 | case selectability::disabled: 73 | info.fState |= MFS_DISABLED; 74 | break; 75 | 76 | case selectability::default_state: 77 | case selectability::enabled: 78 | // MFS_ENABLED is zero so we have to negate disabled instead 79 | info.fState &= (~MFS_DISABLED); 80 | break; 81 | 82 | default: 83 | assert(!"Passed a selectability state that doesn't exist in enum"); 84 | BOOST_THROW_EXCEPTION(std::logic_error("Unknown selectability")); 85 | } 86 | } 87 | 88 | inline void adjust_checkedness( 89 | BOOST_SCOPED_ENUM(check_mark) state, MENUITEMINFOW& info) 90 | { 91 | switch (state) 92 | { 93 | case check_mark::visible: 94 | info.fState |= MFS_CHECKED; 95 | break; 96 | 97 | case check_mark::default_state: 98 | case check_mark::invisible: 99 | // MFS_UNCHECKED is zero so we have to negate checked instead 100 | info.fState &= (~MFS_CHECKED); 101 | break; 102 | 103 | default: 104 | assert(!"Passed a check mark state that doesn't exist in enum"); 105 | BOOST_THROW_EXCEPTION(std::logic_error("Unknown checkedness")); 106 | } 107 | } 108 | 109 | } 110 | 111 | }}} // namespace washer::gui::menu 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /include/washer/gui/menu/item/selectable_item.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Interface to items that can appear in menu bars as well as menus. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_ITEM_SELECTABLE_ITEM_HPP 33 | #define WASHER_GUI_MENU_ITEM_SELECTABLE_ITEM_HPP 34 | #pragma once 35 | 36 | #include 37 | 38 | namespace washer { 39 | namespace gui { 40 | namespace menu { 41 | 42 | class button; 43 | 44 | /** 45 | * Interface to items that, when clicked, might result in an action. 46 | * 47 | * These items have an clickable appearance which we are calling a ''button''. 48 | * It is commonly a text caption but can also be a bitmap or a custom drawn 49 | * item. Separators are the only non-selectable menu item. 50 | * 51 | * Selectable menu items are the only items that can appear in menu bars. In 52 | * other words, menu bars don't allow separators. 53 | * 54 | * @note It is possible to put a separator into a menu item using the windows 55 | * API but it's forbidden by the documentation. Similarly, you can 56 | * add string captions, add submenus and force-enable the separator. 57 | * However, as these are invalid uses of a separator, we don't support 58 | * them. 59 | */ 60 | class selectable_item 61 | { 62 | public: 63 | 64 | virtual ~selectable_item() {} 65 | 66 | /** 67 | * Enable or disable the menu item's button. 68 | * 69 | * Will grey the button and prevent it reacting when hovered over or 70 | * clicked. 71 | */ 72 | virtual selectable_item& selectability( 73 | BOOST_SCOPED_ENUM(selectability) state) = 0; 74 | 75 | /** 76 | * Add or remove a check mark from beside the menu item. 77 | * 78 | * @note Even popup sub-menu items can have a check mark, odd as that 79 | * may seem. 80 | * @note This has no visible effect on items in menu bars. 81 | */ 82 | virtual selectable_item& check_mark_visibility( 83 | BOOST_SCOPED_ENUM(check_mark) state) = 0; 84 | 85 | /** 86 | * The menu item's clickable appearance. 87 | */ 88 | virtual ::washer::gui::menu::button button() const = 0; 89 | 90 | virtual bool is_selectable() const = 0; 91 | virtual bool check_mark_is_visible() const = 0; 92 | virtual bool is_highlighted() const = 0; 93 | }; 94 | 95 | }}} // namespace washer::gui::menu 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /include/washer/gui/menu/item/selectable_item_description.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Interface to objects describing selectable menu items. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012, 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_ITEM_SELECTABLE_ITEM_DESCRIPTION_HPP 33 | #define WASHER_GUI_MENU_ITEM_SELECTABLE_ITEM_DESCRIPTION_HPP 34 | #pragma once 35 | 36 | #include // selectability, check_mark 37 | #include 38 | 39 | #include // MENUITEMINFO 40 | 41 | namespace washer { 42 | namespace gui { 43 | namespace menu { 44 | 45 | /** 46 | * Interface to objects that describe (but aren't) menu items that, when 47 | * clicked, might result in an action. 48 | * 49 | * Such items have an clickable appearance which we are calling a ''button''. 50 | * It is commonly a text caption but can also be a bitmap or a custom drawn 51 | * item. Separators are the only non-selectable menu item. 52 | * 53 | * Selectable menu items are the only items that can appear in menu bars. In 54 | * other words, menu bars don't allow separators. 55 | * 56 | * @note It is possible to put a separator into a menu item using the windows 57 | * API but it's forbidden by the documentation. Similarly, you can 58 | * add string captions, add submenus and force-enable the separator. 59 | * However, as these are invalid uses of a separator, we don't support 60 | * them. 61 | */ 62 | class selectable_item_description : public item_description 63 | { 64 | // To allow basic_menu to be the only class that can see our 65 | // underlying Win32 representation 66 | template friend class basic_menu; 67 | 68 | public: 69 | 70 | /** 71 | * Modify whether item is created with its button enabled or disabled. 72 | * 73 | * This just sets the initial state and can be changed once the item is 74 | * in created in the menu. 75 | * 76 | * If this method is not called, the item will be created enabled by 77 | * default. 78 | */ 79 | virtual selectable_item_description& selectability( 80 | BOOST_SCOPED_ENUM(selectability) state) = 0; 81 | 82 | /** 83 | * Modify whether item is created with a visible check mark beside it. 84 | * 85 | * This just sets the initial state and can be changed once the item is 86 | * in created in the menu. 87 | * 88 | * If this method is not called, the item will be created without a 89 | * check mark by default. 90 | * 91 | * @note Even popup sub-menu items can have a check mark, odd as that 92 | * may seem. 93 | * @note This has no visible effect on items added to menu bars. 94 | */ 95 | virtual selectable_item_description& check_mark_visibility( 96 | BOOST_SCOPED_ENUM(check_mark) state) = 0; 97 | 98 | /** 99 | * @class 100 | * 101 | * Although not explicitly said on MSDN, it seems that highlighting is 102 | * not a property intended to be set when a menu item is created so this 103 | * interface doesn't include a method to set it. 104 | * 105 | * Instead, items can be force-highlighted once in the menu 106 | * (HiliteMenuItem) and tested for their highlight state to react to UI. 107 | */ 108 | }; 109 | 110 | }}} // namespace washer::gui::menu 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /include/washer/gui/menu/item/separator_item.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Menu separator. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_ITEM_SEPARATOR_ITEM_HPP 33 | #define WASHER_GUI_MENU_ITEM_SEPARATOR_ITEM_HPP 34 | #pragma once 35 | 36 | #include 37 | 38 | namespace washer { 39 | namespace gui { 40 | namespace menu { 41 | 42 | /** 43 | * Line dividing menu into logical sections. 44 | */ 45 | class separator_item : private boost::noncopyable 46 | { 47 | public: 48 | 49 | separator_item(const detail::item_position& item) : m_item(item) {} 50 | 51 | /** 52 | * The ID of the item. 53 | * 54 | * Used to find an item in a menu even if its position changes. 55 | */ 56 | UINT id() const 57 | { 58 | return m_item.get_menuiteminfo(MIIM_ID).wID; 59 | } 60 | 61 | private: 62 | detail::item_position m_item; 63 | }; 64 | 65 | namespace detail { 66 | 67 | template 68 | inline typename Visitor::result_type do_separator_item_accept( 69 | const item_position& item, Visitor& visitor) 70 | { 71 | separator_item item_view(item); 72 | return visitor(item_view); 73 | } 74 | 75 | template 76 | inline typename Visitor::result_type do_const_separator_item_accept( 77 | const item_position& item, Visitor& visitor) 78 | { 79 | const separator_item item_view(item); 80 | return visitor(item_view); 81 | } 82 | 83 | } 84 | 85 | }}} // namespace washer::gui::menu 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /include/washer/gui/menu/item/separator_item_description.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Menu separator builder. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012, 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_ITEM_SEPARATOR_ITEM_DESCRIPTION_HPP 33 | #define WASHER_GUI_MENU_ITEM_SEPARATOR_ITEM_DESCRIPTION_HPP 34 | #pragma once 35 | 36 | #include 37 | 38 | #include // MENUITEMINFO 39 | 40 | namespace washer { 41 | namespace gui { 42 | namespace menu { 43 | 44 | /** 45 | * Line dividing menu into logical sections. 46 | */ 47 | class separator_item_description : public item_description 48 | { 49 | public: 50 | separator_item_description() : m_id(0) {} 51 | 52 | virtual separator_item_description& id(UINT new_id) 53 | { 54 | m_id = new_id; 55 | return *this; 56 | } 57 | 58 | private: 59 | 60 | virtual void do_insertion_and_relinquish_resources( 61 | const boost::function& inserter) const 62 | { 63 | inserter(as_menuiteminfo()); 64 | // No resources to release 65 | } 66 | 67 | virtual separator_item_description* do_clone() const 68 | { 69 | return new separator_item_description(*this); 70 | } 71 | 72 | MENUITEMINFOW as_menuiteminfo() const 73 | { 74 | MENUITEMINFOW info = MENUITEMINFOW(); 75 | info.cbSize = sizeof(MENUITEMINFOW); 76 | 77 | // Using MIIM_TYPE instead of MIIM_FTYPE for backward compatibility 78 | // with Win 98. 79 | //info.fMask = MIIM_FTYPE | MIIM_ID; 80 | info.fMask = MIIM_TYPE | MIIM_ID; 81 | info.fType = MFT_SEPARATOR; 82 | info.wID = m_id; 83 | 84 | return info; 85 | } 86 | 87 | UINT m_id; 88 | }; 89 | 90 | }}} // namespace washer::gui::menu 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /include/washer/gui/menu/item/sub_menu_item.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Item that pops open another menu. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_ITEM_SUB_MENU_ITEM_HPP 33 | #define WASHER_GUI_MENU_ITEM_SUB_MENU_ITEM_HPP 34 | #pragma once 35 | 36 | #include // selectable_item_core 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | 44 | namespace washer { 45 | namespace gui { 46 | namespace menu { 47 | 48 | /** 49 | * Menu nested in or below main menu bar. 50 | * 51 | * Purpose: to extract an item with a submenu from an HMENU. 52 | */ 53 | class sub_menu_item : public selectable_item, private boost::noncopyable 54 | { 55 | public: 56 | 57 | /** 58 | * The ID of the item. 59 | * 60 | * Used to find an item in a menu even if its position changes. 61 | */ 62 | UINT id() const 63 | { 64 | return m_core.id(); 65 | } 66 | 67 | virtual sub_menu_item& selectability( 68 | BOOST_SCOPED_ENUM(washer::gui::menu::selectability) state) 69 | { 70 | m_core.button_state(state); 71 | return *this; 72 | } 73 | 74 | virtual sub_menu_item& check_mark_visibility( 75 | BOOST_SCOPED_ENUM(check_mark) state) 76 | { 77 | m_core.check_mark(state); 78 | return *this; 79 | } 80 | 81 | virtual ::washer::gui::menu::button button() const 82 | { 83 | return m_core.button(); 84 | } 85 | 86 | virtual bool is_selectable() const 87 | { 88 | return m_core.is_selectable(); 89 | } 90 | 91 | virtual bool check_mark_is_visible() const 92 | { 93 | return m_core.check_mark_is_visible(); 94 | } 95 | 96 | virtual bool is_highlighted() const 97 | { 98 | return m_core.is_highlighted(); 99 | } 100 | 101 | ::washer::gui::menu::menu menu() const 102 | { 103 | HMENU submenu = m_core.get_menuiteminfo(MIIM_SUBMENU).hSubMenu; 104 | assert(submenu); 105 | return ::washer::gui::menu::menu(menu_handle::foster_handle(submenu)); 106 | } 107 | 108 | explicit sub_menu_item(const detail::item_position& item) : m_core(item) {} 109 | 110 | private: 111 | 112 | detail::selectable_item_core m_core; 113 | }; 114 | 115 | namespace detail { 116 | 117 | template 118 | inline typename Visitor::result_type do_sub_menu_item_accept( 119 | const item_position& item, Visitor& visitor) 120 | { 121 | sub_menu_item item_view(item); 122 | return visitor(item_view); 123 | } 124 | 125 | template 126 | inline typename Visitor::result_type do_const_sub_menu_item_accept( 127 | const item_position& item, Visitor& visitor) 128 | { 129 | const sub_menu_item item_view(item); 130 | return visitor(item_view); 131 | } 132 | 133 | } 134 | 135 | }}} // namespace washer::gui::menu 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /include/washer/gui/menu/item/sub_menu_item_description.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Builder for pop-out items. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012, 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_ITEM_SUB_MENU_ITEM_DESCRIPTION_HPP 33 | #define WASHER_GUI_MENU_ITEM_SUB_MENU_ITEM_DESCRIPTION_HPP 34 | #pragma once 35 | 36 | #include 37 | #include 38 | #include // adjust_selectability, 39 | // adjust_checkedness 40 | #include 41 | 42 | #include // MENUITEMINFO 43 | 44 | #include // assert 45 | 46 | namespace washer { 47 | namespace gui { 48 | namespace menu { 49 | 50 | /** 51 | * Menu nested in or below main menu bar. 52 | * 53 | * Purpose: to associate a caption text and command ID with a menu to ready it 54 | * for insertion into a menu bar or into another menu. 55 | * 56 | * Menus can be used independently so they do not intrinsically have 57 | * a caption or command ID; these only make sense for menus that are going to 58 | * be inserted into another menu or menu bar. 59 | */ 60 | class sub_menu_item_description : public selectable_item_description 61 | { 62 | public: 63 | 64 | sub_menu_item_description( 65 | const button_description& button, const menu& menu) 66 | : 67 | m_id(0), 68 | m_button(button.clone()), 69 | m_menu(menu), 70 | m_selectability(selectability::default_state), 71 | m_checkedness(check_mark::default_state) 72 | { 73 | assert(m_menu.valid() || !"Constructed from invalid menu"); 74 | } 75 | 76 | sub_menu_item_description() : m_id(0) {} 77 | 78 | virtual sub_menu_item_description& id(UINT new_id) 79 | { 80 | m_id = new_id; 81 | return *this; 82 | } 83 | 84 | virtual sub_menu_item_description& selectability( 85 | BOOST_SCOPED_ENUM(washer::gui::menu::selectability) state) 86 | { 87 | m_selectability = state; 88 | return *this; 89 | } 90 | 91 | virtual sub_menu_item_description& check_mark_visibility( 92 | BOOST_SCOPED_ENUM(check_mark) state) 93 | { 94 | m_checkedness = state; 95 | return *this; 96 | }; 97 | 98 | private: 99 | 100 | virtual void do_insertion_and_relinquish_resources( 101 | const boost::function& inserter) const 102 | { 103 | inserter(as_menuiteminfo()); 104 | m_menu.m_menu.release(); 105 | } 106 | 107 | virtual sub_menu_item_description* do_clone() const 108 | { 109 | return new sub_menu_item_description(*this); 110 | } 111 | 112 | MENUITEMINFOW as_menuiteminfo() const 113 | { 114 | MENUITEMINFOW info = m_button->as_menuiteminfo(); 115 | 116 | info.fMask |= MIIM_SUBMENU | MIIM_ID; 117 | info.wID = m_id; 118 | assert(m_menu.valid() || !"Invalid menu"); 119 | info.hSubMenu = m_menu.handle().get(); 120 | 121 | if (m_selectability != selectability::default_state || 122 | m_checkedness != check_mark::default_state) 123 | { 124 | info.fMask |= MIIM_STATE; 125 | } 126 | 127 | detail::adjust_selectability(m_selectability, info); 128 | detail::adjust_checkedness(m_checkedness, info); 129 | 130 | return info; 131 | } 132 | 133 | UINT m_id; 134 | boost::shared_ptr m_button; 135 | ::washer::gui::menu::menu m_menu; 136 | BOOST_SCOPED_ENUM(washer::gui::menu::selectability) m_selectability; 137 | BOOST_SCOPED_ENUM(check_mark) m_checkedness; 138 | }; 139 | 140 | }}} // namespace washer::gui::menu 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /include/washer/gui/menu/menu.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Windows HMENU menu wrapper for menus and menu bars. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_MENU_HPP 33 | #define WASHER_GUI_MENU_MENU_HPP 34 | #pragma once 35 | 36 | #include 37 | #include 38 | // menu_handle_creator, menu_bar_handle_creator 39 | #include 40 | #include 41 | 42 | #pragma warning(push) 43 | #pragma warning(disable : 4100) // unreferenced formal parameter 44 | #pragma warning(disable : 4510) 45 | #pragma warning(disable : 4610) 46 | #include // BOOST_CONCEPT_ASSERT 47 | #include // Collection 48 | #include // ReadableIterator 49 | #pragma warning(pop) 50 | 51 | namespace washer { 52 | namespace gui { 53 | namespace menu { 54 | 55 | /** 56 | * Menu that can be used as a context menu, as a sub-menu of a menu bar or as 57 | * a sub-menu of another menu. 58 | */ 59 | typedef basic_menu menu; 60 | 61 | /** 62 | * Main application window menu bar. 63 | */ 64 | typedef basic_menu< 65 | selectable_item_description, detail::menu_bar_handle_creator> menu_bar; 66 | 67 | }}} // namespace washer::gui::menu 68 | 69 | #if (BOOST_VERSION >= 104900) 70 | // Not sure when Collection was added but 1.49 will do 71 | BOOST_CONCEPT_ASSERT((boost::Collection)); 72 | BOOST_CONCEPT_ASSERT((boost::Collection)); 73 | #endif 74 | 75 | BOOST_CONCEPT_ASSERT(( 76 | boost_concepts::ReadableIterator)); 77 | BOOST_CONCEPT_ASSERT(( 78 | boost_concepts::ReadableIterator)); 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /include/washer/gui/menu/menu_handle.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | HMENU lifetime management. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012, 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_MENU_HANDLE_HPP 33 | #define WASHER_GUI_MENU_MENU_HANDLE_HPP 34 | #pragma once 35 | 36 | #include // safe_destroy_menu 37 | #include // is_menu 38 | 39 | #include 40 | #include 41 | 42 | #include // assert 43 | 44 | namespace washer { 45 | namespace gui { 46 | namespace menu { 47 | 48 | /** 49 | * Lifetime characteristics for wrapped menu handle. 50 | * 51 | * Purpose: to offer two different ways of managing a wrapped HMENU; one that 52 | * takes ownership of its lifetime and one that does not take responsibility for 53 | * managing its lifetime. 54 | */ 55 | class menu_handle 56 | { 57 | typedef boost::shared_ptr::type> 58 | shared_menu_handle; 59 | 60 | // Because shared_ptr doesn't let us release, but we really have to be 61 | // able to to hand ownership to objects we don't manage, (don't worry, 62 | // the valid() method of basic_menu catches the stragglers by throwing 63 | // if we try to use them after they have gone away) we use this class 64 | // to change the behaviour of the deleter when we need to release. 65 | class settable_deleter 66 | { 67 | public: 68 | settable_deleter(bool do_delete) : m_do_delete(do_delete) {} 69 | 70 | void operator()(HMENU raw_handle) 71 | { 72 | if (m_do_delete) 73 | { 74 | detail::safe_destroy_menu(raw_handle); 75 | } 76 | } 77 | 78 | void set_deletion(bool do_delete) 79 | { 80 | m_do_delete = do_delete; 81 | } 82 | 83 | private: 84 | bool m_do_delete; 85 | }; 86 | 87 | public: 88 | 89 | static menu_handle foster_handle(HMENU handle) 90 | { 91 | assert(detail::win32::is_menu(handle) || !"Must be valid handle"); 92 | return menu_handle( 93 | shared_menu_handle(handle, settable_deleter(false))); 94 | } 95 | 96 | static menu_handle adopt_handle(HMENU handle) 97 | { 98 | assert(detail::win32::is_menu(handle) || !"Must be valid handle"); 99 | return menu_handle( 100 | shared_menu_handle(handle, settable_deleter(true))); 101 | } 102 | 103 | HMENU get() const 104 | { 105 | return m_handle.get(); 106 | } 107 | 108 | /** 109 | * Gives up this object's ownership, if any, of the menu. 110 | * 111 | * If the menu handle is adopted, this converts it to a fostered handle. 112 | * If the menu handle is already fostered, this simply returns it. 113 | */ 114 | HMENU release() 115 | { 116 | boost::get_deleter(m_handle)->set_deletion(false); 117 | return m_handle.get(); 118 | } 119 | 120 | friend void swap(menu_handle& a, menu_handle& b) 121 | { 122 | swap(a.m_handle, b.m_handle); 123 | } 124 | 125 | private: 126 | 127 | menu_handle(shared_menu_handle handle) : m_handle(handle) {} 128 | 129 | shared_menu_handle m_handle; 130 | }; 131 | 132 | }}} // namespace washer::gui::menu 133 | 134 | #endif 135 | -------------------------------------------------------------------------------- /include/washer/gui/menu/visitor.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Visitor convenience interface for menu items and menu item buttons. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_MENU_VISITOR_HPP 33 | #define WASHER_GUI_MENU_VISITOR_HPP 34 | #pragma once 35 | 36 | namespace washer { 37 | namespace gui { 38 | namespace menu { 39 | 40 | /** 41 | * Convenience interface giving subclasses the static visitor concept necessary 42 | * to visit menu items and menu item buttons. 43 | * 44 | * Purpose: This class only exists to make it easier to create visitors suitable 45 | * to pass to `item::accept` by defining their result type. In particular, 46 | * classes are not required to inherit from this interface in order to be used 47 | * as menu item visitors. 48 | */ 49 | template 50 | class menu_visitor 51 | { 52 | public: 53 | 54 | typedef ResultType result_type; 55 | 56 | ~menu_visitor() {} 57 | }; 58 | 59 | }}} // namespace washer::gui::menu 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /include/washer/hook.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Window hooking. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_HOOK_HPP 33 | #define WASHER_HOOK_HPP 34 | #pragma once 35 | 36 | #include // last_error 37 | 38 | #include // errinfo_api_function 39 | #include // errinfo 40 | #include // BOOST_THROW_EXCEPTION 41 | #include // remove_pointer 42 | 43 | #include // GetCurrentThreadId, SetWindowsHookEx 44 | 45 | namespace washer { 46 | 47 | typedef boost::shared_ptr::type> hhook; 48 | 49 | namespace detail { 50 | 51 | inline hhook windows_hook(int type, HOOKPROC hook_function, DWORD thread_id) 52 | { 53 | HHOOK hook = ::SetWindowsHookExW(type, hook_function, NULL, thread_id); 54 | if (hook == NULL) 55 | BOOST_THROW_EXCEPTION( 56 | boost::enable_error_info(last_error()) << 57 | boost::errinfo_api_function("SetWindowsHookExW")); 58 | 59 | return hhook(hook, ::UnhookWindowsHookEx); 60 | } 61 | 62 | } 63 | 64 | /** 65 | * Install a windows hook function for the current thread. 66 | * 67 | * The hook is uninstalled when the returned hhook goes out of scope. 68 | */ 69 | inline hhook windows_hook(int type, HOOKPROC hook_function) 70 | { 71 | return detail::windows_hook(type, hook_function, ::GetCurrentThreadId()); 72 | } 73 | 74 | /** 75 | * Install a windows hook function globally. 76 | * 77 | * The hook is uninstalled when the returned hhook goes out of scope. 78 | */ 79 | inline hhook windows_global_hook(int type, HOOKPROC hook_function) 80 | { 81 | return detail::windows_hook(type, hook_function, 0); 82 | } 83 | 84 | } 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /include/washer/message.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Windows message system. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_MESSAGE_HPP 33 | #define WASHER_MESSAGE_HPP 34 | #pragma once 35 | 36 | #include // SendMessage 37 | 38 | namespace washer { 39 | 40 | namespace detail { 41 | namespace native { 42 | 43 | template 44 | inline LRESULT send_message( 45 | HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); 46 | 47 | template<> 48 | inline LRESULT send_message( 49 | HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) 50 | { return ::SendMessageA(hwnd, message, wparam, lparam); } 51 | 52 | template<> 53 | inline LRESULT send_message( 54 | HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) 55 | { return ::SendMessageW(hwnd, message, wparam, lparam); } 56 | } 57 | } 58 | 59 | template 60 | inline R send_message_return(HWND hwnd, UINT message, W wparam, L lparam) 61 | { 62 | return (R)( 63 | detail::native::send_message( 64 | hwnd, message, (WPARAM)wparam, (LPARAM)lparam)); 65 | } 66 | 67 | template 68 | inline void send_message(HWND hwnd, UINT message, W wparam, L lparam) 69 | { 70 | send_message_return(hwnd, message, wparam, lparam); 71 | } 72 | 73 | } // namespace washer 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /include/washer/object_with_site.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Standard IObjectWithSite implementation. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_OBJECT_WITH_SITE_HPP 33 | #define WASHER_OBJECT_WITH_SITE_HPP 34 | #pragma once 35 | 36 | #include // com_error 37 | #include // comtype 38 | 39 | #include // WASHER_COM_CATCH_AUTO_INTERFACE 40 | 41 | #include // BOOST_THROW_EXCEPTION 42 | 43 | #include // IObjectWithSite 44 | 45 | template<> struct ::comet::comtype<::IObjectWithSite> 46 | { 47 | static const ::IID& uuid() throw() { return ::IID_IObjectWithSite; } 48 | typedef ::IUnknown base; 49 | }; 50 | 51 | namespace washer { 52 | 53 | /** 54 | * Mixin providing a standard implementation of IObjectWithSite. 55 | */ 56 | class object_with_site : public IObjectWithSite 57 | { 58 | public: 59 | 60 | typedef IObjectWithSite interface_is; 61 | 62 | virtual IFACEMETHODIMP SetSite(IUnknown* pUnkSite) 63 | { 64 | try 65 | { 66 | m_ole_site = pUnkSite; 67 | on_set_site(m_ole_site); 68 | } 69 | WASHER_COM_CATCH_AUTO_INTERFACE(); 70 | 71 | return S_OK; 72 | } 73 | 74 | virtual IFACEMETHODIMP GetSite(REFIID riid, void** ppvSite) 75 | { 76 | try 77 | { 78 | if (!ppvSite) 79 | BOOST_THROW_EXCEPTION(comet::com_error(E_POINTER)); 80 | *ppvSite = NULL; 81 | 82 | HRESULT hr = m_ole_site.get()->QueryInterface(riid, ppvSite); 83 | if (FAILED(hr)) 84 | BOOST_THROW_EXCEPTION( 85 | comet::com_error_from_interface(m_ole_site, hr)); 86 | } 87 | WASHER_COM_CATCH_AUTO_INTERFACE(); 88 | 89 | return S_OK; 90 | } 91 | 92 | protected: 93 | 94 | comet::com_ptr ole_site() { return m_ole_site; } 95 | 96 | private: 97 | 98 | /** 99 | * Custom site action. 100 | * 101 | * Override this method to perform a custom action when the site is set. 102 | */ 103 | virtual void on_set_site(comet::com_ptr ole_site) {} 104 | 105 | comet::com_ptr m_ole_site; 106 | }; 107 | 108 | } // namespace washer 109 | 110 | #endif 111 | -------------------------------------------------------------------------------- /include/washer/shell/format.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Shell string-formatting functions. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_SHELL_FORMAT_HPP 33 | #define WASHER_SHELL_FORMAT_HPP 34 | #pragma once 35 | 36 | #include // datetime_t 37 | 38 | #include // errinfo_api_function 39 | #include // errinfo 40 | #include // numeric_cast 41 | #include // BOOST_THROW_EXCEPTION 42 | 43 | #include 44 | #include 45 | 46 | #include // SHFormatDateTime, StrFormatKBSize 47 | 48 | namespace washer { 49 | namespace shell { 50 | 51 | namespace detail { 52 | namespace native { 53 | 54 | inline int sh_format_date_time( 55 | const FILETIME* pft, DWORD* pdwFlags, char* buffer, UINT size) 56 | { return ::SHFormatDateTimeA(pft, pdwFlags, buffer, size); } 57 | 58 | inline int sh_format_date_time( 59 | const FILETIME* pft, DWORD* pdwFlags, wchar_t* buffer, UINT size) 60 | { 61 | int rc = ::SHFormatDateTimeW(pft, pdwFlags, buffer, size); 62 | 63 | /* 64 | * The wide-string version doesn't include the null character, 65 | * despite what the documentation claims. 66 | * 67 | * XXX: Maybe this is a per-OS bug in which case we have to so 68 | * something cleverer here. 69 | */ 70 | if (rc != 0) 71 | return rc + 1; 72 | else 73 | return rc; 74 | } 75 | 76 | inline char* str_format_kb_size( 77 | LONGLONG file_size, char* buffer, UINT size) 78 | { return ::StrFormatKBSizeA(file_size, buffer, size); } 79 | 80 | inline wchar_t* str_format_kb_size( 81 | LONGLONG file_size, wchar_t* buffer, UINT size) 82 | { return ::StrFormatKBSizeW(file_size, buffer, size); } 83 | 84 | } 85 | } 86 | 87 | /** 88 | * Format a date the way comonly used by the Windows shell. 89 | * 90 | * The following shows an example of the string returned for different 91 | * flag values: 92 | * 93 | * FDTF_DEFAULT (or no flags) 94 | * 5/13/2059 4:36 AM 95 | * FDTF_LONGDATE | FDTF_SHORTTIME 96 | * Tuesday, May 13, 2059, 4:36 AM 97 | * FDTF_LONGDATE | FDTF_LONGTIME | FDTF_RELATIVE 98 | * Today, May 13, 2059, 4:36:06 AM 99 | * 100 | * Corresponds to SHFormatDateTime. 101 | */ 102 | template 103 | inline std::basic_string format_date_time( 104 | const comet::datetime_t& date, DWORD flags=FDTF_DEFAULT) 105 | { 106 | FILETIME ft; 107 | date.to_filetime(&ft); 108 | 109 | std::vector buffer(512); // XXX: Unfortunately we have to hard-code this 110 | 111 | int len = detail::native::sh_format_date_time( 112 | &ft, &flags, &buffer[0], boost::numeric_cast(buffer.size())); 113 | // flags gets modifed but that's OK as its a local copy. However, that 114 | // means we can't return any information about these changes to the caller 115 | 116 | if (len == 0) 117 | BOOST_THROW_EXCEPTION( 118 | boost::enable_error_info( 119 | std::runtime_error("Couldn't convert date to a string")) << 120 | boost::errinfo_api_function("SHFormatDateTime")); 121 | 122 | return std::basic_string(&buffer[0], len - 1); 123 | } 124 | 125 | /** 126 | * Format a number as a file size in kilobytes. 127 | * 128 | * For example 3023 will be converted to something like "3,023 KB" depending 129 | * on locale. 130 | */ 131 | template 132 | inline std::basic_string format_filesize_kilobytes(LONGLONG file_size) 133 | { 134 | std::vector buf(64); // XXX: Unfortunately we have to hard-code this 135 | T* str = detail::native::str_format_kb_size( 136 | file_size, &buf[0], boost::numeric_cast(buf.size())); 137 | 138 | return (str) ? str : std::basic_string(); 139 | } 140 | 141 | }} // namespace washer::shell 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /include/washer/shell/pidl_array.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Helper class to use wrapped PIDLs as an array. 5 | 6 | @if license 7 | 8 | Copyright (C) 2009, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_SHELL_PIDL_ARRAY_HPP 33 | #define WASHER_SHELL_PIDL_ARRAY_HPP 34 | #pragma once 35 | 36 | #include // swap, transform 37 | #include 38 | 39 | namespace washer { 40 | namespace shell { 41 | namespace pidl { 42 | 43 | namespace detail { 44 | 45 | template 46 | typename T::const_pointer raw_pidl_from_wrapper(const T& wrapped_pidl) 47 | { 48 | return wrapped_pidl.get(); 49 | } 50 | 51 | template 52 | std::vector 53 | raw_pidls_from_wrappers(It begin, It end) 54 | { 55 | std::vector array; 56 | transform( 57 | begin, end, back_inserter(array), 58 | raw_pidl_from_wrapper); 59 | return array; 60 | } 61 | } 62 | 63 | /** 64 | * Helper class to let a collection of wrapped PIDLs be used where an array 65 | * of raw pidls is expected. 66 | * 67 | * The values are only valid during the lifetime of the original collection 68 | * of wrapped PIDLs with which the array was constructed. Once the original 69 | * collection is destroyed the values in the array point to deallocated 70 | * memory. 71 | */ 72 | template 73 | class pidl_array 74 | { 75 | public: 76 | 77 | typedef typename T::const_pointer value_type; 78 | 79 | template 80 | pidl_array(It begin, It end) : 81 | m_array(detail::raw_pidls_from_wrappers(begin, end)) {} 82 | 83 | ~pidl_array() throw() {} 84 | 85 | pidl_array(const pidl_array& a) : 86 | m_array(a.m_array) {} 87 | 88 | pidl_array& operator=(const pidl_array& a) 89 | { 90 | pidl_array copy(a); 91 | swap(copy); 92 | return *this; 93 | } 94 | 95 | /** 96 | * Return a pointer to the array. 97 | */ 98 | const value_type* as_array() const 99 | { 100 | return (size()) ? &m_array[0] : NULL; 101 | } 102 | 103 | /** 104 | * Number of PIDLs in the array. 105 | */ 106 | size_t size() const 107 | { 108 | return m_array.size(); 109 | } 110 | 111 | /** 112 | * No-fail swap. 113 | */ 114 | void swap(pidl_array& a) throw() 115 | { 116 | std::swap(a.m_array, m_array); 117 | } 118 | 119 | private: 120 | std::vector m_array; 121 | }; 122 | 123 | }}} // namespace washer::shell::pidl 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /include/washer/shell/property_key.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | PROPERTYKEY wrapper. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_SHELL_PROPERTY_KEY_HPP 33 | #define WASHER_SHELL_PROPERTY_KEY_HPP 34 | #pragma once 35 | 36 | #include // totally_ordered 37 | 38 | #include // uuid_t 39 | 40 | #include // PROPERTYKEY 41 | 42 | namespace washer { 43 | namespace shell { 44 | 45 | /** 46 | * C++ version of the PROPERTYKEY (aka SHCOLUMNID) struct. 47 | * 48 | * Provides total ordering for use as keys in associative containers. 49 | */ 50 | class property_key : boost::totally_ordered 51 | { 52 | public: 53 | property_key(const PROPERTYKEY& pkey) 54 | : m_pid(pkey.pid), m_fmtid(pkey.fmtid) {} 55 | 56 | bool operator==(const property_key& other) const 57 | { 58 | return m_pid == other.m_pid && m_fmtid == other.m_fmtid; 59 | } 60 | 61 | bool operator<(const property_key& other) const 62 | { 63 | return m_pid < other.m_pid || 64 | ((m_pid == other.m_pid) && (m_fmtid < other.m_fmtid)); 65 | } 66 | 67 | /** 68 | * Convert to raw PROPERTYKEY struct. 69 | */ 70 | PROPERTYKEY get() const 71 | { 72 | PROPERTYKEY pkey; 73 | pkey.fmtid = m_fmtid; 74 | pkey.pid = m_pid; 75 | return pkey; 76 | } 77 | 78 | private: 79 | DWORD m_pid; 80 | comet::uuid_t m_fmtid; 81 | }; 82 | 83 | }} // namespace washer::shell 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /include/washer/shell/services.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Helpers to access services provided by Windows shell objects. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_SHELL_SERVICES_HPP 33 | #define WASHER_SHELL_SERVICES_HPP 34 | #pragma once 35 | 36 | #include // comtype 37 | #include // com_ptr 38 | 39 | #include // IServiceProvider 40 | #include // IShellBrowser, IShellView 41 | 42 | template<> struct comet::comtype 43 | { 44 | static const IID& uuid() throw() { return IID_IServiceProvider; } 45 | typedef IUnknown base; 46 | }; 47 | 48 | template<> struct comet::comtype 49 | { 50 | static const IID& uuid() throw() { return IID_IShellBrowser; } 51 | typedef IOleWindow base; 52 | }; 53 | 54 | template<> struct comet::comtype 55 | { 56 | static const IID& uuid() throw() { return IID_IShellView; } 57 | typedef IOleWindow base; 58 | }; 59 | 60 | namespace washer { 61 | namespace shell { 62 | 63 | /** 64 | * Return the parent IShellBrowser from an OLE site. 65 | */ 66 | inline comet::com_ptr shell_browser( 67 | comet::com_ptr ole_site) 68 | { 69 | if (!ole_site) 70 | BOOST_THROW_EXCEPTION(comet::com_error(E_POINTER)); 71 | 72 | comet::com_ptr sp = try_cast(ole_site); 73 | 74 | comet::com_ptr browser; 75 | HRESULT hr = sp->QueryService(SID_SShellBrowser, browser.out()); 76 | if (FAILED(hr)) 77 | BOOST_THROW_EXCEPTION(comet::com_error_from_interface(sp, hr)); 78 | 79 | return browser; 80 | } 81 | 82 | /** 83 | * Return the parent IShellView of a shell browser. 84 | */ 85 | inline comet::com_ptr shell_view( 86 | comet::com_ptr browser) 87 | { 88 | comet::com_ptr view; 89 | HRESULT hr = browser->QueryActiveShellView(view.out()); 90 | if (FAILED(hr)) 91 | BOOST_THROW_EXCEPTION(comet::com_error_from_interface(browser, hr)); 92 | 93 | return view; 94 | } 95 | 96 | }} // namespace washer::shell 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /include/washer/window/detail/window.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Window wrapper implementation details. 5 | 6 | @if license 7 | 8 | Copyright (C) 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_GUI_WINDOW_DETAIL_WINDOW_HPP 33 | #define WASHER_GUI_WINDOW_DETAIL_WINDOW_HPP 34 | #pragma once 35 | 36 | #include // last_error 37 | #include 38 | // destroy_window, get_window_text_length 39 | #include 40 | 41 | #include // errinfo_api_function 42 | #include // errinfo 43 | #include // numeric_cast 44 | #include // BOOST_THROW_EXCEPTION 45 | 46 | #include // assert 47 | #include // logic_error 48 | #include 49 | 50 | namespace washer { 51 | namespace window { 52 | namespace detail { 53 | 54 | inline void safe_destroy_window(HWND hwnd) 55 | { 56 | try 57 | { 58 | win32::destroy_window(hwnd); 59 | } 60 | catch (const std::exception& e) 61 | { 62 | washer::trace("Exception while destroying window: %s") % e.what(); 63 | } 64 | } 65 | 66 | inline void no_destroy_window(HWND) 67 | { 68 | } 69 | 70 | /** 71 | * The *lower bound* on the length of a window's text. 72 | * 73 | * In other words, the text may actually be shorter but never longer. 74 | */ 75 | template 76 | inline size_t window_text_length(HWND hwnd) 77 | { 78 | ::SetLastError(0); 79 | 80 | int cch = win32::get_window_text_length(hwnd); 81 | 82 | if (cch < 0) 83 | BOOST_THROW_EXCEPTION( 84 | std::logic_error("impossible (negative) text length")); 85 | if (cch == 0 && ::GetLastError() != 0) 86 | BOOST_THROW_EXCEPTION( 87 | boost::enable_error_info(washer::last_error()) << 88 | boost::errinfo_api_function("GetWindowTextLength")); 89 | 90 | return boost::numeric_cast(cch); 91 | } 92 | 93 | /** 94 | * Set a window's text. 95 | */ 96 | template 97 | inline void window_text(HWND hwnd, const std::basic_string& text) 98 | { 99 | if (!win32::set_window_text(hwnd, text.c_str())) 100 | BOOST_THROW_EXCEPTION( 101 | boost::enable_error_info(washer::last_error()) << 102 | boost::errinfo_api_function("SetWindowText")); 103 | } 104 | 105 | 106 | template 107 | inline std::basic_string window_text(HWND hwnd) 108 | { 109 | std::vector buffer(detail::window_text_length(hwnd) + 1); 110 | // +space for NULL 111 | 112 | ::SetLastError(0); 113 | 114 | int cch = detail::win32::get_window_text( 115 | hwnd, (buffer.empty()) ? NULL : &buffer[0], 116 | boost::numeric_cast(buffer.size())); 117 | 118 | if (cch < 0) 119 | BOOST_THROW_EXCEPTION( 120 | std::logic_error("impossible (negative) text length")); 121 | if (cch == 0 && ::GetLastError() != 0) 122 | BOOST_THROW_EXCEPTION( 123 | boost::enable_error_info(washer::last_error()) << 124 | boost::errinfo_api_function("GetWindowText")); 125 | 126 | assert((unsigned long)cch <= buffer.size()); 127 | 128 | if (buffer.empty()) 129 | return std::basic_string(); 130 | else 131 | return std::basic_string( 132 | &buffer[0], boost::numeric_cast(cch)); 133 | } 134 | 135 | 136 | }}} // namespace washer::window::detail 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /include/washer/window/detail/window_win32.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Thin layer around Win32 window functions. 5 | 6 | @if license 7 | 8 | Copyright (C) 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_WINDOW_DETAIL_WINDOW_WIN32_HPP 33 | #define WASHER_WINDOW_DETAIL_WINDOW_WIN32_HPP 34 | #pragma once 35 | 36 | #include // last_error 37 | 38 | #include 39 | #include // errinfo 40 | #include // BOOST_THROW_EXCEPTION 41 | 42 | #include // SetWindowLongPtr, GetWindowLongPtr, GetWindowTextLength 43 | // GetWindowText, SetWindowText, DestroyWindow, SetMenu, 44 | // GetWidowRect 45 | 46 | namespace washer { 47 | namespace window { 48 | namespace detail { 49 | namespace win32 { 50 | 51 | inline void destroy_window(HWND hwnd) 52 | { 53 | if (!::DestroyWindow(hwnd)) 54 | BOOST_THROW_EXCEPTION( 55 | boost::enable_error_info(washer::last_error()) << 56 | boost::errinfo_api_function("DestroyWindow")); 57 | } 58 | 59 | inline void set_menu(HWND hwnd, HMENU hmenu) 60 | { 61 | if (!::SetMenu(hwnd, hmenu)) 62 | BOOST_THROW_EXCEPTION( 63 | boost::enable_error_info(washer::last_error()) << 64 | boost::errinfo_api_function("SetMenu")); 65 | } 66 | 67 | inline void get_window_rect(HWND hwnd, RECT* rect) 68 | { 69 | if (::GetWindowRect(hwnd, rect) == 0) 70 | BOOST_THROW_EXCEPTION( 71 | boost::enable_error_info(washer::last_error()) << 72 | boost::errinfo_api_function("GetWindowRect")); 73 | } 74 | 75 | 76 | /// @name GetWindowTextLength 77 | // @{ 78 | template 79 | inline int get_window_text_length(HWND hwnd); 80 | 81 | template<> inline int get_window_text_length(HWND hwnd) 82 | { return ::GetWindowTextLengthA(hwnd); } 83 | 84 | template<> inline int get_window_text_length(HWND hwnd) 85 | { return ::GetWindowTextLengthW(hwnd); } 86 | // @} 87 | 88 | /// @name GetWindowText 89 | // @{ 90 | inline int get_window_text( 91 | HWND hwnd, char* out_buffer, int out_buffer_size) 92 | { return ::GetWindowTextA(hwnd, out_buffer, out_buffer_size); } 93 | 94 | inline int get_window_text( 95 | HWND hwnd, wchar_t* out_buffer, int out_buffer_size) 96 | { return ::GetWindowTextW(hwnd, out_buffer, out_buffer_size); } 97 | // @} 98 | // @} 99 | 100 | /// @name SetWindowText 101 | // @{ 102 | inline BOOL set_window_text(HWND hwnd, const char* text) 103 | { return ::SetWindowTextA(hwnd, text); } 104 | 105 | inline BOOL set_window_text(HWND hwnd, const wchar_t* text) 106 | { return ::SetWindowTextW(hwnd, text); } 107 | // @} 108 | 109 | }}}} // namespace washer::window::detail::win32 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /include/washer/window/dialog.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Dialog HWND wrapper class. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011, 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_WINDOW_DIALOG_HPP 33 | #define WASHER_WINDOW_DIALOG_HPP 34 | #pragma once 35 | 36 | #include // window base class 37 | 38 | namespace washer { 39 | namespace window { 40 | 41 | /** 42 | * Wrapper around an icon (a STATIC window with SS_ICON style). 43 | * 44 | * @todo Consider if it is worth checking class and style and throwing 45 | * an exception if it fails. 46 | */ 47 | template 48 | class dialog_window : public window 49 | { 50 | public: 51 | explicit dialog_window(const window_handle& handle) : window(handle) {} 52 | 53 | /** 54 | * Dialog manager message handling procedure. 55 | */ 56 | DLGPROC dialog_procedure() 57 | { 58 | return window_field(hwnd(), DWLP_DLGPROC); 59 | } 60 | 61 | /** 62 | * Change the function that handles dialog messages. 63 | * 64 | * This method is used to 'subclass' the dialog manager. 65 | * 66 | * @returns Pointer to previous dialog message procedure. 67 | */ 68 | DLGPROC change_dialog_procedure(DLGPROC new_dlgproc) 69 | { 70 | return set_window_field(hwnd(), DWLP_DLGPROC, new_dlgproc); 71 | } 72 | 73 | }; 74 | 75 | }} // namespace washer::window 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /include/washer/window/icon.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Icon HWND wrapper class. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011, 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_WINDOW_ICON_HPP 33 | #define WASHER_WINDOW_ICON_HPP 34 | #pragma once 35 | 36 | #include // last_error 37 | #include // window base class 38 | #include // send_message 39 | 40 | #include // errinfo_api_function 41 | #include // errinfo 42 | #include // BOOST_THROW_EXCEPTION 43 | 44 | #include // assert 45 | 46 | namespace washer { 47 | namespace window { 48 | 49 | /** 50 | * Wrapper around an icon (a STATIC window with SS_ICON style). 51 | * 52 | * @todo Consider if it is worth checking class and style and throwing 53 | * an exception if it fails. 54 | */ 55 | template 56 | class icon_window : public window 57 | { 58 | public: 59 | explicit icon_window(const window_handle& handle) : window(handle) {} 60 | 61 | HICON change_icon(HICON new_icon) 62 | { 63 | return washer::send_message_return( 64 | hwnd(), STM_SETIMAGE, IMAGE_ICON, new_icon); 65 | } 66 | }; 67 | 68 | }} // namespace washer::window 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /include/washer/window/window_handle.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | HWND lifetime management. 5 | 6 | @if license 7 | 8 | Copyright (C) 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_WINDOW_WINDOW_HANDLE_HPP 33 | #define WASHER_WINDOW_WINDOW_HANDLE_HPP 34 | #pragma once 35 | 36 | #include 37 | // safe_destroy_window, no_destroy_window 38 | 39 | #include 40 | #include 41 | 42 | #include // HWND 43 | 44 | namespace washer { 45 | namespace window { 46 | 47 | /** 48 | * Lifetime characteristics for wrapped window handle. 49 | * 50 | * Purpose: to abstract away the details of how an underlying Win32 window 51 | * handle's lifetime is managed. One constructor takes ownership of its 52 | * lifetime and one does not. 53 | */ 54 | class window_handle 55 | { 56 | typedef boost::shared_ptr::type> 57 | shared_window_handle; 58 | 59 | public: 60 | 61 | /** 62 | * Wrap a raw HWND without controlling its lifetime. 63 | * 64 | * The main purpose of this constructor is to use a window that we didn't 65 | * create and whose lifetime we don't own. An example would be an HWND 66 | * passed to us by the windows API. 67 | * 68 | * The caller is responsible for ensuring the Win32 window will outlive 69 | * this wrapper. A safer option is to use the `adopt_handle` constructor, 70 | * which will keep the window alive at least as long as the wrapper. 71 | */ 72 | static window_handle foster_handle(HWND handle) 73 | { 74 | return window_handle( 75 | shared_window_handle(handle, detail::no_destroy_window)); 76 | } 77 | 78 | /** 79 | * Wrap a window and take ownership of its underlying Win32 object. 80 | * 81 | * This is the safest of the two constructors as it keeps the window alive 82 | * as long as necessary and makes sure the window is destroyed after the 83 | * wrapper is destroyed. The Win32 window must not be destroyed by the 84 | * caller after passing to this constructor. Doing so will likely 85 | * result in a crash. 86 | */ 87 | static window_handle adopt_handle(HWND handle) 88 | { 89 | return window_handle( 90 | shared_window_handle(handle, detail::safe_destroy_window)); 91 | } 92 | 93 | HWND get() const 94 | { 95 | return m_handle.get(); 96 | } 97 | 98 | friend void swap(window_handle& a, window_handle& b) 99 | { 100 | swap(a.m_handle, b.m_handle); 101 | } 102 | 103 | private: 104 | 105 | window_handle(shared_window_handle handle) : m_handle(handle) {} 106 | 107 | shared_window_handle m_handle; 108 | }; 109 | 110 | }} // namespace washer::window 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(TEST_SOURCES 2 | fixture_permutator.hpp 3 | button_test_visitors.hpp 4 | item_test_visitors.hpp 5 | menu_fixtures.hpp 6 | sandbox_fixture.hpp 7 | wchar_output.hpp 8 | dynamic_link_test.cpp 9 | filesystem_test.cpp 10 | folder_error_adapter_test.cpp 11 | format_test.cpp 12 | global_lock_test.cpp 13 | hook_test.cpp 14 | icon_test.cpp 15 | menu_button_visitor_test.cpp 16 | menu_item_test.cpp 17 | menu_item_extraction_test.cpp 18 | menu_item_visitor_test.cpp 19 | menu_test.cpp 20 | module.cpp 21 | pidl_iterator_test.cpp 22 | pidl_test.cpp 23 | progress_test.cpp 24 | shell_test.cpp 25 | shell_item_test.cpp 26 | task_dialog_test.cpp 27 | window_test.cpp) 28 | 29 | include(max_warnings) 30 | 31 | 32 | # DLL used for DLL-function load testing 33 | 34 | add_library( 35 | load_test_dll SHARED 36 | load_test_dll/load_test_dll.h 37 | load_test_dll/load_test_dll.cpp 38 | load_test_dll/load_test_dll.def) 39 | 40 | # End DLL 41 | 42 | set(Boost_USE_STATIC_LIBS TRUE) 43 | find_package( 44 | Boost 1.40 REQUIRED 45 | COMPONENTS filesystem system unit_test_framework) 46 | 47 | add_executable(tests ${TEST_SOURCES}) 48 | target_include_directories(tests PRIVATE ${Boost_INCLUDE_DIRS}) 49 | target_link_libraries(tests 50 | PRIVATE washer load_test_dll ${Boost_LIBRARIES}) 51 | target_compile_definitions(tests PRIVATE BOOST_ALL_NO_LIB=1) 52 | 53 | add_executable(tests_unicode ${TEST_SOURCES}) 54 | target_include_directories(tests_unicode PRIVATE ${Boost_INCLUDE_DIRS}) 55 | target_link_libraries(tests_unicode 56 | PRIVATE washer load_test_dll ${Boost_LIBRARIES}) 57 | target_compile_definitions(tests_unicode PRIVATE BOOST_ALL_NO_LIB=1 _UNICODE) 58 | 59 | add_executable(tests_win9x ${TEST_SOURCES}) 60 | target_include_directories(tests_win9x PRIVATE ${Boost_INCLUDE_DIRS}) 61 | target_link_libraries(tests_win9x 62 | PRIVATE washer load_test_dll ${Boost_LIBRARIES}) 63 | target_compile_definitions(tests_win9x PRIVATE 64 | BOOST_ALL_NO_LIB=1 WINVER=0x0400 _WIN32_WINNT=0x0400) 65 | 66 | set(TEST_RUNNER_ARGUMENTS 67 | --catch_system_errors --detect_memory_leaks 68 | --result_code=no --log_level=test_suite) 69 | 70 | add_test(tests tests ${TEST_RUNNER_ARGUMENTS}) 71 | add_test(tests_unicode tests_unicode ${TEST_RUNNER_ARGUMENTS}) 72 | add_test(tests_win9x tests_win9x ${TEST_RUNNER_ARGUMENTS}) 73 | -------------------------------------------------------------------------------- /test/button_test_visitors.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Visitors used to make assertions about menu item buttons. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_TEST_MENU_BUTTON_TEST_VISITORS_HPP 33 | #define WASHER_TEST_MENU_BUTTON_TEST_VISITORS_HPP 34 | #pragma once 35 | 36 | #include "wchar_output.hpp" // wchar_t test output 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #include 43 | 44 | #include 45 | 46 | namespace washer { 47 | namespace test { 48 | 49 | class string_button_test : public washer::gui::menu::menu_visitor<> 50 | { 51 | public: 52 | string_button_test(const std::wstring& caption) : m_caption(caption) {} 53 | 54 | void operator()(washer::gui::menu::string_button& button) 55 | { 56 | BOOST_CHECK_EQUAL(button.caption(), m_caption); 57 | } 58 | 59 | template 60 | void operator()(T&) 61 | { 62 | BOOST_FAIL("Unexpected button type"); 63 | } 64 | 65 | private: 66 | std::wstring m_caption; 67 | }; 68 | 69 | class bitmap_button_test : public washer::gui::menu::menu_visitor<> 70 | { 71 | public: 72 | bitmap_button_test(HBITMAP bitmap) : m_bitmap(bitmap) {} 73 | 74 | void operator()(washer::gui::menu::bitmap_button& button) 75 | { 76 | BOOST_CHECK_EQUAL(button.bitmap(), m_bitmap); 77 | } 78 | 79 | template 80 | void operator()(T&) 81 | { 82 | BOOST_FAIL("Unexpected button type"); 83 | } 84 | 85 | private: 86 | HBITMAP m_bitmap; 87 | }; 88 | 89 | class string_button_mutator : public washer::gui::menu::menu_visitor<> 90 | { 91 | public: 92 | string_button_mutator(const std::wstring& caption) : m_caption(caption) {} 93 | 94 | void operator()(washer::gui::menu::string_button& button) 95 | { 96 | button.caption(m_caption); 97 | } 98 | 99 | template 100 | void operator()(T&) 101 | { 102 | BOOST_FAIL("Unexpected button type"); 103 | } 104 | 105 | private: 106 | std::wstring m_caption; 107 | }; 108 | 109 | class bitmap_button_mutator : public washer::gui::menu::menu_visitor<> 110 | { 111 | public: 112 | bitmap_button_mutator(HBITMAP bitmap) : m_bitmap(bitmap) {} 113 | 114 | void operator()(washer::gui::menu::bitmap_button& button) 115 | { 116 | button.bitmap(m_bitmap); 117 | } 118 | 119 | template 120 | void operator()(T&) 121 | { 122 | BOOST_FAIL("Unexpected button type"); 123 | } 124 | 125 | private: 126 | HBITMAP m_bitmap; 127 | }; 128 | 129 | }} 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /test/filesystem_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Tests for file and directory functions. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #include "wchar_output.hpp" // wstring output 33 | 34 | #include // test subject 35 | 36 | #include // path, wpath 37 | #include 38 | 39 | #include 40 | #include 41 | 42 | using washer::filesystem::temporary_directory_path; 43 | using washer::filesystem::unique_path; 44 | 45 | using boost::filesystem::path; 46 | using boost::filesystem::wpath; 47 | 48 | BOOST_AUTO_TEST_SUITE(filesystem_tests) 49 | 50 | /** 51 | * Create unique file name. 52 | */ 53 | BOOST_AUTO_TEST_CASE( unique_name ) 54 | { 55 | BOOST_CHECK(!unique_path().empty()); 56 | BOOST_CHECK(!unique_path().empty()); 57 | } 58 | 59 | /** 60 | * Temp directory path. 61 | */ 62 | BOOST_AUTO_TEST_CASE( temp_directory ) 63 | { 64 | BOOST_CHECK(!temporary_directory_path().empty()); 65 | BOOST_CHECK(temporary_directory_path().is_complete()); 66 | BOOST_CHECK(is_directory(temporary_directory_path())); 67 | 68 | BOOST_CHECK(!temporary_directory_path().empty()); 69 | BOOST_CHECK(temporary_directory_path().is_complete()); 70 | BOOST_CHECK(is_directory(temporary_directory_path())); 71 | } 72 | 73 | 74 | BOOST_AUTO_TEST_SUITE_END(); 75 | -------------------------------------------------------------------------------- /test/fixture_permutator.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Create permutations of test fixtures. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_TEST_FIXTURE_COMBINATOR_HPP 33 | #define WASHER_TEST_FIXTURE_COMBINATOR_HPP 34 | #pragma once 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | namespace washer { 44 | namespace test { 45 | 46 | namespace detail { 47 | 48 | template 49 | struct fixtures_loop 50 | { 51 | BOOST_MPL_ASSERT(( boost::mpl::is_sequence )); 52 | 53 | template 54 | struct use : boost::mpl::apply {}; 55 | 56 | typedef typename boost::mpl::fold< 57 | Inner, boost::mpl::vector<>, 58 | boost::mpl::push_back< boost::mpl::_1, use > 59 | >::type type; 60 | 61 | BOOST_MPL_ASSERT(( boost::mpl::is_sequence )); 62 | }; 63 | 64 | } 65 | 66 | /** 67 | * Produces all possible permutations of two lists of fixtures. 68 | * 69 | * The lists are combined by templated inheritance so the `Outer` list fixtures 70 | * but take a template parameter and inherit from it. This is instantiated 71 | * with the items from the `Inner` list. 72 | */ 73 | template 74 | struct fixture_permutator 75 | { 76 | BOOST_MPL_ASSERT(( boost::mpl::is_sequence )); 77 | BOOST_MPL_ASSERT(( boost::mpl::is_sequence )); 78 | 79 | typedef typename boost::mpl::fold< 80 | Outer, boost::mpl::vector<>, 81 | boost::mpl::copy< 82 | detail::fixtures_loop, 83 | boost::mpl::back_inserter 84 | > 85 | >::type type; 86 | 87 | BOOST_MPL_ASSERT(( boost::mpl::is_sequence )); 88 | }; 89 | 90 | }} 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /test/global_lock_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Tests for global lock management class. 5 | 6 | @if license 7 | 8 | Copyright (C) 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #include // test subject 33 | 34 | #include // shared_ptr 35 | #include // system_error 36 | #include 37 | #include // remove_pointer 38 | 39 | #include // memcpy 40 | #include 41 | 42 | BOOST_AUTO_TEST_SUITE(global_lock_tests) 43 | 44 | namespace { 45 | std::string test_data = "Mary had a little lamb"; 46 | 47 | typedef boost::shared_ptr::type> hglobal; 48 | 49 | hglobal test_global() 50 | { 51 | hglobal global( 52 | ::GlobalAlloc(GMEM_MOVEABLE, test_data.size()), ::GlobalFree); 53 | void* p = ::GlobalLock(global.get()); 54 | std::memcpy(p, &test_data[0], test_data.size()); 55 | ::GlobalUnlock(global.get()); 56 | 57 | return global; 58 | } 59 | } 60 | 61 | /** 62 | * Lock test memory. Should be unlocked automatically at the end of the test. 63 | */ 64 | BOOST_AUTO_TEST_CASE( lock_memory ) 65 | { 66 | hglobal global = test_global(); 67 | washer::global_lock lock(global.get()); 68 | BOOST_REQUIRE(lock.get()); 69 | 70 | BOOST_CHECK_EQUAL_COLLECTIONS( 71 | test_data.begin(), test_data.end(), 72 | lock.get(), lock.get() + test_data.size()); 73 | } 74 | 75 | /** 76 | * Locking an invalid HGLOBAL should throw. 77 | */ 78 | BOOST_AUTO_TEST_CASE( invalid_lock ) 79 | { 80 | BOOST_CHECK_THROW( 81 | washer::global_lock(NULL), boost::system::system_error); 82 | } 83 | 84 | BOOST_AUTO_TEST_SUITE_END(); 85 | -------------------------------------------------------------------------------- /test/hook_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Tests for window hooking 5 | 6 | @if license 7 | 8 | Copyright (C) 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #include // test subject 33 | 34 | #include // system_error 35 | #include 36 | 37 | BOOST_AUTO_TEST_SUITE(hook_tests) 38 | 39 | LRESULT CALLBACK test_keyboard_proc(int nCode, WPARAM wParam, LPARAM lParam) 40 | { 41 | // Win9x doesn't allow NULL as the first argument 42 | return ::CallNextHookEx(NULL /*hhook*/, nCode, wParam, lParam); 43 | } 44 | 45 | /** 46 | * Install a hook for the current thread. 47 | * Should be destroyed automatically at end of test. 48 | */ 49 | BOOST_AUTO_TEST_CASE( thread_hook ) 50 | { 51 | washer::hhook hook = washer::windows_hook( 52 | WH_KEYBOARD, test_keyboard_proc); 53 | BOOST_CHECK(hook); 54 | } 55 | 56 | /** 57 | * Install a global hook. Should be destroyed automatically at end of test. 58 | */ 59 | BOOST_AUTO_TEST_CASE( global_hook ) 60 | { 61 | washer::hhook hook = washer::windows_global_hook( 62 | WH_KEYBOARD_LL, test_keyboard_proc); 63 | BOOST_CHECK(hook); 64 | } 65 | 66 | /** 67 | * Try to install a global-only hook as a thread hook. 68 | * It should throw an exception. 69 | */ 70 | BOOST_AUTO_TEST_CASE( thread_hook_fail ) 71 | { 72 | BOOST_CHECK_THROW( 73 | washer::windows_hook( 74 | WH_KEYBOARD_LL, test_keyboard_proc), boost::system::system_error); 75 | } 76 | 77 | BOOST_AUTO_TEST_SUITE_END(); 78 | -------------------------------------------------------------------------------- /test/icon_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Tests for icon functions. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011, 2013 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #include // test subject 33 | 34 | #include 35 | 36 | #include 37 | 38 | using washer::gui::standard_icon_type; 39 | 40 | using std::string; 41 | using std::wstring; 42 | 43 | namespace { 44 | 45 | namespace native { 46 | 47 | inline HICON load_icon(HINSTANCE hinstance, const char* name) 48 | { return ::LoadIconA(hinstance, name); } 49 | 50 | inline HICON load_icon(HINSTANCE hinstance, const wchar_t* name) 51 | { return ::LoadIconW(hinstance, name); } 52 | } 53 | 54 | HICON load_legacy_icon(standard_icon_type::type type) 55 | { 56 | HICON icon = native::load_icon( 57 | NULL, MAKEINTRESOURCE( 58 | washer::gui::detail::icon_type_to_ici_icon_num(type))); 59 | BOOST_REQUIRE(icon); 60 | 61 | return icon; 62 | } 63 | } 64 | 65 | BOOST_AUTO_TEST_SUITE(standard_icon_tests) 66 | 67 | /** 68 | * Load each type of system icon. 69 | */ 70 | BOOST_AUTO_TEST_CASE( load_system_icon ) 71 | { 72 | BOOST_CHECK(load_standard_icon(standard_icon_type::application)); 73 | BOOST_CHECK(load_standard_icon(standard_icon_type::question)); 74 | BOOST_CHECK(load_standard_icon(standard_icon_type::warning)); 75 | BOOST_CHECK(load_standard_icon(standard_icon_type::error)); 76 | BOOST_CHECK(load_standard_icon(standard_icon_type::information)); 77 | #if(WINVER >= 0x0400) 78 | BOOST_CHECK(load_standard_icon(standard_icon_type::windows_logo)); 79 | #endif 80 | #if(WINVER >= 0x0600) 81 | BOOST_CHECK(load_standard_icon(standard_icon_type::shield)); 82 | #endif 83 | } 84 | 85 | /** 86 | * Loading the same system icon twice should yield the same handle. 87 | */ 88 | BOOST_AUTO_TEST_CASE( repeat_load_system_icon ) 89 | { 90 | HICON icon1 = load_standard_icon(standard_icon_type::error); 91 | HICON icon2 = load_standard_icon(standard_icon_type::error); 92 | BOOST_CHECK_EQUAL(icon1, icon2); 93 | } 94 | 95 | /** 96 | * Loading a system icon via the wrapped version of LoadImage should yield 97 | * the same handle returned by the legacy LoadIcon (wrapped only here in the 98 | * tests). 99 | */ 100 | BOOST_AUTO_TEST_CASE( load_image_load_icon ) 101 | { 102 | HICON icon1 = load_standard_icon(standard_icon_type::error); 103 | HICON icon2 = load_legacy_icon(standard_icon_type::error); 104 | BOOST_CHECK_EQUAL(icon1, icon2); 105 | } 106 | 107 | BOOST_AUTO_TEST_SUITE_END(); 108 | -------------------------------------------------------------------------------- /test/load_test_dll/load_test_dll.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Dummy DLL to test dynamic linking. 5 | 6 | @if license 7 | 8 | Copyright (C) 2013, 2014 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #include "load_test_dll.h" 33 | 34 | extern "C" 35 | { 36 | 37 | char* test_function() 38 | { 39 | return "Ran DLL function successfully"; 40 | } 41 | 42 | int unary_test_function(int x) 43 | { 44 | return x * 2; 45 | } 46 | 47 | int binary_test_function(int x, int y) 48 | { 49 | return x * y; 50 | } 51 | 52 | int __cdecl cdecl_test_function(int x) 53 | { 54 | return x * 3; 55 | } 56 | 57 | int __stdcall stdcall_test_function(int x) 58 | { 59 | return x * 3; 60 | } 61 | 62 | int __fastcall fastcall_test_function(int x) 63 | { 64 | return x * 3; 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /test/load_test_dll/load_test_dll.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | EXPORTS 3 | test_function 4 | unary_test_function 5 | binary_test_function 6 | cdecl_test_function 7 | stdcall_test_function 8 | fastcall_test_function -------------------------------------------------------------------------------- /test/load_test_dll/load_test_dll.h: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Dummy DLL to test dynamic linking. 5 | 6 | @if license 7 | 8 | Copyright (C) 2013, 2014 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_TEST_LOAD_TEST_DLL_LOAD_TEST_DLL_H 33 | #define WASHER_TEST_LOAD_TEST_DLL_LOAD_TEST_DLL_H 34 | 35 | extern "C" 36 | { 37 | 38 | // The functions must also be listed in the DEF file so that 39 | // GetProcAddress can find them without needed a mangled name 40 | // (http://stackoverflow.com/a/597573/67013). (Really only 41 | // stdcall and fastcall seem to need this but that's probably 42 | // compiler-specific) 43 | 44 | char* test_function(); 45 | 46 | int unary_test_function(int); 47 | 48 | int binary_test_function(int, int); 49 | 50 | int __cdecl cdecl_test_function(int x); 51 | 52 | int __stdcall stdcall_test_function(int x); 53 | 54 | int __fastcall fastcall_test_function(int x); 55 | 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /test/module.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Unit test module. 5 | 6 | @if license 7 | 8 | Copyright (C) 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #define BOOST_TEST_MODULE washer tests 33 | #include 34 | -------------------------------------------------------------------------------- /test/progress_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Tests for IProgressDialog wrapper. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #include // test subject 33 | 34 | #include // auto_coinit 35 | 36 | #include 37 | 38 | using washer::gui::progress; 39 | 40 | using comet::auto_coinit; 41 | 42 | namespace { 43 | 44 | class com_fixture 45 | { 46 | private: 47 | auto_coinit com; 48 | }; 49 | 50 | //const int SLEEP_TIME = 5000; 51 | const int SLEEP_TIME = 5; 52 | 53 | } 54 | 55 | BOOST_FIXTURE_TEST_SUITE(progress_tests, com_fixture) 56 | 57 | /** 58 | * Progress dialogue text display. 59 | */ 60 | BOOST_AUTO_TEST_CASE( text ) 61 | { 62 | progress dialogue( 63 | NULL, L"Test title", progress::modality::modal, 64 | progress::time_estimation::none, progress::bar_type::finite, 65 | progress::minimisable::yes, progress::cancellability::cancellable); 66 | dialogue.line(1, L"Text 1"); 67 | dialogue.line(2, L"Text 2"); 68 | dialogue.line(3, L"Text 3"); 69 | for (int i = 0; i <= SLEEP_TIME; ++i) 70 | { 71 | dialogue.update(i, SLEEP_TIME); 72 | ::Sleep(1); 73 | } 74 | } 75 | 76 | /** 77 | * Progress dialogue long path display. 78 | */ 79 | BOOST_AUTO_TEST_CASE( path ) 80 | { 81 | progress dialogue( 82 | NULL, L"Test title", progress::modality::modal, 83 | progress::time_estimation::none, progress::bar_type::finite, 84 | progress::minimisable::yes, progress::cancellability::cancellable); 85 | dialogue.line(1, L"Text 1"); 86 | dialogue.line_compress_paths_if_needed( 87 | 2, L"C:\\a\\very\\extremely\\indubitably\\" 88 | L"supercalifragilistically\\expialidociously\\long\\path"); 89 | dialogue.line_compress_paths_if_needed( 90 | 3, L"/a/very/very/extremely/indubitably/" 91 | L"supercalifragilistically/expialidociously/long/unix/path"); 92 | for (int i = 0; i <= SLEEP_TIME; ++i) 93 | { 94 | dialogue.update(i, SLEEP_TIME); 95 | ::Sleep(1); 96 | } 97 | } 98 | 99 | /** 100 | * Progress dialogue with automatic time estimation. 101 | */ 102 | BOOST_AUTO_TEST_CASE( text_with_time ) 103 | { 104 | progress dialogue( 105 | NULL, L"Test title", progress::modality::modal, 106 | progress::time_estimation::automatic_time_estimate, 107 | progress::bar_type::finite, 108 | progress::minimisable::yes, progress::cancellability::cancellable); 109 | dialogue.line(1, L"Text 1"); 110 | dialogue.line(2, L"Text 2"); 111 | for (int i = 0; i <= SLEEP_TIME; ++i) 112 | { 113 | dialogue.update(i, SLEEP_TIME); 114 | ::Sleep(3); 115 | } 116 | } 117 | 118 | /** 119 | * Progress dialogue with time and marquee. 120 | */ 121 | BOOST_AUTO_TEST_CASE( text_with_time_and_marquee ) 122 | { 123 | progress dialogue( 124 | NULL, L"Test title", progress::modality::modal, 125 | progress::time_estimation::automatic_time_estimate, 126 | progress::bar_type::marquee, 127 | progress::minimisable::yes, progress::cancellability::cancellable); 128 | dialogue.line(1, L"Text 1"); 129 | dialogue.line(2, L"Text 2"); 130 | for (int i = 0; i <= SLEEP_TIME; ++i) 131 | { 132 | dialogue.update(i, SLEEP_TIME); 133 | ::Sleep(3); 134 | } 135 | } 136 | 137 | /** 138 | * Progress dialogue with time but no progress bar. 139 | */ 140 | BOOST_AUTO_TEST_CASE( text_with_time_only ) 141 | { 142 | progress dialogue( 143 | NULL, L"Test title", progress::modality::modal, 144 | progress::time_estimation::automatic_time_estimate, 145 | progress::bar_type::none, 146 | progress::minimisable::yes, progress::cancellability::cancellable); 147 | dialogue.line(1, L"Text 1"); 148 | dialogue.line(2, L"Text 2"); 149 | for (int i = 0; i <= SLEEP_TIME; ++i) 150 | { 151 | dialogue.update(i, SLEEP_TIME); 152 | ::Sleep(3); 153 | } 154 | } 155 | 156 | BOOST_AUTO_TEST_SUITE_END(); 157 | -------------------------------------------------------------------------------- /test/sandbox_fixture.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Fixture creating a temporary sandbox directory. 5 | 6 | @if license 7 | 8 | Copyright (C) 2012 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_TEST_SANDBOX_FIXTURE_HPP 33 | #define WASHER_TEST_SANDBOX_FIXTURE_HPP 34 | #pragma once 35 | 36 | #include // temporary_directory_path, unique_path 37 | 38 | #include // wpath 39 | #include // wofstream 40 | #include 41 | #include // BOOST_REQUIRE etc. 42 | 43 | #include // _wtempnam 44 | #include 45 | #include 46 | 47 | namespace washer { 48 | namespace test { 49 | 50 | namespace detail { 51 | 52 | const std::wstring SANDBOX_NAME = L"washer-test-sandbox"; 53 | 54 | /** 55 | * Return the path to the sandbox directory. 56 | */ 57 | inline boost::filesystem::wpath sandbox_directory() 58 | { 59 | boost::shared_ptr name( 60 | _wtempnam(NULL, SANDBOX_NAME.c_str()), free); 61 | BOOST_REQUIRE(name); 62 | 63 | return name.get(); 64 | } 65 | 66 | inline bool is_child_path( 67 | const boost::filesystem::wpath& parent, 68 | const boost::filesystem::wpath& child) 69 | { 70 | boost::filesystem::wpath lhs = complete(parent); 71 | boost::filesystem::wpath rhs = complete(child); 72 | 73 | boost::filesystem::wpath::iterator left(lhs.begin()); 74 | boost::filesystem::wpath::iterator right(rhs.begin()); 75 | 76 | for (;*left == *right && left != lhs.end() && right != rhs.end(); 77 | ++left, ++right); 78 | 79 | return left == lhs.end(); 80 | } 81 | } 82 | 83 | /** 84 | * Fixture that creates and destroys a sandbox directory. 85 | */ 86 | class sandbox_fixture 87 | { 88 | public: 89 | sandbox_fixture() : m_sandbox(detail::sandbox_directory()) 90 | { 91 | create_directory(m_sandbox); 92 | } 93 | 94 | ~sandbox_fixture() 95 | { 96 | try 97 | { 98 | remove_all(m_sandbox); 99 | } 100 | catch (...) {} 101 | } 102 | 103 | boost::filesystem::wpath sandbox() 104 | { 105 | return m_sandbox; 106 | } 107 | 108 | /** 109 | * Create a new empty file in the fixture sandbox with a random name 110 | * and return the path. 111 | */ 112 | boost::filesystem::wpath new_file_in_sandbox( 113 | const boost::filesystem::wpath& subdirectory, 114 | const std::wstring& extension) 115 | { 116 | BOOST_REQUIRE_MESSAGE( 117 | detail::is_child_path(sandbox(), subdirectory), 118 | "Test file must not stray outside sandbox"); 119 | 120 | boost::filesystem::wpath filename = 121 | washer::filesystem::unique_path(); 122 | boost::filesystem::wpath p = 123 | #if defined(BOOST_FILESYSTEM_VERSION) && BOOST_FILESYSTEM_VERSION > 2 124 | subdirectory / (filename.wstring() + extension); 125 | #else 126 | subdirectory / (filename.string() + extension); 127 | #endif 128 | 129 | BOOST_REQUIRE(!exists(p)); 130 | BOOST_REQUIRE(p.is_complete()); 131 | 132 | boost::filesystem::wofstream s(p); 133 | 134 | BOOST_REQUIRE(exists(p)); 135 | BOOST_REQUIRE(is_regular_file(p)); 136 | 137 | return p; 138 | } 139 | 140 | boost::filesystem::wpath new_file_in_sandbox() 141 | { 142 | return new_file_in_sandbox(sandbox(), std::wstring()); 143 | } 144 | 145 | /** 146 | * Create a new empty directory in the fixture sandbox with a random name 147 | * and return the path. 148 | */ 149 | boost::filesystem::wpath new_directory_in_sandbox( 150 | const boost::filesystem::wpath& subdirectory) 151 | { 152 | BOOST_REQUIRE_MESSAGE( 153 | detail::is_child_path(sandbox(), subdirectory), 154 | "Test directory must not stray outside sandbox"); 155 | 156 | boost::filesystem::wpath p = 157 | subdirectory / washer::filesystem::unique_path(); 158 | 159 | create_directory(p); 160 | 161 | BOOST_CHECK(exists(p)); 162 | BOOST_CHECK(is_directory(p)); 163 | BOOST_CHECK(p.is_complete()); 164 | return p; 165 | } 166 | 167 | boost::filesystem::wpath new_directory_in_sandbox() 168 | { 169 | return new_directory_in_sandbox(sandbox()); 170 | } 171 | 172 | private: 173 | boost::filesystem::wpath m_sandbox; 174 | }; 175 | 176 | }} // namespace washer::test 177 | 178 | #endif 179 | -------------------------------------------------------------------------------- /test/wchar_output.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | @file 3 | 4 | Helper functions for Boost.Test allowing wide strings as test output. 5 | 6 | @if license 7 | 8 | Copyright (C) 2009, 2010, 2011 Alexander Lamaison 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | 23 | If you modify this Program, or any covered work, by linking or 24 | combining it with the OpenSSL project's OpenSSL library (or a 25 | modified version of that library), containing parts covered by the 26 | terms of the OpenSSL or SSLeay licenses, the licensors of this 27 | Program grant you additional permission to convey the resulting work. 28 | 29 | @endif 30 | */ 31 | 32 | #ifndef WASHER_TEST_WCHAR_OUTPUT_HPP 33 | #define WASHER_TEST_WCHAR_OUTPUT_HPP 34 | #pragma once 35 | 36 | #include // last_error 37 | 38 | #include // wpath 39 | #include // numeric_cast 40 | #include 41 | #include // BOOST_THROW_EXCEPTION 42 | 43 | #include // assert 44 | #include 45 | #include 46 | #include 47 | 48 | #include // GetRunningObjectTable 49 | #include // WideCharToMultiByte 50 | 51 | namespace washer { 52 | namespace test { 53 | 54 | namespace detail { 55 | 56 | template 57 | struct converter 58 | { 59 | typedef _FromElem FromElem; 60 | typedef _ToElem ToElem; 61 | typedef std::basic_string FromType; 62 | typedef std::basic_string ToType; 63 | }; 64 | 65 | struct narrow : converter 66 | { 67 | int operator()( 68 | const FromElem* pszWide, int cchWide, 69 | ToElem* pszNarrow, int cbNarrow) 70 | { 71 | return ::WideCharToMultiByte( 72 | CP_UTF8, 0, pszWide, cchWide, pszNarrow, cbNarrow, NULL, NULL); 73 | } 74 | }; 75 | 76 | } 77 | 78 | 79 | /** 80 | * Convert a basic_string-style string from one element type to another. 81 | * 82 | * @tparam T Converter functor to perform the actual conversion. 83 | */ 84 | template 85 | inline typename T::ToType convert_string(const typename T::FromType& from) 86 | { 87 | const int size = boost::numeric_cast(from.size()); 88 | if (size == 0) 89 | return typename T::ToType(); 90 | 91 | // Calculate necessary buffer size 92 | int len = T()(from.data(), size, NULL, 0); 93 | 94 | // Perform actual conversion 95 | if (len > 0) 96 | { 97 | std::vector buffer(len); 98 | len = T()( 99 | from.data(), size, 100 | &buffer[0], static_cast(buffer.size())); 101 | if (len > 0) 102 | { 103 | assert(len == boost::numeric_cast(buffer.size())); 104 | return typename T::ToType(&buffer[0], len); 105 | } 106 | } 107 | 108 | BOOST_THROW_EXCEPTION(washer::last_error()); 109 | } 110 | 111 | /** 112 | * Convert a Windows wide string to a UTF-8 (multi-byte) string. 113 | */ 114 | inline std::string wide_string_to_utf8(const std::wstring& wide) 115 | { 116 | return convert_string(wide); 117 | } 118 | 119 | }} 120 | 121 | namespace std { 122 | 123 | inline std::ostream& operator<<( 124 | std::ostream& out, const std::wstring& wide_in) 125 | { 126 | out << washer::test::wide_string_to_utf8(wide_in); 127 | return out; 128 | } 129 | 130 | inline std::ostream& operator<<( 131 | std::ostream& out, const wchar_t* wide_in) 132 | { 133 | out << std::wstring(wide_in); 134 | return out; 135 | } 136 | 137 | inline std::ostream& operator<<( 138 | std::ostream& out, const boost::filesystem::wpath& path) 139 | { 140 | out << path.string(); 141 | return out; 142 | } 143 | } 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /test/window_test.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alamaison/washer/01730af6612f5049abd409c779b1332dd1b839ed/test/window_test.cpp --------------------------------------------------------------------------------