inspect delphi control object without modify source code - delphi

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.

Related

DragDrop between two FMX applications

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.

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.

Creating Delphi Activex Servers from existing objects

In Delphi the process of adding an activex object to a project is fairly simple - you import the class and Delphi wraps handlers around it and you're done in seconds. What I'm wanting to do though is create a server that the class connects to rather than a client for the class.
The specific case I'm working on is with OPOS printer drivers. I want to add an OPOS printer driver interface to an existing program so that the OPOS control objects can see my program as just another printer object class. I can readily import the printer type library as a component that I'm a client of, but I'm unsure what I need to do to be the other side of that conversation. I suspect I'm looking at something the wrong way but pretty much all the reference material I've found assumes I want to be a client or that I want to define an entirely new server. I'm also a COM newbie so it's a little confusing. I've been playing with XE and D7, and have created a tlb as per the printer control but obviously haven't quite been able to get it to fly.
Can anyone give me a nudge in the right direction here?

Where should I begin when building a component?

I am looking to build my own component and have no idea where to begin. I have some Delphi books but they are old and outdated, and am looking for some recommendations on tutorials/books to help me do this. The component will be pretty simple, basically 2 labels and an image. I need hundreds of these in an array, so I thought a component would be the best route. The text will adjust based on width etc, and have some mouseover events. So basically, where do I begin?
I am using Delphi 2009, this will be a win32 app.
Thanks!
You can order Ray Konopka's book Dev. Custom Delphi 3 Components - PDF for 25$. It's a specialized book on the subject and very good for a beginner too.
The main principles behind developing components is:
Whether the component is visual or
not (Does it need a Canvas to paint on)
Does it need a window handle or not (visual or non-visual)
Once you answered those questions you can look at Delphi's source code for examples.
As far as I know, Delphi Component Design, by Danny Thorpe, is still the best book on the subject. Component design hasn't changed significantly in the last 15 years, so whatever books you have probably aren't as outdated as you think. There are three things to keep in mind while reading older references:
Names of certain units have changed. There's no DsgnIDE anymore, for example. It's DesignIDE instead.
Design-time code is strictly separated from run-time code now. This means you can't use DesignIDE in your component's unit, or else you're barred from using run-time packages. Older Delphi versions didn't have this technical restriction (although it's always been a legal restriction), so old code examples you find might need to change a little bit.
Strings are Unicode now, so as with all old code examples you find, there might be some invalid assumptions about character sizes that you'll need to recognize.
The biggest obstacle to writing components is that you're expected to use various protected members of the classes you descend from, but those frequently aren't documented, so you'll have to be much more willing to go read the VCL source code for examples of how various methods are used.
The easiest way to do what you want is to create a new form. Drop the labels and image and arrange them the way you want; if it suits your need, put them on a panel so they can be moved around as a unit.
Select all the components you want included (and including the panel if you chose to use one), and then click the Component item on the IDE's main menu, and select the "Create Component Template". (It's only enabled if you have selected components on the current form.) A dialog will appear asking you for a name for the new component, and the Component Palette page on which you want it to appear.
Take a look at this article, which describes how to build new components made up of a group of existing components.
Don't worry about your books being old.
Just about everything from the old days still works fine and what little doesn't is generally due to name conflicts or the addition of Unicode in the 2009 version.
They aren't Microsoft, they don't go breaking old code without good reason. In fact, take some code from the old DOS days--assuming it doesn't try to manipulate the screen it's likely to run with minimal fixup.
Don't worry about your old books! Since v3, Delphi hasn't changed much. This is why most of the programs compiled with D3 still compiles in D7 or even newer versions. And if it doesn't compile, probably you need to change a line or two, here and then.
I would recommend you to search other VERY simple components on Internet and see how they are made. Then make your own and post it here. Let other take a look at it and suggest improvements or spot bugs.
About your control's design:
1) maybe you DON'T need those two labels. You can just paint the text directly on the image. If you have lots of those components as you say, you may save a little bit of memory.
2) you may NOT want to have lots and lots and lots of images loading in one form. The overhead may be significant. What you can do is to load the pictures ONLY in images that are visible on screen - and you will put on screen ONLY 5-10 images (or whatever number of images you can show on the form without going out of screen). As the user scrolls down, you keep the same same TImage controls on screen but you load new (next) images in them.
3) You may not want to store labels and TImage in an array (I suppose it is an TImage because it seems you want to show them on the screen else you won't need labels - you need to explain your problem in more details if I got it wrong). But you can store a TBitmap and the text (that you want to display in labels) instead.
So, you may need to calculate how much CPU/disk overhead your hundreds of controls will create and how much memory they need. If you stay well under 1GB and the loading time is under 10 seconds, then it is relatively ok. IF not, you may want to think about your control's design before starting to actually implement it.
Hope this was helpful.
See ya.

Differences between Application.MessageBox, Windows.MessageBox and Dialogs.MessageDlg in Delphi

In Delphi; what are the differences between Application.MessageBox, Windows.MessageBox or Dialogs.MessageDlg?
Or which is more efficient to use computer memory?
Windows.MessageBox is the WinAPI MessageBox, Application.MessageBox is a wrapper around it. Dialogs.MessageDlg however is a VCL form. So if you are concerned about memory or thread safety, the first two might be better suited. MessageDlg OTOH is more flexible and easier to use (IMHO, of course).
Nowadays, I'd consider task dialogs (TaskDialogIndirect, TTaskDialog or another wrapper).
Windows MessageBox is localized by OS (Yes, No, Cancel...), MessageDlg can be localized by hand.
If I remember correctly, there is one important distinction bewteen the Delphi VCL message boxes and the Windows ones - you can specifiy flags that stop the Application messages from being serviced (eg MB_SYSTEMMODAL). This can be useful for displaying errors where you need to 'freeze' your application - the Delphi MessageDlg will still fire timer events even whilst on screen. See:
MSDN MessageBox stuff
Memory usage shouldn't be such a problem with message boxes. I personally prefer the VCL form (Dialogs.MessageBox) since I can localize it from the Consts.pas unit. I also like it from the fact that I can add custom controls to it, like checkboxes for "don't show this again" and other stuff like this.
Why do you care about the tiny amount of memory used by a message box? There are many other things you should be concerning yourself with when writing a Delphi app. In any case, as far as I'm aware these are all thin wrappers around the Windows MessageBox API.
They all do the same - invoke WinAPI function MessageBox(). The difference in resource consumption if any is minimal. If you care so much you can call MessageBox() directly - just include "uses Windows".

Resources