DragDrop between two FMX applications - delphi

Hi I need to drag an image from one application to another. Both are Delphi FMX applications. I was successful in doing it within one application but now need to transfer between two separate applications, ie no memory sharing. I would be happy to save all info into a file and transfer the file name in the operation. I do detect the dragover event in the receiving application but the data property is nil and I don't know how to populate it with a useful value.
I am using Windows 10, Delphi XE10.3
Any example, explanation will be helpful
Thank you

Did you find an answer?
I am trying something similar. Andreas is right about proper OLE, but it will be a lot of work to implement in FireMonkey.
The problem is that FireMonkey, on Windows, only interprets external drags of files (by their name and path) or unicode text. It can accept other external drags, but extracts no information so it is useless.
Look in FMX.Platform.Win.
TWinFropTarget.GetDataObject() is the culprit.
PlatformWin.FDragAndDropActive is true for internal drags and false for external.
External drags of CF_HDROP (filenames) and CF_UNICODETEXT (unicode text) only are interpreted.
To implement yourself steps would be
Roll your own IDropTarget.
Register it with Windows. See TPlatformWin.CreateWindow(), call to RegisterDragDrop()
Create a mechanism for freeing it, which is all TWinWindowHandle.FWinDropTarget does, but FWinDropTarget is private.
Hook it up to the form or component that will receive the drop.
Enhance GetDataObject, or whatever replacement you have decided, to interpret the external drags that are of interest. This requires more research.
Above generally covers the receiver.
The sender requires yet more research for how to initialise a Drag Drop of the content of interest in Windows.
Repeat for other platforms as required!
Drag and Drop component suite for VCL, https://torry.net/pages.php?id=233, probably has a lot of the code to do this, although I have not looked at it.
If anyone tries this, please update this thread.

Andreas and my answers are about dragging the image itself. In the question you suggest that sending the filename would be acceptable. Following further research to solve my own issue I can give you the categoric answer for this solution, which avoids would be significantly less work.
Drag Drop, as you already know, involves a Source, a Target and Data.
Fire Monkey Drag Drop implementation for internal drags (i.e. within the application) uses its own data format, namely the Data record. For internal drags only the Data.Source property is populated.
For external drags (i.e. between applications, whether FMX or not) OLE has to be used for the data.
All drags can be received by all open applications. But unless OLE data has been set by the Source the Destination will be unable to interpret what the drag is or where it is from. Your question states "I do detect the dragover event in the receiving application but the data property is nil". You are experiencing the situation I am describing.
Delphi FMX will interpret and decode OLE data received for Files and Text content. Files is a list of filenames with paths, not the files themselves. Other OLE content is ignored, such as image. See my previous answer for how to enhance FMX to interpret other OLE content.
Delphi FMX does not set OLE data. Therefore to implement drag drop from a Fire Monkey application to another application, including another Fire Monkey application, it is necessary to write you own start drag code which populates OLE data. In my previous answer this is written more briefly as "The sender requires yet more research for how to initialise a Drag Drop of the content of interest in Windows."
Such Drag Start code would be called from OnMouseDown event of the Source control. For Windows I think
create a COleDataSource
set the data
call its DoDragDrop method
I have not tried it because my application will not be a Source of inter-application drags.

Related

How can I obtain the original text of a visual component property?

I would like to be able to read the original text of a component (published) property at runtime after it has been (potentially) changed.
The context is that I'm writing an extension of a translation library that we used in our application. That library is old and not supported by the supplier any more so I am on my own to make it work.
Unfortunately, the way the library is coded makes it impossible to use from an ISAPI Dll (for instance, in an Intraweb application). The dictionary part works but the automated translation component does not (mostly because it tries to overwrite some code section in memory). I'm therefore trying to salvage the parts that works (form translation tools and dictionary storage) while rewriting the part that doesn't (well, only the elements that I'm interested in, really).
I'm, however, stopped by the fact that, once a component text property has been translated, it will not match the original text any more and won't be found in the dictionary.
That code is supposed to work in Delphi 7 although I'm planning to migrate it to XE5 as soon as I have enough time for that.
"Once a component text property has been translated, it will not match
the original text any more and won't be found in the dictionary."
Can you keep a separate lookup map yourself, of translated content to original? Add to this any time a string is replaced with its translated content. That way you can go back and forth between the original and translated at will.
In XE5, the easiest way would be to use a TDictionary. In D7, you may have to roll your own container.
You can make a procedure that save the original values to a List or some array, then call that procedure in the Form's Loaded method (you have to override it, and don't forget to call inherited at the end of it.) Then search for the directory entry in that list. The Form's Loaded method is called after all the components is loaded from the DFM but before the FormCreate. So here you can find all the original properties.
From what I understand, what you want is to get back the value of string properties as they are stored in the DFM at compile time.
So, I guess the most reliable way to do so would be from the DFM itself. As far as I know, DFMs are always stored inside the binaries as resources (though there might be some exceptions...). I looked into doing something similar a while ago. I didn't manage to make it work as R&D time ran out (I only had a couple of hours), but if you want to look into it, I'd start with
TCustomForm.Create
InitInheritedComponent
InternalReadComponentRes
TStream.ReadComponent
TReader.ReadRootComponent
Maybe someone can confirm whether this approach can work or not and what are the caveat, but until then, I think it's a valid research direction for you.

