Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Linking a CFrameWnd class to a resource

Posted on 2004-08-03
30
Medium Priority
?
1,282 Views
Last Modified: 2013-11-20

I am aware that what I am about to ask is vague, but once i get a push in the right direction, I can start to be more specific.

My situation is that I am continuing someone else's project.
The code that opens the main window of the application is done in a way I've never used before, and so am confused about.

It is :

      CMainFrame* pFrame = new CMainFrame();
      m_pMainWnd = pFrame;

      pFrame->LoadFrame(IDR_MAINFRAME,
            WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,
            NULL);

      pFrame->ShowWindow(SW_SHOW);
      pFrame->UpdateWindow();

and this occurs in the InitInstance() method, where CMainFrame is derived from CFrameWnd.

Am i correct in saying that this window is being created on the fly, using the IDR_MAINFRAME toolbar resource only.

Let's say I want to edit this window, add some buttons, change its look and so on.
Up until now I have only done this through editing the resources directly. Since this dialog doesn't exist in the ResourceView, how can I do this?


Cheers for any ideas.
0
Comment
Question by:pikco
  • 11
  • 10
  • 5
  • +1
30 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 11711990
>Am i correct in saying that this window is being created on the fly, using the IDR_MAINFRAME toolbar resource only.
Yes, you are, it looks like it is not a doc/view architecture project.

>Let's say I want to edit this window, add some buttons, change its look and so on.
This must be done inside CMainFrame implementation (mainfrm.cpp), because this window it is NOT associated with any graphical template like dialog do.
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 11713139
I suspect inside the frame a dialog will be created dynamically (eg in the OnCreate of the Frame).  It is this dialog resource you need to edit and add buttons and other controls to.
0
 

Author Comment

by:pikco
ID: 11714271
thanks for your replies..

so Jaime, does that mean that I need to add buttons etc. in code?
is this easy to do?
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 3

Expert Comment

by:jimbucci
ID: 11715924
In OnCreate() you can do pretty much anything you want to change the look of the window.  
I would suggest using PreCreateWindow() if you want to set the system properties of the window - like the close button and the minimize/maximize buttons.  You can also remove the menu here - at least that's what I do.

Since you are not using a dialog resource to create a view inside the mainframe then you will have to add buttons manually.  You can also modify/add toolbars here.

Jim
0
 

Author Comment

by:pikco
ID: 11716138

ahhh, okay, so where can i find out how to add buttons manually?
0
 
LVL 3

Expert Comment

by:jimbucci
ID: 11716315
The easiest way is to add some CButton objects to your CFrameWnd derived class then create them in OnCreate().
Call CButton::Create(...) then if need be call MoveWindow() for the buttons.  You will need an event handler for each button.

Sometimes it's just easier to create a view class then create the view and place it into the frame.
Jim
0
 
LVL 55

Assisted Solution

by:Jaime Olivares
Jaime Olivares earned 399 total points
ID: 11716817
in mainfrm.h:

class CMainFrame : public CFrameWnd
{
      // some members
   
      CButton m_Button1, m_Button2, etc...

      // some functions

      void OnClicked1();
      void OnClicked2();    // Buttons event handlers
}

in mainfram.cpp:

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
      //{{AFX_MSG_MAP(CMainFrame)
      ON_WM_SIZE()
      ON_WM_CREATE()
      //}}AFX_MSG_MAP
      ON_NOTIFY(BN_CLICKED, ID_BUTTON1, OnClick1)   // <---- Add those events manually
      ON_NOTIFY(BN_CLICKED, ID_BUTTON2, OnClick2)
END_MESSAGE_MAP()

CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
       // Some code

       CRect rect(0,0,1,1);   // dummy values
       m_Button1.Create(WS_CHILD|WS_VISIBLE, rect, this, ID_BUTTON1  );
       m_Button2.Create(WS_CHILD|WS_VISIBLE, rect, this, ID_BUTTON2  );
}

