Solved

How to open a dialog in a child window (MDI)?

Posted on 2004-04-08
45
1,511 Views
Last Modified: 2013-11-20
I've got a MDI application and want to open a dialog (lets call it IDD_DIALOG1) in a new child window by clicking a button. on the same time I want to close the existing child window (where the button was placed).

In other words I want to open a child window just like "file-->new" in the generated standard MDI application, but with the content of IDD_DIALOG1 instead the standard one.

Already tried it with Create (opens the dialog in the same child window) and DoModal (refuses to work).
0
Comment
Question by:blubbbb
  • 21
  • 21
  • 3
45 Comments
 
LVL 15

Expert Comment

by:lakshman_ce
ID: 10784310
Send the WM_CLOSE message to your child frame window on button click and then call your dialog DoModal() inside the WM_CLOSE handler for your child frame like ,

void CChildFrame::OnClose()
{
      // TODO: Add your message handler code here and/or call default
      
      CMDIChildWnd::OnClose();
      
      CTestDlg dlg;
      dlg.DoModal();
}

-Lakshman
0
 

Author Comment

by:blubbbb
ID: 10784851
This looks like it will always open the same dialog in the new child window?

There are multiple buttons on every dialog that should open different new dialogs (IDD_DIALOG1, IDD_DIALOG2, IDD_DIALOG3, etc.).

And how does the code that I need for the child window to close itself look like?
0
 
LVL 15

Expert Comment

by:lakshman_ce
ID: 10785258
>There are multiple buttons on every dialog that should open different new dialogs

Are you talking about mulitple buttons on the dialog opened through button click?

-Lakshman
0
 

Author Comment

by:blubbbb
ID: 10785451
The first dialog you see when the program starts is like a "login" dialog. The "OK"-button there should be able to open multiple dialogs depending on what was entered in the editcontrol field.

like:
if ok-button was clicked()
{
  if value entered in the field == "dialog1"
  {
    open IDD_DIALOG1;
    close old dialog; //the login-one, but leave the new one open
  }
  if value entered in the field == "dialog2"
  {
    open IDD_DIALOG2;
    close old dialog; //the login-one, but leave the new one open
  }
  //etc.......
}

The other dialogs will have multiple buttons and every button opens a different dialog.

Exambple:
IDD_DIALOG1: button1, button2
IDD_DIALOG2: button3, button4

button1 opens IDD_DIALOG3
button2 opens IDD_DIALOG4
button3 opens IDD_DIALOG5
button4 opens IDD_DIALOG6

After the new dialog opened, the old one should be closed, so you always only have one single dialog at the same time.
0
 
LVL 15

Expert Comment

by:lakshman_ce
ID: 10786490
Try this,

strText is the text in your edit control

void CMultiDialogDlg::OnOK()
{
      ::SendMessage(this->m_hWnd,WM_CLOSE,0L,0L);      
}

void CMultiDialogDlg::OnClose()
{
      // TODO: Add your message handler code here and/or call default
      CDialog::OnClose();
      if(strText == "Dialog1")
      {
            CDialog1 dlg1;
            dlg1.DoModal();
      }
      if(strText == "Dialog2")
      {
            CDialog2 dlg2;
            dlg2.DoModal();
      }
      if(strText == "Dialog3")
      {
            CDialog3 dlg3;
            dlg3.DoModal();
      }
      
}

Do similarly in other dialogs (say if you are clicking on some other button on Dialog2, have code like this in Dialog2)


-Lakshman
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10790433
You said you've an MDI application?

Then, most likely you start Login Dialog by a View class, say CMyView like this (or you could do it this way)

   void CMyView::OnInitialUpdate(...)
   {
        CLoginDlg login;
        login.DoModal();

   }

Change it to that:

   void CMyView::OnInitialUpdate(...)
   {
        CLoginDlg login;
        while (login.DoModal() != IDOK)
        {
            CString nextDialog = login.m_strNextDialog; // suppose it is a member
            if (nextDialog == "Dialog1")
            {
                CDialog1 dlg1;
                dlg1.DoModal();
            }
            else if (nextDialog == "Dialog2")
            {
                CDialog2 dlg2;
                dlg2.DoModal();
            }
            ....
            else
            {
                login.m_strErrText = "Invalid Dialogname [" + login.m_strNextDialog  + "]";
            }
        }

   }

Regards, Alex
0
 

Author Comment

by:blubbbb
ID: 10811472
I haven't been able to bring anything of this to work:

>::SendMessage(this->m_hWnd,WM_CLOSE,0L,0L);    
Doesn't close my child window.


>void CMyView::OnInitialUpdate(...)
>   {
>        CLoginDlg login;
>        login.DoModal();
>
>   }
There is no DoModal in my OnInitialUpdate by default. It looks like this:
void CMy::OnInitialUpdate()
{
      m_pSet = &GetDocument()->m_MySet;
      CRecordView::OnInitialUpdate();
}

The first dialog (IDD_MY_FORM) will be opened in a child window by default on startup. There is no code in the project where it will be opened, or I haven't found it.
If I disable it's opening by default (http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q141/7/25.asp&NoWebContent=1) and try to open it or another dialog with DoModal in OnInitialUpdate, it just won't show up.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10811996
A CRecordView is derived from CFormView and that is a non-modal dialog. Non-modal means that you may click to menus, toolbar buttons, other views while your dialog is open. You may also minimize the dialog.

If you haven't modal dialogs but formviews the problem is different as you have to change views - or more precisely - as you have to change the active view of your active document (An MDI application may have more than one open document but default is that one single document has only one single view. The relation between document and view is defined in CMyApp::InitInstance(..) where there is a DocTemplate that creates frame, doc and view.

If the first dialog is a formview all other 'dialogs' should be made formviews also. You change views by creating a new view and calling GetDocument()->AddView(pNewView) and GetDocument()->RemoveView(pOldView). However, there is one little problem: When calling these functions from a handler function of the previous view you cannot delete the view as it is still active and might process some more messages (what would crash if the view got deleted).
To overcome this, you could call DestroyWindow(this) and overload CWnd::PostNcDestroy() what is the last function that is called. The implementation of this virtual function is like this:

   void CMyView::PostNcDestroy()
   {
         delete this;
   }

Hope, that helps

Alex


0
 

Author Comment

by:blubbbb
ID: 10813084
So I should do something like this?

void CMyView::OnBnClickedOk()    // OK-Button on the first dialog
{
    switch(str)    // str is the string entered in the "login" field
    {
        case(name1)
        {
            open dialog1 in a new view
            close old view
        }
        case(name2)
        {
            open dialog2 in a new view
            close old view
        }
        // etc.....
      }
}

My main problem is that I don't know how open and close views.

>GetDocument()->AddView(pNewView)
needs to declare pNewView, but how?

I've tried something like:
CDialog pNewView(IDD_DIALOG1)
but it won't accept this.

The dialog ID has too be written somewhere or the program doesn't know what dialog to open I guess, yet I have no idea why always IDD_MY_FORM will be opened on startup when it's nowhere written in the code.

I've made a pic to show it a bit more clear what I'm trying to do:
http://www.yetnet.ch/marble/geist/dialogs.gif

Its a project connected to a access database, reading the login informations out of a table. Depending on what you enter in the login field, you get the menu (dialog) for this group. On this menu, every button opens a new, different dialog (view). You should never be able to see or access more than one dialog at one time, thats why I want to close the old view after making a new one. The navigation through the dialogs/views should work with only buttons.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10816065
I took me a little time to add the functionality you want to my TestFrm project. It is SDI, so i used CMainFrame where you have to use your FrameWnd derivated  class.

These are the steps:

1. Create CFormView (or CRecordView) derived classes usiing the dialog ids.

2. The header looks like that:

#if !defined(AFX_MYVIEW_H__B744EBB0_8D5A_11D8_AC9F_0002A57F6614__INCLUDED_)
#define AFX_MYVIEW_H__B744EBB0_8D5A_11D8_AC9F_0002A57F6614__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// MyView.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CMyView form view

#ifndef __AFXEXT_H__
#include <afxext.h>
#endif

class CMyBaseView : public CFormView
{
// Operations
public:
    CMyBaseView(UINT idd) : CFormView(idd) {}
    virtual ~CMyBaseView() {}
      virtual BOOL Create(LPCTSTR, LPCTSTR, DWORD,
            const RECT&, CWnd*, UINT, CCreateContext*);
};

class CMyView : public CMyBaseView
{
protected:
public:
      CMyView();           // protected constructor used by dynamic creation
      DECLARE_DYNCREATE(CMyView)

// Form Data
public:
      //{{AFX_DATA(CMyView)
      enum { IDD = IDD_DIALOG2 };
            // NOTE: the ClassWizard will add data members here
      //}}AFX_DATA

// Attributes
public:

// Operations
public:

// Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CMyView)
      protected:
      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
      //}}AFX_VIRTUAL

// Implementation
protected:
      virtual ~CMyView();
#ifdef _DEBUG
      virtual void AssertValid() const;
      virtual void Dump(CDumpContext& dc) const;
#endif

      // Generated message map functions
      //{{AFX_MSG(CMyView)
            // NOTE - the ClassWizard will add and remove member functions here.
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MYVIEW_H__B744EBB0_8D5A_11D8_AC9F_0002A57F6614__INCLUDED_)

I added class CMyBaseView to this header - better is to take an own file. That class is to derive all these views from an own baseclass as we have to override the virtual function

      virtual BOOL Create(LPCTSTR, LPCTSTR, DWORD,
            const RECT&, CWnd*, UINT, CCreateContext*);

That is the implementation of this function:


// virtual override of CFormView::Create
BOOL CMyBaseView::Create(LPCTSTR /*lpszClassName*/, LPCTSTR /*lpszWindowName*/,
      DWORD dwRequestedStyle, const RECT& rect, CWnd* pParentWnd, UINT nID,
      CCreateContext* pContext)
{
    return CFormView::Create(NULL, NULL, dwRequestedStyle, rect, pParentWnd, nID, pContext);
}

Derive all your views from CMyBaseView. You only have to change class declaration

class CMyView : public CMyBaseView
{
       ...
};

and constructor

CMyView::CMyView()
      : CMyBaseView(CMyView::IDD)
{
      ....
}


Then, you have to enhance your frame class, normally called CChildFrame by adding these public members to the class declaration

public:
    CCreateContext* m_pContext;
    virtual BOOL OnCreateClient( LPCREATESTRUCT lpcs, CCreateContext* pContext );

The OnCreateClient function is implemented like this:

BOOL CChildFrame::OnCreateClient( LPCREATESTRUCT lpcs, CCreateContext* pContext )
{    
    m_pContext = new CCreateContext;
    m_pContext->m_pCurrentDoc =  pContext->m_pCurrentDoc;
    m_pContext->m_pCurrentFrame = pContext->m_pCurrentFrame;
    m_pContext->m_pNewDocTemplate = NULL;
    m_pContext->m_pLastView = NULL;
    m_pContext->m_pNewViewClass = NULL;
    return CFrameWnd::OnCreateClient( lpcs, pContext );
}

Then, we had to add a virtual function to all views (including the login view)

    virtual void PostNcDestroy();

That function makes the 'delete'. It's implementation is like this:

void CMyRecordView::PostNcDestroy()
{
    delete this;  // PostNcDestroy is called by the framework
                     // after all windows resources had been freed.
}

So, finally we implement the CMyRecordView::OnClickedOk() handler (your login dialog class)

CMyRecordView::OnClickedOk()
{
    UpdateData(FALSE);   // get members from screen

    CChild* pFrame = (CChildFrame*)GetParentFrame();
    CCreateContext* pContext = pFrame->m_pContext;  // here we get the frame context
    pContext->m_pLastView = this;
    pContext->m_pNewViewClass = NULL;

    CMyBaseView* pNextView = NULL;

    if (m_strNextDialog.CompareNoCase("dialog1") == 0)
    {
        pNextView = new CMyView();  
    }
   
    else if (m_strNextDialog.CompareNoCase("dialog2") == 0)
    {
        pNextView = new CMyView2();  
    }
    else
    {
        AfxMessageBox("Invalid dialog " + m_strNextDialog, MB_STOP);
        return;
    }

    // create a window and attach it to the formview
    pNextView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
        CFrameWnd::rectDefault, GetParent(), AFX_IDW_PANE_FIRST, pContext);
       
    pNextView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);

    GetDocument()->RemoveView(this);
    pNextView->ShowWindow(SW_SHOW);
   
    pFrame->SetActiveView(pNextView);
    pFrame->RecalcLayout();
    DestroyWindow();
}


That it is.

Regards, Alex




0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10816130
If your view classes are derived from CRecordView and not from CFormView, just replace CFormView by CRecordView in the code above.

Regards, Alex
0
 

Author Comment

by:blubbbb
ID: 10821724
I've tried it with SDI too, if this seems to be the easiest solution.

But I've still got problems with the OK-Button on the login dialog.

Lets say there are 3 logins in the database (for testing purposes):
1.
login: admin
password: 123

2.
login: member
password: 1234

3.
login: guest
password: 12345

I think this would look something like this:

void CMyView::OnBnClickedOk()
{
    if(m_Name == "admin")  // m_Name is what was entered in the login field
    {
        if(m_Pw == "123")  // m_Pw is what was entered in the password field
        {
            // open IDD_ADMIN, but how?
            // close IDD_LOGIN
        }
        else
        {
            MessageBox("Wrong Password");
        }
    }    
    else if(m_Name == "member")
    {
        if(m_Pw == "1234")
        {
            // open IDD_MEMBER, but how?
            // close IDD_LOGIN
        }
        else
        {
            MessageBox("Wrong Password");
        }
    }
    else if(m_Name == "guest")
    {
        if(m_Pw == "12345")
        {
            // open IDD_GUEST, but how?
            // close IDD_LOGIN
        }
        else
        {
            MessageBox("Wrong Password");
        }
    }
    else
    {
        MessageBox("No such login");
    }
}

