User-Interface Threads with Doc/View inside
Paulo Soares -- psoares@ip.pt
Thursday, August 22, 1996
Environment: VC++ 4.2, Windows95
I need to provide an application with an RTF editing window. This window =
should popup when a button is pressed and will edit text that will =
go/come to/from a database. One solution would be to create a temporary =
file and call wordpad or another editor. Other solution would be to =
create a memory mapped file and call a modified wordpad to avoid the =
creation of file on disk.
I don't want to load another editor, it takes too much time.
Creating an RTF editor with CRichEditCtrl in a dialog is possible but I =
would loose the graphics and CRichEditView is so near.
I thought (I'm so naive) that it would just be a matter of creating an =
User-Interface thread, put the CRichEditView and friends inside and the =
problem would be solved. After all, it's all derived from CWinThread. =
Wrong! The doc/view model is tightly coupled to CWinApp and there can be =
only one (like the Immortal).
To make my tests I started with the application MyWord from Jeff =
Prosise's book 'Programming Windows 95 in MFC'. This is a simple RTF =
editor and works pretty well as a stand alone. It derives from =
CRichEditView. I managed to get something to appear when I eliminated =
the CSingleDocTemplate and replaced it with:
BOOL CWordApp::InitInstance ()
{
/* CSingleDocTemplate* pDocTemplate;
pDocTemplate =3D new CSingleDocTemplate (
IDR_MAINFRAME,
RUNTIME_CLASS (CWordDoc),
RUNTIME_CLASS (CMainFrame),
RUNTIME_CLASS (CWordView)
);
AddDocTemplate (pDocTemplate);
*/
m_pDocManager->AddDocTemplate(pDocTemplate);*/
CMainFrame* pMainFrame =3D new CMainFrame;
pMainFrame->ShowWindow(SW_SHOWNORMAL);
pMainFrame->UpdateWindow();
m_pMainWnd =3D pMainFrame;
CWordView *wv =3D new CWordView;
wv->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
CRect(0,0,0,0), pMainFrame, AFX_IDW_PANE_FIRST, NULL);
=20
m_pMainWnd->DragAcceptFiles ();
CWordDoc *wd =3D new CWordDoc;
wd->AddView(wv);
pMainFrame->SetActiveView(wv);
return TRUE;
}
The view edits text and graphics but the tool bar and status bar don't =
appear and if I call them explicitly they appear but ASSERT when =
GetActiveView is called. The value in InitInstance is correct but is =
changed somewhere to 0xfdfdfdfd.
The books I have on MFC are OK when explaining the doc/view model in =
CWinApp with CSingleDocTemplate but don't say anything about using the =
model in a user-interface thread.=20
Can anyone shed some light on this matter?
Best Regards,
Paulo Soares
psoares@ip.pt
Rommel Songco -- rsongco@spectrasoft.com
Monday, August 26, 1996
Hello there!
In multithreaded applications, you are going to have problems at times if
you call member functions belonging to objects created by other threads.
You said that you get an ASSERT when GetActiveView is called. I would
guess that this is a member function of your CMainFrame in the main thread
and that you're calling this from the child thread.
Regards,
Rommel
rsongco@spectrasoft.com
Gordon Weakliem -- gweakl@metronet.com
Tuesday, August 27, 1996
Paulo Soares wrote:
<...>
> I thought (I'm so naive) that it would just be a matter of creating an User-Interface thread,
>put the CRichEditView and friends inside and the problem would be solved. After all, it's all
>derived from CWinThread. Wrong! The doc/view model is tightly coupled to CWinApp and there can
>be only one (like the Immortal).
One what? CWinApp, CWinThread or CView? You can have multiple threads per app. You can have
as many views as you like per document. But you already know that if you've gotten this far.
The trick is to define your doc so it encapsulates all the data you might want to view; then you
can have each view display any piece of it it wants to. Now, I haven't had any experience with
CRichEditView, and I've heard that it's not so easy to work with as the simpler views, but the
principle is still there.
>From your code sample, it looks like the problem is that you're not creating a CDocTemplate.
This is the heart of the framework; without it, you'll find that none of the free stuff you get
with MFC works anymore. GetActiveView() ASSERTs because it is going to walk the view list that
AddDocTemplate() added your view to. So unless you add a doc template, GetActiveView is going
to return NULL, it finds nothing on the list and ASSERTs that the value it's about to return
isn't NULL. Furthermore, your toolbars are created in the CSingleDocTemplate constructor (the
2nd argument). Since you don't call the constructor, these aren't created.
The bottom line is that you need a Doc template. If you've got an SDI app, this is going to be
tricky, but I suspect it can be done.
>
> BOOL CWordApp::InitInstance ()
> {
> /* CSingleDocTemplate* pDocTemplate;
> pDocTemplate = new CSingleDocTemplate (
> IDR_MAINFRAME,
> RUNTIME_CLASS (CWordDoc),
> RUNTIME_CLASS (CMainFrame),
> RUNTIME_CLASS (CWordView)
> );
>
> AddDocTemplate (pDocTemplate);
> */
> m_pDocManager->AddDocTemplate(pDocTemplate);*/
> CMainFrame* pMainFrame = new CMainFrame;
> pMainFrame->ShowWindow(SW_SHOWNORMAL);
> pMainFrame->UpdateWindow();
> m_pMainWnd = pMainFrame;
> CWordView *wv = new CWordView;
>
> wv->Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
> CRect(0,0,0,0), pMainFrame, AFX_IDW_PANE_FIRST, NULL);
>
> m_pMainWnd->DragAcceptFiles ();
> CWordDoc *wd = new CWordDoc;
> wd->AddView(wv);
> pMainFrame->SetActiveView(wv);
> return TRUE;
> }
>
> The view edits text and graphics but the tool bar and status bar don't appear and if I call them explicitly they appear but ASSERT when GetActiveView is called
> The books I have on MFC are OK when explaining the doc/view model in CWinApp with CSingleDocTemplate but don't say anything about using the model in a user-int
>
--
Gordon Weakliem
gweakl@metronet.com
http://www.metronet.com/~gweakl
Paulo Soares -- psoares@ip.pt
Thursday, August 29, 1996
[Mini-digest: 2 responses]
On Tuesday, August 27, 1996 12:13 PM, Gordon =
Weakliem[SMTP:gweakl@metronet.com] wrote:
>>From your code sample, it looks like the problem is that you're not =
creating a CDocTemplate. =20
>This is the heart of the framework; without it, you'll find that none =
of the free stuff you get=20
>with MFC works anymore. GetActiveView() ASSERTs because it is going to =
walk the view list that=20
>AddDocTemplate() added your view to. So unless you add a doc template, =
GetActiveView is going=20
>to return NULL, it finds nothing on the list and ASSERTs that the value =
it's about to return=20
>isn't NULL. Furthermore, your toolbars are created in the =
CSingleDocTemplate constructor (the=20
>2nd argument). Since you don't call the constructor, these aren't =
created.
The problem is that I cannot use AddDocTemplate() as this is a member of =
CWinApp and I cannot have a CWinApp in a user-interface thread. The =
documentation states that there can only be one CWinApp in the =
application. Perhaps there's a way to have two or more as it derives =
from CWinThread but I could not do it.
Best Regards,
Paulo Soares
psoares@ip.pt
-----From: drt@ebt.com (Randy Taylor)
Hi Gordon & All,
Generally speaking, I don't think think the DocMgr/DocTemplate part of the
MFC is required
if all I want from the Doc/View model is the "view management" portion, but
I'm looking for
confirmation from people who know this better than I do. I found the
DocMgr/DocTemplate code
to be heavily oriented toward file system based data (my data is in an
object database) : look
at the way it uses the CRecentFileList class and the "file extensions". I
found it to be a lot
easier to just CFrameWnd::LoadFrame and CFrame::ActiveFrame rather than
going thru the doc template
stuff. Further, my app is SDI with multiple instances of the primary
CFrameWnd... before I abandoned
the DocMgr/DocTemplate stuff, I found that I had to override every virtual
in CSingleDocTemplate
and to use none of it's member data in order to launch additional top level
CFrameWnd's !
Then I simply abandoned the CDocMgr/CDocTemplate stuff altogether.
My current issue is that my application has excessive problems with
view/data communication
and update because we got rid of Doc/View altogether and we have multiple
windows which
display the same data in different ways and each window can affect the others.
I want to re-introduce Doc/View into my app but I am convinced that the
DocMgr/DocTemplate
won't work (the code gets too complicated for little benefit) for me.
So... is the DocTemplate usage "required" for Doc/View ?
Also, which GetActiveView function were you refering to in your post? The
only one I know
about is the CFrameWnd::GetActiveView. It's implementation looks like this
in MFC 4.1
CView* CFrameWnd::GetActiveView() const
{
ASSERT(m_pViewActive == NULL ||
m_pViewActive->IsKindOf(RUNTIME_CLASS(CView)));
return m_pViewActive;
}
I don't see it walking any list of CView derivatives. What am I missing here?
Cheers.
randy_taylor@ebt.com
Gordon Weakliem -- gweakl@metronet.com
Thursday, September 12, 1996
I know this response is about 2 weeks late, but here goes...
> Hi Gordon & All,
> Generally speaking, I don't think think the DocMgr/DocTemplate part of the MFC is required
> if all I want from the Doc/View model is the "view management" portion, but I'm looking for
> confirmation from people who know this better than I do. I found the DocMgr/DocTemplate code
> to be heavily oriented toward file system based data (my data is in an object database) : look
> at the way it uses the CRecentFileList class and the "file extensions". I found it to be a lot
> easier to just CFrameWnd::LoadFrame and CFrame::ActiveFrame rather than going thru the doc template
> stuff. Further, my app is SDI with multiple instances of the primary CFrameWnd... before I abandoned
> the DocMgr/DocTemplate stuff, I found that I had to override every virtual in CSingleDocTemplate
> and to use none of it's member data in order to launch additional top level CFrameWnd's !
I did some thinking & research into this and I've basically decided that the best way to do a VB-like
interface (That's what it sounds like your application is) is to derive a new class from CDocTemplate.
The overview of the CDocTemplate class in books online says : "If your application requires a
user-interface paradigm that is fundamentally different from SDI or MDI, you can derive your own class
from CDocTemplate."
> Then I simply abandoned the CDocMgr/CDocTemplate stuff altogether.
> My current issue is that my application has excessive problems with
> view/data communication
> and update because we got rid of Doc/View altogether and we have multiple
> windows which
> display the same data in different ways and each window can affect the others.
> I want to re-introduce Doc/View into my app but I am convinced that the
> DocMgr/DocTemplate
> won't work (the code gets too complicated for little benefit) for me.
> So... is the DocTemplate usage "required" for Doc/View ?
Well, I sat down and wrote a sample MDI program that doesn't use doc/template, but it wasn't a total
success. Basically, the child frame is created but not made visible. Undoubtedly, I've done
something dumb, but I just haven't had the time to look at it. I'll make the source code available to
anyone who wants it, if anyone thinks this is useful.
> Also, which GetActiveView function were you refering to in your post? The
> only one I know
> about is the CFrameWnd::GetActiveView. It's implementation looks like this
> in MFC 4.1
I had made the comment that I though the original poster was getting into trouble because he wasn't
using a doc template and that CFrameWnd::GetActiveView() would ASSERT and blow up the way he was
going. I'm not sure where I was coming from with that one.
The bottom line on Doc/View is that yes, it is possible to write an MFC app without Doc/View. On the
other hand, sometimes the hassle in circumventing it isn't worth the effort. I've actually managed to
get some mileage out of doc/view in some non-tradiditional document situations, such as treating a
portion of the registry as a document and then displaying the contents in a view.
--
Gordon Weakliem
gweakl@metronet.com
http://www.metronet.com/~gweakl
| Вернуться в корень Архива
|