Double buffering/wxScrolledWindow problem

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
jamesrf
Earned a small fee
Earned a small fee
Posts: 14
Joined: Fri Sep 03, 2004 11:26 am
Location: Oxford, UK
Contact:

Double buffering/wxScrolledWindow problem

Post by jamesrf » Fri Sep 10, 2004 4:29 pm

Hi board,

I am trying to double buffer stuff that I'm drawing in a wxScrolledWindow but I don't seem to be able to do it without allocating a bitmap that is the virtual size of the window. Obviously this won't work if the view is huge. What I want is to allocate a bitmap that is the size of the client rect and then blit it. But I can't. This is the code I've got, which works except for the allocated size of the bitmap. Everything drawn to the window is in "unscrolled coordinates". I've tried calling PrepareDC() on the MemoryDC and I've tried passing the PaintDC to the MemoryDC constructor but neither of these work. Can anyone help? A way that I know of to definitely get round it is to convert everything to window coords before drawing and then don't call PrepareDC - but this makes using a wxScrolledWindow a bit pointless. Can anyone help?

James

wxMemoryDC dc;
int x, y;
GetVirtualSize(&x, &y); // Want to call GetClientSize() here...
wxBitmap bitmap(x, y);
dc.SelectObject(bitmap);
dc.Clear();

paint(dc);

wxPaintDC paintDC(this);
PrepareDC(paintDC);
paintDC.Blit(0, 0, x, y, &dc, 0, 0);

rhorn
In need of some credit
In need of some credit
Posts: 8
Joined: Sun Aug 29, 2004 11:13 pm
Location: Oshkosh, WI, United States
Contact:

Post by rhorn » Fri Sep 10, 2004 5:59 pm

You need to figure out your scroll position and blit from there. See wxScrolledWindow::CalcUnscrolledPosition.
I have a slightly more updated version of wxImagick on my website.

If this helped you, please take the time to rate the value of this post:
http://rate.affero.net/rhorn/

Cursor
Earned some good credits
Earned some good credits
Posts: 120
Joined: Sun Aug 29, 2004 3:09 pm
Location: Grenoble, France
Contact:

Post by Cursor » Sat Sep 11, 2004 8:57 am

We talk about wxScrolledWindow, I have another problem with it too.
As a big flikking is visible, I would use a wxBufferedPaintDC. in my intercept of wPaintEvent.
It is OK : no flikkinkg, correct offset according scorllbars.
But one problem : when I scroll (pageup/pagedown) the old showed zone is correctly blited but the outer zone (now visible) is badly refreshed.

An idea ?

jamesrf
Earned a small fee
Earned a small fee
Posts: 14
Joined: Fri Sep 03, 2004 11:26 am
Location: Oxford, UK
Contact:

Post by jamesrf » Mon Sep 13, 2004 10:45 am

Cursor wrote:We talk about wxScrolledWindow, I have another problem with it too.
As a big flikking is visible, I would use a wxBufferedPaintDC. in my intercept of wPaintEvent.
It is OK : no flikkinkg, correct offset according scorllbars.
But one problem : when I scroll (pageup/pagedown) the old showed zone is correctly blited but the outer zone (now visible) is badly refreshed.

An idea ?
I didn't know about the wxBufferedPaintDC. It basically does the same thing as the code I posted. I can't get it to work with a wxScrolledWindow. I've tried Ryan's suggestion but nothing works.

I'm not sure how to interpret what you've written. I'm not sure whether you've got it nearly working, or whether its actually just completely broken...

Has anyone ever done double buffering with a wxScrolledWindow? How on earth do you do it???

rhorn
In need of some credit
In need of some credit
Posts: 8
Joined: Sun Aug 29, 2004 11:13 pm
Location: Oshkosh, WI, United States
Contact:

Post by rhorn » Mon Sep 13, 2004 11:23 am