But I don't know how to navigate through the dialogs.
I've tried your solution but can't find where to put the IDs of the dialogs, and still have problems and errors with the pointers.

A note to the picture I've posted above, the lower-right dialog should have had the ID "DIALOG2" instead of "DIALOG1", that was a typing error, if you didn't already figure.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10822164
>> I've tried it with SDI too, if this seems to be the easiest solution.

The difference between MDI and SDI is only the CChildFrame class that allows you to have multiple "documents". If you replace CChildFrame by CMainFrame in my code above, you have the SDI solution,

>> But I don't know how to navigate through the dialogs.

It seems, you still haven't recognized the difference between views and dialogs. So, we should clear the misunderstandings first.

I assumed because of one of your previous post's that the Login "dialog" isn't a CDialog derived class but a Application Wizard generated class derived from CRecordView. CRecordView is derived from CFormView that means that your initial view handles the dialog resource IDD_MY_FORM. I already told you that a formview is a non-modal dialog where  toolbar buttons and menus are available while the dialog is opened. A CRecordView additionally adds database support to the class. That means you may iterate thru a database table showing fields of that table by using member variables of your derived view class.

Now, you want to replace the initial dialog form by others depending on the password given by the user. The way i suggested to solve that is to replace the initial view CMy or CMyView (you used both class names, so i don't know the name) by a second or third view. Look at this

     CMyApp                         There is one and only only instance

     CMyDoc                          In SDI you have one instance, in MDI maybe more.
                                           Also in MDI you may have more than one document class
                                                       
     CMyView[n]                    You may have one or more view classes for any document class.

     CMainFrame                    That is the application frame (one instance) you see with
                                           menus, toolbars, status. In an SDI your views get showed within
                                           the main frame, either one at a time maximized or all together
                                           (you my click on separate windows as in Visual Studio).

     CChildFrame                    In MDI you may have different frames (menus, toolbars) for any
                                           document type (class). The child frame could be a separate frame
                                           within the main frame  or can be maximized to the mainframe, i. e.
                                           you see only one frame (though both instances are existing).

You now, have only one view. To be able to use the code above, you have to create a second view using IDD_ADMIN,  a third view using IDD_MEMBER and a fourth view with IDD_GUEST. These views must be derived either from CFormView or from CRecordView depending on need of database support or not. You create these views using Class Wizard (CTRL + W) - Add New Class... where you can choose CFormView or CRecordView as baseclass. In all cases you have to define IDD_ADMIN,  IDD_MEMBER or IDD_GUEST as dialog resource id (if you couldn't select these ids, it is because you already defined dialog classes using these ids. Then, copy the dialog forms and use new ids or close your project, delete the dialogs, delete the *.clw file and and get a new *.clw file created by Class Wizard after reopening the project).

If you are at this point, you should give me a feedback.

Regards, Alex


0
 

Author Comment

by:blubbbb
ID: 10822685
I've now made classes using all the dialog resource IDs. I do need database support in every view, but CRecordView was not available to chose from when making the classes, so I've chosen CFormView.

So I'm now at the point where I need to know how to display new views and destroy old ones?
I've experimented with the OK-Button code above and the new views, but failed to declare some variables and the pointers.

pNextView = new CMyView();   <---- CMyView is the name of my class using this dialog?
It didn't find it, and when I included the headers of this new view classes in my (ProjectName)View.cpp it said can't access protected elements.

I've also got problems with:
    CChildFrame* pFrame = (CChildFrame*)GetParentFrame();
    CCreateContext* pContext = pFrame->m_pContext;  // here we get the frame context

Renaming CChildFrame to CMainFrame didn't work.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10823197
Ok, we are advancing..

>> but CRecordView was not available to chose from

That is strange? I am working with VC6.0? What is your version?

But we can change it manually, later.

>> I included the headers of this new view classes in my (ProjectName)View.cpp

Ok, that's correct. Add

#include mainfrm.h

also.

>> pNextView = new CMyView();   // failed

you have to use the new view classes. However, we need a common base class for all views and change the constructor from 'protected' to 'public'.

Create 2 source files  mybaseview.h and mybaseview.cpp.
Copy the class declaration of CMyBaseView to the header file and the implementation of CMyBaseView::CMyBaseView() and CMyBaseView::Create() to the cpp file.

//-------------------------------------------------------------
// mybaseview.h  
#ifndef CMYBASE_VIEW_H
#define CMYBASE_VIEW_H

class CMyBaseView : public CFormView
{
// Operations
public:
    CMyBaseView(UINT idd);
    virtual ~CMyBaseView() {}
    virtual BOOL Create(LPCTSTR, LPCTSTR, DWORD,
        const RECT&, CWnd*, UINT, CCreateContext*);
};



#endif
//------------------- end of mybaseview.h ---------------------

//-------------------------------------------------------------
// mybaseview.cpp
#include "mybaseview.h"

// constructor
CMyBaseView::CMyBaseView(UINT idd)
: CFormView(idd)
{
}

// virtual override of CWnd::Create
BOOL CMyBaseView::Create(LPCTSTR /*lpszClassName*/, LPCTSTR /*lpszWindowName*/,
    DWORD dwRequestedStyle, const RECT& rect, CWnd* pParentWnd, UINT nID,
    CCreateContext* pContext)
{
    return CFormView::Create(NULL, NULL, dwRequestedStyle, rect, pParentWnd, nID, pContext);
}
//------------------ end of mybaseview.cpp --------------------



Then, add

#include "mybaseview.h"

to all of your new view header files.

Change baseclass from CFormView to CMyBaseView for all new view classes (we couldn't do it for CMyView as it is derived from CRecordView. But, when finally changing CFormView to CRecordView we could change CMyView also. That will allow to return to the login dialog from any of the new dialogs later.

         

Add

public:

above the constructor of new view class(es)



Goto cpp files of new view classes and replace CFormView by CMyBaseView in the initialiser list of the constructor.


Finally, add the changes i described for CChildFrame to the CMainFrame class (i suppose you have SDI now).
All should compile now if you make comments /*  */ to the implementation of OnClickedOK().

Please give feedback if you've been come so far.

Regards, Alex

0
 

Author Comment

by:blubbbb
ID: 10823818
>That is strange? I am working with VC6.0? What is your version?
I'm using VC++.NET, but I've got 6.0 on another machine here as backup if something refuses to work with .NET.

I've done so far, but if I compile I'll get a ton of errors (65).

The first ones bring me to the "public:" above the constructors of the new view classes with "error C2059" (syntax fault or something like that, I don't know how to translate it correctly).
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10823953
>> I'm using VC++.NET

Seems that MS has 'improved' Class Wizard and skipped ODBC support. But we do it manually, later...

>> but if I compile I'll get a ton of errors (65).

Don't worry if you have a lot of errors as it is mostly some semicolons or brackets missing...

>> I don't know how to translate it correctly

you may post the local german error text ;-)


Your (new) view classes should look like this:

class CAdminView : public CMyBaseView
{
protected:         // YOU MAY DELETE THAT LINE
public:              // THAT MAKES THE CONSTRUCTOR PUBLIC
      CAdminView();           // protected constructor used by dynamic creation
      DECLARE_DYNCREATE(CAdminView)

// Form Data
public:
      //{{AFX_DATA(CAdminView)
      enum { IDD = IDD_ADMIN };
            // NOTE: the ClassWizard will add data members here
      //}}AFX_DATA

// Attributes
public:

// Operations
public:

// Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CAdminView)
      protected:
      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
      //}}AFX_VIRTUAL

// Implementation
protected:
      virtual ~CAdminView();
#ifdef _DEBUG
      virtual void AssertValid() const;
      virtual void Dump(CDumpContext& dc) const;
#endif

      // Generated message map functions
      //{{AFX_MSG(CAdminView)
            // NOTE - the ClassWizard will add and remove member functions here.
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()

};

/////////////////////////////////////////////////////////////////////////////



Regards, Alex

0
 

Author Comment

by:blubbbb
ID: 10830768
I've still got around 60 errors, and one fatal error.

First error is in MyView.cpp:
CMyDoc* CMyView::GetDocument() const // Nicht-Debugversion ist inline
{
      ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMyDoc)));
      return (CMyDoc*)m_pDocument;
}
m_pDocument not declared


