Getting started with understanding the knowledge of MFC through small exercises-passing values between parent and child windows, changing the color of listctrl lines, dual buffering technology to solve control flickering, custom messages, etc.

Source: Internet
Author: User

Modify again

Modification

NOTE: For the modification content, see the end of the article.

Knowledge points learned in this exercise:

1. listctrl control: Set the listctrl grid, change the color of the content item across rows, insert a row of data, delete the data, select the entire row, and use dual-buffer technology to solve the flickering problem ..

2. Use of modal dialog box and non-Modal Dialog Box

3. Pass values between parent and child windows

 
If the dialog box is modalProgramThe execution of the original program is suspended until the modal window is closed. The non-modal mode is displayed directly, and the original program continues to execute the following statements, and other windows are also available.

Title: Use of MFC Data Structures

Requirements:

1. In the dialog box, use clistctrl, report style, and radio mode. The table consists of two columns: the first column name "title" and the second column name "content ".

2. Click "add" to bring up the new dialog box as shown in. After entering the information, click "OK" to add it to the list.

Note:: The "title" column in the list must be unique.

3. Click "delete" to delete the row from the list.

Note:: After deletion, the current row is moved down. However, if the last row is deleted, the current row is still the last row.

4. Click "query. In the displayed non-mode dialog box, enter "title" and click "Search". The system automatically displays the "content" corresponding to the "title" in the clistctrl list ".

Note:: As shown in the dialog box, a non-mode dialog box is required. You can click the search button multiple times to display only one Search dialog box.

Uses the (ing) Data Structure cmapstringtosting.

5. Click "send" to bring up the new dialog box as shown in. Import the contents in the clistctrl list in the Exercise 2 dialog box to the list of the new dialog box. The style of the new dialog box must be consistent with that of the "Exercise 2" dialog box.

The first version has been detected, and many problems have emerged. For example, each time a new space is added, and the program is deleted only once, the memory leakage can be imagined. In addition, the singleton mode of the first version is designed to be quite non-physical, with allocation but not release.

 
// Singleton Mode Static cfinddatadlg * getinstance () {// problem: the instance is not released in the corresponding location, causing memory leakage // If (null = m_pinstance) // {// m_pinstance = new cfinddatadlg; //} // return m_pinstance; static cfinddatadlg DLG; // you do not need to manage the memory return & DLG after such a change ;}

In addition, the class constructor, copy constructor, destructor, and value assignment operator overload must be private to avoid beingCodeCalled.

 
PRIVATE: cfinddatadlg (cwnd * pparent = NULL); cfinddatadlg (cfinddatadlg &); Virtual ~ Cfinddatadlg (); cfinddatadlg operator = (const cfinddatadlg &);

For more information about the singleton mode design, seeHttp://blog.csdn.net/boyhailong/article/details/6645681

About custom message passing

Send custom messages to the parent window

Getparent ()-> sendmessage (wm_usrmsg_add, wparam (& m_strtitle), lparam (& m_strcontent); // the length of an integer is the same as that of a pointer, so it is no problem to pass a pointer.

 
Lresult cexercise3dlg: onadddata (wparam, lparam) // custom message step 3 {// cstring strsrc = m_pdlgadddata-> gettitle (); // previously, this method was relatively rigid. cstring strtitle = * (cstring *) wparam; // This method is more flexible. // equivalent to cstring pstrtitle = (cstring *) wparam; cstring strcontent = * (cstring *) lparam ;}

Custom message processing steps:

1: Specify the sender and receiver. In this example, the main window is the receiver, and the addition window is the sender.

2: add it to the sender's header file

 
# Define wm_usrmsg_add (wm_user + 100) // custom message Step 1

Wm_usrmsg_add is defined by the user

3: declare the message Response Function in the receiver header file.

// Message response, add data custom message step 2afx_msg lresult onadddata (wparam, lparam); declare_message_map ()

4: Message ing

 
Begin_message_map (cexercise3dlg, cdialog) //} afx_msg_mapon_message (wm_usrmsg_add, onadddata) on_message (wm_usrmsg_find, onfinddata) end_message_map ()

5. Define the custom message Response Function in the implementation file (CPP) of the receiver.

 
Lresult cexercise3dlg: onadddata (wparam, lparam) // custom message step 3 {... // implement function}

6: Send messages in the code segment of the message to be sent in the sender's implementation file (CPP)

 
// This-> sendmessage (wm_usrmsg_add,); // custom message Step 4 // send a message to the parent window instead of to yourself, So thisgetparent () should not be used () -> sendmessage (wm_usrmsg_add, wparam (& m_strtitle), lparam (& m_strcontent ));

How is it? It's easy to customize messages. Here we need to remind you of the difference between sendmessage and postmessage:

 
Postmessage is only responsible for placing messages in the message queue. It is not sure when and whether to process sendmessage. It must wait for the response code (DWORD type) to receive the message) after the postmessage is executed, the system returns the sendmessage immediately. The message will not be returned until the message is processed.
  
 
Note: Do not pass a temporary variable pointer through postmessage. It is very likely that the variable has been destroyed when the message is processed, and an error will occur during access.

