How to keep editor alive in Virtualtreeview? - delphi

I'm trying to build a simple 2 columns grid "property editor" based on VirtualTreeView.
(I want to mimic look and user experience seen on Delphi's IDE object inspector)
The component is working almost and can handle multiple editors,
but I'm facing an annoying bug :
When I click on a new node (a new row), the node is selected and the editor appears, regardless of the column I've clicked on. It's expected and OK.
Then, when I click on the first column of the same row, I expect to see my editor content validated and the editor keeping focus (like in delphi's object inspector).
But the editor content is validated then it disappear and the entire node (row) is selected. The editor won't get back (even if I click on second column), until I select another node and click back on the previously selected node.
EDIT : added illustration and precision about my code.
about the code :
I do not have inserted code here because I used (as a starting point) the exact same code as the one found on Advanced Demo (properties page)
What I tried and found out :
the 2003's compiled Advanced demo (properties tree page) found here seems to works like what I expect from my component (and from virtual treeview).
But when I compile this same demo (I tried with versions 4.5.2, 4.8.7 and even 5.0.0 from current trunk on google code, on both delphi 2007 and 2009) the bug reappears !
I first think there was a documented breaking change between 2003 and more recent versions,
but I can't find anything.
I've also played with all available options trying to solve this, but without success.
I still don't know if this problem comes from new delphi RTL or a breaking change (bug?) in virtualtreeview.
so my questions :
do you have the same problem when compiling Advanced demo ?
any tip or workaround in code to solve my problem ?
As a side note, I nearly give up with virtualtreeview this afternoon and I wanted to try a solution with another component... I found this interesting question and decided to try berg's component, but was stopped in the buying process when reading an advice on their homepage (see my comment on the related question)

The VSTs onChange just gets called by changing the selection of nodes. The state will not change anymore, if the node is already selected. So, you have to implement a behaviour similar to Object Inspector on your own, e.g. by calling VSTs EditNode()-Method in the OnClick-Callback:
procedure TMainForm.VSTClick(Sender: TObject);
var node: PVirtualNode;
begin
node:= VST.GetFirstSelected();
if(node <> nil) then
VST.EditNode(node, EDITABLE_COLUMN_INDEX);
end;

Related

GExpert's Replace Components Expert doesn't replace the text in the form file (*.dfm)

I am using Delphi 2010 and GExperts stable release 1.35
I am testing the "Replace Components" expert.
I add a main form and a secondary form. Each has three TEdits on it.
I use the Replace Components Expert to replace all TEdits with TRzEdit. I Check the Replace all components on all forms of the project.
It works, it replaces them all. However, it doesn't do anything to the DFM file. How do i make it replace those instances.
If i save, compile, or rebuild, i get errors.
If i try to view the form as text after replacing, i get errors.
Can someone explain to me the steps to make this work?
Thanks
I just tried it with Delphi XE and GExperts 1.35 and it does indeed crash now even after a single "Replace Selected". (It used to work fine in the past).
It seems that using the hidden menu Project | Clear Unit Cache just after Replace Components then doing a full build before trying any Save/Compile/View As Text... fixes the problem.
I think this menu is surfaced with cnPack. I don't have it and cannot guarantee, but you can easily do it yourself by adding the following unit in one of your installed packages:
unit FGEnableHiddenMenus;
interface
procedure Register;
implementation
uses
Classes, Forms, Menus;
procedure Register;
var
Comp: TComponent;
begin
//Make a hidden menu item visible
Comp := Application.MainForm.FindComponent('ProjectClearUnitCacheItem');
if Comp is TMenuItem then
TMenuItem(Comp).Visible := True;
end;
end.
Source: Brian Long's old goodies
Update:
I had to replace a couple of TEdit by TDBEdit on our main project at work and this trick worked.
But on a new Project with 3 Forms, it failed consistently to write/commit/save the changes on the last Form (same environment).
FYI, I tried with and without DDevExtensions 2.5 and IDEFixPack 4.6.1
Update2:
Went digging in the GExperts forum as suggested by Ulrich and finally found a possible explanation. The new property Touch does not like being copied from one component to another when the source is destroyed (causing the AV).
The suggested workaround is to do a bidirectional mapping in the Expert Settings to disable the copy for this property:
You might be running into this bug while trying to copy the Touch property from the old to the new component, but it has a workaround you can fairly easily test:
http://tech.groups.yahoo.com/group/GExpertsDiscuss/message/3994
Details:
There is a limitation/bug in Delphi 2010 and XE where if you assign a
Component.Touch property from one component to another and destroy the
original component that the new component becomes corrupt (it isn't
like component/interface references, where they either auto-correct
themselves or are reference counted).
For the moment, you can assign a bi-directional replace component
property map from TPanel.Touch to TGroupBox.Touch (use the two components being replaced in your specific case) that is marked as
a disabled property map, and that will work around this problem. Our next release
will not try to assign that property any longer.
GExperts 1.36 is also now available and includes a workaround for this issue. The workaround has been in the GExperts version control system and in testing for several weeks already.

How I can add some items to the code completion combobox of the Delphi IDE

I'm working in a Delphi IDE expert and I wonder if it's possible add new items to the code completion combobox displayed by the Delphi IDE when the user press CtrlSpace
UPDATE:
What I need is add items to the code completion list based in a specified type.
example suppose which I have a type called TMytype, what I want to do is add addional items to the code completion list when the user type a variable of the type TMytype
check this image
I found your question somewhat confusing but if you are in search of credible source on "Custom Live Templates" and the like on Delphi, head to the blog of Cary Jensen here.
Edit:
Looking forward to further improvement of the scope of the question, I suggest here another direction to explore:
Source code manipulation using IOTAEditor, IOTASourceEditor, IOTAEditReader and the like
Some Parsing for sanity check prior to apply any modification.
Adoption of Client DataSet as a format to store data (It's serializable) to simplify the coding of IDE editors.
Perhaps I haven't fully grasped the extent of what you are asking here, but you can add templates simply by going to 'View|Templates' from the Delphi IDE. This then opens a template viewer. Press the '+' icon. It opens a template1.xml document which you can then edit so create your new item.
If you wish to do this programatically, just add an xml file (of the same format) to the ..\RAD Studio\code_templates folder.

Remove AddIn path from UDF in Excel formula

My addin was xla, now I use excelDNA, so it becomes xll,
When I open spreadsheet built in previous version of My addin,
for the UDF, it shows myUDF with path of xla. e.g "C:\Program Files\Installation folder\MyUDFs.xla!MyUDF",
when I click Edit link and change source to "C:...\MyUDFs.xll"
I got a pop up which says
"Excel cannot update one or more links in this workbook. To update the links, open all the link source files(click Edit Links on the Data tab).
To be sure all calculations are updated. press F9"
I click OK, then the path of MyUDF changes from xla to xll, e.g. C:\Program Files\Installation folder\MyUDFs.xll!MyUDF
For clients, this will break all their spreadsheets (could be 100+) built in previous version.
I know I can write a VBA code to remove paths from all MyUDF. but it is not ideal since users have to open up spreadsheet and put the code in spreadsheet and run.
I wonder if there is a better/more convenient way for clients to solve the issue
thanks
Internally, Excel stores different information for an .xla function
and an .xll function. It's not so easy to around so that you can make
an .xll that is compatible with functions that were entered into the
sheet as functions in an .xla.
You can also see how Excel stores this information by poking around inside the .xmlx file a bit.
This Wilmott discussion might be relevant:
http://www.wilmott.com/messageview.cfm?catid=10&threadid=79763
For your case the best I can suggest is adding a conversion macro to
your .xll, and having the user press the 'Fix-up' button when they
open spreadsheets that have not been converted yet.
This is the solution I use at last. I keep my xla addin, in xll, I register the same MyUDF with the same sigature(while, almost the same, optional parameters are not supported in xll, but are used in my xla) and set IsHidden = true. So there is only one MyUDF shows up in insert function list. When you type in =MyUDF and click function wizard, the version in xll shows up in function argument window. In Excel 2007, when I type =MyUDF, there is no function in drop down. In Excel 2010, when I type =MyUDF, there is a drop down. So the solution works better in Excel 2010.

How do I make Beyond Compare ignore certain differences while comparing versions of Delphi Form Files

I use Beyond Compare (version 3.1.10) to compare different versions of Delphi Form Files, but I don't want to see differences concerning ExplicitTop, ExplicitLeft, ExplicitHeight and ExplicitWidth.
Details:
These lines will always begin with a number of whitespace characters, then "ExplicitXXX = " and a number. Older versions of Delphi didn't have these lines, so I want to ignore differences where these lines are added to the newest version, and I also want to ignore differences where the number has changed.
Does anyone know how to do this?
Edit:
Duplicate (more or less) of:
How do I configure BeyondCompare to ignore SCM replaced text in comments?
Load a pair of DFM files showing the difference.
Click the Session Settings button (aka Rules w/ umpire icon) or use the Session->Session Settings menu item.
Switch to the Importance tab then click the Edit Grammar... button to open a second dialog.
Click the New... button below the top listbox to open a third dialog.
Change the Element Name option to something like Explicit*, change the Text Matching to Explicit(Left|Top|Width|Height) = \d+ and check the Match character case and Regular expression checkboxes, then click Ok, then click Ok again in the second dialog.
Explicit* should now appear in the original dialog's Grammar Elements list. Uncheck it, then change the combobox at the bottom of the dialog from Use for this view only to Update session defaults.
I don't use Beyond Compare, but if you want to have newer versions of Delphi stop adding the (IMO useless) Explicit* properties, you can use Andreas Hausladen's DDevExtensions
In my case (C#), I wanted to ignore the entire line which contained namespaces (and thus, using's) which I changed.
(Referenced Walkthrough - Ignore entire line if text exist in line
ie.
namespace INSERT.NAMESPACE.HERE
changed to
namespace INSERT.NAMESPACE.HERE.NEW
To do that
In step 5. of Craig's solution, change the Text Matching to
" .\*INSERT.NAMESPACE.HERE.\* "
(include the quotes)
That's it.
Craig Peterson's answer is correct.
N.B. However! The tab 'importance' is not always visible from Session/Session-settings. Always, from inside a Folder list view, it will not be there. It seems there are certain filetypes that do not have it either, though I'm less clear on that. BC has so many options and plugins I bet there is a workaround, but for me I have been ok so far.
http://www.scootersoftware.com/vbulletin/showthread.php?t=8457

Delphi "EClassNotFound" errors, and corrupted DFM possibility

I am getting a cascading set of "EClassNotFound" errors in in my Delphi 2007 project. Doesn't seem to be caused by the missing Name property value as often is the case, and though adding RegisterClass(XXX) in the initialization section(s) fixes the EClassNotFound error at hand, another one follows it seemingly indefinitely.
I finally cracked open the DFM file in text editor, and it looks likely corrupted to me (lots of non-ASCII characters amidst form element names, and very "unstructured" looking when compared to what I'm used to seeing in a DFM file). (I'd post a same here but not sure that's OK, w/the non-aSCII, so will hold off).
The form loads fine, and seems to compile / syntax check OK too, but once I run it, trouble.
Going back to early versions of it in SVN, it looks like it's been in this state for some time, which makes me think that either A) the DFM file isn't my problem, or B) the Delphi form-streaming is quite fault-tolerant/robust (Bonus Question: Which is it?).
If the DFM file is the problem, and is corrupted, rolling back will have to be a roll-back WAY back, and that's gonna be expensive. Given that the IDE can still load it, is there any utility that can clean up the file?
Or, am I totally off base w/the DFM as primary suspect?
Thanks folks for the input. Forgot about the binary/text options w/DFM files, so that was helpful. It looks like the DFM itself is not corrupted.
Still having the EClassError issue though. re: It being missing property values, or referencing non-existing properties, etc., a further question: Is the class the error is given for (currently TnxSqlUpdateObject, but probably more waiting in the wings if experience thus far is consistent) usually/always the actual "culprit" class/object?
For instance, right now my main form has four references to TnxSqlUpdateObject, w/those actually dropped on the form. If I put RegisterClass(TnxSqlUpdateObject) in the initialization section, it runs fine for that EClassNotFound error but then goes on to the next one (in this case, TStringField).
I have reinstalled the NexusDB components in this case, and also built a new project using some of the components I thought might be the problem. It compiles and runs fine, UNTIL I add this other form from my real project (which, in turn, unfortunately references quite a few others).
SO, it sounds like my real issue is how to methodically diagnose and fix any and all EClassNotFound errors?
I get this error if a component is on the form, but doesn't have an entry in the form definition in the source file too. Most often when I've copied and pasted from another form. Simplest solution is to select the component, cut it, then paste it back. When you save, the component's unit will be added to the source, and when you run it again it will all be okay.
Well, a dfm file could be binary or tekst (as I'm correct from version 4.0).
You can check this by right click on the form and check the Text DFM flag.
If a dfm file is corrupt, tou can try to fix it by removing all suspicious lines.
Be sure to leave the object .. end sets intact and you probably only loose some property values.
By the way, the dfm file should look like this (to get an idea of the general structure):
object Form5: TForm5
Left = 0
DesignSize = (
426
652)
object Button1: TButton
Left = 343
end
object Memo2: TMemo
Anchors = [akLeft, akTop, akRight, akBottom]
end
end
If it does not look like that you are probably editing the binary file.
If you have a recent compiled exe that works, you can use a resource-editor, like PE Explorer, to get the dfm-definition. Then you can compare the one from the exe with the one that you now have.
I believe there is tools to convert binary dfm-files to text-files too. This will give you a better view on the file, and help you decide if it's really corrupted or not. I see Felix has something on the topic.
If the Delphi IDE shows the form ok without errors, I can't believe there is a corruption-error. Could there be a package problem? Do you use runtime-packages?
Update:
Hvae you tried Eurekalog or madExcept or something similar to get a more detailed error message with callstack and memorydumt? Maybe that will give you some clue about the problem.
But generally i think this error comes from missing runtime package, or a missing unit in the uses-clause. If you think you know witch component causes the error, search the source for the call to RegisterClass( ), and see if that unit somehow is included in the projcets uses-clause. If not, add it and try again.
If you can load the form in the Delphi IDE the DFM resource is not corrupted. Delphi uses the same code to load the DFM as the final executable will use, so I think that won't be the reason.
You can open the DFM in the Delphi IDE directly (if the corresponding pas file is not open), or you can use Alt+F12 to switch between form view and text view of the DFM. In this view the structure should be sane, with correct indentation and so on.
As Gamecat pointed out you can use the command in the form popup menu to toggle the DFM storage format. Leave it as text for Delphi 5+, it works better this way with SVN.
As for the cause of your runtime problem - I have no idea...
Edit: After your ruling out the DFM as the source of the problem I can only assume that an important unit in the uses list is missing, which can only happen if not all the components on your form have a corresponding member field. You should check that all the components referenced in the DFM are also in the form, even when you do not access them in your code. This will in turn cause Delphi to add any missing units to the uses clause when the file is saved. Manually registering components should not be necessary if the form class has references to all the components in the DFM.
For a quick check you could create a test form, drop all of the components that your "problem" form has onto it (one instance is enough), and check whether this works.
This can happen in case you have changed one of your custom components and removed a property from it. The property is stil in the DFM and Delphi tries to initialize it.
Try to remove manually parts from your DFM so you can pinpoint which component is causing the problem.
Try this:
Make backup first
Right click on form in designer; uncheck "Text DFM"
Save
Right click on form in designer; check "Text DFM"
Save

Resources