Fatal error is:
MyBaseView.cpp(19): fatal error C1010:
Unerwartetes Dateiende während der Suche nach der Direktive für die vorkompilierte Headerdatei
0
 

Author Comment

by:blubbbb
ID: 10830800
I've just brought it down to 25 errors (wrote a class name wrong), but the errors in the post above are still there.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10831184
>> CMyView::
>> m_pDocument not declared

CMyView is the LoginDialog isn't it? You shouldn't change this as it is derived from CRecordView.

Please change only the 'new' views,  AdminView, MemberView and GuestView.

>> MyBaseView.cpp(19): fatal error C1010

When using Precompiled Headers - you may switch that in Project Settings - at top of all cpp files there MUST be

#include "stdafx.h"

Make sure, that there isn't another #include statement before

Regards, Alex



0
 

Author Comment

by:blubbbb
ID: 10831309
>CMyView is the LoginDialog isn't it? You shouldn't change this as it is derived from CRecordView.
>Please change only the 'new' views,  AdminView, MemberView and GuestView.

I didn't make any changes to it, this was generated  from the wizard when I made the project.
At first all worked, but now this seems to not work anymore with the new adds.

I've commented it out to get rid of the errors from this, now the next errors are here:

    BEGIN_MESSAGE_MAP(CMyView, CRecordView) <---
      // Standarddruckbefehle
      ON_COMMAND(ID_FILE_PRINT, CRecordView::OnFilePrint) <---
      ON_COMMAND(ID_FILE_PRINT_DIRECT, CRecordView::OnFilePrint) <---
      ON_COMMAND(ID_FILE_PRINT_PREVIEW, CRecordView::OnFilePrintPreview) <---
      ON_BN_CLICKED(IDC_OK, OnBnClickedOk)
      ON_BN_CLICKED(IDC_ABBRECHEN, OnBnClickedAbbrechen)
    END_MESSAGE_MAP()

Can't access protected elements, that are declared in CRecordView and CView (C2248).

If this is only needed for printing as I guess from the name, could I comment it out as well, as I don't need the option to print?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10831530
>> If this is only needed for printing

No, that is windows messaging and you'll need it.

Would you post all files that didn't compile (cpp + h), so i can fix the errors?
Don't forget any new header file!

Regards,Alex
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10831541
I need a full list of the compile errors, also.

Copy it from output window and post it here.

Regards, Alex
0
 

Author Comment

by:blubbbb
ID: 10831728
I've got some different names, so:
projectname is QS_Tool
MyView.cpp = QS_ToolView.cpp
MyView.h = QS_ToolView.h
MyBaseView = QS_ToolBaseView

views:
adminmenu = CAdminView
dozentenmenu
mandantenmenu
tnmenu
etc..

There will be around 20-40 more views and classes following, but I've got only this ones for now, to start and test the project.


The 2 files that returned errors:
cpp
/////////////////////////////////////////////////////////////////////////////
// QS_ToolView.cpp : Implementierung der Klasse CQS_ToolView
//

#include "stdafx.h"
#include "QS_Tool.h"

#include "QS_ToolSet.h"
#include "QS_ToolDoc.h"
#include "QS_ToolView.h"
#include ".\qs_toolview.h"

#include "MainFrm.h"

// Views
#include "adminmenu.h"
#include "dozentenmenu.h"
#include "mandantenmenu.h"
#include "tnmenu.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CQS_ToolView
IMPLEMENT_DYNCREATE(CQS_ToolView, CRecordView)

BEGIN_MESSAGE_MAP(CQS_ToolView, CRecordView)
      // Standarddruckbefehle
      //ON_COMMAND(ID_FILE_PRINT, CRecordView::OnFilePrint)
      //ON_COMMAND(ID_FILE_PRINT_DIRECT, CRecordView::OnFilePrint)
      //ON_COMMAND(ID_FILE_PRINT_PREVIEW, CRecordView::OnFilePrintPreview)
      ON_BN_CLICKED(IDC_OK, OnBnClickedOk)
      ON_BN_CLICKED(IDC_ABBRECHEN, OnBnClickedAbbrechen)
END_MESSAGE_MAP()

// CQS_ToolView Erstellung/Zerstörung
CQS_ToolView::CQS_ToolView()
      : CQS_ToolBaseView(CQS_ToolView::IDD)
      , m_Name(_T(""))
      , m_Pw(_T(""))
{
      m_pSet = NULL;
      // TODO: Hier Code zum Erstellen einfügen
}

CQS_ToolView::~CQS_ToolView()
{
}

void CQS_ToolView::PostNcDestroy()            // CRecordView anstatt CQS_ToolView??
{
    delete this;            // PostNcDestroy is called by the framework
                                    // after all windows resources had been freed.
}

void CQS_ToolView::DoDataExchange(CDataExchange* pDX)
{
      CRecordView::DoDataExchange(pDX);
      // Sie können hier DDX_Field*-Funktionen einfügen, um die Steuerelemente mit den Datenbankfeldern zu verbinden:
      // DDX_FieldText(pDX, IDC_MYEDITBOX, m_pSet->m_szColumn1, m_pSet);
      // DDX_FieldCheck(pDX, IDC_MYCHECKBOX, m_pSet->m_bColumn2, m_pSet);
      // Weitere Informationen finden Sie in den MSDN- und ODBC-Beispielen.
      DDX_Text(pDX, IDC_NAME, m_Name);
      DDX_Text(pDX, IDC_PW, m_Pw);
}

