From 66ebcd769667cfb4feca76ee27a4540fca951191 Mon Sep 17 00:00:00 2001 From: narzoul Date: Sat, 13 Feb 2016 22:15:15 +0100 Subject: [PATCH] Added manual rendering of scroll bar arrows --- DDrawCompat/CompatGdiScrollBar.cpp | 171 ++++++++++++++++++++++++ DDrawCompat/CompatGdiScrollBar.h | 47 +++++++ DDrawCompat/CompatGdiWinProc.cpp | 20 ++- DDrawCompat/DDrawCompat.vcxproj | 2 + DDrawCompat/DDrawCompat.vcxproj.filters | 6 + 5 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 DDrawCompat/CompatGdiScrollBar.cpp create mode 100644 DDrawCompat/CompatGdiScrollBar.h diff --git a/DDrawCompat/CompatGdiScrollBar.cpp b/DDrawCompat/CompatGdiScrollBar.cpp new file mode 100644 index 0000000..a6f29e2 --- /dev/null +++ b/DDrawCompat/CompatGdiScrollBar.cpp @@ -0,0 +1,171 @@ +#include "CompatGdi.h" +#include "CompatGdiScrollBar.h" + +namespace +{ + enum ScrollBarInfoIndex + { + SBII_SCROLLBAR = 0, + SBII_TOP_RIGHT_ARROW = 1, + SBII_PAGEUP_PAGERIGHT_REGION = 2, + SBII_THUMB = 3, + SBII_PAGEDOWN_PAGELEFT_REGION = 4, + SBII_BOTTOM_LEFT_ARROW = 5 + }; +} + +namespace CompatGdi +{ + ScrollBar::ScrollBar(HWND hwnd, HDC compatDc) : + m_hwnd(hwnd), m_compatDc(compatDc), m_windowRect(), + m_isLeftMouseButtonDown(false), m_cursorPos(), + m_horizontalSbi(), m_verticalSbi() + { + const LONG windowStyle = GetWindowLongPtr(hwnd, GWL_STYLE); + + m_horizontalSbi.isVisible = 0 != (windowStyle & WS_HSCROLL); + m_verticalSbi.isVisible = 0 != (windowStyle & WS_VSCROLL); + + if (m_horizontalSbi.isVisible || m_verticalSbi.isVisible) + { + GetWindowRect(hwnd, &m_windowRect); + + m_isLeftMouseButtonDown = + hwnd == GetCapture() && + GetAsyncKeyState(GetSystemMetrics(SM_SWAPBUTTON) ? VK_RBUTTON : VK_LBUTTON) < 0 && + GetCursorPos(&m_cursorPos); + + if (m_isLeftMouseButtonDown) + { + m_cursorPos.x -= m_windowRect.left; + m_cursorPos.y -= m_windowRect.top; + } + + if (m_horizontalSbi.isVisible) + { + m_horizontalSbi = getScrollBarInfo(OBJID_HSCROLL); + } + + if (m_verticalSbi.isVisible) + { + m_verticalSbi = getScrollBarInfo(OBJID_VSCROLL); + } + } + } + + void ScrollBar::drawAll() const + { + drawHorizArrows(); + drawVertArrows(); + } + + void ScrollBar::drawArrow(const ScrollBarChildInfo& sbci, UINT dfcState) const + { + UINT stateFlags = 0; + if (sbci.state & STATE_SYSTEM_UNAVAILABLE) + { + stateFlags |= DFCS_INACTIVE; + } + else if (sbci.state & STATE_SYSTEM_PRESSED) + { + stateFlags |= DFCS_PUSHED; + } + + RECT rect = sbci.rect; + CALL_ORIG_GDI(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); + } + } + + void ScrollBar::drawVertArrows() const + { + if (m_verticalSbi.isVisible) + { + drawArrow(m_verticalSbi.topLeftArrow, DFCS_SCROLLUP); + drawArrow(m_verticalSbi.bottomRightArrow, DFCS_SCROLLDOWN); + } + } + + void ScrollBar::excludeFromClipRegion(const RECT& rect) const + { + ExcludeClipRect(m_compatDc, rect.left, rect.top, rect.right, rect.bottom); + } + + void ScrollBar::excludeFromClipRegion(const ScrollBarInfo& sbi) const + { + if (sbi.isVisible) + { + 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; + + 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]; + } + 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]; + } + + if (m_isLeftMouseButtonDown) + { + setPressedState(scrollBarInfo.topLeftArrow); + setPressedState(scrollBarInfo.bottomRightArrow); + } + + return scrollBarInfo; + } + + void ScrollBar::setPressedState(ScrollBarChildInfo& sbci) const + { + if (!(sbci.state & STATE_SYSTEM_UNAVAILABLE) && PtInRect(&sbci.rect, m_cursorPos)) + { + sbci.state |= STATE_SYSTEM_PRESSED; + } + } +} diff --git a/DDrawCompat/CompatGdiScrollBar.h b/DDrawCompat/CompatGdiScrollBar.h new file mode 100644 index 0000000..8b89dd7 --- /dev/null +++ b/DDrawCompat/CompatGdiScrollBar.h @@ -0,0 +1,47 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN + +#include + +namespace CompatGdi +{ + class ScrollBar + { + public: + ScrollBar(HWND hwnd, HDC compatDc); + + void drawAll() const; + void drawHorizArrows() const; + void drawVertArrows() const; + void excludeFromClipRegion() const; + + private: + struct ScrollBarChildInfo + { + RECT rect; + LONG state; + }; + + struct ScrollBarInfo + { + ScrollBarChildInfo topLeftArrow; + ScrollBarChildInfo bottomRightArrow; + bool isVisible; + }; + + 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; + + HWND m_hwnd; + HDC m_compatDc; + RECT m_windowRect; + bool m_isLeftMouseButtonDown; + POINT m_cursorPos; + ScrollBarInfo m_horizontalSbi; + ScrollBarInfo m_verticalSbi; + }; +} diff --git a/DDrawCompat/CompatGdiWinProc.cpp b/DDrawCompat/CompatGdiWinProc.cpp index 7fec504..74ff7a8 100644 --- a/DDrawCompat/CompatGdiWinProc.cpp +++ b/DDrawCompat/CompatGdiWinProc.cpp @@ -5,6 +5,7 @@ #include "CompatGdi.h" #include "CompatGdiDc.h" +#include "CompatGdiScrollBar.h" #include "CompatGdiTitleBar.h" #include "CompatGdiWinProc.h" #include "DDrawLog.h" @@ -159,6 +160,10 @@ namespace titleBar.drawAll(); titleBar.excludeFromClipRegion(); + CompatGdi::ScrollBar scrollBar(hwnd, compatDc); + scrollBar.drawAll(); + scrollBar.excludeFromClipRegion(); + OffsetRect(&clientRect, clientOrigin.x - windowRect.left, clientOrigin.y - windowRect.top); ExcludeClipRect(compatDc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom); CALL_ORIG_GDI(BitBlt)(compatDc, 0, 0, @@ -182,7 +187,7 @@ namespace DWORD /*dwEventThread*/, DWORD /*dwmsEventTime*/) { - if (OBJID_TITLEBAR == idObject) + if (OBJID_TITLEBAR == idObject || OBJID_HSCROLL == idObject || OBJID_VSCROLL == idObject) { if (!hwnd || !CompatGdi::beginGdiRendering()) { @@ -193,7 +198,18 @@ namespace HDC compatDc = CompatGdiDc::getDc(windowDc); if (compatDc) { - CompatGdi::TitleBar(hwnd, compatDc).drawAll(); + if (OBJID_TITLEBAR == idObject) + { + CompatGdi::TitleBar(hwnd, compatDc).drawAll(); + } + else if (OBJID_HSCROLL == idObject) + { + CompatGdi::ScrollBar(hwnd, compatDc).drawHorizArrows(); + } + else if (OBJID_VSCROLL == idObject) + { + CompatGdi::ScrollBar(hwnd, compatDc).drawVertArrows(); + } CompatGdiDc::releaseDc(windowDc); } diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 3d8569f..b49e21c 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -150,6 +150,7 @@ + @@ -176,6 +177,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 21611fa..2d95a5c 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -84,6 +84,9 @@ Header Files + + Header Files + @@ -140,6 +143,9 @@ Source Files + + Source Files +