Reputation: 73
I am making a scrollbar for the first time and don't understand why I have a duplicate of my scrollbar when content is scrollable. Here is how it looks, I don't know if you can see it good enough but here's a screenshot; one scrollbar is the thick gray one (the one a want to keep, looks more like the classic scrollbar), and one is a little gray rectangle to the left of it. Both of these scrollbars work and scroll my program. :
But when content is not scrollable then it looks like this:
Here is my ScrollBar.cpp if this will help:
#include "ScrollBar.h"
ScrollBar::ScrollBar(){}
ScrollBar::~ScrollBar(){
RemoveWindowSubclass(hWnd, scrollProc, IDC_STATIC);
delete con;
}
ScrollBar::ScrollBar(HWND hWnd, HINSTANCE hInst) : hWnd(hWnd),hInst(hInst) {
this->hWndParent = GetParent(hWnd);
con = new Controls(hWndParent);
}
void ScrollBar::createScroll(int x, int y, int w, int h, bool stickRight, bool stickBottom) {
this->x = x;
this->y = y;
this->width = w;
this->height = h;
hScroll = con->create("scrollbar", WS_VISIBLE | WS_CHILD | SBS_VERT, x, y, width, height,"scrollBar","",0, stickRight, stickBottom);
//Creates like this
/// CreateWindowEx(0, type, text, styles, cData.x, cData.y, cData.width, cData.height, hWnd, (HMENU)id, NULL, (LPVOID)lParam);
SetWindowSubclass(hScroll, scrollProc, IDC_STATIC, (DWORD_PTR)this);
SetWindowSubclass(hWndParent, scrollProc, IDC_STATIC, (DWORD_PTR)this);
con->setEventListener();
}
void ScrollBar::setScrollRange(int scrollMaxHeight) {
scrollMaxH = scrollMaxHeight == -1 ? scrollMaxH : scrollMaxHeight;
SCROLLINFO si = { 0 };
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE;
si.nMin = 0;
si.nMax = scrollMaxH;
SetScrollInfo(hScroll, SB_VERT, &si, false);
}
void ScrollBar::setScrollSize() {
SCROLLINFO oSi = { 0 };
oSi.cbSize = sizeof(oSi);
oSi.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;
GetScrollInfo(hScroll, SB_VERT, &oSi);
RECT rect = GetLocalCoordinates(hWnd);
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
SCROLLINFO si = { 0 };
si.cbSize = sizeof(si);
si.fMask = SIF_PAGE;
si.nPage = height;
SetScrollInfo(hScroll, SB_VERT, &si, TRUE);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;
GetScrollInfo(hScroll, SB_VERT, &si);
int res = oSi.nPos - si.nPos;
if (res > 0) {
setChildScrollOffset(hWnd, res);
}
}
void ScrollBar::handleVScroll(int action,int thum) {
int nPos;
int nOldPos;
SCROLLINFO si = { 0 };
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS;
GetScrollInfo(hScroll, SB_VERT, &si);
nOldPos = si.nPos;
switch (action)
{
case SB_TOP:
nPos = si.nMin;
break;
case SB_BOTTOM:
nPos = si.nMax;
break;
case SB_LINEUP:
nPos = si.nPos - 30;
break;
case SB_LINEDOWN:
nPos = si.nPos + 30;
break;
case SB_PAGEUP:
nPos = si.nPos - 30;
break;
case SB_PAGEDOWN:
nPos = si.nPos + 30;
break;
case SB_THUMBTRACK:
nPos = thum;
break;
default:
nPos = si.nPos;
break;
}
SetScrollPos(hScroll, SB_VERT, nPos, TRUE);
nPos = GetScrollPos(hScroll, SB_VERT);
if (nOldPos != nPos) {
ScrollWindowEx(hWnd, 0, nOldPos - nPos, NULL, NULL, NULL, NULL,
SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN);
UpdateWindow(hWnd);
setChildScrollOffset(hWnd, nOldPos - nPos);
}
}
void ScrollBar::setChildScrollOffset(HWND h, int offset) {
Controls* childsCon = reinterpret_cast<Controls*>(GetWindowLongPtr(h, GWLP_USERDATA));
for (auto it : childsCon->sControls)
{
childsCon->getControlItem(it.first)->y += offset;
}
}
LRESULT CALLBACK ScrollBar::scrollProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) {
ScrollBar* lpData = (ScrollBar*)dwRefData;
HDC hdc = (HDC)wParam;
PAINTSTRUCT ps;
HBRUSH hbrBackground;
switch (uMsg) {
case WM_SIZE:
{
lpData->setScrollSize();
break;
}
case WM_VSCROLL:
{
lpData->handleVScroll(LOWORD(wParam), HIWORD(wParam));
return true;
}
case WM_MOUSEWHEEL:
{
short zDelta = (short)(0xFFFF & (wParam >> 16));
if (zDelta > 0)
PostMessage(lpData->hScroll, WM_VSCROLL, SB_LINEUP, NULL);
else
PostMessage(lpData->hScroll, WM_VSCROLL, SB_LINEDOWN, NULL);
return 0;
}
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
Upvotes: 1
Views: 268
Reputation: 4017
You need to distinguish between Standard Scroll Bars and Scroll Bar Controls. A scroll bar control is a control window that belongs to the SCROLLBAR window class.
For more details about how to Create Scroll Bar, I suggest you could refer to the Doc: How to Create Scroll Bars
According to the code, you want to create a Scroll Bar Controls. So you should creates a window without standard horizontal and vertical scroll bars and then use the CreateWindowEx function to create a scroll bar by specifying the SCROLLBAR window class.
Could you please show a minimal, reproducible sample?
Upvotes: 0
Reputation: 15162
I am blind and so can't see your screen shots but does your parent window have WS_VSCROLL? (you don't show the styles associated with that window). If so remove it, the WS_VSCROLL adds a scrollbar that is not control-based to the window's non-client area.
Upvotes: 1