15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


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 system 

Hi 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




| Вернуться в корень Архива |