MFC basic structure questions - c++

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 these :
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!!

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.

Introduction to the MFC architecture
The Microsoft Foundation Class library framework does a reasonable job of providing the basics of an MVC design pattern using messages of various sort to provide the communication between the various parts. However like any framework it provides a structure which can provide lots of functionality you do not have to write as well as quite a bit of restrictions and constraints if your approach is not congruent with the framework.
The framework uses messages between cooperating entities, extending the idea of Windows messages and using the message infrastructure of the Windows operating system. Some of these cooperating entities have their own Windows message pump (modal dialogs and threads) while the rest use the application message pump serviced by the main or UI thread.
Messages sent to the application's main window such as keyboard or mouse events or posted messages using PostMessage() are pulled off the Windows message queue by the main window thread, also known as the main UI thread, servicing the message pump and then forwarded to the entity that it belongs to by the MFC framework. This is why actions that pause or wait the main UI thread make the application unresponsive. The main UI thread must continually run to pull Windows messages from the Windows message queue and then distribute them to the rest of the application.
The MFC framework forwards messages by looking through a list of message maps in order to find which entity or MFC class instance is expecting the message and if one is found, calling the C++ function specified in the message map entry with the arguments the MFC specification requires. The expectation is that any message processing function will either complete the action quickly and return back to the MFC framework's message dispatch functionality or will use a thread to perform any action that requires some time and then return.
The MVC design pattern views the application as made up of three cooperating entities, the Model entity containing the data, the View entity which presents a view of the Model and its data, and the Controller entity which is the affordance the user manipulates to change what is viewed as well as the model and its data.
The MFC framework architecture starts with a couple of base classes which are then specialized through inheritance. For instance there is a general view class which provides the message infrastructure for a general display then subclasses extend and specialize the general view class. For instance the CView class is specialized with the CScrollView class.
Main types of MFC UI classes
In general the document class will handle messages that involve changes to the document content and the view class will handle messages that involve the presentation of the document content. The document class is responsible for serializing all of the data or content to or from the document object from or to a file.
The document class uses the Observer design pattern to allow views to know when an update is needed. The document class has a list of view instances so that when a change is made to the document or model or data, all of the registered views are sent a message indicating a change and need to update.
The view class is responsible for displaying a view of the document data to a device such as a window on the screen or a printer. So it would be normal for a CView class to have a function that would handle a print request sent via a message with a message Id of ID_FILE_PRINT or ID_FILE_PRINT_PREVIEW.
When data within the document changes, a message can be sent to all of the views registered with the document informing those views of the data change so that the views can decide whether to make changes to the view or not.
The third main class of the framework, the CWinApp or application class is a container and manager for the document and view classes. Within the app object, which is the entry point for the application (a construct which is also used for an MFC DLL as well to provide for the DLL load and unload entry points), is the hooks for the main message pump. The purpose of the app class is to set up the initial environment and to then allow the programmer to hook their particular document and view objects into the MFC framework of the app class.
Since the CWinApp class is a container for the application, it would be normal for it to handle such events as ID_FILE_NEW or ID_FILE_OPEN as it would cause the document class to close out the current document and reinitialize the application to start with a new document and its associated views.
My opinion is that the About dialog handling and Help handling was put into the CWinApp class since it was the easiest place to put it. Typically an About is a dialog with a basic description of the application. And both Help and About may be things you want to access without having to start a document or view first.
The MFC framework has other, supporting classes for the main UI functionality. There are also other additional libraries that have been added since MFC was first introduced in the early 1990s.
A few details about messages
Windows messages have a message Id indicating the type of message. There are various ranges of message Id values that are allocated to different purposes. One range is the WM_USER range that an application can use without concern of using a message Id assigned to a Windows message such as a keyboard message. Part of this range is allocated to MFC messages (see WM_USER vs WM_APP as well as Sending and receiving Windows messages as well as How to handle a posted, registered windows message within a VCL application? ).
These messages are standard Windows messages using PostMessage() or SendMessage() with the standard Windows format of handle of the target window, a message identifier, and the two parameters which are used to provide additional information. The MFC framework has lots of different C Preprocessor defines for various message identifiers. If you follow the class derivation hierarchy you will find that document classes, CDocument, end up being derived from CCmdTarget classes just as the view classes, CView or derivations of CView, are as well. CCmdTarget in turn derives from the most basic MFC class, CObject.
Much of the message map functionality seems to come from the functionality of the CCmdTarget class which uses a method of accepting a message, checking to see if the message identifier is in the CCmdTarget message list for the specific object and if not passing it on to the next CCmdTarget object in the chain. So the MFC framework uses a kind of Strategy Design Pattern so that a message is passed along a chain of components until an object that can handle the message is found.
Due to the age of the MFC framework, quite a bit of the exposed pieces use the C Preprocessor and macros. You can inspect the macros to see what they are doing and how they are implemented using the Visual Studio IDE. And those parts of the MFC framework that are implemented as templates are also easily available through the Visual Studio IDE to read. Both macros and templates are in the MFC include files.
However to read the code in the actual classes you will need to find a copy of the MFC source body. Using the MFC Source Files from the Microsoft web site provides a starting point including where to find the source from your installation of Visual Studio.
The Microsoft Foundation Class (MFC) Library supplies full source
code. Header files (.h) are in the \atlmfc\include directory;
implementation files (.cpp) are in the \atlmfc\src\mfc directory.
I would not recommend forking this with your own changes.
Your third question is about threads and the approach you describe does not make sense within the MFC framework. With MFC you would normally create a thread using the AfxBeginThread() or AfxBeginThreadEx() functions. There are two kinds of threads, one with a user interface and one without.
It does not make sense that a multi-threaded MFC application would need to modify the message pump. You would instead send messages to the thread once you have created it using something like PostThreadMessage(). The thread can receive messages by calling either the GetMessage() or PeekMessage() functions. Each MFC thread has a message pump and message queue that is set up "when the thread makes its first call to one of the User or GDI functions" (see PostThreadMessageW function).
References
Is MFC is based on any design pattern,if so which design pattern?
Windows Messages
SendMessage/PostMessage to a derived CView class not working for MFC application
MFC - How to post a message to all views that were derived from CView class?
Is the 'C' in MVC really necessary?
This article, Threads with MFC, in code project provides an overview and source example.

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.

