| Tenouk C & C++ | MFC Home | IE 4 Common Controls 1 | Win32 Memory Management | Download | Site Index |


 

 

 

 

 

 

Module 19a:

Internet Explorer 4 Common Controls 2

 

 

 

 

 

 

Program examples compiled using Visual C++ 6.0 (MFC 6.0) compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this Tutorial are listed below:

  1. The MYMFC25A Example...a continuation...

 

 Add the CDialog1 variables. Start ClassWizard and click on the Member Variables tab to view the Member Variables page. Enter the following member variables for each control listed.

 

Control ID

Data Member

Type

IDC_DATETIMEPICKER1

m_MonthCal1

CDateTimeCtrl

IDC_DATETIMEPICKER2

m_MonthCal2

CDateTimeCtrl

IDC_DATETIMEPICKER3

m_MonthCal3

CDateTimeCtrl

IDC_DATETIMEPICKER4

m_MonthCal4

CDateTimeCtrl

IDC_IPADDRESS1

m_ptrIPCtrl

CIPAddressCtrl

IDC_MONTHCALENDAR1

m_MonthCal5

CMonthCalCtrl

IDC_STATIC1

m_strDate1

CString

IDC_STATIC2

m_strDate2

CString

IDC_STATIC3

m_strDate3

CString

IDC_STATIC4

m_strDate4

CString

IDC_STATIC5

m_strDate5

CString

IDC_STATIC6

m_strIPValue

CString

IDC_STATIC7

m_strComboEx1

CString

IDC_STATIC8

m_strComboEx2

CString

 

Table 2.

 

Adding the CDialog1 variables.

 

Figure 16: Adding the CDialog1 variables.

 

 

Program the short date time picker. In this example, we don't mind if the first date time picker starts with the current date, so we don't have any OnInitDialog() handling for this control. However, if we wanted to change the date, we would make a call to SetTime() for the control in OnInitDialog(). At runtime, when the user selects a new date in the first date and time picker, the companion static control should be automatically updated.

 

To achieve this, we need to use ClassWizard to add a handler for the DTN_DATETIMECHANGE message. Start ClassWizard (or CTRL-W) and choose IDC_DATETIMEPICKER1 from the Object IDs list and DTN_DATETIMECHANGE from the Messages list. Accept the default message name and click OK. Repeat this step for each of the other three IDC_DATETIMEPICKER IDs. Your ClassWizard should look like the illustration here.

 

Adding a handler for the DTN_DATETIMECHANGE message.

 

Figure 17: Adding a handler for the DTN_DATETIMECHANGE message.

 

Next add the following code to the handler for Datetimepicker1 created by ClassWizard:

 

void CDialog1::OnDatetimechangeDatetimepicker1(NMHDR* pNMHDR, LRESULT* pResult)

{

    CTime ct;

    m_MonthCal1.GetTime(ct);

    m_strDate1.Format(_T("%02d/%02d/%2d"), ct.GetMonth(),ct.GetDay(),ct.GetYear());

    UpdateData(FALSE);

    *pResult = 0;

}

 

 

Listing 1.

 

This code uses the m_MonthCal1 data member that maps to the first date time picker to retrieve the time into the CTime object variable ct. It then calls the CString::Format member function to set the companion static string. Finally the call to UpdateData(FALSE) triggers MFC's DDX and causes the static to be automatically updated to m_strDate1.

Program the long date time picker. Now we need to provide a similar handler for the second date time picker.

 

void CDialog1::OnDatetimechangeDatetimepicker2(NMHDR* pNMHDR, LRESULT* pResult)

{

    CTime ct;

    m_MonthCal2.GetTime(ct);

    m_strDate2.Format(_T("%02d/%02d/%2d"), ct.GetMonth(),ct.GetDay(),ct.GetYear());

    UpdateData(FALSE);

 

    *pResult = 0;

}

 

 

Listing 2.

 

