You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

530 lines
18 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/clipboard/clipboard_scope.hpp
  3. *
  4. * Purpose: Clipboard scoping and facade class.
  5. *
  6. * Created: 26th May 2005
  7. * Updated: 10th August 2009
  8. *
  9. * Thanks: To Martin Moene for reporting the problem with the data type
  10. * in set_data_or_deallocate_and_throw_(), and for calling for
  11. * clarification of the get_data() semantics
  12. *
  13. * Home: http://stlsoft.org/
  14. *
  15. * Copyright (c) 2005-2009, Matthew Wilson and Synesis Software
  16. * All rights reserved.
  17. *
  18. * Redistribution and use in source and binary forms, with or without
  19. * modification, are permitted provided that the following conditions are met:
  20. *
  21. * - Redistributions of source code must retain the above copyright notice, this
  22. * list of conditions and the following disclaimer.
  23. * - Redistributions in binary form must reproduce the above copyright notice,
  24. * this list of conditions and the following disclaimer in the documentation
  25. * and/or other materials provided with the distribution.
  26. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  27. * any contributors may be used to endorse or promote products derived from
  28. * this software without specific prior written permission.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  31. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  32. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  34. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  35. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  36. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  37. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  38. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  39. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGE.
  41. *
  42. * ////////////////////////////////////////////////////////////////////// */
  43. /** \file winstl/clipboard/clipboard_scope.hpp
  44. *
  45. * \brief [C++ only] Definition of the winstl::clipboard_scope class
  46. * (\ref group__library__windows_clipboard "Windows Clipboard" Library).
  47. */
  48. #ifndef WINSTL_INCL_WINSTL_CLIPBOARD_HPP_CLIPBOARD_SCOPE
  49. #define WINSTL_INCL_WINSTL_CLIPBOARD_HPP_CLIPBOARD_SCOPE
  50. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  51. # define WINSTL_VER_WINSTL_CLIPBOARD_HPP_CLIPBOARD_SCOPE_MAJOR 2
  52. # define WINSTL_VER_WINSTL_CLIPBOARD_HPP_CLIPBOARD_SCOPE_MINOR 0
  53. # define WINSTL_VER_WINSTL_CLIPBOARD_HPP_CLIPBOARD_SCOPE_REVISION 7
  54. # define WINSTL_VER_WINSTL_CLIPBOARD_HPP_CLIPBOARD_SCOPE_EDIT 34
  55. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  56. /* /////////////////////////////////////////////////////////////////////////
  57. * Includes
  58. */
  59. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  60. # include <winstl/winstl.h>
  61. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  62. #ifndef WINSTL_INCL_WINSTL_CLIPBOARD_ERROR_HPP_EXCEPTIONS
  63. # include <winstl/clipboard/error/exceptions.hpp>
  64. #endif /* !WINSTL_INCL_WINSTL_CLIPBOARD_ERROR_HPP_EXCEPTIONS */
  65. #ifndef WINSTL_INCL_WINSTL_MEMORY_HPP_GLOBAL_ALLOCATOR
  66. # include <winstl/memory/global_allocator.hpp>
  67. #endif /* !WINSTL_INCL_WINSTL_MEMORY_HPP_GLOBAL_ALLOCATOR */
  68. #ifndef STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_BASE
  69. # include <stlsoft/memory/allocator_base.hpp> // for STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT
  70. #endif /* !STLSOFT_INCL_STLSOFT_MEMORY_HPP_ALLOCATOR_BASE */
  71. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_CSTRING_FUNCTIONS
  72. # include <stlsoft/string/cstring_functions.hpp>
  73. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_CSTRING_FUNCTIONS */
  74. /* /////////////////////////////////////////////////////////////////////////
  75. * Namespace
  76. */
  77. #ifndef _WINSTL_NO_NAMESPACE
  78. # if defined(_STLSOFT_NO_NAMESPACE) || \
  79. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  80. /* There is no stlsoft namespace, so must define ::winstl */
  81. namespace winstl
  82. {
  83. # else
  84. /* Define stlsoft::winstl_project */
  85. namespace stlsoft
  86. {
  87. namespace winstl_project
  88. {
  89. # endif /* _STLSOFT_NO_NAMESPACE */
  90. #endif /* !_WINSTL_NO_NAMESPACE */
  91. /* /////////////////////////////////////////////////////////////////////////
  92. * Classes
  93. */
  94. /** \brief Indicates failure to access or manipulate the Windows clipboard.
  95. *
  96. * \ingroup group__library__windows_clipboard
  97. *
  98. * \see winstl::clipboard_scope
  99. */
  100. class clipboard_scope_exception
  101. : public clipboard_exception
  102. {
  103. /// \name Member Types
  104. /// @{
  105. public:
  106. typedef clipboard_exception parent_class_type;
  107. typedef clipboard_scope_exception class_type;
  108. /// @}
  109. /// \name Construction
  110. /// @{
  111. public:
  112. clipboard_scope_exception(char const* reason, error_code_type err)
  113. : clipboard_exception(reason, err)
  114. {}
  115. /// @}
  116. /// \name Not to be implemented
  117. /// @{
  118. private:
  119. class_type& operator =(class_type const&);
  120. /// @}
  121. };
  122. /** \brief This class acquires access to the Win32 clipboard, and acts as
  123. * a facade over the clipboard API.
  124. *
  125. * \ingroup group__library__windows_clipboard
  126. *
  127. * The class provides a simple and straightforward facade to the clipboard,
  128. * while at the same time acquiring and releasing ownership of the
  129. * clipboard. The following code acquires access to the clipboard, and sets
  130. * a string on to it:
  131. \code
  132. // 1. Set the data on the clipboard
  133. {
  134. winstl::clipboard_scope scope;
  135. scope.set_data("The data");
  136. }
  137. \endcode
  138. *
  139. * As long as no other thread/process changes the clipboard contents in the
  140. * meanwhile, this can then be read back, as follows:
  141. *
  142. \code
  143. // 2. Get the data from the clipboard
  144. {
  145. winstl::clipboard_scope scope;
  146. char const* str;
  147. scope.get_data(str);
  148. std::cout << "Clipboard data: " << str << std::endl;
  149. }
  150. \endcode
  151. *
  152. * In each case, the lifetime of the
  153. * \link winstl::clipboard_scope clipboard_scope\endlink is scoped with a
  154. * block - <code>{ }</code> - in order to release ownership of the
  155. * clipboard.
  156. *
  157. * \note All the methods throw an instance of
  158. * \link winstl::clipboard_scope_exception clipboard_scope_exception\endlink
  159. * if they fail.
  160. */
  161. class clipboard_scope
  162. #if defined(STLSOFT_COMPILER_IS_DMC)
  163. : protected global_allocator<void>
  164. #else /* ? compiler */
  165. : private global_allocator<void>
  166. #endif /* compiler */
  167. {
  168. /// \name Types
  169. /// @{
  170. private:
  171. typedef global_allocator<void> parent_class_type;
  172. public:
  173. typedef clipboard_scope class_type;
  174. typedef global_allocator<void> allocator_type;
  175. /// @}
  176. /// \name Construction
  177. /// @{
  178. public:
  179. /// \brief Takes ownership of the clipboard
  180. ///
  181. /// \param hwndOwner Window to be associated as owner of the clipboard.
  182. /// May be NULL, in which case the current thread owns the clipboard.
  183. ss_explicit_k clipboard_scope(HWND hwndOwner = NULL) stlsoft_throw_1(clipboard_scope_exception);
  184. /// \brief Gives up ownership of the clipboard.
  185. ~clipboard_scope() stlsoft_throw_0();
  186. /// @}
  187. /// \name Attributes
  188. /// @{
  189. public:
  190. /// \brief Returns a copy of the allocator used by the class.
  191. allocator_type get_allocator() const;
  192. /// @}
  193. /// \name Operations
  194. /// @{
  195. public:
  196. /// \brief Empties the clipboard.
  197. void clear() stlsoft_throw_1(clipboard_scope_exception);
  198. /// \brief Returns the current owner of the clipboard.
  199. HWND owner() const;
  200. /// \brief Indicates whether a given format is available.
  201. ws_bool_t is_fmt_available(UINT fmt) const;
  202. /// \brief Sets the given data with the given format into the clipboard.
  203. void set_data(UINT fmt, HANDLE hData) stlsoft_throw_1(clipboard_scope_exception);
  204. /// \brief Sets the given text to the clipboard with CF_TEXT format.
  205. void set_data(char const* str) stlsoft_throw_1(clipboard_scope_exception);
  206. /// \brief Sets the given text to the clipboard with CF_TEXT format.
  207. void set_data(char const* str, ws_size_t n) stlsoft_throw_1(clipboard_scope_exception);
  208. /// \brief Sets the given text to the clipboard with CF_UNICODETEXT format.
  209. void set_data(wchar_t const* str) stlsoft_throw_1(clipboard_scope_exception);
  210. /// \brief Sets the given text to the clipboard with CF_UNICODETEXT format.
  211. void set_data(wchar_t const* str, ws_size_t n) stlsoft_throw_1(clipboard_scope_exception);
  212. /// \brief Sets the bitmap to the clipboard with CF_BITMAP format.
  213. void set_data(HBITMAP hBmp) stlsoft_throw_1(clipboard_scope_exception);
  214. /// \brief Sets the bitmap to the clipboard with CF_HDROP format.
  215. void set_data(HDROP hDrop) stlsoft_throw_1(clipboard_scope_exception);
  216. /// \brief Sets the bitmap to the clipboard with CF_ENHMETAFILE format.
  217. void set_data(HENHMETAFILE hEmf) stlsoft_throw_1(clipboard_scope_exception);
  218. /// \brief Sets the bitmap to the clipboard with CF_PALETTE format.
  219. void set_data(HPALETTE hPal) stlsoft_throw_1(clipboard_scope_exception);
  220. /// \brief Gets the data with the requested format from the clipboard
  221. ///
  222. /// \note The handle must be used before the clipboard_scope destructor is
  223. /// invoked, or its contents copied
  224. HANDLE get_data(UINT fmt) const stlsoft_throw_1(clipboard_scope_exception);
  225. /// \brief Gets the clipboard data with the CF_TEXT format.
  226. ///
  227. /// \note The string pointer must be used before the clipboard_scope destructor is
  228. /// invoked, or its contents copied
  229. void get_data(char const*& str) const stlsoft_throw_1(clipboard_scope_exception);
  230. /// \brief Gets the clipboard data with the CF_UNICODETEXT format.
  231. ///
  232. /// \note The string pointer must be used before the clipboard_scope destructor is
  233. /// invoked, or its contents copied
  234. void get_data(wchar_t const*& str) const stlsoft_throw_1(clipboard_scope_exception);
  235. /// \brief Gets the clipboard data with the CF_BITMAP format.
  236. ///
  237. /// \note The bitmap handle must be used before the clipboard_scope destructor is
  238. /// invoked, or its contents copied
  239. void get_data(HBITMAP& hBmp) const stlsoft_throw_1(clipboard_scope_exception);
  240. /// \brief Gets the clipboard data with the CF_HDROP format.
  241. ///
  242. /// \note The drop handle must be used before the clipboard_scope destructor is
  243. /// invoked, or its contents copied
  244. void get_data(HDROP& hDrop) const stlsoft_throw_1(clipboard_scope_exception);
  245. /// \brief Gets the clipboard data with the CF_ENHMETAFILE format.
  246. ///
  247. /// \note The metafile handle must be used before the clipboard_scope destructor is
  248. /// invoked, or its contents copied
  249. void get_data(HENHMETAFILE& hEmf) const stlsoft_throw_1(clipboard_scope_exception);
  250. /// \brief Gets the clipboard data with the CF_PALETTE format.
  251. ///
  252. /// \note The palette handle must be used before the clipboard_scope destructor is
  253. /// invoked, or its contents copied
  254. void get_data(HPALETTE& hPal) const stlsoft_throw_1(clipboard_scope_exception);
  255. /// @}
  256. /// \name Members
  257. /// @{
  258. private:
  259. template< ss_typename_param_k A
  260. , ss_typename_param_k T
  261. >
  262. void set_data_or_deallocate_and_throw_(UINT fmt, T* memory, A& ator) stlsoft_throw_1(clipboard_scope_exception)
  263. {
  264. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  265. try
  266. {
  267. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  268. set_data(fmt, static_cast<HANDLE>(memory));
  269. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  270. }
  271. catch(...)
  272. {
  273. ator.deallocate(memory);
  274. throw;
  275. }
  276. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  277. }
  278. /// @}
  279. /// \name Members
  280. /// @{
  281. private:
  282. clipboard_scope(class_type const&);
  283. class_type& operator =(class_type const&);
  284. /// @}
  285. };
  286. ////////////////////////////////////////////////////////////////////////////
  287. // Unit-testing
  288. #ifdef STLSOFT_UNITTEST
  289. # include "./unittest/clipboard_scope_unittest_.h"
  290. #endif /* STLSOFT_UNITTEST */
  291. /* /////////////////////////////////////////////////////////////////////////
  292. * Shims
  293. */
  294. /* /////////////////////////////////////////////////////////////////////////
  295. * Implementation
  296. */
  297. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  298. inline clipboard_scope::clipboard_scope(HWND hwndOwner /* = NULL */) stlsoft_throw_1(clipboard_scope_exception)
  299. {
  300. if(!::OpenClipboard(hwndOwner))
  301. {
  302. STLSOFT_THROW_X(clipboard_scope_exception("Cannot open clipboard", ::GetLastError()));
  303. }
  304. }
  305. inline clipboard_scope::~clipboard_scope() stlsoft_throw_0()
  306. {
  307. ::CloseClipboard();
  308. }
  309. inline clipboard_scope::allocator_type clipboard_scope::get_allocator() const
  310. {
  311. allocator_type const& ator = *this;
  312. return ator;
  313. }
  314. inline void clipboard_scope::clear() stlsoft_throw_1(clipboard_scope_exception)
  315. {
  316. if(!::EmptyClipboard())
  317. {
  318. STLSOFT_THROW_X(clipboard_scope_exception("Cannot empty clipboard", ::GetLastError()));
  319. }
  320. }
  321. inline HWND clipboard_scope::owner() const
  322. {
  323. HWND hwnd = ::GetClipboardOwner();
  324. if( NULL == hwnd &&
  325. ERROR_SUCCESS != ::GetLastError())
  326. {
  327. STLSOFT_THROW_X(clipboard_scope_exception("Cannot get clipboard owner", ::GetLastError()));
  328. }
  329. return hwnd;
  330. }
  331. inline ws_bool_t clipboard_scope::is_fmt_available(UINT fmt) const
  332. {
  333. return BOOL2bool(::IsClipboardFormatAvailable(fmt));
  334. }
  335. inline void clipboard_scope::set_data(UINT fmt, HANDLE hData) stlsoft_throw_1(clipboard_scope_exception)
  336. {
  337. if(NULL == ::SetClipboardData(fmt, hData))
  338. {
  339. STLSOFT_THROW_X(clipboard_scope_exception("Cannot set clipboard data", ::GetLastError()));
  340. }
  341. }
  342. inline void clipboard_scope::set_data(char const* str) stlsoft_throw_1(clipboard_scope_exception)
  343. {
  344. #ifdef STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT
  345. allocator_type::rebind<char>::other ator(*this);
  346. #else /* ? STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  347. global_allocator<char> ator;
  348. #endif /* STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  349. char* memory = stlsoft_ns_qual(string_dup)(str, ator);
  350. set_data_or_deallocate_and_throw_(CF_TEXT, memory, ator);
  351. }
  352. inline void clipboard_scope::set_data(char const* str, ws_size_t n) stlsoft_throw_1(clipboard_scope_exception)
  353. {
  354. #ifdef STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT
  355. allocator_type::rebind<char>::other ator(*this);
  356. #else /* ? STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  357. global_allocator<char> ator;
  358. #endif /* STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  359. char* memory = stlsoft_ns_qual(string_dup)(str, n, ator);
  360. set_data_or_deallocate_and_throw_(CF_TEXT, memory, ator);
  361. }
  362. inline void clipboard_scope::set_data(wchar_t const* str) stlsoft_throw_1(clipboard_scope_exception)
  363. {
  364. #ifdef STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT
  365. allocator_type::rebind<wchar_t>::other ator(*this);
  366. #else /* ? STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  367. global_allocator<wchar_t> ator;
  368. #endif /* STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  369. wchar_t* memory = stlsoft_ns_qual(string_dup)(str, ator);
  370. set_data_or_deallocate_and_throw_(CF_UNICODETEXT, memory, ator);
  371. }
  372. inline void clipboard_scope::set_data(wchar_t const* str, ws_size_t n) stlsoft_throw_1(clipboard_scope_exception)
  373. {
  374. #ifdef STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT
  375. allocator_type::rebind<wchar_t>::other ator(*this);
  376. #else /* ? STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  377. global_allocator<wchar_t> ator;
  378. #endif /* STLSOFT_LF_ALLOCATOR_REBIND_SUPPORT */
  379. wchar_t* memory = stlsoft_ns_qual(string_dup)(str, n, ator);
  380. set_data_or_deallocate_and_throw_(CF_UNICODETEXT, memory, ator);
  381. }
  382. inline void clipboard_scope::set_data(HBITMAP hBmp) stlsoft_throw_1(clipboard_scope_exception)
  383. {
  384. set_data(CF_BITMAP, hBmp);
  385. }
  386. inline void clipboard_scope::set_data(HDROP hDrop) stlsoft_throw_1(clipboard_scope_exception)
  387. {
  388. set_data(CF_HDROP, hDrop);
  389. }
  390. inline void clipboard_scope::set_data(HENHMETAFILE hEmf) stlsoft_throw_1(clipboard_scope_exception)
  391. {
  392. set_data(CF_ENHMETAFILE, hEmf);
  393. }
  394. inline void clipboard_scope::set_data(HPALETTE hPal) stlsoft_throw_1(clipboard_scope_exception)
  395. {
  396. set_data(CF_PALETTE, hPal);
  397. }
  398. inline HANDLE clipboard_scope::get_data(UINT fmt) const stlsoft_throw_1(clipboard_scope_exception)
  399. {
  400. HANDLE hData = ::GetClipboardData(fmt);
  401. if( NULL == hData &&
  402. ERROR_SUCCESS != ::GetLastError())
  403. {
  404. STLSOFT_THROW_X(clipboard_scope_exception("Cannot get clipboard data", ::GetLastError()));
  405. }
  406. return hData;
  407. }
  408. inline void clipboard_scope::get_data(char const*& str) const stlsoft_throw_1(clipboard_scope_exception)
  409. {
  410. str = static_cast<char const*>(get_data(CF_TEXT));
  411. }
  412. inline void clipboard_scope::get_data(wchar_t const*& str) const stlsoft_throw_1(clipboard_scope_exception)
  413. {
  414. str = static_cast<wchar_t const*>(get_data(CF_UNICODETEXT));
  415. }
  416. inline void clipboard_scope::get_data(HBITMAP& hBmp) const stlsoft_throw_1(clipboard_scope_exception)
  417. {
  418. hBmp = static_cast<HBITMAP>(get_data(CF_BITMAP));
  419. }
  420. inline void clipboard_scope::get_data(HDROP& hDrop) const stlsoft_throw_1(clipboard_scope_exception)
  421. {
  422. hDrop = static_cast<HDROP>(get_data(CF_HDROP));
  423. }
  424. inline void clipboard_scope::get_data(HENHMETAFILE& hEmf) const stlsoft_throw_1(clipboard_scope_exception)
  425. {
  426. hEmf = static_cast<HENHMETAFILE>(get_data(CF_ENHMETAFILE));
  427. }
  428. inline void clipboard_scope::get_data(HPALETTE& hPal) const stlsoft_throw_1(clipboard_scope_exception)
  429. {
  430. hPal = static_cast<HPALETTE>(get_data(CF_PALETTE));
  431. }
  432. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  433. /* /////////////////////////////////////////////////////////////////////////
  434. * Namespace
  435. */
  436. #ifndef _WINSTL_NO_NAMESPACE
  437. # if defined(_STLSOFT_NO_NAMESPACE) || \
  438. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  439. } // namespace winstl
  440. # else
  441. } // namespace winstl_project
  442. } // namespace stlsoft
  443. # endif /* _STLSOFT_NO_NAMESPACE */
  444. #endif /* !_WINSTL_NO_NAMESPACE */
  445. /* ////////////////////////////////////////////////////////////////////// */
  446. #endif /* WINSTL_INCL_WINSTL_CLIPBOARD_HPP_CLIPBOARD_SCOPE */
  447. /* ///////////////////////////// end of file //////////////////////////// */