Read text from edit control in MFC and VS2010 - c++

I'm writing a simple MFC application with a Dialog window and some buttons.
I added also a edit control in order to let user insert a text string.
I'd like to read the value which is present in the edit control and to store it in a string but i do not know how to do this.
I have no compilation error, but I always read only a "." mark.
I added a variable name to the text edit control which is filepath1 and this is the code:
// CMFC_1Dlg dialog
class CMFC_1Dlg : public CDialogEx
{
// Construction
public:
CMFC_1Dlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_MFC_1_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedButton1();
afx_msg void OnBnClickedButton2();
afx_msg void OnEnChangeEdit1();
CString filePath1;
}
//...
void CMFC_1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialogEx::OnSysCommand(nID, lParam);
}
}
CMFC_1Dlg::CMFC_1Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CMFC_1Dlg::IDD, pParent)
,filePath1(("..\\Experiments\\Dirs\\"))
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CMFC_1Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, filePath1);
}
// then i try to get the string value with
CString txtname=filePath1;
_cprintf("Value %s\n", txtname); // but i always read just a "."

_cprintf("Value %S\n", txtname.GetString());
Note the capital 'S'
or you can cast:
_cprintf("Value %S\n", (LPCTSTR)txtname);
You would be better off using an edit control. To create a CEdit variable, right click on the edit box in VS and select "Add Member Variable", give the variable a name and click OK.
You can then retrieve the text in the edit box like this:
CEdit m_EditCtrl;
// ....
CString filePath1;
m_EditCtrl.GetWindowText(filePath1);

I think your original code was OK for DDX use and CString. The advice to use a control variable and avoid the DDX/DDV functions is really one of preference and not the issue.
I suspect you are compiling with the UNICODE libraries but explicitly calling an ASCII function _cprintf. UNICODE is held as two bytes, for ASCII characters one of these will be 0. If you pass this to an ASCII string function it will stop after the first character.
If you are using UNICODE then call _cwprintf or use the tchar.h macro _tcprintf which will call the correct version for the compiler switch.
Tip: If you are targeting UNICODE only and will never require MBCS support then avoid using the tchar.h macros as they will obscure any issues with char and TCHAR data type mixing.

Step 1: Create a CEdit control variable using "Add Variable List".
Step 2: Use GetDlgItemText() to hold the text of that edit control.
Example: such as CEdit control list variable is mc_strChatPane, then GetDlgItemText(mc_strChatPane, message) where message is a user defined CString variable.

Related

How to change the background color of a CFiledialog (2)

Tools : Visual Studio 2019, MFC, cpp
I'm looking for how to change the background color for the CFileDialog dialog box. I found this link ==> Q115087: HOWTO: Change the Background Color of a Common Dialog.
I have extracted this code and insert it all into my project then two files mydlg.h and mydlg.cpp. I replace the CFileDialog object with mydlg.
This the code included:
Header file ==> mydlg.h
//
#include <dlgs.h>
#define BACKGROUNG_COLOR RGB(0, 0, 255)
//////////////////////////////////////////////////////////////////////
// CMyDlg dialog
class CMyDlg : public CFileDialog
{
// Construction
public:
CMyDlg(CWnd* pParent = NULL); // standard constructor
// Add a CBrush pointer to store the new background brush
CBrush m_pBkBrush;
// Dialog Data
//{{AFX_DATA(CMyDlg)
enum { IDD = FILEOPENORD };
// NOTE: the ClassWizard will add data members here
//}}AFX_DATA
// Implementation
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Generated message map functions
//{{AFX_MSG(CMyDlg)
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
Code file CMyDlg.cpp
CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/): CFileDialog(TRUE, NULL, NULL, OFN_HIDEREADONLY)
{
//{{AFX_DATA_INIT(CMyDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
}
void CMyDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMyDlg)
// NOTE: the ClassWizard will add DDX and DDV calls here
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMyDlg, CFileDialog)
//{{AFX_MSG_MAP(CMyDlg)
ON_WM_CTLCOLOR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////////////
// CMyDlg message handlers
HBRUSH CMyDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
m_pBkBrush.CreateSolidBrush(BACKGROUNG_COLOR);
switch (nCtlColor) { // ==> breakpoint here
case CTLCOLOR_STATIC:
{
// Set the static text to white on blue.
pDC->SetBkColor(BACKGROUNG_COLOR); return (m_pBkBrush);
}
case CTLCOLOR_DLG: return (m_pBkBrush);
default: return CFileDialog::OnCtlColor(pDC, pWnd, nCtlColor);
}
How i call it
CMyDlg FileOpenDialog(TRUE,NULL,local_File,OFN_FILEMUSTEXIST |
OFN_HIDEREADONLY|OFN_PATHMUSTEXIST,
OpenFilter, // filter
AfxGetMainWnd()); // the parent window
CString local_string= Current_Dir();
FileOpenDialog.m_ofn.lpstrInitialDir = local_string;
status = Mess.LoadString(IDS_STRING191);
FileOpenDialog.m_ofn.lpstrTitle = Mess;
if (FileOpenDialog.DoModal() == IDOK)
{
pszSource = FileOpenDialog.m_ofn.lpstrFile;
return true;
}
return false;
Compilation OK
Observation the background color does not change
When i put a stop point on the switch in the function OnCtlColor we do not pass there.
Have you an idea, can you help me?
Thank you
Have you read this article How To Change the Background Color of a Common Dialog Q117778 - does not work where it says:
Changing the background colour of a standard File dialog seems to be possible but requires more steps than in case of a simple dialog.
If it is absolutely crucial to change the colour and no simpler solutions, then consider this summary:
Derive a class from CFileDialog.
In the constructor, get the value of m_ofn.lpfnHook and store to a variable. Write to m_ofn.lpfnHook an address of a new hook procedure. The new hook procedure will call the old one.
In the new hook procedure, intercept the WM_INITDIALOG message and do this: get the parent HWND and get the GWL_WNDPROC value (the old window procedure) of the parent and store it in a variable. Replace this procedure with a new window procedure. The new window procedure will call the old one.
In the new window procedure, intercept the WM_CTLCOLORDLG message and proceed as explained in documentation and above posts.
The linked conversation thread is dated 2009 which is more recent that your linked tutorial.

