Solved

More Advanced Dialog Problem in VC++

Posted on 2015-02-10
25
164 Views
Last Modified: 2015-02-22
I am working on a dialog with an edit box and a browse button.  The purpose of the dialog is to enable the user to browse to the file on his computer, and when he opens the file he wants, the path and name of the file are to be put into the edit box where it will be used by later software.  I can browse to the file and open it, but I cannot find out how to capture that path and name and place it in the edit box.
Here is the code to open the file (from VS2013 help)
CString fileName;
CFileDailog dlgFile(TRUE);
OPENFILENAME& ofn = dlgFile.GetOFN();
dlgFile.DoModal();
0
Comment
Question by:Dave Shields
  • 10
  • 9
  • 6
25 Comments
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 40602886
GetPathName returns a CString with the path to the selected file

https://msdn.microsoft.com/en-us/library/5b9c3c1f.aspx
0
 
LVL 32

Expert Comment

by:sarabande
ID: 40603197
you need to add a buffer to the ofn where the filename was returned:

const int FILE_LIST_BUFFER_SIZE = MAX_PATH + 1 + 1;  // two extra characters for termination

CString fileName;
LPTSTR p = fileName.GetBuffer( FILE_LIST_BUFFER_SIZE );
CFileDialog dlgFile(TRUE);
OPENFILENAME& ofn = dlgFile.GetOFN( );
ofn.lpstrFile = p;
ofn.nMaxFile = FILE_LIST_BUFFER_SIZE;

dlgFile.DoModal();
fileName.ReleaseBuffer();

Open in new window


note, file dialog also allows multiple selection of files. if that is an option, you need to set

 ofn.Flags |= OFN_ALLOWMULTISELECT;

and increase the buffer size to a multiple of  (MAX_PATH+1).

after fileName.ReleaseBuffer(), you would need to parse the string as it could contain multiple strings where each of them is terminated by a zero character.

Sara
0
 

Author Comment

by:Dave Shields
ID: 40606579
Hi Sara,
Thanks for the reply, I have used your code and the dialog still opens the filesw on my HD.
 However I still cannot get the program to add the pathname which I get as a CString into the edit box control, so that the resulting path shows in the edit box control as if I had typed it in there.  I look forward to your assistance on this.
Dave
0
 

Author Comment

by:Dave Shields
ID: 40606586
my comments above tell the whole story.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 40606618
Did you read my comment?  That is how to get the file path from the dialog.
0
 
LVL 32

Expert Comment

by:sarabande
ID: 40607349
However I still cannot get the program to add the pathname which I get as a CString into the edit box control,

if you added a member variable of CString for the edit box you simply could assign the file name from the OPENFILENAME struct to the member and call UpdateData(FALSE); to put the string from member to screen.

....
dlgFile.DoModal();
fileName.ReleaseBuffer();

m_strFilePath = fileName;  // assuming you have added a member m_strFilePath for the edit box
UpdateData(FALSE);

alternatively you could set the path to the edit text directly:

CWnd * pEdit = GetDlgItem(IDC_EDIT_FILEPATH); // here use the id of the edit box
if (pEdit != NULL)
      pEdit->SetWindowText(fileName);

Open in new window


Sara
0
 

Author Comment

by:Dave Shields
ID: 40608691
Setting the fileName using the member name made the compiler complain that the member was not defined.
but using the pEdit route did the trick in Spades.!!
0
 
LVL 32

Expert Comment

by:sarabande
ID: 40609109
made the compiler complain that the member was not defined
if you right-click in the dialog resource at your edit control you could add a CString member variable for the CEdit. such members would be sent from class to screen by UpdateData(false) und got from screen to member by UpdateData(true).

Sara
0
 

Author Comment

by:Dave Shields
ID: 40611349
When I constructed the dialog box I added member variables to all edit controls.  The name of the one we have worked on is "m_editbox_HD".  When I work on button actions, I work inside autocreated MFC functions.  Inside this it does not recognize "m_editbox_HD"  AND it complains if I try to call it CSdiDialog.m_editbox_HD.  The functions are double void type - return void and do nat take any parameters.  Before I can continue I need to set up the ANALYZE button to use the text from m_editbox_HD variable and call the analyze funtion with the CString as a parameter.

If you have a solution for this please reply with the sample code.
0
 
LVL 32

Expert Comment

by:sarabande
ID: 40611999
I added member variables to all edit controls.
when adding members you can choose between members for the controls and members for the data. you also can have both. the data member would be  a CString member that can be exchanged by calling UpdateData member function. the UpdateData uses the generated DoDataExchange function to subclass the controls, and exchange from member to screen and screen to member.


Inside this it does not recognize "m_editbox_HD"
if m_editbox_HD is a member of your dialog class, then all member functions of the dialog class can use the member. you probably tried to using m_editbox_HD like a CString member what is not possible if it is created as a CEdit (control).

it complains if I try to call it CSdiDialog.m_editbox_HD
that is wrong syntax if CSdiDialog is a classname.

void CSdiDialog::OnClickedBtnAnalyze()
{
      ...
      // get current contents of edit box from screen
      CString strEdit;
      m_editBox_HD.GetWindowText(strEdit);
      analyze(strEdit);
      ...
}

Open in new window


alternatively, if you added a CString member m_strEdit_HD to your dialog class which is associated to the same edit control, you could do:

void CSdiDialog::OnClickedBtnAnalyze()
{
      ...
      // get current contents of all controls from screen
      UpdateData(TRUE);
      analyze(m_strEdit_HD);
      ...
}

Open in new window


Sara
0
 

Author Comment

by:Dave Shields
ID: 40612186
Thank you for your rapid reply.  After the dialog face was created I added a class (CSdiDialog) and member variables to the class such as m_editbox_HD.  The code framewotk for the Button Clicked code was generated by visual studio when I double clicked on the Dialog buttons.  Here is how it looks now (file attached).  The problem might be that I am working in an application called MFCApplication2Dlg and I'm trying to access names that are part of a class called CSdiDialog.  The Browse button probably worked because we used the dialog IDC names for reference rather than the member variable names.

I am sure your code is good, but the compiler is working in a closed double void function, and doesn't recognize your names.

Do you work at microsoft??
0
 
LVL 32

Expert Comment

by:sarabande
ID: 40612271
Do you work at microsoft??
no.

the dialog face was created I added a class (CSdiDialog)
you probably created an SDI (single document interface) document-view project rather than a dialog-based project. the latter would contain only one dialog which was called modal from application class in InitInstance member function.

the SDI contains out of a frame, a document and a view class. the triple was created from application class in InitInstance as well but differently to the modal dialog which runs its own message loop, the SDI uses the application class to run the message pump which is the heart of a windows application.

I assume that the CSdiDialog actually was a 'view' and not a dialog. the main difference is that the view always is non-modal and that it shares the user interface with the frame window which is implented by the framework in class CMainFrame. so the application uses an instance of a CSingleDocTemplate to create first a frame (which holds the title, the menus and the toolbar), then a document and finally a view. the document class should hold the data and the application logic and the view should represent the data from document. if the view classes uses a form for user interface, it should be derived from CFormView rather than from CView. this would allow to directly associate a dialog resource to your view class what makes it possible to use it like a CDialog derived class with little differences. you probably did not know that and created the MFCApplication2Dlg instead what most likely is the cause for the current issues. if I am right you best would create a new project where you could correct that mistake. the crucial step is at the page 'Generate Classes' where you can determine the base class of your view class. if that is a form you definitively should choose CFormView class as base class, or you run into issues like the one you encountered. I would use a new name for example SDIForm. you can open the old project in a separate visual studio instance. that way you easily can copy code or resources from the old to the new project.

Sara
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 32

Expert Comment

by:sarabande
ID: 40612354
The Browse button probably worked because we used the dialog IDC names for reference rather than the member variable names.
you should see that after the wizard generated the sources by help of the framework, your project is pure c++ code with the exception of a few macros (which were preprocessor code). that means member variables can be used in any member function of the class. if the members were protected also member functions of derived classes can directly access member variables of their own class and their base class(es). if the members are public members you even can access them from other classes. however, you need a variable representing the object of the class where the members are defined to access them.

