+
+ DECLARE_NO_COPY_CLASS(ScreenHDC)
+};
+
+// the same as ScreenHDC but for window DCs
+class WindowHDC
+{
+public:
+ WindowHDC(HWND hwnd) { m_hdc = ::GetDC(m_hwnd = hwnd); }
+ ~WindowHDC() { ::ReleaseDC(m_hwnd, m_hdc); }
+
+ operator HDC() const { return m_hdc; }
+
+private:
+ HWND m_hwnd;
+ HDC m_hdc;
+
+ DECLARE_NO_COPY_CLASS(WindowHDC)
+};
+
+// the same as ScreenHDC but for memory DCs: creates the HDC compatible with
+// the given one (screen by default) in ctor and destroys it in dtor
+class MemoryHDC
+{
+public:
+ MemoryHDC(HDC hdc = 0) { m_hdc = ::CreateCompatibleDC(hdc); }
+ ~MemoryHDC() { ::DeleteDC(m_hdc); }
+
+ operator HDC() const { return m_hdc; }
+
+private:
+ HDC m_hdc;
+
+ DECLARE_NO_COPY_CLASS(MemoryHDC)
+};
+
+// a class which selects a GDI object into a DC in its ctor and deselects in
+// dtor
+class SelectInHDC
+{
+public:
+ SelectInHDC(HDC hdc, HGDIOBJ hgdiobj) : m_hdc(hdc)
+ { m_hgdiobj = ::SelectObject(hdc, hgdiobj); }
+
+ ~SelectInHDC() { ::SelectObject(m_hdc, m_hgdiobj); }
+
+ // return true if the object was successfully selected
+ operator bool() const { return m_hgdiobj != 0; }
+
+private:
+ HDC m_hdc;
+ HGDIOBJ m_hgdiobj;
+
+ DECLARE_NO_COPY_CLASS(SelectInHDC)
+};
+
+// a class for temporary bitmaps
+class CompatibleBitmap
+{
+public:
+ CompatibleBitmap(HDC hdc, int w, int h)
+ {
+ m_hbmp = ::CreateCompatibleBitmap(hdc, w, h);
+ }
+
+ ~CompatibleBitmap()
+ {
+ if ( m_hbmp )
+ ::DeleteObject(m_hbmp);
+ }
+
+ operator HBITMAP() const { return m_hbmp; }
+
+private:
+ HBITMAP m_hbmp;
+};
+
+// when working with global pointers (which is unfortunately still necessary
+// sometimes, e.g. for clipboard) it is important to unlock them exactly as
+// many times as we lock them which just asks for using a "smart lock" class
+class GlobalPtr
+{
+public:
+ GlobalPtr(HGLOBAL hGlobal) : m_hGlobal(hGlobal)
+ {
+ m_ptr = GlobalLock(hGlobal);
+ if ( !m_ptr )
+ {
+ wxLogLastError(_T("GlobalLock"));
+ }
+ }
+
+ ~GlobalPtr()
+ {
+ if ( !GlobalUnlock(m_hGlobal) )
+ {
+#ifdef __WXDEBUG__
+ // this might happen simply because the block became unlocked
+ DWORD dwLastError = ::GetLastError();
+ if ( dwLastError != NO_ERROR )
+ {
+ wxLogApiError(_T("GlobalUnlock"), dwLastError);
+ }
+#endif // __WXDEBUG__
+ }
+ }
+
+ operator void *() const { return m_ptr; }
+
+private:
+ HGLOBAL m_hGlobal;
+ void *m_ptr;
+
+ DECLARE_NO_COPY_CLASS(GlobalPtr)