How to add a self-painted MFC control to favorites

Source: Internet
Author: User

How to add a self-painted MFC control to favorites

 

Http://blog.csdn.net/cug_stu/archive/2010/11/15/6010966.aspx

 

The source code has been uploaded.

Implementation of the Custom button

Author: du xiuxing

 

I. Preparations

Before coding, you should first determine the appearance of the button in various States. The basic statuses of the button control include:
Normal status, which is the way the button is displayed at the beginning.
Over status. It is displayed when you move the cursor over the button.
Down status, which is displayed when you press the button.
Focus status, which is released after the button is pressed. For example, after the standard button is released, a dotted box is displayed inside the button.
The Disable status, of course, is when the button is set to invalid.

Based on the actual appearance of common buttons in Windows XP, I designed the appearance of XP buttons in various States, as shown in:

 
As for the down state, the text is moved to the lower right direction on the basis of the over State to achieve the effect of downpressure.

II. Implementation Principles and difficulties

Next, create a class. On the workspace's classview page, right-click the root node of the List tree and select new class...

 

Define a derived class in the pop-up window, as shown in. Note that you only need to enter the name and base class items, and keep the default values for other options.

 

The following describes how buttons are implemented:

1. Add the owner draw attribute for the button during control initialization. This is because in MFC, to activate the control's self-painting function, the property of the control must contain the property value bs_ownerdraw. In this step, we can add presubclasswindow () to the cxpbutton class through the Class Wizard () function. After the control's self-painting function is activated, the drawitem () function is run every time the control state changes. This function is used to draw the display of the control in various States.

2. Add the wm_mouseleave message function. When the mouse pointer leaves the button, this message function is triggered. We add code to the function to notify the drawitem function that the mouse pointer has left and re-draw the button.

3. add the wm_mousehover message function. When the mouse pointer is above the button, this message function is triggered. We re-Add the code in the function to notify the drawitem function that the mouse pointer is now above the button, redraw the button.

4. Add the drawitem function. In drawitem, draw the appearance of a button Based on the current status of the button. It can be said that most of the functions of the Self-painted control are implemented in this function. The drawitem function contains a pointer to lpdrawitemstruct, which will be explained later in this article.

There are two difficulties. First, wm_mouseleave and wm_mousehover are not standard Windows message functions. They cannot be added through the Class Wizard. All the adding operations must be completed by manually entering the code. Another difficulty is the lpdrawitemstruct pointer in drawitem, which points to a drawitemstruct structure, which contains various details of the control and provides us with the necessary information to implement the self-painting function.

Difficulty 1:
In fact, wm_mouseleave and wm_mousehover are triggered by the wm_mousemove message, while wm_mousemove is a standard Windows message. Therefore, we can add the wm_mousemove message function for the cxpbutton class through the Class Wizard.
 

The code of the function is as follows. This code is very useful. In other self-painted controls, if you want to trigger the wm_mouseleave and wm_mousehover messages, you can use a similar method.

Void cxpbutton: onmousemove (uint nflags, cpoint point)
{
// Todo: add your message handler code here and/or call default
If (! M_btracking)
{
Trackmouseevent tme;
Tme. cbsize = sizeof (TME );
Tme. hwndtrack = m_hwnd;
Tme. dwflags = tme_leave | tme_hover;
Tme. dwhovertime = 1;
M_btracking = _ trackmouseevent (& TME );
}
Cbutton: onmousemove (nflags, point );
} We will then add the wm_mouseleave and wm_mousehover message functions. Find the function declaration of afx_msg void onmousemove (uint nflags, cpoint point) in the cxpbutton class declaration (that is, in xpbutton. h file);, followed by the input

Afx_msg lresult onmouseleave (wparam, lparam );
Afx_msg lresult onmousehover (wparam, lparam );
Find on_wm_mousemove () in the xpbutton. cpp file and enter

On_message (wm_mouseleave, onmouseleave)
On_message (wm_mousehover, onmousehover)

Difficulty 2:
Next, let's take a look at the useful information provided by the drawitemstruce structure?
The drawitemstruct structure is defined as follows:

Typedef struct tagdrawitemstruct {
Uint ctltype; // control type
Uint ctlid; // Control ID
Uint Itemid; // the index value of a menu item, a list box, or a certain item in the combo box
Uint itemaction; // control action
Uint itemstate; // control state
Hwnd hwnditem; // parent window handle or menu handle
HDC; // The drawing device handle corresponding to the control
Rect rcitem; // The rectangular area occupied by the Control
DWORD itemdata; // the value of an item in the list box or combo box
} Drawitemstruct, * pdrawitemstruct, * lpdrawitemstruct. In fact, not only are button controls, but other controls, such as ComboBox, ListBox, and statictext, all use drawitemstruct to record control information. For more information about this structure, see the appendix in this document.

You may have seen many examples of self-painted buttons. In fact, the function structure of the Self-painted buttons is similar, the differences in their display effect mainly depend on the degree to which the code writer can use and master the GDI plot function. If you are interested, you can study the data structure of the drawitem function in the cxpbutton class. In fact, you only need to modify part of the code of the GDI drawing function, and you can now make another self-painted button control.

Iii. Use of Button classes

The following shows how to use the cxpbutton class. Add a button control to the dialog box. Assume that its ID is idc_button1. Go to the member variables attribute page of the Class Wizard (Class Wizard) and add a variable m_btnnormal to idc_button1. Confirm to exit and compile again. Then you can see the XP style redefines button.

 

