|
I think it is a great work!!! thanks a lot of...
MR.Flicker
|
|
|
|
|
I have a CWnd class with scrolls and its not working! Also im working with different mapping modes.
Any ideia?
|
|
|
|
|
It is good for view,
but does not work well in formview,
it still flicking when I zoom in or out my graph, why?
How to do in formview?
Help me!
Thanks
wang feng
|
|
|
|
|
Well, I have programming MFC for some time now, and have used numerous CView-derived classes. But I have not used CFormView yet. My humble guess is that there is some function (probably able to be overridden) that is related to drawing/updating the view that the other view's dont have.
I suggest going to MSDN and looking up the CFormView members, especially the OnWhatever functions section and compare it to say...CView or CEditView. Check for different functions and check their descriptions.
|
|
|
|
|
OnPaint()
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientRect(&rect);
CMemDC memDC(&dc,&rect)
however when a SetWindowOrg does not perform wat it is supposed to perform. Wat's wrong?
The setting of the window origin is wrong.
Thanxs
|
|
|
|
|
Faced similiar problem in OnPaint to draw a static area. After commenting the SetWindowExt, SetViewportExt and SetWindowOrg, I was able to draw properly.
|
|
|
|
|
Just what I needed. Cleared up a number of problems, including the redraw of overlapping objects.
You're properly acknowledged in the "About" dialog of my app. Saved me hours.
MT
http://www.teddev.com
|
|
|
|
|
Could anyone offer any advice on using this technique with a dialog-based app (if it's even possible). I'm new to the game and I'm trying to get rid of some update-related flicker in a progress control that I'm stepping through with a timer. Any advice would be appreciated.
blitzn
|
|
|
|
|
if you are subclassing your progress control u can do this
#include "memdc.h"
void CMyProgressCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rect;
GetClientWindow(&rect);
CMemDC memDC(&dc,&rect);
// do your updating of your progress control
memDC.FillSolidRect(.........);
}
|
|
|
|
|
As I said, it does not work
|
|
|
|
|
In case anyone wants it, I have added some additional code into memdc.h that will allow it to support non-MFC C++ and straight C via ifdefs. Let me know here if you are interested.
|
|
|
|
|
I have received enough requests that I have decided to post it here.
<br />
<br />
<br />
#ifndef _MEMDC_H_<br />
#define _MEMDC_H_<br />
#else<br />
#error this file has already been included<br />
#endif<br />
<br />
#ifdef __cplusplus<br />
<br />
<br />
#ifdef _AFXDLL // for use with MFC<br />
<br />
<br />
class CMemDC : public CDC<br />
{<br />
private: <br />
CBitmap m_bitmap;
CBitmap* m_oldBitmap;
CDC* m_pDC;
CRect m_rect;
BOOL m_bMemDC;
public:<br />
<br />
CMemDC(CDC* pDC, const CRect* pRect = NULL) : CDC()<br />
{<br />
ASSERT(pDC != NULL); <br />
<br />
m_pDC = pDC;<br />
m_oldBitmap = NULL;<br />
m_bMemDC = !pDC->IsPrinting();<br />
<br />
if( pRect == NULL )<br />
{<br />
pDC->GetClipBox(&m_rect);<br />
}<br />
else<br />
{<br />
m_rect = *pRect;<br />
}<br />
<br />
if( m_bMemDC )<br />
{<br />
CreateCompatibleDC(pDC);<br />
pDC->LPtoDP(&m_rect);<br />
<br />
m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());<br />
m_oldBitmap = SelectObject(&m_bitmap);<br />
<br />
SetMapMode(pDC->GetMapMode());<br />
SetWindowExt(pDC->GetWindowExt());<br />
SetViewportExt(pDC->GetViewportExt());<br />
pDC->DPtoLP(&m_rect);<br />
SetWindowOrg(m_rect.left, m_rect.top);<br />
}<br />
else<br />
{<br />
m_bPrinting = pDC->m_bPrinting;<br />
m_hDC = pDC->m_hDC;<br />
m_hAttribDC = pDC->m_hAttribDC;<br />
}<br />
<br />
COLORREF bgc = pDC->GetBkColor();<br />
FillSolidRect( m_rect, bgc );<br />
}<br />
<br />
<br />
~CMemDC() <br />
{ <br />
if( m_bMemDC )<br />
{<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 />
else<br />
{<br />
m_hDC = m_hAttribDC = NULL;<br />
} <br />
}<br />
<br />
CMemDC* operator->() { return this; } <br />
<br />
operator CMemDC*() { return this; }<br />
};<br />
<br />
<br />
#endif // _AFXDLL<br />
<br />
<br />
<br />
class CMemoryDC<br />
{<br />
private:<br />
HBITMAP m_hbitmap;<br />
HBITMAP m_holdbmp;<br />
HDC m_hDC;<br />
HDC m_holdDC;<br />
RECT m_rBounds;<br />
int m_Width;<br />
int m_Height;<br />
<br />
public:<br />
CMemoryDC( HDC hDC, const RECT *rBounds )<br />
{<br />
m_holdDC = hDC;<br />
m_hDC = CreateCompatibleDC( hDC );<br />
memcpy( &m_rBounds, rBounds, sizeof( RECT ) );<br />
m_Width = m_rBounds.right - m_rBounds.left;<br />
m_Height = m_rBounds.bottom - m_rBounds.top;<br />
m_hbitmap = CreateCompatibleBitmap( hDC, m_Width, m_Height );<br />
m_holdbmp = (HBITMAP)SelectObject( m_hDC, m_hbitmap );<br />
}<br />
<br />
~CMemoryDC() <br />
{<br />
BitBlt( m_holdDC, m_rBounds.left, m_rBounds.top, m_Width, m_Height, <br />
m_hDC, m_rBounds.left, m_rBounds.top, SRCCOPY );<br />
SelectObject( m_holdDC, m_holdbmp );<br />
if( m_hbitmap != NULL ) DeleteObject( m_hbitmap );<br />
if( m_hDC != NULL ) DeleteDC( m_hDC );<br />
}<br />
<br />
HDC GetDC() { return m_hDC; }<br />
<br />
HDC operator->() { return m_hDC; }<br />
};<br />
<br />
<br />
#else // __cplusplus<br />
<br />
<br />
#ifndef _INC_MALLOC<br />
#include <malloc.h><br />
#endif<br />
<br />
<br />
typedef struct<br />
{<br />
HBITMAP m_hbitmap;<br />
HBITMAP m_holdbmp;<br />
HDC m_hDC;<br />
HDC m_holdDC;<br />
RECT m_rBounds;<br />
int m_Width;<br />
int m_Height;<br />
} MemDC;<br />
<br />
<br />
__inline MemDC * InitMemDC( HDC hDC, const RECT *rBounds )<br />
{<br />
MemDC * mdc = calloc( 1, sizeof( MemDC ) );<br />
if( ! mdc )<br />
return NULL;<br />
<br />
mdc->m_holdDC = hDC;<br />
mdc->m_holdbmp = NULL;<br />
<br />
mdc->m_hDC = CreateCompatibleDC( hDC );<br />
memcpy( &mdc->m_rBounds, rBounds, sizeof( RECT ) );<br />
mdc->m_Width = mdc->m_rBounds.right - mdc->m_rBounds.left;<br />
mdc->m_Height = mdc->m_rBounds.bottom - mdc->m_rBounds.top;<br />
mdc->m_hbitmap = CreateCompatibleBitmap( hDC, mdc->m_Width, mdc->m_Height );<br />
mdc->m_holdbmp = (HBITMAP)SelectObject( mdc->m_hDC, mdc->m_hbitmap );<br />
return mdc;<br />
}<br />
<br />
<br />
__inline HDC GetMemDC( MemDC *mdc )<br />
{<br />
return mdc->m_hDC;<br />
}<br />
<br />
<br />
__inline MemDC * TermMemDC( MemDC *mdc )<br />
{<br />
BitBlt( mdc->m_holdDC, mdc->m_rBounds.left, mdc->m_rBounds.top,<br />
mdc->m_Width, mdc->m_Height, mdc->m_hDC,<br />
mdc->m_rBounds.left, mdc->m_rBounds.top, SRCCOPY );<br />
SelectObject( mdc->m_holdDC, mdc->m_holdbmp );<br />
if( mdc->m_hbitmap != NULL )<br />
DeleteObject( mdc->m_hbitmap );<br />
if( mdc->m_hDC != NULL )<br />
DeleteDC( mdc->m_hDC );<br />
free( mdc );<br />
return NULL;<br />
}<br />
<br />
<br />
#endif // __cplusplus<br />
<br />
|
|
|
|
|
hi,
you should account for left and top of rBounds in CMemoryDC ctor like this
// offset dc origin
SetWindowOrgEx(m_hDC, m_rBounds.left, m_rBounds.top, NULL);
you don't need m_Width and m_Height if you have m_rBounds -- just calc them on the fly.
you can check for rBounds == NULL and do a GetClipBox in the ctor the way the original class is doing. an assert would be nice if m_rBounds.left == rBounds.right (no clipbox found).
nice piece of code, didn't notice it before and just finished re-implementing it myself )
HTH,
</wqw>
|
|
|
|
|
The MemDC works fine, even in a ScrollView. The only problem I can see by now is using DrawDragRect. If ScrollPos is not (0,0), I have to call LPtoDP on the drag rect before calling DrawDragRect. Why?
|
|
|
|
|
I am having trouble with CListView and the CMemDC class. It works fine for the columns that have been inserted but not for the rest of the screen. It is a simple listview from the wizard with CListView as the base class. I then add three columns and fill up about 10 rows. but only the first ten rows are cleared of the background image. The rest show the window that was on the screen before the app was run.
As more rows are added then they are cleared as well. Also, if the window is opened beyond the 3 columns then the extra space on the right is also not cleared up.
I am fairly new to MFC and I have tried to adjust how the rect is created with no luck. I thought if I created a larger bitmap it would work.
Any help/or ideas would be apprecitated. And I appologize if I am missing something simple here.
Thanks,
John
|
|
|
|
|
---
Eugene Pustovoyt
Sonork ID 100.10002:Yaumen
|
|
|
|
|
There's an error in your usage of OnEraseBackground(). It should return TRUE, not FALSE.
Great article otherwise; I've been using variants of this class for years, and it's (IMHO) essential to creating good-looking apps.
|
|
|
|
|
MemDc work under MM_TEXT mode, doesn't work under other modes?
|
|
|
|
|
I think you need to provide more info. The example included with CMemDC demonstrates using it in most modes including MM_TEXT. The only thing I'm aware of that could be a problem is using it with a CScrollView.
So, please send me a small example the demonstrates the issue you are having and why you believe this is a mapping mode issue with CMemDC.
Thanks,
Keith
|
|
|
|
|
1) What is the purpose of the two functions that allow usage as a pointer? I've been passing pointers to classes for years without adding such function to my classes.. including this class.
2) This class sure has grown since it's original lightweight implementation. Isn't the constructor much too big to be an inline function? (That is, an _efficient_ inline function.)
|
|
|
|
|
To simplify the drawing routine in an application, I decided to use this class. It does a lot better. However, it assumes you are always going to be painting the background and therefore uses FillRectSolid to clear the exising background.
This was not suitable for my work, which involves a lot of already intensive drawing using memory dc with CMemDC class only doing additional drawing on top.
To get it to work for me, I modified the class a bit, and here is the result-please let me know if you find problems with it.
class CMemDC : public CDC
{
private:
CBitmap m_bitmap;
CBitmap* m_oldBitmap;
CDC* m_pDC;
CRect m_rect;
BOOL m_bMemDC;
CDC m_dcBk;
CBitmap* m_pbmpOldBk;
CBitmap m_bmpBk;
public:
CMemDC(CDC* pDC, const CRect* pRect = NULL, BOOL bCopyBk = FALSE) : CDC()
{
ASSERT(pDC != NULL);
m_pbmpOldBk = NULL;
m_pDC = pDC;
m_oldBitmap = NULL;
m_bMemDC = !pDC->IsPrinting();
if (pRect == NULL)
{
pDC->GetClipBox(&m_rect);
}
else
{
m_rect = *pRect;
}
if (m_bMemDC)
{
CreateCompatibleDC(pDC);
pDC->LPtoDP(&m_rect);
m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
m_oldBitmap = SelectObject(&m_bitmap);
SetMapMode(pDC->GetMapMode());
pDC->DPtoLP(&m_rect);
SetWindowOrg(m_rect.left, m_rect.top);
}
else
{
m_bPrinting = pDC->m_bPrinting;
m_hDC = pDC->m_hDC;
m_hAttribDC = pDC->m_hAttribDC;
}
if (!bCopyBk)
{
FillSolidRect(m_rect, pDC->GetBkColor());
}
else
{
CWnd* pWnd = m_pDC->GetWindow();
ASSERT(pWnd);
CClientDC clDC(pWnd);
m_dcBk.CreateCompatibleDC(&clDC);
m_bmpBk.CreateCompatibleBitmap(&clDC, m_rect.Width(), m_rect.Height());
m_pbmpOldBk = m_dcBk.SelectObject(&m_bmpBk);
m_dcBk.BitBlt(0, 0, m_rect.Width(), m_rect.Height(), &clDC, m_rect.left, m_rect.top, SRCCOPY);
BitBlt(0, 0, m_rect.Width(), m_rect.Height(), &m_dcBk, 0, 0, SRCCOPY);
}
}
~CMemDC()
{
if (m_bMemDC)
{
m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
this, m_rect.left, m_rect.top, SRCCOPY);
if (m_pbmpOldBk)
SelectObject(m_pbmpOldBk);
SelectObject(m_oldBitmap);
}
else
{
m_hDC = m_hAttribDC = NULL;
}
}
CMemDC* operator->()
{
return this;
}
operator CMemDC* ()
{
return this;
}
};
#endif
Paul Selormey, Bsc (Elect Eng), MSc (Mobile Communication) is currently Windows open source developer in Japan, and open for programming contract anywhere!
|
|
|
|
|
The code you provided saved a project of mine from the recycle bin! Thanks!
|
|
|
|
|
This is really a helpful class, and it solved the flicker problem.
Here is one issue that I saw. I used it in my CScrollView (I think other view might have the same issue). If I pops up a message box (or any window) on the top of the view, and move the box around, the CScrollView doesn't refresh the background, so you can see all the movement tracks on your CScrollView.
I'm guessing this is probably caused by return "FALSE" in OnEraseBkgnd() method. I'm wondering why you are doing this? Or can you solve the problem that I described above?
Thanks,
Jerry
|
|
|
|
|
Sir when i view a bitmap on View .I apply some image operations If another window is opened over it the covering portion is erased any clue;)
my email id amritpalbhatia@rediffmail.com
|
|
|
|
|
I use a CScrollView derived class and I don't get the whole view redrawn when I use CMemDC and the Scrollposition is different than the origin...
anybody?
|
|
|
|
|