annotate foosdk/sdk/foobar2000/helpers/atl-misc.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
1 #pragma once
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include "win32_misc.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 #include <SDK/ui_element.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 #include <SDK/ui.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 #include <SDK/contextmenu_manager.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 #include <SDK/preferences_page.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 #include <libPPUI/WTL-PP.h>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 #include <utility>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 class CMenuSelectionReceiver : public CWindowImpl<CMenuSelectionReceiver> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 CMenuSelectionReceiver(HWND p_parent) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 WIN32_OP( Create(p_parent) != NULL );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 ~CMenuSelectionReceiver() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 if (m_hWnd != NULL) DestroyWindow();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21 typedef CWindowImpl<CMenuSelectionReceiver> _baseClass;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 DECLARE_WND_CLASS_EX(TEXT("{DF0087DB-E765-4283-BBAB-6AB2E8AB64A1}"),0,0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 BEGIN_MSG_MAP(CMenuSelectionReceiver)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 MESSAGE_HANDLER(WM_MENUSELECT,OnMenuSelect)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26 END_MSG_MAP()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 virtual bool QueryHint(unsigned p_id,pfc::string_base & p_out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 return false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 LRESULT OnMenuSelect(UINT,WPARAM p_wp,LPARAM p_lp,BOOL&) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 if (p_lp != 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 if (HIWORD(p_wp) & MF_POPUP) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
35 m_status.release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
36 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 pfc::string8 msg;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 UINT cmd = LOWORD(p_wp);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 if ( cmd == 0 || !QueryHint(cmd,msg)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
40 m_status.release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
41 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 if (m_status.is_empty()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 if (!static_api_ptr_t<ui_control>()->override_status_text_create(m_status)) m_status.release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 if (m_status.is_valid()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 m_status->override_text(msg);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
49 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
50 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
51 m_status.release();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
52 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 return 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
56 service_ptr_t<ui_status_text_override> m_status;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 PFC_CLASS_NOT_COPYABLE(CMenuSelectionReceiver,CMenuSelectionReceiver);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 class CMenuDescriptionMap : public CMenuSelectionReceiver {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 CMenuDescriptionMap(HWND p_parent) : CMenuSelectionReceiver(p_parent) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 void Set(unsigned p_id,const char * p_description) {m_content.set(p_id,p_description);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 bool QueryHint(unsigned p_id,pfc::string_base & p_out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 return m_content.query(p_id,p_out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 pfc::map_t<unsigned,pfc::string8> m_content;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 class CMenuDescriptionHybrid : public CMenuSelectionReceiver {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 CMenuDescriptionHybrid(HWND parent) : CMenuSelectionReceiver(parent) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 void Set(unsigned id, const char * desc) {m_content.set(id, desc);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 void SetCM(contextmenu_manager::ptr mgr, unsigned base, unsigned max) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79 m_cmMgr = mgr; m_cmMgr_base = base; m_cmMgr_max = max;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 bool QueryHint(unsigned p_id,pfc::string_base & p_out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 if (m_cmMgr.is_valid() && p_id >= m_cmMgr_base && p_id < m_cmMgr_max) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 return m_cmMgr->get_description_by_id(p_id - m_cmMgr_base,p_out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 return m_content.query(p_id,p_out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 pfc::map_t<unsigned,pfc::string8> m_content;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 contextmenu_manager::ptr m_cmMgr; unsigned m_cmMgr_base, m_cmMgr_max;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93 inline pfc::string_base & operator<<(pfc::string_base & p_fmt,const CPoint & p_point) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 return p_fmt << "(" << p_point.x << "," << p_point.y << ")";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 inline pfc::string_base & operator<<(pfc::string_base & p_fmt,const CRect & p_rect) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 return p_fmt << "(" << p_rect.left << "," << p_rect.top << "," << p_rect.right << "," << p_rect.bottom << ")";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 template<typename TClass>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 class CAddDummyMessageMap : public TClass {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 BEGIN_MSG_MAP(CAddDummyMessageMap<TClass>)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 END_MSG_MAP()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
108 template<typename _parentClass> class CWindowFixSEH : public _parentClass { public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 __try {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 return _parentClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 } __except(uExceptFilterProc(GetExceptionInformation())) { return FALSE; /* should not get here */ }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 template<typename ... arg_t> CWindowFixSEH( arg_t && ... arg ) : _parentClass( std::forward<arg_t>(arg) ... ) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 template<typename TClass>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 class CWindowAutoLifetime : public CWindowFixSEH<TClass> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120 typedef CWindowFixSEH<TClass> TBase;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 template<typename ... arg_t> CWindowAutoLifetime(HWND parent, arg_t && ... arg) : TBase( std::forward<arg_t>(arg) ... ) {Init(parent);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 void Init(HWND parent) {WIN32_OP(this->Create(parent) != NULL);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 void OnFinalMessage(HWND wnd) {PFC_ASSERT_NO_EXCEPTION( TBase::OnFinalMessage(wnd) ); PFC_ASSERT_NO_EXCEPTION(delete this);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 template<typename TClass>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 class ImplementModalTracking : public TClass {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 template<typename ... arg_t> ImplementModalTracking(arg_t && ... arg) : TClass(std::forward<arg_t>(arg) ...) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 BEGIN_MSG_MAP_EX(ImplementModalTracking)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 MSG_WM_INITDIALOG(OnInitDialog)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 MSG_WM_DESTROY(OnDestroy)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 CHAIN_MSG_MAP(TClass)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 END_MSG_MAP()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 void OnDestroy() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
139 m_modal.deinitialize();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
140 SetMsgHandled(FALSE);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
141 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 BOOL OnInitDialog(CWindow, LPARAM) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 m_modal.initialize(this->m_hWnd);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 SetMsgHandled(FALSE);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 return FALSE;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 modal_dialog_scope m_modal;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 template<typename TClass>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 class ImplementModelessTracking : public TClass {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 template<typename ... arg_t> ImplementModelessTracking(arg_t && ... arg ) : TClass(std::forward<arg_t>(arg) ... ) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156 BEGIN_MSG_MAP_EX(ImplementModelessTracking)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 MSG_WM_INITDIALOG(OnInitDialog)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 MSG_WM_DESTROY(OnDestroy)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 CHAIN_MSG_MAP(TClass)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 END_MSG_MAP_HOOK()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 BOOL OnInitDialog(CWindow, LPARAM) {m_modeless.Set( this->m_hWnd ); SetMsgHandled(FALSE); return FALSE; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 void OnDestroy() {m_modeless.Set(NULL); SetMsgHandled(FALSE); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164 CModelessDialogEntry m_modeless;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 namespace fb2k {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168 template<typename dialog_t, typename ... arg_t> dialog_t * newDialogEx( HWND parent, arg_t && ... arg ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 return new CWindowAutoLifetime<ImplementModelessTracking< dialog_t > > ( parent, std::forward<arg_t>(arg) ... );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 template<typename dialog_t, typename ... arg_t> dialog_t * newDialog(arg_t && ... arg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 return new CWindowAutoLifetime<ImplementModelessTracking< dialog_t > > (core_api::get_main_window(), std::forward<arg_t>(arg) ...);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 class CMenuSelectionReceiver_UiElement : public CMenuSelectionReceiver {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178 CMenuSelectionReceiver_UiElement(service_ptr_t<ui_element_instance> p_owner,unsigned p_id_base) : CMenuSelectionReceiver(p_owner->get_wnd()), m_owner(p_owner), m_id_base(p_id_base) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180 bool QueryHint(unsigned p_id,pfc::string_base & p_out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 return m_owner->edit_mode_context_menu_get_description(p_id,m_id_base,p_out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 const unsigned m_id_base;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 const service_ptr_t<ui_element_instance> m_owner;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188 static bool window_service_trait_defer_destruction(const service_base *) {return true;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 //! Special service_impl_t replacement for service classes that also implement ATL/WTL windows.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 template<typename _t_base>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 class window_service_impl_t : public implement_service_query< CWindowFixSEH<_t_base> > {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 typedef window_service_impl_t<_t_base> t_self;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196 typedef implement_service_query< CWindowFixSEH<_t_base> > t_base;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198 BEGIN_MSG_MAP_EX(window_service_impl_t)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199 MSG_WM_DESTROY(OnDestroyPassThru)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 CHAIN_MSG_MAP(__super)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201 END_MSG_MAP_HOOK()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203 int FB2KAPI service_release() throw() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 int ret = --m_counter;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205 if (ret == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206 if (window_service_trait_defer_destruction(this) && !InterlockedExchange(&m_delayedDestroyInProgress,1)) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207 PFC_ASSERT_NO_EXCEPTION( service_impl_helper::release_object_delayed(this); );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208 } else if (this->m_hWnd != NULL) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 if (!InterlockedExchange(&m_destroyWindowInProgress, 1)) {// don't double-destroy in weird scenarios
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 service_ptr_t<service_base> bump(this); // prevent delete this from occurring in mid-DestroyWindow
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211 PFC_ASSERT_NO_EXCEPTION(::DestroyWindow(this->m_hWnd));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212 // We don't know what else happened inside DestroyWindow() due to message queue flush
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213 // Safely retry destruction by bump object destructor
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 // m_hWnd doesn't have to be null here - we'll possibly get cleaned up by OnFinalMessage() instead
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 } else { // m_hWnd is NULL
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 PFC_ASSERT_NO_EXCEPTION( delete this );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 int FB2KAPI service_add_ref() throw() {return ++m_counter;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224 template<typename ... arg_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 window_service_impl_t( arg_t && ... arg ) : t_base( std::forward<arg_t>(arg) ... ) {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227 ~window_service_impl_t() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 PFC_ASSERT(this->m_hWnd == NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 void OnDestroyPassThru() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232 SetMsgHandled(FALSE); m_destroyWindowInProgress = 1;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 void OnFinalMessage(HWND p_wnd) override {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235 t_base::OnFinalMessage(p_wnd);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 service_ptr_t<service_base> bump(this);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 volatile LONG m_destroyWindowInProgress = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 volatile LONG m_delayedDestroyInProgress = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240 pfc::refcounter m_counter;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243 namespace fb2k {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 template<typename obj_t, typename ... arg_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245 service_ptr_t<obj_t> service_new_window(arg_t && ... arg) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 return new window_service_impl_t< obj_t > ( std::forward<arg_t> (arg) ... );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 static void AppendMenuPopup(HMENU menu, UINT flags, CMenu & popup, const TCHAR * label) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 PFC_ASSERT( flags & MF_POPUP );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252 WIN32_OP_D( CMenuHandle(menu).AppendMenu(flags, popup, label) );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253 popup.Detach();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 class CMessageMapDummy : public CMessageMap {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 LRESULT& lResult, DWORD dwMsgMapID) {return FALSE;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 template<typename TDialog> class preferences_page_instance_impl : public TDialog {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 preferences_page_instance_impl(HWND parent, preferences_page_callback::ptr callback) : TDialog(callback) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271 WIN32_OP(this->Create(parent) != NULL);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 // complain early if what we created isn't a child window
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274 PFC_ASSERT( (this->GetStyle() & (WS_POPUP|WS_CHILD)) == WS_CHILD );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276 HWND get_wnd() {return this->m_hWnd;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278 static bool window_service_trait_defer_destruction(const preferences_page_instance *) {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279 template<typename TDialog> class preferences_page_impl : public preferences_page_v3 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 preferences_page_instance::ptr instantiate(HWND parent, preferences_page_callback::ptr callback) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282 return fb2k::service_new_window<preferences_page_instance_impl<TDialog> >(parent, callback);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286 class CEmbeddedDialog : public CDialogImpl<CEmbeddedDialog> {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 CEmbeddedDialog(CMessageMap * owner, DWORD msgMapID, UINT dialogID) : m_owner(*owner), IDD(dialogID), m_msgMapID(msgMapID) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 BEGIN_MSG_MAP(CEmbeddedDialog)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291 CHAIN_MSG_MAP_ALT_MEMBER(m_owner, m_msgMapID)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292 END_MSG_MAP()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 const DWORD m_msgMapID;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295 const UINT IDD;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296 CMessageMap & m_owner;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
299
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
300 // ui_element stuff here because of window_service_impl_t
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
301
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
302 template<typename instance_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
303 class ui_element_instance_impl_helper : public instance_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
304 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
305 template<typename ... args_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
306 ui_element_instance_impl_helper(args_t && ... args) : instance_t(std::forward<args_t>(args) ...) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
307
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
308 GUID get_guid() override { return instance_t::g_get_guid(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
309 GUID get_subclass() override { return instance_t::g_get_subclass(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
310 HWND get_wnd() override { return *this; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
311 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
312
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
313
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
314 namespace fb2k {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
315 template<typename TImpl, typename ... args_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
316 ui_element_instance::ptr newUIElement(HWND parent, args_t && ... args) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
317 auto item = fb2k::service_new_window < ui_element_instance_impl_helper < TImpl > >(std::forward<args_t>(args) ...);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
318 item->initialize_window(parent);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
319 return item;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
320 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
321 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
322
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
323 template<typename TImpl, typename TInterface = ui_element> class ui_element_impl : public TInterface {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
324 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
325 GUID get_guid() { return TImpl::g_get_guid(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
326 GUID get_subclass() { return TImpl::g_get_subclass(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
327 void get_name(pfc::string_base & out) { TImpl::g_get_name(out); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
328
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
329 template<typename ... args_t>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
330 ui_element_instance::ptr instantiate_helper(HWND parent, args_t && ... args) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
331 return fb2k::newUIElement<TImpl>(parent, std::forward<args_t>(args) ...);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
332 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
333
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
334 ui_element_instance::ptr instantiate(HWND parent, ui_element_config::ptr cfg, ui_element_instance_callback::ptr callback) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
335 PFC_ASSERT(cfg->get_guid() == get_guid());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
336 return instantiate_helper(parent, cfg, callback);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
337 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
338 ui_element_config::ptr get_default_configuration() { return TImpl::g_get_default_configuration(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
339 ui_element_children_enumerator_ptr enumerate_children(ui_element_config::ptr cfg) { return NULL; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
340 bool get_description(pfc::string_base & out) { out = TImpl::g_get_description(); return true; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
341 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
342
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
343
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
344 #endif // _WIN32