CMainFrame::OnSize(UINT nType, int cx, int cy)
{
       // Some code

       // You can make your controls to resize, according to frame size

       m_Button1.MoveWindow(CRect(10,10,cx-20,25);
       m_Button2.MoveWindow(CRect(10,40,80,55);
}

// add these handlers manually

void CMainFrame::OnClicked1()
{
    // some action here
}

void CMainFrame::OnClicked2()
{
    // some action here
}
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 11717546
I would still put a dialog into the frame - no need to do the controls in code, you do them in the resource editor as you would any other dialog.

Just have a member var that is a pointer to the dlg, in the OnCreate of the frame use new to create a new dialog then create.
0
 

Author Comment

by:pikco
ID: 11723218
AndyAinscow:

That sounds like exactly what I should do, since its probably faster to do than in code.
I'm still not sure how to do it yet though.

Since it alraedy creates a dialog on the fly, does this mean it will open up two if I do this?

Thanks for your replies also.
0
 
LVL 45

Accepted Solution

by:
AndyAinscow earned 402 total points
ID: 11723610
You have created a frame, not a dialog.  What I am saying is that when the frame is created you create a dialog (as you would a modeless dialog) and have the parent of the dialog your frame and it is positioned inside the frame to fill the client area.  I would suggest creating this child dialog in the OnCreate of the frame (delete the pointer to the dialog in the destructor of the frame to prevent memory leaks).

eg.  (very roughly)
in header for the frame
CMyDlg* m_pMyDlg;  //CMyDlg is the dialog class you want in the frame

in the .cpp file

int CMyFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
      if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
            return -1;
      
      m_pMyDlg= new CMyDlg(this);
      if (!m_pMyDlg->Create(this,
            WS_CHILD | WS_VISIBLE, 0))
      {
            delete m_pMyDlg;
            m_pMyDlg= NULL;
            return -1;
      }

//the following may need some tweaking to get it sized correctly
      CRect rectClient, rectWindow;
      m_pMyDlg->GetWindowRect(rectWindow);

      SetWindowPos(NULL, 10, 10,
            rectWindow.Width()+20, rectWindow.Height()+20,//20 is just a fudge, you ought to allow for borders, titlebar...
            SWP_NOZORDER | SWP_NOACTIVATE);

      GetClientRect(rectClient);
      m_pMyDlg->SetWindowPos(NULL, 0, h,
            rectClient.Width(), rectClient.Height(),
            SWP_NOZORDER | SWP_NOACTIVATE);

return 0;
}

It may
0
 

Author Comment

by:pikco
ID: 11725488

Hey, thanks for that reply.
I think its getting warmer now, using that idea my main dialog now opens up to be the same size as the CMyDlg class dialog, however, I still can't see any of the things I add in the resource editor. what could i be forgetting?
0
 
LVL 3

Assisted Solution

by:jimbucci
jimbucci earned 399 total points
ID: 11725529
Basically that's what the CFormView class does - you create a dialog resource for the view then pull the view into your frame.  When you create a MFC application with doc/view architecture that's what the wizard does.
Here' some code:

BOOL CMyFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
   if (!CFrameWnd::OnCreateClient(lpcs, pContext))
        return FALSE;
   
    // Create the view (with no document)
    CCreateContext sContext;
    sContext.m_pNewViewClass    = RUNTIME_CLASS(CMyFormView);
    sContext.m_pCurrentDoc      = NULL;
    sContext.m_pNewDocTemplate  = NULL;
    sContext.m_pLastView        = NULL;
    sContext.m_pCurrentFrame    = this;

    m_pFormView = (CMyFormView*) CreateView(&sContext);

    if(!m_pFormView)
        return FALSE;

    SetActiveView(m_pFormView);
    ShowOwnedWindows(TRUE);

    m_pFormView->SetFocus();
    m_pFormView->UpdateWindow();
   
    return TRUE;
}

You add a new MFC class derived from CFormview.  You will then be placed into the resource editor for the dialog resource you will use for the formview.

I hope this helps
Jim
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 11725890
m_pFormView->ShowWindow(SW_SHOW);

does that help?
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 11725893
Your form view is based on the dialog isn't it?
0
 
LVL 3

Expert Comment

by:jimbucci
ID: 11726006
Calling ShowWindow() is not necessary because of the call to ShowOwnedWindows().

CFormviews are CView classes based on a dialog resource - similar to VB forms.  You can pop them in and out like CViews and they can be used in splitters.  I use them quite a lot.

Jim

0
 

Author Comment

by:pikco
ID: 11732698
Yeah, ShowWindow() opens up the original dialog as well as the new dialog.

Jim, would this work in my case,

sContext.m_pNewViewClass    = RUNTIME_CLASS(CMyFrame);   doesn't seem to like my class

SetActiveView(m_pMyDlg);    the method is looking for a CView?

I'm not sure what CMyFormView in your example is, is it a class derived from a dialog?


Thanks.
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 11733617
pikco - you are getting a mix of my idea and that from jimbucci.

I am suggesting a modeless child DIALOG inside your frame.  The other is a CFormView based view inside the frame.
Please post some code so we know what you are doing.

0
 
LVL 3

Expert Comment

by:jimbucci
ID: 11742128
CMyView is a CFormView derived class.  The sContext.m_pNewViewClass requires a CView derived class - placing the frame in their would probably just fail.  SetActiveView requires a CView derived class.