Related

VC++: How to capture the Events fired from an ActiveX (.ocx) inside ATL project

I am making an wrapper of a control, an interface of the ocx object. Had to create an ATL project and then add/load the ocx file. It has exposed properties, methods and events. I am able to control/used its properties and methods however I was stuck on events, especially handling it after it fires.
Have searched it on google and most of the guides I've found are making it from scratch or from the ATL events itself. What I am trying to achieve is to make use of the exposed events from the ocx. Any have idea?
Thank you very much.
In ATL your standard options to handle COM events is to use IConnectionPointContainer and friends as explained in Event Handling and ATL:
For information on how to fire events and implement connection points, read ATL Connection Points.
Or, and especially for ActiveX control events, your second option is IDispEventImpl class references there by the first link as well:
Using IDispEventImpl, inlcuding sample referenced
AtlEvnt.exe sample shows how to creates ATL sinks by using the ATL IDispEventImpl and IDispEventSimpleImpl classes
IDispEventImpl is explained in detail on other resources too, e.g.:
Understanding COM Event Handling on CodeProject

Custom message pump for MessageBox (Windows)?

I have a large code base where there are lots of calls to AfxMessageBox(...). What I need to do is while these messageboxes are modal service some external IO (i.e. a network communication).
I've considered writing a custom CDialog and my own message pump - but I'm unsure of how to make the CDialog generic enough that I can reliably create all the messageboxes without having to test them all.
Alternatively I've been looking at hooking into the messageboxes' windproc function through SetWindowsHookEx but this has the limitation that it happens after the messagepump and will not fire if there are no messages for that dialog.
Does anyone have any suggestions on how to acheive this or if either of my two approaches above are worth pursuing. ?