Program the third date time picker. The third date time picker needs a similar handler, but since we set the Show None style in the dialog properties, it is possible for the user to specify a NULL date by checking the inline check box. Instead of blindly calling GetTime(), we have to check the return value. If the return value of the GetTime() call is nonzero, the user has selected a NULL date. If the return value is zero, a valid date has been selected. As in the previous two handlers, when a CTime object is returned, it is converted into a string and automatically displayed in the companion static control.

 

void CDialog1::OnDatetimechangeDatetimepicker3(NMHDR* pNMHDR, LRESULT* pResult)

{

    //NOTE: this one can be null!

    CTime ct;

    int nRetVal = m_MonthCal3.GetTime(ct);

    if (nRetVal) //If not zero, it's null; and if it is,

                 // do the right thing.

    {

        m_strDate3 = "NO DATE SPECIFIED!!";

    }

    else

    {

        m_strDate3.Format(_T("%02d/%02d/%2d"),ct.GetMonth(),ct.GetDay(),ct.GetYear());

    }

    UpdateData(FALSE);

    *pResult = 0;

}

 

 

Listing 3.

 

Program the time picker. The time picker needs a similar handler, but this time the format displays hours/minutes/seconds instead of months/days/years:

 

void CDialog1::OnDatetimechangeDatetimepicker4(NMHDR* pNMHDR, LRESULT* pResult)

{

    CTime ct;

    m_MonthCal4.GetTime(ct);

    m_strDate4.Format(_T("%02d:%02d:%2d"), ct.GetHour(), ct.GetMinute(), ct.GetSecond());

    UpdateData(FALSE);

    *pResult = 0;

}

 

 

Listing 4.

 

Program the Month Selector. You might think that the month selector handler is similar to the date time picker's handler, but they are actually somewhat different. First of all, the message you need to handle for detecting when the user has selected a new date is the MCN_SELCHANGE message. Select this message in the ClassWizard, as shown here.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Adding message handler for IDC_MONTHCALENDAR1 ID.

 

Figure 18: Adding message handler for IDC_MONTHCALENDAR1 ID.

 

In addition to the different message handler, this control uses GetCurSel() as the date time picker instead of GetTime(). The code below shows the MCN_SELCHANGE handler for the month calendar control.

 

void CDialog1::OnSelchangeMonthcalendar1(NMHDR* pNMHDR, LRESULT* pResult)

{

    CTime ct;

    m_MonthCal5.GetCurSel(ct);

    m_strDate5.Format(_T("%02d/%02d/%2d"), ct.GetMonth(),ct.GetDay(),ct.GetYear());

    UpdateData(FALSE);

    *pResult = 0;

}

 

MFC Visual C++ code segment

 

Listing 5.

 

Program the IP control. First we need to make sure the control is initialized. In this example, we initialize the control to 0 by giving it a 0 DWORD value. If you do not initialize the control, each segment will be blank. To initialize the control, add this call to the CDialog1::OnInitDialog function:

 

m_ptrIPCtrl.SetAddress(0L);

 

MFC Visual C++ code segment

 

Listing 6.

 

Now we need to add a handler to update the companion static control whenever the IP address control changes. First we need to add a handler for the IPN_FIELDCHANGED notification message using ClassWizard, as shown here.

 

Adding a handler for the IPN_FIELDCHANGED notification message using ClassWizard.

 

Figure 19: Adding a handler for the IPN_FIELDCHANGED notification message using ClassWizard.

 

Next we need to implement the handler as follows:

 

void CDialog1::OnFieldchangedIpaddress1(NMHDR* pNMHDR, LRESULT* pResult)

{

    DWORD dwIPAddress;

    m_ptrIPCtrl.GetAddress(dwIPAddress);

 

    m_strIPValue.Format("%d.%d.%d.%d   %x.%x.%x.%x",

        HIBYTE(HIWORD(dwIPAddress)),

        LOBYTE(HIWORD(dwIPAddress)),

        HIBYTE(LOWORD(dwIPAddress)),

        LOBYTE(LOWORD(dwIPAddress)),

        HIBYTE(HIWORD(dwIPAddress)),

        LOBYTE(HIWORD(dwIPAddress)),

        HIBYTE(LOWORD(dwIPAddress)),

        LOBYTE(LOWORD(dwIPAddress)));

    UpdateData(FALSE);

    *pResult = 0;

}

 

