Creating custom Hint window - delphi

I'm trying to find a way to use my 2nd form as a hint window for a component (for example a TLabel) in my 1st form.
At the moment, I'm exploring the use of THintWindow and HintWindowClass, but it is not possible to directly assign a TForm to HintWindowClass. Some examples I've seen so far use a TBitmap which is then drawn on the THintWindow.Canvas, which is not bad, but I'd still like to use some kind of integrated automatic mechanism.
Another solution that crossed my mind is to manually implement this functionality using OnMouseEnter, OnMouseMove and OnMouseLeave events of the said Tlabel.
If there actually is a way to "assign" a TForm to HintWindowClass, I'd like to ask if anyone can provide a code snippet illustrating this. Thanks.

THintWindow is a descendant of TCustomControl. TForm is not a descendant of either of those classes, so you cannot assign any TForm class to HintWindowClass. Hint windows need to descend from THintWindow. Anything you can put on a form you can also put on a THintWindow. You'll just have to instantiate it manually and assign its Parent property to make it appear.
The closest you can probably get to "visually" designing a hint window is to design a frame. Make your THintWindow descendant create an instance of the frame, and then override ActivateHint (and ActivateHintData, if you need the data) to forward the hint text and desired size to your frame.

Related

Delphi tcustomcontrol/twincontrol

Can someone please explain me which control is better to create custom componens? What is the difference between twincontrol and tcustomcontrol?
Thank you in advance
Can someone please explain me which control is better to create custom componens?
That depends on what kind of component you are making and what its requires are.
Is it visual?
If no, use TComponent.
if yes, does it need its own HWND (input focus, window messages, etc)?
If no, use TGraphicControl.
If yes, does it need to custom paint itself?
if yes, use TCustomControl.
if no, use TWinControl.
What is the difference between twincontrol and tcustomcontrol?
TCustomControl is a TWinControl descendant that adds some additional handling for the WM_PAINT message, on top of what TWinControl does. TCustomControl exposes a public Canvas property that you can draw on. During painting, it enables the csCustomPaint flag in the ControlState property, and then calls a virtual Paint() method that your component can override. So the benefit of TCustomControl is that it makes custom painting a little easier to manage. Nothing more.

What is the ideal way to modify sub control styles in a custom firemonkey control?

I am attempting to develop my first proper custom control for the Firemonkey framework and have ran into what may possibly be an obvious (or not) solution.
Inside my Firemonkey control I have declared FPanel: TPanel; which is then created in the constructor and freed in the destructor. The panel is created along with my control when I add it to a new Multi-Device Form without any problems.
By default the TPanel has borders around the sides of the control which I do not need in my control.
So my question is, what is the ideal way to remove the borders of a TPanel which is child to my custom control? I could not see an obvious property to change, unless I am mistaking I believe we must modify the style of the panel which I assume would be done via a TStyleBook.
Am I right then in thinking that I need to add a TStyleBook to my control, and from there add the panel to the Style book and modify it this way? Unless I am missing something this seems like a lot of extra work for what should be a very quick and simple change.
Assuming this is the correct way, is there an example of modifying a TStyleBook through code?
Thanks.
Because all Firemonkey controls can be parents, one way is to not use TPanel at all and instead replace it with another Firemonkey control such as the TRectangle shape.
The TRectangle shape can then be customised directly through its properties to remove the border which can be achieved by setting the Corners and Sides to False.
Additionally if you don't require any borders whatsoever then the TLayout control behaves just like a TPanel but without the borders.

How to close an FMX TFrame shown in a TPopup from event handlers inside the TFrame

I use a frame that is shown by calling TPopup.Popup(true); method. If the frame contains a button with the ModalResult property set (to, for example, mrOK) it closes automatically when clicked by the user. But I need to close the frame in an OnClick event of a TListBox in it.
Frame does not have Close method.
I would like to avoid using message posting to the parent form as it might cause future problems when the application is ported to Android as well as I would prefer not to declare the OnClick event handler for the Frame.ListBox in the parent Form because the frame might be shown by several different forms and it will worsen the quality of parent Form code making it heavy and difficult to read.
I would highly appreciate suggestions how to do this.
I found the following way out. I call
(GetParentComponent as TPopup).IsOpen:=false;
When you inherit from TPopUp like explained here (How to make my own dialog component from Firemonkey TPopUp?) then you can call ClosePopup when an event is trigerred in your frame.

Add shortcut to a TForm or Panel.Transparent?

