I created a simple design-time component that helps to select and bring to front other components on the same form. (It is more convenient than IDE object tree view when designing full screen forms in a single monitor environment). But in Delphi XE2, I cannot reliably ensure and detect that the helper component itself is on the top. When I select it, the IDE draws 8 blue balls as a marker around it, and it seems to me that those markers are part of the actual top level window.
So, how could I check if a component is selected in the IDE designer?
So, how could I check if a component is selected in the IDE designer?
Create a design-time editor for your component (make sure you implement it in a designtime-only package, not a runtime package), and register it with RegisterComponentEditor(). TComponentEditor has a Designer property to access the Form Designer's IDesigner interface, which has a GetSelections() method:
procedure GetSelections(const List: IDesignerSelections);
IDesignerSelections has Count and Items[] properties, where Items[] returns a TPersistent object. So you can loop through the list looking for your desired component object(s) (all components derive from TPersistent).
IDesigner also has SelectComponent() and SetSelections() methods, so you can have the Form Designer select other components as needed:
procedure SelectComponent(Instance: TPersistent); overload;
procedure SelectComponent(const ADesignObject: IDesignObject); overload;
procedure SetSelections(const List: IDesignerSelections);
Related
I have added a published event to my main form, expeecting it would show up in the editor, but it doesn't.
Am I doing something wrong, or is this just not the case?
THIFISongEndEvent = procedure(Sender: TObject; EstimatedEndTime: TDateTime) of object;
TMain = class(TForm)
[...]
published
property OnSongEnd: THIFISongEndEvent read FOnSongEnd write SetOnSongEnd;
EDIT: Added Code
Published properties of TComponent descendants are visible in the Object Inspector only when these components are registered in a design-time package. Otherwise, you would not even be able to drop the component onto the Form.
As Forms are usually designed in the Form Designer, they are probably not registered for design-time, and thus their published properties added on top of the base TForm properties cannot be known by the Object Inspector.
Is it possible to drag and drop nodes from TVirtualStringTree into a VCL control when the DragType is set to dtOLE (not dtVCL)
I have a situation where I need to be able to drag nodes from one VT to another VT (dtOLE works fine), but at the same time, while dragging, I need an option to be able to drop the nodes into a TListBox (or other VCL control).
I tried setting DragAcceptFiles() API for the TListBox handle, but it had no effect.
How can it be done?
There is no DragAcceptFiles property on TListBox. If you mean that you are calling the Win32 API DragAcceptFiles() function on the TListBox.Handle window, that would only work if:
you manually subclass the TListBox.WindowProc property to handle the WM_DROPFILES window message.
TVirtualStringTree provides the CF_HDROP format during OLE dragging.
2 is not true, though. CF_HDROP is meant only for dragging filesystem paths, which is not what TVirtualStringTree drags. So using DragAcceptFiles() is out.
TVirtualStringTree (and other TBaseVirtualTree descendants) uses custom data formats during OLE dragging (the interface section of the VirtualTrees.pas unit declares these format IDs, so you do not need to register them manually in your own code):
CF_VIRTUALTREE contains an IStream or HGLOBAL holding a serialized form of the selected tree nodes that are being dragged. The serialization is comprised of a series of data chunks describing each node. You will have to refer to the implementation of the VirtualTree.pas unit to decipher this format (I'm not going to do it here).
CF_VTREFERENCE contains an HGLOBAL holding a TVTReference record (which is also declared in the interface section of the VirtualTrees.pas unit) containing a pointer to the actual TBaseVirtualTree object that is being dragged from and the ID of the process that the tree belongs to.
So, in order for you to be able to drop tree nodes onto the TListBox, you will have to do the following:
write a class that implements the IDropTarget interface (or use a pre-existing implementation, such as from Anders Melander's Drag&Drop suite).
register that class with the TListBox.Handle window using RegisterDragDrop().
in your IDropTarget implementation, you can query the provided IDataObject for the CF_VIRTUALTREE and CF_VTREFERENCE formats. If successful, your Drop() method will have access to the tree node data that is being dragged and can copy it into the TListBox as needed.
Assuming your TListBox exists in the same process as the TVirtualStringTree being dragged from, I would suggest focusing on just CF_VTREFERENCE, since it is a very small and simple format (see the implementation of the TBaseVirtualTree.GetTreeFromDataObject() method), and parsing the CF_VIRTUALTREE data would be overkill (see the implementation of the TBaseVirtualTree.ProcessOLEData() method) when you can just enumerate through the source TVirtualStringTree directly instead.
In want to use LiveBindings in Delphi XE5. I am new to this.
I have a VCL TForm with a TEdit.
I have a component in a seperate unit:
TMyComponent=class(TComponent)
private
FMyProperty: Integer;
public
property MyProperty: Integer read FMyProperty write FMyProperty;
end;
Now I want to bind MyProperty to the TEdit.
I tried this with right clicking on the TEdit and select "Bind visually" as well as with the LiveBindings wizard. The problem is that the MyComponent is not listed in the components list there.
The unit which contains MyComponent is in the uses clause of the form.
What am I doing wrong?
Thanks!
The IDE only knows about component classes that have been registered with it. To make this work at design-time, you need to build a package that registers the component class. Otherwise, you'll need to create the bindings programmatically. I'm not particularly familiar with the LiveBindings system, but there are several questions in the livebindings tag that show how it's done.
So basically here is what I did:
I made a new FMHD Application and dropped a TTabControl and a Button on it. Then I designed an interface IFoo. To keep it simple, let's just pretend it only has one procedure:
type
IFoo = interface
['{D035-N07-M4773R-...}']
procedure makeTab(tc : TTabControl);
End;
I implemented this interface in a DLL. The DLL is loaded via LoadLibrary and exports a
function getFoo : IFoo;
MakeTab basically creates a TTabItem and sets tc as it's parent:
procedure TFoo.makeTab(tc : TTabControl);
var
tab
: TTabItem;
begin
tab := TTabItem.Create(tc);
tab.text := 'Hi, I am Tab';
tab.Parent := tc;
// ...
end;
If I forgot something, I am very sorry. I do not have the exact source in front of me at the moment.
This method is invoked when the Button on the form is pressed.
But nothing happens.
So I put this method into my TForm1 class. If I call it now, a tab is created.
So how can I create this tab (and several child components) from within the DLL on the application's main form?
The fundamental issue here is that you cannot share Delphi class types between modules using DLLs. The reason is that there will be multiple versions of what needs to be a single type. One version in the executable, and one version in each DLL that uses it.
This is the same well known issue that exists with the VCL and is the reason why runtime packages were developed. And that's your solution for FMX also. If you need to share Delphi class types between modules you need there to be one single definition of a type. And runtime packages are the mechanism that makes that possible.
So, stop using DLLs, move the code into a runtime package, make sure that the RTL and FMX are linked using runtime packages, and that problem will be solved.
Every once in a while when I am tweaking my TFrame classes (adding properties, methods, etc), the IDE gets confused and acts as if it thinks the frame is a form, complete with header/caption, borders, etc. Yet, clearly the class is declared as a TFrame descendent. Any ideas as to what causes this, how to prevent, and how to fix?
I'm using Delphi 2007 Pro. Also note (if it matters), the TFrame descendents are typically registered with the IDE (i.e. on the palette) via a design-time package.
Later: Additional "specifics": The frame that I'm having this problem with at the moment is, visually, a VERY basic TFrame (only change from brand new TFrame is size, and background color).
Here's its class declaration:
TBasePanel = class(TFrame)
private
FPanelManager: TPanelManager;
procedure SetPanelManager(const Value: TPanelManager);
protected
procedure Connect; virtual; abstract;
procedure Disconnect; virtual; abstract;
procedure Refresh; virtual;
procedure Requery; virtual; abstract;
published
property PanelManager: TPanelManager read FPanelManager write
SetPanelManager;
This frame is used as a base class for a number of others. I am usually editing it directly from the BPL project it belongs to (because all of these frames install to the palette), rather than as part of an EXE project, with related Forms open etc.
Also, "Embedded designer" is checked in Tools -> Options.
I am saving all DFM files as text rather than binary as well (if that matters at all).
I have encountered the same problem. The following steps solved the problem for us, it might also work for you:
in the IDE: close all forms that use the frame
open the frame, view as text (*.dfm)
the dfm probably begins with object MyFrame: TMyFrameClass
change this to inherited MyFrame: TMyFrameClass
I don't know what caused the problem.
Perhaps you had unchecked the 'Embedded designer' check box? (Tools | Options | Environment Options | VCL Designer). Then, indeed, your frame is shown at design time as a form (with caption, border etc.). Also a concrete code of your problematic TFrame descendant or more details about your case would help.
As far as I know, you have to have both the form and the frame open in the editor when you edit the frame. Else there can be update problems. Although I haven't seen this one.
But I gave up on frames a long time ago because I did not find them very reliable.
Right now I only use them for prototyping, creating a custom component (derived of a panel with the apropriate controls on it).
You may have to register custom module to the IDE
But your additional properties won't work well unless they are in ancestor class.
I have encounter a lot of problems with TFrame and finally came to such workaround that solves all my problems: I create and design frames visually, but use them only by hand-coding.
As a side effect my applications became smaller, because of less dfm-s.