Implement a custom painted a trilogy
Now that you know the map controls various options available (including the benefits of using custom paint), so, let's take a look at how to achieve a custom painting need to control the three main steps,
'perform a NM_CUSTOMDRAW message handler,
'designated processing needed to draw phase,
'screening specific rendering stage (in these stages, you need to add your own specific to control rendering code),
Perform a NM_CUSTOMDRAW message handler
When need to draw a common control, MFC will control the custom paint notification message (originally sent to the control's parent window) in the form of NM_CUSTOMDRAW messages back to the controls, the following is a NM_CUSTOMDRAW handler example,
Void CMyCustomDrawControl: : OnCustomDraw (NMHDR * pNMHDR, LRESULT * pResult) {LPNMCUSTOMDRAW pNMCD=reinterpret_cast (pNMHDR); . }
As you can see, the NM_CUSTOMDRAW handlers pass a pointer to NMHDR structure type, however, the value is not used to like NMHDR consists of three members (hwndFrom, id From and code) structure,
Therefore, you usually need to convert the structure pointer to more structure information - LPNMCUSTOMDRAW, NMCUSTOMDRAW LPNMCUSTOMDRAW orientation, it contains such as dwDrawStage dwItemSpec member and uItemState - they are the current drawing stage and exact drawing (for example, the control itself, or the control of a project or item) required,
It is worth noting here, can also be NMHDR pointer to specific are painting the type of control structure, table 1 shows that the control of a list and related custom map structure type name,
Table 1: control and its related custom paint structure
Control structure (defined in commctrl. H)
Rebar, Trackbar AuthTicket, My Resources, My. The Settings, My. The User and My WebServices,
NMCUSTOMDRAW
The List - the view
NMLVCUSTOMDRAW
The Toolbar
NMTBCUSTOMDRAW
Tooltip
NMTTCUSTOMDRAW
The Tree - the view
NMTVCUSTOMDRAW
Specify the processing required for drawing stage
As I mentioned before, draw a control there are some "stage", in particular, your drawing process can be understood as a series of stages, which controls informed the content of the need to draw his father window, in fact, the controls will even send a notification before, during, and after painting and its control, allowing the programmer to control the process better,
In all cases, a single NM_CUSTOMDRAW processing procedures at every stage of drawing are invoked, however, keep in mind: custom map allows you to incorporate it in your own drawing the default controls, you need to specify which drawing you will deal with phase, this by setting the NM_CUSTOMDRAW handler of the second parameter (pResult) is complete, in fact, if you have never set up this value, is in the initial stage of CDDS_PREPAINT calls the function, function will no longer be called you!
Technically, only two stages specified need draw phase (CDDS_PREPAINT and CDDS_ITEMPREPAINT), they affect send notification message content, however, usually only specifies the code at the end of the handler will handle the rendering stage, the listed in table 2 is used to specify the rendering phase code (attention) the value of the
Table 2: custom draw back sign
Custom draw back sign meaning
CDRF_DEFAULT
Instructions controls to draw, the value is the default value, should not put it together with other values,
CDRF_SKIPDEFAULT
Is used to specify the control doesn't make any paint,
CDRF_NEWFONT
When the code change map of items/subitems font used,
CDRF_NOTIFYPOSTPAINT
Make the notification message sent after control or each item/items draw,
CDRF_NOTIFYITEMDRAW
Points out that the item (or items) will be drawn, note that the values are the same as the CDRF_NOTIFYSUBITEMDRAW below it,
CDRF_NOTIFYSUBITEMDRAW
Points out that the item (or items) will be drawn, note that the values are the same as the CDRF_NOTIFYITEMDRAW below it,
CDRF_NOTIFYPOSTERASE
When need to inform the code after the delete control use,
The following as an example, the code specified, when drawing control item (CDRF_NOTIFYITEMDRAW) and children (CDRF_NOTIFYPOSTPAINT), and mapped, should call NM_CUSTOMDRAW handler,
Void CListCtrlWithCustomDraw: : OnNMCustomdraw (NMHDR * pNMHDR, LRESULT * pResult) {LPNMCUSTOMDRAW pNMCD=reinterpret_cast (pNMHDR); . * pResult=0;//Initialize value * pResult |=CDRF_NOTIFYITEMDRAW; * pResult |=CDRF_NOTIFYSUBITEMDRAW; * pResult |=CDRF_NOTIFYPOSTPAINT; }
Screening of the specified drawing stage
Once assigned to focus on stage, you need to deal with these phases, for each stage of the drawing process is only one message to be sent, practice is to perform a switch statement to determine accurate rendering stage, the different stages of drawing by the following symbol definition:
CDDS_PREPAINT CDDS_ITEM CDDS_ITEMPREPAINT CDDS_ITEMPOSTPAINT CDDS_ITEMPREERASE CDDS_ITEMPOSTERASE CDDS_SUBITEM CDDS_POSTPAINT CDDS_PREERASE CDDS_POSTERASE
For a CListCtrl derived class that has a NM_CUSTOMDRAW handler example, which you can find that code decided the current drawing stage way:
Void CMyCustomDrawControl: : OnCustomDraw (NMHDR * pNMHDR, LRESULT * pResult) {LPNMCUSTOMDRAW pNMCD=reinterpret_cast (pNMHDR); The switch (pNMCD - & gt; DwDrawStage) {case CDDS_PREPAINT:... break; Case CDDS_ITEMPREPAINT:... break; Case CDDS_ITEMPREPAINT | CDDS_SUBITEM:... break; . } * pResult=0; }
Note that in order to determine items (for example, a list view control) drawing stage, you must use the bitwise or operator, it has two values: one for CDDS_ITEMPREPAINT or CDDS_ITEMPOSTPAINT, another for CDDS_SUBITEM,
To explain it, we will assume that you want to draw some processing before the list view item, will write a switch statement to handle CDDS_ITEMPREPAINT,
Case CDDS_ITEMPREPAINT:... break;
If, however, is a type of the item you concern drawing stage, will be the following:
Case CDDS_ITEMPREPAINT | CDDS_SUBITEM:... break;
Returns the first return pages first
Example: create a list view control custom painting
controlAs mentioned earlier, you can fully control and its control of drawing, or perform only a small part of the specific to the application, and the control, the focus of this article focus on more control rendering technology rather than advanced paint technology, we will practice a simple example, the listview control is a custom map, therefore, a text displays in create Mosaic appearance of alternating unit for different color,
'to create a project based on Visual c + + 2005 dialog box, called ListCtrlColor,
'Class from the View of choosing Project menu options, and click Add Class to invoke the Add Class dialog box,
'from the category list, select MFC, then from the template list, select the MFC Class,
'click the Add button, call MFC Class Wizard dialog box,
'for the Class name, type value CListCtrl CListCtrlWithCustomDraw and select the Base Class,
'click the Finish button, the class header and executable files,
'for the Class View, right-click the CListCtrlWithCustomDraw Class, and select the Properties context menu option,
'display the Properties window, click the Messages at the top of the button, display a message list two columns, you can achieve for its handler,
'click NM_CUSTOMDRAW items in the message list, and then down the second column of the combo box arrow, and select the value OnNMCustomdraw,
'now, processing drawing code, here, we only simple processing and children drawing stage, specified based on the current line (item) and columns (child) of the text and background colors, to do this, a modified OnNMCustomdraw function as follows:
Void CListCtrlWithCustomDraw: : OnNMCustomdraw (NMHDR * pNMHDR, LRESULT * pResult) {LPNMLVCUSTOMDRAW lpLVCustomDraw=reinterpret_cast (pNMHDR); The switch (lpLVCustomDraw - & gt; NMCD. DwDrawStage) {case CDDS_ITEMPREPAINT: case CDDS_ITEMPREPAINT | CDDS_SUBITEM: if (0==((lpLVCustomDraw - & gt; NMCD. DwItemSpec + lpLVCustomDraw - & gt; ISubItem) % 2)) {lpLVCustomDraw - & gt; ClrText=RGB (255255255);//white text
LpLVCustomDraw - & gt; ClrTextBk=RGB (0, 0);//black background} else {lpLVCustomDraw - & gt; ClrText=CLR_DEFAULT; LpLVCustomDraw - & gt; ClrTextBk=CLR_DEFAULT; } break; Default: break; } * pResult=0; * pResult |=CDRF_NOTIFYPOSTPAINT; * pResult |=CDRF_NOTIFYITEMDRAW; * pResult |=CDRF_NOTIFYSUBITEMDRAW; }
Now, we have to test new control to do this, you only need to use the listview control CListCtrlWithCustomDraw class in the dialog, and carries on the subclass is derived, the following is to complete the operation steps,
'in Resource view, open the application's main dialog box (IDD_LISTCTRLCOLOR_DIALOG),
nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull