views:

167

answers:

2

There are few things I'm not sure of :

When you create a basic SDI using MFC app wizard (let's call it TestMfc) you get :

4 major classes :

CTestMfcApp
CTestMfcView
CTestMfcDoc
CMainFrame

What I noticed is that CTestMfcApp has those declaration

ON_COMMAND(ID_APP_ABOUT, &CTestMfcApp::OnAppAbout)
    // Standard file based document commands
    ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
    ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
    // Standard print setup command
    ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinApp::OnFilePrintSetup)

while CTestMfcView has those :
BEGIN_MESSAGE_MAP(CTestMfcView, CEditView)
    // Standard printing commands
    ON_COMMAND(ID_FILE_PRINT, &CEditView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_DIRECT, &CEditView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CEditView::OnFilePrintPreview)
END_MESSAGE_MAP()

What I don't understand is why does MFC create that separation? I can't see why the app class needs to declare functions for handling events... isn't that the view's job? If for exmaple there are few windows it's even becoming more clear.

Second, how those events get called? I know there's supposed to be WINPROC function who's supposed to get the MSG and call the right handler. is the ON_COMMAND the macro who sets some kind of pointer function who is later available to the the WINPROC function. And why doesn't the ON_COMMAND get a WINDOWS handle... if for example there is another WINDOW in the program with the same ID ?

Third and last, let's say I want to change some window's threads to an alert state. To do that I want to change the main loop (which keeps calling getmessage/dispatchmessage etc.. and insert the waitformultibleonject function. where is the winmain function? I can't find it when the appwizard is doing all the job for me.

Thanks!!

+2  A: 

In MFC, messages "bubble up" until they find a handler. IIRC it's View -> Document -> Document Template -> MainFrame -> App. This allows to handle view-specific events in the view, document-specific events in the document etc.

Usually, global handlers end up in the mainframe class. However, you can use multiple mainframe windows - even with different behavior - where the distinction between "MainFrame" and "App class" becomes important.

Control-specific handlers do belong in the view class, though. I'd put only WM_COMMAND handlers into higher-up classes.


for your third question: I wouldn't do that. While MFC avoids a few common modal loops, you can't avoid them all. OnIdle is a good place to implement defered updates.


[update] MFC uses one global WNDPROC to handle all messages. It uses a HWND to CWnd mapping to locate the MFC object. When the WNDPROC sees a WM_COMMAND message, it will first check the message map of the receiver window if it contains a handler for that message. If there is none, it will do a variety of checks, e.g. "Is this not just a CWnd, but a CView?" Yes --> get the document and see if the documents message map has a handler for this particular command.

peterchen
i still don't understand how the ONCOMMAND macro know to which windows handle to specify the handler function.my third concern was in order to use APC, which i have to insert my thread to alert state in order to get those... so how do you recomment i do that besides using waitformultipleobjects which seems correct to me
Idan
Idan, I have added some more info to the question. For the other question, it would be best to ask separately.
peterchen
A: 

Print is normally handled in the view because in win32 you print by calling the OnPaint event to a printer rather than the screen. Also for any events that involve getting the mouse position it's easier to do it in the view.

You can easily get the current doc form the view but it's more effort to get the view form the doc.

Martin Beckett