how do a calculation for scroolbars?

we have the window size. we can add a child control to a position more big than size. i can calculate that size. so now i have 2 RECT's:
1
2
3
4
RECT window;
RECT childwindow;
GetClientRect(hwndwindow, &window);
GetClientRect(hwndchildwindow, &childwindow);

now we have the 2 windows sizes.
using the window styles, i can use WS_VSCROLL and WS_HSCROLL styles for add the scroolbars. using the GetScrollInfo() and SetScrollInfo() i can control the scroolbars values.
from that 2 RECTS, how can i calculate the scroolbar for get the nMax of the SCROLLINFO structure?(maybe we need minus the scroolbar size too)
i have almost done:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class ChildWindows
{
private:
    vector<HWND> HwndChildWindows;
    BOOL EnumWindowsMethod( HWND hWnd )
    {
        HwndChildWindows.push_back( hWnd );
        return TRUE;
    }

    static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
    {
        return reinterpret_cast <ChildWindows*> (lParam)->EnumWindowsMethod( hwnd );
    }
public:
    ChildWindows(HWND parent=ActivatedForm)
    {
        EnumChildWindows(parent, EnumChildProc, (LPARAM)this);
    }

    HWND& operator[](int index)
    {
        if(index>=HwndChildWindows.size())
        {
            index=HwndChildWindows.size()-1;
        }
        return HwndChildWindows[index];
    }

    int count()
    {
        return HwndChildWindows.size();
    }
};

POINT GetClientWindowSize(HWND Window=ActivatedForm)
{
    ChildWindows ahwndChildWindows;
    POINT ptSize{0,0};
    RECT rectparent, rectwindow;
    GetClientRect(Window,&rectparent);

    for(int i=0; i<ahwndChildWindows.count(); i++)
    {
        GetWindowRect(ahwndChildWindows[i],&rectwindow);
        ScreenToClient(Window,&rectwindow);
        if(rectwindow.bottom > rectparent.bottom)
        {
            ptSize.y=rectwindow.bottom;
        }

        if(rectwindow.right > rectparent.right)
        {
            ptSize.x=rectwindow.right;
        }
    }
    return ptSize;
}

when i click on a button:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
btnarray[5].MouseClick=[]()//button click
    {
        POINT ws=GetClientWindowSize();
        RECT rtcParent;
        GetClientRect(ActivatedForm,&rtcParent);
        DebugText((string)to_string(ws.y) + "\t" + to_string(rtcParent.bottom));
        if(ws.y>rtcParent.bottom)
        {
            SetWindowLong(ActivatedForm, GWL_STYLE,GetWindowLong(ActivatedForm, GWL_STYLE) | WS_VSCROLL);
            SCROLLINFO SCinfo;
            SCinfo.cbSize=sizeof(SCROLLINFO);
            SCinfo.fMask=SIF_RANGE;
            SCinfo.nMin =0;            
            if(ws.x>rtcParent.right)
                SCinfo.nMax =ws.y-rtcParent.bottom + GetSystemMetrics(SM_CXVSCROLL) ;
            else
                SCinfo.nMax =ws.y-rtcParent.bottom;
            SetScrollInfo(ActivatedForm,SB_VERT,&SCinfo, TRUE);
            DebugText(to_string(SCinfo.nMax));
        }
        if(ws.x>rtcParent.right)
        {
            SetWindowLong(ActivatedForm, GWL_STYLE,GetWindowLong(ActivatedForm, GWL_STYLE) | WS_HSCROLL);
            SCROLLINFO SCinfo;
            SCinfo.cbSize=sizeof(SCROLLINFO);
            SCinfo.fMask=SIF_RANGE;
            SCinfo.nMin =0;
            if(ws.y>rtcParent.bottom)
                SCinfo.nMax =ws.x-rtcParent.right + GetSystemMetrics(SM_CXHSCROLL) ;
            else
                SCinfo.nMax =ws.x-rtcParent.right;

            SetScrollInfo(ActivatedForm,SB_HORZ,&SCinfo, TRUE);
        }
        SetWindowPos(ActivatedForm,NULL,0,0,0,0,SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME);
    };