When the listctrl control is not selected, the delete button should be unavailable and available when selected, and ask whether to delete it. If no row is selected, the delete button becomes unavailable again.

Add Message Processing nm_click

 
Void cexercise3dlg: onnmclicklist (nmhdr * pnmhdr, lresult * presult) {// todo: add the control notification handler code here * presult = 0; lpnmitemactivate pnmitem = reinterpret_cast <lpnmitemactivate> (pnmhdr); If (-1 = pnmitem-> iItem) // The row number {getdlgitem (idc_btn_del) of the currently selected row is) -> enablewindow (false);} else {getdlgitem (idc_btn_del)-> enablewindow (true );}}

There are two problems in the modified version:

First, when the "Search" dialog box is opened, the content of listctrl in the main window has been copied to the member variables of the Search Class. At this time, the value passed by listctrl has been determined, when "add" is enabled, the newly added content cannot be passed into the "Search" class, so the newly added value cannot be correctly searched. This is also the case with the delete operation.

The second is to open the search window in a simpler and easier-to-understand way, that is, to find the data members of the class defined as the main window, combined with create (), iswindowvisible (), domodal () and setfocus () functions ensure that only one instance is displayed at a time.

Create () in the constructor of the main window ();

M_dlgfinddata.create (idd_dialog_find, this );

Next, add the following code to the corresponding function:

 
If (! M_dlgfinddata.iswindowvisible () // if the window is not currently displayed in {int ncount = m_lstctrl.getitemcount (); // cmapstringtostring mapstsdata; // For (INT I = 0; I <ncount; ++ I) // mapstsdata [m_lstctrl.getitemtext (I, 0)] = m_lstctrl.getitemtext (I, 1); // combine (mapstsdata); Combine (& m_maplstdata ); m_dlgfinddata.showwindow (true); m_dlgfinddata.setfocus ();} else {m_dlgfinddata.setfocus (); // sets the current focus}

Solution to problem 1:

Method 1: You can change the Add window to the modal mode (New-> Create-> showwindow), and use the domodal method to ensure that the search operation cannot be performed during the add operation. After a new piece of data is added, the data is updated in the listctrl control. When you perform the search operation, the member variables of the Search Class are updated to update the data before searching. This ensures that the program has no errors. This method is the easiest and most convenient. You can modify the code on your own.

Method 2: Call in non-modal mode. The general idea is to define a data member in the main window (parent window) class to update the content of listctrl in real time, when the add or delete operation is executed, the data member is updated accordingly. When performing the search operation, pass the pointer of the data member in the main window to the class corresponding to the search window (subwindow) (define a data member pointer of the corresponding type in the search class ), the real-time data of the main window is used directly when data is retrieved. This method is more efficient than the previous method of copying the listctrl content of the main window. It is simple, secure, and easy to understand, and saves a lot of memory space. This is especially evident when a large amount of data is transferred. Therefore, ajioy strongly recommends this method.

 
// Query void cexercise3dlg: onbnclickedbtnquery () {// do I need to use the singleton mode? If (null = m_pdlgfinddata) {m_pdlgfinddata = cfinddatadlg: getinstance (); cmapstringtostring mapstsdata; int ncount = Hangzhou (); For (INT I = 0; I <ncount; ++ I) {mapstsdata [m_lstctrl.getitemtext (I, 0)] = m_lstctrl.getitemtext (I, 1);} // m_pdlgfinddata-> setmapdata (mapstsdata); // inefficient, m_pdlgfinddata-> setmapdata (& m_maplstdata) is not recommended; // very efficient, simple, secure, and easy to understand m_pdlgfinddata-> Create (idd_dialog_find, this );} else {m_pdlgfinddata-> setfocus ();} m_pdlgfinddata-> showwindow (true );}
Void cfinddatadlg: setmapdata (const cmapstringtostring * mapdata) {// int_ptr ncount = mapdata. getsize (); // const cmapstringtostring: cpair * pcurval; // pcurval = mapdata. pgetfirstassoc (); // while (null! = Pcurval) // {// m_mapstsdata [pcurval-> key] = pcurval-> value; // pcurval = mapdata. pgetnextassoc (pcurval); //} m_pmapstsdata = mapdata; // the efficiency and performance of pointer switching are both improved, and the memory overhead is also reduced}

Remember to define data member variables in the cfinddatadlg. h header file

 
Const cmapstringtostring * m_pmapstsdata; // content in clistctrl of the parent window

Complete

Source Code address: http://download.csdn.net/detail/ajioy/5241570 (the first version, can download the contrast modified version for learning)

Http://pan.baidu.com/share/link? Author ID = 471517 & UK = 805795666 (modified version, high code quality)

http://pan.baidu.com/share/link? Consumer id = 472397 & UK = 805795666 (final version, high quality)

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.