MFC Visual C++ code segment

 

Listing 7.

 

The first call to CIPAddressCtrl::GetAddress retrieves the current IP address into the local dwIPAddress DWORD variable. Next we make a fairly complex call to CString::Format to deconstruct the DWORD into the various fields. This call uses the LOWORD macro to first get to the bottom word of the DWORD and the HIBYTE/LOBYTE macros to further deconstruct the fields in order from field 0 to field 3.

 

Add a handler for the first extended combo box. No special initialization is required for the extended combo box, but we do need to handle the CBN_SELCHANGE message. The following code shows the extended combo box handler. Can you spot the ways that this differs from a "normal" combo box control?

 

Adding a handler for the first extended combo box, IDC_COMBOBOXEX1.

 

Figure 20: Adding a handler for the first extended combo box, IDC_COMBOBOXEX1.

 

void CDialog1::OnSelchangeComboboxex1()

{

    COMBOBOXEXITEM cbi;

    CString str ("dummy_string");

    CComboBoxEx * pCombo = (CComboBoxEx *)GetDlgItem(IDC_COMBOBOXEX1);

 

    int nSel = pCombo->GetCurSel();

    cbi.iItem = nSel;

    cbi.pszText = (LPTSTR)(LPCTSTR)str;

    cbi.mask = CBEIF_TEXT;

    cbi.cchTextMax = str.GetLength();

    pCombo->GetItem(&cbi);

    SetDlgItemText(IDC_STATIC7,str);

    return;

}

 

MFC Visual C++ code segment

 

Listing 8.

 

The first thing you probably noticed is the use of the COMBOBOXEXITEM structure for the extended combo box instead of the plain integers used for items in an older combo box. Once the handler retrieves the item, it extracts the string and calls SetDlgItemText() to update the companion static control.

 

Add Images to the Items in the second extended combo box. The first extended combo box does not need any special programming. It is used to demonstrate how to implement a simple extended combo box very similar to the older, non-extended combo box. The second combo box requires a good bit of programming. First we created six bitmaps and eight icons that we need to add to the resources for the project, as shown in the following illustration.

 

A complete bitmap and icon set that you have to create.

 

Figure 21: A complete bitmap and icon set that you have to create.

 

Of course, you are free to use any bitmaps and icons.

 

Inserting new resource, a bitmap.

 

Figure 22: Inserting new resource, a bitmap.

 

Selecting the bitmap resource.

 

Figure 23: Selecting the bitmap resource.

 

 

Inserting a new icon.

 

Figure 24: Inserting a new icon.

 

Editing the icon and modifying the properties.

 

Figure 25: Editing the icon and modifying the properties.

 

A completed set of the bitmaps and icons for MYMFC25A project.

 

Figure 26: A completed set of the bitmaps and icons for MYMFC25A project.

 

There are two ways to add our graphics to an extended combo box. The first method is to attach images to existing combo box items. Remember that we used the dialog editor to add the Doremon, Tweety, Mack, etc. items to the combo box. The second method is to add new items and specify their corresponding images at the time of addition.

Before we start adding graphics to the extended combo box, let's create a public CImageList data member in the CDialog1 class named m_imageList. Be sure you add the data member to the header file (Dialog1.h) for the class.

 

Adding a public CImageList data member to the CDialog1 class.

 

Figure 27: Adding a public CImageList data member to the CDialog1 class.

 

Entering the variable type and name.

 

Figure 28: Entering the variable type and name.

 

