Click to See Complete Forum and Search --> : Can ScrollDC(...) be used with memoryDC????


umeshSharma_ait
June 10th, 2003, 08:46 AM
Hi all,

Can I use ScrollDC(...) api for scrolling memoryDC ??? I had used but Iam not getting the result. MemoryDC content remain as it is before.

Is ScrollDC(..) is correct solution for scrolling memory DC content..

Plz reply

Umesh

DarkenMind
June 17th, 2003, 03:16 AM
Hi,

afaik it is not possible nor neccessary to scroll a MemoryDC.

What do you want exactly to do?
Scrolling to a visible surface (window including dc) might be performed via BitBlt from your MemoryDC.

Therefore you don't need to 'scroll' the MemoryDC, but you copy the Rectangle ( scrolloffset x, scrolloffsety, windowwidth, windowheight) to your visible DC.

I'm using a derived class from CScrollview to scroll the contents of a MemoryDC.

It's a little bit tricky, but i create a CScrollView descendant without Document/View architecture, for example in "OnInitDialog":

CDerievedView *pView = (CDerivedView *) RUNTIME_CLASS(CDerivedView)->CreateObject();
pView->SetScrollSizes( MM_TEXT, CSize(0,0));

CRect ClientRect;
GetClientRect( ClientRect);
//modify the ClientRect to fit in your window
pView->Create( NULL, NULL, WS_CHILD | WS_VISIBLE, ClientRect, this, 0);


now you can size the DC of the view to the size of your MemoryDC via

SetScrollSizes( MM_TEXT, CSize( MemDC_Width, MemDC_Height));


now you have only to override the OnDraw function in your View:

CDerivedView::OnDraw(CDC* pDC)
{
CRect rect;

GetClientRect( rect);

CPoint Scroll = GetScrollPosition();

ScrollToPosition( Scroll);
BitBlt( pDC->GetSafeHdc(), Scroll.x, Scroll.y, rect.Width(), rect.Height(), MemoryDC, Scroll.x, Scroll.y, SRCCOPY);
}

now. it is not transferring the full DC, but only the visible rectangle. Event at a size of 800x600 its very fast.

I implemented this technique in my own ActiveX-Control.


If you got any questions, just ask me :-)

umeshSharma_ait
June 18th, 2003, 01:18 AM
Hi,
Thnx for replying...
I will tell u my whole problem in detail....
Iam working on the word processor like applicaion....Iam implementing double buffering in it. For I had used memoryDC to reduce the flickering.
Problem :- when iam scrolling the client are of window then I need to process only that portion of client area which is scrolled in.Rest should not be processed.

Now Iam using
::ScrollWindowEx( mhWindow, nXScroll, YScroll, (RECT*)opScroll, (RECT*)opClip, NULL, &oUpdate, SW_ERASE);

where
mhwindow - window handle which i have to scroll
nXScroll - amount of horizontal scroll
nYScroll - amount of vertical scroll
....
With this my window content is scrolled but my memoryDC content remain as it was before.
Now if I have to display the content then whole memory content should be drawn and then displayed on to the screen which take considerable amount of time because of that my scrolling response become slow.

I have following solution for this problem....

1. I will bitblt the area which is not affected from screenDC to memoryDC .Process only that portion which is scrolled inside ..

2. use Bitblt(...) where destination and source DC will memoryDC and shift the content to the scrolled side.Process only that portion which is scrolled inside ..Finally display to the screen.
But with that Iam not sure whether I can use the memoryDC as both source and destination or not...
Plz clarify this if u Can......

3. use scrollDC(..) on memoryDC which I asked earliar....

If u another good solution then plz let me know...

waiting for ur reply :-)

Umesh

DarkenMind
June 18th, 2003, 02:09 AM
Hi,

I'm not quite sure, whether i understood, what you exactly try to do. But it sounds to me like your MemoryDC should reflect all changes done to the window, right?

However there is no need to "scroll" a memory DC!
If you plan to use a memory DC, you cannot scroll it, you need to create it with the full scrolling size.

eg: Your Window has a visible surface of 300x400 pixels, and your Spreadsheet or whatever you display/edit has a total size of 2300 x 3600 pixels (just an example).

If you want a memory DC containing the whole information, you will need to create a compatible bitmap of the desired size, an select it into the DC, here a small function, how to resize a DC:

void ResizeDC( HDC hDC, int nWidth, int nHeight)
{
HDC hdcDesktop = GetDC(NULL);
HBITMAP hbmNew = CreateComaptibleBitmap( hdcDesktop, nWidth, nHeight);
if (hbmNew == NULL)
// some error
return;

ReleaseDC( NULL, hdcDesktop);

HGDIOBJ hbmOld = SelectObject( hDC, hbmNew);
if (hbmOld == NULL)
// again something went wrong
return;

DeleteObject( hbmOld);
}

with this function you can set the size of your memory DC, but there is no warranty, it will work with very large bitmaps. I had the same problem in my ActiveX Control, because i wanted to render the whole picture in a memory DC, an on Scroll only BitBlt the needed portion.

I did'nt manage it.
Maybe you will find a way, but resizing with a compatible bitmap is the only way i know to resize a DC.

When your window is scrolling, and some content has changed, you will have to BitBlt the affected region into the memory DC.
Hope i'm right :-)

If you want to "grab" to complete content of the window (including non visible area), you only need to BitBlt to memory DC with the whole size. If your window is going to be destroyed, you can "steal" the contents:

void StealDC( hDC hdcSource, hdc hdcDest)
{
HDC hdcDesktop = GetDC(NULL);
HBITMAP hbmNew = CreateCompatibleBitmap( hdcDesktop, 1, 1);

ReleaseDC( NULL, hdcDesktop);
HBITMAP hbmSave = (HBITMAP) SelectObject( hdcSource, hbmNew);

if (hbmSave == NULL)
return;

HGDIOBJ hbmOld = SelectObject( hdcDest, hbmSave);

if (hbmOld == NULL)
return;

DeleteObject( hbmOld);
}

Hope this will help you.
I'm offline till next monday, so good luck :-)

umeshSharma_ait
June 24th, 2003, 06:20 AM
hi ,
My project is MDI application .In that there are few modeless dialog boxes which are the child of the mainframe.Mainframe is also parent of childwnd in which actually drawing taking place.
During vertical and horizontal scrolling, Iam drawing only that part of the client area which is newly scrolled inside.
Problem is if some modelless window are present over the client area of the childwnd window then during scrolling, the area (i.e. part of client area of childwnd window) which is behind the modelless dialog which is also scrolled is not coming under invalidation.
Iam not getting how to invalidate that area only. I dont want to process whole cleint area of the parent window.
How can I have that area under invalidation so that i can process that area only ??

hoping for reply soon

Umesh