If you introduce the cxpbutton source file to your project, you cannot see the cxpbutton option in the variable type. However, you can add the following methods:

1. Save the project and exit.
2. Find a file named. CLW in the project directory and delete it. However, we recommend that you back up the data just in case.
3. Open the project again and enter the Class Wizard. A pop-up dialog box is displayed. Select Yes )".

 

4. Select "add all" to use the variable type of cxpbutton in the Class Wizard.

Iv. Summary and tips

For a button, you must call the drawitem function to re-paint any visible part of the button. The bs_ownerdraw attribute must be set for the auto-draw button. The set code is completed in the presubclasswindows function. In addition, to prevent changes in system font settings from affecting the expression of the control, you can also specify a fixed font for the control in this function. But note that
Let's review the basic steps for implementing the Custom button:
A. determine the design scheme;
B. initialize, but remember to restore the previous GDI object and release the occupied resources before exiting the function;
C. Add the corresponding message function;
D. Add the drawing function drawitem. In drawitem, the order of drawing is generally to draw the outer border first, then the background color, then write the text, and finally draw the inner border. However, some people also like to put the border in the final painting, which is not a big problem.

V. Appendix

Drawitemstruct structure document (translated by msdn)

Drawitemstruct

Drawitemstruct provides necessary information for the control or menu item to be painted. Get a pointer to this structure in the wm_drawitem message function corresponding to the control or menu item to be drawn. The drawitemstruct structure is defined as follows:
Typedef struct tagdrawitemstruct {
Uint ctltype;
Uint ctlid;
Uint Itemid;
Uint itemaction;
Uint itemstate;
Hwnd hwnditem;
HDC;
Rect rcitem;
Ulong_ptr itemdata;
} Drawitemstruct;

Structure member:

Ctltype
The control type is specified, and its values are shown in the following table.

Value
Description

Odt_button
Button Control

Odt_combobox
Combo Control

Odt_listbox
List box Control

Odt_listview
List View Controls

Odt_menu
Menu item

Odt_static
Static text Control

Odt_tab
Tab Control

Ctlid

The id value of the Self-painted control is specified, and this member is not required for the menu item.

Itemid
Indicates the menu item ID, or the index value of an item in the list box or combo box. For an empty list box or combo box, the value of this Member is-1. At this time, the application only draws the focus rectangle (the coordinates of the rectangle are given by the rcitem Member). Although there is no display item in the control, it is necessary to draw the focus rectangle, this prompts you whether the control has the input focus. Of course, you can also set the itemaction member as the appropriate value, so that you do not need to draw the focus.

Itemaction
Specifies the painting behavior. The value can be one or more of the Union values shown in the following table.

Value
Description

Oda_drawentire
Set this value when the entire control needs to be drawn.

Oda_focus
This value is set if the control needs to be drawn when the focus is obtained or lost. Check the itemstate member to check whether the control has the input focus.

Oda_select
This value is set if the control needs to be drawn when the selected status changes. Check the itemstate member to check whether the control is selected.

Itemstate
Specifies the visible status of the painted items after the current painting is completed. For example, if the menu item should be dimmed, you can specify the ods_grayed status flag. The value can be the union of one or more values shown in the following table.

Value
Description

Ods_checked
You can set this value if the menu item is selected. This value is only useful for menu items.

Ods_comboboxedit
Only the selected area is drawn in the Self-painted combo box control.

Ods_default
Default value.

Ods_disabled
This value is set if the control is disabled.

Ods_focus
If the control needs to enter focus, set this value.

Ods_grayed
This value is set if the control needs to be dimmed. This value is used only when the menu is drawn.

Ods_hotlight
Windows 98/Me, Windows 2000/XP: If the mouse pointer is placed above the control, this value is set, and the control displays a highlighted color.

Ods_inactive
Windows 98/Me, Windows 2000/XP: indicates that no menu item is activated.

Ods_noaccel
Windows 2000/XP: whether the control has a quick keyboard.

Ods_nofocusrect
Windows 2000/XP: do not draw the effect of capturing the focus.

Ods_selected
The selected menu item.

Hwnditem
Specifies the window handle of the Self-painted control, such as the combo box, list box, And button. If the self-painted object is used as a menu item, it indicates the menu handle that contains the menu item.

HDC
Specifies the device environment Used for the painting operation.

Rcitem
Specifies the area of the rectangle to be drawn. The rectangular area is the scope of the above HDC. The system will automatically crop parts outside the self-drawn Area of the control, such as the combo box, list box, or button. That is to say, the coordinate point (0, 0) in rcitem refers to the upper left corner of the control. However, the system does not crop a menu item. Therefore, when creating a menu item, you must first obtain the position of the menu item through a certain conversion to ensure that the painting operation is performed in the desired area.

Itemdata
For menu items, the value of this Member can be

Cmenu: appendmenu,
Cmenu: insertmenu or
Cmenu: modifymenu

The value passed to the menu by other functions.

For the list box or the combo box, the value of this Member can be

ComboBox: addstring,
Ccombobox: insertstring,
Clistbox: addstring or
Clistbox: insertstring

The value passed to the control.

If the value of ctltype is odt_button or odt_static, the value of itemdata is 0.

This article from the csdn blog, reproduced please indicate the source: http://blog.csdn.net/cug_stu/archive/2010/11/15/6010966.aspx

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.