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:
parent
ab35223c2f
commit
66ebcd7696
171
DDrawCompat/CompatGdiScrollBar.cpp
Normal file
171
DDrawCompat/CompatGdiScrollBar.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
47
DDrawCompat/CompatGdiScrollBar.h
Normal file
47
DDrawCompat/CompatGdiScrollBar.h
Normal 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;
|
||||
};
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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" />
|
||||
|
@ -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">
|
||||
|
Loading…
x
Reference in New Issue
Block a user