Question

I am trying to draw a graph that has a scrollbar,
the graph uses time for the x-axis and i'd like to have a limited x-axis (1 minute)
so up until 1 minute, the scroll bar's page is the length of the scrollbar,
after that the page should be '60 seconds long' and the scrollbar max should be 'elapsed time' long
when you drag the scrollbar it tracks along, and pulls up the relevant bit of the graph.
the graph should auto-scroll until its dragged away (and auto-scroll once its dragged back to max)

this is what i have so far

is defined at the top of the wndproc
static SCROLLINFO sci = {sizeof(SCROLLINFO),SIF_RANGE|SIF_POS|SIF_PAGE|SIF_TRACKPOS,0,0,0,0,0};

in the WM_HSCROLL event:

GetScrollInfo((HWND)lParam, SB_CTL, &sci);
        int pos;
        pos = sci.nPos;
        switch(LOWORD(wParam))
        {
            case SB_PAGELEFT:
                pos -= sci.nPage;
                break;
            case SB_LINELEFT:
                pos -= (sci.nMax/10);
                break;
            case SB_PAGERIGHT:
                pos += sci.nPage;
                break;
            case SB_LINERIGHT:
                pos += (sci.nMax/10);
                break;
            case SB_THUMBTRACK:
                tsTracking = true;
                pos = sci.nTrackPos;
                break;
            case SB_THUMBPOSITION:
                tsTracking = false;
                pos = sci.nTrackPos;
                break;
        }
        if (pos < sci.nMin) pos = sci.nMin;
        if (pos > sci.nMax) pos = sci.nMax;
        if (pos != sci.nPos)
        {
            sci.fMask = SIF_POS;
            sci.nPos = pos;
            if(sci.nPos >= (sci.nMax-(sci.nPage*1.2)-1))    //this should detect when the thumb has reached the end of the scrollbar
                sci.nPos = sci.nMax;
            SetScrollInfo((HWND)lParam, SB_CTL, &sci, TRUE);
            PostMessage(hWnd, WM_COMMAND, IDM_DISPLAYRESULTS, 0);
        }
        break;

in the drawing code called from WM_PAINT
(yes i realize i shouldn't be setting the scrollbar's info here, i intend to put it in its proper place once its working properly)

at the top of the graph-drawing function:

static SCROLLINFO sci = {sizeof(SCROLLINFO),SIF_RANGE|SIF_POS|SIF_PAGE|SIF_TRACKPOS,0,0,0,0,0};

in the graph-drawing function:

__int64 
    elapsed_time = g_h_maxX-g_h_minX,                                   //the elapsed time
    windowLengthMS,                                                     //the current window length in ms (between 0 and MAX_TIME_WIDTH_MS)
    start,                                                              //the start of the current window
    end;                                                                //the end of the current window
static UINT32 windowMaxS = 1;                                           //how long the window max is (used for x sub-divisions)
double 
    xTickStep,                                                          //x division step
    yTickStep,                                                          //y division step
    xScale,                                                             //x-scale (used to get the time relative to the elapsed time and size of the graph)
    yScale;                                                             //y-scale (used to get the data being plotted relative to its max, and the size of the graph)
if(!tsTracking)                                                         //a global bool, checking if the scrollbar's thumb is being dragged
{
    GetScrollInfo(get_chwnd(IDCW_HARMONICSRESULTSTIMESHIFTSB),SB_CTL,&sci); //gets the scroll info for the scrollbar
    int pos = sci.nPos*(double(elapsed_time)/double(sci.nMax - sci.nMin));  //gets the position relative to the new max     
    sci.nMin = g_h_minX;                                                    //sets min (should always be the same, done for completeness)
    sci.nMax = (((g_h_maxX-MAX_TIME_WIDTH_MS)>0)?(g_h_maxX):0);             //sets max to either max, or 0 (if max isnt bigger then page length)
    sci.nPage = MAX_TIME_WIDTH_MS;                                          //sets the page length to the window length
    sci.nPos = pos;                                                         //sets position to its new value
    if(sci.nPos >= (sci.nMax-(sci.nPage*1.2)-1))                                    //if position is one "page" from the end
        sci.nPos = sci.nMax;                                                    //set it to max
    SetScrollInfo(get_chwnd(IDCW_HARMONICSRESULTSTIMESHIFTSB),SB_CTL,&sci,true);  
}                                                                           //set scroll info

