scrolled data view

Are you writing your own components and need help with how to set them up or have questions about the components you are deriving from ? Ask them here.
Post Reply
felix
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sat Nov 05, 2011 10:46 am

scrolled data view

Post by felix »

Hey,

I am developing a custom hexeditor control, which should be able to display large files (2gb+, ie only a part of the file is read and the content is drawn into the control). The idea is to have something like a scrolled wxListCtrl, with two colums: offset and data. Above each column, there is a bar (much like a wxListCtrl), which can be clicked (in a wxListCtrl, this is often used to sort the items). This bar should be able to display some text. Also, the bar is always shown, even if the user scrolls down.

As you can see, it`s a pretty classic hexeditor or hexdisplay.
But where would you derive the class from? From a scrolled window, a virtual scrolled window or maybe a list control (remember the bars)?
Equally important, how could i implement highlighting of a single byte/multiple bytes?

If i had to implement it right now, i would go for a wxVScrollledWIndow and two fully independent small buttons of some sort as a label-bars.
I would then calculate the offset for the file from the position of the scroll bars, read data from the file, draw() it to the scrolled window byte per byte.
As for the selection, i would monitor the left mouse button for UP/DOWN events, save the position in the scrolledwindow and re-draw the whole thing, setting the background of the bytes in question to a different color. This does not account for, eg, letting the user have a custom width for the two columns, by just resizing the columns.

Is this generally a good idea? What could i improve or how would you implement this? :D
Auria
Site Admin
Site Admin
Posts: 6695
Joined: Thu Sep 28, 2006 12:23 am
Contact:

Re: scrolled data view

Post by Auria »

I think the way you are proposing makes a lot of sense. It is more work than using a class like wxGrid but in the end it will probably pay off as it will be more flexible
"Keyboard not detected. Press F1 to continue"
-- Windows
felix
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sat Nov 05, 2011 10:46 am

Re: scrolled data view

Post by felix »

Ok, thanks, i`ll start working on it now :)
felix
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sat Nov 05, 2011 10:46 am

Re: scrolled data view

Post by felix »

Hi there again,

So i implemented a basic version of this yesterday, and all seems to work fine. However, when i repaint the whole window multiple times per second, it eats up 20% of my CPU power. There is also a light flickering.
I refresh the content of the scrolled window whenever the left mouse button goes up (new selection).

Code: Select all

Refres(true);
Actually i would have to monitor the mouse the entire time, once the left button went down, if i want to display "live" selecting.

Here`s my OnPaint() event handling:

Code: Select all

EVT_PAINT(MyScrolledWindow::OnPaint)

Code: Select all

	wxPaintDC dc(this);

	dc.SetPen(*wxBLACK_PEN);
	dc.SetBrush(*wxGREY_BRUSH);

	const int lineh = 16;
	const int charw = 16;

//i == row, j == colum
	for(int i=0; i<20; i++)
	{
		for(int j=0; j<16; j++)
		{
			dc.DrawLabel("FF", wxRect(j*charw, i*lineh, charw, lineh), wxALIGN_CENTER);
		}
	}
As you can see, i am drawing a 20x16 "grid" onto the scrolled window, each cell being the text string "FF".

Is it really a good idea to draw an entire custom control on a wxDC? But then, it`s the only way i see for editing large files.
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: scrolled data view

Post by doublemax »

Is it really a good idea to draw an entire custom control on a wxDC? But then, it`s the only way i see for editing large files.
Yes, that's the only way.

However, if you're displaying a large file "virtually", make sure to use the information from wxScrolledWindow::GetViewStart() and the client size of the window and draw the things that are actually visible on screen.

I wouldn't care too much about performance right now. First get the thing working, there is still room for speed optimization later. E.g. as you're probably using a fixed-width font for the hex-display you could prerender chars and cache them in a bitmap instead of using the font rendering. Or you could cache complete lines in a bitmap and only update them when the content changes.

For the flickering, check this:
http://wiki.wxwidgets.org/Drawing_on_a_ ... flickering
Use the source, Luke!
felix
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sat Nov 05, 2011 10:46 am

Re: scrolled data view

Post by felix »

hi again,

i implemented it now, and it displays a 700 mb file just fine. :)
That`s the good news. The problem is still the performance.

It lags and flickers on every redraw, not to mention on scrolling. It also eats up 60+% of my cpu power.
I wrote the same thing in native Win32, using GDI+ APIs only, and the speed is incredible. Virtually no lagging, flickering or cpu consumption.
What i noticed is that drawing an entire line at a time is MUCH better than drawing every cell separately. Under Win32 i was using the GDI DrawLabel() equivalent, so since it IS possible to have an excellence performance that way i would actually refrain from caching bitmaps, etc.

