How to call the correct OnDraw() function?
junping li -- junping@infolytica.qc.ca Friday, August 09, 1996 Environment: VC++4.1/Win95 Hi, I have an application which has several types of views derived from CView. After I used the following code to find the current active view from the main frame, CMDIChildWnd* pWnd = MDIGetActive(); CView* theView = pWnd->GetActiveView(); I want to call theView's OnDraw() function. If CView's OnDraw() is a public method, I would get the correct derived view class' OnDraw() function called since OnDraw() is a virtual function. However, CView's OnDraw() is a protected method which prevents me calling it from the main frame. The reason I want to call the OnDraw() is that I want to pass a memory DC which has a CBitmap selected in it so that the GDI calls performed in the view's OnDraw() are actually drawn to the CBitmap. I don't want to use the isKindOf() testing to find the correct view class since I assume the views are not known beforehand. Does anybody know the way to get around the problem? I greatly appreciate the answers. Thank you in advance! Have a nice day! Junping
MICHAEL@datatree.com Monday, August 12, 1996 [Mini-digest: 6 responses] Create a user-defined message in your CView class that calls OnDraw(). (See ON_MESSAGE.) Then call the user-defined message from your main frame. >Environment: VC++4.1/Win95 > > CView's OnDraw() is a protected function, which prevents >me calling it from the main frame. Michael Thal michael@datatree.com Data Tree Corp. http://www.datatree.com -----From: Mario Contestabile > CMDIChildWnd* pWnd = MDIGetActive(); > CView* theView = pWnd->GetActiveView(); >I want to call theView's OnDraw() function. If CView's OnDraw() >is a public method, I would get the correct derived view class' >OnDraw() function called since OnDraw() is a virtual function. Perhaps pWnd->Invalidate() is what you are looking for. mcontest@universal.com -----From: ppbillc@srv2.sj.ablecom.net > However, CView's OnDraw() is a protected method which prevents > me calling it from the main frame. The reason I want to call > the OnDraw() is that I want to pass a memory DC which has > a CBitmap selected in it so that the GDI calls performed in the > view's OnDraw() are actually drawn to the CBitmap. I don't want > to use the isKindOf() testing to find the correct view class > since I assume the views are not known beforehand. > > Does anybody know the way to get around the problem? > > Junping > JunPing Derive a class and create a public function that calls OnDraw class CMyView : public CView { public: Draw() { Create your Bitmap and DC OnDraw(NEWDC); } }; Bill -----From: "petter.hesselberg"Create a common abstract baseclass for all your views, e.g., CMyViewBase, in turn derived from CView or a derivative. In CMyViewBase, declare a virtual public function (e.g., OnPublicDraw), which in turn calls the protected OnDraw function. This does strike me as architecturally convoluted--have you considered other solutions? Regards, Petter -----From: "Lee, Benny" Junping, You can send the CView a WM_PAINT message. Benny -----From: glachape@spherenet.com You are not supposed to call the OnDraw function from outside the object first because it is protected and second because I do not think this is in the MFC objects philosophy. I would push the use of CDocument::UpdateAllViews function. In this function, you can pass different parameters and specially a CObject* hint pointer. This pointer could be your CDC pointer. Inside your CView derived object, the OnUpdate function will be called and could handle this properly. Hope this could help... Ghis //////////////////////////////////////////////////// Ghislain Lachapelle (glachape@spherenet.com) . . . . . -)------+====+ . -)----==== ,' ,' . . . `. `.,;___,' . `, |____l_\ _,.....------c==]""______ |,,,,,,.....____ _ . . "-:______________ |____l_|]''''''''''' . . ,'"",'. `. . -)-----==== `. `. LS . -)-------+====+ . . . .
Yury Kosov -- Yury@msn.com Tuesday, August 13, 1996 [Mini-digest: 5 responses] I don't think this is possible, but here is my solution for the same problem: How draw into private DC. This is not a standard situation, but sometimes it is needed for the CView to draw into own DC, not the one provided by MFC. This would be easy if CView::OnDraw would be a public virtual method, but it is not. One of the workaround for this problem is to use the CView::OnUpdate() method. 1. Create the private DC member for the CMyView() to draw into. class CMyView : public CView { ... CDC *m_DrawDC; }; 2. Override OnDraw method to perform the drawing: void CMyView::OnDraw(CDC *pDC) { if(m_DrawDC) { // perform the required drawing } else { // draw into default pDC } } 3. Now the trick is to set up the right destination DC for the View without worrying about the kind of the view, so that application can support different kinds of the view. The best way is to use CView::OnUpdate(): void CMyView::OnUpdate(CView *sender, LPARAM lHint, CObject *pHint) { switch (lHint) { case UPDATE_DC: m_DrawDC = (CDC)pHint; break; .......... default: ASSERT(FALSE); } } 4. Now the high level code should not care about the kind of the view it's dealing with and actually should not care to call OnDraw() method of the view.: CDC *OutputDC = new CDC(); OutputDC->CreateCompatibleDC(0); OutputDC->SelectObject(myBitmap); // Do anything else to setup the destination DC // Update a particular View, for example Active MDI View: CMDIChildWnd *pWnd = MDIGetActive(); ASSERT(pWnd); CView *pView = pWnd->GetACtiveView(); ASSERT(pView); pView->OnUpdate(0,UPDATE_DC,(CObject *)OutputDC); // Or update All Views if necessary: CDocument *pDocument = GetMyDocument(); // depends where you are ASSERT(pDocument); pDocument->UpdateAllViews(0,UPDATE_DC,(CObject *)OutputDC); NOTE: I haven't discuss here anything about memory management and ownership of the DrawDC. That depends upon the application logic. Yury Kosov, CoreTek, Inc. yury@msn.com -----From: PP mail systemHi Junping! I guess I really don't understand. Per broadcast eMail from mfc-l/glachape@spherenet.com, the usual procedure is, within CMyView::OnUpdate(...) to set up drawing with CClientDC dc(this); OnPrepareDC(&dc); It's no different in VIEWCORE.CPP (see line 186 for 4.1): // CView drawing support void CView::OnPaint() { // standard paint routine CPaintDC dc(this); OnPrepareDC(&dc); OnDraw(&dc); } so, the way I see it, you can (i) supply your own DC instead of "this" in OnUpdate(), which seems a fairly likely route; or (ii) do whatever you want to "dc" during OnPrepareDC(): attack the supplied m_hDC and m_hAttribDC -- whatever. Having forced the sequence with an Invalidate(), I can't see why you can't get OnDraw() to use the DC that you want. What am I missing? Yours in puzzlement, Jim LW -----From: Deepak Saxena What you want to do can most easilly be accomplished by a user defined message that is sent to the view and with the WPARAM as the pointer to the DC. Then just add a message handler to the views that you want to support this operation. Basically: #define WM_MYDRAW (WM_USER + 1) CMDIChildWnd* pWnd = MDIGetActive(); CView* theView = pWnd->GetActiveView(); theView->SendMessage( WM_MYDRAW, (WPARAM)pMemoryDc); the handler: CMyView::OnMyDraw(WPARAM wParam, LPARAM lParam) { CDC *pDC = (CDC*)wParam; // Do stuff to DC to prepare it OnDraw(pDC); } Now, one thing you can do is to make a base view class(we'll call it CMyView) and have it handle this. Then you can just derive all your classes from here. however, since you might have different view classes(ScrollViews, FormViews, CtrlViews, etc...) I advise to just take this function and put it directly into the MFC source for the CView class. That way you'll always have this feature available for use. Deepak -----From: Clarence Chiang > Hi Li! > adding > CRect rect; > pWnd->GetClientRect(&rect); > pWnd->Invalidate(&rect); > pWnd->ShowWindow(SW_SHOW); > Regards, > Jim LW I guess the problem with the original question is that s/he wants to pass OnDraw a different DC than the one automatically passes in by the framework. Clarence -----From: David.Lowndes@bj.co.uk > Try adding CRect rect; pWnd->GetClientRect(&rect); pWnd->Invalidate(&rect); pWnd->ShowWindow(SW_SHOW); < Woudn't this be better? pWnd->Invalidate(); pWnd->UpdateWindow(); Dave Lowndes
| Вернуться в корень Архива |