if (elapsed_time > MAX_TIME_WIDTH_MS)                                   //if elapsed time is longer then the max window length
{
    end = ((double)sci.nPos / double(sci.nMax)) * g_h_maxX;                 //set the end to current (scroll position / scroll max) * latest time -> this should put end relative to the scrollbar
    start = end-MAX_TIME_WIDTH_MS;                                          //sets start to end - window length
    if (start < 0)                                                          //if start is now less than zero                                                    
    {
        end = MAX_TIME_WIDTH_MS;                                                //set end to window length
        start = 0;                                                              //set start to 0
    }
}
else                                                                    //if (elapsed_time <= MAX_TIME_WIDTH_MS)                            
{
    start = g_h_minX;                                                       //start is min
    end = g_h_maxX;                                                         //end is max
}
windowLengthMS = (end-start);                                           //find the current window length
if(_MSTOSECS(windowLengthMS) > windowMaxS)                              //if the current window length beats one fo the markers
    windowMaxS = ((windowMaxS < 10)?windowMaxS+1:(windowMaxS==40)?windowMaxS*1.5:windowMaxS*2); //change subdiv scaling
xScale = double(graph_width)/double(windowLengthMS);                    //set x-scale to width / window length
yScale = (double)(graph_height)/((double)g_h_maxY - (double)g_h_minY);  //set y-scale to height / (maxVal-minVal)

int ticks = _MSTOSECS(elapsed_time);                                    //ticks = full seconds elapsed
xTickStep = double(graph_width)/double(ticks+1);                        //tickstep = seconds+1 (accounts for 0)
yTickStep = double(graph_height)/double(Y_TICKS);                       //6 y-ticks, constant.

SelectObject(hDC,hThickPen);
{                                                                       //scope to clear variables!
    double x;                                                               //x to store subdiv x-location
    for(i = ticks; i >= 0; i--)                                             //for each subdiv
    {
        if(((windowMaxS>40)?(!(i%3)):(windowMaxS >20)?(!(i%2)):i))          //have if <=20 secs, each second is shown on x, >20 <=40, every second second is shown, >40 seconds, every 3rd second is shown
        {
            x = round((_SECSTOMS(i)*xScale));                                   //find x-pos
            sprintf(buf,"%d",(i+_MSTOSECS(start)));                                             //print to buffer
            SetRect(&rc, fr.left+x-5, fr.bottom+5, fr.left+x+xTickStep, fr.bottom+25); //get text rectangle
            DrawText(hDC, buf, -1, &rc, DT_SINGLELINE | DT_VCENTER | DT_LEFT);  //draw text
        }
        if (i!=ticks && (windowMaxS>40)?(!(i%6)):(windowMaxS >20)?(!(i%4)):(windowMaxS>10)?(!(i%2)):i)//every <10, each sec gets a subdiv, <20 each second tick gets a subdiv, <40 each 6th tick gets a subdiv
        {
            MoveToEx(hDC, GRAPH_XL_OFFSET+x, graph_bottom, NULL);               //draw the line
            LineTo(hDC, GRAPH_XL_OFFSET+x, graph_bottom-graph_height);          //draw the line
        }
    }
}

as for globals:
g_h_minX is the start time and
g_h_maxX is the last result time
MAX_TIME_WIDTH_MS is the "window length" in ms -> how long i want the scroll bar page (60 seconds)

so the idea is to set end to where the scroll bar is, and get the start by taking the window length from end, and working out which part of the graph we're trying to look at.

i've been fiddling with this for the last 2 days and i'm running out of ideas. im sure i'm close, but i cant quite figure it out,

edit:
updated the code slightly
it also seems i forgot to say what the problem was.
the scolling code isnt working properly, it autoscrolls when new data comes in,
but when i drag the thumb away from the end of the scrollbar, it just snaps to the start, and wont move. on closer inspection, the arrows work, and the "page-right" "page-left" on the right-click menu work, just not the tracking

any help would be appreciated.

thanks in advance.

Was it helpful?

Solution

