MFC document/view woes
I'm programming a tile editor for one of my games. Here is my setup.
I've got a tile window docked to the main frame window and I've written specialized code to handle drawing, selecting, scrolling, etc, for the tiles. I want this to be docked so I derived it from CDialogBar so I could get docking functionality.
Here is the problem. CDialogBar can only be created inside of CFrameWnd::OnCreate so the CDialogBar derived class which I call CTileDlgBar can only be used inside of the CFrameWnd derived class - CMainFrame.
Ok but I also need to know the tilesize being used in my app so I can correctly draw the tiles in the larger view window which resides in the main frame.
My system does not extract tiles from large bitmaps. Rather the entire bitmap is loaded and you select a cursor or 'grabber' size rectangle and when you click the LMB on a bitmap in the TileDlgBar, it automatically extracts the bitmap that resides in the chosen rectangle.
Now when you click in the view window, I want the bitmap that was selected in the docked dialog window to appear in the view.
Here is the problem. How the heck can I pass the bitmap from the dialog window class to the view window class? If you know how the document/view architecture works you will understand that just creating a function to pass a pointer to the CView class doesn't work. Since the dialog class is a member of the frame window class and the frame window doesn't know anything about the view - or at least every time I call GetActiveView() it returns a NULL pointer......I can't pass any information between them.
I was going to use this:
CMapView *map=(CMapView *)GetActiveView();
Then the view would have a pointer to the dialog bar class and everything works great. But every frieking time I do this, the pointer returned is NULL as if there is no active view.
How can I use this cool dialog bar I coded given the major restraints inherent in the doc/view architecture? According to MS, my document should hold the data - so are they saying that my dialog should report back to the document class? It's not possible. The dialog bar cannot be in the document class...there is no way to create it and attach it to the frame window.
I'll include a screenshot so you guys can see what's going on.
When using the Doc/View "architecture", don't feel like your code is constrained to any kind of framework.
Basically, all you need is "global" access to your CTileDlgBar object. So an easy change would be to have your view call:
Ok, so that will get a pointer to everything I need. Should I put TileDlgBar elsewhere? It's very confusing reading the docs supplied with MFC. I don't want to work against the framework but I really don't know where to put the stupid thing.
So AfxGetMainwnd() will return a CFrameWnd()? or just a CWnd()? So casting from a CWnd to CFrameWnd is allowed?
Thanks. MFC isn't too bad and I'm getting fairly good at it, but there are some constraints in the doc/view that...well....I just don't get.
>> I don't want to work against the framework but I really don't know where to put the stupid thing.
This is exactly how I felt when I started learning and using MFC. You don't really "work against" the framework - you just utilize what you know of it. My first MFC project was an SDI app with 90% of the code implemented right in the view. And the CDocument derived class looked exactly as it did when the wizard generated it. I've not used CDocument derived classes in several projects.
>>...but there are some constraints in the doc/view that...I just don't get.
To this day, I still find myself asking, "now how the hell do I get a pointer to the view from here?". I use doc/view so little that hardly any of it stays in my head. This is where a good [reference] book comes in handy. I'll use it to refresh my memory then hit up MSDN to fill in the rest.
>>Should I put TileDlgBar elsewhere?
Nah. Let CMainFrame contain it physically and in code.
>>So AfxGetMainwnd() will return a CFrameWnd()?
AfxGetMainWnd() returns the m_pMainWnd of the application object. If you look in your InitInstance(), you'll see where m_pMainWnd is a heap allocated instance of CMainFrame, which is a derived class of CFrameWnd. We can upcast the pointer returned from AfxGetMainWnd() because we know what it is.
Ok will do. Thanks for your help. I tried this doc/view stuff some years ago with Borland OWL or Object Windows Library. It really was not much different than MFC, but I must say MFC is easier because of the way classes are created. I really like classes with void constructors and with a specific Create function. I'm not sure how Bjarne would feel about it, but I really am starting to dislike constructors that require params more and more. At least you know in MFC that the object is indeed valid and it is your use of the object that is probably incorrect.
In OWL sometimes your constructor would fail and it was because of one of the params. Perhaps it's just a matter of style or taste, but I really like MFC's constructor a lot better. In fact all my constructors in my engine code and games require 0 parameters.
When I had problems with doc/view last time I thought it was because I just wasn't good enough at C/C++ - now I know that is not the case this time. But it doesn't make it any less frustrating.
With such a big vast framework to use often times I wonder - ok I just created this big class....but perhaps there is already a class in MFC that does what I want. It is this check and balance stuff that is driving me nuts. Since I'm a video game programmer I often tend to write my own code to do everything just as I want. In MFC often this results in me re-inventing the wheel and actually making the project harder and slower in dev time than it should be.
But you gotta admit that you like how I got docking window functionality with just a few changes in a generic CWnd class. I don't know why ClassWizard will not let you specify CDialogBar and certain other classes as bases.