1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Added manual rendering of scroll bar arrows

This commit is contained in:
narzoul 2016-02-13 22:15:15 +01:00
parent ab35223c2f
commit 66ebcd7696
5 changed files with 244 additions and 2 deletions

View File

@ -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;
}
}
}

View File

@ -0,0 +1,47 @@
#pragma once
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
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;
};
}

View File

@ -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);
}

View File

@ -150,6 +150,7 @@
<ClInclude Include="CompatGdiDc.h" />
<ClInclude Include="CompatGdiDcCache.h" />
<ClInclude Include="CompatGdiFunctions.h" />
<ClInclude Include="CompatGdiScrollBar.h" />
<ClInclude Include="CompatGdiTitleBar.h" />
<ClInclude Include="CompatGdiWinProc.h" />
<ClInclude Include="Config.h" />
@ -176,6 +177,7 @@
<ClCompile Include="CompatGdiCaret.cpp" />
<ClCompile Include="CompatGdiDcCache.cpp" />
<ClCompile Include="CompatGdiFunctions.cpp" />
<ClCompile Include="CompatGdiScrollBar.cpp" />
<ClCompile Include="CompatGdiTitleBar.cpp" />
<ClCompile Include="CompatGdiWinProc.cpp" />
<ClCompile Include="CompatVtable.cpp" />

View File

@ -84,6 +84,9 @@
<ClInclude Include="CompatGdiTitleBar.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CompatGdiScrollBar.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="DllMain.cpp">
@ -140,6 +143,9 @@
<ClCompile Include="CompatGdiTitleBar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CompatGdiScrollBar.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="DDrawCompat.def">