A Listbox-like bitmap browser

Description Of Class CTitledPicsWnd

CTitledPicsWnd provides a large-icon-list-view-style window class with scrolling capabilities, but instead of just icons it can display bitmaps with titles below. The size of the 'section' that each bitmap occupies can be set specifically, or can be left to find the best fit. 'Best fit' means that the largest bitmap's width will be used to decide how wide each section is, and the window will fit as many sections as it can fit completely across its width. The pictures are then set out on as many rows as required. If the stretch option is selected, any smaller bitmaps will be stretched to fit the space of the largest bitmap. Also, if the section size is set specifically and is smaller than the largest bitmap, the bitmaps will be stretched or squashed as necessary. (Note: if the section size is too small, and the largest bitmap does not fit and stretching is not selected, the results will be unpredictable - best fit is the default, and is recommended).

The class supports several methods similar to a CObArray for adding to, removing from or getting the size of the array of bitmaps and titles. The bitmaps and titles are handled simultaneously as if it was one big array.

The class also supports a subset of CListBox / CComboBox behaviour; you can set the current selection or retrieve it, you can select items with the left or right mouse buttons, and the window sends notifications (similar to BN_CLICKED or CBN_SELCHANGE) for left-clicking, right-clicking, double-clicking or selection changing to its parent. The only drawback to the notification system is that handlers have to be added manually, as detailed below.

The class accepts either resource IDs of bitmaps (these must be valid), or pointers to CBitmap objects (these must have already been loaded - from file, for example). You can mix these types within the same window. Note that bitmap pointers you add must not be deleted while the window is showing; they must remain valid. When the window is destroyed, then you are responsible for deleting them (the window does not).

Supported Methods:

int Add(CBitmap *pBmp, CString strTitle)
Adds a bitmap pointer and its corresponding title to the array of bitmaps. The index of the added item is returned.

int Add(UINT uBmpID, CString strTitle)
Adds a bitmap resource ID and its corresponding title to the array of bitmaps. The index of the added item is returned.

UINT GetSelectedBitmapType(void)
Returns TPW_BITMAPTYPE_RESOURCE or TPW_BITMAPTYPE_OBJECT depending on the type of the bitmap that was added at the index of the currently-selected item. If no item is currently selected, 0 is returned.

UINT GetSelectedBitmapID(void)
Returns the resource ID of the bitmap that was added at the index of the currently-selected item. If no item is currently selected, or the bitmap at the selected index was a pointer, 0 is returned.

CBitmap *GetSelectedBitmapPointer(void)
Returns the pointer of the bitmap that was added at the index of the currently-selected item. If no item is currently selected, or the bitmap at the selected index was a resource ID, NULL is returned.

CString GetSelectedTitle(void)
Returns the title of the bitmap added at the index of the currently-selected item. If no item is currently selected, an empty string is returned.

void SetSel(int iIndex)
Sets the currently-selected item. This can be TPW_NONE to remove the current selection.

int GetSel(void)
Returns the index of the currently-selected item. If no item is currently selected, TPW_NONE is returned.

void StretchBitmaps(BOOL bStretch = TRUE)
Use this to dictate whether bitmaps are stretched (or shrunk, if necessary) to fit the allocated section size. The default is FALSE.

void SetSpacing(UINT uSpacing)
Each section has a small amount of space around the outside (this space is included in the section size). The default is two pixels either side, top and bottom. Use this method to change this default. The section size does not change because of this.

UINT GetSize(void)
Returns the number of bitmaps in the window's array.

void SetSize(UINT uNewSize)
Similar to a CObArray, this sets a size for the array of bitmaps and titles and is useful if you have a fair number to add and want to avoid the overhead of the array growing automatically - you can set the array to be big enough to hold all the items you will be adding right from the start. Be aware that if you set the size smaller than the current size, the extra data will be lost (as with a normal array).

void RemoveAll(void)
Removes all items from the array. Any bitmap pointers which have been added are NOT deleted - you are responsible for doing that.

void RemoveAt(UINT uIndex, UINT uCount = 1)
Similar to a CObArray, this removes one or more items from the array, starting at the specified index.

void SetSectionSize(int cx, int cy)
By default, the sections are calculated on a best-fit basis (the recommended option). Use this method to specifically set the size of the section. Be aware that if you do not have the stretch option on and you make the sections too small, the results will be unpredictable. Note that the spacing is included in the section size, so you must make allowances for this.

Using CTitledPicsWnd:

  1. In the parent class, embed a member variable which is a pointer to a CTitledPicsWnd object. It is important that you use a pointer, because CViews (the base class of CTitledPicsWnd) delete their wrapper objects automatically when the Windows component (the HWND) is destroyed; so, if you embed an actual object, you will get an assertion.
  2. In the parent class' initialisation routine (OnInitDialog() for CDialog-derived, OnInitialUpdate() for CViewWM_CREATE) for other CWnd-derived), construct the -derived, or OnCreate() (generated by adding a handler for CTitledPicsWndfollows: object and call its Create() method, as
    m_pWndPicList = new CTitledPicsWnd ; 
    m_pWndPicList->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
    rctWindow, this, window ID); 
    