Now we can add some of the bitmap images to the image list and then "attach" the images to the three items already in the extended combo box. Add the following code to your CDialog1's OnInitDialog() method to achieve this:

 

    //Initialize the IDC_COMBOBOXEX2

    CComboBoxEx* pCombo = (CComboBoxEx*) GetDlgItem(IDC_COMBOBOXEX2);

    //First let's add images to the items there.

    //We have six images in bitmaps to match to our strings:

 

    //CImageList * pImageList = new CImageList();

    m_imageList.Create(32,16,ILC_MASK,12,4);

 

    CBitmap bitmap;

 

    bitmap.LoadBitmap(IDB_BMBIRD);

    m_imageList.Add(&bitmap, (COLORREF)0xFFFFFF);

    bitmap.DeleteObject();

 

    bitmap.LoadBitmap(IDB_BMBIRDSELECTED);

    m_imageList.Add(&bitmap, (COLORREF)0xFFFFFF);

    bitmap.DeleteObject();

 

    bitmap.LoadBitmap(IDB_BMDOG);

    m_imageList.Add(&bitmap, (COLORREF)0xFFFFFF);

    bitmap.DeleteObject();

 

    bitmap.LoadBitmap(IDB_BMDOGSELECTED);

    m_imageList.Add(&bitmap, (COLORREF)0xFFFFFF);

    bitmap.DeleteObject();

 

    bitmap.LoadBitmap(IDB_BMFISH);

    m_imageList.Add(&bitmap, (COLORREF)0xFFFFFF);

    bitmap.DeleteObject();

 

    bitmap.LoadBitmap(IDB_BMFISHSELECTED);

    m_imageList.Add(&bitmap, (COLORREF)0xFFFFFF);

    bitmap.DeleteObject();

 

    //Set the imagelist

    pCombo->SetImageList(&m_imageList);

    //Now attach the images to the items in the list.

    COMBOBOXEXITEM    cbi;

    cbi.mask = CBEIF_IMAGE|CBEIF_SELECTEDIMAGE|CBEIF_INDENT;

    CString strTemp;

    int nBitmapCount = 0;

    for (int nCount = 0;nCount < 3;nCount++)

    {

        cbi.iItem = nCount;

        cbi.pszText = (LPTSTR)(LPCTSTR)strTemp;

        cbi.cchTextMax = 256;

        pCombo->GetItem(&cbi);

        cbi.iImage = nBitmapCount++;

        cbi.iSelectedImage = nBitmapCount++;

        cbi.iIndent = (nCount & 0x03);

        pCombo->SetItem(&cbi);

    }

 

MFC Visual C++ code segment

 

Listing 9.

 

First the extended combo box initialization code creates a pointer to the control using GetDlgItem(). Next it calls Create() to create memory for the images to be added and to initialize the image list. The next series of calls loads each bitmap, adds them to the image list, and then deletes the resource allocated in the load.

CComboBoxEx::SetImageList is called to associate the m_imageList with the extended combo box. Next a COMBOBOXEXITEM structure is initialized with a mask, and then the for loop iterates from 0 through 2, setting the selected and unselected images with each pass through the loop. The variable nBitmapCount increments through the image list to ensure that the correct image ID is put into the COMBOBOXEXITEM structure. The for loop makes a call to CComboBoxEx::GetItem to retrieve the COMBOBOXEXITEM structure for each item in the extended combo box. Then the loop sets up the images for the list item and finally calls CComboBoxEx::SetItem to put the modified COMBOBOXEXITEM structure back into the extended combo box and complete the association of images with the existing items in the list.

Add Items to the Extended Combobox. The other technique available for putting images into an extended combo box is to add them dynamically, as shown in the code added to OnInitDialog() below:

 

    HICON hIcon[8];

    int n;

    //Now let's insert some color icons

    hIcon[0] = AfxGetApp()->LoadIcon(IDI_WHITE);

    hIcon[1] = AfxGetApp()->LoadIcon(IDI_BLACK);

    hIcon[2] = AfxGetApp()->LoadIcon(IDI_RED);

    hIcon[3] = AfxGetApp()->LoadIcon(IDI_BLUE);

    hIcon[4] = AfxGetApp()->LoadIcon(IDI_YELLOW);

    hIcon[5] = AfxGetApp()->LoadIcon(IDI_CYAN);

    hIcon[6] = AfxGetApp()->LoadIcon(IDI_PURPLE);

    hIcon[7] = AfxGetApp()->LoadIcon(IDI_GREEN);

    for (n = 0; n < 8; n++) {

        m_imageList.Add(hIcon[n]);

    }

 

    static char* color[] = {"white", "black", "red",

                            "blue", "yellow", "cyan",

                            "purple", "green"};

 

    cbi.mask = CBEIF_IMAGE|CBEIF_TEXT|CBEIF_OVERLAY|CBEIF_SELECTEDIMAGE;

 

    for (n = 0; n < 8; n++) {

        cbi.iItem = n;

        cbi.pszText = color[n];

        cbi.iImage = n+6; // 6 is the offset into the image list from

        cbi.iSelectedImage = n+6; // the first six items we added...

        cbi.iOverlay = n+6;

        int nItem = pCombo->InsertItem(&cbi);

        ASSERT(nItem == n);

    }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