BOOL CQS_ToolView::PreCreateWindow(CREATESTRUCT& cs)
{
      // TODO: Ändern Sie hier die Fensterklasse oder die Darstellung, indem Sie
      // CREATESTRUCT cs modifizieren.
      return CRecordView::PreCreateWindow(cs);
}

void CQS_ToolView::OnInitialUpdate()
{
      m_pSet = &GetDocument()->m_QS_ToolSet;
      CRecordView::OnInitialUpdate();
}


// CQS_ToolView drucken
BOOL CQS_ToolView::OnPreparePrinting(CPrintInfo* pInfo)
{
      // Standardvorbereitung
      return DoPreparePrinting(pInfo);
}

void CQS_ToolView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
      // TODO: Zusätzliche Initialisierung vor dem Drucken hier einfügen
}

void CQS_ToolView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
      // TODO: Bereinigung nach dem Drucken einfügen
}


// CQS_ToolView Diagnose
#ifdef _DEBUG
void CQS_ToolView::AssertValid() const
{
      CRecordView::AssertValid();
}

void CQS_ToolView::Dump(CDumpContext& dc) const
{
      CRecordView::Dump(dc);
}

CQS_ToolDoc* CQS_ToolView::GetDocument() const // Nicht-Debugversion ist inline
{
      ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CQS_ToolDoc)));
      return (CQS_ToolDoc*)m_pDocument;
}
#endif //_DEBUG


// CQS_ToolView Datenbankunterstützung
CRecordset* CQS_ToolView::OnGetRecordset()
{
      return m_pSet;
}

// CQS_ToolView Meldungshandler
/*
void CQS_ToolView::OnBnClickedOk()
{
    UpdateData(FALSE);   // get members from screen

    CMainFrame* pFrame = (CMainFrame*)GetParentFrame();
    CCreateContext* pContext = pFrame->m_pContext;  // here we get the frame context
    pContext->m_pLastView = this;
    pContext->m_pNewViewClass = NULL;

    CQS_ToolBaseView* pNextView = NULL;

//    if (m_Name.CompareNoCase("admin") == 0)
//    {
//        pNextView = new CQS_ToolView1();  
//    }
    if (m_Name == "admin")
    {
            if (m_Pw == "admin123")
            {
                  pNextView = new adminmenu();
            }
            else
            {
                  AfxMessageBox("Falsches Passwort", MB_OK);
            }
    }
      else if (m_Name == "dozent")
    {
            if (m_Pw == "dozent123")
            {
                  pNextView = new dozentenmenu();
            }
            else
            {
                  AfxMessageBox("Falsches Passwort", MB_OK);
            }
    }
      else if (m_Name == "mandant")
    {
            if (m_Pw == "mandant123")
            {
                  pNextView = new mandantenmenu();
            }
            else
            {
                  AfxMessageBox("Falsches Passwort", MB_OK);
            }
    }
      else if (m_Name == "teilnehmer")
    {
            if (m_Pw == "teilnehmer123")
            {
                  pNextView = new tnmenu();
            }
            else
            {
                  AfxMessageBox("Falsches Passwort", MB_OK);
            }
    }
    else
    {
        AfxMessageBox("Invalid username " + m_Name, MB_OK);
        return;
    }

    // create a window and attach it to the formview
    pNextView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
        CFrameWnd::rectDefault, GetParent(), AFX_IDW_PANE_FIRST, pContext);
       
    pNextView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);

    GetDocument()->RemoveView(this);
    pNextView->ShowWindow(SW_SHOW);
   
    pFrame->SetActiveView(pNextView);
    pFrame->RecalcLayout();
    DestroyWindow();
}*/

void CQS_ToolView::OnBnClickedAbbrechen()
{
      // TODO: Fügen Sie hier Ihren Kontrollbehandlungscode für die Benachrichtigung ein.
      PostQuitMessage(0);
}
// QS_ToolView.cpp ende
/////////////////////////////////////////////////////////////////////////////


and h:
/////////////////////////////////////////////////////////////////////////////
// QS_ToolView.h : header file
//

#if !defined(AFX_QS_TOOLVIEW_H__B744EBB0_8D5A_11D8_AC9F_0002A57F6614__INCLUDED_)
#define AFX_QS_TOOLVIEW_H__B744EBB0_8D5A_11D8_AC9F_0002A57F6614__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


// CQS_ToolView form view

#ifndef __AFXEXT_H__
#include <afxext.h>
#include "QS_ToolBaseView.h"
#endif

class CQS_ToolView : public CQS_ToolBaseView
{
protected:
public:
     CQS_ToolView();                              // protected constructor used by dynamic creation
     DECLARE_DYNCREATE(CQS_ToolView)
       virtual void PostNcDestroy();            // Delete-Funktion

// Form Data
public:
     //{{AFX_DATA(CMyView)
     enum { IDD = IDD_QS_TOOL_FORM };
       CQS_ToolSet* m_pSet;
          // NOTE: the ClassWizard will add data members here
     //}}AFX_DATA

// Attributes
public:
      CQS_ToolDoc* GetDocument() const;

// Operations
public:

// Overrides
public:
      virtual CRecordset* OnGetRecordset();
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
      virtual void DoDataExchange(CDataExchange* pDX);            // DDX/DDV-Unterstützung
      virtual void OnInitialUpdate();                                          // Erster Aufruf nach Erstellung
      virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
      virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
      virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// Implementation
protected:
     virtual ~CQS_ToolView();
#ifdef _DEBUG
     virtual void AssertValid() const;
     virtual void Dump(CDumpContext& dc) const;
#endif

     // Generated message map functions
     //{{AFX_MSG(CMyView)
          // NOTE - the ClassWizard will add and remove member functions here.
     //}}AFX_MSG
     DECLARE_MESSAGE_MAP()
public:
      afx_msg void OnBnClickedOk();
      afx_msg void OnBnClickedAbbrechen();
      CString m_Name;
      CString m_Pw;
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MYVIEW_H__B744EBB0_8D5A_11D8_AC9F_0002A57F6614__INCLUDED_)

// QS_ToolView.h
/////////////////////////////////////////////////////////////////////////////


This are the errors:

