PDA

View Full Version : Graphical Components



Gadget
16-01-2003, 07:58 PM
Please forgive my stupidity with this...

I am a fairly experience Delphi developer. I have mastered most of what Delphi has to offer, but the one thing that I have never done in any detail is to create 'brand new' graphical components. I have usually descended from TImage, which is a bit mickey mouse I know...

I have used DirectX in delphi before, and understand most of the basics. I have just started a new project and have hit some minor problems that I am worrying on how to solve... I was using hoping to use a TRichEdit with this game as it does everything I want and is easy to use. GDI components are causing me too many problems, the latest of which is the scrollbar in the TRichEdit halting the main game loop when you 'hold' it.

To this end I need to create a DirectX object model, and I need some advice on how to do this. What should I decend from? Has anyone got any examples of dx components that I can look at? My main concerns are capturing mouse messages, eg. drag, click, over etc.

Thanks

TheLion
16-01-2003, 09:46 PM
If I'm not mistaken there are is a good tutorials over at Alistair Keys (AliMonster) website : http://www.alistairkeys.co.uk/

and here is a direct link to the component tutorial I was refering to:
http://www.alistairkeys.co.uk/compone1.shtml

I hope this helps a little ! :)

Alimonster
16-01-2003, 11:53 PM
Thanks for pimping my tutorial, TheLion :).

First of all, maybe a little detail about how your game loop is structured might be useful. If you find that RichEdit does all that you want, it'd be a bit of a shame to let little annoyances get in the way!

Now for something completely different:

Disclaimer: I'm tired. The following is probably nonsense

In this case, mind you, I'd reinvent the wheel from scratch ;). Here's how I would do a RichEdit-style control if I ever had the motivation . Some very quick suggestions, based on the rationale... it's fun reinventing the wheel! I'm hoping to build up a complete DX GUI library (btw, search for DXGUI (?), which I think is a Delphi GUI library) some day. As such, the following may seem rather "back to basics" to you.

First of all, the big question: why do you need the RichEdit? If it's simply to display text then that's simple enough, but if you need typing and other editor functionality then it's a bit more bothersome.

I'd store a background for your new textbox in a surface somewhere (a lovely bitmap, probably).

The font itself would be much simpler if it was fixed-width, which would make calculating the positions of each very simple. You would want to store the letters on a surface, side by side, in typical texture-mapped-font stylee. When you want to draw a string, you'd pluck each letter and blit its rectangle to form words. Of course, if you feel like making it proportional, rather than fixed-width, for letters then be my guest ;). You can either generate the letters by using the GDI textout function for the surface DC or you can do it predrawn in a paint package. Draw 'em with Blt.

Scrolling is relatively simple, but here's a snippet for you from my site: here (http://www.alistairkeys.co.uk/scrolly.shtml). The example code uses the VCL but it's not difficult to transfer to other APIs.

I'd store every line in a TStringList - it's what it was made for, after all! You could add per-line objects with AddObject if you wanted neato features per line (maybe timestamps, for example).

Here's the variables I'd want so far:

The background image (surface)
The lines of text (TStringList)
A texture-mapped font (surface)
The current position in pixels (integer)
Width (integer)
Height (integer)
Left (integer)
Top (integer)

Here's a rough guide for displaying it:

draw the background image

Next, we have to calculate where the text appears. The calculations there are just what I did in the tutorial - the top index to display is (pixel position div text_vertical_spacing). This will give you the index to display next. You'd then want the offset - your first line might be a few pixels up the way, off the screen. This can be found from (pixel position mod text_vertical_spacing).

first_line := pixel position div text_vertical_spacing
offset := pixel position mod text_vertical_spacing

Set a variable for the current y position to (-offset) for first line, found with the mod above

You'd then loop for (top most index to top most index + vertical lines wanted), each time drawing a row:

current y := -offset

for index := first_line to first_line + lines_to_display do
begin
if current line index >= lines.count then break; // end of message
draw lines starting at (left_margin, current y)
current y := current y + text_vertical_spacing
end;

That assumes you're using a clipper (and blt instead of bltfast) -- or your API's equivalent draw+clip function.

Easy enuff - that's you got the display mostly done. Whenever you want to change what's shown, you change the pixel position. This gives you an easy way to do scrolling! You'd simply draw some buttons (another surface, maybe) for scrolling up and down. They'd adjust the pixel position accordingly (inc'ing or dec'ing by a given scroll speed). You might also want a trackbar for the current position. This is easy to do with basic arithmetic - just calculate its position as a percentage of the total available height. If you've scrolled 75 percent of the way down the page, draw the trackbar 75 percent between the top and bottom scroll buttons!

Drawing a row of text can be simple or complex, depending on your needs. If you want custom colours or font styles (like bold, italic) then you have to embed the code somehow (e.g. adding special characters, maybe even HTML, around the given words). You'll probably be writing your own text rendering routine anyway, which can take care of most of the details. If so, it's not really the textbox's job to do the fancy styles, but the text rendering routine. I'll leave that to you.

Right, so at this point we would have a background image for the box, plus lines of text that can be scrolled vertically using the scroll buttons/scrollbar. We might also want keyboard shortcuts, like pageup or pagedown.

Another possible addition here would be horizontal scrolling. It's possible to add horizontal scrolling in much the same manner as we did vertical scrolling. Simply keep an integer position for how far along to the right we've scrolled, in pixels, then do the div and mod calculations for the correct position. We then simply draw the text starting at (left offset, current y), where left offset is (-horizontal scrolling div text_horizontal_spacing). Again, it assumes clipping.

We also need a text cursor. This can be represented by a coordinate pair (x and y values) for its current position, plus a selection start point and how many characters have been selected (if any). I've not given much thought about this, mind you, but you'd have to change the main text rendering logic somehow.

The only other major parts would be typing in the text and dealing with the mouse. The keyboard + mouse bits depend on how you want the textbox to react. I can't think about htat just now due to wanting-to-sleep-right-away.

You might also want a focus boolean so that the textbox only steals keyboard input (for stuff like selecting text, page up/page down) when the user is typing away. You'd check for clicks in the region [left, top, left+width, top+height] as per usual. If the user clicked in it, you'd activate its big and clever features.

It sounds like a fun project. I might try writing it over the weekend (or not). [i]Did I mention that I'm bored?

I regained my motivation briefly while pimping this site to our newest member, Jonny, on a newsgroup. Don't think it will last for long so I'll have to make the most of it ;).

Clootie
17-01-2003, 06:19 AM
Reinventing weel is a funny!
Have you tried to emulate IME input? :shock: :lol: :lol:
Basically leave to GDI and Windows input what it can do the best!

Gadget
17-01-2003, 09:16 PM
I don't 'need' to use a TRichEdit, it's just that it was working... lol

Basically, all I need is a scrolling text window that I can get text back from when I click on the relevant line.

What's the best way of showing sub forms in dx? I am starting to hate these dx and GDI issues...

Thanks for those tutorials and the advice btw ;)