The gdi api i was mainly using was ExtTextOutW()

http://msdn.microsoft.com/en-us/library ... 85%29.aspx

what else could i try to improve the drawing process? :|

and ofcourse thanks for your help so far! [-o<


p.s. i tried using a wxBufferedPaintDC, but then the entire screen just turns black...any idea why?
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: scrolled data view

Post by doublemax »

what else could i try to improve the drawing process?
Try wxDC::DrawText() (or even the undocumented DrawAnyText() instead of DrawLabel(). The first one is a small wrapper around ::TextOut() and shouldn't be noticable slower. The latter one is slower as it supports multiple lines.
i tried using a wxBufferedPaintDC, but then the entire screen just turns black...any idea why?
Really the whole screen or just the window you were drawing on? In either case, there must be something wrong with the paint event handler. Could you show some code and how you connect the event handler (Event table macro or Connect/Bind call).
Use the source, Luke!
felix
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sat Nov 05, 2011 10:46 am

Re: scrolled data view

Post by felix »

1)
you re right, DrawText() is a lot faster. (DrawAnyText doenst appear to be a member of wxDC).
However, DrawLabel() (and ExtTextOutW() ) offer to center the text within a certain rectangle, a feature i find to be highly useful and of which i made use a lot in the Past (in GDI, i am new to wxWidgets). Not only necessarily here, but in other custom controls of mine.

If i click on the scroll bar and rush it all the way down, which takes me a couple of seconds, at best, the OnPaint() event is called 120 times. Is that really necessary? Seems like a lot right now....

As for the BufferedDc, the code is the same i showed in a post above:

Code: Select all

EVT_PAINT(MyScrolledWindow::OnPaint)
And yes, only the window in question, not the entire screen, sorry... #-o
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: scrolled data view

Post by doublemax »

Could you strip your code down to a small compilable sample and attach it here?
BTW: What OS are you testing on?

Are you still calling Refresh() when a scroll event happens? Usually when a window is scrolled, the OS copies the part of the window that just moves and the application only receives a paint event for the small strip that actually needs to be redrawn. By the Refresh() call you force another, complete redraw.

Another possible optimization is to redraw only the regions that need to be updated.
Check the sample code here on how to use the wxRegionIterator class:
http://docs.wxwidgets.org/stable/wx_wxp ... paintevent
Use the source, Luke!
felix
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sat Nov 05, 2011 10:46 am

Re: scrolled data view

Post by felix »

Could you strip your code down to a small compilable sample and attach it here?
this may turn into a quiet difficult task, but i ll upload something tomorrow :)
for small strip that actually needs to be redrawn.
i still call refresh(true), yes. I dont really see a handy way right now to re-draw only a small strip, though.
Same applies to the region-class thing, but i ll take a closer look tomorrow, thanks for pointing it out. :)

What`s a little frustrating to me is the fact that i can simply force a full re-draw using native GDI apis, with an outstanding result. Guess handy classes and platform independent code come at a price after all ;)

I am on a XP SP3.
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: scrolled data view

Post by doublemax »

What`s a little frustrating to me is the fact that i can simply force a full re-draw using native GDI apis, with an outstanding result. Guess handy classes and platform independent code come at a price after all
That's why i'd like to see some sample code that i can test myself. Of course wxWidgets does have an overhead, but in this particular case i don't see why it should be that much slower than native GDI.
Use the source, Luke!
felix
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sat Nov 05, 2011 10:46 am

Re: scrolled data view

Post by felix »

unfortunately, i wont reach my development PC today, so i will post that code tomrrow.
The only option i see right now would be to draw everything to a bitmap, then blt that bitmap to the window.
This would enable me to only redraw a lmited rectangle, as doublemax proposed.

From my GDI experiences, drawing directly to the screen was always faster, though.

:)
felix
Earned a small fee
Earned a small fee
Posts: 17
Joined: Sat Nov 05, 2011 10:46 am

Re: scrolled data view

Post by felix »

Ah! I solved it!

Here`s what you have to do:

-use a wxBufferedPaintDC
-create an empty EVT_ERASE_BACKGROUND event
-erase the background manually (DrawRect(0,0,width,height))

The result is absolute ZERO flickering, not even on scrolling.


Big thanks to doublemax and Auria for helping me out! :)
Once i wrapped this all up into a custom widget, i ll post it here in the code dump.
Post Reply