All of the code I provided is for using a CView derived class with a CFrameWnd derived class.  The MFC framework handles a lot of the placement and creation of the windows for you - although you can still set the size of the view as you wish.

Using a dialog as a child to a frame window would work just fine - the fact is that I've never done it.  Using the MFC frame-view type of UI seemed easier to me.  

The best way to try what I suggest is to create a new project and where you select the type of view class select CFormView.  You will then be presented with the resource editor for the dialog.  If you run the program your dialog resource will show in the view.  Looking at the code should reveal how the view gets inside the frame.

Jim

0
 

Author Comment

by:pikco
ID: 11742557
Andy:

My code at the moment is pretty similar to what you suggested earlier:

    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
          return -1;
     
     m_pMyDlg= new CMyFrame(this);

      
     if(!m_pMyDlg->Create(NULL,NULL,WS_CHILD | WS_VISIBLE,CRect(0,0,0,0),this,NULL))
     {
          delete m_pMyDlg;
          m_pMyDlg= NULL;
          return -1;
     }

//size later
     CRect rectClient, rectWindow;
     m_pMyDlg->GetWindowRect(rectWindow);

     SetWindowPos(NULL, 10, 10,  rectWindow.Width()+20, rectWindow.Height()+20,//check later          SWP_NOZORDER | SWP_NOACTIVATE);

     GetClientRect(rectClient);
     m_pMyDlg->SetWindowPos(NULL, 0, 0,
          rectClient.Width(), rectClient.Height(),
          SWP_NOZORDER | SWP_NOACTIVATE);


At the moment it will open up the dialog as before, at the same size as the CMyFrame dialog.
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 11742635
from help

CDialog::Create
BOOL Create( LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL );

BOOL Create( UINT nIDTemplate, CWnd* pParentWnd = NULL );


Is your m_pMyDlg based on a CDialog derived class?
 
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 11742799
I think you was in the right way when presenting on a CFrameWnd.
0
 

Author Comment

by:pikco
ID: 11742956
Andy:

Yeah, interesting about that, my class definitely is derived from CDialog:

CMyFrame::CMyFrame(CWnd* pParent /*=NULL*/)
      : CDialog(CMyFrame::IDD, pParent)
{   etc......

When i use the classwizard to get the Create method, i get:

BOOL CMyFrame::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
      // TODO: Add your specialized code here and/or call the base class
      
      return CDialog::Create(IDD, pParentWnd);
}

0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 11743268
I am really confused as to what is what in your app.  Please check the header, you should have something like
class CMyFrame : public CDialog
0
 

Author Comment

by:pikco
ID: 11745048
Yes, in the header:


/////////////////////////////////////////////////////////////////////////////
// CMyFrame dialog

class CMyFrame : public CDialog
{
// Construction
public:
      CMyFrame(CWnd* pParent = NULL);   // standard constructor

etc.........
0
 

Author Comment

by:pikco
ID: 11745051
What I wrote before was from the .cpp file.
0
 

Author Comment

by:pikco
ID: 11771603
Is it fair for me to close this question off?
I haven't really received any ideas that have worked.
Any objections let me know ;)
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 11772699
Does my idea have not worked? Apparently using a dialog template could be simpler, but you have verified this is not necessarily true. When you work with a frame window, it is better to make controls directly as childs, in my opinion.
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 11780768
This advice may be of help.  It really depends on how much was done by your colleague before you took the app over.

Ask yourself the following questions.
Do I need a toolbar?
Do I need a menu?
Do I need a statusbar?
Will I be using accelerators? (Press alt+A and it acts as if you had pressed a button for example)

If the answers are no then create a new dialog based project.
If an answer is yes then create a new SDI, modify settings as required (KEEP doc/view) and at the final stage change the CView to CFormView.  That will create a dialog resource that you can use the resource editor to add buttons ... to.

A bit of info maybe you don't know.  The dialog based app does NOT automatically provide support for some user interface updating and actions the way a SDI/MDI based project does.  Doing the above will mean you have less to code if you did require one of those features in your app.
0
 

Author Comment

by:pikco
ID: 11782913
It doesn't really help, but thanks for the advice anyway. I've chosen to just continue workign on top of the old interface.

I think best thiing for me to do is award points across the 3 of you for being so nice and helping.
On an aside, If any of you three want to point me in the direction of some good garbage collection tips or classes that do it for you if such things may exist, that would be nice too.

=)
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 11782954
I don't like garbage collection in general - A memory leak tells me I haven't got the logic correct.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
If you use Adobe Reader X it is possible you can't open OLE PDF documents in the standard. The reason is the 'save box mode' in adobe reader X. Many people think the protected Mode of adobe reader x is only to stop the write access. But this fe…
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.
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Suggested Courses

824 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