How to connect together in the documentview structure (2)

xiaoxiao2021-03-06  21

(3) Contact between documents and views

In the view class, there is a protective data member: cdocument * m_pdocument; It saves all pointers that are displaying the views of the document, and access to these views can be implemented by cdocument's member function GetFirstViewPosition and GetNextView functions.

When the view is created, the view and documentation in the oncreate function have been associated:

INT CView :: OnCreate (LPCReatestruct LPCS)

{

IF (CWnd :: OnCreate (LPCS) == -1)

Return -1;

CcreateContext * pContext = (ccreatecontext *) lpcs-> lpcreateparams;

IF (PContext! = null &&pontext-> m_pcurrentdoc! = null)

{

PCONTEXT-> M_PCurrentDoc-> AddView (this);

Assert (m_pdocument! = Null);

}

Else

{

Trace0 ("Warning: Creating a Pane with no cdocument./n");

}

Return 0;

}

This association is implemented by the AddView function of the document class:

Void CDocument :: AddView (CView * PView)

{

......

m_viewlist.addtail (pVIEW);

PVIEW-> m_pdocument = tris;

OnchangeDViewList ();

}

In this function, first, the document object first adds the added view pointer to its own view chain table, then pointing to the M_PDocument member of the added view.

It is well known that the way documents communicate with the view first calls the UpdateAllViews function of the document, thus calling the view's onupdate function:

Void CDocument :: UpdateAllViews (CView * psenter, lparam lhint, cobject * phint)

// Walk THROUGH ALL VIEWS

{

/ / The view is not empty and the sender cannot be empty.

AskERT (psenter == null ||! M_viewlist.isempty ());

Position POS = getFirstViewPosition ();

While (POS! = null)

{

CView * pView = getNextView (POS);

Ask_VALID (PVIEW);

/ / Do not invoke the sender's onupdate function

IF (PView! = psenter)

PView-> onupdate (psenter, lhint, phint);

}

}

The default implementation in the ONUPDATE function of the view is only the notification view for redrawing:

INVALIDATE (TRUE);

We generally overload some of this update view or other operations, such as updating the scroll range of the view scroll bar.

(4) Connection between frame windows and documents

When the frame window is created, the view is created, the relevant functions are as follows:

INT CFrameWnd :: OnCreate (lpcreateStruct LPCS)

{

CcreateContext * pContext = (ccreatecontext *) lpcs-> lpcreateparams;

Return OncreateHelper (LPCS, PCONTEXT);

}

Int cframeWnd :: OnCreateHelper (lpcreateStruct LPCS, CCReateContext * PContext)

{

IF (CWnd :: OnCreate (LPCS) == -1)

Return -1;

// Create Special Children Firstren First

IF (! OncreateClient (LPCS, PCONTEXT))

{

Trace0 ("Failed to Create Client Pane / View for Frame./N");

Return -1;

}

// Post Message for Initial Message String

Postmessage (WM_SetMESSAGESTRING, AFX_IDS_IDLEMESSAGE);

// Make Sure The Child Windows Have Been Properly Sized

RECALCLAYOUT ();

Return 0; // Create OK

}

Bool cframewnd :: oncreateclient (lpcreatestruct, ccreatecontext * pcontext)

{

// Default Create Client Will Create a View if asked for IT

IF (PContext! = null &&pontext-> m_pnewview! = null)

{

IF (CreateView (PCONTEXT, AFX_IDW_PANE_FIRST) == NULL)

Return False;

}

Return True;

}

CWnd * cframeWnd :: CreateView (ccreateContext * PContext, uint NID)

{

CWND * pView = (cwnd *) PContext-> m_pnewviewclass-> createObject ();

IF (pView == null)

{

Return NULL;

}

Ask_KINDOF (CWND, PVIEW);

IF (! pView-> Create (null, null, afx_ws_default_view,

CRECT (0, 0, 0, 0), THIS, NID, PCONTEXT))

{

Return null; // can't Continue without a view

}

IF (AfxData.bwin4 && (PView-> getExStyle () & ws_ex_cliented))

{

ModifyStyleex (WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);

}

Return PVIEW;

}

The OpenDocumentFile function in the document template has occurred as follows:

InitialUpdateFrame (pframe, pdocument, bmakevisible);

The implementation of this function of the document template is:

Pframe-> InitialUpdateFrame (PDOC, Bmakevisible);

It is actually called the same name function for the frame window:

