Search code examples
delphifocuscustom-controlsdelphi-7

Can Windows manage multiple focus points on a single control?


I'm building a custom control which is to have multiple focus points. For example, within 1 control, let's say there's 3 regions (could be defined as a rect on the canvas) which are to be able to have focus. Depending on which one has focus, I don't want the default Windows dotted line around it, but some special handling. I know nothing about how to even give 1 custom control its own focus.

The original project was a single TPanel with a few VCL controls on it, each of course being its own window, thus having its own focus. But now I'm putting it into a custom class of its own, which these 3 controls will no longer exist (they were only there in version 1 as a prototype) and I need to now somehow mimic the focus in these different regions.

I guess similar to something as simple as a TListBox, where certain items within that control get the focus instead of the entire control its self.

Here's a picture to help demonstrate what I'm making...

enter image description here

The one on the top is the original with the buttons. But the one on the bottom is the new one I'm building which is all custom drawn.

To elaborate, I'd like to see if Windows already has special handling for this type of scenario before I go and re-invent the wheel.

I'm not looking for the "Easiest" way to accomplish this. And I also do not want recommendations to revert back to how I had it before, because there's many reasons I don't want 1 control with multiple other controls within. I just need a yes or no, with an explanation.

More

I just realized the main concern is the use of the tab key. The control has to first get the focus, start the focus on whichever sub-item it's supposed to, then respond to tab on my command until it reaches the end, then pass the tabbing over to the next control. Then it also needs shift+tab as well. How on earth would I implement this tabbing? That's where I got stuck, but it just struck me that this is the main reason I'm asking.


Solution

  • No you can't get windows to recognize multiple points of keyboard focus inside the same window handle, since each control with a window handle either has, or does not have, keyboard focus. The "inner focus" between multiple controls is up to you to sort out.

    As you already knew, the most simple way to accomplish this is to have multiple sub-controls with their own window-handles, which is what you said you are doing:

    TMyThreeEditControls = class(TControl) //  parent has no window handle!!!!
        protected
            FEdit1:TEdit;
            FEdit2:TEdit;
            FEdit3:TEdit;
        ...
    end
    

    In the situation above, the parent control is a TControl, it creates several sub controls, in my example above, all three have their own window handles, and thus Windows can display keyboard focus when you hit tab, and handle mouse focus as part of Windows's common controls library's functionality.

    In short, the "composite" approach where you include sub-objects (other controls) in your main control, which you are trying to move away from is in fact, the only way to let Windows do most of the work.

    On the other hand, what you might be looking for is not a way to have a control paint itself, but some code to make something look like it is focused, in your own custom painting routines, if that is what you are looking for, you should look into the VCL source code or this link on about.com for examples on how to tell Windows to draw a focus rectangle, etc. The about.com link is an imitation and does not use real windows code to draw focus in a Windows-theme aware way.

    Update: it is possible that what you are also looking for is the way to determine if mouse co-ordinates are within a specified rectangle (the rectangle represents a button in your case) and if so, to draw a "hot state" for the button. There are more sub-tasks than this to accomplish if you wish to build a control yourself, I recommend you study existing controls such as TStringGrid and TCategoryButtons in the VCL source code, to see the MouseMove, MouseDown, and MouseUp handling code you will need to do the things you are trying to do. In particular, StringGrid source code is the way to see how the "tab key" can be used within a single control with a single window handle, because in that control the tab key can be used (if the right options are turned on) to navigate among all the cells inside the string grid, as if each one was a separate control, even though it is all one control.