-------------------------------------------------------------------------------------------------------

MFC Visual C++ code segment screen shot

 

Listing 10.

 

The for loop fills out the COMBOBOXEXITEM structure and then calls CComboBoxEx::InsertItem with each item to add it to the list.

 

Add a handler for the second extended combo box. The second extended combo box handler is essentially the same as the first:

 

Adding a handler for the second extended combo box, IDC_COMBOBOXEX2.

 

Figure 29: Adding a handler for the second extended combo box, IDC_COMBOBOXEX2.

 

void CDialog1::OnSelchangeComboboxex2()

{

    COMBOBOXEXITEM cbi;

    CString str ("dummy_string");

    CComboBoxEx * pCombo = (CComboBoxEx *)GetDlgItem(IDC_COMBOBOXEX2);

    int nSel = pCombo->GetCurSel();

    cbi.iItem = nSel;

    cbi.pszText = (LPTSTR)(LPCTSTR)str;

    cbi.mask = CBEIF_TEXT;

    cbi.cchTextMax = str.GetLength();

    pCombo->GetItem(&cbi);

    SetDlgItemText(IDC_STATIC8, str);

 

    return;

}

 

MFC Visual C++ code segment screen shot

 

Listing 11.

 

Connect the view and the dialog. Add code to the virtual OnDraw() function in mymfc25AView.cpp. The following code replaces the previous code:

 

void CMymfc25AView::OnDraw(CDC* pDC)

{

    pDC->TextOut(30, 30, "Press the left mouse button here.");

}

 

MFC Visual C++ code segment screen shot

 

Listing 12.

 

Use ClassWizard to add the OnLButtonDown() member function to the CMymfc25AView class. Edit the AppWizard-generated code as follows:

 

Adding the OnLButtonDown() member function to the CMymfc25AView class to handle the left mouse click.

 

Figure 30: Adding the OnLButtonDown() member function to the CMymfc25AView class to handle the left mouse click.

 

void CMymfc25AView::OnLButtonDown(UINT nFlags, CPoint point)

{

    CDialog1 dlg;

    dlg.DoModal();

}

 

MFC Visual C++ code segment screen shot

 

Listing 13.

 

Add a statement to include Dialog1.h in file mymfc25AView.cpp.

 

MFC Visual C++ code segment screen shot

 

Listing 14.

 

Compile and run the program. Now you can experiment with the various IE4 common controls to see how they work and how you can apply them in your own applications.

 

MYMFC25A program output.

 

Figure 31: MYMFC25A program output.

 

MYMFC25A program output, full of Internet Explorer 4 common controls.

 

Figure 32: MYMFC25A program output, full of Internet Explorer 4 common controls.

 

 

 

 

 

 

Further reading and digging:

  1. MSDN MFC 7.0 class library online documentation.

  2. MSDN MFC 9.0 class library online documentation - latest version.

  3. MSDN Library

  4. Windows data type.

  5. Win32 programming Tutorial.

  6. The best of C/C++, MFC, Windows and other related books.

  7. Unicode and Multibyte character set: Story and program examples.

 

 

 

 


 

| Tenouk C & C++ | MFC Home | IE 4 Common Controls 1 | Win32 Memory Management | Download | Site Index |