How to get the property list and values of a control within a third-party Delphi application?

I'd like to get information about a third party application's controls such as a list of its properties and their values: something like RTTI information but for a third-party Delphi application.
I see that this is possible. For example TestComplete has the ObjectSpy window which can give many useful information about the control, including RTTI information. How can this be done ?
Edit: To explain why I'm investigating this issue... I'm a registered user of TestComplete/TestExecute and I do like... most of it. I can get over the minor things but the one major problem for me is their license verification system which requires me to have a physical computer (not a virtual machine) always on just for the sake of running a license server so that TestExecute can run at night. As I have basic testing needs (compare screenshots and check basic Delphi component's properties) I wondered how hard it would be to make my own private very simple "TestExecute-like" application.
To go further, I suggest you these relevant resources found here on SO
Writing a very basic debugger (The accepted answer along with its comment thread are all valuable).
Is it possible to access memory from an application to another ? How? (Excerpt from the accepted answer: It is possible. Just use the Windows API functions WriteProcessMemory/ReadProcessMemory. Pass in the handle of the process and the pointer to the data).
Search the memory of another process (The excellent accepted answer also forwards to another valuable resource delphi-code-coverage by Christer Fahlgren and Nick Ring).
StackWalk of other process in delphi? (Check Barry Kelly's answer !!!, the same for the one from the AsmProfiler author !!!).
I strongly suggest you to port to Delphi this c++ project entitled Get Process Info with NtQueryInformationProcess: A hands on experience on using ReadProcessMemory to access the CommandLine used to launch another process.
Last Edit:
NtQuerySystemInformation Delphi Example.
RRUZ's answer to Delphi - get what files are opened by an application as suggested by LU RD.
When we want to take another application which is compiled with debug information and get stuff out of it at runtime, what we are dealing with is the problem of "how to write my own custom debugger/profiler/automated-test kernel".
TestComplete and other AutomatedQA programs contain a Debugger and Profiler Kernel which can start up, run and remotely control apps, and parse their Debug information in several formats, including the TurboDebugger TD32 information attached to these executables. Their profiling kernel also can see each object as it is created, and can iterate the RTTI-like debug information to determine that an object that was created is of a particular class type, and then see what properties exist in that object.
Now, TestComplete adds on top of the AQTime-level of stuff, the ability to introspect Window handles, and intuit from Window Handles, the Delphi class Names that are behind it. However, it's much easier for you (or me) to write a program which can tell you that the mouse is over a window handle that belongs to a TPanel, than to know which version of Delphi created that particular executable, what version of TPanel that is, then, and what properties it would contain, and to read those values back from a running program, which requires that you implement your own "debugger engine". I am not aware of any open source applications that you could even use to get a start writing your own debugger, and you certainly can't use the ones that are inside AQTime/TestComplete, or the one inside Delphi itself, in your own apps.
I could not write you a sample program to do this, but even if I could, it would require a lot of third-party library support. To see the window classes for a window handle which your mouse is over, look for how to implement something like the MS Spy++ utility.
An easy case is if your mouse is mousing over a window inside your own application. For that, see this about.com link, which simply uses RTTI.

inspect delphi control object without modify source code

I have an Stock program which developed by Delphi, I want a tools which can read the data from the stock program, for example, the stock price in Delphi grid object.
The Stock program under test is close source, so no chance modify source code which QTP/Robot inspector required. I cannot tell out which Delphi version it is using, neither the object is a standard delphi control.
So anyone can tell out is it possible to inspect that delphi program object data through other technology ?
thanks in advance.
You can use a tool like Winsight to find out the structure of the program window, and use FindWindow and EnumerateChildWindows to find the controls. Then you can use GetWindowText api to get the text of the control. This will work with most controls, but might not work for all. For instance TLabel control has no handle, but does its drawing itself. It has not handle to get the text from and it won't show up in WinSight. You'll have to OCR the window to get those label texts. :p
But this 'testing' sounds more like 'hacking' or 'controlling' to me, if you don't even know what kind of controls are used and which version of Delphi is used, why are you the one testing this program this way?
Trying to read data out of a Delphi grid control is not going to work out for you. It's not like a standard Windows edit control which you could just call GetWindowText on.
If you really want to get the information from this existing program then you'd need to poke at its internal memory or do an OCR on a screen grab. All pretty horrible to contemplate.

Delphi - How do i find out what a component is doing 'behind the scenes'

Im attempting to write a new component descendant from a common component (TDateTimePicker). My ultimate goal is to sub-class the TDateTimePicker so that when the user enters the component, the 'SelText' is set to a particular part of the DateTime.
At the moment, the behaviour of the TDateTimePicker is to focus the last selected text when it receives focus again. What i would like to acheive first, is to find out (look at) the code that actually is executed when the user focuses the TDateTimePicker.
I can see TDateTimePicker is a decendant of TCommonCalender which in turn is a decendant of TWinControl. But ive tried placing a breakpoint on procedures in TWinControl and they cannot be reached (which i guess is correct behaviour since a lot of components inherit from TWinControl).
So how do i find out what is happening when the user enters a TDateTimePicker? What code is run? Is it all hidden? I would hope this may shed some light on what i need to do to override the default bahaviour to accomplish my goal.
TDateTimePicker is a wrapper around a Windows Standard Control. The Delphi wrapper simply sends messages to the Windows control, so there's not much Delphi code to read.
You'll have to treat the TDateTimePicker as a "black box". Whatever happens in there, it's an implementation detail you're not supposed to care about. In fact the implementation details for the Date Time Picker have changed, for example, with Windows 7!
In Project|Options|Compiler check the 'Use debug DCUs' and the rebuild the application. Depending on the Delphi version this checkbox can be found in different places, this is for Delphi 2007.

Tabbed document interface in Delphi

I'm considering different user interface layouts for my next project and I was wondering if there are either integrated or 3rd party frameworks which allow me to create tabbed document interface?
To clarify, what I want is not some kind of docking mechanism or either an MDI interface but primarily a framework which allows me to have one main form and one or more secondary forms which will be shown as tabs inside the main form.
Though I said I don't want any kind of docking mechanism, I made a small test application that actually uses it. The result I got is very close to what I want. First, I miss some features like the close button on each tab. Second, I'd have to create some kind of framework of my own in order to automate all tasks, like creating and destroying the tabs, associating each new form with its tab, freeing the form when the associated tab is closed and so on. I'm not saying I can't do it but I'd like to know if there are any ready-made frameworks which already have all these features. Though I'd prefer an open source solution, a commercial one is also welcome.
Third-party components are not mandatory here.
You can use standard Delphi controls to obtain what you want:
Put a TPageControl on your form (from Win32 tab);
Set its Align property to alClient;
Right click on the control, then select "New page" to add a new page.
Then don't write your "tabbed" interface on forms, but on frames.
You can also create pages by code, displaying the frame inside each page.
I don't think there is any framework for tabbed interface, but for nice looking tab/page controls with close buttons on each tab, please check the following:
rkSmartTabs, it simulates Google Chrome browser's tabbed UI. and it's open source.
TAdvOfficePager, MS Office style.
Hope it helps.
I recommend using a tool bar(TToolBar or any similar) and frames(TFrame) in order to mimic tabbed interface, reason?! well Delphi is going cross platform(no secret in that) they will port most if not all of the standard VCL shipped with Delphi, so WHY NOT use this as an advantage?
Just create the frame(dynamically) when the user clicks on a button from tool bar and destroy the previous one(if exists) so you will keep memory usage at minimum, application startup/shutdown time will be very good, on the other hand, if you chose to use (cx)TPageControl, TAdvPager, etc. you might get caught in a situation in which one form(the main I suspect) will have so many VCL's that it will take a lot of UNNECESSARY memory and it will be slow.
Using frames has a lot of advantages, if somewhere in your application you need a "tab" to be shown, you can simply create the needed frame dynamically and use it without additional work.
Anyways, this is my two cents, hope this helps.
I recommend TvjPageList, which is part of the JVCL suite of components. It's open source and seems to fit your requirements.
I use JVCL JvDocking, and its tabbed docking system, to make MDI-like applications.
You can also float, or tile your windows, in addition to having them in tabs.

Resources