Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi: How to use windowless controls?

i know that windowless controls are not magic. A windowless control can have input focus (e.g. Internet Explorer). Input focus is nothing more than drawing either:

  • a blinking cursor
  • a dotted line around the perimeter
  • a slight blue tinge on a button

and when the user begins mashing keys, reacting appropriately. You know the keystrokes are meant for that focused control, because that's the control has focus.

In the case of my (Windows®) window, i would have to know that my windowless child control (let's pretend it's a descendant of TGraphicControl) gets the keyboard events. So during my form's OnKeyDown, OnChar, OnKeyUp, i would need to pretend they are going to my windowless child control.

Which i can do, but it is a pain.

But then the user will probably want to use Tab navigation, and i'll have to somehow intercept Delphi's normal tab control order handling, and hook in myself to say that this thing is the next (and previous) in the tab order.

Which i can do, but it is a pain.

And then there's ActiveControl, which doesn't understand anything except TWinControl's. So if Delphi ever tries to figure out who has focus, it will go insane. So i'd have to have an alternate implementation of ActiveControl.

Which i can do, but it is a pain.

In other words: is this just too much work? i'm fighting eveything that Delphi is, all so i can have a few dozen windowless controls accessible through keyboard input? The Delphi designers never contemplated using interactive windowless controls, and if i try now to work it in, i'll just stuck in the hurtlocker?

Delphi gave me the chance of aiding me willingly, but i have elected the way of pain.


Some further explanation of windowless controls is needed.

Not every control you interact with has to be a windows control. It is quite possible to have focus on, and send keyboard input to, a control that is not a Windows window.

For example, nearly every control you see in an Internet Explorer browser window is a windowless control. In the following screenshot you can see an edit control, which you can type in, and a button which (in this screenshot) has focus:

alt text

You can see the dotted focus rectangle, and the button is bluish (which on Windows indicates that it has focus).

If i were to press Spacebar while the Google Search button has focus, it would press the button. The reason this works is because Microsoft wrote an entire widget library of controls. These controls look and feel (almost) exactly like the regular common controls - they are very nearly exact clones of the Windows common controls, right down to the themes being applied.

Mozilla Firefox and Google Chrome also use a widget library of controls. They don't use Microsoft's built-in windowed controls, but instead use a library of graphical, interactive, windowless widgets.

And if you have a suitable development environment, then the windowless widgets work just like "normal" windowed controls. GTK+ is a widget library, and Glade is an IDE that lets you layout controls in that widget library.

i don't know in what development environment Firefox, Chrome, or Blender were created in, but their widgets support windowless controls.


So now onto my question.

Unless i'm mistaken, it appears to me that although Delphi supports a base TControl, (which has width, height, and can paint itself), it cannot receive keyboard focus. It seems to me that Borland never designed Delphi's VCL as a generic widget library. The only evidence i have to support this is that a Form's ActiveControl is a TWinControl:

property ActiveControl: TWinControl;

That doesn't mean that Delphi could be, or must be, limited to windowed controls. The VCL widget library could be extended to support giving focus to windowless controls.

But perhaps Delphi already supports windowless controls, and i just don't realize it? Is there already an established mechanism in Delphi to support giving focus to TControl's? But i'm a reasonably smart guy, and i'm pretty sure Delphi's VCL cannot do what other widget libraries can do.

Which then leads to another question: how much work would be be to subclass forms and such to support it? Is there someone else out there, perhaps someone on TeamB, who's much smarter than i, who has already tried it, and come to the conclusion that it's impossible?

i'm asking now, up front, if trying to add windowless control support is damn near impossible (i.e. futile) - so that i don't spend weeks on it for nothing. i'm trying to draw on the knowledge of a community of Delphi developers.

i'm asking a question.

like image 1000
Ian Boyd Avatar asked Dec 12 '22 23:12

Ian Boyd


2 Answers

It's futile to build windowless controls and fit them into Delphi's VCL framework.

You bring up Internet Explorer as an example. But in that case, it's entirely in charge of everything that resides on it. It has its own internal notion of what the active control is, but think about what it looks like from the outside: It's just one giant control. When you ask the OS what has focus, the single browser control has it, no matter which of the browser's subcontrols appears to have focus.

When you press Tab, it looks to the OS as though the browser has simply consumed a tab character, just like edit controls do. Edit controls move the cursor over a few spaces and add tab characters to their internal buffers; browser controls move the cursor to another region of the display.

You're thinking of doing all this on a Delphi TForm. Delphi forms already have a framework for managing the active control and handling keystrokes, and you're going to have to fight it all. If you want windowless controls, go the Internet Explorer route and build your own container control to hold them so that you can remain in charge of everything that happens inside it.

Your container can be a VCL control, but the things you put on it probably can't — they'll still be expecting to use the VCL focus- and keyboard-handling rules. Notice how you can't put ordinary Windows controls in Internet Explorer, either. Anything you put there needs to go through specific ActiveX interfaces. Maybe you'll need interfaces, too, or maybe you can just make your own set of control classes that descend from some special ancestor class you design to work with your container. Don't start with TGraphicControl; it's too entrenched in the VCL to be usable as the basis for your offshoot control library.

It will be a lot of work, but then again, so was Internet Explorer.

like image 171
Rob Kennedy Avatar answered Dec 29 '22 05:12

Rob Kennedy


Yes, it is futile.
And it's not Delphi's fault, you're just fighting Windows itself.
If you need a control that behaves like a windowed control, use a windowed one.
And you're right, trying to recreate the whole API stack of windowed controls from scratch is a pain.

like image 31
Francesca Avatar answered Dec 29 '22 04:12

Francesca