d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(115): error C2065: 'm_pDocument': nichtdeklarierter Bezeichner
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(115): error C2227: Der linke Teil von '->IsKindOf' muss auf Klasse/Struktur/Union zeigen
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(29): error C2248: 'CRecordView::GetThisMessageMap': Kein Zugriff auf protected Element, dessen Deklaration in der Klasse "CRecordView" erfolgte
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(73): error C2248: 'CView::PreCreateWindow': Kein Zugriff auf protected Element, dessen Deklaration in der Klasse "CView" erfolgte
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(60): error C2248: 'CWnd::DoDataExchange': Kein Zugriff auf protected Element, dessen Deklaration in der Klasse "CWnd" erfolgte
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(105): error C2352: 'CRecordView::AssertValid::CRecordView::AssertValid': Unzulässiger Aufruf einer nicht statischen Memberfunktion
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(110): error C2352: 'CRecordView::Dump::CRecordView::Dump': Unzulässiger Aufruf einer nicht statischen Memberfunktion
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(79): error C2352: 'CRecordView::OnInitialUpdate::CRecordView::OnInitialUpdate': Unzulässiger Aufruf einer nicht statischen Memberfunktion
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(73): error C2352: 'CView::PreCreateWindow::CView::PreCreateWindow': Unzulässiger Aufruf einer nicht statischen Memberfunktion
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(60): error C2352: 'CWnd::DoDataExchange::CWnd::DoDataExchange': Unzulässiger Aufruf einer nicht statischen Memberfunktion
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(27): error C2440: 'return': 'CQS_ToolView *' kann nicht in 'CObject *' konvertiert werden
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(34): error C2440: 'static_cast': 'void (__thiscall CQS_ToolView::* )(void)' kann nicht in 'AFX_PMSG' konvertiert werden
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(35): error C2440: 'static_cast': 'void (__thiscall CQS_ToolView::* )(void)' kann nicht in 'AFX_PMSG' konvertiert werden
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.h(21): error C2504: 'CQS_ToolBaseView': Basisklasse undefiniert
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.h(21): error C2504: 'CQS_ToolBaseView': Basisklasse undefiniert
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(43): error C2614: 'CQS_ToolView': Unzulässige Elementinitialisierung: 'CQS_ToolBaseView' ist weder Basis noch Element
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(87): error C3861: 'DoPreparePrinting': Bezeichner wurde auch mit einer argumentbezogenen Suche nicht gefunden
d:\Eigene Dateien\Visual Studio Projects\QS_Tool\QS_ToolView.cpp(116): error C3861: 'm_pDocument': Bezeichner wurde auch mit einer argumentbezogenen Suche nicht gefunden
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10831962
You replaced CRecordView by CQS_ToolBaseView in the header file.

We can't do that before all views have been derived from CRecordView (and not from CFormView)

So, rechange header to this:
/////////////////////////////////////////////////////////////////////////////
// QS_ToolView.h : header file
//

#if !defined(AFX_QS_TOOLVIEW_H__B744EBB0_8D5A_11D8_AC9F_0002A57F6614__INCLUDED_)
#define AFX_QS_TOOLVIEW_H__B744EBB0_8D5A_11D8_AC9F_0002A57F6614__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000


// CQS_ToolView form view

#ifndef __AFXEXT_H__
#include <afxext.h>
#include "QS_ToolBaseView.h"
#endif

class CQS_ToolView : public CRecordView
{
protected:
public:
     CQS_ToolView();                         // protected constructor used by dynamic creation
     DECLARE_DYNCREATE(CQS_ToolView)
      virtual void PostNcDestroy();          // Delete-Funktion

// Form Data
public:
     //{{AFX_DATA(CMyView)
     enum { IDD = IDD_QS_TOOL_FORM };
      CQS_ToolSet* m_pSet;
          // NOTE: the ClassWizard will add data members here
     //}}AFX_DATA

// Attributes
public:
     CQS_ToolDoc* GetDocument() const;

// Operations
public:

// Overrides
public:
     virtual CRecordset* OnGetRecordset();
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
     virtual void DoDataExchange(CDataExchange* pDX);          // DDX/DDV-Unterstützung
     virtual void OnInitialUpdate();                                   // Erster Aufruf nach Erstellung
     virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
     virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
     virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// Implementation
protected:
     virtual ~CQS_ToolView();
#ifdef _DEBUG
     virtual void AssertValid() const;
     virtual void Dump(CDumpContext& dc) const;
#endif

     // Generated message map functions
     //{{AFX_MSG(CMyView)
          // NOTE - the ClassWizard will add and remove member functions here.
     //}}AFX_MSG
     DECLARE_MESSAGE_MAP()
public:
     afx_msg void OnBnClickedOk();
     afx_msg void OnBnClickedAbbrechen();
     CString m_Name;
     CString m_Pw;
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_MYVIEW_H__B744EBB0_8D5A_11D8_AC9F_0002A57F6614__INCLUDED_)

// QS_ToolView.h
/////////////////////////////////////////////////////////////////////////////

Regards, Alex

0
 

Author Comment

by:blubbbb
ID: 10832196
Ok looks good so far, now I've got two errors left:

QS_ToolView.cpp:

// CQS_ToolView Erstellung/Zerstörung
CQS_ToolView::CQS_ToolView()
      : CQS_ToolBaseView(CQS_ToolView::IDD)
      , m_Name(_T(""))
      , m_Pw(_T(""))
{ //<----- errors are supposed to be here
      m_pSet = NULL;
      // TODO: Hier Code zum Erstellen einfügen
}

error C2512: 'CRecordView': Kein geeigneter Standardkonstruktor verfügbar
error C2614: 'CQS_ToolView': Unzulässige Elementinitialisierung: 'CQS_ToolBaseView' ist weder Basis noch Element
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10832269
Change CQS_ToolBaseView to CRecordView here also:

// CQS_ToolView Erstellung/Zerstörung
CQS_ToolView::CQS_ToolView()
     : CRecordView(CRecordView::IDD)
     , m_Name(_T(""))
     , m_Pw(_T(""))
{
     m_pSet = NULL;
     // TODO: Hier Code zum Erstellen einfügen
}

Then, it compiles and you may try the OnBnClickedOk functionality. You should be able to replace QS_ToolView by any of the other views. However, two things left:

- We need CRecordView derivation for all views.
- CQS_ToolView should be derivated from CQS_ToolBaseView - as all others . Then, you might have a
  menu item where you can go back to another login.

Regards, Alex

0
 

Author Comment

by:blubbbb
ID: 10832391
I've still got an error in one of the lines above:

    : CRecordView(CRecordView::IDD)

IID is no element from CRecordView.

And once it compiles, how to code OnBnClickedOk to replace the first view with the others?
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10832539
Sorry, my fault

It is CQS_ToolView::IDD    

>> how to code OnBnClickedOk to replace

I already recognized a valid looking implementation above:

Just, type  'admin' and 'admin123' and it should work.

You might set a breakpoint to the function and check whether the pContext variable got properly set from CMainFrame.

Regards, Alex
0
 

Author Comment

by:blubbbb
ID: 10832836
It starts now, but somehow I always get the "Invalid username" Box, whatever I enter.

I've made m_Name and m_Pw with the wizard by right clicking on the fields, "add variable" and used the typ "value".
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 160 total points
ID: 10832863
It was my fault.

Change to

     UpdateData(TRUE);  // get values from Screen

as UpdateData(FALSE) puts old values to screen.

Regards, Alex




0
 

Author Comment

by:blubbbb
ID: 10834221
Wow, it's finally working. I think I should be able to continue on my own now.

Thanks a lot for your help!

But one little question left:
If I enter a wrong password, the program crashes in debug modus and jumps to:
pNextView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
        CFrameWnd::rectDefault, GetParent(), AFX_IDW_PANE_FIRST, pContext);

