简体   繁体   中英

Adding edit box to ATL dialog using ATL CEdit in CAxDialogImpl

I have project on ATL(C++) VS2010. I have created a dialog class. With two buttons and want to add something like a textbox. I have read that is responsible for this component CEdit.

CEdit* pEdit = (CEdit*)GetDlgItem(IDC_EDIT1);

1. But nowhere referred to as resource declare IDC_EDIT1.

2. It is necessary to connect afxwin.h. I plugged in the library in stdafx.h on top.

It has issued me an error:

Building MFC application with /MD[d] (CRT dll version) requires MFC
shared dll version. Please #define _AFXDLL or do not use /MD[d]

I thought that problem this. error Please #define _AFXDLL or do not use /MD[d] occurs even after making changes in Project Properties

Then I got an error:

#error directive: WINDOWS.H already included. MFC apps must not #include

I deleted all references WINDOWS.H, but the error remained.

Is there a solution without using CEdit.

CWindow textBox(GetDlgItem(IDC_EDIT1));
textBox.SetWindowTextW(L"hello");

But the question remains. As a resource to specify IDC_EDIT1? In general, where it should be specified, as stated, is there any examples. I could not find anything. Maybe because of my bad English.

I add in Resource.h

#define IDC_EDIT1                       113

In file .rc i have two button:

DEFPUSHBUTTON   "OK",IDOK,209,179,50,14
PUSHBUTTON      "Cancel",IDCANCEL,263,179,50,14

How add my IDC_EDIT1 in file .rc?

????     "text",IDC_EDIT1,263,179,50,14

According to stackoverflow How to get text from CEdit control the CEdit is not part of the standard ATL from Microsoft but is instead a Windows Template Library (WTL) extension .

It appears that the listview and the treeview common controls do have ATL support from Microsoft.

From the errors you mention, it sounds like you are pulling MFC components into your build along with MFC related properties in your solution. You need to check that you are only using ATL includes and properties and libraries in your build. Check your standard include file stdafx.h is using ATL includes.

Here is some source code to consider. This is from a sample application I have been doing using ATL which displays a simple dialog box with a listview control with two columns showing data from a key in the Windows Registry. The dialog allows the user to double click on a particular row of the listview control and it then takes the value associated with the string value key and allows the string value value to be edited.

I am using wchar_t and std::wstring to hold my text data since the Windows API is all wide characters.

The .rc file contains the following dialog template. I used the standard dialog design tools available in Resource View of Visual Studio to drop controls on the dialog and modify their properties. I also used the dialog design tool to add event handlers for button click and other events. The tool will add the event handling skeleton to the source files and update the message map.

IDD_PROVDIALOG DIALOGEX 0, 0, 224, 209
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Provision control"
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,167,7,50,16
    PUSHBUTTON      "Cancel",IDCANCEL,167,26,50,16
    CONTROL         "",IDC_LIST1,"SysListView32",LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,154,155
    EDITTEXT        IDC_EDIT_PROP,7,179,154,23,ES_MULTILINE | ES_AUTOHSCROLL
    PUSHBUTTON      "Save",IDC_BUTTON_SAVE,179,180,38,22
END

The listview of the dialog is filled in and the dialog presented to the user. I then have the following two event handlers. The first event handler is for when the Save button is clicked. The second event handler is for when the user double clicks on a row, actually the first column, of the listview control.

The data is stored in an ATL simple map and when the dialog is created we provide a pointer to the map. So the dialog has a pointer to the Registry data as CSimpleMap <std::wstring, std::wstring> *m_RegistryData;

Here is the Save button click event handler which pulls the text from the edit control and updates data map. Once the data map is updated then we tell the listview to update itself.

LRESULT CProvDialog::OnBnClickedButtonSave(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL & bHandled)
{
    CWindow pEdit = GetDlgItem (IDC_EDIT_PROP);

    int iTextSize = pEdit.GetWindowTextLength ();
    if (iTextSize > 0 && m_EditKey.length () > 0) {
        wchar_t myText[128];
        pEdit.GetWindowText(myText, 127);
        m_RegistryData->SetAt (m_EditKey, myText);

        m_EditKey.clear();            // clear the key area since we have done an update
        pEdit.SetWindowText (L"");    // clear the edit box before returning for user feedback.

        CWindow pListView = GetDlgItem(IDC_LIST1);  // Get the listview control window handle
        pListView.RedrawWindow(NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
    }
    bHandled = TRUE;
    return 1;
}

To be complete here is the handler for the double click in the listview control. This does a basic sanity check to make sure the double click is valid and then using the row number of the double clicked row, this is a zero based value, we pull the key and the value from the corresponding row of the map data structure. We save the key so that we can do an update later and we put the value associated with the key into the edit box.

The use of a reinterpret_cast is from using an example from the Microsoft MSDN library examples. For a discussion on reinterpret_cast see stackoverflow When to use reinterpret_cast?

LRESULT CProvDialog::OnNMDblclkList1(int idCtrl, LPNMHDR pNMHDR, BOOL & bHandled)
{
    // Handle a double click in the listview control.
    //   "The iItem, iSubItem, and ptAction members of this
    //    structure [NMITEMACTIVATE] contain information about the item."
    LPNMITEMACTIVATE plvdi  = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);

    if (plvdi->iItem >= 0) {
        // we have a valid listview row number so lets update our edit box
        CWindow pEdit = GetDlgItem (IDC_EDIT_PROP);

        pEdit.SetWindowText (m_RegistryData->GetValueAt(plvdi->iItem).c_str());
        m_EditKey = m_RegistryData->GetKeyAt(plvdi->iItem);
    }

    bHandled = TRUE;
    return 1;
}

As a side note, here is a bit of source needed to allow for the display of a multi-column listview . The control needs to have the Details view turned on and so to make sure that a multi-column view is enabled, I use the following code during the initialization of the dialog box and its components.

// First of all lets make sure that the listview is in Details or Report style.
// If the control is not in Details or Report style then even though we add columns
// only the first column will be displayed.  Multiple columns only available in Details view.
ULONG  ulWinStyle = pListView.GetWindowLong (GWL_STYLE);
ulWinStyle |= LVS_REPORT;
pListView.SetWindowLong (GWL_STYLE, ulWinStyle);

The listview control is created by the following piece of source in the dialog initialization. We are using LPSTR_TEXTCALLBACK along with a handler for the NMLVDISPINFOW message to populate the listview control.

// Initialize LVITEM members that are common to all items.
LVITEM lvI = {0};
lvI.pszText   = LPSTR_TEXTCALLBACK; // Sends an LVN_GETDISPINFO message.
lvI.mask      = LVIF_TEXT | LVIF_STATE | LVCF_SUBITEM;
lvI.stateMask = 0;
lvI.state     = 0;

// Initialize LVITEM members that are different for each item.
int iCount = m_RegistryData->GetSize();
for (int index = 0; index < iCount; index++)
{
    // Insert the item row with the first column into the list.
    lvI.iItem  = index;
    lvI.iSubItem  = 0;
    if (ListView_InsertItem (pListView.m_hWnd, &lvI) != -1) {
        // insert the second column into the listview.
        lvI.iSubItem  = 1;
        ListView_SetItem (pListView.m_hWnd, &lvI);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM