|
Hi Keith,
I was using your buffer class for drawing to the Devicecontext.It worked fine until I introduced zooming.Iam zoomimg my view using the "SetWorldTransform" in "OnPrepareDc".
I have zoom percentage from 200& 500.
The problem Iam facing now is when I zoom(for example below 200%) & move vertical scroll bar,I dont get the full text of the page in the view.I get only parts of the next.
wHEN zooming,I guess the clip rectangle is not the same.How can I modify my code in "OnDraw",so that I can pass the right rect to the MemoryDc.
Hope you can give a hand....
Thanks...
Please see below the codes in my View.
*************************************
void TestView::OnDraw(CDC* pDC)
{
CSize size;
size.cx = 45;
size.cy = 45;
//Creating a temporary Dc which is my buffer class.
MemDc DC(pDC);
SetScrollSizes(MM_TEXT, size);
}
void TestView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
pDC->SetMapMode(MM_TEXT);
SetGraphicsMode(pDC->GetSafeHdc(), GM_ADVANCED);
TEXTMETRIC Metrics;
pDC->GetTextMetrics(Metrics);
Form.eM11 = 0.01 * zoom;//Member variable of my class & can be 200,500
Form.eM21 = 0;
Form.eDx = 0;
Form.eM12 = 0;
Form.eM22 = 0.01 * zoom;
Form.eDy = 0;
SetWorldTransform(pDC->GetSafeHdc(), &Form);
LOGFONT LogFont;
Font.GetLogFont(&LogFont);
CScrollView::OnPrepareDC(pDC, pInfo);
}
-- modified at 7:14 Wednesday 28th September, 2005
|
|
|
|
|
Dear Keith,
First of all a big thanks for sharing your CMemDC class! It's great!
I've been using CMemDC for all the painting of my views, but I have encountered this problem of getting a strip of horizontal streaks right across the top of the screen when I run my application. I suspect it's something wrong with my drawing code for the bitmaps I display on the screen. Can I ask whether the following, when using CMemDC as the destination CDC, is correct for blitting the bitmaps on the screen? Your help is greatly appreciated!
=========================================================================
void MyView::drawBitmaps(CDC* pDC)
{
// Note: pDC is a CMemDC* of the DC passed to the view's OnDraw(pDC)
// --------------------- draw the baby bitmap --------------------- //
BITMAP bmpInfo;
m_bmpBaby.GetBitmap(&bmpInfo);
// Create an in-memory DC compatible with the
// display DC we're using to paint
CDC dcMemory;
dcMemory.CreateCompatibleDC(pDC);
// Select the bitmap into the in-memory DC
CBitmap* pOldBitmap = dcMemory.SelectObject(&m_bmpBaby);
// Set position of the bitmap
int nX = m_babyPicRect.left;
int nY = m_babyPicRect.top;
int nW = m_babyPicRect.Width();
int nH = m_babyPicRect.Height();
// Copy the bits from the in-memory DC into CMemDC
pDC->StretchBlt(nX, nY, nW, nH, &dcMemory, 0, 0, bmpInfo.bmWidth,
bmpInfo.bmHeight, SRCCOPY);
dcMemory.SelectObject(pOldBitmap);
// ------------------- draw the electrodes bitmap ---------------------
m_bmpElectrodeLoc.GetBitmap(&bmpInfo);
// Select the bitmap into the in-memory DC
pOldBitmap = dcMemory.SelectObject(&m_bmpElectrodeLoc);
// Set position of the bitmap
nX = m_elecPosPicRect.left;
nY = m_elecPosPicRect.top;
nW = m_elecPosPicRect.Width();
nH = m_elecPosPicRect.Height();
pDC->StretchBlt(nX, nY, nW, nH, &dcMemory, 0, 0, bmpInfo.bmWidth,
bmpInfo.bmHeight, SRCCOPY);
dcMemory.SelectObject(pOldBitmap);
}
==========================================================================
What happens is that my application requires the view to repaint when OnTimer() is called, because I need to display certain information on a timely basis. drawBitmaps() is thus called every few seconds. I do not see the corrupted colour strip appearing the first few times, but it starts after one to two minutes, then reoccurs every so often.
My apologies for such a long question! Thanks in advance!!
Kind regards,
Isa
|
|
|
|
|
Would someone please be able to help me out on this one? Is my problem the same as the one mentioned in the 'streaks and smudging' thread?
Thanks in advance...
|
|
|
|
|
Hey, thanks for the code, this has been a great tool to get rid of the flicker with. Unfortunately, a new problem has arisen: whenever i move a window or a dialog across the view, it'll leave random streaks vertical or horizontal to the direction the window/dialog is dragged across it. There's also a bit of smudging of characters as well. How do I fix this?
|
|
|
|
|
I can honestly say I've never run across this behavior. However, if my application was doing this I would look at my drawing code. It sounds to me like you aren't redrawing the entire clip rectangle for some reason, which is leaving the artifacts you are describing.
Please let me know what you find out.
Thanks,
Keith Rule
|
|
|
|
|
I have found the problem occurs in my app as well. Essentially when a dilog box is overlaid on CView drawn using CMemDC and the dialog box is moved in quick jerks it leaves a thin blue line (the colour of the border of the dialog box). The problem seems to go away when you specify the correct rect in CMemDC(DC*, RECT*) ctor.
If winter comes is spring far behind? - (PBShelley -Ode to the West Wind)
|
|
|
|
|
I've looked at this and modified your CMemDC ctor as follows:
CMemDC(CDC* pDC, const CRect* pRect = NULL) : CDC()
//pRect is in device co-ordinates
//printing stuff removed as I didn't need it
{
ASSERT(pDC != NULL);
// Some initialization
m_pDC = pDC;
m_oldBitmap = NULL;
// Get the rectangle to draw
CRect lrect;
if (pRect == NULL) {
pDC->GetClipBox(&m_rect);
lrect=m_rect;
pDC->LPtoDP(&lrect);
} else {
lrect = *pRect;
m_rect=lrect;
pDC->DPtoLP(&m_rect);
}
//lrect is in device units
//m_rect is in logical units
CreateCompatibleDC(pDC);
m_bitmap.CreateCompatibleBitmap(pDC, lrect.Width(),lrect.Height());
m_oldBitmap = SelectObject(&m_bitmap);
SetMapMode(pDC->GetMapMode());
SetWindowExt(pDC->GetWindowExt());
SetViewportExt(pDC->GetViewportExt());
//pDC->DPtoLP(&m_rect);
SetWindowOrg(m_rect.left, m_rect.top);
// Fill background
FillSolidRect(m_rect, pDC->GetBkColor());
}
Now it seems OK.
chakra
"Some people will do anything for money...Even work"
|
|
|
|
|
yeah, i have the same situation as you have, if no rect specified in ctor, there would be streaks if jerk the the drawing window from unhiding.
one is the other who absorbs the thoughts of others
|
|
|
|
|
I set window extent, viewport exten and window origin.
good luck
chakra
If winter comes is spring far behind? - (PBShelley -Ode to the West Wind)
|
|
|
|
|
hey, charkra did you change the windowOrg? ViewOrg? WinExtent? ViewExtent?
in my codes, I changed the ViewOrg, so the BitBlt could not work . these all could trigger the bug.
in this sense, the class CMemDC is not so feasible as it looks.
one is the other who absorbs the thoughts of others
|
|
|
|
|
I've got the same problem...know of any other possible solution or another class to use?
Thx!
|
|
|
|
|
I'm guessing here, but in your example, one of the modes you support is MM_ANISOTROPIC. At first glance, it appears to work. However, the settings for the viewport extent and the window extent effectively make your MM_ANISOTROPIC equivalent to MM_TEXT...
// Equivalent to MM_TEXT which does not experience rounding errors
pDC->SetWindowExt(1,1);
pDC->SetViewportExt(1,1);
In order to effectively use MM_ANISOTRIC or MM_ISOTROPIC, you need to modify the extents which will usually introduce "off by one errors" or "rounding errors". These errors can be observed in your code if you remove the animation, output a line of text or some graphic in Anisotropic and modify the extents in OnPrepareDC. I have had issues with this technique as presented in 5 other books. I would guess this is what others are experiencing but failing to provide you with much information about.
Microsoft article Q89215 "Mapping Modes and Round-Off Errors" Link to the article last time I checked[^] sums this all up and gives a few clues on how to get around this. Be forwarned, the article is OLD (16 bit days) but the material is still relevant. The article does not provide any good "fit to width" or "fit to size" solutions but the hints as to what a programmer should do to circumvent these "rounding errors" are there. You will find that you can still use the mapping modes to do 80% of the work for you but you WILL need to provide work arounds and accept some tradeoffs and reasonable upper limits on scaling but the general offscreen buffer technique presented in your article will work in the "roll your own" modes like MM_ANISOTROPIC or MM_ISOTROPIC without smearing or smudging.
I hope this information helps those who are experiencing "smearing" to adapt the technique to their respective environments and needs.
NOTE:make sure your "Display Properties/Effects" tab property page has the "Show window contents while dragging" setting turned on to observe the effect.
-- modified at 12:22 Friday 9th June, 2006
|
|
|
|
|
Whoever voted the post down obviously did not try the authors code in the context I presented so I will restate it...
"These errors can be observed in (the) code if you remove the animation, output a line of text or some graphic in Anisotropic and modify the extents in OnPrepareDC."
NOTE:make sure your "Display Properties/Effects" tab property page has the "Show window contents while dragging" setting turned on to observe the effect.
Do this and drag the help/about box over the text and you'll see the smudging and smearing. If you sensed some sort of bashing on the article, then your making up stories and reading a bit much into what was intended to help others (like myself) who spent weeks, if not months trying to debug the remnant smearing in the technique presented by Charles Petzold, Jones, and many others in their texts that are pretty much the same as in the article. The technique works when the extents ratio is 1/1 but try changing the extents as you would with MM_ANISOTROPIC or MM_ISOTROPIC and you will find yourself in the same boat, scratching your head, tempted to resort to your own custom scaling.
The Microsoft article referenced made a lightbulb go on for me and I found a solution which allows the use of MM_ISOTROPIC with memory buffering and no smearing so I thought I'd share the fact that Article Q89215 proved helpful for me in my problem context and might be for others. If not, I wish them luck in their endeavors nonetheless. At least I tried to help.
At least post a reply indicating why you voted it down so I could learn something if you had something to say concerning the smudging problem observed by some members of CP.
-- modified at 12:23 Friday 9th June, 2006
|
|
|
|
|
Right so after 4 days of solid work on this i have finally found out what is wrong.
It resides in the rounding errors between DP and LP and that the offscreen bitmap and the DC get misaligned.
It eventually boiled down to SetWindowOrg(m_rect.left, m_rect.top); resulting in misalignment.
I replaced this with:
CPoint viewportOrg = pDC->GetViewportOrg();
SetViewportOrg(viewportOrg);
I have added/removed bits to the class to make it work with my CScrollView. I got rid of the DPtoLP conversions as I was finding errors in the rounding.
You MUST pass it a rectangle that outlines the client box:
CRect clientRect;
GetClientRect(&clientRect);
CMemDC pMemDC(pDC, &clientRect);
Note: This works with my CScrollView. I haven't tested it in any other situations.
class CMemDC : public CDC {
private:
CBitmap m_bitmap;
CBitmap* m_oldBitmap;
CDC* m_pDC;
CRect m_updateRect_LP;
CRect m_clientRect_DP;
BOOL m_bMemDC;
public:
CMemDC(CDC* pDC, const CRect* pClientRect) : CDC()
{
ASSERT(pDC != NULL);
ASSERT(pClientRect != NULL);
m_pDC = pDC;
m_oldBitmap = NULL;
m_bMemDC = !pDC->IsPrinting();
m_clientRect_DP = *pClientRect;
pDC->GetClipBox(&m_updateRect_LP);
if (m_bMemDC) {
CreateCompatibleDC(pDC);
m_bitmap.CreateCompatibleBitmap(pDC, m_clientRect_DP.Width(), m_clientRect_DP.Height());
SetMapMode(pDC->GetMapMode());
SetWindowExt(pDC->GetWindowExt());
SetViewportExt(pDC->GetViewportExt());
m_oldBitmap = SelectObject(&m_bitmap);
CPoint viewportOrg = pDC->GetViewportOrg();
SetViewportOrg(viewportOrg);
CPoint windowOrg = pDC->GetWindowOrg();
SetWindowOrg(windowOrg);
m_updateRect_LP.InflateRect(1,1);
SelectClipRgn(NULL);
IntersectClipRect(&m_updateRect_LP);
}
else
{
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}
}
~CMemDC()
{
if (m_bMemDC)
{
m_pDC->BitBlt(
m_updateRect_LP.left,
m_updateRect_LP.top,
m_updateRect_LP.Width(),
m_updateRect_LP.Height(),
this,
m_updateRect_LP.left,
m_updateRect_LP.top,
SRCCOPY);
SelectObject(m_oldBitmap);
}
else
{
m_hDC = m_hAttribDC = NULL;
}
}
CMemDC* operator->()
{
return this;
}
operator CMemDC*()
{
return this;
}
};
Matt Clarkson
"When the world says 'Give up',
Hope whispers 'Try it one more time.'"
Edit: Added SetWindowOrg.
modified on Wednesday, August 19, 2009 5:57 AM
|
|
|
|
|
I'm writting some text using DrawText function, but it looks bad on the screen, how could I write "nice" text?.
my code is as follows:
init of CFont:
LOGFONT lf;
strcpy(lf.lfFaceName,font_name);
lf.lfHeight=tamy;
lf.lfWeight=bold ? FW_BOLD : FW_NORMAL;
lf.lfEscapement=0;
lf.lfCharSet=ANSI_CHARSET;
lf.lfClipPrecision=CLIP_DEFAULT_PRECIS;
lf.lfItalic=FALSE;
lf.lfOrientation=0;
lf.lfOutPrecision =OUT_DEVICE_PRECIS;
lf.lfPitchAndFamily=FF_DONTCARE;
lf.lfQuality = PROOF_QUALITY;
lf.lfStrikeOut=FALSE;
lf.lfUnderline=FALSE;
lf.lfWidth = tamx; //always is 0
if(!m_font.CreatePointFontIndirect(&lf,NULL))
use of this font:
pDC->SetBkMode(TRANSPARENT);
//centered text
pDC->DrawText(m_text,rectButton,
DT_CENTER|DT_VCENTER|DT_NOCLIP|DT_NOPREFIX|DT_SINGLELINE);
what I'm doing wrong?
thanks in advance.
David.
|
|
|
|
|
Hi there,
I use DrawText as well but have not encountered any problems. What do you mean the text looks bad? Are you drawing on screen or on a button (noticing u have a varialbe 'rectButton')? More source code would help
Cheers,
Isa
|
|
|
|
|
Hi!
Is it possible to get MemDC to work correctly with MM_ISOTROPIC mapping mode? The flicker is gone but when I try to move the bitmap in the window it moves up when I try to drag it down. This is because the y-axis goes upwards in my application. Any help much appreciated!
Thanks!
--
Daniel
|
|
|
|
|
HI Daniel
I am using it with MM_ISOTROPIC. No problem. Does your code work without MemDC? If not you problem lies elsewhere.
joe
If winter comes is spring far behind? - (PBShelley -Ode to the West Wind)
|
|
|
|
|
How can we keep the font is the same one?
|
|
|
|
|
MemDC doesn't reproduce all of the state of the current DC. This is why the examples show defining MemDC immediately in your painting process rather than later.
However, if you need to keep font information, the logical place for you to do this would be in the CMemDC constructor.
Keith Rule
|
|
|
|
|
I'm sorry for my doubt,in my opinion , is there need to free memory resource after we used the variable m_bitmap ?
That is ,in ~CMemDC() function,modify as follow:
<br />
if (m_bMemDC) {<br />
m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),<br />
this, m_rect.left, m_rect.top, SRCCOPY); <br />
<br />
SelectObject(m_oldBitmap); <br />
<br />
m_bitmap.DeleteObject();<br />
} else {<br />
m_hDC = m_hAttribDC = NULL;<br />
}
After all ,thanks for your good work!
|
|
|
|
|
I've used this class for years and have never observed a memory leak with it (and believe me I've looked).
Keith Rule
|
|
|
|
|
The whole approach is failing in alternative Mapping Modes. It only can be used in combination with MM_TEXT. I'm using MM_HIMETRIC, which would imply buffering into a bitmap 100x100=10,000 times larger than for MM_TEXT - there's no such PC to handle a multi-gigabyte bitmap for buffering...
Professional C++ libraries for getting images from any TWAIN or DirectShow compatible device on www.neatcpp.com
|
|
|
|
|
VitalyTomilov wrote:
The whole approach is failing in alternative Mapping Modes. It only can be used in combination with MM_TEXT. I'm using MM_HIMETRIC, which would imply buffering into a bitmap 100x100=10,000 times larger than for MM_TEXT - there's no such PC to handle a multi-gigabyte bitmap for buffering...
This technique simply encapsulates a standard double buffering scheme into a convenient class. There's nothing special or magic about this approach. And like any approach, it isn't appropriate for all situations. The situation you just described will break any double buffering scheme.
That doesn't mean this approach is broken (it isn't), it just means it's not appropriate for current application.
I'm sorry for your difficulties. Good Luck.
Keith Rule
|
|
|
|
|
Part of the view where i'm drawing objects within a clipped area isn't drawn at all, i.e. when i use GUI API ::SelectClipRgn nothing will be drawn within the selected clipping region. Any idea how to fix this?
|
|
|
|
|