I myself have found that writing directly to the screen (preferebly during vblank) gives the absolute best results. I've written my GUIs from complete scratch, and have never even looked at source code from other windowing systems. Once you know all the fundimentals of how to code and how the computers work under it all, it's easy to do virtually anything.
I haven't written a GUI for VESA video modes yet, but the concepts hold true. Virtually all, even not so modern video cards have double buffering capabilities, and every thing has V/HBLANK stuff whether you know about it or not.
I never get flickering or anything, it's highly efficient. A couple points:
- when moving the window, simply XOR the rectangle of the window as it's new position, then on movement, XOR the original region, XOR the new region, and so forth. BLISTERING fast, no need to waste redrawing. Sure, Windows can redraw the whole window on each drag, but have you tried running it on a 386? How about using good 'ol Win31 on a trusty 286? Win31's windowing system was faster on a 286 than XP with it's visual enhancements turned on on a PIII
- never ever ever draw stuff that you don't need to, such as the parent window of a control being redrawn, etc. and only update windows that MUST be updated
- I have a WndCalcRect() function which calculates the window's regions, screen, client, etc. from the X,Y,width,height. The window stores a couple RECT structs and a width/height. This function is only called on window creation and window move. EXACTLY! everything is then done by reading the RECT structs and width/height (btw, unions for x,left/y,top
). The less calculation the better.
- if you need to draw a complex control, like a fancy button, allocate a temp buffer of (width*height), draw all the stuff to that, then blit it. Otherwise, for a simple button, you can just draw the rect/outline/text/icon, and it will be fine.
- on a VERY rare occasion, you'll be drawing pixel by pixel, in which case you'd need to check if it's coordinate is visible in the current port and should be drawn. Generally though, you should only check once per draw. Each line, rect, outline, bitmap, etc. that is drawn to the screen should simply have it's bounds checked and adjusted accordigly, then go from there. You can then blit lines of pixels and such, without any per-pixel checking. I even do this on font characters, because even if they are only 8x8 pixels or less, it will still save time (8x8 adds up! compare operations eat up your CPU!)
- do the keyboard (ie. tab-switching between controls, arrow keys for listboxes, menus and such, etc.) code first. Complete it all first, before implementing the mouse. Many people don't bother with standard keyboard support in their GUIS--that's bad. Do all the keyboard stuff, then add the mouse support. I added the mouse support with all the port clicking, window dragging, etc. in a matter of hours the first time. They keyboard stuff on the other hand take a little longer, so get it out of the way first