To thwart the nit-pickers, let me start with, I searched here with this and could not find an answer, and yes, also I did scroll through the "Similar questions."...
Adding shortcuts to a TForm
I want to drag and drop some shortcuts from the Desktop to a TForm in my application. I am using Anders Melander's brilliant Drag Drop Suite (DDS).
I tried putting a TImage on the form but the DDS does not drop to an Image so I added a TPanel with a TImage on it. I could then drop on the panel and assign the image to the TImage.Picture. Problem was the Panel has no Transparent Property so the shortcut on the form looks clunky with the visible Panel behind it.
I need to be able to drop to the TImage or make the underlying TPanel transparent.
Can anyone help with code-snippets for either of those options, or better yet, a method of dropping a Shortcut directly on to my Form.
Thanks
Coincidentally I needed to make a TWinControl (the base for every visible control with a window handle, including TPanel) transparent. I found numerous results and applied them to this answer.
It's been a while since I implemented drag and drop, but I assume you call some API and pass it the handle of the panel? That answers the question why you can't use TImage. TImage is a graphic control, a control without a handle, that relies on its parent for recieving messages and drawing itself.
It should be possible to use the form, though, since that has a handle too.
If the TImage is directly on the TForm, then let the TForm handle the drop, no TPanel needed. OLE Drag&Drop operations (which Ander's components implement) provide coordinates where dragging and dropping occurs. The TForm should be able to detect when a drag is over the area occupied by the TImage and what type of data is being dragged, and only allow dropping of supported types within that area, extracting the dropped data and updating the TImageas needed, and denying anything else that does not match that criteria.

Delphi, frames vs forms. What for multi-document interface?

yesterday I've started discussion on "MDI vs tabbed interface". I've asked whether should I continue developing my app as MDI-based, or should I embed the child forms into tab sheets.
Someone pointed that I should use TFrames instead... My question is: why?
What are pros of using TFrames when embedding the form over TFrame? So far I don't know any, switching would only require me to rewrite some parts of code...
(I'm not going to use embedding at design time anyway!)
Thanks in advance
Answering the comment to provide a reason why to use frames:
I would consider frames to be building blocks of the GUI, with design time combination of existing components to more advanced components. Before Delphi 5 one would have used a TCustomPanel descendant with child controls and registered this as the new component, ready to be dropped onto a form. Frames allow for the same thing with less hassle.
They allow you to concentrate on developing exactly the functionality you need, and nothing more. Done right you can then embed them into tab control sheets, into modal or modeless dialogs, into MDI child frames and into standard frames. You can even add several of them into one form - something one would probably not do with embedded forms. The point is that for maximum reusability a layered approach is often necessary, and frames help with that.
A frame is fit for embedding from the go. A form has to be adapted to not show a caption bar and border, normally one would override the CreateParams() and adjust the window style accordingly. There are a lot more form properties in the inspector that just don't make sense for an embedded form. IMHO one should use the most basic and generic entity that suffices. A form just is much more than a control container for embedding.
OTOH I don't know of any disadvantage of embedding a frame that embedding a form wouldn't have.
Edit:
There's a comment regarding events like OnCreate or OnShow that frames don't have. Actually, I'd consider that another advantage of frames, as event handlers don't have parameters, so a lot of stuff gets hard-coded in forms, necessarily.
Consider the case of per-user settings: in OnCreate there's not much information available, so one invariably ends up using a constant or the name of the form for the INI file section, making it very hard or even impossible to reuse the form or to create several instances of it. With frames on the other hand a method LoadSettings is the obvious way to do it, and it can carry the necessary parameters. That way control is returned to where it belongs, to the container of the embedded frame / form. Reusability is only possible if the behaviour can be adjusted from the outside.
For contained objects that are not components and need to be lifetime-managed, there are for example AfterConstruction and BeforeDestruction.
Maybe you will find some answers in this thread: gui-design-multiple-forms-vs-simulated-mdi-tabs-vs-pagecontrol
Frame use the fastest load and without delay when creating the frame.
But the frame should be has a parent to embedded it. Disadvantage with no onCreate or onShow event has been triggered. but you can call with message for trigger onShow event like this one :
put on private section of frame:
procedure CMShowingChanged(var M: TMessage); message CM_SHOWINGCHANGED;
and then create the code like this :
procedure TFrame1.CMShowingChanged(var M: TMessage);
begin
inherited;
if Showing then
begin
// .... put your code for onShowing is triggered
end
else
begin
// .... put your code for onHiding is triggered
end;
end;
Hope can helping you to consider embedded frame for GUI.
You may consider combined with PageControl to control your frame opening.
Manz
I had same decision few years ago for one of our applications, we wanted to make it looks embedded forms, first I used the Frames and I wrote a class to manage it.
Later I found TLMDDisplayForm component from LMDTools, which making embedding forms inside it very easy task, it reduced the code used and we have more features.
one of main goals that we changed from frames to Forms was missing some events of TForm like: OnCreate, OnShow, OnActive which we use for some tasks in our applications, beside missing some properties such as: ActiveControl and other things I don't remember.
If you would like to go with Forms, I suggest you to use LMDTools which make the task easier for you, beside the basic version is free :-)
For dynamically inserted forms/frames I personally prefer to use embedded forms over frames. Several versions back when one would edit a frame which was set to alClient, the frame would resize between edits and any controls which were aligned specific to the right of the frame would change position. When using embedded forms this didn't happen so I made the switch. I believe this issue is now fixed with later versions of Delphi.
I strongly agree with the points Mghie made earlier regarding the inability to pass information to the embedded form through notification events. To solve this I generally implement a series of interfaces in each embedded form for communication. This really simplifies the code, and allows for more generic implementations where you have a single "container" that will be dealing with many different types of embedded forms/frames. A few examples of this are available on my blog as part of the wizard framework I designed.
I think both should be used. For example, I have a "standard" frame that has a dbnavigator, dbgrid and datasource components which is very handy for the typical data browsing. Instead of inserting such components every time, I insert a frame that also has the ability to export its data (with JVCL :D) to several formats...but I know what I want to display at design time, so I suggest a very easy rule: if it is known at design time, use frames, otherwise use embedded forms.
However, keep in mind that forms were not designed to be embedded. Using them like so, its unnatural (as a vampire states when she buries her 80 old year daughter and she looked like 30 :D). The embedded form knows little about the one that owns it and can also (logically) assume that is not embedded.
Complementing that, a frame is a component, and so, when embedded (owned by) in a form, the form knows about it and the frame knows about the form (can use its methods and properties. An embedded one can also do that but requires extra coding)
Perhaps Embarcadero could give us a hand by creating a TEmbeddableForm or an interface for such purposes
Regards,
Alvaro Castiello
Frames are good when you want to repeat a "sub-form" multiple times in a form. I'd not use them for tabbed interfacing, as the embedded form is a better solution for MDI/Tabbed interface use.

Resources