foobar2000 SDK  2015-01-14
win32_misc.h
Go to the documentation of this file.
1 PFC_NORETURN PFC_NOINLINE void WIN32_OP_FAIL();
2 PFC_NORETURN PFC_NOINLINE void WIN32_OP_FAIL_CRITICAL(const char * what);
3 
4 #ifdef _DEBUG
5 void WIN32_OP_D_FAIL(const wchar_t * _Message, const wchar_t *_File, unsigned _Line);
6 #endif
7 
8 //Throws an exception when (OP) evaluates to false/zero.
9 #define WIN32_OP(OP) \
10  { \
11  SetLastError(NO_ERROR); \
12  if (!(OP)) WIN32_OP_FAIL(); \
13  }
14 
15 // Kills the application with appropriate debug info when (OP) evaluates to false/zero.
16 #define WIN32_OP_CRITICAL(WHAT, OP) \
17  { \
18  SetLastError(NO_ERROR); \
19  if (!(OP)) WIN32_OP_FAIL_CRITICAL(WHAT); \
20  }
21 
22 //WIN32_OP_D() acts like an assert specialized for win32 operations in debug build, ignores the return value / error codes in release build.
23 //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.
24 #ifdef _DEBUG
25 #define WIN32_OP_D(OP) \
26  { \
27  SetLastError(NO_ERROR); \
28  if (!(OP)) WIN32_OP_D_FAIL(PFC_WIDESTRING(#OP), PFC_WIDESTRING(__FILE__), __LINE__); \
29  }
30 
31 #else
32 #define WIN32_OP_D(OP) (void)( (OP), 0);
33 #endif
34 
35 
37 public:
39 
40  bool is_registered() const {return m_class != 0;}
41  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);
42  void toggle_off();
43  ATOM get_class() const {return m_class;}
44 
46 private:
47  registerclass_scope_delayed(const registerclass_scope_delayed &) {throw pfc::exception_not_implemented();}
48  const registerclass_scope_delayed & operator=(const registerclass_scope_delayed &) {throw pfc::exception_not_implemented();}
49 
50  ATOM m_class;
51 };
52 
53 
54 
55 typedef CGlobalLockScope CGlobalLock;//for compatibility, implementation moved elsewhere
56 
57 bool SetClipboardDataBlock(UINT p_format,const void * p_block,t_size p_block_size);
58 
59 template<typename t_array>
60 static bool SetClipboardDataBlock(UINT p_format,const t_array & p_array) {
61  PFC_STATIC_ASSERT( sizeof(p_array[0]) == 1 );
62  return SetClipboardDataBlock(p_format,p_array.get_ptr(),p_array.get_size());
63 }
64 
65 template<typename t_array>
66 static bool GetClipboardDataBlock(UINT p_format,t_array & p_array) {
67  PFC_STATIC_ASSERT( sizeof(p_array[0]) == 1 );
68  if (OpenClipboard(NULL)) {
69  HANDLE handle = GetClipboardData(p_format);
70  if (handle == NULL) {
71  CloseClipboard();
72  return false;
73  }
74  {
75  CGlobalLock lock(handle);
76  const t_size size = lock.GetSize();
77  try {
78  p_array.set_size(size);
79  } catch(...) {
80  CloseClipboard();
81  throw;
82  }
83  memcpy(p_array.get_ptr(),lock.GetPtr(),size);
84  }
85  CloseClipboard();
86  return true;
87  } else {
88  return false;
89  }
90 }
91 
92 
94 public:
96  if (FAILED(OleInitialize(NULL))) throw pfc::exception("OleInitialize() failure");
97  }
99  OleUninitialize();
100  }
101 
102 private:
104 };
105 
107 public:
109  if (FAILED(CoInitialize(NULL))) throw pfc::exception("CoInitialize() failed");
110  }
111  CoInitializeScope(DWORD params) {
112  if (FAILED(CoInitializeEx(NULL, params))) throw pfc::exception("CoInitialize() failed");
113  }
115  CoUninitialize();
116  }
117  PFC_CLASS_NOT_COPYABLE_EX(CoInitializeScope)
118 };
119 
120 
121 unsigned QueryScreenDPI();
122 
123 SIZE QueryScreenDPIEx();
124 
125 static WORD GetOSVersion() {
126  const DWORD ver = GetVersion();
127  return (WORD)HIBYTE(LOWORD(ver)) | ((WORD)LOBYTE(LOWORD(ver)) << 8);
128 }
129 
130 #if _WIN32_WINNT >= 0x501
131 #define WS_EX_COMPOSITED_Safe() WS_EX_COMPOSITED
132 #else
133 static DWORD WS_EX_COMPOSITED_Safe() {
134  return (GetOSVersion() < 0x501) ? 0 : 0x02000000L;
135 }
136 #endif
137 
138 
139 
140 
141 
143 public:
144  EnableWindowScope(HWND p_window,BOOL p_state) throw() : m_window(p_window) {
145  m_oldState = IsWindowEnabled(m_window);
146  EnableWindow(m_window,p_state);
147  }
148  ~EnableWindowScope() throw() {
149  EnableWindow(m_window,m_oldState);
150  }
151 
152 private:
154  HWND m_window;
155 };
156 
157 bool IsMenuNonEmpty(HMENU menu);
158 
160 public:
161  SetTextColorScope(HDC dc, COLORREF col) throw() : m_dc(dc) {
162  m_oldCol = SetTextColor(dc,col);
163  }
164  ~SetTextColorScope() throw() {
165  SetTextColor(m_dc,m_oldCol);
166  }
167  PFC_CLASS_NOT_COPYABLE_EX(SetTextColorScope)
168 private:
169  HDC m_dc;
170  COLORREF m_oldCol;
171 };
172 
174 public:
175  CloseHandleScope(HANDLE handle) throw() : m_handle(handle) {}
176  ~CloseHandleScope() throw() {CloseHandle(m_handle);}
177  HANDLE Detach() throw() {return pfc::replace_t(m_handle,INVALID_HANDLE_VALUE);}
178  HANDLE Get() const throw() {return m_handle;}
179  void Close() throw() {CloseHandle(Detach());}
180  PFC_CLASS_NOT_COPYABLE_EX(CloseHandleScope)
181 private:
182  HANDLE m_handle;
183 };
184 
186 public:
187  inline CModelessDialogEntry() : m_wnd() {}
188  inline CModelessDialogEntry(HWND p_wnd) : m_wnd() {Set(p_wnd);}
189  inline ~CModelessDialogEntry() {Set(NULL);}
190 
191  void Set(HWND p_new) {
193  if (m_wnd) api->remove(m_wnd);
194  m_wnd = p_new;
195  if (m_wnd) api->add(m_wnd);
196  }
197 private:
198  PFC_CLASS_NOT_COPYABLE_EX(CModelessDialogEntry);
199  HWND m_wnd;
200 };
201 
204 
205 
206 
207 void SetDefaultMenuItem(HMENU p_menu,unsigned p_id);
208 
209 
210 
211 
212 class TypeFind {
213 public:
214  static LRESULT Handler(NMHDR* hdr, int subItemFrom = 0, int subItemCnt = 1) {
215  NMLVFINDITEM * info = reinterpret_cast<NMLVFINDITEM*>(hdr);
216  const HWND wnd = hdr->hwndFrom;
217  if (info->lvfi.flags & LVFI_NEARESTXY) return -1;
218  const size_t count = _ItemCount(wnd);
219  if (count == 0) return -1;
220  const size_t base = (size_t) info->iStart % count;
221  for(size_t walk = 0; walk < count; ++walk) {
222  const size_t index = (walk + base) % count;
223  for(int subItem = subItemFrom; subItem < subItemFrom + subItemCnt; ++subItem) {
224  if (StringPrefixMatch(info->lvfi.psz, _ItemText(wnd, index, subItem))) return (LRESULT) index;
225  }
226  }
227  for(size_t walk = 0; walk < count; ++walk) {
228  const size_t index = (walk + base) % count;
229  for(int subItem = subItemFrom; subItem < subItemFrom + subItemCnt; ++subItem) {
230  if (StringPartialMatch(info->lvfi.psz, _ItemText(wnd, index, subItem))) return (LRESULT) index;
231  }
232  }
233  return -1;
234  }
235 
236  static wchar_t myCharLower(wchar_t c) {
237  return (wchar_t) CharLower((wchar_t*)c);
238  }
239  static bool StringPrefixMatch(const wchar_t * part, const wchar_t * str) {
240  unsigned walk = 0;
241  for(;;) {
242  wchar_t c1 = part[walk], c2 = str[walk];
243  if (c1 == 0) return true;
244  if (c2 == 0) return false;
245  if (myCharLower(c1) != myCharLower(c2)) return false;
246  ++walk;
247  }
248  }
249 
250  static bool StringPartialMatch(const wchar_t * part, const wchar_t * str) {
251  unsigned base = 0;
252  for(;;) {
253  unsigned walk = 0;
254  for(;;) {
255  wchar_t c1 = part[walk], c2 = str[base + walk];
256  if (c1 == 0) return true;
257  if (c2 == 0) return false;
258  if (myCharLower(c1) != myCharLower(c2)) break;
259  ++walk;
260  }
261  ++ base;
262  }
263  }
264 
265  static size_t _ItemCount(HWND wnd) {
266  return ListView_GetItemCount(wnd);
267  }
268  static const wchar_t * _ItemText(HWND wnd, size_t index, int subItem = 0) {
269  NMLVDISPINFO info = {};
270  info.hdr.code = LVN_GETDISPINFO;
271  info.hdr.idFrom = GetDlgCtrlID(wnd);
272  info.hdr.hwndFrom = wnd;
273  info.item.iItem = index;
274  info.item.iSubItem = subItem;
275  info.item.mask = LVIF_TEXT;
276  ::SendMessage(::GetParent(wnd), WM_NOTIFY, info.hdr.idFrom, reinterpret_cast<LPARAM>(&info));
277  if (info.item.pszText == NULL) return L"";
278  return info.item.pszText;
279  }
280 
281 };
282 
283 
284 class mutexScope {
285 public:
286  mutexScope(HANDLE hMutex_, abort_callback & abort);
287  ~mutexScope();
288 private:
289  PFC_CLASS_NOT_COPYABLE_EX(mutexScope);
291 };
292 
293 class CDLL {
294 public:
295 #ifdef _DEBUG
296  static LPTOP_LEVEL_EXCEPTION_FILTER _GetEH() {
297  LPTOP_LEVEL_EXCEPTION_FILTER rv = SetUnhandledExceptionFilter(NULL);
298  SetUnhandledExceptionFilter(rv);
299  return rv;
300  }
301 #endif
302  CDLL(const wchar_t * Name) : hMod() {
303  Load(Name);
304  }
305  CDLL() : hMod() {}
306  void Load(const wchar_t * Name) {
307  PFC_ASSERT( hMod == NULL );
308 #ifdef _DEBUG
309  auto handlerBefore = _GetEH();
310 #endif
311  WIN32_OP( hMod = LoadLibrary(Name) );
312 #ifdef _DEBUG
313  PFC_ASSERT( handlerBefore == _GetEH() );
314 #endif
315  }
316 
317 
318  ~CDLL() {
319  if (hMod) FreeLibrary(hMod);
320  }
321  template<typename funcptr_t> void Bind(funcptr_t & outFunc, const char * name) {
322  WIN32_OP( outFunc = (funcptr_t)GetProcAddress(hMod, name) );
323  }
324 
325  HMODULE hMod;
326 
327  PFC_CLASS_NOT_COPYABLE_EX(CDLL);
328 };
329 
331 public:
332  void open( const char * inPath, file::ptr inReader, abort_callback & aborter);
333  void close();
334 
335  winLocalFileScope() : m_isTemp() {}
336  winLocalFileScope( const char * inPath, file::ptr inReader, abort_callback & aborter ) : m_isTemp() {
337  open( inPath, inReader, aborter );
338  }
339 
341  close();
342  }
343 
344  const wchar_t * Path() const {return m_path.c_str();}
345 private:
346  bool m_isTemp;
347  std::wstring m_path;
348 };
349 
350 
351 
352 class CMutex {
353 public:
354  CMutex(const TCHAR * name = NULL);
355  ~CMutex();
356  HANDLE Handle() {return m_hMutex;}
357  static void AcquireByHandle( HANDLE hMutex, abort_callback & aborter );
358  void Acquire( abort_callback& aborter );
359  void Release();
360 private:
361  CMutex(const CMutex&); void operator=(const CMutex&);
363 };
364 
365 class CMutexScope {
366 public:
367  CMutexScope(CMutex & mutex, DWORD timeOutMS, const char * timeOutBugMsg);
368  CMutexScope(CMutex & mutex);
369  CMutexScope(CMutex & mutex, abort_callback & aborter);
370  ~CMutexScope();
371 private:
372  CMutexScope(const CMutexScope &); void operator=(const CMutexScope&);
374 };
void SetDefaultMenuItem(HMENU p_menu, unsigned p_id)
Definition: win32_misc.cpp:134
CloseHandleScope(HANDLE handle)
Definition: win32_misc.h:175
void GetOSVersionStringAppend(pfc::string_base &out)
Definition: win32_misc.cpp:111
CModelessDialogEntry(HWND p_wnd)
Definition: win32_misc.h:188
const registerclass_scope_delayed & operator=(const registerclass_scope_delayed &)
Definition: win32_misc.h:48
static DWORD WS_EX_COMPOSITED_Safe()
Definition: win32_misc.h:133
registerclass_scope_delayed(const registerclass_scope_delayed &)
Definition: win32_misc.h:47
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)
Definition: win32_misc.cpp:3
CoInitializeScope(DWORD params)
Definition: win32_misc.h:111
CGlobalLockScope CGlobalLock
Definition: win32_misc.h:55
EnableWindowScope(HWND p_window, BOOL p_state)
Definition: win32_misc.h:144
std::wstring m_path
Definition: win32_misc.h:347
PFC_CLASS_NOT_COPYABLE(OleInitializeScope, OleInitializeScope)
static WORD GetOSVersion()
Definition: win32_misc.h:125
void info(const char *p_message)
Definition: console.cpp:4
HANDLE hMutex
Definition: win32_misc.h:290
static bool StringPartialMatch(const wchar_t *part, const wchar_t *str)
Definition: win32_misc.h:250
typedef BOOL(WINAPI *pPowerSetRequest_t)(__in HANDLE PowerRequest
static LPTOP_LEVEL_EXCEPTION_FILTER _GetEH()
Definition: win32_misc.h:296
static LRESULT Handler(NMHDR *hdr, int subItemFrom=0, int subItemCnt=1)
Definition: win32_misc.h:214
unsigned QueryScreenDPI()
Definition: win32_misc.cpp:27
static wchar_t myCharLower(wchar_t c)
Definition: win32_misc.h:236
void * GetPtr() const
Definition: win-objects.h:75
static bool StringPrefixMatch(const wchar_t *part, const wchar_t *str)
Definition: win32_misc.h:239
HMODULE hMod
Definition: win32_misc.h:325
PFC_NORETURN PFC_NOINLINE void WIN32_OP_FAIL()
Definition: win32_misc.cpp:52
t_type replace_t(t_type &p_var, const t_newval &p_newval)
Definition: primitives.h:682
typedef HANDLE(WINAPI *pPowerCreateRequest_t)(__in void *Context)
SIZE QueryScreenDPIEx()
Definition: win32_misc.cpp:35
void GetOSVersionString(pfc::string_base &out)
Definition: win32_misc.cpp:81
HANDLE Detach()
Definition: win32_misc.h:177
size_t t_size
Definition: int_types.h:48
bool IsMenuNonEmpty(HMENU menu)
Definition: win32_misc.cpp:43
CDLL()
Definition: win32_misc.h:305
PFC_CLASS_NOT_COPYABLE_EX(SetTextColorScope) private COLORREF m_oldCol
Definition: win32_misc.h:167
HANDLE Handle()
Definition: win32_misc.h:356
winLocalFileScope(const char *inPath, file::ptr inReader, abort_callback &aborter)
Definition: win32_misc.h:336
void Set(HWND p_new)
Definition: win32_misc.h:191
void WIN32_OP_D_FAIL(const wchar_t *_Message, const wchar_t *_File, unsigned _Line)
Definition: win32_misc.cpp:66
CMutex & m_mutex
Definition: win32_misc.h:373
void Bind(funcptr_t &outFunc, const char *name)
Definition: win32_misc.h:321
static bool GetClipboardDataBlock(UINT p_format, t_array &p_array)
Definition: win32_misc.h:66
const wchar_t * Path() const
Definition: win32_misc.h:344
void Load(const wchar_t *Name)
Definition: win32_misc.h:306
static size_t _ItemCount(HWND wnd)
Definition: win32_misc.h:265
static const wchar_t * _ItemText(HWND wnd, size_t index, int subItem=0)
Definition: win32_misc.h:268
std::exception exception
Definition: primitives.h:193
CDLL(const wchar_t *Name)
Definition: win32_misc.h:302
HANDLE Get() const
Definition: win32_misc.h:178
HANDLE m_hMutex
Definition: win32_misc.h:362
SetTextColorScope(HDC dc, COLORREF col)
Definition: win32_misc.h:161
t_size GetSize() const
Definition: win-objects.h:76
bool SetClipboardDataBlock(UINT p_format, const void *p_block, t_size p_block_size)
Definition: win32_misc.cpp:143
PFC_NORETURN PFC_NOINLINE void WIN32_OP_FAIL_CRITICAL(const char *what)
Definition: win32_misc.cpp:58
Helper template used to easily access core services. Usage: static_api_ptr_t api; api->doso...
Definition: service.h:533
~CDLL()
Definition: win32_misc.h:318
bool is_registered() const
Definition: win32_misc.h:40