问题
I want to post a message to all views. I'm considering get a Document global reference and then implement a method like below
void SomeAppDoc::DispatchToAll( UINT msg, WPARAM wP, LPARAM lP )
{
//some how get all view's reference
//iterate and update each views
}
What is the effective way?
回答1:
The simplest way is to call CDocument::UpdateAllViews, which calls the OnUpdate function of each view attached to the document.
If you really need to post a message to each view, rather than call OnUpdate
, do something similar to UpdateAllViews
:
void SomeAppDoc::DispatchToAll(UINT msg, WPARAM wParam, LPARAM lParam)
{
POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = GetNextView(pos);
pView->PostMessage(msg, wParam, lParam);
}
}
I hope this helps!
回答2:
I had a similar problem however I found this provided answer to be insufficient as there are two parts to a solution to this question.
The first is as provided with the process of iterating through the various views and using PostMessage()
to send a message to each view.
The second part is what to do on the CView
side that is receiving the message being sent and I want to provide a bit of a note on that part.
In the MFC application I am working on, I wanted to send a message to the CView
and was running into an exception due to a mistake on my part as to how to process the message being sent.
In the class derived from CDocument
I had a function that iterates over the list of CView
objects to send a message to each. In this particular case I was wanting to reposition the view port to a designated section of a report. This required the Windows message that was sent to include an offset value as well as a message identifier.
POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = GetNextView(pos);
if (pView)
pView->PostMessage(WM_APP + 10, sectionHeader.m_ListOffset, 1);
}
I am using the standard Windows SDK define WM_APP
to create a unique message identifier within the range of user defined message ids (as opposed to standard Windows message ids) to send a message indicating the offset to use as the WPARAM
argument of PostMessage()
. See Message Map Macros - ON_MESSAGE which states:
User-defined messages are any messages that are not standard Windows WM_MESSAGE messages. When selecting a message ID, you must use values within the range of WM_USER (0x0400) to 0x7FFF or WM_APP (0x8000) to 0xBFFF. For more information regarding message IDs, see WM_APP.
In the CView
class I added an entry to the message map for the CView
class. I am using ON_MESSAGE
rather than ON_COMMAND
because I need to provide the offset to the CView
processing the message.
ON_MESSAGE(WM_APP + 10, &CPCSampleView::OnWindowSetSection)
and then added the source for the actual message handler itself which calculates the correct viewport scroll position by using the offset of the text line in a buffer along with the line height of each text line:
LRESULT CPCSampleView::OnWindowSetSection(WPARAM wParam, LPARAM lParam)
{
CPCSampleDoc *pDoc = GetDocument();
CPoint ptOrigin;
ptOrigin = GetScrollPosition();
wParam *= m_sizeCell.cy; // multiple text line offset by height of each line of text
ptOrigin.y = wParam; // change the vertical position of the scroll bar
ScrollToPosition(ptOrigin); // move the scroll bar elevator
this->UpdateWindow(); // tell view to update displayed window to match elevator position
return 0;
}
For more details about messages see Message Handling and Mapping in the Microsoft docs.
来源:https://stackoverflow.com/questions/8740263/mfc-how-to-post-a-message-to-all-views-that-were-derived-from-cview-class