Re: Drawing on DC



see below...
On Sat, 18 Nov 2006 13:13:02 -0800, MarcoMB <MarcoMB@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:

thanks for all support... i created different class, one per object(class for
circles, class for rectangle, etc)
****
You are being very vague here about what you did. I would expect that you have done

class Drawing {
public:
virtual void Draw(...some args...) PURE;
....
};

class Circle : public Drawing {
public:
virtual void Draw(...some args...);
};

class Rectangle : public Drawing {
public:
virtual void Draw(...some args...);
};

If you did not do this, why not?
****
and i've implemented CObArray containing
objects drawed and so created.
****
Generally, get nervous when you declare a CObArray. They aren't type-safe. As a good
basic design principle, take as given "If I'm writing a CObArray, I've made a mistake",
and go from there. There might exist, in some weird and wondrous world, a need for a
CObArray, but I've never found one. Beginners latch onto this because it seems to be a
simple solution, but in fact it is one of the worst possible choices.

CArray<Drawing *, Drawing *> objects;

The alternative is to create a CList of Drawing objects, which has different tradeoffs but
is otherwise an equally valid implementation of a display list.

The Z-order is implicit in the array. The bottommost object is at position 0 and the
topmost object at position GetSize() - 1. If you want to change the Z-order of an object,
you change its position in the array (now you understand how Move Forward and Move
Backward work in most drawing programs: they swap the element with the one after it (Move
Forward) or the one before it (Move Backward). Move To Top moves the element to the last
position, and Move To Bottom moves the element to position 0).
****
In every objects class there's the related Draw
function
****
What is a "related function"? I've never heard this term used in C++ programming
*****
that substitute the onDraw,
*****
That doesn't make any sense. It would be *called* from OnDraw, but it wouldn't
*substitute* for OnDraw.
*****
called only when Invalidate to make
cycles in the arrays and so redraw the objects.
****
Other than the strange description, this would be the basic idea.

A prety good approximation to what you need to do in OnDraw is shown below. There could
be issues of setting mapping modes, origins, and a few other bells and whistles, but the
core algorithm is very simple:

void CMyClass::OnDraw(CDC * pDC)
{
for(int i = 0; i < objects.GetSize(); i++)
objects[i]->Draw(pDC); // "some args" might just be the pDC, for example...
}
****
My problem was mantaining
objects on screen when positioning them, becouse invalidating constinously
their little area(to eliminate flicker)i lost the object when there wasn't
mouse moving.
****
This makes no sense. You *can't* "lose" an object because it is still in the display
list; all that has changed is its x,y origin position. So if you invalidate its original
location (as you come into OnMouseMove) and its target location (as you leave
OnMouseMove), it will simply be redrawn. Where's the problem?
****
I resolved my problem introducing an event function OnTimer so
that i can redrawing continously object even if WM_MOUSEMOVE isn't called.
****
ABSOLUTELY THE WRONG APPROACH! There are so many things wrong with this concept I'm not
even sure where to begin! You should only draw when you need to draw, and that means you
respond to WM_PAINT messages. This is the OnDraw handler. The rest of the time, you
don't draw. Constantly redrawing based on a timer event is wasteful, and frankly,
nonsensical. You are trying to solve a problem whose solution is well-understood and
well-specified, and you are missing the basic concepts and have failed to understand how
Windows grpahics work, and as a consequence you are seeing weird behavior, which you are
flailing about attempting to fix, when simply implementing the correct solution (OnDraw)
would make go away. You have to keep the information necessary to re-create the entire
drawing, from scratch, without warning, at any time. Without this, the kinds of problems
you are seeing follow naturally from a misdirected solution. And your attempts to "solve"
it are completely off-base.

If you are "losing" the object being dragged, it says there is a fundamental failure in
your algorithm, and tossing kludges at it isn't going to solve the fundamental problem.
Fix the fundamental problem. I have no idea what you are doing wrong, but the proposed
solution is, to say the least, nonsensical.

You really have to CAREFULLY STUDY the Scribble tutorial; you have missed the fundamental
concepts of Windows graphics completely!
****
I don't know if it's the right way, but it's work fine.I thought also to manage
the OnIdle thread,
****
There is no such thing as "the OnIdle thread". There is an OnIdle handler which is called
in your main GUI thread if there is nothing else to do, but this is equally poor design to
use this for your redrawing. PLEASE study how graphics work in Windows; you are simply
kludging together hopelessly incorrect solutions otherwise.
****
but i don't know if it's better.Maybe the best could be
creating a buffer DC abd then BitBlt the image, also if i draw DC objects
that aren't bitmaps so how can work a buffer DC and BitBlt?
****
Drawing your objects on a bitmap merely renders the circle, rectangle, etc. as bits (which
is what is done when you draw them directly to the screen), but the use of the
intermediate bitmap reduces flicker because this intermediate bitmap can be transferred to
the visible window within one frame time. But until you get the fundamental algorithms
right, worrying about optimizations like this is inappropriate. Get the core tecnology
right, FIRST. Right now, you are a very long way from that.

You have obviously missed all of the key ideas in the Scribble tutorial, because you
fixated on trivia such as lines vs. objects. Study the core algorithms first. Then you
can see how they generalize to other objects.
joe
*****
Joseph M. Newcomer [MVP]
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
.



Relevant Pages

  • Re: CRectTracker: how to remove old rectangle without flick
    ... flicker free rectangle drawing. ... afx_msg void OnPaint(); ... >> It seems that you are not drawing the resize rect within the OnPaint ... >> would have a class for each shape that the user would be able to draw. ...
    (microsoft.public.vc.mfc)
  • Re: MFC Custom Control in a MFC DLL
    ... You are confusing drawing with "initialization". ... Doing drawing outside the OnDraw handler makes no sense! ... (There are VERY RARE exceptions, such as doing rubber-banding in OnMouseMove, but they are ... assume that it is not valid to draw outside OnDraw. ...
    (microsoft.public.vc.mfc)
  • Re: MFC Custom Control in a MFC DLL
    ... You are confusing drawing with "initialization". ... Doing drawing outside the OnDraw handler makes no sense! ... (There are VERY RARE exceptions, such as doing rubber-banding in OnMouseMove, but they are ... assume that it is not valid to draw outside OnDraw. ...
    (microsoft.public.vc.mfc)
  • Re: Drawing on DC
    ... class Circle: public Drawing { ... It would be *called* from OnDraw, ... You should only draw when you need to draw, ... Drawing your objects on a bitmap merely renders the circle, rectangle, etc. as bits (which ...
    (microsoft.public.vc.mfc)
  • Re: How do you MAGNIFY the view?
    ... Larry posted some code and I posted some slightly different code myself (the second lot which refreshed only the "previously occupied area" of the magnifying rectangle rather than refreshing the entire picturebox) and neither of them showed any flicker under normal use on Larry's "circles" example. ... In your particular case, where the "sprite" is rectangular and which does not need to have any transparent areas, you only need to buffer your drawing if the "original sprite rectangle" and the "new sprite rectangle" either totally or partially overlap. ... In cases where they do not overlap then you can simply "draw the original background at the old location" and then "draw the new magnified rectangle" at the new location, drawing both of them straight to the display as I think you are already doing. ...
    (microsoft.public.vb.general.discussion)

Loading