tags:

views:

70

answers:

3

I have a list of items that are each associated with a start and end time and date. What I want to do is, given a time and date range, display only the items that fall within that window, even partially.

What I'm doing is creating a CListCtrl with all the items in it and the CListCtrl is sorted by start time by default. But given a time range, I don't know how to search for the first item that is within the range.

Another problem with the list control is it displays as a list, whereas it would be nice if there was a control that could also show things that are concurrent side by side.

I'm doing this within a dialog application.

A: 

Concurrent things side by side is going to require a custom control.

Filling the list with things within a data range is done by checking which items are within that range at the moment you insert them into the list box. So don't make a list with all items. This is so obvious that I guess I misunderstood your question.

Roel
+1  A: 

You're asking for some very specific functionality. It sounds like you are either building a scheduling app or are trying to display a log of things that have happened in the past. This is called a Gantt Chart. You can buy Gannt Chart controls for MFC on the web. Google for some.

There's more to your question than just how to paint it; You cannot and should not be using a CListCtrl as your data structure. You seem to have an array of objects that are start & end times. For example:

struct Range {
   int startTime; 
   int endTime;
};
std::vector<Range> events;

Once you have put your events into this simple vector, you will have to loop through all of the elements and compare the start/end times to see if they overlap the Range that you are considering:

typedef std::vector<Range> RangeVec;
typedef RangeVec::iterator  RangeIter;

void is_between(int time, const Range& r)
{
    return time >= r.start && time <= r.end;
}

void findRanges(RangeVec *matches, const RangeVec& input, const Range& query)
{
    for (RangeIter it = input.begin(); it != input.end(); ++it) {
        if (is_between(it.start, query) || is_between(it.end, query) || 
            (it.start <= query.start && it.end >= query.end))
    {           
        matches->push_back(*it);
    }
}

You can now loop through your matches and display them however you want. If you are brave, it's rather easy to write a custom control with a subclassed CWnd::OnPaint() that just draws rectangles as long as your overlapped range representing each match.

Armentage
A: 

I'd buy one of the third part controls for this...

Tim