With the right name/pw and wrong name it works, just right name and wrong pw doesn't.

Thats how this looks on the OK Button where I want to check if name/pw was right:
    if (m_Name == "admin")
    {
          if (m_Pw == "admin123")
          {
               pNextView = new adminmenu();
          }
          else
          {
               MessageBox("Wrong Password");
          }
    }
    else
    {
        AfxMessageBox("Invalid username " + m_Name, MB_OK);
        return;
    }
Whats wrong with that?

If I can't get this to work, can I just use this?
    if (m_Name == "admin")
    {
          if (m_Pw == "admin123")
          {
               pNextView = new adminmenu();
          }
    }
    else
    {
        MessageBox("Invalid username or password");
        return;
    }
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10834397
Add a return statement in case a wrong password is given.

    {
        AfxMessageBox("Falsches Passwort", MB_OK);
        return;          // PREVENTS FALLING THRU
    }    

The next steps are:

1. Change CQS_ToolBaseView to be derived from CRecordView. You have to make changes
    in header and cpp.
2. All new views should get
            virtual CRecordset* OnGetRecordset();
   Just copy it from CQS_ToolView
3. Then, derive CQS_ToolView from CQS_ToolBaseView. You have to make changes
    in header and cpp. Search for CRecordView and replace it.

Regards, Alex
   
0
 

Author Comment

by:blubbbb
ID: 10842743
I've done this, and got:

QS_Tool error LNK2001: Nichtaufgelöstes externes Symbol "public: virtual class CRecordset * __thiscall adminmenu::OnGetRecordset(void)" (?OnGetRecordset@adminmenu@@UAEPAVCRecordset@@XZ)

in every of the new view classes.

And how do I code a "back" or "logout" button on one of the new dialogs/views? That closes the new view and goes back to the login view.

I've tried to copy some text from the OK-Button on the login view and replaced
pNextView = new adminmenu();
with
pNextView = new CQS_ToolView();
but that didn't work.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10843124
>> QS_Tool error LNK2001: Nichtaufgelöstes externes Symbol "public: virtual class CRecordset * __thiscall adminmenu::OnGetRecordset(void)"
>> ? OnGetRecordset@adminmenu@@UAEPAVCRecordset@@XZ)

You forgot to copy the function OnGetRecordSet() from CQS_ToolView.cppy to all other views ccp file (by changing the class name)..

>> And how do I code a "back" or "logout" button on one of the new dialogs/views?
>> I've tried to copy some text from the OK-Button on the login view

Yes, that's the way to do it. You have to adopt the functionality of CQS_ToolView::OnBnClickedOK() to e. g. adminmenu::OnBnClickedLogout().

- Get a new CQS_ToolView (pointer)(did you made the constructor public as with the other views?)
- Get the CMainFrame pointer.
- Get the Context* of document/view creation from mainframe pointer
- Create the window using Create function. That will also add the view to the document - if the context still is ok.
- Remove the current view from document
- call DestroyWindow to get the adminmenu view destroyed (deleted) (you have to overlaod PostNcDestroy function as you have done it in CQS_ToolView,cpp)

Tell me, if there are problems.

Regards, Alex



0
 

Author Comment

by:blubbbb
ID: 10853342
This is my back-button code:
///////////////////////////////////////////////////////////////////
CMainFrame* pFrame = (CMainFrame*)GetParentFrame();
CCreateContext* pContext = pFrame->m_pContext;  // here we get the frame context
pContext->m_pLastView = this;
pContext->m_pNewViewClass = NULL;

CQS_ToolView* pLoginView;
//CQS_ToolBaseView* pLoginView;
//pLoginView = new CQS_ToolView();
      
// Es wird ein Fenster erstellt, und an das FormView angehängt
pLoginView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
CFrameWnd::rectDefault, GetParent(), AFX_IDW_PANE_FIRST, pContext);

GetDocument()->RemoveView(this);
pLoginView->ShowWindow(SW_SHOW);
   
pFrame->SetActiveView(pLoginView);
pFrame->RecalcLayout();
DestroyWindow();            // Altes View schliessen
///////////////////////////////////////////////////////////////////

Will return some errors, first one:
error C2065 CQS_ToolView nicht deklarierter bezeichner

If I include QS_ToolView.h it will return some errors in this file, first one of them:
error C2143 syntaxfehler: es fehlt ; vor * in:
CQS_ToolDoc* GetDocument() const;

If I include QS_ToolDoc.h it will return even more errors.


If I replace
CQS_ToolView* pLoginView;

with
CQS_ToolBaseView* pLoginView;
pLoginView = new CQS_ToolView();

It will return:
error C2061: Syntaxfehler: Bezeichner CQS_ToolView

If I include QS_ToolView.h it will return the same errors as above:
error C2143 syntaxfehler: es fehlt ; vor * in:
CQS_ToolDoc* GetDocument() const;


Besides that, if I comment the text on this button out, and Login in my program, it will crash with:
Unbehandelte Ausnahme bei 0x7c1e8651 (mfc71d.dll) in QS_Tool.exe:
0xC0000005: Zugriffsverletzung-Leseposition 0xcdcdcdd1.

and spring to here:
BOOL CRecordset::IsOpen() const
{
    if(m_hstmt == NULL) <--------
        return FALSE;

    ........

line 1232 in dbcore.cpp

I've already implemented the database support, so it will read the logins out of a table and compare them with the entered ones.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10853516
>> error C2065 CQS_ToolView nicht deklarierter bezeichner

You have been right: CQs_ToolView.h must be included

>> error C2143 syntaxfehler: es fehlt ; vor * in:
>> CQS_ToolDoc* GetDocument() const;

That is because the new views don't seem to have a GetDocument() function. In your new classes you should have this:

class adminmenu : public CQS_ToolBaseView
{
    ...

public:
      CQS_ToolDoc* GetDocument() const  {  return (CQS_ToolDoc*)CRecordView::GetDocument();  }
};

That function normally gets created from Class Wizard. It gives you a pointer to the document that is associated with all the views. The framework gets the class name and document pointer from the pContext member that we hold in the CMainFrame class. You may copy the declaration and implementation of GetDocument() from your CQS_ToolView class, also, but the implementation should be similar. Don't forget to include CQS_ToolDoc.h in the header files of your new views.

>> 0xC0000005: Zugriffsverletzung-Leseposition 0xcdcdcdd1.

The Debugger initializes all member  pointers with that value. So, this error indicates that you are trying to use a pointer that hasn't been created with 'new'.

Regards, Alex




0
 

Author Comment

by:blubbbb
ID: 10855293
I have no idea where this pointer without new should be. This error started to show up recently. Everything but a login with success works fine, so it might be on the login button? But it already worked once before with the same code as now:

void CQS_ToolView::OnBnClickedOk()
{
    UpdateData(TRUE);

    CMainFrame* pFrame = (CMainFrame*)GetParentFrame();
    CCreateContext* pContext = pFrame->m_pContext;
    pContext->m_pLastView = this;
    pContext->m_pNewViewClass = NULL;

    CQS_ToolBaseView* pNextView = NULL;

    CString feld_login_name;
    CString feld_login_passwort;
    CString      feld_login_art;

      m_pSet->MoveFirst();
      while(!m_pSet->IsEOF())
      {
            feld_login_name            = m_pSet->m_loginName;
            feld_login_passwort = m_pSet->m_loginPasswort;
            feld_login_art            = m_pSet->m_loginPerm;
                        
            if(m_Name == feld_login_name)
            {
                  if(m_Pw == feld_login_passwort)
                  {                        
                        switch(feld_login_art[0])
                        {
                        case '1':      // Admin
                              pNextView = new adminmenu();
                              break;
                        case '2':      // Teilnehmer
                              pNextView = new tnmenu();
                              break;
                        case '3':      // Dozent
                              pNextView = new dozentenmenu();
                              break;
                        case '4':      // Mandant
                              pNextView = new mandantenmenu();
                              break;
                        }
                        pNextView->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
                        CFrameWnd::rectDefault, GetParent(), AFX_IDW_PANE_FIRST, pContext);
       
                        pNextView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);

                        GetDocument()->RemoveView(this);
                        pNextView->ShowWindow(SW_SHOW);
   
                        pFrame->SetActiveView(pNextView);
                        pFrame->RecalcLayout();
                        DestroyWindow();      
                        return;
                  }
                  else
                  {      
                        AfxMessageBox("Falsches Passwort", MB_OK);
                        return;
                  }
            }
            m_pSet->MoveNext();
      }
      AfxMessageBox("Falsches Login", MB_OK);
      return;
}
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10855374
>> If I include QS_ToolView.h it will return the same errors as above:
>> error C2143 syntaxfehler: es fehlt ; vor * in:
>> CQS_ToolDoc* GetDocument() const;