I am extending CTabCtrl but but cant insert any tabs

I am extending CTabCtrl but when I call InsertItem on my extended object none tab gets inserted. Who knows why is that. What do I do wrong?
class MyTabControl : public CTabCtrl
{
public:
MyListControl m_listCtrl;
void switchInterface(IDataProvider *provider);
public:
MyTabControl();
~MyTabControl();
afx_msg void OnGetDispInfo(NMHDR *pNMHDR, LRESULT *pResult);
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
DECLARE_MESSAGE_MAP()
};
If I remove ON_WM_CREATE() macro from message map then I can add tabs. Implementation of OnCreate function contains m_listCtrl.Create() function call and return 0 if list control is created successfully. What is wrong with this?
The CTabCtrl class is terribly old and poorly functional; you will have to do all the showing/hiding logic of controls when user is switching from one tab to another by your own hand. I recommend you to extend from CMFCTabCtrl instead.

C++/MFC Error accessing control's variable

I created a control's variable for CEdit:
class CGateDlg : public CDialog
{
...
public:
// here is my control's variable
CEdit m_edit_a;
// here I map variable to control
virtual void DoDataExchange(CDataExchange* pDX);
}
And this is how I map my variable to the control:
void CGateDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_A, m_edit_a);
}
This is how it works: user types some text into the edit box. Then he presses the "Reset" button which clears the edit box. This is a piece of code responsible for clearing edit box after clicking Reset button:
void CGateDlg::OnBnClickedReset()
{
// clear edit box
m_edit_a.SetWindowTextW(L"");
}
Application starts without any errors. I type some text into EditBox and hit "Reset" button. Then I get an error which leads me to winocc.cpp, line 245 (ENSURE(this)):
void CWnd::SetWindowText(LPCTSTR lpszString)
{
ENSURE(this);
ENSURE(::IsWindow(m_hWnd) || (m_pCtrlSite != NULL));
if (m_pCtrlSite == NULL)
::SetWindowText(m_hWnd, lpszString);
else
m_pCtrlSite->SetWindowText(lpszString);
}
I think the problem is with the hWnd:
this 0x0030fa54 {CEdit hWnd=0x00000000} CWnd * const
but how to fix it ?
Everything works fine when I access my control's value using this:
CEdit *m_edit_a;
m_edit_a = reinterpret_cast<CEdit *>(GetDlgItem(IDC_EDIT_A));
m_edit_a->SetWindowTextW(L"");
What am I doing wrong ?
I can see two possibilities:
The control does not exist when the dialog starts. The first thing that CDialog::OnInitDialog will do is call DoDataExchange, so if you're creating the control later in the initialization process it's too late.
Your own OnInitDialog is not calling CDialog::OnInitDialog so DoDataExchange is not being called.
I think you should no use directly the meber of your control (in this case m_edit_a). Instead you should use a memeber variable, let's say CStrimg m_edit_data, and you should link it to the control:
DDX_Text(pDX, IDC_EDIT_A, m_edit_data); // as you did it in DDC_Cotrol
Now you can use directy the variable, but in order the control to be updated you should use the following code before using it:
UpdateData(true); // unlocks the control in a sense
m_edit_data = "this is my test";
UpdateData(false); // locks the control again (in a sense)
This is normal procedure in MFC :), hope I helped...
ohh... you should also add the control to String Table ... (let me know if you do not know)
I can not find something wrong with you. I Create a new project using VC6.0,and associate a variable to the Edit,just link you do. the exe operates normally.
class CEditTestDlg : public CDialog
{
// Construction
public:
CEditTestDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CEditTestDlg)
enum { IDD = IDD_EDITTEST_DIALOG };
CEdit m_Edit;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CEditTestDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
......
.cpp
void CEditTestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CEditTestDlg)
DDX_Control(pDX, IDC_EDIT1, m_Edit);
//}}AFX_DATA_MAP
}
void CEditTestDlg::OnBnClickedReset()
{
// TODO: Add your control notification handler code here
m_Edit.SetWindowText("tttt");
}
so,I think it is not a code problem.You had better try again.
If your dialog starts off calling CDialog::OnInitDialog() and your DoDataExchange starts off calling CDialog::DoDataExchange but still you have null hWnd pointers and get CNotSupportedException, make sure your resource (rc) file's dialog template includes all the controls (IDC_) and such you have in DoDataExchange.
Check for overriding definitions if using a DLL that also provides resources.

