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.

843 lines
24 KiB

  1. /* /////////////////////////////////////////////////////////////////////////
  2. * File: winstl/control_panel/applet_module.hpp
  3. *
  4. * Purpose: Control Panel module/applet manipulation classes.
  5. *
  6. * Created: 1st April 2006
  7. * Updated: 10th August 2009
  8. *
  9. * Home: http://stlsoft.org/
  10. *
  11. * Copyright (c) 2006-2009, Matthew Wilson and Synesis Software
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or without
  15. * modification, are permitted provided that the following conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright notice, this
  18. * list of conditions and the following disclaimer.
  19. * - Redistributions in binary form must reproduce the above copyright notice,
  20. * this list of conditions and the following disclaimer in the documentation
  21. * and/or other materials provided with the distribution.
  22. * - Neither the name(s) of Matthew Wilson and Synesis Software nor the names of
  23. * any contributors may be used to endorse or promote products derived from
  24. * this software without specific prior written permission.
  25. *
  26. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36. * POSSIBILITY OF SUCH DAMAGE.
  37. *
  38. * ////////////////////////////////////////////////////////////////////// */
  39. /** \file winstl/control_panel/applet_module.hpp
  40. *
  41. * \brief [C++ only] Definition of the
  42. * \link winstl::applet applet\endlink
  43. * and
  44. * \link winstl::applet_module applet_module\endlink
  45. * classes
  46. * (\ref group__library__windows_control_panel "Windows Control Panel" Library).
  47. */
  48. #ifndef WINSTL_INCL_WINSTL_CONTROL_PANEL_HPP_APPLET_MODULE
  49. #define WINSTL_INCL_WINSTL_CONTROL_PANEL_HPP_APPLET_MODULE
  50. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  51. # define WINSTL_VER_WINSTL_CONTROL_PANEL_HPP_APPLET_MODULE_MAJOR 1
  52. # define WINSTL_VER_WINSTL_CONTROL_PANEL_HPP_APPLET_MODULE_MINOR 1
  53. # define WINSTL_VER_WINSTL_CONTROL_PANEL_HPP_APPLET_MODULE_REVISION 11
  54. # define WINSTL_VER_WINSTL_CONTROL_PANEL_HPP_APPLET_MODULE_EDIT 23
  55. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  56. /* /////////////////////////////////////////////////////////////////////////
  57. * Compatibility
  58. */
  59. /*
  60. [Incompatibilies-start]
  61. STLSOFT_COMPILER_IS_GCC: __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
  62. [Incompatibilies-end]
  63. */
  64. /* /////////////////////////////////////////////////////////////////////////
  65. * Includes
  66. */
  67. #ifndef WINSTL_INCL_WINSTL_H_WINSTL
  68. # include <winstl/winstl.h>
  69. #endif /* !WINSTL_INCL_WINSTL_H_WINSTL */
  70. #ifndef WINSTL_INCL_WINSTL_CONTROL_PANEL_H_FUNCTIONS
  71. # include <winstl/control_panel/functions.h>
  72. #endif /* !WINSTL_INCL_WINSTL_CONTROL_PANEL_H_FUNCTIONS */
  73. #ifndef WINSTL_INCL_WINSTL_CONTROL_PANEL_ERROR_HPP_EXCEPTIONS
  74. # include <winstl/control_panel/error/exceptions.hpp>
  75. #endif /* !WINSTL_INCL_WINSTL_CONTROL_PANEL_ERROR_HPP_EXCEPTIONS */
  76. #ifndef WINSTL_INCL_WINSTL_STRING_HPP_RESOURCE_STRING
  77. # include <winstl/string/resource_string.hpp>
  78. #endif /* !WINSTL_INCL_WINSTL_STRING_HPP_RESOURCE_STRING */
  79. #ifndef WINSTL_INCL_WINSTL_DL_HPP_MODULE
  80. # include <winstl/dl/module.hpp>
  81. #endif /* !WINSTL_INCL_WINSTL_DL_HPP_MODULE */
  82. #ifndef STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING
  83. # include <stlsoft/string/simple_string.hpp>
  84. #endif /* !STLSOFT_INCL_STLSOFT_STRING_HPP_SIMPLE_STRING */
  85. #ifndef STLSOFT_INCL_VECTOR
  86. # define STLSOFT_INCL_VECTOR
  87. # include <vector>
  88. #endif /* !STLSOFT_INCL_VECTOR */
  89. /* /////////////////////////////////////////////////////////////////////////
  90. * Namespace
  91. */
  92. #ifndef _WINSTL_NO_NAMESPACE
  93. # if defined(_STLSOFT_NO_NAMESPACE) || \
  94. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  95. /* There is no stlsoft namespace, so must define ::winstl */
  96. namespace winstl
  97. {
  98. # else
  99. /* Define stlsoft::winstl_project */
  100. namespace stlsoft
  101. {
  102. namespace winstl_project
  103. {
  104. # endif /* _STLSOFT_NO_NAMESPACE */
  105. #endif /* !_WINSTL_NO_NAMESPACE */
  106. /* /////////////////////////////////////////////////////////////////////////
  107. * Forward declarations
  108. */
  109. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  110. class applet_module;
  111. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  112. /* /////////////////////////////////////////////////////////////////////////
  113. * Classes
  114. */
  115. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  116. /** \brief [IMPLEMENTATION]
  117. */
  118. struct applet_module_base
  119. {
  120. HINSTANCE m_hinst;
  121. APPLET_PROC m_pfn;
  122. HWND m_hwnd;
  123. int m_flags;
  124. public:
  125. applet_module_base()
  126. : m_hinst(NULL)
  127. , m_pfn(NULL)
  128. , m_hwnd(NULL)
  129. , m_flags(0)
  130. {}
  131. };
  132. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  133. /** \brief Represents a Control Panel Applet
  134. *
  135. * \ingroup group__library__windows_control_panel
  136. *
  137. * Instances of this class are managed by the applet_module class, and
  138. * available by its subscript operator. For example, the following code
  139. * retrieves a reference to the first applet and invokes it:
  140. \code
  141. winstl::applet_module &module = . . . ;
  142. winstl::applet &applet0 = module[0];
  143. applet0.open();
  144. \endcode
  145. *
  146. */
  147. class applet
  148. {
  149. /// \name Member Types
  150. /// @{
  151. public:
  152. /// \brief The type of this class
  153. typedef applet class_type;
  154. /// \brief The string type
  155. typedef stlsoft_ns_qual(basic_simple_string)<TCHAR> string_type;
  156. /// \brief The index type
  157. typedef ss_size_t index_type;
  158. private:
  159. typedef basic_resource_string< string_type
  160. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  161. , resource_exception_policy
  162. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  163. , stlsoft_ns_qual(null_exception_policy)
  164. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  165. > resource_string_type_;
  166. /// @}
  167. /// \name Construction
  168. /// @{
  169. private:
  170. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  171. friend class applet_module;
  172. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  173. applet(applet_module_base *module, index_type index);
  174. public:
  175. /** \brief Releases any resources associated with the instance.
  176. */
  177. ~applet() stlsoft_throw_0();
  178. /// @}
  179. /// \name Operations
  180. /// @{
  181. public:
  182. /** \brief Invokes the applet, with the given window, if specified,
  183. * as the dialog parent.
  184. *
  185. * \param hwnd [in] Handle to a window that will act as the parent
  186. * window for the applet dialog.
  187. */
  188. void open(HWND hwnd = NULL);
  189. /** \brief Invokes the applet passing a parameter string, with the
  190. * given window, if specified, as the dialog parent.
  191. *
  192. * \param hwnd [in] Handle to a window that will act as the parent
  193. * window for the applet dialog.
  194. * \param arguments [in] Arguments to pass to the applet.
  195. */
  196. void open(HWND hwnd, TCHAR const* arguments);
  197. /// @}
  198. /// \name Attributes
  199. /// @{
  200. public:
  201. /// \brief The index of the applet in the containing applet module
  202. index_type get_index() const;
  203. /// \brief The applet name
  204. string_type get_name() const;
  205. /// \brief The description of the applet
  206. string_type get_description() const;
  207. /// \brief The icon associated with the applet
  208. HICON get_icon() const;
  209. /// \brief The user-date, if any, associated with the applet.
  210. LONG get_data() const;
  211. /// @}
  212. /// \name Members
  213. /// @{
  214. private:
  215. applet_module_base *m_module;
  216. index_type m_index;
  217. HICON m_icon;
  218. string_type m_name;
  219. string_type m_description;
  220. LONG m_data;
  221. /// @}
  222. };
  223. /** \brief Represents a Control Panel Applet module, and provides methods
  224. * for loading and accessing applets.
  225. *
  226. * The following code enumerates all the applet modules in the Windows
  227. * system directory, and prints out the name and description of each
  228. * applet contained within.
  229. *
  230. \code
  231. #include <winstl/findfile_sequence.hpp>
  232. #include <winstl/system_directory.hpp>
  233. #include <winstl/control_panel/applet_module.hpp>
  234. #include <iostream>
  235. int main()
  236. {
  237. try
  238. {
  239. winstl::system_directory sysDir;
  240. winstl::findfile_sequence files(sysDir, "*.cpl", winstl::findfile_sequence::files);
  241. { for(winstl::findfile_sequence::const_iterator b = files.begin(); b != files.end(); ++b)
  242. {
  243. winstl::applet_module module(*b, winstl::applet_module:dontExpectNonZeroInit);
  244. winstl::applet_module::const_iterator b = module.begin();
  245. winstl::applet_module::const_iterator e = module.end();
  246. std::cout << "path: " << module.get_path() << std::endl;
  247. for(; b != e; ++b)
  248. {
  249. winstl::applet const &applet = *b;
  250. std::cout << " applet index: " << applet.get_index() << std::endl;
  251. std::cout << " name: " << applet.get_name() << std::endl;
  252. std::cout << " description: " << applet.get_description() << std::endl;
  253. }
  254. std::cout << std::endl;
  255. }}
  256. }
  257. catch(std::exception &x)
  258. {
  259. std::cerr << "Exception: " << x.what() << std::endl;
  260. }
  261. return 0;
  262. }
  263. \endcode
  264. *
  265. * Note the use of the
  266. * \link winstl::applet_module::load_flags dontExpectNonZeroInit\endlink
  267. * flag, which is recommended because several common control panel
  268. * modules do not correctly implement their CPL_INIT handlers.
  269. *
  270. * \ingroup group__library__windows_control_panel
  271. */
  272. class applet_module
  273. #if defined(STLSOFT_COMPILER_IS_DMC)
  274. : public applet_module_base
  275. #else /* ? compiler */
  276. : private applet_module_base
  277. #endif /* compiler */
  278. {
  279. /// \name Member Types
  280. /// @{
  281. public:
  282. /// \brief The type of this class
  283. typedef applet_module class_type;
  284. /// \brief The value type
  285. typedef applet value_type;
  286. /// \brief The size type
  287. typedef ss_size_t size_type;
  288. /// \brief The index type
  289. typedef ss_size_t index_type;
  290. /// \brief The string type
  291. typedef stlsoft_ns_qual(basic_simple_string)<TCHAR> string_type;
  292. private:
  293. typedef stlsoft_ns_qual_std(vector)<value_type> applets_type_;
  294. public:
  295. /// \brief The mutating (non-const) iterator type
  296. typedef applets_type_::iterator iterator;
  297. /// \brief The non-mutating (const) iterator type
  298. typedef applets_type_::const_iterator const_iterator;
  299. /// \brief Prototype of <b>cdecl</b> function that receives error notifications.
  300. typedef void (STLSOFT_CDECL *onFailureC)(TCHAR const* path);
  301. /// \brief Prototype of <b>stdcall</b> function that receives error notifications.
  302. typedef void (STLSOFT_STDCALL *onFailureS)(TCHAR const* path);
  303. private:
  304. struct error_translator
  305. {
  306. public:
  307. error_translator();
  308. error_translator(onFailureC pfn);
  309. error_translator(onFailureS pfn);
  310. private:
  311. static void STLSOFT_CDECL on_failure(TCHAR const* path);
  312. private:
  313. int cc; // One of STLSOFT_CDECL_VALUE or STLSOFT_STDCALL_VALUE
  314. union
  315. {
  316. onFailureC pfnC;
  317. onFailureS pfnS;
  318. };
  319. };
  320. /// @}
  321. /// \name Member Constants
  322. /// @{
  323. public:
  324. /// \brief Flags that moderate the load behaviour.
  325. enum load_flags
  326. {
  327. ignoreIconLoadFailures = 0x0001 //!< \brief Ignores icon load failures and continues applet loading.
  328. , dontExpectNonZeroInit = 0x0002 //!< \brief Some applet module entry points don't return 0.
  329. , assumeOneAppletIfNone = 0x0004 //!< \brief Some applet module entry points return 0 from CPL_GETCOUNT.
  330. };
  331. /// @}
  332. /// \name Construction
  333. /// @{
  334. public:
  335. /// \brief Constructs an instance containing all the applets in the
  336. /// given module.
  337. ///
  338. /// \param path [in] Path of the applet module.
  339. /// \param flags [in] Flags that moderate the loading behaviour.
  340. /// \param hwndParent [in] Handle to a window to act as the parent for
  341. /// the dialog(s) of the applet(s) contained in the module
  342. ///
  343. /// \exception winstl::control_panel_exception Thrown if the applet module
  344. /// initialisation fails.
  345. /// \exception winstl::resource_exception Thrown if the icon cannot be loaded
  346. /// for a given applet, and
  347. /// \link applet_module::load_flags ignoreIconLoadFailures\endlink.
  348. ss_explicit_k applet_module(TCHAR const* path, int flags = ignoreIconLoadFailures, HWND hwndParent = NULL);
  349. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  350. ss_explicit_k applet_module(TCHAR const* path, onFailureC pfn, int flags = ignoreIconLoadFailures, HWND hwndParent = NULL);
  351. ss_explicit_k applet_module(TCHAR const* path, onFailureS pfn, int flags = ignoreIconLoadFailures, HWND hwndParent = NULL);
  352. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  353. /// @}
  354. /// \name Attributes
  355. /// @{
  356. public:
  357. /// \brief The path used to initialise the instance.
  358. string_type const &get_path() const;
  359. /// @}
  360. /// \name Accessors
  361. /// @{
  362. public:
  363. /// \brief The number of applets in the module.
  364. size_type size() const;
  365. /// \brief Returns a mutable (non-const) reference to the applet at the index.
  366. ///
  367. /// \param index [in] Applet index
  368. ///
  369. /// \note The behaviour is undefined if index >= size()
  370. value_type& operator [](index_type index);
  371. /// \brief Returns a non-mutable (const) reference to the applet at the index.
  372. ///
  373. /// \param index [in] Applet index
  374. ///
  375. /// \note The behaviour is undefined if index >= size()
  376. value_type const& operator [](index_type index) const;
  377. /// @}
  378. /// \name Iteration
  379. /// @{
  380. public:
  381. /// \brief Begins the iteration
  382. ///
  383. /// \return An iterator representing the start of the sequence
  384. iterator begin();
  385. /// \brief Ends the iteration
  386. ///
  387. /// \return An iterator representing the end of the sequence
  388. iterator end();
  389. /// \brief Begins the iteration
  390. ///
  391. /// \return An iterator representing the start of the sequence
  392. const_iterator begin() const;
  393. /// \brief Ends the iteration
  394. ///
  395. /// \return An iterator representing the end of the sequence
  396. const_iterator end() const;
  397. /// @}
  398. /// \name Implementation
  399. /// @{
  400. private:
  401. void init_(int flags, HWND hwndParent);
  402. /// @}
  403. /// \name Members
  404. /// @{
  405. private:
  406. const string_type m_path;
  407. module m_module;
  408. applets_type_ m_applets;
  409. error_translator m_errorTranslator;
  410. /// @}
  411. /// \name Not to be implemented
  412. /// @{
  413. private:
  414. applet_module(class_type const&);
  415. class_type& operator =(class_type const&);
  416. /// @}
  417. };
  418. /* /////////////////////////////////////////////////////////////////////////
  419. * Implementation
  420. */
  421. #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
  422. // applet
  423. inline applet::applet(applet_module_base *module, applet::index_type index)
  424. : m_module(module)
  425. , m_index(index)
  426. , m_icon(NULL)
  427. , m_name()
  428. , m_description()
  429. , m_data(0)
  430. {
  431. WINSTL_ASSERT(NULL != module);
  432. WINSTL_ASSERT(0 == index || index < control_panel_get_count(m_module->m_pfn, m_module->m_hwnd));
  433. ::SetLastError(0);
  434. if( !control_panel_init(m_module->m_pfn, m_module->m_hwnd) &&
  435. 0 == (m_module->m_flags & applet_module::dontExpectNonZeroInit))
  436. {
  437. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  438. STLSOFT_THROW_X(control_panel_exception("Applet initialisation failed", ::GetLastError()));
  439. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  440. ::SetLastError(ERROR_DLL_INIT_FAILED);
  441. m_module = NULL;
  442. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  443. }
  444. else
  445. {
  446. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  447. try
  448. {
  449. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  450. CPLINFO info = { CPL_DYNAMIC_RES, CPL_DYNAMIC_RES, CPL_DYNAMIC_RES, 0 };
  451. control_panel_inquire(m_module->m_pfn, m_module->m_hwnd, m_index, &info);
  452. if(CPL_DYNAMIC_RES != info.idIcon)
  453. {
  454. m_icon = ::LoadIcon(m_module->m_hinst, MAKEINTRESOURCE(info.idIcon));
  455. if( NULL == m_icon &&
  456. applet_module::ignoreIconLoadFailures == (m_module->m_flags & applet_module::ignoreIconLoadFailures))
  457. {
  458. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  459. STLSOFT_THROW_X(resource_exception("Could not load the applet icon", ::GetLastError(), MAKEINTRESOURCE(info.idIcon), RT_ICON));
  460. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  461. }
  462. }
  463. if(CPL_DYNAMIC_RES != info.idName)
  464. {
  465. m_name = resource_string_type_(m_module->m_hinst, info.idName);
  466. }
  467. if(CPL_DYNAMIC_RES != info.idInfo)
  468. {
  469. m_description = resource_string_type_(m_module->m_hinst, info.idInfo);
  470. }
  471. m_data = info.lData;
  472. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  473. }
  474. catch(...)
  475. {
  476. control_panel_uninit(m_module->m_pfn, m_module->m_hwnd);
  477. throw;
  478. }
  479. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  480. }
  481. }
  482. inline applet::~applet() stlsoft_throw_0()
  483. {
  484. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  485. WINSTL_ASSERT(NULL != m_module);
  486. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  487. if(NULL != NULL)
  488. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  489. {
  490. control_panel_uninit(m_module->m_pfn, m_module->m_hwnd);
  491. }
  492. }
  493. inline void applet::open(HWND hwnd)
  494. {
  495. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  496. WINSTL_ASSERT(NULL != m_module);
  497. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  498. if(NULL != NULL)
  499. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  500. {
  501. if(NULL == hwnd)
  502. {
  503. hwnd = m_module->m_hwnd;
  504. }
  505. control_panel_run(m_module->m_pfn, hwnd, m_index, m_data);
  506. }
  507. }
  508. inline void applet::open(HWND hwnd, TCHAR const* arguments)
  509. {
  510. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  511. WINSTL_ASSERT(NULL != m_module);
  512. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  513. if(NULL != NULL)
  514. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  515. {
  516. if( NULL == arguments ||
  517. '\0' == *arguments)
  518. {
  519. this->open(hwnd);
  520. }
  521. else
  522. {
  523. if(NULL == hwnd)
  524. {
  525. hwnd = m_module->m_hwnd;
  526. }
  527. control_panel_run(m_module->m_pfn, hwnd, m_index, arguments);
  528. }
  529. }
  530. }
  531. inline applet::index_type applet::get_index() const
  532. {
  533. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  534. WINSTL_ASSERT(NULL != m_module);
  535. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  536. if(NULL == m_module)
  537. {
  538. return ~index_type(0);
  539. }
  540. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  541. return m_index;
  542. }
  543. inline applet::string_type applet::get_name() const
  544. {
  545. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  546. WINSTL_ASSERT(NULL != m_module);
  547. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  548. if(NULL == m_module)
  549. {
  550. return m_name;
  551. }
  552. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  553. if(m_name.empty())
  554. {
  555. NEWCPLINFO info = { sizeof(info), 0, 0, 0, NULL, { '\0' }, { '\0' }, { '\0' } };
  556. control_panel_newinquire(m_module->m_pfn, m_module->m_hwnd, m_index, &info);
  557. return info.szName;
  558. }
  559. return m_name;
  560. }
  561. inline applet::string_type applet::get_description() const
  562. {
  563. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  564. WINSTL_ASSERT(NULL != m_module);
  565. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  566. if(NULL == m_module)
  567. {
  568. return m_description;
  569. }
  570. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  571. if(m_description.empty())
  572. {
  573. NEWCPLINFO info = { sizeof(info), 0, 0, 0, NULL, { '\0' }, { '\0' }, { '\0' } };
  574. control_panel_newinquire(m_module->m_pfn, m_module->m_hwnd, m_index, &info);
  575. return info.szInfo;
  576. }
  577. return m_description;
  578. }
  579. inline HICON applet::get_icon() const
  580. {
  581. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  582. WINSTL_ASSERT(NULL != m_module);
  583. #else /* ? STLSOFT_CF_EXCEPTION_SUPPORT */
  584. if(NULL == m_module)
  585. {
  586. return NULL;
  587. }
  588. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  589. if(NULL == m_icon)
  590. {
  591. NEWCPLINFO info = { sizeof(info), 0, 0, 0, NULL, { '\0' }, { '\0' }, { '\0' } };
  592. control_panel_newinquire(m_module->m_pfn, m_module->m_hwnd, m_index, &info);
  593. return info.hIcon;
  594. }
  595. return m_icon;
  596. }
  597. inline LONG applet::get_data() const
  598. {
  599. return m_data;
  600. }
  601. // applet_module::error_translator
  602. inline applet_module::error_translator::error_translator()
  603. : cc(STLSOFT_CDECL_VALUE)
  604. {
  605. pfnC = on_failure;
  606. }
  607. inline applet_module::error_translator::error_translator(applet_module::onFailureC pfn)
  608. : cc(STLSOFT_CDECL_VALUE)
  609. {
  610. pfnC = pfn;
  611. }
  612. inline applet_module::error_translator::error_translator(applet_module::onFailureS pfn)
  613. : cc(STLSOFT_STDCALL_VALUE)
  614. {
  615. pfnS = pfn;
  616. }
  617. inline /* static */ void STLSOFT_CDECL applet_module::error_translator::on_failure(TCHAR const* /* path */)
  618. {}
  619. // applet_module
  620. inline void applet_module::init_(int flags, HWND hwndParent)
  621. {
  622. WINSTL_ASSERT(NULL == m_hwnd);
  623. WINSTL_ASSERT(NULL == m_pfn);
  624. ::SetLastError(0);
  625. if(NULL == m_module.get_symbol("CPlApplet", m_pfn))
  626. {
  627. #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
  628. STLSOFT_THROW_X(control_panel_exception("Control panel entry point not found", ::GetLastError()));
  629. #endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
  630. }
  631. else
  632. {
  633. m_flags = flags;
  634. m_hwnd = hwndParent;
  635. m_hinst = m_module.get_module_handle();
  636. size_type numApplets = control_panel_get_count(m_pfn, m_hwnd);
  637. if( 0 == numApplets &&
  638. assumeOneAppletIfNone == (m_flags & assumeOneAppletIfNone))
  639. {
  640. numApplets = 1;
  641. }
  642. { for(size_type index = 0; index < numApplets; ++index)
  643. {
  644. m_applets.push_back(applet(this, index));
  645. }}
  646. }
  647. }
  648. inline applet_module::applet_module(TCHAR const* path, int flags /* = ignoreIconLoadFailures */, HWND hwndParent /* = NULL */)
  649. : m_path(path)
  650. , m_module(path)
  651. , m_applets()
  652. , m_errorTranslator()
  653. {
  654. init_(flags, hwndParent);
  655. }
  656. inline applet_module::applet_module(TCHAR const* path, applet_module::onFailureC pfn, int flags /* = ignoreIconLoadFailures */, HWND hwndParent /* = NULL */)
  657. : m_path(path)
  658. , m_module(path)
  659. , m_applets()
  660. , m_errorTranslator(pfn)
  661. {
  662. init_(flags, hwndParent);
  663. }
  664. inline applet_module::applet_module(TCHAR const* path, applet_module::onFailureS pfn, int flags /* = ignoreIconLoadFailures */, HWND hwndParent /* = NULL */)
  665. : m_path(path)
  666. , m_module(path)
  667. , m_applets()
  668. , m_errorTranslator(pfn)
  669. {
  670. init_(flags, hwndParent);
  671. }
  672. inline applet_module::string_type const& applet_module::get_path() const
  673. {
  674. return m_path;
  675. }
  676. inline applet_module::size_type applet_module::size() const
  677. {
  678. return m_applets.size();
  679. }
  680. inline applet_module::value_type &applet_module::operator [](index_type index)
  681. {
  682. WINSTL_MESSAGE_ASSERT("Invalid index", index < size());
  683. return m_applets[index];
  684. }
  685. inline applet_module::value_type const& applet_module::operator [](index_type index) const
  686. {
  687. WINSTL_MESSAGE_ASSERT("Invalid index", index < size());
  688. return m_applets[index];
  689. }
  690. inline applet_module::iterator applet_module::begin()
  691. {
  692. return m_applets.begin();
  693. }
  694. inline applet_module::iterator applet_module::end()
  695. {
  696. return m_applets.end();
  697. }
  698. inline applet_module::const_iterator applet_module::begin() const
  699. {
  700. return m_applets.begin();
  701. }
  702. inline applet_module::const_iterator applet_module::end() const
  703. {
  704. return m_applets.end();
  705. }
  706. #endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
  707. /* /////////////////////////////////////////////////////////////////////////
  708. * Unit-testing
  709. */
  710. #ifdef STLSOFT_UNITTEST
  711. # include "./unittest/applet_module_unittest_.h"
  712. #endif /* STLSOFT_UNITTEST */
  713. /* ////////////////////////////////////////////////////////////////////// */
  714. #ifndef _WINSTL_NO_NAMESPACE
  715. # if defined(_STLSOFT_NO_NAMESPACE) || \
  716. defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
  717. } // namespace winstl
  718. # else
  719. } // namespace winstl_project
  720. } // namespace stlsoft
  721. # endif /* _STLSOFT_NO_NAMESPACE */
  722. #endif /* !_WINSTL_NO_NAMESPACE */
  723. /* ////////////////////////////////////////////////////////////////////// */
  724. #endif /* WINSTL_INCL_WINSTL_CONTROL_PANEL_HPP_APPLET_MODULE */
  725. /* ///////////////////////////// end of file //////////////////////////// */