Delphi: How to use windowless controls?

I know that windowless control is not magic . A windowless control may have input focus (such as Internet Explorer). The input focus is nothing more than drawing:

and when the user starts to press keys, reacting accordingly. You know that keystrokes are for this focused control because this control has focus.

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

What can I do, but it's a pain.

But then the user will probably want to use the Tab navigation, and I will have to somehow intercept the usual Delphi processing the tab control order and cling to myself to say that this thing is the next (and previous) in the tab order.

What can I do, but it's a pain.

And there is ActiveControl that understands nothing but TWinControl . So if Delphi ever tries to figure out who it is focused on, it will go crazy. So I need to have an alternative implementation of ActiveControl.

What can I do, but it's a pain.

In other words: is it too much work? Am I struggling with everything Delphi has, and everything so that I have several dozen windowless controls accessible from the keyboard? Delphi designers never thought about using interactive controls without windows, and if I try to work with them now, will I just get stuck in a hearthlocker ?

Delphi gave me the opportunity to help me willingly, but I chose the path of pain.


Some further explanation of windowless controls is needed.

Not every control you interact with must be a Windows control. It is possible to focus and transfer keyboard input to a non-Windows control.

For example, almost every control that you see in an Internet Explorer browser window is a windowless item. In the next screenshot, you see the edit control that you can enter, and the button that (in this screenshot) has focus:

alt text

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

If I pressed Spacebar when the Google Search button was in focus, it would have pressed the button. This works because Microsoft has written a whole library of widget controls. These controls look (almost) exactly the same as regular general controls - they are almost exact clones of the general Windows controls right up to the themes used.

Mozilla Firefox and Google Chrome also use the widget control library. They do not use Microsoft's built-in window controls, but use a library of graphical interactive widgets without windows.

And if you have a suitable development environment, then windowless widgets work just like "normal" window controls. GTK + is a widget library, and Glade is an IDE that allows you to place controls in this widget library.

I don’t know in which development environment Firefox, Chrome or Blender were created, but their widgets support windowless controls.


So now to my question.

If I'm not mistaken, it seems to me that although Delphi supports the base TControl (which has width, height, and can draw itself), it cannot get keyboard focus. It seems to me that Borland never designed Delphi VCL as a universal library of widgets. The only evidence I have to confirm is that Form ActiveControl is a TWinControl:

 property ActiveControl: TWinControl; 

This does not mean that Delphi can or should be limited to windowed controls. The VCL widget library can be expanded to support focusing on windowless controls.

But maybe Delphi already supports windowless controls , and I just don't get it? Does Delphi already have a focus support mechanism on TControl ? But I'm a smart enough guy, and I'm sure Delphi VCL cannot do what other widget libraries can do.

What then leads to another question: how much work will be done on the forms of the subclass and such to support it? Is there someone else, perhaps someone in TeamB, who is much smarter than me, who have already tried this, and came to the conclusion that this is impossible ?

Now I immediately ask if an attempt to add control support without windows is damn impossible (that is, useless), so that I do not waste weeks on it. I am trying to use the knowledge of the Delphi developer community.

I ask a question.

+4
source share
7 answers

It is not practical to create controls without a window and to place them in a Delphi VCL environment.

An example is Internet Explorer. But in this case, he is fully responsible for everything that is on him. He has his own internal idea of ​​what active control is, but think about how it looks from the outside: this is just one gigantic control. When you ask the OS that it has focus, it has one browser control, regardless of which browser sub-controller has focus.

When you press Tab, it looks at the OS, as if the browser just used the tab character, like the edit controls. Editing controls move the cursor a few spaces and add tabs to their internal buffers; browsers move the cursor to another area of ​​the display.

You are thinking of doing all this on Delphi TForm. Delphi forms already have a structure for controlling active control and handling keystrokes, and you have to deal with it. If you need windowless controls, open the Internet Explorer route and create your own container control to hold them so you can not be responsible for everything that happens inside it.

