00001 void WIN32_OP_FAIL();
00002 #ifdef _DEBUG
00003 void WIN32_OP_D_FAIL(const wchar_t * _Message, const wchar_t *_File, unsigned _Line);
00004 #endif
00005
00006
00007 #define WIN32_OP(OP) \
00008 { \
00009 SetLastError(NO_ERROR); \
00010 if (!(OP)) WIN32_OP_FAIL(); \
00011 }
00012
00013
00014
00015 #ifdef _DEBUG
00016 #define WIN32_OP_D(OP) \
00017 { \
00018 SetLastError(NO_ERROR); \
00019 if (!(OP)) WIN32_OP_D_FAIL(PFC_WIDESTRING(#OP), PFC_WIDESTRING(__FILE__), __LINE__); \
00020 }
00021
00022 #else
00023 #define WIN32_OP_D(OP) (void)( (OP), 0);
00024 #endif
00025
00026
00027 class registerclass_scope_delayed {
00028 public:
00029 registerclass_scope_delayed() : m_class(0) {}
00030
00031 bool is_registered() const {return m_class != 0;}
00032 void toggle_on(UINT p_style,WNDPROC p_wndproc,int p_clsextra,int p_wndextra,HICON p_icon,HCURSOR p_cursor,HBRUSH p_background,const TCHAR * p_classname,const TCHAR * p_menuname);
00033 void toggle_off();
00034 ATOM get_class() const {return m_class;}
00035
00036 ~registerclass_scope_delayed() {toggle_off();}
00037 private:
00038 registerclass_scope_delayed(const registerclass_scope_delayed &) {throw pfc::exception_not_implemented();}
00039 const registerclass_scope_delayed & operator=(const registerclass_scope_delayed &) {throw pfc::exception_not_implemented();}
00040
00041 ATOM m_class;
00042 };
00043
00044
00045
00046 template<typename t_object>
00047 class syncd_storage {
00048 private:
00049 typedef syncd_storage<t_object> t_self;
00050 public:
00051 syncd_storage() {}
00052 template<typename t_source>
00053 syncd_storage(const t_source & p_source) : m_object(p_source) {}
00054 template<typename t_source>
00055 void set(t_source const & p_in) {
00056 insync(m_sync);
00057 m_object = p_in;
00058 }
00059 template<typename t_destination>
00060 void get(t_destination & p_out) const {
00061 insync(m_sync);
00062 p_out = m_object;
00063 }
00064 t_object get() const {
00065 insync(m_sync);
00066 return m_object;
00067 }
00068 template<typename t_source>
00069 const t_self & operator=(t_source const & p_source) {set(p_source); return *this;}
00070 private:
00071 mutable critical_section m_sync;
00072 t_object m_object;
00073 };
00074
00075 template<typename t_object>
00076 class syncd_storage_flagged {
00077 private:
00078 typedef syncd_storage_flagged<t_object> t_self;
00079 public:
00080 syncd_storage_flagged() : m_changed_flag(false) {}
00081 template<typename t_source>
00082 syncd_storage_flagged(const t_source & p_source) : m_changed_flag(false), m_object(p_source) {}
00083 void set_changed(bool p_flag = true) {
00084 insync(m_sync);
00085 m_changed_flag = p_flag;
00086 }
00087 template<typename t_source>
00088 void set(t_source const & p_in) {
00089 insync(m_sync);
00090 m_object = p_in;
00091 m_changed_flag = true;
00092 }
00093 bool has_changed() const {
00094 insync(m_sync);
00095 return m_changed_flag;
00096 }
00097 t_object peek() const {insync(m_sync); return m_object;}
00098 template<typename t_destination>
00099 bool get_if_changed(t_destination & p_out) {
00100 insync(m_sync);
00101 if (m_changed_flag) {
00102 p_out = m_object;
00103 m_changed_flag = false;
00104 return true;
00105 } else {
00106 return false;
00107 }
00108 }
00109 t_object get() {
00110 insync(m_sync);
00111 m_changed_flag = false;
00112 return m_object;
00113 }
00114 template<typename t_destination>
00115 void get(t_destination & p_out) {
00116 insync(m_sync);
00117 p_out = m_object;
00118 m_changed_flag = false;
00119 }
00120 template<typename t_source>
00121 const t_self & operator=(t_source const & p_source) {set(p_source); return *this;}
00122 private:
00123 bool m_changed_flag;
00124 mutable critical_section m_sync;
00125 t_object m_object;
00126 };
00127
00128 typedef CGlobalLockScope CGlobalLock;
00129
00130 static bool SetClipboardDataBlock(UINT p_format,const void * p_block,t_size p_block_size) {
00131 bool success = false;
00132 if (OpenClipboard(NULL)) {
00133 EmptyClipboard();
00134 HANDLE handle = GlobalAlloc(GMEM_MOVEABLE,p_block_size);
00135 if (handle == NULL) {
00136 CloseClipboard();
00137 throw std::bad_alloc();
00138 }
00139 {CGlobalLock lock(handle);memcpy(lock.GetPtr(),p_block,p_block_size);}
00140 if (SetClipboardData(p_format,handle) == NULL) {
00141 GlobalFree(handle);
00142 } else {
00143 success = true;
00144 }
00145 CloseClipboard();
00146 }
00147 return success;
00148 }
00149
00150 template<typename t_array>
00151 static bool SetClipboardDataBlock(UINT p_format,const t_array & p_array) {
00152 pfc::static_assert<sizeof(p_array[0]) == 1>();
00153 return SetClipboardDataBlock(p_format,p_array.get_ptr(),p_array.get_size());
00154 }
00155
00156 template<typename t_array>
00157 static bool GetClipboardDataBlock(UINT p_format,t_array & p_array) {
00158 pfc::static_assert<sizeof(p_array[0]) == 1>();
00159 if (OpenClipboard(NULL)) {
00160 HANDLE handle = GetClipboardData(p_format);
00161 if (handle == NULL) {
00162 CloseClipboard();
00163 return false;
00164 }
00165 {
00166 CGlobalLock lock(handle);
00167 const t_size size = lock.GetSize();
00168 try {
00169 p_array.set_size(size);
00170 } catch(...) {
00171 CloseClipboard();
00172 throw;
00173 }
00174 memcpy(p_array.get_ptr(),lock.GetPtr(),size);
00175 }
00176 CloseClipboard();
00177 return true;
00178 } else {
00179 return false;
00180 }
00181 }
00182
00183
00184 class OleInitializeScope {
00185 public:
00186 OleInitializeScope() {
00187 if (FAILED(OleInitialize(NULL))) throw pfc::exception("OleInitialize() failure");
00188 }
00189 ~OleInitializeScope() {
00190 OleUninitialize();
00191 }
00192
00193 private:
00194 PFC_CLASS_NOT_COPYABLE(OleInitializeScope,OleInitializeScope);
00195 };
00196
00197 class CoInitializeScope {
00198 public:
00199 CoInitializeScope() {
00200 if (FAILED(CoInitialize(NULL))) throw pfc::exception("CoInitialize() failed");
00201 }
00202 ~CoInitializeScope() {
00203 CoUninitialize();
00204 }
00205 PFC_CLASS_NOT_COPYABLE_EX(CoInitializeScope)
00206 };
00207
00208
00209 unsigned QueryScreenDPI();
00210
00211 SIZE QueryScreenDPIEx();
00212
00213 static WORD GetOSVersion() {
00214 const DWORD ver = GetVersion();
00215 return (WORD)HIBYTE(LOWORD(ver)) | ((WORD)LOBYTE(LOWORD(ver)) << 8);
00216 }
00217
00218 #if _WIN32_WINNT >= 0x501
00219 #define WS_EX_COMPOSITED_Safe() WS_EX_COMPOSITED
00220 #else
00221 static DWORD WS_EX_COMPOSITED_Safe() {
00222 return (GetOSVersion() < 0x501) ? 0 : 0x02000000L;
00223 }
00224 #endif
00225
00226
00227 static t_size GetOptimalWorkerThreadCount() throw() {
00228 DWORD_PTR mask,system;
00229 t_size ret = 0;
00230 GetProcessAffinityMask(GetCurrentProcess(),&mask,&system);
00231 for(t_size n=0;n<sizeof(mask)*8;n++) {
00232 if (mask & ((DWORD_PTR)1<<n)) ret++;
00233 }
00234 if (ret == 0) return 1;
00235 return ret;
00236 }
00237
00239 class CVerySimpleThread {
00240 public:
00241 CVerySimpleThread() : m_thread(INVALID_HANDLE_VALUE) {}
00242 ~CVerySimpleThread() {WaitTillThreadDone();}
00243 void StartThread() {
00244 CloseThread();
00245 HANDLE thread;
00246 WIN32_OP( (thread = CreateThread(NULL,0,g_entry,reinterpret_cast<void*>(this),0,NULL) ) != NULL);
00247 m_thread = thread;
00248 }
00249 bool IsThreadActive() const {
00250 return m_thread != INVALID_HANDLE_VALUE;
00251 }
00252 void WaitTillThreadDone() {
00253 CloseThread();
00254 }
00255 protected:
00256 virtual void ThreadProc() {}
00257 private:
00258 void CloseThread() {
00259 if (IsThreadActive()) {
00260 WaitForSingleObject(m_thread,INFINITE);
00261 CloseHandle(m_thread); m_thread = INVALID_HANDLE_VALUE;
00262 }
00263 }
00264
00265 static DWORD CALLBACK g_entry(void* p_instance) {
00266 return reinterpret_cast<CVerySimpleThread*>(p_instance)->entry();
00267 }
00268 unsigned entry() {
00269 try {
00270 ThreadProc();
00271 } catch(...) {}
00272 return 0;
00273 }
00274 HANDLE m_thread;
00275
00276 PFC_CLASS_NOT_COPYABLE_EX(CVerySimpleThread)
00277 };
00278
00280 class CSimpleThread : private completion_notify_receiver {
00281 public:
00282 CSimpleThread() : m_thread(INVALID_HANDLE_VALUE) {}
00283 ~CSimpleThread() {AbortThread();}
00284 void StartThread() {
00285 AbortThread();
00286 m_abort.reset();
00287 m_ownNotify = create_task(0);
00288 HANDLE thread;
00289 WIN32_OP( (thread = CreateThread(NULL,0,g_entry,reinterpret_cast<void*>(this),0,NULL) ) != NULL);
00290 m_thread = thread;
00291 }
00292 void AbortThread() {
00293 m_abort.abort();
00294 CloseThread();
00295 }
00296 bool IsThreadActive() const {
00297 return m_thread != INVALID_HANDLE_VALUE;
00298 }
00299 void WaitTillThreadDone() {
00300 CloseThread();
00301 }
00302 protected:
00303 virtual unsigned ThreadProc(abort_callback & p_abort) {return 0;}
00305 virtual void ThreadDone(unsigned p_code) {};
00306 private:
00307 void CloseThread() {
00308 if (IsThreadActive()) {
00309 WaitForSingleObject(m_thread,INFINITE);
00310 CloseHandle(m_thread); m_thread = INVALID_HANDLE_VALUE;
00311 }
00312 orphan_all_tasks();
00313 }
00314
00315 void on_task_completion(unsigned p_id,unsigned p_status) {
00316 if (IsThreadActive()) {
00317 CloseThread();
00318 ThreadDone(p_status);
00319 }
00320 }
00321 static DWORD CALLBACK g_entry(void* p_instance) {
00322 return reinterpret_cast<CSimpleThread*>(p_instance)->entry();
00323 }
00324 unsigned entry() {
00325 unsigned code = ~0;
00326 try {
00327 code = ThreadProc(m_abort);
00328 } catch(...) {}
00329 if (!m_abort.is_aborting()) m_ownNotify->on_completion_async(code);
00330 return code;
00331 }
00332 abort_callback_impl m_abort;
00333 HANDLE m_thread;
00334 completion_notify_ptr m_ownNotify;
00335
00336 PFC_CLASS_NOT_COPYABLE_EX(CSimpleThread);
00337 };
00338
00339
00340
00341 class EnableWindowScope {
00342 public:
00343 EnableWindowScope(HWND p_window,BOOL p_state) throw() : m_window(p_window) {
00344 m_oldState = IsWindowEnabled(m_window);
00345 EnableWindow(m_window,p_state);
00346 }
00347 ~EnableWindowScope() throw() {
00348 EnableWindow(m_window,m_oldState);
00349 }
00350
00351 private:
00352 BOOL m_oldState;
00353 HWND m_window;
00354 };
00355
00356 bool IsMenuNonEmpty(HMENU menu);
00357
00358 class SetTextColorScope {
00359 public:
00360 SetTextColorScope(HDC dc, COLORREF col) throw() : m_dc(dc) {
00361 m_oldCol = SetTextColor(dc,col);
00362 }
00363 ~SetTextColorScope() throw() {
00364 SetTextColor(m_dc,m_oldCol);
00365 }
00366 PFC_CLASS_NOT_COPYABLE_EX(SetTextColorScope)
00367 private:
00368 HDC m_dc;
00369 COLORREF m_oldCol;
00370 };
00371
00372 class CloseHandleScope {
00373 public:
00374 CloseHandleScope(HANDLE handle) throw() : m_handle(handle) {}
00375 ~CloseHandleScope() throw() {CloseHandle(m_handle);}
00376 HANDLE Detach() throw() {return pfc::replace_t(m_handle,INVALID_HANDLE_VALUE);}
00377 HANDLE Get() const throw() {return m_handle;}
00378 void Close() throw() {CloseHandle(Detach());}
00379 PFC_CLASS_NOT_COPYABLE_EX(CloseHandleScope)
00380 private:
00381 HANDLE m_handle;
00382 };
00383
00384 class CModelessDialogEntry {
00385 public:
00386 inline CModelessDialogEntry() : m_wnd() {}
00387 inline CModelessDialogEntry(HWND p_wnd) : m_wnd() {Set(p_wnd);}
00388 inline ~CModelessDialogEntry() {Set(NULL);}
00389
00390 void Set(HWND p_new) {
00391 static_api_ptr_t<modeless_dialog_manager> api;
00392 if (m_wnd) api->remove(m_wnd);
00393 m_wnd = p_new;
00394 if (m_wnd) api->add(m_wnd);
00395 }
00396 private:
00397 PFC_CLASS_NOT_COPYABLE_EX(CModelessDialogEntry);
00398 HWND m_wnd;
00399 };