Maybe a forward declaration is missing. Try to add

class CQS_ToolDoc;

above your class declaration

class CQS_ToolView : public CQS_ToolBaseView
{
    ....
};

>> Besides that, if I comment the text on this button out, and Login in my program,

What do you mean by "I comment the text on this button out" ?

>> Unbehandelte Ausnahme bei 0x7c1e8651 (mfc71d.dll) in QS_Tool.exe:
>> 0xC0000005: Zugriffsverletzung-Leseposition 0xcdcdcdd1.

To localize the error set a break point somewhere before crash. Add 'Debug Menu' after Debugger i started. Goto 'Exceptions.. " or "Ausnahmen...". There you should se a list of exceptions. Select 0xC0000005 access violation and check the button 'Stop always' (maybe 'Immer anhalten'). After that leave the Debug Menu and goto crash. Open the stack window and select the top-most function that contains your code or contains MFC C++  (not assembler). Check all local pointer you see in the Local Variables window. None of them should have value '0xcdcdcdcd' or any other constructed value.

If you have still problems, you may zip the whole project (make a clear before as i need no *.obj; *.exe; *.sbr; *.ilk; *.pch *.res) and don't forget database if it is an access db - and send it to info@sbsweb.info.

Regards, Alex





0
 

Author Comment

by:blubbbb
ID: 10857419
>> If I include QS_ToolView.h it will return the same errors as above:
>> error C2143 syntaxfehler: es fehlt ; vor * in:
>> CQS_ToolDoc* GetDocument() const;
I've already fixed that.

>What do you mean by "I comment the text on this button out" ?
I wasn't able to start the program because the "Back"-button had errors in the code. So I turned the code on this button with /**/ into a comment to start the program without the function of the button.

But now it should work fine, I just have this error in the debugger.
I've found out the variable "this" might be at faut, it looks like this:

Name                 Value                                          Type
this                    0xcdcdcdcd {CRecordset}              const CRecordset * const
   nRetCode        -13108                                         short
   bOpen             -858993460                                 int
   nCols              -13108                                         short

But don't know how to fix it.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10857962
You remember? We first created the new views by deriving them from CFormView and not from CRecordView. The main difference is - as CRecordView is derived from CFormView also - that CRecordView has an association to a CRecordset instance where you may iterate thru an ODBC table. Now, you have an unitialized CRecordset pointer in your new view classes. That means, that there is some initializing code missing:

Yo'll find a member variable m_pSet in CQSToolView class and a lot of implementation around this. You have to copy all code to your new view classes. Don't forget the wizard code and message maps and ignore the hint that you shouldn't make changes in that area.

Good luck.

Alex
0
 

Author Comment

by:blubbbb
ID: 10858619
I've tried to copy everything to the new classes that should do something, but didn't bring it to work.

I've mailed the project now, hope you can find the error.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10859930
You have to change OnGetRecordset() for all views as it wll called before OnInitialUpdate ... sometimes, e. g.

// CQS_ToolView Datenbankunterstützung
CRecordset* CQS_ToolView::OnGetRecordset()
{
    if (m_pSet == NULL)                             // That pointer was NULL
        m_pSet = &GetDocument()->m_QS_ToolSet;
    return m_pSet;
}

I've found a few statements that should be changed also:

In all view cpp replace CQS_ToolBaseView by CRecordView in the IMPLEMENT_DYNCREATE and BEGIN_MESSAGE_MAP macro. That is because CQS_ToolBaseView has neither message handling nor dynamic creation. My VC6 compiler denies to compile then. Although VC7 seems to be more generous, you should change it as it isn't correct.

In mainfrm.cpp delete the m_pContext pointer in the destructor:

CMainFrame::~CMainFrame()
{
    delete m_pContext;
}

Regards, Alex


IMPLEMENT_DYNCREATE(CQS_ToolView, CRecordView)

BEGIN_MESSAGE_MAP(CQS_ToolView, CRecordView)


0
 

Author Comment

by:blubbbb
ID: 10861872
>Although VC7 seems to be more generous, you should change it as it isn't correct.
Yes, it compiles now. The Release version refuses to work with "unresolved extern symbol", but the Debug version is working, so I'll just use this version. I already had the same LNK error with the release but not debug in another version of the program where I made a new class for the "back"-button.

I may add extra functionality and expand the program later, but now I have what I wanted at the beginning. I should be able to make the buttons on the other views work now.

Once again, thanks a lot for your time, it really helped a lot.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10866374
To get your Release version working you have to replace GetDocument() declaration in CQS_ToolView.h by this:

#ifdef _DEBUG
     CQS_ToolDoc* GetDocument() const;                   // that's the line you have now
#else
     CQS_ToolDoc* GetDocument() const
     {       return (CQS_ToolDoc*)m_pDocument; };
#endif

The problem is, that implementation in CQS_ToolView.cpp is only compiled in DEBUG Version as there is #ifdef _DEBUG before.

Regards, Alex

0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
notReplace  challenge 53 102
dog bark java program 15 82
matchUp  challenge 9 72
Annoying "thing" blocks my view 4 51
This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.

759 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

19 Experts available now in Live!

Get 1:1 Help Now