Can't get the handle of a Cwnd Class in MFC Windowless Activex?

I have asked two questions earlier about this and for each post there was some solutions i tried them, but the problem still exist.
My first question was : why a windowless Activex does not return the Handle. the suggestion was "change the creation setting an make windowless activate off, i have tried it but still m_hWnd property has returned zero as GetSafeHwnd() method has did.
the second one was the same question this one focused on COleControl class and it's ancestor CWnd. the solution was as this "Create invisible window somewhere in your control initialization code. Handle the messages sent to this window, and call controls methods directly". so i did that but the created class still returns zero handle.
here is my new invisible class source:
// moWind.cpp : implementation file
//
#include "stdafx.h"
#include "PINActive.h"
#include "moWind.h"
#include "include\xfspin.h"
#include <math.h>
// moWind
IMPLEMENT_DYNAMIC(moWind, CWnd)
moWind::moWind(){}
moWind::~moWind(){}
//=============================================================
LRESULT moWind::OnExecuteEvent (WPARAM wParam, LPARAM lParam)
{
WFSRESULT *pResult = (WFSRESULT *)lParam;
CString EK=_T("");
CString str;
int reskey=0;
if (pResult->u.dwEventID=WFS_EXEE_PIN_KEY)
{
LPWFSPINKEY pressedkey;
pressedkey=(LPWFSPINKEY)pResult->lpBuffer;
reskey = log10((double)pressedkey->ulDigit) / log10((double)2);
EK.Format("%d",reskey);
xfsOnKeyEvent->OnKeyRecieved(reskey);
}
else
{
str.Format("ExecuteEvent: ID = %d\r\n", pResult->u.dwEventID);
}
MessageBox("a Execute message Recieved");
return 0;
}
BEGIN_MESSAGE_MAP(moWind, CWnd)
ON_MESSAGE(WFS_EXECUTE_EVENT,OnExecuteEvent)
END_MESSAGE_MAP()
and this is .h file of the class:
// moWind.h
class IXFSEvents
{
protected:
IXFSEvents(){};
virtual ~IXFSEvents(){};
public:
virtual void OnKeyRecieved(int key)=0;
};
class moWind : public CWnd
{
DECLARE_DYNAMIC(moWind)
public:
moWind();
virtual ~moWind();
void Register(IXFSEvents* obj)
{
xfsOnKeyEvent= obj;
}
protected:
IXFSEvents* xfsOnKeyEvent;
LRESULT OnExecuteEvent (WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
};
and at the end here this the way I've used this class in my Activex:
in the myActivex.h file:
include "moWind.h"
class CmyActivexCtrl : public COleControl, public IXFSEvents
{
...
Class definition
...
protected:
moWind tmpWind;
.
.
};
finally in the creation method of myActivex i have initialized the component callback method an wanted to get it's Handle as this:
CmyActivexCtrl::CmyActivexCtrl()
{
InitializeIIDs(&IID_DmyActivex, &IID_DmyActivexEvents);
tmpWind.Register(this);
myOtherComponent.WindowsHandle=tmpWind.GetSafeHwnd(); //here my Cwnd derived class returns zero
//my other component gets the handle and call an API with it to register
//the given handle and force the API to send the messages to that handle.
}
As you mentioned you need a window handle to be able to receive user messages through it, you always have an option of creating a helper window, such as message only window, see Using CreateWindowEx to Make a Message-Only Window.
For your windowless control it is okay to not have any window handle at all, so you cannot really rely on handle availability unless you own a window yourself.

How do I add an edit box to MFC CFolderDialog ("browse for folder" dialog)?

I currently have a CFolderDialog class that is used in my CDocManagerEx class for handling file operations as follows:
alt text http://img268.yfrog.com/img268/9271/filedialog.png
I don't know if I need to show the method implementation of this class (I found this from a project posted here), but here is the class definition if it helps:
class CFolderDialog
{
friend static int CALLBACK BrowseDirectoryCallback(
HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData);
public:
CFolderDialog( LPCTSTR lpszFolderName = NULL,
DWORD dwFlags = NULL/*BIF_RETURNONLYFSDIRS*/,
CWnd* pParentWnd = NULL);
virtual ~CFolderDialog();
virtual int DoModal();
CString GetPathName() const;
protected:
virtual void OnInitDialog();
virtual void OnSelChanged(ITEMIDLIST* pIdl);
virtual void CallbackFunction(HWND hWnd, UINT uMsg, LPARAM lParam);
void EnableOK(BOOL bEnable = TRUE);
void SetSelection(LPCTSTR pszSelection);
void SetSelection(ITEMIDLIST* pIdl);
void SetStatusText(LPCTSTR pszStatusText);
CString ShortName(const CString& strName);
public:
BROWSEINFO m_bi;
protected:
CString m_strInitialFolderName;
CString m_strFinalFolderName;
TCHAR m_szDisplayName[MAX_PATH];
TCHAR m_szPath[MAX_PATH];
HWND m_hDialogBox;
};
class CMyFolderDialog : public CFolderDialog
{
public:
CMyFolderDialog(LPCTSTR lpszFolderName = NULL,
DWORD dwFlags = NULL,
CWnd* pParentWnd = NULL,
LPCTSTR pszFileFilter = NULL);
virtual ~CMyFolderDialog();
protected:
virtual void OnSelChanged(ITEMIDLIST* pIdl);
protected:
CString m_strFileFilter;
};
My goal of this question is adding an edit control to the window just below the workspace where the directory is selected. What would be the easiest way to accomplish this?
If you just want an edit control that allows the user to type in the name of a directory entry, that is possible. The C++ class you're using is a wrapper round the Win32 SHBrowseForFolder() method, and that method supports having an edit box by setting the BIF_EDITBOX (or better, BIF_USENEWUI) in the ulFlags member of the BROWSEINFO structure.
Looking at the C++ class, it looks like the simplest way to achieve this will be to pass BIF_USENEWUI as the dwFlags member in the constructor call. (Though I'd be tempted to just call SHBrowseForFolder directly and not bother with the C++ class.)
Do note the warning about this flag in MSDN, though: OleInitialize() or CoInitialize() must have been called before bringing up the dialog with this flag.
More generally, if you want an edit control that you can use for your own purposes, allowing the user to enter anything, that's more of a problem: there's no way to extend the dialog used by SHBrowseForFolder() with custom controls. If you want to do that, you'd end up having to re-implement the whole dialog, which isn't a good idea.
Also, as a final note, if you can limit yourself to Vista (and beyond) then there's another way to have a directory selection dialog: use the new IFileDialog COM interface, with the FOS_PICKFOLDERS flag.
Maybe some of the ideas in this will do what you want?
http://www.codeproject.com/KB/dialog/browse_for_folder_dialog.aspx
or this
http://www.codeguru.com/cpp/w-p/files/browserfunctionsdialogs/article.php/c4443