The Create() function is the standard CWnd method; it is left like this in case you want to supply your own window class, although it is recommended that you use the default.

To get the rectangle for the window size, it is recommended that you place a picture control (CStatic) on the dialogue resource template and use its position and dimensions to create the rectangle for the CTitledPicsWnd.

Now you can call any other methods you want to set the window up, and then you can add your bitmaps and their titles. Do not forget that any resource IDs you pass in must be valid bitmap resources, and any CBitmap pointers must have been initialised with a valid bitmap.

CTitledPicsWnd can be used in a dialogue box or in any other window type.

Handling Notifications From CTitledPicsWnd:

The only drawback with this class and its notification codes is that you have to add the handlers manually to its parent. Here is how:

1) In the parent class' message map (code file), add a line:

ON_CONTROL(notification_code, window_id, member_function_name)

The notification codes are TPWN_SELCHANGE, TPWN_CLICK, TPWN_RCLICK and TPWN_DBLCLK, for a change of selection, a left-click, a right-click and a double-click.

In the parent class' header file, in the message-map-generated section, add a line:

afx_msg void member_function_name(void);

Finally, define the function in the parent class' code file (without the afx_msg).

Note that the selection change notification occurs both when the selection is changed using SetSel() and when the mouse is clicked over a section (either mouse button) - but only if the new selection is different from the previous selection. Click notifications occur when the mouse is clicked over a section, no matter which section was last clicked. The selection always follows the mouse click (either button).

Using The Demo

When the program is run, select 'Show' from the Dialogue Box menu. As you click each picture (or its associated title, with either button) the selection change is shown below the window, as is the type of mouse event. This demonstrates the use of the notification messages.

Downloads

Download demo project - 98 Kb

Download source - 5 Kb



Comments

  • maintain the aspect ratio

    Posted by Legacy on 10/31/2002 12:00am

    Originally posted by: Andrea Tosato

    Hello,
    I'm go to using your class CTitledPicsWnd.
    It is very good but I would to resize the picture maintain the aspect ratio.
    I have an algorithm to do this but I don't understand how insert it
    into OnDraw() of class.
    Can you help me?

    Thank you in advance, regards.

    Tosato Andrea

    Reply
  • Changing Title Font

    Posted by Legacy on 07/14/1999 12:00am

    Originally posted by: Shirly Armin

    I really want to use your sample but there is a problem with the FONT.
    I'v already found the function "CreateFont" and changed some values there BUT --> If I have a long title I can't see it all the file name in my example is cut and i see only part of it .

    1. Why it can't show the file name in 2 lines or more?
    (I didn't use STRETCH method!!!
    2. How can I change the color of the selection rectangle so when moving for one item to another it will be more visible??


    I hope you can help me with that!!

    Reply
  • Assertion In Debug Mode

    Posted by Legacy on 07/11/1999 12:00am

    Originally posted by: Jason Teagle

    It has been pointed out to me that in debug mode the class 
    
    can assert. It only happens when the CTitledPicsWnd is
    embedded in a dialogue box rather than a frame window (I
    tested it in debug mode, but in an MDI child frame - I
    didn't know this would happen. When I put it into a
    dialogue box for the test program, I had already declared
    it OK and so just compiled in release mode).

    The reason is that when you activate the window with the
    mouse the WM_MOUSEACTIVATE message is sent - and the MFC
    processes this by checking if the parent is a frame window,
    or the child of one; if it isn't, it asserts. I don't know
    why this check is performed, but it is easy to get round.
    Here is how:

    In the CTitledPicsWnd class, add a handler for the
    WM_MOUSEACTIVATE message. This generates an override of
    OnMouseActivate(). In this override, change the code to the
    following:

    int CTitledPicsWnd::OnMouseActivate(CWnd* pDesktopWnd,
    UINT nHitTest,
    UINT message)
    {
    return MA_ACTIVATE ;
    }

    I have verified that this works. I will update the files on
    CodeGuru as soon as possible (my source files are
    temporarily unavailable to me - just switching to a new PC
    system).

    Reply
  • Ooooops !

    Posted by Legacy on 07/08/1999 12:00am

    Originally posted by: jinee

    it looks so cool.
    but it can't work in debug mode...
    I can't avoid assertion.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • QA teams don't have time to test everything yet they can't afford to ship buggy code. Learn how Coverity can help organizations shrink their testing cycles and reduce regression risk by focusing their manual and automated testing based on the impact of change.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds