Ich hatte ein ähnliches Problem, jedoch fand ich diese bereitgestellte Antwort als unzureichend, da es zwei Teile einer Lösung zu dieser Frage gibt.
Der erste Teil besteht darin, den Prozess des Durchlaufs durch die verschiedenen Ansichten und die Verwendung von PostMessage()
zum Senden einer Nachricht an jede Ansicht bereitzustellen.
Der zweite Teil ist, was auf der CView
-Seite zu tun ist, die die Nachricht empfängt, und ich möchte zu diesem Teil eine Anmerkung machen.
In der MFC-Anwendung, an der ich arbeite, wollte ich eine Nachricht an die CView
senden und stieß auf eine Ausnahme aufgrund eines Fehlers meinerseits, wie die gesendete Nachricht verarbeitet werden sollte.
In der von CDocument
abgeleiteten Klasse hatte ich eine Funktion, die über die Liste von CView
-Objekten iteriert, um eine Nachricht an jede zu senden. In diesem speziellen Fall wollte ich den Ansichtsbereich in einen bestimmten Abschnitt eines Berichts verschieben. Dafür musste die gesendete Windows-Nachricht einen Offset-Wert sowie einen Nachrichtenidentifikator einschließen.
POSITION pos = GetFirstViewPosition();
while (pos != NULL)
{
CView* pView = GetNextView(pos);
if (pView)
pView->PostMessage(WM_APP + 10, sectionHeader.m_ListOffset, 1);
}
Ich verwende die Standard-Windows-SDK-Definition WM_APP
, um einen eindeutigen Nachrichtenidentifikator im Bereich der benutzerdefinierten Nachrichten-IDs (im Gegensatz zu Standard-Windows-Nachrichten-IDs) zu erstellen, um eine Nachricht zu senden, die den Offset als das WPARAM
-Argument von PostMessage()
verwendet. Siehe Message Map Macros - ON_MESSAGE, die besagt:
Benutzerdefinierte Nachrichten sind Nachrichten, die keine standardmäßigen Windows-Nachrichten sind. Bei der Auswahl einer Nachrichten-ID müssen Werte im Bereich von WM_USER (0x0400) bis 0x7FFF oder WM_APP (0x8000) bis 0xBFFF verwendet werden. Weitere Informationen zu Nachrichten-IDs finden Sie unter WM_APP.
In der CView
-Klasse habe ich einen Eintrag in der Nachrichtenkarte für die CView
-Klasse hinzugefügt. Ich verwende ON_MESSAGE
anstelle von ON_COMMAND
, weil ich dem CView
den Offset zur Verarbeitung der Nachricht bereitstellen muss.
ON_MESSAGE(WM_APP + 10, &CPCSampleView::OnWindowSetSection)
und fügte dann die Quelle für den tatsächlichen Nachrichtenhandler hinzu, der die richtige Scroll-Position des Viewports berechnet, indem er den Offset der Textzeile in einem Puffer sowie die Zeilenhöhe jeder Textzeile verwendet:
LRESULT CPCSampleView::OnWindowSetSection(WPARAM wParam, LPARAM lParam)
{
CPCSampleDoc *pDoc = GetDocument();
CPoint ptOrigin;
ptOrigin = GetScrollPosition();
wParam *= m_sizeCell.cy; // multipliziere den Textzeilenoffset mit der Höhe jeder Textzeile
ptOrigin.y = wParam; // ändere die vertikale Position der Scrollleiste
ScrollToPosition(ptOrigin); // bewege den Scroll-Leistenelevator
this->UpdateWindow(); // sag der Ansicht, das angezeigte Fenster an die Position des Elevators anzupassen
return 0;
}
Für weitere Details zu Nachrichten siehe Message Handling and Mapping in den Microsoft-Dokumenten.