jamesrf wrote:
Cursor wrote:We talk about wxScrolledWindow, I have another problem with it too.
As a big flikking is visible, I would use a wxBufferedPaintDC. in my intercept of wPaintEvent.
It is OK : no flikkinkg, correct offset according scorllbars.
But one problem : when I scroll (pageup/pagedown) the old showed zone is correctly blited but the outer zone (now visible) is badly refreshed.

An idea ?
I didn't know about the wxBufferedPaintDC. It basically does the same thing as the code I posted. I can't get it to work with a wxScrolledWindow. I've tried Ryan's suggestion but nothing works.

I'm not sure how to interpret what you've written. I'm not sure whether you've got it nearly working, or whether its actually just completely broken...

Has anyone ever done double buffering with a wxScrolledWindow? How on earth do you do it???
Yes, and it's just like double buffering anywhere else. What I would suggest is to create a wxMemoryDC member for the class you want to double buffer, as well as a wxBitmap member and a wxImage (or wxImagick) member. Do all your drawing on the wxMemoryDC member (with the wxBitmap member created from the wxImage member), then just blit it to your target DC. I don't bother with wxBufferd[Paint]DC because they create too much overhead. It essentially does this, but continuously deletes and recreates them, which I find wasteful.

PS You'll want to do this in response to a paint event.
I have a slightly more updated version of wxImagick on my website.

If this helped you, please take the time to rate the value of this post:
http://rate.affero.net/rhorn/

jamesrf
Earned a small fee
Earned a small fee
Posts: 14
Joined: Fri Sep 03, 2004 11:26 am
Location: Oxford, UK
Contact:

Post by jamesrf » Tue Sep 14, 2004 4:48 pm

rhorn wrote:
jamesrf wrote:
Cursor wrote:We talk about wxScrolledWindow, I have another problem with it too.
As a big flikking is visible, I would use a wxBufferedPaintDC. in my intercept of wPaintEvent.
It is OK : no flikkinkg, correct offset according scorllbars.
But one problem : when I scroll (pageup/pagedown) the old showed zone is correctly blited but the outer zone (now visible) is badly refreshed.

An idea ?
I didn't know about the wxBufferedPaintDC. It basically does the same thing as the code I posted. I can't get it to work with a wxScrolledWindow. I've tried Ryan's suggestion but nothing works.

I'm not sure how to interpret what you've written. I'm not sure whether you've got it nearly working, or whether its actually just completely broken...

Has anyone ever done double buffering with a wxScrolledWindow? How on earth do you do it???
Yes, and it's just like double buffering anywhere else. What I would suggest is to create a wxMemoryDC member for the class you want to double buffer, as well as a wxBitmap member and a wxImage (or wxImagick) member. Do all your drawing on the wxMemoryDC member (with the wxBitmap member created from the wxImage member), then just blit it to your target DC. I don't bother with wxBufferd[Paint]DC because they create too much overhead. It essentially does this, but continuously deletes and recreates them, which I find wasteful.

PS You'll want to do this in response to a paint event.
Thanks for your help Ryan - appreciated. I don't understand the need for a wxImage member. Also, this doesn't really help me that much because I'm basically doing this already (albeit with different lifetime semantics). I don't suppose there's an example of a double buffered wxScrolledWindow anywhere?

soichih
In need of some credit
In need of some credit
Posts: 1
Joined: Sun Sep 11, 2005 2:47 am

I had the same problem, and this is how you fix it.

Post by soichih » Sun Sep 11, 2005 2:50 am

void objectmap::OnPaint( wxPaintEvent &event )
{
wxBufferedPaintDC dc(this);

//get the current visible area (is this the easiest way!?!?)
wxSize clientsize = GetClientSize();
int xbegin, ybegin;
GetViewStart(&xbegin, &ybegin);
int xunit, yunit;
GetScrollPixelsPerUnit(&xunit, &yunit);
xbegin*=xunit;
ybegin*=yunit;

//this correct the problem with the scrolling
dc.SetDeviceOrigin(-xbegin, -ybegin);

//do your all drawing as if you don't know anything about scrolling nor double-buffering
}

Post Reply