Monthly Archives: September 2015

As an exercise in dynamically creating controls and custom event handling, this article will walk through a simple thumbnail control that supports both left- and right-mouse clicks. The control will populate itself with a dynamic set of panels. The control posts two custom messages to its parent: WM_ELEMCLICK and WM_ELEMRIGHTCLICK. When the user left-clicks a panel, WM_ELEMCLICK will be posted to the parent dialog for the event. When the user right-clicks a panel, a WM_ELEMCLICK message will be posted to indicate a changing selection and a pop-up menu will be presented. If the user clicks the pop-up menu, a WM_ELEMRIGHTCLICK message will also be posted to the parent window. Any of this functionality can be easily modified based on the desired application. To keep the scope in check, each panel will be drawn as a simple, solid-colored panel. In a real application, a more sophisticated OnPaint() function will be needed to render images or dynamically draw application-specific data.

The control can handle a large number of panels. For this specific example, we are loading the control with five panels, but only displaying three at a time. The control supports a function to scroll left and right, which is called when dialog buttons are clicked. Below are a few screenshots.

The main window before any user interaction:

Notice the change in panels below as the user has selected to scroll right by one panel (by clicking the button labeled Right):

Here, the user has left-clicked a panel. The panel has highlight itself and a left-click message has been posted to the dialog. This is indicated by the text control:

Finally, the image below shows the progression of a right-click, including the pop-up menu and events indicated by the text control:

This program consists of three primary classes:

CBaseStatic – This is the most fundamental of the classes. It extends a CStatic class and encapsulates a single panel in our thumbnail control. It handles the left button click and a right mouse-button up event. Interestingly, CStatic does not handle left- and right-clicks in the same way.

CBaseCollection – This is the control class from a user’s perspective. It also extends the CStatic MFC class. When the AddElement() function is called, a new CBaseStatic panel is dynamically created and added to the control. It tracks a vector of these panels, and determines the dynamic width of each panel by dividing its client width by the number of displayed panels. It also tracks the left-most displayed panel and uses the DisplayBases() function to handle rendering the control.

CDynamicWidgetDlg – This is the parent dialog used primarily for example purposes. It contains an instance of the CBaseCollection control, a CEdit control to provide feedback on handled messages, and buttons to allow scrolling back and forth.