void CSdiDialog::OnInitialUpdate()
{
       MFCApplication2Dlg * pDlg = new  MFCApplication2Dlg(this);
       // here you can access members of the MFCApplication2Dlg if they were defined in public scope.
       pDlg->m_strText = "ABC";
       ...

Open in new window


if you want to access members of the CSdiDialog in MFCApplication2Dlg you would need a variable in MFCApplication2Dlg for the CSdiDialog to do it same way.

there are a few ways how to get such a variable. Simplest is to use a member variable. for that you define a member

CSdiDialog * m_pSdiDialog;

in your class (make it a private member). then in the constructor

MFCApplication2Dlg(CWnd* pParent) 
   : CDialogEx(MFCApplication2Dlg::IDD, pParent)
   , m_pSdiDialog ((CSdiDialog *) pParent)
{
       // the rest  keeps unchanged
       ... 

Open in new window

MFCApplication2Dlg::
you set the member to the pParent pointer which was passed by the CSdiDialog as 'this' when creating the MFCApplication2Dlg. note, the cast to CSdiDialog is necessary cause the pParent was passed as CWnd* which is a base class pointer.

if you do so, you can directly access public members and member functions of the CSdiDialog class from your dialog by using the m_pSdiDialog pointer.

a second way is to retrieve the pointer on the fly. for example if you have

void MFCApplication2Dlg::OnClickedButton()
{
     CSdiDialog *   pSdiDialog  = (CSdiDialog *) GetParent();  
     // define a reference (is an alias) of the edit box defined in CSdiDialog
     CEdit & myEdit = pSdiDialog->m_editBox_HD;  
     // here you can access the edit box defined in the other class
     ...

Open in new window


note, the second code is not recommended. it is bad design to create members in the wrong class. dialog members always should be handled in the class were they were defined and not from other classes.

Sara
0
 

Author Comment

by:Dave Shields
ID: 40612438
HI Sara,
You got ahead of me, or I got behind.  I'm using VC++ 2013 Community.  I am attaching Three screenshots of the rirst three menus that I use.  I will now review your comments,   You should know tho, that as much as possible I have been using Visual Studio to write the code for me.  Thanks.
ThirdScreen.gif
0
 
LVL 32

Expert Comment

by:sarabande
ID: 40612555
hmm. the screenshot doesn't show 3 'menus' but the second page of the wizard to create a new mfc application. what is strange that it shows that you have chosen a dialog-based mfc application. does that mean that your current mfc application is also dialog-based? if so, why the dialog was called CSdiDialog? SDI is the 'Single Document Interface' which use model-view architecture and is much more complex than a simple dialog-based application. why did you create a second dialog with the even more strange name 'MFCApplication2Dlg' if you already have a main dialog? and how were the two dialogs supposed to work together?

note, it is not impossible to have two (or more) dialog classes working together where one is modal and the others were embedded as non-modal dialogs in the first one. but this model is difficult even for advanced mfc developers and it is in no way supported by the generic code generation by wizard.

You got ahead of me, or I got behind.
I assumed that your current CSdiDialog is derived from CView. you would come to this if choosing 'Single Document' for application type in the wizard page you posted as gif. you easily can check whether your old project was dialog-based or not by looking in the class header file. if CSdiDialog was derived from CDialogEx your application seems to be dialog-based. if it is derived from CView or any CView derived class like CFormView, you have a valid SDI application with frame, document and view class generated by wizard.

if that is true, you would choose 'Single Document' for the new project as well (please use a better name different from MFCApplicationX) and choose CFormView as base class for the view class when you come to the page 'Generated Classes'.

if your current project actually is dialog-based I would need a screenshot of the dialog form and the class headers of both dialog classes. for that take the class definition(s) into clipboard, add 'code tags' into your comment (use 'Code' button from toolbar). then, paste your code between the code tags). don't add files because I am working in an environment where I couldn't risk to open unknown file attachments.

Sara
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 40612585
As you seem to be an absolute beginner with little grasp of the basics you might want to look at this set of articles I wrote some time ago:
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3707-Sudoku-a-complete-MFC-application-Part-1.html
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3741-Sudoku-a-complete-MFC-application-Part-2.html
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3822-Sudoku-a-complete-MFC-application-Part-3.html
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3823-Sudoku-a-complete-MFC-application-Part-4.html
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3824-Sudoku-a-complete-MFC-application-Part-5.html
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3825-Sudoku-a-complete-MFC-application-Part-6.html
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3827-Sudoku-a-complete-MFC-application-Part-7.html
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3828-Sudoku-a-complete-MFC-application-Part-8.html
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3829-Sudoku-a-complete-MFC-application-Part-9.html
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3830-Sudoku-a-complete-MFC-application-Part-10.html
http://www.experts-exchange.com/Programming/System/Windows__Programming/MFC/A_3831-Sudoku-a-complete-MFC-application-Part-11.html

It documents starting and coding a complete small application with MFC.  (As you probably have found a lot of what you find with searching is small code snippets which as beginner probably are hard to follow).
0
 

Author Comment

by:Dave Shields
ID: 40614578
Sara,
First, I hope I have not offended you with my slowness.  My only excuse is that thr first time I built a dialog ap, it was in 2007 using VS2003.  I have failed to realize that there have been great strides at Microsoft and IT in general.  Back in VS2003 it was necessary to add the SdiDialog (I failed to recognize the signifigance of the name), but now VS writes a lot more of the code, and often it's better code.   By slavishly following Kate Gregory's 2003 instructions, I muddied up the VS code in VS2013.
   Thank you for your brilliance and depth of knowledge, and your patience in dealing with me.   I believe I am out of the woods now, and can see myself through to the end of my project.  By the way I didn't pick a good name for this project, as it was just a testbed exercise before I wemt into the final draft.  I will do a revised project without the CSdiDialog class and post the results back here.
    Truthfully I have never experienced the insight from an EE expert before.  I am srill astounded that you could discern the roots of the problem with the little I supplied.  All the best to you and yours.
Dave
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 40614605
>>Back in VS2003 it was necessary to add the SdiDialog

Actually it was much earlier (in the nineties) that Microsoft introduced a dialog based MFC app, not with VS2003.
0
 
LVL 32

Expert Comment

by:sarabande
ID: 40616121
Andy is right. I remember that already the first mfc for 16-bit windows came with three application types: sdi, mdi, and dialog based. that was in the early 90-ties.

an additional parent "dialog" was necessary for implementation of a 'notebook' or 'property sheet' which is a tabbed dialog where each tab handles another dialog page. though mfc later provided classes for these, they never had a wizard for to generate a starter application (as fas as I know).

 I believe I am out of the woods now, and can see myself through to the end of my project.
if I understand correctly, your program is a dialog-based mfc application with two dialogs where the one is modal and the other is 'somehow' embedded as a non-modal dialog? because of this constellation you need to exchange data between the dialogs in both directions.

beside of the basic issues you may encounter when working with such a design but surely could be handled, it still could make sense, to creating a new sdi application (or a property sheet if that is the current 'nature' of your program) and 'port' the existing sources to the new base. we surely could help you with the decision if you provide the needed information.

Sara
0
 

Author Comment

by:Dave Shields
ID: 40616531
HI Sara,
Although I had earlier c++ programs (Borland) before VS2003 I had not used visual studio until VS2003.  What a diference 10 years makes.  The problems were solved when I started over, omitted adding the class that was needed in 2003 (CSdiDialog) and added my member variables directly to the main application class.  As i mentioned earlier, I came to the need for that because of your questions.
   At this point I think I am over the real hurdle in this program, and only the grinding toil of detail programming lies ahead.  To help me I have just got a new book from Amazon - Visual Studio 2013.  However if I do get stuck, I will be sure to fall back on this thread of posts.  Thanks.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 40616623
I hope it is about MFC and not .net C++
There are rather large differences between the two and mixing MFC and .net is possible but not trivial.
0
 
LVL 32

Accepted Solution

by:
sarabande earned 500 total points
ID: 40616821
I hope it is about MFC and not .net C++
a new book from Amazon - Visual Studio 2013 - will only have a small chapter for c++ mfc.

you may look alternatively for
- the MFC Answer Book, w. CD-ROM: Solutions for Effective Visual C++ Applications of Eugene Kain
- Software Application Development: A Visual C++, MFC, and STL Tutorial (Chapman & Hall/CRC Computer and Information... Bud Fox Ph.D. and Bud...

the first is pretty old (VC6 1998), but would not contain any .NET stuff. MS didn't add much to mfc since they focused on .NET. therefore the answer book still is valid for almost all your questions.
the second is from 2012 and also helps to understand the standard library STL. the stl libray is a perfect complement to mfc as it is strong with containers and templates where mfc is weak.

The problems were solved when I started over, omitted adding the class that was needed in 2003 (CSdiDialog)
yes, if the CSdiDialog was only a useless bag window, it is good to remove it. you may move the member variables for the user interface to the remaining dialog class and all members which were used for application logic to the main application class. the main application class should have a member variable for the dialog. the dialog class can access the main application class by the global variable 'theApp'. if the compiler complains that 'theApp' is not found, you may add

extern YourApp theApp;

Open in new window


to your main header file below the class definition of 'YourApp' (of course you have to use your application class name instead of 'YourApp').

in the yourapp.cpp file you would add

// the one and only application object
YourApp  theApp;

Open in new window


below the include statements.

if doing so, you could access member variables or member functions of your application class from dialog class via theApp like

void CMyDialog::OnClickedButton()
{
       if (theApp.GetOptionFromInifile("xxxxx") == true)
       {
              ....

Open in new window


Sara
0
 

Author Closing Comment

by:Dave Shields
ID: 40623430
A pleasure to work with Sara.  She has a really impressive knowledge of MFC and all its children.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 40623938
From the original question
>>but I cannot find out how to capture that path...

apologies for spamming you at the start with the answer to that - I assumed you wanted to know how to do that
0
 

Author Comment

by:Dave Shields
ID: 40624223
Even experts are not perfect .  I'm sure you have lots to offer.

Dave
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
Let’s list some of the technologies that enable smooth teleworking. 
This video demonstrates how to use each tool, their shortcuts, where and when to use them, and how to use the keyboard to improve workflow.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now