A container can be a VCL control, but all you can do with it is probably not - they will still expect to use VCL rules to control focus and keyboard. Note how you cannot use regular Windows controls in Internet Explorer. All you need to go through certain ActiveX interfaces. You may need interfaces, or maybe you can just create your own set of management classes that come from some special ancestor class that you develop to work with your container. Do not start with TGraphicControl ; it is too rooted in VCL to be used as the basis for your branch management library.

There will be a lot of work, but again, Internet Explorer was just the same.

+4
source

Yes, it is useless.
And this is not Delphi's mistake; you are simply fighting Windows itself.
If you need a control that behaves like a window control, use a window control. And you're right, trying to recreate the entire stack of window controls APIs from scratch is a pain.

+4
source

Yes, you pretty much understood that. Using windowless controls means you lose everything that Windows can do to help you. Having more than a pair on one actual window is a pain.

+3
source

Most of these programs most likely were not originally developed using tools such as RAD, so they had no choice but to reinvent the wheel. One of Delphi's biggest benefits is its deep support for VCL and third-party components to provide the desired look.

One of the methods that I used with great success to reduce the number of window descriptors used in a complex (tax preparation) application based on a form was to draw text on the canvas and transfer a separate subclass of TCustomEdit to the user's editing position. It was trivial to grab the TAB / Up / Down keys and move the edit to the appropriate position. The task we discovered was to draw a hot rectangle around a field that depended on the mouse. We ended up with a TObject grid array, where the array element would be nil (no field), TLIst (the grid contains several fields) or a class containing our field descriptor. This reduced the number of range checks that we had to perform, since it was more likely that the field contained only one field or no more than 4 fields.

+1
source

fpGUI Toolkit is an example of what you want. The latest fpGUI code in the source code repository is based on a multi-window design. It just means that each widget / component has a window handle, but Windows or Linux does nothing with this window, other basic notifications (mouseenter, mouseexit, etc.). fpGUI still has full control over where each component goes, if they can be focused, how they look, etc. Some widgets / components in fpGUI are also unclosed components. for example: TfpgScrollbar, TfpgMainMenu, button in ComboBox, etc.

If you need a true version without windows, that is, there is only one top-level window in which there is a window handle, all other widgets / components inside this window do not actually exist for the OS (they do not have window handles), then fpGUI can also help. The original design of the fpGUI Toolkit was based on such a design. Again, look in the source code repository for the v0.4 code branch. I, that design, fpGUI had to handle absolutely everything, creating mouseenter / mouseleave events, translate coordinate systems for container components, process (fake) component states, etc. .... Yes, the initial design is a lot of work, but then You have a very portable structure that can be easily applied to other OSs.

And yes, fpGUI is fully implemented in Object Pascal using the Free Pascal compiler to give me cross-platform support. FpGUI currently runs on Windows, Linux (32 and 64-bit), Windows Mobile, and Embedded Linux (ARM) devices.

+1
source

I have no idea what your problem really is, but I think this little story may be relevant ...

We have an application that fills out a dozen forms. The user can fill out additional forms, as well as change the values ​​filled in by the application themselves.

Now in our first implementation, we used window components for each individual input field so that the fields can receive focus and input. This turned out to be a big problem because all of these windows took up a lot of resources.

Now we have windowless controls for each input field. This means that everything that we finish is a combined drawing of the form and its input fields. When the user clicks inside the drawing or uses a few keystrokes to move / set the focus, we create a new window control for the click field. When the user moves to the next input field, we destroy the first window and create a new one. Thus, we have only one window control, which again gave us a good speed improvement.

Again - I have no idea what you really want to manage. TWinControl is TWinControl for some reason, but there may be a solution to what you want, whatever it is ...

0
source

I think fgGUI can help you.

Check out the wiki first.

I think you can use this framework for your application in Delphi, since it is completely written in Pascal. In fact, it is based on FreePascal;)

NTN

0
source

Source: https://habr.com/ru/post/1302094/


All Articles