I have a project with many mfc views.
how can I send many requests to update views in the same time in c++ (mfc) ?
how can I use CWinthred classes ?
From your thread you should call PostMessage(WM_NEED_TO_UPDATE_ALL_VIEWS) to post your custom message (WM_USER based) to your main window. (which is CMainFrame I assume)
When you receive WM_NEED_TO_UPDATE_ALL_VIEWS in your main app window you should call UpdateAllViews(NULL); method to update all views.
Related
I have console MFC form application that consists from one form. In MFC application contructor thread with task is started :
CfbSrvApp::CfbSrvApp()
{
AfxBeginThread(MTServerThread,0);
}
MTServerThread procedure sometimes needs to show simple text input or yes/no form.
How to create MFC form in separate MTServerThread.
Main form sometimes can be minimised to tray, but input forms should appear to desktop anyway.
Derive a class from CWinThread.
Overwrite InitInstance
Create the Dialog there as known with DoModal
Create the new Thread with AfxBeginThread and RUNTIME_CLASS(CYourNewCWiNThreadClass)
Main form sometimes can be minimised to tray, but input forms should
appear to desktop anyway.
For what you want to achieve, it is better to create Modeless dialog in the main thread itself. Let the background server thread update the UI of the modeless dialog by sending messages to the main thread. This way you can minimize the main form in tray but still show modeless dialog.
What is the best way to communicate between two windows in Qt?
I need to have a separate login window and main application window which appears one after another (the second one, I mean main application window, will show only if the login was successful). Should I create these two objects (login window and main application objects) in the main function or make login window data member of the main application class and create it in the constructor of the main application class?
You can create login window as a data member of the main application class and create it in its constructor. Next you can invoke login by connecting a signal named login_
asked() of the main class to a slot named perform_login() and emitting the signal after that:
QObject::connect(this,SIGNAL(login_asked()),this,SLOT(perform_login())
,Qt::QueuedConnection);
emit login_asked();
You should hide your main window in the perform_login() slot and show your login form like:
this->setVisible(false);
loginfm->show();
You can notify your main application of the failure or success in login by signals and slots like:
QObject::connect(loginfm,SIGNAL(login_accepted()),this,SLOT(entered()));
QObject::connect(loginfm,SIGNAL(login_canceled()),this,SLOT(canceled()));
In the the slot entered() of your main window you should show the main window:
this->setVisible(true);
This way you can invoke login as many as you like during the application life cycle by just emiting the login_asked() signal.
The login window should be a QDialog-derived window. This has accepted and rejected signals, which you can trivially handle in your main window. (This answers the question in the title)
It doesn't matter very much where you create them, that's really a style issue. I'd probably put it in main myself, but if I took over an existing codebase I wouldn't bother changing such details.
What are the differences between FormView and Dialog in MFC? and can anyone suggest when to use FormView and when to use Dialog?
I have to respectfully disagree with posts above. There is no difference between CFormView and a dialog.
CFormView is a dialog created as modeless and hosted by the frame as a client, resized as frame resize.
It is created from dialog resource you have to supply, as any standalone dialog. All message handlers for dialog controls are the same.
CFormView Create member calls CreateDlg, passing dialog template loaded by the constructor.
CWnd CreateDialog, calls CreateDlgIndirect member that in turn calls CreateDialogIndirect API creating modeless dialog.
You can also embed modeless dialog inside another dialog and it is still a dialog.
A dialog application just shows a dialog (and whatever controls you put in the dialog, plus any other controls you pop up from it, etc.)
A FormView gives you a fairly normal application with a main menu and such -- but the view part can also hold controls.
You'd use a dialog if you just want a dialog, and a formview if you want (possibly multiple) views that can hold controls. Big difference is that making it a dialog changes the basic nature of the entire application, where a formview just changes one view -- you could (for example) also have other (non-form) views if you wanted.
someone_ smiley
To answer your question about dialog versus CFormView.
I rarely use dialog-based application; only in cases that require simple tasks without overhead of more complicated UI.
Most of programmers start with dialog based app and after getting into implementing some functionality, it usually turns that the application needs menu and a toolbar and status bar, data storing/handling object, command routing handling and so on.
I would suggest creating SDI application with non-resizable frame.
You will have a dialog look and all the functionality of the MFC application free. You do not have to use document support if you do not need one.
From the coders view point, FormView supports laying out of UI controls with dialog resource, in WYSIWYG way. So when making a view with a lots of controls FormView could be helpful.
Dialog is not a view. It is totally different. Dialogs are separate windows and normally presented in the modal event loop (or modelessly in special cases).
In an MDI application, when the user switches between views something has to be updated. What's the best message to handle for realizing when this happens?
In my application a document has only one view, but logically I want to get notified when switch is between documents.
You can catch WM_SETFOCUS in CChildFrame (ChildFrm.h). When a user clicks a view window, or sets focus to a view in another manner, this member function can be a bridge to whatever you need to set in the application.
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.