I have managed to find the problem, I ended up converting everything to seconds and working with that, that ended up working, so i must have been having some scaling issues.
the code ended up like this:

case WM_HSCROLL:
    {
        SCROLLINFO sci = {sizeof(SCROLLINFO),SIF_RANGE|SIF_POS|SIF_PAGE|SIF_TRACKPOS,0,0,0,0,0};
        GetScrollInfo((HWND)lParam, SB_CTL, &sci);
        int pos;
        pos = sci.nPos;
        switch(LOWORD(wParam))
        {
            case SB_PAGELEFT:
                pos -= sci.nPage;
                break;
            case SB_LINELEFT:
                pos -= 2;
                break;
            case SB_PAGERIGHT:
                pos += sci.nPage;
                break;
            case SB_LINERIGHT:
                pos += 2;
                break;
            case SB_THUMBTRACK:
                tsTracking = true;
                pos = sci.nTrackPos;
                break;
            case SB_THUMBPOSITION:
                tsTracking = false;
                pos = sci.nTrackPos;
                break;
            case SB_LEFT:
                pos = sci.nMin;
                break;
            case SB_RIGHT:
                pos = sci.nMax;
                break;
        }
        if (pos < sci.nMin) pos = sci.nMin;
        if (pos > sci.nMax) pos = sci.nMax;
        if (pos != sci.nPos)
        {
            sci.fMask = SIF_POS;
            sci.nPos = pos;
            //if(sci.nPos >= (sci.nMax-sci.nPage))      //this should detect when the thumb has reached the end of the scrollbar
            //  sci.nPos = sci.nMax;
            SetScrollInfo((HWND)lParam, SB_CTL, &sci, TRUE);
            PostMessage(hWnd, WM_COMMAND, IDM_DISPLAYRESULTS, 0);
        }
    }
    break;

for the scrolling code and

 __int64 
    elapsed_time = g_h_maxX-g_h_minX,                                   //the elapsed time
    windowLengthMS,                                                     //the current window length in ms (between 0 and MAX_TIME_WIDTH_MS)
    start,                                                              //the start of the current window
    end;                                                                //the end of the current window
static UINT32 windowMaxS = 1;                                           //how long the window max is (used for x sub-divisions)
double 
    xTickStep,                                                          //x division step
    yTickStep,                                                          //y division step
    xScale,                                                             //x-scale (used to get the time relative to the elapsed time and size of the graph)
    yScale;                                                             //y-scale (used to get the data being plotted relative to its max, and the size of the graph)
    GetScrollInfo(get_chwnd(IDCW_HARMONICSRESULTSTIMESHIFTSB),SB_CTL,&sci); //gets the scroll info for the scrollbar

if (elapsed_time >= MAX_TIME_WIDTH_MS)                                  //if elapsed time is longer then the max window length
{
    start = _SECSTOMS(sci.nPos);                                            //sets start to end - window length
    end = start+MAX_TIME_WIDTH_MS;                                          //set the end to current (scroll position / scroll max) * latest time -> this should put end relative to the scrollbar

}
else                                                                    //if (elapsed_time <= MAX_TIME_WIDTH_MS)                            
{
    start = g_h_minX;                                                       //start is min
    end = g_h_maxX;                                                         //end is max
}
windowLengthMS = (end-start);                                           //find the current window length
if(_MSTOSECS(windowLengthMS) > windowMaxS)                              //if the current window length beats one fo the markers
    windowMaxS = ((windowMaxS < 10)?windowMaxS+1:(windowMaxS==40)?windowMaxS*1.5:windowMaxS*2); //change subdiv scaling
xScale = double(graph_width)/double(windowLengthMS);                    //set x-scale to width / window length
yScale = (double)(graph_height)/((double)max - (double)g_h_minY);   //set y-scale to height / (maxVal-minVal)
if(!(g_h_maxY-g_h_minY))
    yScale = 1;
if(!windowLengthMS)
    xScale = 1;
int ticks = _MSTOSECS(elapsed_time);                                    //ticks = full seconds elapsed
xTickStep = double(graph_width)/double(ticks+1);                        //tickstep = seconds+1 (accounts for 0)
yTickStep = double(graph_height)/double(Y_TICKS);                       //6 y-ticks, constant.

for the graph x-scaling

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top