AX Miscellaneous
From TeamDeveloperWiki
This page covers miscellaneous ActiveX/COM tips & tricks.
Contents |
How to disable internal TD error messages
You can disable the TD error messages when errors occur while calling ActiveX/COM functionality.
While having the internal messages off, you have to code custom error handling.
! Set internal error messages OFF Call SalActiveXAutoErrorMode( FALSE ) ! Do ActiveX/COM functionality here... ... ! Set internal error messages ON Call SalActiveXAutoErrorMode( TRUE )
Copy/Paste of ActiveX objects results in : ActiveX object creation failed
Sometimes, on specific ActiveX objects, it is impossible to copy/paste the object from one form to another.
The original object works, but a copy to a new form results in a "ActiveX object creation failed" error at runtime.
Another issue which could emerge is that in the IDE the events are not shown. Even copy/paste of implemented events
of the original ActiveX object to another one could lead to a compile error "Undefined Event Name".
This is due to a TD bug, caused by the fact that the pasted copy of the ActiveX object looses information which is needed
to correctly work in the IDE and at runtime.
But there is a workaround which could solve this annoying issue.
When a new ActiveX object is placed on a form, TD creates an invisible block of information within the object in the source.
Here an example. Below you see a form window on which an ActiveX object is placed (named axInternetExplorer)

When you open the source in notepad, and look for axInternetExplorer, you will find something like this:
.head 2 + Contents .head 3 + ActiveX: axInternetExplorer .data RESOURCE 5 0 1 4270659340 0000: 000A000009020000 0000000000000000 020000D0CF11E0A1 B11AE1F8000000FF 0020: 003E000300FEFF09 00F0060000000F01 000000F601000110 0000020000002601 0040: 00FEFFFFF8000000 F8FFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 0060: FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 0080: FF40FDFFFFFFFEFF FF66FEFFFEFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 00A0: FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 00C0: FFFFFFFFFFFFFFFF FFFFFFFF2052006F 006F740081004500 6E0074C072007900 00E0: 0000FFFFFFFFFFA0 16000500FFFF4F01 00000061F956880A 34D01100A96B00C0 0100: 4FD705A2F8000000 0FA068897600779B C90103000000F0C0 000000284A004545 0120: 5000085300724300 4F00C24F4C000000 FFFFFFFFFF821602 01FFFFFFFFFA0000 0140: FFFFFFFFF09C0000 00FFFFFFFFFFFFFF FFAFFFFFFFFA0000 FFFFFFFFFFFFFFFF 0160: FFFFFFFFFFAFFFFF FFFA0000FFFFFFFF FF460100020000F6 FEFFFFFFFFFFFFFF 0180: FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 01A0: FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 044C0000C51A0000 01C0: E06515000000FFFF 6F4C00FFFFFF0F08 0000006F4C00D001 1402000076C00046 01E0: F080000000FFFFFF FFF4010000FFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 0200: FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFF .enddata .head 4 - Class Child Ref Key: 0
Just after the line ".head 3 + ActiveX: axInternetExplorer" you see a data block starting from .data up to .enddata.
In between there are a bunch of hex codes. This block holds information needed for the IDE and at runtime to reference the ActiveX object correctly.
What those codes mean and how to get the info from it is unknown to me.
Now, what happens when you copy the ActiveX object from one form to another. Just have a look with notepad at the location where
the newly copied object is placed:
.head 2 + Contents .head 3 + ActiveX: axInternetExplorer .head 4 - Class Child Ref Key: 0
As can be seen, the data block is not there, so it is lost in the copy/paste process.
This results in faulty IDE behaviour of the object (eg events are missing) or at runtime the object can not be created.
To solve this you need to manually copy/paste the missing data block from a working ActiveX object (same class) to the faulty object using notepad (or other text editor).
Copy the entire .data line up until .enddata line and place it right under the ActiveX:<<name>> line.
If done right, the newly copied ActiveX object will work like its original.
How to generate a GUID
Creating a GUID programatically can be done in two ways.
First, you may use the CDK for this.
See CDK : How to generate a GUID
Since TD is UNICODE-able, you may also call some of the OLE-APIs directly.
You have to import the following functions:
Library name: ole32.dll
Function: CoCreateGuid
Description: Creates a GUID, a unique 128-bit integer used for CLSIDs and interface identifiers.
*Returns: S_OK - The GUID was successfully created.
Export Ordinal: 0
Returns
Number: DWORD
Parameters
structPointer
Receive String: byte[16]
! Pointer to the requested GUID on return.
Function: StringFromGUID2
Description: Converts a globally unique identifier (GUID) into a string of printable characters.
*Returns: 0 (zero) - Array at lpsz is too small to contain a string representation of a GUID.
Non-zero value - The number of bytes (not characters) in the returned string, including the null terminator.
Export Ordinal: 0
Returns
Number: INT
Parameters
structPointer
String: byte[16]
! GUID to be converted.
Receive String: LPWSTR
! Pointer to a caller-allocated string variable to contain the resulting string on return.
Number: INT
! Number of characters available in the buffer indicated by lpsz.
After that, two simple calls give you a new GUID.
! Create a new GUID Call SalSetBufferLength( createdGUID, 16 ) ! a GUID has 16 bytes (= 128 bits) Call CoCreateGuid( createdGUID ) ! ! Transform to string Call SalSetBufferLength( createdGUIDString, 100 ) Call StringFromGUID2( createdGUID, createdGUIDString, 50 )
And that's it! Create new GUID with TD 5.2