when the WM_VSCROLL is called:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
case WM_VSCROLL:
                {
                    static bool Vstops=false;
                    SCROLLINFO si;
                    ZeroMemory(&si, sizeof(si));
                    si.cbSize = sizeof(si);
                    si.fMask = SIF_ALL;
                    GetScrollInfo(inst->hwnd,SB_VERT, &si);//the nMax is 34, in these case

                    if( LOWORD(wParam)==SB_LINEDOWN && si.nPos<si.nMax)
                    {
                        SetScrollPos(inst->hwnd,SB_VERT, GetScrollPos(inst->hwnd,SB_VERT) +1,TRUE);
                        ScrollWindowEx(inst->hwnd,0,-1,NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                    }
                    else if( LOWORD(wParam)==SB_LINEUP)
                    {
                        if(GetScrollPos(inst->hwnd,SB_VERT)>0)
                        {
                            SetScrollPos(inst->hwnd,SB_VERT, GetScrollPos(inst->hwnd,SB_VERT) -1,TRUE);
                            ScrollWindowEx(inst->hwnd,0,+1,NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                        }
                    }
                    else if(LOWORD(wParam)==SB_THUMBPOSITION && Vstops==false)//when the user up the click
                    {
                        int thumbposition = HIWORD(wParam);
                        bool upthumb=(thumbposition<si.nPos);

                        SetScrollPos(inst->hwnd,SB_VERT, thumbposition,TRUE);

                        int newposition=0;

                        if(upthumb==false)
                        {
                            newposition= +si.nPos - thumbposition;
                        }
                        else
                        {
                            newposition =  si.nPos - thumbposition;
                        }
                        ScrollWindowEx(inst->hwnd,0,newposition,NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                    }

                    else if(LOWORD(wParam)==SB_THUMBTRACK && Vstops==false)//while draggind
                    {
                        int thumbposition = HIWORD(wParam);
                        bool upthumb=(thumbposition<si.nPos);

                        SetScrollPos(inst->hwnd,SB_VERT, thumbposition,TRUE);

                        int newposition=0;

                        if(upthumb==false)
                        {
                            newposition= +si.nPos - thumbposition;
                        }
                        else
                        {
                            newposition =  si.nPos - thumbposition;
                        }
                        ScrollWindowEx(inst->hwnd,0,newposition,NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                    }

                    else if(LOWORD(wParam)==SB_TOP && Vstops==false)
                    {
                        static int i=i+1;
                        SetWindowText(inst->hwnd,to_string(i).c_str());
                    }
                }
                break;

now works greate ;)
but i need more information for complete the code:
1 - what is the scrollbar notification or property\some strutucte member for when i click on shaft scrollbar section(between the thumb and the arrows buttons)?
2 - the scrollbars values must be changed:
1 - the window is sized;
2 - add\remove a child control;
3 - move or resize a child control.
can anyone advice me more about these?
(maybe for avoid several code and user handle messages)
that code works. but i'm doing 1 important thing wrong that i don't understand correctly.
how can i calculate the nMax and nPage if they are dependent?
how can i calculate the nMax and nPage if they are dependent?
What do you mean?

Max is usually the complete needed size for the graphics/text.
Page is usually the client window size.
thanks for that.
when i use the SB_PAGEUP or SB_PAGEDOWN: the position is calculated: int thumbposition =si.nPos+si.nPage;
is these correct?
The only difference between SB_LINE... and SB_PAGE... is the amount to scroll. Hence it should look alike. The SB_THUMB... doesn't apply.

Take a look at this:
1
2
3
4
5
6
7
8
                        if(upthumb==false)
                        {
                            newposition= +si.nPos - thumbposition; // How does this line
                        }
                        else
                        {
                            newposition =  si.nPos - thumbposition; // differ from the line above?
                        }
I'd say that you can omit the 'if(...)' in both cases.
thanks for correct me that.
but the SB_PAGE isn't for use the nPage value?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
else if(LOWORD(wParam)==SB_PAGEDOWN)//when the user up the click
                    {
                        int thumbposition =si.nPos+si.nPage;
                        if(thumbposition>=si.nMax)
                            thumbposition=si.nMax;
                        SetScrollPos(inst->hwnd,SB_VERT, thumbposition,TRUE);
                        if(GetScrollPos(inst->hwnd,SB_VERT)==si.nMax)
                            ScrollWindowEx(inst->hwnd,0,-(si.nPos-si.nPage),NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                        else
                            ScrollWindowEx(inst->hwnd,0,-si.nPage,NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                    }

                    else if(LOWORD(wParam)==SB_PAGEUP)//when the user up the click
                    {
                        int thumbposition =si.nPos-si.nPage;
                        if(thumbposition<=0)
                            thumbposition=0;
                        SetScrollPos(inst->hwnd,SB_VERT, thumbposition,TRUE);
                        if(GetScrollPos(inst->hwnd,SB_VERT)==si.nMax)
                            ScrollWindowEx(inst->hwnd,0,+(si.nPos-si.nPage),NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                        else
                            ScrollWindowEx(inst->hwnd,0,+si.nPage,NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                    }
the SB_PAGE works fine.
now i'm having problems with SB_THUMBPOSITION and SB_THUMBTRACK...
while i draging the mouse the scroll is done. but when i release the mouse button, the thumb is positioned on back.. why? what i'm doing wrong?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
else if(LOWORD(wParam)==SB_THUMBPOSITION)//when the user up the click
                    {

                        int thumbposition =HIWORD(wParam);

                        //SetScrollPos(inst->hwnd,SB_VERT, thumbposition,TRUE);

                        int newposition=0;

                        newposition =  si.nPos - thumbposition;

                        //ScrollWindowEx(inst->hwnd,0,newposition,NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                    }
                    else if(LOWORD(wParam)==SB_THUMBTRACK)//while draggind
                    {
                        int thumbposition = HIWORD(wParam);


                        SetScrollPos(inst->hwnd,SB_VERT, thumbposition,TRUE);

                        int newposition=0;

                        newposition =  si.nPos - thumbposition;

                        ScrollWindowEx(inst->hwnd,0,newposition,NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                    }

can anyone explain to me what i'm doing wrong?
Sorry, yes the SB_PAGE is ok.
The reason why I mentioned SB_LINE is that you usually scroll more than just a pixel. In that case the calculation would be the same. By the way, here is a simplified calculation:

Up:int scroll_amount = std::min(si.nPage, si.nPos);
Down:int scroll_amount = std::min(si.nPage, si.nMax - si.nPos);

the thumb is positioned on back.. why? what i'm doing wrong?
Line 23: thumbposition is already the new position, hence si.nPos - thumbposition is wrong.
sorry the thumb position continues on back :(
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
else if(LOWORD(wParam)==SB_THUMBTRACK)//while draggind
                    {
                        int thumbposition =HIWORD(wParam);


                        SetScrollPos(inst->hwnd,SB_HORZ, thumbposition,TRUE);

                        int newposition=0;

                        newposition =  si.nPos - thumbposition;
                        ScrollWindowEx(inst->hwnd,si.nPos - thumbposition,0,NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);


                    }
                    else if(LOWORD(wParam)==SB_THUMBPOSITION)//while draggind
                    {
                        int thumbposition =HIWORD(wParam) ;
                        SetScrollPos(inst->hwnd,SB_HORZ, thumbposition,TRUE);
                        ScrollWindowEx(inst->hwnd,si.nPos - thumbposition,0,NULL,NULL,NULL,NULL,SW_SCROLLCHILDREN | SW_INVALIDATE | SW_ERASE);
                    }
let me ask anotherthing(out of topic): on my form, i see 2 strange things:
1 - i mouve de mouse, on form border, until the cursor icon size been showed. i just click on it(just a mouse click). while i move the mouse, the form is resizing;
2 - when i mouse click on thumb button and release it after moving it, is like i continue doing the mouse click on thumb. why these behavior?
(the 2nd, fo course, can affect the scrolling)
ok.. i was doing 1 error on my message loop. and now it's fixed. thanks for all
give me 1 information that i don't know calculate it :(
think on nPos. the value is any place. now resize the window. how i know the wright position?
(ok the nPage and the nMax are changed correctly. that i have sure)
Changing the size of the window does not affect the position. You just need to change the page size.

Take a look at other programs (like notepad or something). What happens to the scroll bar position if you change the size of the window?



2 - when i mouse click on thumb button and release it after moving it, is like i continue doing the mouse click on thumb. why these behavior?
This is usually lagging. I. e. the response to the event might be too slow.
that problem was, too, from my message loop. now don't happens.
see these code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void setAutoScroll(bool autoscroll)
        {
            blnAutoScroll=autoscroll;
            if((GetWindowLong(hwnd,GWL_STYLE)& WS_VSCROLL))
            {
                SetWindowLong(hwnd,GWL_STYLE,GetWindowLong(hwnd,GWL_STYLE) &~WS_VSCROLL);
            }

            if((GetWindowLong(hwnd,GWL_STYLE)& WS_HSCROLL))
            {
                SetWindowLong(hwnd,GWL_STYLE,GetWindowLong(hwnd,GWL_STYLE) &~WS_HSCROLL);
            }

            if(blnAutoScroll==true)
            {
                POINT ws=GetClientWindowSize();
                RECT rtcParent;
                GetClientRect(hwnd,&rtcParent);
                if(ws.y>rtcParent.bottom)
                {
                    SetWindowLong(hwnd, GWL_STYLE,GetWindowLong(hwnd, GWL_STYLE) | WS_VSCROLL);
                    SCROLLINFO SCinfo;
                    SCinfo.cbSize=sizeof(SCROLLINFO);
                    SCinfo.fMask=SIF_RANGE | SIF_PAGE;
                    SCinfo.nMin =0;
                    SCinfo.nMax =ws.y;
                    SCinfo.nPage=rtcParent.bottom;
                    SetScrollInfo(hwnd,SB_VERT,&SCinfo, TRUE);
                }
                if(ws.x>rtcParent.right)
                {
                    SetWindowLong(hwnd, GWL_STYLE,GetWindowLong(hwnd, GWL_STYLE) | WS_HSCROLL);
                    SCROLLINFO SCinfo;
                    SCinfo.cbSize=sizeof(SCROLLINFO);
                    SCinfo.fMask=SIF_RANGE | SIF_PAGE;
                    SCinfo.nMin =0;
                    SCinfo.nMax =ws.x;
                    SCinfo.nPage=rtcParent.right;
                    SetScrollInfo(hwnd,SB_HORZ,&SCinfo, TRUE);
                }
            }
            SetWindowPos(hwnd,NULL,0,0,0,0,SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME);
        }

imagine that i change the nPos(in execute mode) to 1000. i resize the window. when i put both scrollbars to nMax, i can't see the last child control :(
i did a new test coder777. thanks for all.. .thank you. now works fine:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void setAutoScroll(bool autoscroll)
        {
            blnAutoScroll=autoscroll;
            if((GetWindowLong(hwnd,GWL_STYLE)& WS_VSCROLL))
            {
                SetWindowLong(hwnd,GWL_STYLE,GetWindowLong(hwnd,GWL_STYLE) &~WS_VSCROLL);
            }

            if((GetWindowLong(hwnd,GWL_STYLE)& WS_HSCROLL))
            {
                SetWindowLong(hwnd,GWL_STYLE,GetWindowLong(hwnd,GWL_STYLE) &~WS_HSCROLL);
            }

            if(blnAutoScroll==true)
            {
                POINT ws=GetClientWindowSize();
                RECT rtcParent;
                GetClientRect(hwnd,&rtcParent);
                if(ws.y>rtcParent.bottom)
                {
                    SetWindowLong(hwnd, GWL_STYLE,GetWindowLong(hwnd, GWL_STYLE) | WS_VSCROLL);
                    SCROLLINFO SCinfo;
                    SCinfo.cbSize=sizeof(SCROLLINFO);
                    SCinfo.fMask=SIF_RANGE | SIF_PAGE;
                    SCinfo.nMin =0;
                    SCinfo.nMax =ws.y;
                    SCinfo.nPage=rtcParent.bottom;
                    SetScrollInfo(hwnd,SB_VERT,&SCinfo, TRUE);
                }
                if(ws.x>rtcParent.right)
                {
                    SetWindowLong(hwnd, GWL_STYLE,GetWindowLong(hwnd, GWL_STYLE) | WS_HSCROLL);
                    SCROLLINFO SCinfo;
                    SCinfo.cbSize=sizeof(SCROLLINFO);
                    SCinfo.fMask=SIF_RANGE | SIF_PAGE;
                    SCinfo.nMin =0;
                    SCinfo.nMax =ws.x;
                    SCinfo.nPage=rtcParent.right;
                    SetScrollInfo(hwnd,SB_HORZ,&SCinfo, TRUE);
                }
            }
            SetWindowPos(hwnd,NULL,0,0,0,0,SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME);
        }

and parent resize:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//the WM_SIZING is for maximized
                case WM_SIZING:
                case WM_SIZE:
                {
                    if(inst->getAutoScroll()==true)
                    {
                        RECT a;
                        GetClientRect(inst->hwnd,&a);
                        SCROLLINFO SCinfo;
                        SCinfo.cbSize=sizeof(SCROLLINFO);
                        SCinfo.fMask=SIF_PAGE;
                        GetScrollInfo(inst->hwnd,SB_VERT,&SCinfo);
                        SCinfo.nPage=a.bottom;
                        SetScrollInfo(inst->hwnd,SB_VERT,&SCinfo, TRUE);
                        GetScrollInfo(inst->hwnd,SB_HORZ,&SCinfo);
                        SCinfo.nPage=a.right;
                        SetScrollInfo(inst->hwnd,SB_HORZ,&SCinfo, TRUE);
                    }
                    RECT a;
                    GetWindowRect(inst->hwnd,&a);
                    ScreenToClient(GetParent(inst->hwnd),&a);
                    InvalidateRect(inst->hwnd, &a,true);
                    inst->Resize();
                    return 0;
                }
                break;

now i came up with idea for save CPU :P
when i resize\position\add child control, i send a message(SendMessage() ) with it's handle(HWND) and see it's client rectangle for test the bottom\right with nMax or vertical\horizontal scrollbars.
thanks for all.
correct me these please:
can i use these const, in these way:
1
2
3
4
#define WM_GETCHILD (WM_USER+1)
#define WM_LOSECHILD (WM_USER+2)
#define WM_SIZECHILD (WM_USER+3)
#define WM_MOVECHILD (WM_USER+4) 

why i'm asking?
because the OS can use some of them and i don't know about it :(
can i use these const, in these way:
Yes, read this:

https://msdn.microsoft.com/en-us/library/windows/desktop/ms644931.aspx
thanks for all
Topic archived. No new replies allowed.