Void CFrameWnd :: InitialUpdateFrame (cdocument * pdoc, bool bmakevisible)

{

CView * pView = null; if (getActiveView () == NULL)

{

// Take the main view

CWND * PWND = getDescendantWindow (AFX_IDW_PANE_FIRST, TRUE);

IF (PWND! = null && pwnd-> iskindof (runtime_class (cView))))

{

/ / The main view exists and legal, set the current main view as an active view

PVIEW = (CView *) PWND;

SetActiveView (PVIEW, FALSE);

}

}

IF (BMakevisible)

{

SendMessageTodescendants (WM_Initialupdate, 0, 0, True, True);

IF (PView! = NULL)

PView-> OnactivateFrame (Wa_INACTIVE, THIS);

......

ActivateFrame (ncmdshow);

IF (PView! = NULL)

PView-> OnactivateView (True, PView, PView);

}

// Update Frame Counts and Frame Title (May Already Have Been Visible)

IF (PDOC! = NULL)

PDOC-> UPDATEFRAMECUNTS ();

OnUpdateFrameTitle (TRUE);

}

The operation in the above function is mainly used to set the active view with SetActiveView and call the onactivateFrame function of the view. Maintain a protective member in the CFrameWnd class: cView * m_pviewactive;, the setacitveView function is mainly to do it:

Void CFrameWnd :: SetActiveView (CView * PViewNew, Bool Bnotify)

{

CView * pViewold = m_pviewactive;

IF (PVIEWNEW == PVIEWOLD)

Return; // do not re-activate if setActiveView Called More Than ONCE

m_pviewactive = null; // no active for the folloading processing

// deactivate the old one

IF (PViewOLD! = NULL)

PViewold-> OnactivateView (False, PViewNew, PViewOLD);

IF (M_PViewActive! = NULL)

Return; // already set

m_pviewactive = pViewnew;

// Activate

IF (PVIEWNEW! = null && bnotify)

PVIEWNEW-> OnactivateView (True, PViewNew, PViewOLD);

}

CframeWnd has another function returns to this member:

CView * cframeWnd :: getActiveView () const

{

Assert (m_pviewactive == null ||

m_pviewactive-> iskindof (runtime_class (cView)));

Return M_PViewActive;

}

CFrameWnd has a function that can get the current active document, which is indirect through the active view:

CDocument * cframeWnd :: getActiveDocument () {

Assert_Valid (this);

CView * pView = getActiveView ();

IF (PView! = NULL)

Return pView-> getDocument ();

Return NULL;

}

(5) The association between the MDI main window and the sub-window:

When you created in the MDI sub-window, specify the relationship between it and the MDI:

Bool cmdichildwnd :: Create (LPCTSTR LPSZCLASSNAME,

LPCTSTSTSZZWINDOWNAME, DWORD DWSTYLE,

Const Rect & Re, cmdiframeWnd * PParentWnd,

CCReateContext * PCONText)

{

IF (pParentWnd == null)

{

CWND * PMainWnd = AFXGETTHREAD () -> m_pmainwnd;

Assert (PMainWnd! = NULL);

Assert_kindof (cmdiframewnd, pmainwnd);

PParentWnd = (cmdiframewnd *) PMainWnd;

}

......

PparentWnd-> RecalcLayout ();

Createstruct CS;

......

/ / Specify the MDI sub-window to which you belong

cs.hwndparent = pparentWnd-> m_hwnd;

......

cs.lpcreateparams = (lpvoid) PCONText;

IF (! PrecreateWindow (CS))

{

Postncdestroy ();

Return False;

}

MDICREATESTRUCT MCS;

......

MCS.Style = cs.style & ~ (ws_maximize | ws_visible);

MCS.LPARAM = (long) cs.lpcreateparams;

AfxhookWindowCreate (this);

// Send a WM_MDICREATE message, create a MDI sub-window

HWnd hwnd = (hwnd) :: SendMessage (pparentWnd-> m_hwndmdiclient,

WM_MDicReate, 0, (LPARAM) & MCS);

IF (! AFXUNHOOKWINDOWCREATE ())

Postncdestroy (); // Cleanup if Mdicreate Fails Too Soon

......

Return True;

}

When the MDI sub-window is created, the MDI main window can implement the management of sub-windings with its own function, for example, get the current active sub-window is achieved by sending a WM_MDiGetActive message.

转载请注明原文地址:https://www.9cbs.com/read-61125.html

New Post(0)