From 205f517845791d659c2c22393ebb0930c5277132 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sat, 13 Feb 2021 12:03:00 +0100 Subject: [PATCH] Fixed scroll bar control painting and thumb tracking --- DDrawCompat/D3dDdi/Resource.cpp | 35 +-- DDrawCompat/D3dDdi/Resource.h | 3 +- DDrawCompat/DDraw/DirectDrawPalette.cpp | 9 +- DDrawCompat/DDraw/RealPrimarySurface.cpp | 1 - DDrawCompat/DDrawCompat.vcxproj | 4 +- DDrawCompat/DDrawCompat.vcxproj.filters | 12 +- DDrawCompat/Gdi/AccessGuard.cpp | 41 --- DDrawCompat/Gdi/AccessGuard.h | 21 -- DDrawCompat/Gdi/CompatDc.cpp | 44 +++ DDrawCompat/Gdi/CompatDc.h | 27 ++ DDrawCompat/Gdi/Dc.cpp | 40 +-- DDrawCompat/Gdi/Dc.h | 2 +- DDrawCompat/Gdi/DcFunctions.cpp | 51 +--- DDrawCompat/Gdi/ScrollBar.cpp | 356 +++++++++++++++-------- DDrawCompat/Gdi/ScrollBar.h | 51 ++-- DDrawCompat/Gdi/ScrollFunctions.cpp | 28 -- DDrawCompat/Gdi/TitleBar.cpp | 51 ++-- DDrawCompat/Gdi/TitleBar.h | 12 +- DDrawCompat/Gdi/User32WndProcs.cpp | 109 +++---- DDrawCompat/Gdi/WinProc.cpp | 82 ++++-- DDrawCompat/Gdi/Window.cpp | 2 +- DDrawCompat/Win32/Log.cpp | 7 + DDrawCompat/Win32/Log.h | 1 + 23 files changed, 493 insertions(+), 496 deletions(-) delete mode 100644 DDrawCompat/Gdi/AccessGuard.cpp delete mode 100644 DDrawCompat/Gdi/AccessGuard.h create mode 100644 DDrawCompat/Gdi/CompatDc.cpp create mode 100644 DDrawCompat/Gdi/CompatDc.h diff --git a/DDrawCompat/D3dDdi/Resource.cpp b/DDrawCompat/D3dDdi/Resource.cpp index 288ae32..c179714 100644 --- a/DDrawCompat/D3dDdi/Resource.cpp +++ b/DDrawCompat/D3dDdi/Resource.cpp @@ -187,18 +187,6 @@ namespace D3dDdi { } - void Resource::beginGdiAccess(bool isReadOnly) - { - if (m_lockResource) - { - if (!m_lockData[0].isSysMemUpToDate) - { - copyToSysMem(0); - } - m_lockData[0].isVidMemUpToDate &= isReadOnly; - } - } - HRESULT Resource::blt(D3DDDIARG_BLT data) { if (!isValidRect(data.DstSubResourceIndex, data.DstRect)) @@ -471,14 +459,6 @@ namespace D3dDdi #endif } - void Resource::endGdiAccess(bool isReadOnly) - { - if (m_lockResource && !isReadOnly && m_lockData[0].isSysMemUpToDate) - { - m_lockData[0].isVidMemUpToDate = false; - } - } - void* Resource::getLockPtr(UINT subResourceIndex) { return m_lockData.empty() ? nullptr : m_lockData[subResourceIndex].data; @@ -517,6 +497,21 @@ namespace D3dDdi return m_device.getOrigVtable().pfnLock(m_device, &data); } + void Resource::prepareForGdiRendering(bool isReadOnly) + { + if (!m_lockResource) + { + return; + } + + if (!m_lockData[0].isSysMemUpToDate) + { + copyToSysMem(0); + } + m_lockData[0].isVidMemUpToDate &= isReadOnly; + m_lockData[0].qpcLastForcedLock = Time::queryPerformanceCounter(); + } + void Resource::prepareForRendering(UINT subResourceIndex, bool isReadOnly) { if (m_lockResource && 0 == m_lockData[subResourceIndex].lockCount) diff --git a/DDrawCompat/D3dDdi/Resource.h b/DDrawCompat/D3dDdi/Resource.h index c793f68..74c6d0e 100644 --- a/DDrawCompat/D3dDdi/Resource.h +++ b/DDrawCompat/D3dDdi/Resource.h @@ -26,12 +26,11 @@ namespace D3dDdi operator HANDLE() const { return m_handle; } - void beginGdiAccess(bool isReadOnly); HRESULT blt(D3DDDIARG_BLT data); HRESULT colorFill(D3DDDIARG_COLORFILL data); - void endGdiAccess(bool isReadOnly); void* getLockPtr(UINT subResourceIndex); HRESULT lock(D3DDDIARG_LOCK& data); + void prepareForGdiRendering(bool isReadOnly); void prepareForRendering(UINT subResourceIndex, bool isReadOnly); void setAsGdiResource(bool isGdiResource); HRESULT unlock(const D3DDDIARG_UNLOCK& data); diff --git a/DDrawCompat/DDraw/DirectDrawPalette.cpp b/DDrawCompat/DDraw/DirectDrawPalette.cpp index f9ff453..8d0fe4b 100644 --- a/DDrawCompat/DDraw/DirectDrawPalette.cpp +++ b/DDrawCompat/DDraw/DirectDrawPalette.cpp @@ -1,11 +1,10 @@ #include #include -#include "Common/Time.h" -#include "Config/Config.h" -#include "DDraw/DirectDrawPalette.h" -#include "DDraw/Surfaces/PrimarySurface.h" -#include "Gdi/AccessGuard.h" +#include +#include +#include +#include namespace DDraw { diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index 641d4ec..02e1f16 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index a02cd9a..6f3dbad 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -213,7 +213,7 @@ - + @@ -287,7 +287,7 @@ - + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 755c67c..ac12b5d 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -297,9 +297,6 @@ Header Files\Gdi - - Header Files\Gdi - Header Files\Gdi @@ -402,6 +399,9 @@ Header Files\Gdi + + Header Files\Gdi + @@ -545,9 +545,6 @@ Source Files\Gdi - - Source Files\Gdi - Source Files\Gdi @@ -620,5 +617,8 @@ Source Files\Gdi + + Source Files\Gdi + \ No newline at end of file diff --git a/DDrawCompat/Gdi/AccessGuard.cpp b/DDrawCompat/Gdi/AccessGuard.cpp deleted file mode 100644 index ea107df..0000000 --- a/DDrawCompat/Gdi/AccessGuard.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "D3dDdi/Device.h" -#include "D3dDdi/Resource.h" -#include "DDraw/RealPrimarySurface.h" -#include "DDraw/Surfaces/PrimarySurface.h" -#include "Gdi/AccessGuard.h" - -namespace Gdi -{ - AccessGuard::AccessGuard(Access access, bool condition) - : m_access(access) - , m_condition(condition) - { - if (m_condition) - { - D3dDdi::ScopedCriticalSection lock; - auto gdiResource = D3dDdi::Device::getGdiResource(); - if (gdiResource) - { - gdiResource->beginGdiAccess(ACCESS_READ == m_access); - } - } - } - - AccessGuard::~AccessGuard() - { - if (m_condition) - { - D3dDdi::ScopedCriticalSection lock; - auto gdiResource = D3dDdi::Device::getGdiResource(); - if (gdiResource) - { - gdiResource->endGdiAccess(ACCESS_READ == m_access); - } - if (ACCESS_WRITE == m_access && - (!gdiResource || DDraw::PrimarySurface::getFrontResource() == *gdiResource)) - { - DDraw::RealPrimarySurface::scheduleUpdate(); - } - } - } -} diff --git a/DDrawCompat/Gdi/AccessGuard.h b/DDrawCompat/Gdi/AccessGuard.h deleted file mode 100644 index 0bd5b5a..0000000 --- a/DDrawCompat/Gdi/AccessGuard.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -namespace Gdi -{ - enum Access - { - ACCESS_READ, - ACCESS_WRITE - }; - - class AccessGuard - { - public: - AccessGuard(Access access, bool condition = true); - ~AccessGuard(); - - private: - Access m_access; - bool m_condition; - }; -} diff --git a/DDrawCompat/Gdi/CompatDc.cpp b/DDrawCompat/Gdi/CompatDc.cpp new file mode 100644 index 0000000..be8e34e --- /dev/null +++ b/DDrawCompat/Gdi/CompatDc.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace Gdi +{ + CompatDc::CompatDc(HDC dc, bool isReadOnly) + : m_origDc(dc) + , m_compatDc(Gdi::Dc::getDc(dc)) + , m_isReadOnly(isReadOnly) + { + if (m_compatDc) + { + D3dDdi::ScopedCriticalSection lock; + auto gdiResource = D3dDdi::Device::getGdiResource(); + if (gdiResource) + { + gdiResource->prepareForGdiRendering(isReadOnly); + } + } + else + { + m_compatDc = m_origDc; + } + } + + CompatDc::~CompatDc() + { + if (m_compatDc != m_origDc) + { + D3dDdi::ScopedCriticalSection lock; + auto gdiResource = D3dDdi::Device::getGdiResource(); + if (!m_isReadOnly && (!gdiResource || DDraw::PrimarySurface::getFrontResource() == *gdiResource)) + { + DDraw::RealPrimarySurface::scheduleUpdate(); + } + Gdi::Dc::releaseDc(m_origDc); + } + } +} diff --git a/DDrawCompat/Gdi/CompatDc.h b/DDrawCompat/Gdi/CompatDc.h new file mode 100644 index 0000000..d0a2597 --- /dev/null +++ b/DDrawCompat/Gdi/CompatDc.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +namespace Gdi +{ + class CompatDc + { + public: + CompatDc(HDC dc, bool isReadOnly = false); + CompatDc(const CompatDc&) = delete; + CompatDc(CompatDc&& other) = delete; + CompatDc& operator=(const CompatDc&) = delete; + CompatDc& operator=(CompatDc&&) = delete; + ~CompatDc(); + + operator HDC() const + { + return m_compatDc; + } + + private: + HDC m_origDc; + HDC m_compatDc; + bool m_isReadOnly; + }; +} diff --git a/DDrawCompat/Gdi/Dc.cpp b/DDrawCompat/Gdi/Dc.cpp index f2f43bf..3e834a3 100644 --- a/DDrawCompat/Gdi/Dc.cpp +++ b/DDrawCompat/Gdi/Dc.cpp @@ -22,10 +22,6 @@ namespace HDC origDc; DWORD threadId; int savedState; - HGDIOBJ savedFont; - HGDIOBJ savedBrush; - HGDIOBJ savedPen; - HPALETTE savedPalette; bool useDefaultPalette; }; @@ -38,11 +34,10 @@ namespace void copyDcAttributes(CompatDc& compatDc, HDC origDc, const POINT& origin) { - SelectObject(compatDc.dc, compatDc.savedFont = GetCurrentObject(origDc, OBJ_FONT)); - SelectObject(compatDc.dc, compatDc.savedBrush = GetCurrentObject(origDc, OBJ_BRUSH)); - SelectObject(compatDc.dc, compatDc.savedPen = GetCurrentObject(origDc, OBJ_PEN)); - CALL_ORIG_FUNC(SelectPalette)( - compatDc.dc, compatDc.savedPalette = static_cast(GetCurrentObject(origDc, OBJ_PAL)), FALSE); + SelectObject(compatDc.dc, GetCurrentObject(origDc, OBJ_FONT)); + SelectObject(compatDc.dc, GetCurrentObject(origDc, OBJ_BRUSH)); + SelectObject(compatDc.dc, GetCurrentObject(origDc, OBJ_PEN)); + CALL_ORIG_FUNC(SelectPalette)(compatDc.dc, static_cast(GetCurrentObject(origDc, OBJ_PAL)), FALSE); const int graphicsMode = GetGraphicsMode(origDc); SetGraphicsMode(compatDc.dc, graphicsMode); @@ -98,20 +93,10 @@ namespace void restoreDc(const CompatDc& compatDc) { - if (0 != compatDc.savedState) - { - // Bitmap may have changed during VirtualScreen::update, do not let RestoreDC restore the old one - HGDIOBJ bitmap = GetCurrentObject(compatDc.dc, OBJ_BITMAP); - RestoreDC(compatDc.dc, compatDc.savedState); - SelectObject(compatDc.dc, bitmap); - } - else - { - SelectObject(compatDc.dc, compatDc.savedFont); - SelectObject(compatDc.dc, compatDc.savedBrush); - SelectObject(compatDc.dc, compatDc.savedPen); - CALL_ORIG_FUNC(SelectPalette)(compatDc.dc, compatDc.savedPalette, FALSE); - } + // Bitmap may have changed during VirtualScreen::update, do not let RestoreDC restore the old one + HGDIOBJ bitmap = GetCurrentObject(compatDc.dc, OBJ_BITMAP); + RestoreDC(compatDc.dc, compatDc.savedState); + SelectObject(compatDc.dc, bitmap); } void setClippingRegion(const CompatDc& compatDc, HWND hwnd, const POINT& origin, const RECT& virtualScreenBounds) @@ -135,10 +120,7 @@ namespace ExtSelectClipRgn(compatDc.dc, clipRgn, RGN_AND); } - if (0 != compatDc.savedState) - { - SetMetaRgn(compatDc.dc); - } + SetMetaRgn(compatDc.dc); } } @@ -177,7 +159,7 @@ namespace Gdi } } - HDC getDc(HDC origDc, bool useMetaRgn) + HDC getDc(HDC origDc) { if (!isDisplayDc(origDc)) { @@ -222,7 +204,7 @@ namespace Gdi compatDc.refCount = 1; compatDc.origDc = origDc; compatDc.threadId = GetCurrentThreadId(); - compatDc.savedState = useMetaRgn ? SaveDC(compatDc.dc) : 0; + compatDc.savedState = SaveDC(compatDc.dc); copyDcAttributes(compatDc, origDc, origin); setClippingRegion(compatDc, hwnd, origin, virtualScreenBounds); diff --git a/DDrawCompat/Gdi/Dc.h b/DDrawCompat/Gdi/Dc.h index 87dc1bf..67f1de7 100644 --- a/DDrawCompat/Gdi/Dc.h +++ b/DDrawCompat/Gdi/Dc.h @@ -8,7 +8,7 @@ namespace Gdi { void dllProcessDetach(); void dllThreadDetach(); - HDC getDc(HDC origDc, bool useMetaRgn = true); + HDC getDc(HDC origDc); HDC getOrigDc(HDC dc); void releaseDc(HDC origDc); } diff --git a/DDrawCompat/Gdi/DcFunctions.cpp b/DDrawCompat/Gdi/DcFunctions.cpp index 50c880a..98f646c 100644 --- a/DDrawCompat/Gdi/DcFunctions.cpp +++ b/DDrawCompat/Gdi/DcFunctions.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include #include @@ -14,39 +14,6 @@ namespace { - class CompatDc - { - public: - CompatDc(HDC dc) : m_origDc(dc), m_compatDc(Gdi::Dc::getDc(dc, false)) - { - } - - CompatDc(const CompatDc&) = delete; - - CompatDc(CompatDc&& other) : m_origDc(nullptr), m_compatDc(nullptr) - { - std::swap(m_origDc, other.m_origDc); - std::swap(m_compatDc, other.m_compatDc); - } - - ~CompatDc() - { - if (m_compatDc) - { - Gdi::Dc::releaseDc(m_origDc); - } - } - - operator HDC() const - { - return m_compatDc ? m_compatDc : m_origDc; - } - - private: - HDC m_origDc; - HDC m_compatDc; - }; - std::unordered_map g_funcNames; thread_local bool g_redirectToDib = true; @@ -123,9 +90,9 @@ namespace return t; } - CompatDc replaceDc(HDC dc) + Gdi::CompatDc replaceDc(HDC dc) { - return CompatDc(dc); + return Gdi::CompatDc(dc); } template @@ -137,9 +104,7 @@ namespace if (hasDisplayDcArg(hdc, params...)) { - D3dDdi::ScopedCriticalSection lock; - Gdi::AccessGuard accessGuard(isReadOnly() ? Gdi::ACCESS_READ : Gdi::ACCESS_WRITE); - CompatDc compatDc(hdc); + Gdi::CompatDc compatDc(hdc, isReadOnly()); Result result = Compat::getOrigFuncPtr()(compatDc, replaceDc(params)...); if (isPositionUpdated() && result) { @@ -181,9 +146,7 @@ namespace } else { - D3dDdi::ScopedCriticalSection lock; - Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); - CompatDc compatDc(hdc); + Gdi::CompatDc compatDc(hdc); BOOL result = CALL_ORIG_FUNC(ExtTextOutW)(compatDc, x, y, options, lprect, lpString, c, lpDx); if (result) { @@ -255,9 +218,7 @@ namespace LOG_FUNC("DrawCaption", hwnd, hdc, lprect, flags); if (Gdi::isDisplayDc(hdc)) { - D3dDdi::ScopedCriticalSection lock; - Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); - return LOG_RESULT(CALL_ORIG_FUNC(DrawCaption)(hwnd, replaceDc(hdc), lprect, flags)); + return LOG_RESULT(CALL_ORIG_FUNC(DrawCaption)(hwnd, Gdi::CompatDc(hdc), lprect, flags)); } return LOG_RESULT(CALL_ORIG_FUNC(DrawCaption)(hwnd, hdc, lprect, flags)); } diff --git a/DDrawCompat/Gdi/ScrollBar.cpp b/DDrawCompat/Gdi/ScrollBar.cpp index 49fcfc5..00dd1a9 100644 --- a/DDrawCompat/Gdi/ScrollBar.cpp +++ b/DDrawCompat/Gdi/ScrollBar.cpp @@ -1,177 +1,285 @@ #include -#include #include namespace { enum ScrollBarInfoIndex { - SBII_SCROLLBAR = 0, - SBII_TOP_RIGHT_ARROW = 1, - SBII_PAGEUP_PAGERIGHT_REGION = 2, + SBII_SELF = 0, + SBII_TOP_ARROW = 1, + SBII_PAGEUP_REGION = 2, SBII_THUMB = 3, - SBII_PAGEDOWN_PAGELEFT_REGION = 4, - SBII_BOTTOM_LEFT_ARROW = 5 + SBII_PAGEDOWN_REGION = 4, + SBII_BOTTOM_ARROW = 5 }; + + bool isVertical(HWND hwnd, int bar) + { + if (SB_CTL == bar) + { + return CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_STYLE) & SBS_VERT; + } + return SB_VERT == bar; + } + + thread_local Gdi::ScrollBar* g_trackedScrollBar = nullptr; } namespace Gdi { - ScrollBar::ScrollBar(HWND hwnd, HDC compatDc) : - m_hwnd(hwnd), m_compatDc(compatDc), m_windowRect(), - m_isLeftMouseButtonDown(false), m_cursorPos(), - m_horizontalSbi(), m_verticalSbi() + ScrollBar::ScrollBar(HWND hwnd, int bar) + : m_hwnd(hwnd) + , m_bar(bar) + , m_windowRect{} + , m_sbi{} + , m_isVertical(isVertical(hwnd, bar)) + , m_arrowSize(CALL_ORIG_FUNC(GetSystemMetrics)(m_isVertical ? SM_CYVSCROLL : SM_CXHSCROLL)) + , m_left(m_isVertical ? &RECT::left : &RECT::top) + , m_top(m_isVertical ? &RECT::top : &RECT::left) + , m_right(m_isVertical ? &RECT::right : &RECT::bottom) + , m_bottom(m_isVertical ? &RECT::bottom : &RECT::right) + , m_trackedChildId(-1) + , m_trackedThumbOffset(0) { - const LONG windowStyle = CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_STYLE); - - m_horizontalSbi.isVisible = 0 != (windowStyle & WS_HSCROLL); - m_verticalSbi.isVisible = 0 != (windowStyle & WS_VSCROLL); + LONG objectId = OBJID_CLIENT; + if (SB_HORZ == bar) + { + objectId = OBJID_HSCROLL; + } + else if (SB_VERT == bar) + { + objectId = OBJID_VSCROLL; + } + m_sbi.cbSize = sizeof(m_sbi); + GetScrollBarInfo(hwnd, objectId, &m_sbi); GetWindowRect(hwnd, &m_windowRect); + OffsetRect(&m_sbi.rcScrollBar, -m_windowRect.left, -m_windowRect.top); - if (m_horizontalSbi.isVisible || m_verticalSbi.isVisible) + if (g_trackedScrollBar && + hwnd == g_trackedScrollBar->m_hwnd && + bar == g_trackedScrollBar->m_bar && + GetKeyState(GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON) < 0) { - m_isLeftMouseButtonDown = - hwnd == GetCapture() && - GetAsyncKeyState(GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON) < 0 && - GetCursorPos(&m_cursorPos); + DWORD pos = GetMessagePos(); + POINTS pt = *reinterpret_cast(&pos); + POINT p = { pt.x - m_windowRect.left, pt.y - m_windowRect.top }; - if (m_isLeftMouseButtonDown) + if (SBII_THUMB == g_trackedScrollBar->m_trackedChildId) { - m_cursorPos.x -= m_windowRect.left; - m_cursorPos.y -= m_windowRect.top; + RECT trackRect = m_sbi.rcScrollBar; + if (m_isVertical) + { + InflateRect(&trackRect, 8 * (trackRect.right - trackRect.left), 2 * m_arrowSize); + } + else + { + InflateRect(&trackRect, 2 * m_arrowSize, 8 * (trackRect.bottom - trackRect.top)); + } + if (PtInRect(&trackRect, p)) + { + const LONG thumbSize = m_sbi.xyThumbBottom - m_sbi.xyThumbTop; + const LONG minThumbPos = m_arrowSize; + const LONG maxThumbPos = m_sbi.rcScrollBar.*m_bottom - m_sbi.rcScrollBar.*m_top - thumbSize - m_arrowSize; + + LONG thumbPos = (m_isVertical ? p.y : p.x) - m_sbi.rcScrollBar.*m_top - + g_trackedScrollBar->m_trackedThumbOffset; + if (thumbPos < minThumbPos) + { + thumbPos = minThumbPos; + } + if (thumbPos > maxThumbPos) + { + thumbPos = maxThumbPos; + } + + m_sbi.xyThumbTop = thumbPos; + m_sbi.xyThumbBottom = thumbPos + thumbSize; + } } - - if (m_horizontalSbi.isVisible) + else { - m_horizontalSbi = getScrollBarInfo(OBJID_HSCROLL); - } - - if (m_verticalSbi.isVisible) - { - m_verticalSbi = getScrollBarInfo(OBJID_VSCROLL); + RECT rect = getChildRect(g_trackedScrollBar->m_trackedChildId); + if (PtInRect(&rect, p)) + { + m_sbi.rgstate[g_trackedScrollBar->m_trackedChildId] |= STATE_SYSTEM_PRESSED; + } } } } - void ScrollBar::drawAll() const + ScrollBar::~ScrollBar() { - drawHorizArrows(); - drawVertArrows(); - } - - void ScrollBar::drawArrow(const ScrollBarChildInfo& sbci, UINT dfcState) const - { - UINT stateFlags = 0; - if (sbci.state & STATE_SYSTEM_UNAVAILABLE) + if (this == g_trackedScrollBar) { - stateFlags |= DFCS_INACTIVE; - } - else if (sbci.state & STATE_SYSTEM_PRESSED) - { - stateFlags |= DFCS_PUSHED; - } - - RECT rect = sbci.rect; - CALL_ORIG_FUNC(DrawFrameControl)(m_compatDc, &rect, DFC_SCROLL, dfcState | stateFlags); - } - - void ScrollBar::drawHorizArrows() const - { - if (m_horizontalSbi.isVisible) - { - drawArrow(m_horizontalSbi.topLeftArrow, DFCS_SCROLLLEFT); - drawArrow(m_horizontalSbi.bottomRightArrow, DFCS_SCROLLRIGHT); + g_trackedScrollBar = nullptr; } } - void ScrollBar::drawVertArrows() const + void ScrollBar::drawAll(HDC dc, HBRUSH brush) { - if (m_verticalSbi.isVisible) + if (isVisible()) { - drawArrow(m_verticalSbi.topLeftArrow, DFCS_SCROLLUP); - drawArrow(m_verticalSbi.bottomRightArrow, DFCS_SCROLLDOWN); + drawArrow(dc, SBII_TOP_ARROW); + drawPageRegion(dc, brush, SBII_PAGEUP_REGION); + drawThumb(dc, brush); + drawPageRegion(dc, brush, SBII_PAGEDOWN_REGION); + drawArrow(dc, SBII_BOTTOM_ARROW); } } - void ScrollBar::excludeFromClipRegion(const RECT& rect) const + void ScrollBar::drawArrow(HDC dc, LONG childId) { - ExcludeClipRect(m_compatDc, rect.left, rect.top, rect.right, rect.bottom); - } - - void ScrollBar::excludeFromClipRegion(const ScrollBarInfo& sbi) const - { - if (sbi.isVisible) + UINT state = 0; + if (SBII_TOP_ARROW == childId) { - excludeFromClipRegion(sbi.topLeftArrow.rect); - excludeFromClipRegion(sbi.bottomRightArrow.rect); - } - } - - void ScrollBar::excludeFromClipRegion() const - { - excludeFromClipRegion(m_horizontalSbi); - excludeFromClipRegion(m_verticalSbi); - } - - ScrollBar::ScrollBarInfo ScrollBar::getScrollBarInfo(LONG objId) const - { - ScrollBarInfo scrollBarInfo = {}; - - SCROLLBARINFO sbi = {}; - sbi.cbSize = sizeof(sbi); - scrollBarInfo.isVisible = GetScrollBarInfo(m_hwnd, objId, &sbi) && - !(sbi.rgstate[SBII_SCROLLBAR] & (STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_OFFSCREEN)); - - if (!scrollBarInfo.isVisible) - { - return scrollBarInfo; - } - - OffsetRect(&sbi.rcScrollBar, -m_windowRect.left, -m_windowRect.top); - scrollBarInfo.topLeftArrow.rect = sbi.rcScrollBar; - scrollBarInfo.bottomRightArrow.rect = sbi.rcScrollBar; - scrollBarInfo.shaftRect = sbi.rcScrollBar; - - if (OBJID_HSCROLL == objId) - { - const int w = GetSystemMetrics(SM_CXHSCROLL); - - scrollBarInfo.topLeftArrow.rect.right = scrollBarInfo.topLeftArrow.rect.left + w; - scrollBarInfo.topLeftArrow.state = sbi.rgstate[SBII_BOTTOM_LEFT_ARROW]; - - scrollBarInfo.bottomRightArrow.rect.left = scrollBarInfo.bottomRightArrow.rect.right - w; - scrollBarInfo.bottomRightArrow.state = sbi.rgstate[SBII_TOP_RIGHT_ARROW]; - - InflateRect(&scrollBarInfo.shaftRect, -w, 0); + state = m_isVertical ? DFCS_SCROLLUP : DFCS_SCROLLLEFT; } else { - const int h = GetSystemMetrics(SM_CYVSCROLL); - - scrollBarInfo.topLeftArrow.rect.bottom = scrollBarInfo.topLeftArrow.rect.top + h; - scrollBarInfo.topLeftArrow.state = sbi.rgstate[SBII_TOP_RIGHT_ARROW]; - - scrollBarInfo.bottomRightArrow.rect.top = scrollBarInfo.bottomRightArrow.rect.bottom - h; - scrollBarInfo.bottomRightArrow.state = sbi.rgstate[SBII_BOTTOM_LEFT_ARROW]; - - InflateRect(&scrollBarInfo.shaftRect, 0, -h); + state = m_isVertical ? DFCS_SCROLLDOWN : DFCS_SCROLLRIGHT; } - if (m_isLeftMouseButtonDown) + if (m_sbi.rgstate[childId] & STATE_SYSTEM_UNAVAILABLE) { - setPressedState(scrollBarInfo.topLeftArrow); - setPressedState(scrollBarInfo.bottomRightArrow); + state |= DFCS_INACTIVE; + } + else if (m_sbi.rgstate[childId] & STATE_SYSTEM_PRESSED) + { + state |= DFCS_PUSHED; } - return scrollBarInfo; + RECT rect = getChildRect(childId); + DrawFrameControl(dc, &rect, DFC_SCROLL, state); } - void ScrollBar::setPressedState(ScrollBarChildInfo& sbci) const + void ScrollBar::drawPageRegion(HDC dc, HBRUSH brush, LONG childId) { - if (!(sbci.state & STATE_SYSTEM_UNAVAILABLE) && PtInRect(&sbci.rect, m_cursorPos)) + RECT rect = getChildRect(childId); + if (IsRectEmpty(&rect)) { - sbci.state |= STATE_SYSTEM_PRESSED; + return; + } + + FillRect(dc, &rect, brush); + + if (SB_CTL == m_bar) + { + const UINT edges = m_isVertical ? (BF_LEFT | BF_RIGHT) : (BF_TOP | BF_BOTTOM); + DrawEdge(dc, &rect, BDR_SUNKEN, edges | BF_FLAT); + } + + if (m_sbi.rgstate[childId] & STATE_SYSTEM_PRESSED) + { + InvertRect(dc, &rect); + } + } + + void ScrollBar::drawThumb(HDC dc, HBRUSH brush) + { + if (m_sbi.rgstate[SBII_SELF] & STATE_SYSTEM_UNAVAILABLE) + { + drawPageRegion(dc, brush, SBII_THUMB); + } + else + { + RECT rect = m_sbi.rcScrollBar; + rect.*m_top += m_sbi.xyThumbTop; + rect.*m_bottom = m_sbi.rcScrollBar.*m_top + m_sbi.xyThumbBottom; + DrawFrameControl(dc, &rect, DFC_BUTTON, DFCS_BUTTONPUSH); + } + } + + RECT ScrollBar::getChildRect(LONG childId) + { + RECT r = m_sbi.rcScrollBar; + switch (childId) + { + case SBII_TOP_ARROW: + r.*m_bottom = r.*m_top + m_arrowSize; + break; + + case SBII_PAGEUP_REGION: + r.*m_bottom = r.*m_top + m_sbi.xyThumbTop; + r.*m_top += m_arrowSize; + break; + + case SBII_THUMB: + r.*m_bottom = r.*m_top + m_sbi.xyThumbBottom; + r.*m_top += m_sbi.xyThumbTop; + break; + + case SBII_PAGEDOWN_REGION: + r.*m_top += m_sbi.xyThumbBottom; + r.*m_bottom -= m_arrowSize; + break; + + case SBII_BOTTOM_ARROW: + r.*m_top = r.*m_bottom - m_arrowSize; + break; + } + return r; + } + + LONG ScrollBar::hitTest(POINT p) + { + if (m_sbi.rgstate[SBII_SELF] & STATE_SYSTEM_UNAVAILABLE) + { + return -1; + } + + for (UINT i = SBII_TOP_ARROW; i <= SBII_BOTTOM_ARROW; ++i) + { + RECT r = getChildRect(i); + if (PtInRect(&r, p)) + { + return (m_sbi.rgstate[i] & STATE_SYSTEM_UNAVAILABLE) ? -1 : i; + } + } + return -1; + } + + bool ScrollBar::isVisible() + { + return !(m_sbi.rgstate[SBII_SELF] & (STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_OFFSCREEN)); + } + + void ScrollBar::onCtlColorScrollBar(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT result) + { + HWND hwndSb = reinterpret_cast(lParam); + HBRUSH brush = reinterpret_cast(result); + + HDC dc = reinterpret_cast(wParam); + if (hwnd == hwndSb) + { + ScrollBar(hwnd, SB_HORZ).drawAll(dc, brush); + ScrollBar(hwnd, SB_VERT).drawAll(dc, brush); + } + else + { + ScrollBar(hwndSb, SB_CTL).drawAll(dc, brush); + } + } + + void ScrollBar::onLButtonDown(LPARAM lParam) + { + POINTS pt = *reinterpret_cast(&lParam); + POINT p = { pt.x, pt.y }; + if (SB_CTL != m_bar) + { + p.x -= m_windowRect.left; + p.y -= m_windowRect.top; + } + + m_trackedChildId = hitTest(p); + if (-1 != m_trackedChildId) + { + g_trackedScrollBar = this; + if (SBII_THUMB == m_trackedChildId) + { + RECT rect = getChildRect(SBII_THUMB); + m_trackedThumbOffset = m_isVertical ? (p.y - rect.top) : (p.x - rect.left); + } } } } diff --git a/DDrawCompat/Gdi/ScrollBar.h b/DDrawCompat/Gdi/ScrollBar.h index 5c4c4a1..f58a35f 100644 --- a/DDrawCompat/Gdi/ScrollBar.h +++ b/DDrawCompat/Gdi/ScrollBar.h @@ -7,42 +7,33 @@ namespace Gdi class ScrollBar { public: - struct ScrollBarChildInfo - { - RECT rect; - LONG state; - }; + ScrollBar(HWND hwnd, int bar); + ~ScrollBar(); - struct ScrollBarInfo - { - ScrollBarChildInfo topLeftArrow; - ScrollBarChildInfo bottomRightArrow; - RECT shaftRect; - bool isVisible; - }; + void onLButtonDown(LPARAM lParam); - ScrollBar(HWND hwnd, HDC compatDc); - - void drawAll() const; - void drawHorizArrows() const; - void drawVertArrows() const; - void excludeFromClipRegion() const; - const ScrollBarInfo& getHorizontalScrollBarInfo() const { return m_horizontalSbi; } - const ScrollBarInfo& getVerticalScrollBarInfo() const { return m_verticalSbi; } + static void onCtlColorScrollBar(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT result); private: - void drawArrow(const ScrollBarChildInfo& sbci, UINT dfcState) const; - void excludeFromClipRegion(const RECT& rect) const; - void excludeFromClipRegion(const ScrollBarInfo& sbi) const; - ScrollBarInfo getScrollBarInfo(LONG objId) const; - void setPressedState(ScrollBarChildInfo& sbci) const; + void drawAll(HDC dc, HBRUSH brush); + void drawArrow(HDC dc, LONG childId); + void drawPageRegion(HDC dc, HBRUSH brush, LONG childId); + void drawThumb(HDC dc, HBRUSH brush); + RECT getChildRect(LONG childId); + LONG hitTest(POINT p); + bool isVisible(); HWND m_hwnd; - HDC m_compatDc; + int m_bar; RECT m_windowRect; - bool m_isLeftMouseButtonDown; - POINT m_cursorPos; - ScrollBarInfo m_horizontalSbi; - ScrollBarInfo m_verticalSbi; + SCROLLBARINFO m_sbi; + bool m_isVertical; + int m_arrowSize; + LONG RECT::* m_left; + LONG RECT::* m_top; + LONG RECT::* m_right; + LONG RECT::* m_bottom; + LONG m_trackedChildId; + LONG m_trackedThumbOffset; }; } diff --git a/DDrawCompat/Gdi/ScrollFunctions.cpp b/DDrawCompat/Gdi/ScrollFunctions.cpp index cc7bf44..301b91d 100644 --- a/DDrawCompat/Gdi/ScrollFunctions.cpp +++ b/DDrawCompat/Gdi/ScrollFunctions.cpp @@ -1,10 +1,8 @@ #include #include -#include #include #include #include -#include #include #include @@ -48,31 +46,6 @@ namespace return LOG_RESULT(result); } - - int WINAPI setScrollInfo(HWND hwnd, int nBar, LPCSCROLLINFO lpsi, BOOL redraw) - { - LOG_FUNC("SetScrollInfo", hwnd, nBar, lpsi, redraw); - int result = CALL_ORIG_FUNC(SetScrollInfo)(hwnd, nBar, lpsi, redraw); - if (redraw && (SB_HORZ == nBar || SB_VERT == nBar)) - { - Gdi::ScrollBar sb(hwnd, nullptr); - const auto& sbi = SB_HORZ == nBar ? sb.getHorizontalScrollBarInfo() : sb.getVerticalScrollBarInfo(); - if (sbi.isVisible) - { - HDC windowDc = GetWindowDC(hwnd); - SelectClipRgn(windowDc, Gdi::Region(sbi.shaftRect)); - HDC compatDc = Gdi::Dc::getDc(windowDc); - if (compatDc) - { - Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); - CALL_ORIG_FUNC(DefWindowProcA)(hwnd, WM_PRINT, reinterpret_cast(compatDc), PRF_NONCLIENT); - Gdi::Dc::releaseDc(windowDc); - } - CALL_ORIG_FUNC(ReleaseDC)(hwnd, windowDc); - } - } - return LOG_RESULT(result); - } } namespace Gdi @@ -83,7 +56,6 @@ namespace Gdi { HOOK_FUNCTION(user32, ScrollWindow, scrollWindow); HOOK_FUNCTION(user32, ScrollWindowEx, scrollWindowEx); - HOOK_FUNCTION(user32, SetScrollInfo, setScrollInfo); } } } diff --git a/DDrawCompat/Gdi/TitleBar.cpp b/DDrawCompat/Gdi/TitleBar.cpp index 298195c..f32fa60 100644 --- a/DDrawCompat/Gdi/TitleBar.cpp +++ b/DDrawCompat/Gdi/TitleBar.cpp @@ -1,8 +1,6 @@ #include -#include #include #include -#include #include namespace @@ -19,9 +17,8 @@ namespace namespace Gdi { - TitleBar::TitleBar(HWND hwnd, HDC compatDc) + TitleBar::TitleBar(HWND hwnd) : m_hwnd(hwnd) - , m_compatDc(compatDc) , m_buttonWidth(0) , m_buttonHeight(0) , m_tbi{} @@ -75,26 +72,26 @@ namespace Gdi } } - void TitleBar::drawAll() const + void TitleBar::drawAll(HDC dc) const { - drawCaption(); - drawButtons(); + drawCaption(dc); + drawButtons(dc); } - void TitleBar::drawButtons() const + void TitleBar::drawButtons(HDC dc) const { if (!m_hasTitleBar) { return; } - drawButton(TBII_MINIMIZE_BUTTON, DFCS_CAPTIONMIN); - drawButton(TBII_MAXIMIZE_BUTTON, IsZoomed(m_hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX); - drawButton(TBII_HELP_BUTTON, DFCS_CAPTIONHELP); - drawButton(TBII_CLOSE_BUTTON, DFCS_CAPTIONCLOSE); + drawButton(dc, TBII_MINIMIZE_BUTTON, DFCS_CAPTIONMIN); + drawButton(dc, TBII_MAXIMIZE_BUTTON, IsZoomed(m_hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX); + drawButton(dc, TBII_HELP_BUTTON, DFCS_CAPTIONHELP); + drawButton(dc, TBII_CLOSE_BUTTON, DFCS_CAPTIONCLOSE); } - void TitleBar::drawCaption() const + void TitleBar::drawCaption(HDC dc) const { if (!m_hasTitleBar) { @@ -111,20 +108,15 @@ namespace Gdi flags |= DC_GRADIENT; } - RECT virtualScreenBounds = VirtualScreen::getBounds(); - RECT clipRect = m_tbi.rcTitleBar; - OffsetRect(&clipRect, m_windowRect.left - virtualScreenBounds.left, m_windowRect.top - virtualScreenBounds.top); - Region clipRgn(clipRect); - SelectClipRgn(m_compatDc, clipRgn); - CALL_ORIG_FUNC(DrawCaption)(m_hwnd, m_compatDc, &m_tbi.rcTitleBar, flags); - SelectClipRgn(m_compatDc, nullptr); + SelectClipRgn(dc, Region(m_tbi.rcTitleBar)); + DrawCaption(m_hwnd, dc, &m_tbi.rcTitleBar, flags); + SelectClipRgn(dc, nullptr); if (m_hasIcon) { RECT r = m_tbi.rcTitleBar; r.right = r.left + r.bottom - r.top; - CALL_ORIG_FUNC(FillRect)(m_compatDc, &r, - GetSysColorBrush(m_isActive ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION)); + FillRect(dc, &r, GetSysColorBrush(m_isActive ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION)); HICON icon = reinterpret_cast(SendMessage(m_hwnd, WM_GETICON, ICON_SMALL, 96)); if (!icon) @@ -135,11 +127,11 @@ namespace Gdi int height = GetSystemMetrics(SM_CYSMICON); int x = r.left + (r.right - r.left - width) / 2 + 2; int y = r.top + (r.bottom - r.top - height) / 2; - CALL_ORIG_FUNC(DrawIconEx)(m_compatDc, x, y, icon, width, height, 0, nullptr, DI_NORMAL); + DrawIconEx(dc, x, y, icon, width, height, 0, nullptr, DI_NORMAL); } } - void TitleBar::drawButton(std::size_t tbiIndex, UINT dfcState) const + void TitleBar::drawButton(HDC dc, std::size_t tbiIndex, UINT dfcState) const { if (!isVisible(tbiIndex)) { @@ -157,16 +149,7 @@ namespace Gdi } RECT rect = m_tbi.rgrect[tbiIndex]; - CALL_ORIG_FUNC(DrawFrameControl)(m_compatDc, &rect, DFC_CAPTION, dfcState | stateFlags); - } - - void TitleBar::excludeFromClipRegion() const - { - if (m_hasTitleBar) - { - const RECT& r = m_tbi.rcTitleBar; - ExcludeClipRect(m_compatDc, r.left, r.top, r.right, r.bottom); - } + DrawFrameControl(dc, &rect, DFC_CAPTION, dfcState | stateFlags); } bool TitleBar::isVisible(std::size_t tbiIndex) const diff --git a/DDrawCompat/Gdi/TitleBar.h b/DDrawCompat/Gdi/TitleBar.h index 8c0783e..54cbd46 100644 --- a/DDrawCompat/Gdi/TitleBar.h +++ b/DDrawCompat/Gdi/TitleBar.h @@ -9,19 +9,17 @@ namespace Gdi class TitleBar { public: - TitleBar(HWND hwnd, HDC compatDc); + TitleBar(HWND hwnd); - void drawAll() const; - void drawButtons() const; - void drawCaption() const; - void excludeFromClipRegion() const; + void drawAll(HDC dc) const; + void drawButtons(HDC dc) const; + void drawCaption(HDC dc) const; private: - void drawButton(std::size_t tbiIndex, UINT dfcState) const; + void drawButton(HDC dc, std::size_t tbiIndex, UINT dfcState) const; bool isVisible(std::size_t tbiIndex) const; HWND m_hwnd; - HDC m_compatDc; int m_buttonWidth; int m_buttonHeight; TITLEBARINFOEX m_tbi; diff --git a/DDrawCompat/Gdi/User32WndProcs.cpp b/DDrawCompat/Gdi/User32WndProcs.cpp index 4fb9144..c827ef1 100644 --- a/DDrawCompat/Gdi/User32WndProcs.cpp +++ b/DDrawCompat/Gdi/User32WndProcs.cpp @@ -1,7 +1,6 @@ #include -#include -#include +#include #include #include #include @@ -134,6 +133,15 @@ namespace { switch (msg) { + case WM_CTLCOLORSCROLLBAR: + if (reinterpret_cast(lParam) == hwnd) + { + LRESULT result = origDefWindowProc(hwnd, msg, wParam, lParam); + Gdi::ScrollBar::onCtlColorScrollBar(hwnd, wParam, lParam, result); + return result; + } + break; + case WM_NCACTIVATE: return onNcActivate(hwnd, wParam, lParam); @@ -151,12 +159,13 @@ namespace case WM_NCLBUTTONDOWN: { - LRESULT result = origDefWindowProc(hwnd, msg, wParam, lParam); if (wParam == HTHSCROLL || wParam == HTVSCROLL) { - onNcPaint(hwnd, origDefWindowProc); + Gdi::ScrollBar sb(hwnd, wParam == HTHSCROLL ? SB_HORZ : SB_VERT); + sb.onLButtonDown(lParam); + return origDefWindowProc(hwnd, msg, wParam, lParam); } - return result; + return origDefWindowProc(hwnd, msg, wParam, lParam); } } @@ -347,20 +356,8 @@ namespace LRESULT onEraseBackground(HWND hwnd, HDC dc, WNDPROC origWndProc) { - if (hwnd) - { - LRESULT result = 0; - HDC compatDc = Gdi::Dc::getDc(dc); - if (compatDc) - { - Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); - result = CallWindowProc(origWndProc, hwnd, WM_ERASEBKGND, reinterpret_cast(compatDc), 0); - Gdi::Dc::releaseDc(dc); - return result; - } - } - - return CallWindowProc(origWndProc, hwnd, WM_ERASEBKGND, reinterpret_cast(dc), 0); + return CallWindowProc(origWndProc, hwnd, WM_ERASEBKGND, + reinterpret_cast(static_cast(Gdi::CompatDc(dc))), 0); } LRESULT onNcActivate(HWND hwnd, WPARAM /*wParam*/, LPARAM lParam) @@ -375,73 +372,29 @@ namespace LRESULT onNcPaint(HWND hwnd, WNDPROC origWndProc) { + D3dDdi::ScopedCriticalSection lock; HDC windowDc = GetWindowDC(hwnd); - HDC compatDc = Gdi::Dc::getDc(windowDc); - - if (compatDc) - { - D3dDdi::ScopedCriticalSection lock; - Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); - Gdi::TitleBar titleBar(hwnd, compatDc); - titleBar.drawAll(); - titleBar.excludeFromClipRegion(); - - Gdi::ScrollBar scrollBar(hwnd, compatDc); - scrollBar.drawAll(); - scrollBar.excludeFromClipRegion(); - - CallWindowProc(origWndProc, hwnd, WM_PRINT, reinterpret_cast(compatDc), PRF_NONCLIENT); - - Gdi::Dc::releaseDc(windowDc); - } - - CALL_ORIG_FUNC(ReleaseDC)(hwnd, windowDc); + CallWindowProc(origWndProc, hwnd, WM_PRINT, + reinterpret_cast(static_cast(Gdi::CompatDc(windowDc))), PRF_NONCLIENT); + Gdi::TitleBar(hwnd).drawAll(windowDc); + ReleaseDC(hwnd, windowDc); return 0; } LRESULT onPaint(HWND hwnd, WNDPROC origWndProc) { - if (!hwnd) - { - return CallWindowProc(origWndProc, hwnd, WM_PAINT, 0, 0); - } - PAINTSTRUCT paint = {}; HDC dc = BeginPaint(hwnd, &paint); - HDC compatDc = Gdi::Dc::getDc(dc); - - if (compatDc) - { - Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); - CallWindowProc(origWndProc, hwnd, WM_PRINTCLIENT, - reinterpret_cast(compatDc), PRF_CLIENT); - Gdi::Dc::releaseDc(dc); - } - else - { - CallWindowProc(origWndProc, hwnd, WM_PRINTCLIENT, reinterpret_cast(dc), PRF_CLIENT); - } - + CallWindowProc(origWndProc, hwnd, WM_PRINTCLIENT, + reinterpret_cast(static_cast(Gdi::CompatDc(dc))), PRF_CLIENT); EndPaint(hwnd, &paint); - return 0; } LRESULT onPrint(HWND hwnd, UINT msg, HDC dc, LONG flags, WNDPROC origWndProc) { - LRESULT result = 0; - HDC compatDc = Gdi::Dc::getDc(dc); - if (compatDc) - { - Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); - result = CallWindowProc(origWndProc, hwnd, msg, reinterpret_cast(compatDc), flags); - Gdi::Dc::releaseDc(dc); - } - else - { - result = CallWindowProc(origWndProc, hwnd, msg, reinterpret_cast(dc), flags); - } - return result; + return CallWindowProc(origWndProc, hwnd, msg, + reinterpret_cast(static_cast(Gdi::CompatDc(dc))), flags); } LRESULT onSetText(HWND hwnd, WPARAM wParam, LPARAM lParam, WNDPROC origWndProc) @@ -459,6 +412,13 @@ namespace { switch (msg) { + case WM_LBUTTONDOWN: + { + Gdi::ScrollBar sb(hwnd, SB_CTL); + sb.onLButtonDown(lParam); + return CallWindowProc(origWndProc, hwnd, msg, wParam, lParam); + } + case WM_PAINT: return onPaint(hwnd, origWndProc); @@ -468,10 +428,9 @@ namespace SetCursor(LoadCursor(nullptr, IDC_SIZENWSE)); } return TRUE; - - default: - return CallWindowProc(origWndProc, hwnd, msg, wParam, lParam); } + + return CallWindowProc(origWndProc, hwnd, msg, wParam, lParam); } BOOL WINAPI setMenuItemInfoW(HMENU hmenu, UINT item, BOOL fByPositon, LPCMENUITEMINFOW lpmii) diff --git a/DDrawCompat/Gdi/WinProc.cpp b/DDrawCompat/Gdi/WinProc.cpp index a74aef6..5e4146b 100644 --- a/DDrawCompat/Gdi/WinProc.cpp +++ b/DDrawCompat/Gdi/WinProc.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -34,6 +34,7 @@ namespace WindowProc getWindowProc(HWND hwnd); bool isTopLevelWindow(HWND hwnd); + bool isUser32ScrollBar(HWND hwnd); void onCreateWindow(HWND hwnd); void onDestroyWindow(HWND hwnd); void onWindowPosChanged(HWND hwnd); @@ -64,6 +65,14 @@ namespace switch (uMsg) { + case WM_CTLCOLORSCROLLBAR: + if (reinterpret_cast(lParam) != hwnd && + isUser32ScrollBar(reinterpret_cast(lParam))) + { + Gdi::ScrollBar::onCtlColorScrollBar(hwnd, wParam, lParam, result); + } + break; + case WM_NCDESTROY: onDestroyWindow(hwnd); break; @@ -153,6 +162,25 @@ namespace return GetDesktopWindow() == GetAncestor(hwnd, GA_PARENT); } + bool isUser32ScrollBar(HWND hwnd) + { + WNDCLASS wc = {}; + static const ATOM sbAtom = static_cast(GetClassInfo(nullptr, "ScrollBar", &wc)); + if (sbAtom != GetClassLong(hwnd, GCW_ATOM)) + { + return false; + } + + auto it = g_windowProc.find(hwnd); + if (it == g_windowProc.end()) + { + return false; + } + + return GetModuleHandle("comctl32") != Compat::getModuleHandleFromAddress( + IsWindowUnicode(hwnd) ? it->second.wndProcW : it->second.wndProcA); + } + void CALLBACK objectCreateEvent( HWINEVENTHOOK /*hWinEventHook*/, DWORD /*event*/, @@ -177,33 +205,38 @@ namespace DWORD /*dwEventThread*/, DWORD /*dwmsEventTime*/) { - if (OBJID_TITLEBAR == idObject || OBJID_HSCROLL == idObject || OBJID_VSCROLL == idObject) + switch (idObject) { - if (!hwnd) - { - return; - } + case OBJID_TITLEBAR: + { + HDC dc = GetWindowDC(hwnd); + Gdi::TitleBar(hwnd).drawButtons(dc); + ReleaseDC(hwnd, dc); + break; + } - HDC windowDc = GetWindowDC(hwnd); - HDC compatDc = Gdi::Dc::getDc(windowDc); - if (compatDc) + case OBJID_CLIENT: + if (!isUser32ScrollBar(hwnd)) { - Gdi::AccessGuard accessGuard(Gdi::ACCESS_WRITE); - if (OBJID_TITLEBAR == idObject) - { - Gdi::TitleBar(hwnd, compatDc).drawButtons(); - } - else if (OBJID_HSCROLL == idObject) - { - Gdi::ScrollBar(hwnd, compatDc).drawHorizArrows(); - } - else if (OBJID_VSCROLL == idObject) - { - Gdi::ScrollBar(hwnd, compatDc).drawVertArrows(); - } - Gdi::Dc::releaseDc(windowDc); + break; } - CALL_ORIG_FUNC(ReleaseDC)(hwnd, windowDc); + case OBJID_HSCROLL: + case OBJID_VSCROLL: + { + HDC dc = GetWindowDC(hwnd); + if (OBJID_CLIENT == idObject) + { + SendMessage(GetParent(hwnd), WM_CTLCOLORSCROLLBAR, + reinterpret_cast(dc), reinterpret_cast(hwnd)); + } + else + { + DefWindowProc(hwnd, WM_CTLCOLORSCROLLBAR, + reinterpret_cast(dc), reinterpret_cast(hwnd)); + } + ReleaseDC(hwnd, dc); + break; + } } } @@ -421,6 +454,7 @@ namespace Gdi HOOK_FUNCTION(user32, UpdateLayeredWindow, updateLayeredWindow); HOOK_FUNCTION(user32, UpdateLayeredWindowIndirect, updateLayeredWindowIndirect); + CoInitialize(nullptr); g_objectCreateEventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, Dll::g_currentModule, &objectCreateEvent, GetCurrentProcessId(), 0, WINEVENT_INCONTEXT); g_objectStateChangeEventHook = SetWinEventHook(EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_STATECHANGE, diff --git a/DDrawCompat/Gdi/Window.cpp b/DDrawCompat/Gdi/Window.cpp index 6ec8b56..74a9740 100644 --- a/DDrawCompat/Gdi/Window.cpp +++ b/DDrawCompat/Gdi/Window.cpp @@ -83,7 +83,7 @@ namespace SelectClipRgn(screenDc, clipRegion); BitBlt(screenDc, dst.left, dst.top, src.right - src.left, src.bottom - src.top, screenDc, src.left, src.top, SRCCOPY); SelectClipRgn(screenDc, nullptr); - CALL_ORIG_FUNC(ReleaseDC)(nullptr, screenDc); + ReleaseDC(nullptr, screenDc); return true; } diff --git a/DDrawCompat/Win32/Log.cpp b/DDrawCompat/Win32/Log.cpp index e553bec..ec9c009 100644 --- a/DDrawCompat/Win32/Log.cpp +++ b/DDrawCompat/Win32/Log.cpp @@ -346,6 +346,13 @@ std::ostream& operator<<(std::ostream& os, const POINT& p) << p.y; } +std::ostream& operator<<(std::ostream& os, const POINTS& p) +{ + return Compat::LogStruct(os) + << p.x + << p.y; +} + std::ostream& operator<<(std::ostream& os, const RECT& rect) { return Compat::LogStruct(os) diff --git a/DDrawCompat/Win32/Log.h b/DDrawCompat/Win32/Log.h index bb2a8e2..772c381 100644 --- a/DDrawCompat/Win32/Log.h +++ b/DDrawCompat/Win32/Log.h @@ -33,6 +33,7 @@ std::ostream& operator<<(std::ostream& os, const MSG& msg); std::ostream& operator<<(std::ostream& os, const NCCALCSIZE_PARAMS& nccs); std::ostream& operator<<(std::ostream& os, const NMHDR& nm); std::ostream& operator<<(std::ostream& os, const POINT& p); +std::ostream& operator<<(std::ostream& os, const POINTS& p); std::ostream& operator<<(std::ostream& os, const RECT& rect); std::ostream& operator<<(std::ostream& os, const SIZE& size); std::ostream& operator<<(std::ostream& os, const STYLESTRUCT& ss);