diff --git a/build/WinStd-15.0.vcxproj.filters b/build/WinStd-15.0.vcxproj.filters
index 898934f5..00ac3ad3 100644
--- a/build/WinStd-15.0.vcxproj.filters
+++ b/build/WinStd-15.0.vcxproj.filters
@@ -47,6 +47,9 @@
Source Files
+
+ Source Files
+
@@ -100,5 +103,8 @@
Header Files
+
+ Header Files
+
\ No newline at end of file
diff --git a/build/WinStd-16.0.vcxproj.filters b/build/WinStd-16.0.vcxproj.filters
index 898934f5..00ac3ad3 100644
--- a/build/WinStd-16.0.vcxproj.filters
+++ b/build/WinStd-16.0.vcxproj.filters
@@ -47,6 +47,9 @@
Source Files
+
+ Source Files
+
@@ -100,5 +103,8 @@
Header Files
+
+ Header Files
+
\ No newline at end of file
diff --git a/build/WinStd.props b/build/WinStd.props
index f41e3911..d123a7a3 100644
--- a/build/WinStd.props
+++ b/build/WinStd.props
@@ -26,6 +26,7 @@
+
@@ -39,11 +40,12 @@
+
-
+
diff --git a/include/WinStd/GDI.h b/include/WinStd/GDI.h
new file mode 100644
index 00000000..4d3c8e33
--- /dev/null
+++ b/include/WinStd/GDI.h
@@ -0,0 +1,199 @@
+/*
+ Copyright © 1991-2021 Amebis
+
+ This file is part of WinStd.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+///
+/// \defgroup WinStdGdiAPI GDI API
+/// Integrates WinStd classes with Microsoft Windows GDI
+///
+
+#include "Common.h"
+
+#include
+
+namespace winstd
+{
+ template class gdi_handle;
+ class dc;
+ class window_dc;
+ class dc_selector;
+}
+
+
+#pragma once
+
+
+namespace winstd
+{
+ /// \addtogroup WinStdGdiAPI
+ /// @{
+
+ ///
+ /// Windows HGDIOBJ wrapper class
+ ///
+ template
+ class gdi_handle : public handle
+ {
+ HANDLE_IMPL(gdi_handle, NULL)
+
+ public:
+ ///
+ /// Closes an open object handle.
+ ///
+ /// \sa [DeleteObject function](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-deleteobject)
+ ///
+ virtual ~gdi_handle()
+ {
+ if (m_h != invalid)
+ DeleteObject(m_h);
+ }
+
+ protected:
+ ///
+ /// Closes an open object handle.
+ ///
+ /// \sa [DeleteObject function](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-deleteobject)
+ ///
+ void free_internal() noexcept override
+ {
+ DeleteObject(m_h);
+ }
+ };
+
+
+ ///
+ /// Device context wrapper class
+ ///
+ class dc : public handle
+ {
+ HANDLE_IMPL(dc, NULL)
+
+ public:
+ ///
+ /// Deletes the specified device context (DC).
+ ///
+ /// \sa [DeleteDC function](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-deletedc)
+ ///
+ virtual ~dc();
+
+ protected:
+ ///
+ /// Deletes the specified device context (DC).
+ ///
+ /// \sa [DeleteDC function](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-deletedc)
+ ///
+ void free_internal() noexcept override;
+ };
+
+
+ ///
+ /// Device context wrapper class
+ ///
+ class window_dc : public handle
+ {
+ public:
+ inline window_dc() noexcept :
+ m_hwnd(NULL)
+ {}
+
+ inline window_dc(_In_opt_ handle_type h, _In_opt_ HWND hwnd) noexcept :
+ handle(h),
+ m_hwnd(hwnd)
+ {}
+
+ inline window_dc(_Inout_ window_dc &&h) noexcept :
+ handle(std::move(h)),
+ m_hwnd(h.m_hwnd)
+ {}
+
+ inline window_dc& operator=(_Inout_ window_dc &&h) noexcept
+ {
+ handle::operator=(std::move(h));
+ m_hwnd = h.m_hwnd;
+ return *this;
+ }
+
+ WINSTD_NONCOPYABLE(window_dc)
+
+ public:
+ ///
+ /// Releases a device context (DC), freeing it for use by other applications.
+ ///
+ /// \sa [ReleaseDC function](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-releasedc)
+ ///
+ virtual ~window_dc();
+
+ protected:
+ ///
+ /// Releases a device context (DC), freeing it for use by other applications.
+ ///
+ /// \sa [ReleaseDC function](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-releasedc)
+ ///
+ void free_internal() noexcept override;
+
+ protected:
+ HWND m_hwnd; ///< Window handle
+ };
+
+
+ ///
+ /// Context scope DC object restorer
+ ///
+ class dc_selector
+ {
+ WINSTD_NONCOPYABLE(dc_selector)
+ WINSTD_NONMOVABLE(dc_selector)
+
+ public:
+ ///
+ /// Selects an object into the specified device context (DC). The new object replaces the previous object of the same type.
+ ///
+ /// \sa [SelectObject function](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-selectobject)
+ ///
+ inline dc_selector(_In_ HDC hdc, _In_ HGDIOBJ h) noexcept :
+ m_hdc(hdc),
+ m_orig(SelectObject(hdc, h))
+ {
+ }
+
+
+ ///
+ /// Restores original object.
+ ///
+ /// \sa [SelectObject function](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-selectobject)
+ ///
+ virtual ~dc_selector();
+
+
+ ///
+ /// Return result of `SelectObject()` call.
+ ///
+ /// \sa [SelectObject function](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-selectobject)
+ ///
+ inline HGDIOBJ status() const noexcept
+ {
+ return m_orig;
+ }
+
+ protected:
+ HDC m_hdc; ///< A handle to the device context
+ HGDIOBJ m_orig; ///< Original object handle
+ };
+
+ /// @}
+}
diff --git a/src/GDI.cpp b/src/GDI.cpp
new file mode 100644
index 00000000..b67cd6bb
--- /dev/null
+++ b/src/GDI.cpp
@@ -0,0 +1,66 @@
+/*
+ Copyright © 1991-2021 Amebis
+ Copyright © 2016 GÉANT
+
+ This file is part of WinStd.
+
+ Setup is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Setup is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Setup. If not, see .
+*/
+
+#include "PCH.h"
+
+
+//////////////////////////////////////////////////////////////////////
+// winstd::dc
+//////////////////////////////////////////////////////////////////////
+
+winstd::dc::~dc()
+{
+ if (m_h != invalid)
+ DeleteDC(m_h);
+}
+
+
+void winstd::dc::free_internal() noexcept
+{
+ DeleteDC(m_h);
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// winstd::window_dc
+//////////////////////////////////////////////////////////////////////
+
+winstd::window_dc::~window_dc()
+{
+ if (m_h != invalid)
+ ReleaseDC(m_hwnd, m_h);
+}
+
+
+void winstd::window_dc::free_internal() noexcept
+{
+ ReleaseDC(m_hwnd, m_h);
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// winstd::dc_selector
+//////////////////////////////////////////////////////////////////////
+
+winstd::dc_selector::~dc_selector()
+{
+ if (m_orig)
+ SelectObject(m_hdc, m_orig);
+}
diff --git a/src/PCH.h b/src/PCH.h
index 06f3d782..d74cea1a 100644
--- a/src/PCH.h
+++ b/src/PCH.h
@@ -30,6 +30,7 @@
#if _WIN32_WINNT >= _WIN32_WINNT_VISTA
#include "../include/WinStd/ETW.h"
#endif
+#include "../include/WinStd/GDI.h"
#include "../include/WinStd/Hex.h"
#include "../include/WinStd/MSI.h"
#if defined(SECURITY_WIN32) || defined(SECURITY_KERNEL) || defined(SECURITY_MAC)