win32_misc.h

Go to the documentation of this file.
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 //Throws an exception when (OP) evaluates to false/zero.
00007 #define WIN32_OP(OP)    \
00008         {       \
00009                 SetLastError(NO_ERROR); \
00010                 if (!(OP)) WIN32_OP_FAIL();     \
00011         }
00012 
00013 //WIN32_OP_D() acts like an assert specialized for win32 operations in debug build, ignores the return value / error codes in release build.
00014 //Use WIN32_OP_D() instead of WIN32_OP() on operations that are extremely unlikely to fail, so failure condition checks are performed in the debug build only, to avoid bloating release code with pointless error checks.
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;//for compatibility, implementation moved elsewhere
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);//todo?
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 };

Generated on Fri Apr 25 18:49:33 2008 for foobar2000 SDK by  doxygen 1.5.5