http://blog.csdn.net/lijie45655/article/details/6362441
Three-step implementation of custom drawing
Now that you understand the various options available for drawing controls, including the benefits of using custom drawing, let's take a look at the three main steps required to implement a custom drawing control.
Executes a nm_customdraw message handler.
Specifies the drawing phase that is required for processing.
Filter specific drawing stages (in which you need to add your own control-specific drawing code).
Executes a NM_CUSTOMDRAW message handler
When a common control needs to be drawn, MFC feeds the control's custom draw notification message (originally sent to the control's parent window) as a nm_customdraw message to the control. The following is an example of a nm_customdraw handler.
void Cmycustomdrawcontrol::oncustomdraw (nmhdr* pnmhdr, lresult* pResult) { Lpnmcustomdraw pnmcd = reinterpret _cast (PNMHDR); ...}
As you can see, thenm_customdraw handler passes a pointer to the structure of the NMHDR type. However, this value is not sufficient for structures like NMHDR that contain only three members (Hwndfrom,idfrom , and code).
Therefore, you typically need to convert the struct pointer to a more informative structure- Lpnmcustomdraw. Lpnmcustomdraw points to Nmcustomdraw, which contains such things as dwdrawstage,dwitemspec , and Uitemstate members-they are required to determine the current drawing stage and the exact drawing (for example, the control itself, or a project or subkey of the control).
It is important to note that you can also point the NMHDR Pointer to a structure that is specific to the type of the control being drawn. Table 1 shows a list of controls and their associated custom drawing structure type names.
Table 1: Controls and their associated custom drawing structures
Control |
Structure (defined in commctrl.h) |
Rebar, Trackbar,AuthTicket, My.Resources, My.Settings, My.User and My.WebServices. |
Nmcustomdraw |
List-view |
Nmlvcustomdraw |
Toolbar |
Nmtbcustomdraw |
Tooltip |
Nmttcustomdraw |
Tree-view |
Nmtvcustomdraw |
Specify the drawing phase required for processing
As I mentioned earlier, there are some "stages" in drawing a control. In particular, you can interpret the drawing process as a series of stages in which a control notifies the content that its parent window needs to draw. In fact, a control can even send a notification before and after a drawing control and its items, giving programmers more control over the process.
In all cases, a single Nm_customdraw handler is called at each drawing stage. However, keep in mind that custom drawing allows you to merge the default control drawing in your own drawing, and you need to specify which drawing stage you will be working with. This is done by setting the second parameter (PResult) of the Nm_customdraw handler. In fact, if you never set this value, your function will no longer be called after the function is called with the initial phase of Cdds_prepaint !
Technically, there are only two stages that specify the desired drawing phase (Cdds_prepaint and cdds_itemprepaint), which affect the content of the sending notification message. However, typically only the last specified code in the handler will process the drawing phase. Table 2 lists the values that are used to specify the desired drawing stage (code attention).
Table 2: Custom Draw return Flags
Custom draw return flag |
Meaning |
Cdrf_defaul T |
Instructs the control to draw itself. The value is the default value and should not be combined with other values. |
Cdrf_skipdefault |
is used to specify that the control does not make any drawing at all. |
Cdrf_newfont |
Contemporary code to change the font of a drawing item/subkey. |
Cdrf_notifypostpaint |
Causes notification information to be sent after the control or each item/subkey is drawn. |
Cdrf_notifyitemdraw |
Indicates that the item (or subkey) will be drawn. Note that the value below it is the same as Cdrf_notifysubitemdraw. |
Cdrf_notifysubitemdraw |
Indicates that a subkey (or item) will be drawn. Note that the value below it is the same as Cdrf_notifyitemdraw. |
cdrf_notifyposterase |
Used when you need to notify code when a control is deleted. |
The following is an example where the code specifies that when drawing the control's items (Cdrf_notifyitemdraw) and subkeys (Cdrf_notifypostpaint), and when drawing is complete, the nm_ should be called 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;}
Filter the specified drawing stage
Once you have specified the phases to focus on, you need to work with these phases. Because there is only one message to send at each stage of the drawing process, the Convention is to execute a switch statement to determine the exact drawing phase. The different drawing stages are defined by the following flags:
Cdds_prepaintcdds_itemcdds_itemprepaintcdds_itempostpaintcdds_itempreerasecdds_itemposterasecdds_subitemcdds_ Postpaintcdds_preerasecdds_posterase
For a CListCtrl -derived class, there is an example of a Nm_customdraw handler, where you can see how the code determines the current drawing phase:
void Cmycustomdrawcontrol::oncustomdraw (nmhdr* pnmhdr, lresult* pResult) { Lpnmcustomdraw pnmcd = reinterpret _cast (PNMHDR); Switch (pnmcd->dwdrawstage) {case cdds_prepaint: ... break; Case Cdds_itemprepaint: ... break; Case Cdds_itemprepaint | Cdds_subitem: ... break; ... } *presult = 0;}
Note that in order to determine the stage in which a child item (for example, a list view control) is drawn, you must use the bitwise or operator, which has two values: one of which is cdds_itemprepaint or Cdds_ Itempostpaint, the other is Cdds_subitem.
To illustrate it, we assume that you want to do some processing before you draw a list view item. A switch statement is written to handle the cdds_itemprepaint.
Case Cdds_itemprepaint:...break;
However, if it is the pre-drawing phase of the child you are concerned about, you will do the following:
Case Cdds_itemprepaint | Cdds_subitem:...break;
Back to top example: Create a list view Control custom paint control
As mentioned earlier, you can have complete control over the drawing of the control and its items, or just a small portion of the application-specific drawing, and let the control continue. The focus of this article is more on control drawing rather than advanced drawing techniques, and we'll walk through a simple example where the list view control is a custom drawing, so the text of the item will appear as a different color in the alternating unit that created the stitching appearance.
Create a project that is based on the Visual C + + 2005 dialog box named Listctrlcolor.
Select the Project menu option from class View and click Add Class to invoke the Add Class dialog box.
Select MFCfrom the Category list, and then select MFC Classfrom the list of templates.
Click the Add button to invoke the MFC Class Wizard dialog box.
For Class name, type the value Clistctrlwithcustomdraw and select the Base classfor CListCtrl .
Click the Finish button to generate the header and execute file for the class.
For class View, right-click the Clistctrlwithcustomdraw class and select the Properties context menu option.
When the Properties window is displayed, click the Messages button at the top to display a two-column list of messages for which you can implement handlers.
In the message list, click the nm_customdraw item, and then drop down the second column of the combo box arrow, and select the value onnmcustomdraw.
-
Now process the drawing code. Here, we simply handle the item and child pre-drawing stages, specifying the text and background color based on the current row (item) and column (subkey). To do this, modify as shown below; Onnmcustomdraw function:
void Clistctrlwithcustomdraw::o Nnmcustomdraw (NMHDR *pnmhdr, LRESULT *presult) {Lpnmlvcustomdraw Lplvcustomdraw = reinterpret_cast (PNMHDR); Switch (lplvcustomdraw->nmcd.dwdrawstage) {Case Cdds_itemprepaint:case Cdds_itemprepaint | Cdds_subitem:if (0 = = ((lplvcustomdraw->nmcd.dwitemspec + lplvcustomdraw->isubitem)% 2)) {LpLVCu Stomdraw->clrtext = RGB (255,255,255); White text Lplvcustomdraw->clrtextbk = RGB (0,0,0); Black background} else {lplvcustomdraw->clrtext = Clr_default; LPLVCUSTOMDRAW->CLRTEXTBK = Clr_default; } break; Default:break; } *presult = 0; *presult |= Cdrf_notifypostpaint; *presult |= Cdrf_notifyitemdraw; *presult |= Cdrf_notifysubitemdraw;}
Now, let's test the new control. To do this, you only need to use the Clistctrlwithcustomdraw class to place the list view control in a dialog box and derive it as a subclass. Here are the steps to complete the operation.
In the Resource view, open the application's main dialog box (idd_listctrlcolor_dialog).
From Toolbox , drag a List Control to the dialog box.
Right-click the list control and select the Properties context menu option.
Set the View property to report.
Right-click the control and select the Add Variable context menu option.
When the Add Member Variable Wizard dialog box appears, specify m_lstbooks 's Variable nameand click the Finish button.
At this point, you have a CListCtrl derived class (M_lstbooks) that derives the list view control on the dialog box as a subclass. However, M_lstbooks needs to derive from the newly created Clistctrlwithcustomdraw to facilitate the invocation of your drawing code. Therefore, the title file (ListCtrlColorDlg.h) of the dialog box is opened, and M_lstbooks is changed to the Clistctrlwithcustomdraw type.
Before the Clistctrlcolordlg class begins, add the following directives.
#include "ListCtrlWithCustomDraw.h"
Add the following code to the OnInitDialog member function of the dialog box so that we can see some list view rows.
Insert the Columnsm_lstbooks.insertcolumn (0, _t ("Author")), M_lstbooks.insertcolumn (1, _t ("book"));//Define the datastatic struct { TCHAR m_szauthor[50]; TCHAR m_sztitle[100];} Book_info[] = {_t ("Tom Archer"), _t ("Visual c++.net Bible"), _t ("Tom Archer"), _t ("Extending MFC with the. NET Framework"), _t ("Brian Johnson"), _t ("XBox For Dummies")};//Insert the dataint idx;for (int i = 0; i < sizeof Book_info/sizeo F book_info[0]; i++) { idx = M_lstbooks.insertitem (i, book_info[i].m_szauthor); M_lstbooks.setitemtext (i, 1, book_info[i].m_sztitle);}
Now, build and run the application. Figure 1 is an example of an application's appearance.
Figure 1. Custom Draw Sample Application
Summary
When Windows was first introduced into application development as a "next-gen" operating system, its consistency was one of the main arguments for the new graphical user interface. The point of this argument is that it has a common appearance: a unified menu item, a generic control, and so on. This sense of versatility may persist until a second company wants to design its own application. Simply put, any company will not escape this vicious circle by providing applications that look like other applications.
One way to create a unique and memorable user interface is to design and develop custom controls for your application. Hopefully this article will help you, and now you know a very powerful technology that will make your application stand out from many of your competitors ' applications.
http://blog.csdn.net/witch_soya/article/details/7589816
VC control Self-drawing three-step curve