The problem: I need to obtain the selected text from a window in a Windows application (not my program). I am doing my work in Delphi XE and the software I am attempting to access is a kluge built over the past 15 years with C, C++, VB and who knows what else. I do not have the source code. The edit box (an RTF memo) I am attempting to read is of the class "Ter32Class". When I use wm_copy, nothing goes to the clipboard. when I use wm_gettext, nothing. When I use wm_keydown commands (to simulate Ctrl-Ins or Ctrl-C) nothing happens. Note that I can get all of these alternatives to work in wordpad, notepad, and FireFox but not this application (or OpenOffice, incidentally, but that's not the issue). The only way I have been able to programmatically obtain text from this box is to use autohotkey with the simple "send ^c" command. While it works, it is inelegant. HELP?!?
More information: Window hierarchy: Ter32Class is a child of OI_Mdi which is a child of MDIClient, which is a child of OI_Window . I am drilling down to obtain the appropriate handle as it will respond to a paste command.
I am using Delphi XE but I'd love any solution in C++ or VB if no Delphi XE gurus have the answer.
From Quick Macros Forum
One of the windows I need to talk to is of class Ter32Class which
apparently is a TE Edit Control, an editor that doesn't inherit from
the standard RichText Control
and
The published method of talking to this control is via it's DLL
so unless something has changed (post is 2006), it appears you'll need to use it's dll to get the text.
From Sub Systems (TE Edit control website)
Application Interface functions
GetTerBuffer: Retrieve Window Text
HANDLE GetTerBuffer(hWnd, size)
Related
I have created a COM Interop Control in C# to use in my PB application. If I add an ole control to my userobject and select my C# object in the painter, then an olecustomcontrol is created and everything works as expected. However, in order to use a 64-bit version of my object when building the project for a 64-bit platform (in PB Classic 12.6) I added an ole control but hit cancel when asked to select an object, so an olecontrol is created and I can use InsertClass to select my object at runtime. This is working for me but I have one issue: when the user clicks in my control, activating it, the toolbar icons on my MDI window disappear. From the research I have done, it sounds like PB may expect the ole object to provide the menus and toolbars, but my PB menu items are unaffected, it is just the toolbar. My control does contain a toolbar (the control is a rich text editor I created to workaround some shortcomings of the built in control) but I have also tried creating a new Interop Control with only a plain text box on it and got the same results. Actually I also tried using one of the Microsoft controls (Microsoft InkEdit Control) installed on my system, and again got the same results.
Does anyone know how I can fix this toolbar problem? (I'm at a loss, but I'm guessing it may be that I need to somehow tell PB to ignore OLE toolbars and/or tell my C# object not to advertise a toolbar.)
Ah, that legacy code we have to support for decades...
The following would take some research and may not eventually solve the problem, but I'd give it a try. I'd implement a "proxy" COM object that'd serve as an extra layer between your .NET OLE control and its OLE container. Such object would be exposed as OLE control to the PB runtime, and as OLE Container to the .NET control, and forward the COM methods calls between the two. It'd be much easier to code this layer with C++/ATL, but it should be doable with bare C#, too.
Then I'd watch the calls made on IOleInPlaceFrame and IOleInPlaceUIWindow interfaces and block those which lead to the undesired toolbar behavior (if any). I'd also limit the set of OLE control interfaces exposed to the PB runtime to some bare minimum.
The implementation details of AxHost and Control classes might be helpful here, as well as the ATL library source code.
This seems a bug. I created a very simple application that retrieves data into ole control and there was no code in any menu items. As soon data is fetched and ole control gets focus the main MDI toolbar disappear. Somebody should report that bug to SAP.
https://answers.sap.com/questions/300798/toolbar-disappear-when-ole-control-get-focus.html
I have deveoped a custom file type, together with a custom editor (basically a tree with several data pages attached and a few extra buttons). OK, I can run it stand alone and that is fine, and even add it to the tools menu, but I would like to integrate it into the Delphi IDE so that my custom editor (or a similar new version) appears in the IDE, rather like a DFM file has a custom editor. I can find references to most extensions in the Delphi IDE, but not this one. Any guiding hands? Note that this is not a property or component editor (the file type has nothing to do with either of these) nor is it simply syntax highlighting of a text file.
AFAIK it currently isn't possible to reliably integrate a custom editor into the Delphi IDE. The required API simply isn't there. See QC89028 Custom Module support.
During the Delphi 2010 and XE betas I spent most my spare time trying to get a resource editor integrated. Although the effort had the official blessing of Embarcadero and got some, half hearted, support from the IDE engineer, I was never able to get them to deliver on their promises and surface the module API. I eventually abandoned the project.
Update: I've now checked my old correspondence regarding this and it turns out part of the problem was that IOTAModuleCreator (used to implement File|New for custom file types) and IOTAEditorContent (used to transfer data to/from the custom module) only supports text data. Binary data gets mangled.
You can probably do this via an IDE plugin that uses the ToolsAPI (see ToolsAPI.pas in the IDE's source folder (e.g. Program Files (x86)\Embarcadero\Studio\source\ToolsAPI\ToolsAPI.pas.)
For information on writing a plugin in general, see David G Hoyle's excellent blog. Once you know the basics - i.e., write a 'wizard' and get it to do something - you will need to work on integrating your editor.
I have never done this, and so I can't guarantee it is possible. However, some interfaces that look worth investigating and implementing are INTACustomEditorView, which represents a 'view' (file tab when that file is open - think the code editor, Welcome view, type library editor, etc) and IOTAEditorViewServices, to register your custom view. I do not know how you associate a view type with a file type, sorry - possibly something to do with the personality interfaces. You might also be interested in INTACustomEditorSubView which is what creates a tab on the bottom of a file.
Good luck, and if you find a solution please write here so that other people can learn too!
Delphi7 (cannot use latest). I want to replace (easy way, not making my form) MessageDlg calls with Vista style dialogs (must still work on old OS!). I need buttons Yes/No/YesToAll/NoToAll in this.
How to do it?
MessageBox isn't a way: I need all 4 buttons Yes/No/YesToAll/NoToAll in one form, or maybe checkbox instead of ToAll btns.
On Vista you use the native task dialog, TaskDialogIndirect. This has all the functionality you need. You'll need to translate the headers to Pascal, but if you don't fancy doing that yourself then you can use the JEDI header translations, for instance.
On XP and older there is no task dialog. There is no native system dialog with the functionality that you desire. Therefore you need to implement the dialog yourself. Create a Delphi TForm descendent. Add the necessary text, buttons, styling etc. Show it with ShowModal.
One of the issues with all this is that TaskDialogIndirect must be bound at runtime with GetProcAddress. In fact, use GetProcAddress to determine whether TaskDialogIndirect is available, and if not fall back to the XP code path.
If you don't want to build this yourself you can use one of the many extant libraries that offer such functionality. For instance: http://blog.synopse.info/post/2011/03/05/Open-Source-SynTaskDialog-unit-for-XP,Vista,Seven
Presently I am developing a small security application in Delphi. It is intended to be installed in Windows XP and higher OS-s and almost finished, but I'd like to implement the feature to scan MS Office files while opening. To that end, I'm planning to use IOfficeAntiVirus interface. I am trying to realize using the scan method of the interface based on the article by Serge Perevoznyk (http://www.delphi-central.com/MS_Office_AV_API.aspx).
The original example supposed to display a message box when a file is opened, however it does not, although I tried it on different versions of Windows and Office. I compared this solution with the information on MSDN. It seemed to be correct. I suppose there should be some additional settings in the Windows Registry which I missed to make. Can anyone give me some hint where shall I look for the solution?
You do not use IOfficeAntiVirus, you implement it.
You need to create a new ActiveX Library that contains a new ActiveX Control whose implementation class implements the Scan() method. In the Control's registration code, you have to use ICatRegister to register your Control as using the CATID_MSOfficeAntiVirus category. That way, Office/IE can find your ActiveX Control so it can instantiate it and call its Scan() implementation. The second half of Serge's article shows you how to do that (Serge's example shows Scan() taking a PChar as input, but it actually takes a TMsoavinfo^ instead. Don't pass TMsoavinfo using a PChar).
You then have to register the resulting DLL using Windows' command-line regsvr32.exe app.
If Office/IE is not calling your Scan() implementation, then you are likely not registering your ActiveX control correctly, such as if you are not taking 32bit/64bit and/or UAC issues into account.
Just for information's sake if anyone is interested. Remy's answer is correct, however there is a small bug in the initialization section of the above mentioned example project.
Instead of
TComObjectFactory.Create(ComServer, TMsoTest, Class_MsoTest,
'MsoTest', '', ciMultiInstance, tmApartment);
The correct command is:
TMSOAVFactory.Create(ComServer, TMsoTest, Class_MsoTest,
'MsoTest', '', ciMultiInstance, tmApartment);
I'm using Turbo Delphi 2006.
The DLL will be called from within Excel as part of a VBA/DLL combination.
The first part of the problem is trying to find out how to pass to the DLL a reference to the current Excel session. Most other code I've seen was that it launched a separate instance of Excel apart from the one you're in.
I've seen some C++ code that creates an instance of IDispatch and then passes something in to a method of the IDispatch object, but not knowing much C++.
Any ideas?
What you describe is called writing a COM addin. You need to create an automation DLL and implement the IDTExtensibility2 interface. You will then receive the Excel Application interface as a parameter to the OnConnection method.
You will also need to register your DLL as an addin so Excel will automatically load it.
EDIT: Forgot to mention: You might want to take a look at Add-in Express. Their framework and components make getting started with the creation of Office addins ridiculuously easy. You definitely won't have to bother with the details of IDTExtensibility2. All that comes with a (well-justified) price tag, though.
Delphi comes with a set of ActiveX controls to give complete access to Excel and the other Office applications. They should be on the "Servers" tab of the Tool Palette.
If the aren't there, then select Components|Install Packages, and scroll down the list there until the very end, and select the right package.
In a default installation, they should be called:
Microsoft Office Sample Automation Server Wrapper Components
and there should be one for XP and Win2k. The XP ones will work for Vista.
Now that if if you want to automate Excel.
If you merely want to add functionality to Excel by using Delphi, I'd suggest using a COM object, as I suspect that Excel is very accepting of COM objects. Otherwise, you can create a straight DLL, and use that the same way that Excel uses any other DLL.
I do not know much about Office, but I guess you should use COM/ActiveX. Then you also get your IDispatch. See http://delphi.about.com/od/comoleactivex/OLE_COM_DCOM_Automation_ActiveX_Delphi_knowledge_base.htm