How can I write a C++ COM object with asynchronous event firing (like VB6's Timer object)?

I'm writing a C++ COM object for directory change notifications via ReadDirectoryChangesW. A thread in my object will wait for changes, then notify the VB6 client.
I know how to trigger events from the main thread of my program, similar to callback functions, but I don't want to force the user to poll my object for changes every small interval.
As far as I'm aware, what I want could be done by sending window messages, but this needs form subclassing on the VB6 side, which is quite complicated.
So I'm looking for a way to write an object like VB6's Timer which can fire an event in VB6 even when VB6 isn't currently calling into a method of Timer. Is this possible?
COM events.
The topic is rather laborious, it implies defining a 'sink' interface that the event consumer (VB) is passing to the event source, and then raising events by calling methods on the 'sunken' interface. See Architecture of Connectable Objects. You must implement IConnectionPointContainer. The good news is that IDEs are fully aware of this model and will expose your events in the VB designer. From the VB side will be as simple as a double-click on the COM object 'events' properties panel.
As for the 'async' part, this falls in the 'threading' model of your component and the VB host app. In Apartment threads (the default) you will have to raise the events in the main Apartment thread, and you may have to marshal the interface between threads. See What are the rules for CoMarshalInterface and CoUnmarshalInterface?.
The details about asynchronous COM event firing from C++ server to VB6 client can be found in this article.

What is a good MFC C++ GUI architecture for multiple similar window arrangements

I am considering a rewrite of an MFC Dialog application I wrote over a decade ago. I originally chose a Dialog application type because in general the user clicks control inputs and the application provides real-time data from hardware via USB and displays the data in edit boxes. The app also writes information to a file. Since the user never does any file editing I didn't see a need for SDI or MDI application type.
I've now learned that the SDI application type along with CFormView provides some interesting advantages such as scrolling, window resizing:
http://forums.codeguru.com/showthread.php?267664-MFC-Dialog-How-to-enhance-a-dialog-based-application-with-Menu-Toolbar
The reason for my rewrite is that my application is un-maintainable and doesn't scale well. Originally I created a CDialog for each type of "screen" that I show but lots of code is common among the various screens. In fact over time I started reusing CDialog classes and with the use of state variables simply hid, renamed, or repositioned many of the controls to make the screen look appropriate in the context of the application.
I tried deriving the CDialog classes from a common base class but I didn't achieve great code reuse this way. I also found that I had common resources that I was constantly passing around to the various windows which just added unnecessary overhead.
As the application evolved it also became difficult to keep track of the state of the application (for processing USB hardware data input, user input, button enabling etc). Using a hierarchical statechart as the basis for my application might clean this up.
Should I consider putting a superset of ALL the necessary controls on ONE CFormView and simply hiding, renaming, and repositioning controls from the very beginning and using a statechart to manage this?
All the examples I see put the code directly in the input control handlers but maybe I should use the handlers to change state and then let the state machine do the decision-making to reduce this spaghetti code.
So my primary questions are:
1. Would SDI would buy me anything for writing and reading files (such as reporting and logging) if the user does not perform editing?
2. Does CFormView make sense?
3. Does it make sense to put all controls on one CFormView instead of multiple classes and Dialog resources?
4. Have you tried using a state machine in MFC such as Boost Statechart or Miro Samek's Quantum Leaps?
http://www.boost.org/doc/libs/1_58_0/libs/statechart/doc/index.html
http://www.state-machine.com/products/index.html

Win32 api different classes per window?

ive recently started to work with the win32 api and im trying to do a couple of things.
I have a project that is gonna use about 4-5 windows. I want to seperate each of these into a different cpp file where each has its own message Loop. How do i pass information from window to window?(is there some sort of entry point?) at the moment im creating all windows during case WM_CREATE: and I am showing them as required.
I am trying to have a nice OOP design but having trouble with that, my main issue is the communication between windows. I have a fair amount of experience in C# and C++ and other than this the win32 api is not being a problem.
Thanks for your help!
I don't think you want a per-window message loop, unless you want each window in its own thread. You probably need a window procedure instead.
Each window class has its own window procedure, which you register by setting lpfnWndProc field of WNDCLASS structure before passing it to the RegisterClass. Once you've done that, you can use that class when creating a new window with CreateWindow.
In your case, you'll probably want to implement the window procedure so it accepts custom messages (WM_APP + x), and then pass custom messages between windows using PostMessage (for asynchronous communication) or SendMessage (for synchronous communication). If necessary, you can create separate window classes and window procedures for your different windows. A single message loop is capable of pumping messages to all these procedures.
The classic way of inter-window communication is sending / posting messages:
SendMessage
PostMessage