/ i "


Chem32S Reference




Prior Up




Introduction
New features
Events
Methods
Properties
Appendices
Index
Download now




Introduction

This control draws chemicals from .MOL and .RXN files. It can be used to communicate with certain chemical editors which do not conform to OLE standards. The control can also communicate with Modgraph Consultants' Ltd. mainframe hosted Structure Server, and be used to upload, download, search and analyse the large chemically-intelligent database.

The Chem32S control was written using Microsoft Foundation Classes (MFC) in Visual C++. It is designed for Windows NT 4.0 or later, but it has not been tested under Windows 95/98, Windows CE or any version Windows 2000.

The control supports many Events, Methods and Properties including most of the standard MFC ones. In order to work effectively with existing chemical editors, the control supports Dynamic Data Exchange (DDE), both as client and server. It can also launch and manipulate executables. This enables your applications to, for example, launch an editor and exchange information with it.

Because it can be used to launch other programs, this control should not be used on Web pages.




New

Version 1.4.26 can display RXN files, introducing the following:


Versions 1.1.17 to 1.3.25 fixed bugs.


Version 1.1.16 introduces developer licensing. Developers who wish to build applications with this control should purchase a copy of the license file and keep it in the same directory as they keep the control.


Version 1.1.15 introduced the following methods:

It also fixed the following bugs:


Version 1.1.14 of the control fixed a couple of minor bugs which caused Visual Basic indigestion when daft values where fed to some of the control's floating point properties.


The following have been introduced with version 1.1.13 of the control:


The following have been introduced with version 1.1.12 of the control:


The following have been introduced with version 1.1.11 of the control:


The following have been introduced with version 1.1.10 of the control:


The following have been introduced with version 1.1.9 of the control:


The following have been introduced with version 1.1.8 of the control:


The following have been introduced with version 1.1.7 of the control:




Events

Introduction

Standard events supported by this control are Click, DblClick, Error, KeyDown, KeyPress, KeyUp, MouseDown, MouseMove and MouseUp . The precise behaviour of the Error event is controlled by the FireError Property.

The control supports the following additional events:

See Methods, Properties, return to Developer's Reference, or the top of this document.



DDECommand Event

The DDECommand event occurs when a command is received by the control's DDE Server.

void DDECommand(BSTR lpszService, BSTR lpszTopic, BSTR lpszCommand);

The parameters reflect the service, topic and command that have been received by the control.

Before the control can receive a DDE command, your application must prepare the ground, by at least initialising the DDEService property and using the DDEAddTopic method.

See DDEService, DDEAddTopic, DDEDeleteTopic, DDEGetTopic, return to Events, Developer's Reference, or the top of this document.




Methods

In this section, information is arranged into:

The following methods are supported by this control:

See Events, Properties, return to Developer's Reference, or the top of this document.



Error Codes

Functions can return any of the following error codes:

These codes are currently defined as follows:

#define OCX_ERROR -1000

#define OCXERR_WINDOWS (OCX_ERROR - 0)
#define OCXERR_RESOURCE (OCX_ERROR - 1)
#define OCXERR_BADPARAM (OCX_ERROR - 2)
#define OCXERR_NODLL (OCX_ERROR - 3)
#define OCXERR_LOCKMEM (OCX_ERROR - 4)
#define OCXERR_TEXTOUT (OCX_ERROR - 5)
#define OCXERR_BADMOLFILE (OCX_ERROR - 6)
#define OCXERR_ALLOCMEM (OCX_ERROR - 7)
#define OCXERR_OPENFILE (OCX_ERROR - 8)
#define OCXERR_READ (OCX_ERROR - 9)
#define OCXERR_BADFONT (OCX_ERROR -10)
#define OCXERR_NODATA (OCX_ERROR -11)
#define OCXERR_NOSUCHRESULT (OCX_ERROR -12)
#define OCXERR_TESTVERSION (OCX_ERROR -13)
#define OCXERR_MOLFILETOOBIG (OCX_ERROR -14)
#define OCXERR_CREATEFILE (OCX_ERROR -15)
#define OCXERR_CLIPBOARD (OCX_ERROR -16)
#define OCXERR_SIZEMEM (OCX_ERROR -17)
#define OCXERR_WRITE (OCX_ERROR -18)
#define OCXERR_TYPE (OCX_ERROR -19)
#define OCXERR_DDE (OCX_ERROR -20)
#define OCXERR_TOOMANYXEQ (OCX_ERROR -21)
#define OCXERR_LAUNCH (OCX_ERROR -22)
#define OCXERR_READONLY (OCX_ERROR -23)
#define OCXERR_METAFILE (OCX_ERROR -24)
#define OCXERR_UNKNOWN (OCX_ERROR -25)
#define OCXERR_ARCHIVE (OCX_ERROR -26)
#define OCXERR_EOF (OCX_ERROR -27)
#define OCXERR_FORMAT (OCX_ERROR -28)
#define OCXERR_INTERNAL (OCX_ERROR -29)
#define OCXERR_BADRXNFILE (OCX_ERROR -30)
#define OCXERR_NOTENUFBITS (OCX_ERROR -31)


Chemical Methods

The methods discussed in this section are grouped together by a common theme of chemistry.

These functions are only valid when the data displayed by the control was successfully loaded using the LoadMolFile method, the MolFile property, or was Pasted in using the control's own clipboard format. Any attempt to use these functions on data pasted in using any other format will yield undefined results.



CalculateMF Method

The CalculateMF method calculates and returns the molecular formula of the current content of the control.

BSTR CalculateMF ();

To set the molecular formula passed to the server, use the MF property.

See the CalculateWeight method, MF and Weight properties, return to Methods, Developer's Reference, or the top of this document.



CalculateWeight Method

The CalculateWeight method calculates and returns the molecular weight of the current content of the control.

double CalculateWeight ();

To set the molecular weight passed to the server, use the Weight property.

See the CalculateMF method, MF and Weight properties, return to Methods, Developer's Reference, or the top of this document.



GetAtomData Method

The GetAtomData returns some information about a particular atom.

short GetAtomData (short nItem, short nAtom);

nItem identifies exactly which piece of data to obtain, and nAtom identifies the atom to examine (from the range of zero to one less than the atom count returned by GetCount). Any one of the following values, which correspond to value describing the atom in the .MOL file, may be supplied for nItem:

#define ATOM_MASSDIFF 1
#define ATOM_CHARGE 2
#define ATOM_STEREO 3
#define ATOM_HYDROGEN 4
#define ATOM_VALENCE 5
#define ATOM_HO 6
#define ATOM_ELEMENT 7
#define ATOM_INDEX 8
#define ATOM_REACTION_TYPE 9
#define ATOM_REACTION_NUMBER 10
#define ATOM_MAPPING 11
#define ATOM_INVERSION 12
#define ATOM_ISSTEREO 13
#define ATOM_ISFIXED 14

See the GetAtomPosition, GetBondData, and GetCount methods, return to Methods, Developer's Reference, or the top of this document.



GetAtomPosition Method

The GetAtomPosition returns the atom's coördinates, as specified in the .MOL file, not as currently drawn on the screen.

void GetAtomPosition (short nAtom, double* pdbX, double* pdbY, double* pdbZ);

nAtom is the atom number, which must be between zero and one less than the atom count returned by GetCount. Each of the remaining variables point to a double, which is used to receive the corresponding coördinate value.

See the GetAtomData, GetBondData, and GetCount methods, return to Methods, Developer's Reference, or the top of this document.



GetBondData Method

The GetBondData method returns information about a particular bond.

short GetBondData (short nItem, short nBond);

nItem identifies exactly which piece of data to obtain, and nBond identifies the bond to examine (from the range of zero to one less than the bond count returned by GetCount). Any one of the following values, which correspond to value describing the atom in the .MOL file, may be supplied for nItem:

#define BOND_FROM 1
#define BOND_TO 2
#define BOND_TYPE 3
#define BOND_STEREO 4
#define BOND_TOPOLOGY 5
#define BOND_SIDE 6
#define BOND_REACTION 7

See the GetAtomData, GetAtomPosition, and GetCount methods, return to Methods, Developer's Reference, or the top of this document.



GetCount Method

The GetCount returns the number of a particular type in the .MOL file.

BSTR GetCount ();

nItem identifies exactly which count of data to obtain. Any one of the following values, which correspond to a count found in the .MOL file, may be supplied for nItem:

#define COUNT_ATOM 1
#define COUNT_BOND 2
#define COUNT_LIST 3
#define COUNT_CHIRAL 4
#define COUNT_STEXT 5
#define COUNT_COMPONENT 6
#define COUNT_REACTANT 7
#define COUNT_PRODUCT 8
#define COUNT_INTERMEDIATE 9
#define COUNT_LINE 10

You will need to use this method to obtain the atom (COUNT_ATOM) or bond (COUNT_BOND) counts before using GetAtomData, GetAtomPosition, or GetBondData.

See the GetAtomData, GetAtomPosition, and GetBondData methods, return to Methods, Developer's Reference, or the top of this document.



GetRevision Method

The GetRevision returns the chemical's audit revision number.

int GetRevision ();

Each chemical on the server can have an audit number, reflecting the current revision of the data on the server for that chemical. A chemical that has not been submitted has revision number 0.

Return to Methods, Developer's Reference, or the top of this document.



LoadEnhMetaFile Method

The LoadEnhMetaFile method loads a metafile.

short LoadEnhMetaFile (BSTR lpszFile);

lpszFile is the full path name of the enhanced metafile to load. The function returns an error code.

This function is designed to make it simpler to store reactions on the system. The metafile will be displayed if there is nothing else to display, such as a .MOL file.

See the SaveEnhMetaFile method, check the control's error codes, return to Methods, Developer's Reference, or the top of this document.



LoadMolFile Method

The LoadMolFile method loads and interprets a .MOL file.

short LoadMolFile (BSTR lpszFile);

lpszFile is the full path name of the .MOL file to load. The function returns an error code. Please note the .MOL file should be in version 1 format, although this function can make some sense of version 2 format .MOL files. This function cannot read version 3 .MOL files.

See the SaveMolFile method, MolFile property, check the control's error codes, return to Methods, Developer's Reference, or the top of this document.



LoadRxnFile Method

The LoadRxnFile method loads and interprets an .RXN file.

short LoadRxnFile (BSTR lpszFile);

lpszFile is the full path name of the .RXN file to load. The function returns an error code. Please note the .MOL files contained within the .RXN file should be in version 1 format, although this function can make some sense of version 2 format .MOL files. This function cannot read version 3 .MOL files.

See the SaveRxnFile method, RxnFile property, check the control's error codes, return to Methods, Developer's Reference, or the top of this document.



LoadTGFFile Method

The LoadTGFFile method loads, but does not interpret, a .TGF file.

short LoadTGFFile (BSTR lpszFile);

lpszFile is the full path name of the .TGF file to load. The function returns an error code.

Loading a TGF file makes no change to the display. However, when a metafile is Pasted into the control, and subsequently submitted to the server, a TGF which has been loaded after the paste is also sent to the server. This means ASCII files in an editor-dependent format can be associated with a structure, and returned to the editor from the server via this control for subsequent modification.

See the SaveTGFFile method, check the control's error codes, return to Methods, Developer's Reference, or the top of this document.



SaveEnhMetaFile Method

The SaveEnhMetaFile writes an Enhanced Metafile file.

short SaveEnhMetaFile (BSTR lpszTGFFile);

lpszFileName is the full path name of the enhanced metafile file to be written. The function returns an error code.

Note this function simple writes out the enhanced metafile it previously loaded, pasted, or obtained from the server.

See the LoadEnhMetaFile and Pastemethods, check the control's error codes, return to Methods, Developer's Reference, or the top of this document.



SaveMolFile Method

The SaveMolFile writes a .MOL file.

short SaveMolFile (BSTR lpszMolFile, boolean bCreate);

lpszMolFile is the full path name of the .MOL file to create. If bCreate is false, then the file must already exist. The function returns an error code.

Note this function simple writes out the .MOL file it is currently displaying.

See the LoadMolFile and Pastemethods, the MolFile property, check the control's error codes, return to Methods, Developer's Reference, or the top of this document.



SaveRxnFile Method

The SaveRxnFile writes a .RXN file.

short SaveRxnFile (BSTR lpszRxnFile, boolean bCreate);

lpszRxnFile is the full path name of the .RXN file to create. If bCreate is false, then the file must already exist. The function returns an error code.

Note this function simple writes out the .RXN file it is currently displaying.

See the LoadRxnFile and the RxnFile property, check the control's error codes, return to Methods, Developer's Reference, or the top of this document.



SaveTGFFile Method

The SaveTGFFile writes a TGF file.

short SaveTGFFile (BSTR lpszTGFFile, boolean bCreate);

lpszTGFFile is the full path name of the .TGF file to create. If bCreate is false, then the file must already exist. The function returns an error code.

Note this function simple writes out the .TGF file it previously loaded, or obtained from the server.

See the LoadTGFFile and Pastemethods, check the control's error codes, return to Methods, Developer's Reference, or the top of this document.



Server Methods

All Server methods require a TCP/IP link with the Structure Server in order to operate correctly. Information shared with the server includes the .MOL file itself, and some header fields.

To communicate with the server, an application could do the following:

There methods may return server error codes, as well as the control's error codes. Server error codes are negative; server information may be positive - see the structure server documentation for further details.



ClearEntryNumber Method

The ClearEntryNumber method clears the database entry number in a structure. This should be done before submitted a modified structure as something new to the server.

void ClearEntryNumber ();

See the GetEntryNumber and SubmitStructure methods, return to Methods, Developer's Reference, or the top of this document.



ClearHeader Method

The ClearHeader method clears all fields in the header (e.g. all Server Properties).

void ClearHeader ();

See the Server Properties, return to Methods, Developer's Reference, or the top of this document.



Connect Method

The Connect method attempts to establish a connection with the server. It should be called before any other Server Methods.

short Connect (BSTR lpszIPAddress, BSTR lpszService);

The first parameter, lpszIPAddress, is a string containing the server's IP Address in one of the normal formats (such as 123.456.712.345:67 or abc.def.com:123), or the name of an entry in the system standard services file. When the services file is used, the second parameter identifies the service.

The function returns an error code, or zero if successful.

See the Disconnect method, return to Methods, Developer's Reference, or the top of this document.



Display Method

The Display method displays a chemical previously obtained using GetRange.

short Display (short nResult);

The single parameter, nResult, is a number between zero and the number of chemicals obtained using GetRange.

The function returns an error code, or zero if successful.

See the GetRange method, return to Methods, Developer's Reference, or the top of this document.



GetEntryNumber Method

The GetEntryNumber returns the currently displayed chemical's structure server entry number. Such a number is unique to a particular chemical, and can be used to rapidly locate it on the server.

long GetEntryNumber ();

The function returns an error code, or the (positive) entry number if successful.

See the ClearEntryNumber and GetRange method, return to Methods, Developer's Reference, or the top of this document.



GetQuantitySearchResults Method

The GetQuantitySearchResults returns the number of hits following a search.

long GetQuantitySearchResults ();

The function returns an error code, or the (positive) number of hits if successful (or zero if the search failed. It returns invalid information after a call to the SubmitStruct method.

See the SearchKey, SearchSimilar, SearchStruct or SubmitStruct methods, return to Methods, Developer's Reference, or the top of this document.



GetRange Method

The GetRange method is used after a successful search to download chemical information from the server.

short GetRange (short nFrom, short nTo);

The two parameters are the range of results to obtain, between 1 and the number of hits from a search (obtained by calling GetQuantitySearchResults).

The function returns an error code, or the (positive) number of chemicals downloaded if successful. The more chemicals downloaded, the longer the function takes.

See the Display, GetQuantitySearchResults, SearchKey, SearchSimilar or SearchStruct method, return to Methods, Developer's Reference, or the top of this document.



HasChanged Method

The HasChanged method returns true if a structure has changed since it was downloaded from the server.

bool HasChanged ();

Return to Methods, Developer's Reference, or the top of this document.



IsConnected Method

The IsConnected method returns true if the control is currently connected to the server (after a successful call to Connect method).

bool IsConnected ();

See the Connect method, return to Methods, Developer's Reference, or the top of this document.



IsLoggedOn Method

The IsLoggedOn method returns true if the control is currently logged on to the server (after a successful call to Login method).

bool IsLoggedOn ();

See the Login method, return to Methods, Developer's Reference, or the top of this document.



Login Method

The Login method logs the given user into the server.

short Login (BSTR lpszUser, BSTR lpszPassword);

The supplier lpszUser and lpszPassword must have been registered on the server (using server utilities) for this function to succeed. No server methods, apart from Connect and Disonnect can succeed unless this method has been used successfully.

The function returns zero if successful, or a negative error number.

See the Connect, Disonnect and Logout methods, return to Methods, Developer's Reference, or the top of this document.



Logout Method

The Logout method logs the user off the server.

short Logout ();

The method should only be called if the user successfully logged on to the server using Login, before Disconnecting.

The function returns zero if successful, or a negative error number.

See the Disonnect and Login methods, return to Methods, Developer's Reference, or the top of this document.



SearchKey Method

The SearchKey method instructs the structure server to search the database for the given key.

short SearchKey (short nSearch, BSTR lpszKey);

nSearch identifies the search to be carried out, and lpszKey is the key to be used in the search. nSearch can be one of the following values:

These constants are current defined as:

#define SEARCH_KEY 1
#define SEARCH_MF 2
#define SEARCH_ENTRYNO 3
#define SEARCH_AUDIT 4
#define SEARCH_SQL 8
#define SEARCH_EXP_NAME 9

The function returns the number of hits if successful, or a negative error number.

See the SearchSimilar, SearchStruct methods, return to Methods, Developer's Reference, or the top of this document.



SearchSimilar Method

The SearchSimilar method instructs the structure server to search the database for a structure which is similar to the one in the control.

short SearchSimilar(short nSearch, short nPercent);

nSearch identifies the search to be carried out, and nPercent identifies the degree of similarity required (100% implies identical, and 0% implies the entire database - not a good idea!). nSearch can be one of the following values:

These constants are current defined as:

#define SEARCH_SIMILAR 7

The function returns the number of hits if successful, or a negative error number.

See the SearchKey, SearchStruct methods, return to Methods, Developer's Reference, or the top of this document.



SearchStruct Method

The SearchStruct method instructs the structure server to search the database for the structure currently shown in the control.

short SearchStruct (short nSearch);

nSearch identifies the search to be carried out. It can be one of the following values:

These constants are current defined as:

#define SEARCH_FULLSTRUCT 5
#define SEARCH_SUBSTRUCT 6

The function returns the number of hits if successful, or a negative error number.

See the SearchKey, SearchSimilar methods, return to Methods, Developer's Reference, or the top of this document.



SubmitStruct Method

The SubmitStruct method sends the structure contained in the control to the server.

short SubmitStruct (BSTR lpszKey);

lpszKey should be empty if the structure is completely new. It should be an existing key if data in the control is of modification to an existing structure. The server takes this information on advice.

The function returns zero if successful, or a negative error number. You should not call GetQuantitySearchResults after this method before another search, since this method invalidates that information.

See the GetQuantitySearchResults method, return to Methods, Developer's Reference, or the top of this document.



Standard Methods

The control includes a number of methods which support standard Windows activities.



AboutBox Method

The AboutBox method displays a copyright dialogue.

HRESULT AboutBox ();

Return to Methods, Developer's Reference, or the top of this document.



CanCopy Method

The CanCopy method indicates whether the control can copy it's current content to the clipboard.

boolean CanCopy ();

The function returns true if a copy is possible.

See the CanCut, CanPaste, Copy, Cut, and Paste methods, return to Methods, Developer's Reference, or the top of this document.



CanCut Method

The CanCut method indicates whether the control can cut it's current content to the clipboard.

boolean CanCut ();

The function returns true if a cut is possible. The only difference between this and the CanCopy is that this method will return false if the control is set to read only, whereas that method would return true.

See the CanCopy, CanPaste, Copy, Cut, and Paste methods, return to Methods, Developer's Reference, or the top of this document.



CanPaste Method

The CanPaste method indicates whether the control can paste its current content of the clipboard.

boolean CanPaste();

The function returns true if a copy is possible. Note that the control will happily paste a metafile, a bitmap, or its own Chemical control data. It cannot (yet) paste a Sketch file.

See the CanCopy, CanCut, Copy, Cut, and Paste methods, return to Methods, Developer's Reference, or the top of this document.



Clear Method

The Clear method empties the control.

void Clear ();

Return to Methods, Developer's Reference, or the top of this document.



Copy Method

The Copy method copies its content to the clipboard.

boolean Copy();

The control puts its content on the clipboard as a bitmap, and in its own Chemical control format. It returns true if successful.

See the CanCopy, CanCut, CanPaste, Cut, and Paste methods, return to Methods, Developer's Reference, or the top of this document.



Cut Method

The Cut method cuts its content to the clipboard.

boolean Cut();

The control puts its content on the clipboard as a bitmap, and in its own Chemical control format. It returns true if successful.

See the CanCopy, CanCut, CanPaste, Copy, and Paste methods, return to Methods, Developer's Reference, or the top of this document.



DoProperties Method

The DoProperties method displays the control's Property sheet.

void DoProperties ();

Return to Methods, Developer's Reference, or the top of this document.



Paste Method

The Paste pastes the content of the clipboard into the control.

boolean Paste ();

The appropriate data type is selected from the clipboard in the following order:

The plain drawing options for paste are provided to enable the developer to display sophisticated chemical information, such as reactions, which have been prepared in an application such as ISIS/Draw, and which need to be displayed elsewhere. Any attempt to use any of the chemical methods after pasting a metafile or bitmap into the control will yield undefined results.

The control returns true if successful.

See the CanCopy, CanCut, CanPaste, Copy, and Cut methods, return to Methods, Developer's Reference, or the top of this document.



Refresh Method

The Refresh method redraws the control's content.

void Refresh();

Return to Methods, Developer's Reference, or the top of this document.



DDE Methods

The control includes DDE functionality to permit communication with non-OLE compliant chemical editing applications, such as ISIS/Draw. These functions, and the executable methods, enable a developer to simulate OLE by supporting double-clicking on a chemical to run up ISIS/Draw and let the user edit a .MOL file - although this also requires some ISIS/Draw PL macro programming.

Future version of this control may drop these functions - see the DDE Wrap controls.

The DDEService property must be set before any of these methods are used.



DDEAddTopic Method

The DDEAddTopic method adds the specified topic to the list of those accepted by the control's DDE server.

short DDEAddTopic (BSTR lpszTopic);

lpszTopic is the name of the topic to add to the server. The method returns a handle to the topic if successful, or -1 on failure.

The DDE server must have previously been successfully initialised by assigning a value to the DDEService property. Once a topic has been added, a DDECommand event may occur when an external application uses that topic to communicate with the control.

See DDECommand, DDEDeleteTopic, DDEGetTopic, or DDEService, return to Methods, the Developer's Reference, or the top of this document.



DDEConversationCommand Method

The DDEConversationCommand method issues a command to a DDE server.

long DDEConversationCommand (BSTR lpszCommand);

lpszCommand is command to issue to the server. The method returns a value from the server.

The DDE conversation must have been successfully initialised by an earlier call to DDEConversationStart.

See DDEConversationEnd, DDEConversationStart, DDEInUse, DDEService, or DDEXeq, return to Methods, the Developer's Reference, or the top of this document.



DDEConversationEnd Method

The DDEConversationEnd method ends a conversation with a DDE server.

short DDEConversationEnd ();

The DDE conversation must have been successfully initialised by an earlier call to DDEConversationStart.

See DDEConversationCommand, DDEConversationStart, DDEInUse, DDEService, or DDEXeq, return to Methods, the Developer's Reference, or the top of this document.



DDEConversationStart Method

The DDEConversationStart method starts a conversation with a DDE server.

short DDEConversationStart(BSTR lpszService, BSTR lpszTopic);

lpszService identifies the service with which the conversation is desired, and lpszTopic identifies the topic of discussion. The method returns -1 if DDE has not been initialise, 0 if conversation cannot be started for some reason, and 1 if the conversation is successfully started.

DDE can only be initialised by assigning a value to the DDEService property.

See DDEConversationCommand, DDEConversationStart, DDEInUse, DDEService, or DDEXeq, return to Methods, the Developer's Reference, or the top of this document.



DDEDeleteTopic Method

The DDEDeleteTopic method removes the specified topic to the list of those accepted by the control's DDE server.

short DDEDeleteTopic(short nTopic);

nTopic is the value identifying the topic, previously returned by DDEAddTopic. The method returns 0 if successful, and -1 if something went dreadfully wrong.

See DDECommand, DDEAddTopic, or DDEGetTopic, return to Methods, the Developer's Reference, or the top of this document.



DDEGetTopic Method

The DDEGetTopic method returns the name of the specified topic.

BSTR DDEGetTopic(short nTopic);

nTopic is the value identifying the topic, previously returned by DDEAddTopic. The method returns NULL if unsuccessful, or the name of the topic otherwise.

See DDECommand, DDEAddTopic, or DDEDeleteTopic, return to Methods, the Developer's Reference, or the top of this document.



DDEInUse Method

The DDEInUse method confirms whether or not the DDE server has been initialised.

boolean DDEInUse ();

The DDE server can be initialised by assigning a value to the DDEService property.

See DDEService, return to Methods, the Developer's Reference, or the top of this document.



DDEXeq

The DDEXeq method connects to a service, issues a command, and then disconnects from that service.

long DDEXeq(BSTR lpszService, BSTR lpszTopic, BSTR lpszCommand);

lpszService is the DDE server with which you wish to communicate, lpszTopic is the topic of the conversation, and lpszCommand is the single command you wish to issue.

This method is equivalent to calling DDEConversationStart, DDEConversationCommand and DDEConversationEnd in sequence. The method returns -1 if it cannot successfully communicate with the server, and the return value of the command otherwise.

The DDE server can be initialised by assigning a value to the DDEService property.

See DDEConversationCommand, DDEConversationEnd, DDEConversationStart, DDEInUse, DDEService, or DDEXeq, return to Methods, the Developer's Reference, or the top of this document.



Executable Methods

The control includes DDE functionality to permit communication with non-OLE compliant chemical editing applications. These functions, and the DDE methods, enable a developer to simulate OLE by supporting double-clicking on a chemical to run up the editor and let the user edit a .MOL file - although this may require some macro programming in the editor.

Future version of this control may drop these functions - see the Execution Wrap control.



ExecutableClose

The ExecutableClose method sends a close message to an executable.

short ExecutableClose (short nExecutable);

nExecutable is the executable identifier returned by ExecutableLaunch.

If the executable has a number of windows, you should identify the key window using the ExecutableWindow property before you use this method.

Not all executable take any notice of instructions telling them to go away. You can check whether this is the case having used this method by having your program do the following:

See the ExecutableIsRunning, ExecutableLaunch, and ExecutablePredujiceTerminate methods, the ExecutableWindow property, return to Methods, the Developer's Reference, or the top of this document.



ExecutableGetLastError

The ExecutableGetLastError method returns the last system error which occurred as a consequence of using these methods.

long ExectuableGetLastError ();

You should use this function to determine the exact reason why at attempt to use the ExecutableLaunch method failed.

See the ExecutableLaunch method, return to Methods, the Developer's Reference, or the top of this document.



ExecutableHide

The ExecutableHide attempts to hide an executable's window;

void ExecutableHide(short nExecutable);

nExecutable is the executable identifier returned by ExecutableLaunch.

If the executable has a number of windows, you should identify the key window using the ExecutableWindow property before you use this method.

See the ExecutableLaunch, and ExecutableShow methods, the ExecutableWindow property, return to Methods, the Developer's Reference, or the top of this document.



ExecutableIsRunning

The ExecutableIsRunning checks to see if a previously launched executable is still running.

boolean ExecutableIsRunning (short nExecutable);

nExecutable is the executable identifier returned by ExecutableLaunch. The method returns true if the executable is still running.

See the ExecutableLaunch method, the ExecutableWindow property, return to Methods, the Developer's Reference, or the top of this document.



ExecutableLaunch

The ExecutableLaunch method attempts to run a program.

short ExecutableLaunch (BSTR lpszAppName, BSTR lpszCmdLine, BSTR lpszWindowTitle, short nShowWindow);

lpszAppName is a string containing the applications name. If the application is not on the path, you will may need to provide the full path. The method will enclose this parameter in quotes.

lpszCmdLine is a string containing the command line parameters to feed to the program.

lpszWindowTitle is a string containing the program's main window title. This is used by the control to identify which window is to be targeted by other methods, including ExecutableClose, ExecutableHide and ExecutableShow. If this string is omitted, or the program does not launch with a window with this title, then control will attempt to identify an appropriate window. You can also provide this information using the ExecutableWindow property.

nShowWindow is a standard windows parameter identifying how the new applications window is to appear upon launch. This value corresponds to that fed to the standard windows API call ShowWindow - see that call's documentation for further information.

If successful, the method returns zero or a positive number as an executable identifier, which is used by other Executable methods and properties. If the function fails, it returns one of the following error codes:

See the ExecutableClose, ExecutableGetLastError, ExecutableHide, ExecutableIsRunning, ExecutablePredujiceTerminate, ExecutableReuse, and ExecutableShow methods, the ExecutableWindow property, error codes, return to Methods, the Developer's Reference, or the top of this document.



ExecutablePredujiceTerminate

The ExecutablePredujiceTerminate kills a previously launched application.

short ExecutablePrejudiceTerminate(short nExecutable);

nExecutable is the executable identifier returned by ExecutableLaunch.

For a discussion on when to use this method, see the ExecutableClose.

Be warned: killing an application is dangerous and should only be done in the last resort. If you do this, there is a danger that work in progress will not be saved, and it is quite possible for the applications files to become corrupt. Do not use this function unless you have to.

See the ExecutableClose, ExecutableIsRunning, and ExecutableLaunch methods, the ExecutableWindow property, return to Methods, the Developer's Reference, or the top of this document.



ExecutablePostMessage

The ExecutablePostMessage posts an application message to the executable.

short ExecutablePostMessage (short nExecutable, short nMessage, long wParam, long lParam);

nExecutable is the executable identifier returned by ExecutableLaunch. The remaining three paramaters are standard parameters - see your Windows documentation on PostAppMessage. If you want to post a message to the executable's window, use ExecutablePostWndMessage.

See the ExecutablePostWndMessage method, return to Methods, the Developer's Reference, or the top of this document.



ExecutablePostWndMessage

The ExecutablePostWndMessage posts a message to an application's main window.

short ExecutablePostWndMessage (short nExecutable, short nMessage, long wParam, long lParam, boolean bAll);

nExecutable is the executable identifier returned by ExecutableLaunch. The next three parameters are the usual message parameters - see your Windows documentation on PostMessage. The final parameter indicates whether the message is sent to all windows associated with the application, or simply the main one (see ExecutableLaunch and ExecutableWindowTitle). If you want to post a message to the executable's application queue, use ExecutablePostMessage.

See the ExecutableLaunch and ExecutablePostMessage methods, the ExecutablePostMessage property, return to Methods, the Developer's Reference, or the top of this document.



ExecutableReuse

The ExecutableReuse indicates that an executable's slot can be reused.

void ExecutableReuse (short nExecutable);

nExecutable is the executable identifier returned by ExecutableLaunch.

Once an application is launched, its identifier remains reserved for that application until this method is called to free it.

See the ExecutableLaunch methods, return to Methods, the Developer's Reference, or the top of this document.



ExecutableShow

The ExecutableShow method attempts to show a previously hidden executable's window;

void ExecutableShow (short nExecutable, boolean bMaximize);

nExecutable is the executable identifier returned by ExecutableLaunch. If bMaximixe is true, the window is shown maximised, otherwise it is shown normalised.

If the executable has a number of windows, you should identify the key window using the ExecutableWindow property before you use this method.

See the ExecutableHide, and ExecutableLaunch methods, the ExecutableWindow property, return to Methods, the Developer's Reference, or the top of this document.




Properties

These properties are designed to be set from calls in your applications code. None can be set using the standard property page. A number cannot be set using Visual Basic's property sheet. The next generation of this control will support these features.

This section is separated into standard properties, item properties, Server Properties (header properties) and other properties.

This control's non-standard properties are:



Standard Properties

The standard properties supported by this control are Appearance, BackColor, BorderStyle, ForeColor and hWnd . Developers should note the use of the American spelling of these names.



Item Properties

This section discusses the various item properties, which allow an application detailed control on the appearance of a chemical drawn in the control.

All these properties require an item number, which can be one of the following:

These item numbers are currently defined as follows:

#define ITEM_ISOTOPE 1
#define ITEM_SYMBOL 2
#define ITEM_CHARGE 3
#define ITEM_MULTIPLIER 4
#define ITEM_STRUCTURE 5
#define ITEM_COMPOUND 6
#define ITEM_BOND 7
#define ITEM_CARBON 8
#define ITEM_HYDROGEN 9
#define ITEM_CHIRAL 10
#define ITEM_PLUS 11
#define ITEM_ARROW 12


ItemColour

The ItemColour property specifies the colour used to draw the item.

OLE_COLOUR ItemColour (short nItem);

See item properties for details of the possible value of nItem.

See item properties, return to Properties, the Developer's Reference, or the top of this document.



ItemDrawn

The ItemDrawn property determines whether an item is drawn or not.

short Drawn (short nItem);

If this property is non-zero, the item is drawn. The ItemPosition property can also be used to prevent an item appearing.

The Chiral text is only drawn when both this property is set appropriately, and the Chiral property is set.

See the Chiral and ItemPosition properties, item properties, return to Properties, the Developer's Reference, or the top of this document.



ItemFont

The ItemFont property specifies the name of the font used to display a text item.

BSTR ItemFont (short nItem)

See item properties for details of the possible value of nItem. Text items include ITEM_CARBON ITEM_CHARGE, ITEM_CHIRAL, ITEM_COMPOUND, ITEM_HYDROGEN. ITEM_MULTIPLIER, ITEM_ISOTOPE, ITEM_STRUCTURE, ITEM_SYMBOL and ITEM_PLUS. What happens when the font is not available on the user's system is undefined.

See item properties, return to Properties, the Developer's Reference, or the top of this document.



ItemSize

The ItemSize property determines the relative size of an item.

double ItemSize (short nItem);

See item properties for details of the possible value of nItem. The relationship used to determine the size depends on the item, as follows:

See item properties, return to Properties, the Developer's Reference, or the top of this document.



ItemOffset

The ItemOffset property determines the relative offset of certain items.

double ItemOffset (short nItem);

See item properties for details of the possible value of nItem. The relationship used to determine the size depends on the item, as follows:

See item properties, return to Properties, the Developer's Reference, or the top of this document.



ItemPosition

The ItemPosition property determines the relative position of certain items.

short ItemPosition (short nItem);

See item properties for details of the possible value of nItem. The relationship used to determine the size depends on the item.

For the text items ITEM_CHIRAL, ITEM_COMPOUND and ITEM_STRUCTURE, nItem has the following possible values:

For the items ITEM_SYMBOL, ITEM_CARBON and ITEM_HYDROGEN, nItem has the following possible values:

See the ItemDrawn property, item properties, return to Properties, the Developer's Reference, or the top of this document.



Server Properties

This section discuss properties which only have meaning when control is connected to the structure server. Certain properties, such as creation and modification information, are ignored when returned to the server. These properties accompany the .MOL file in a header when sent to and from the server.



CompoundNumber

The CompoundNumber property identifies the structure's compound number. This is the number that is the subject of the SEARCH_KEY SearchKey search.

BSTR CompoundNumber;

Return to Properties, the Developer's Reference, or the top of this document.



CreateDate

The CreateDate property identifies the date on which the structure was created.

BSTR CreateDate;

See the CreateUser and ModUser properties, return to Properties, the Developer's Reference, or the top of this document.



CreateUser

The CreateUser property identifies the user who created the structure.

BSTR CreateUser;

See the CreateDate and ModUser properties, return to Properties, the Developer's Reference, or the top of this document.



DataType

For a description of the DataType property, see the server documentation.

short DataTyp;

Return to Properties, the Developer's Reference, or the top of this document.



ExperimentName

The ExperimentName property specifies a short piece of text, which may be the subject of a search on the server.

BSTR ExperimentName;

See the SearchKey property, return to Properties, the Developer's Reference, or the top of this document.



MF

The MF property contains the chemical's molecular formula.

BSTR MF;

The MF can be calculated using the CalculateMF method.

See the Weight property, the CalculateMF method, return to Properties, the Developer's Reference, or the top of this document.



ModUser

The ModUser property identifies the last user to modify the structure. The property includes both the user, and the date of modification.

BSTR ModUser;

See the CreateUser and CreateDate properties, return to Properties, the Developer's Reference, or the top of this document.



StructureComment

The StructureComment property specifies a piece of text which is associated with the control. It is not drawn.

BSTR StructureComment;

See the StructureId and TestId properties, return to Properties, the Developer's Reference, or the top of this document.



StructureId

The StructureId property specifies a short piece of text which may be drawn in the control.

BSTR StructureId;

The property has been renamed from StructureText.

See the ItemColour, ItemFont, ItemOffset, ItemPosition, ItemSize, StructureComment, and TestId properties, return to Properties, the Developer's Reference, or the top of this document.



StructureType

The StructureType property identifies the structure type (!) - see the structure server documentation for more information.

short StructureType;

Return to Properties, the Developer's Reference, or the top of this document.



TestId

The TestId property specifies a number which is associated with the control. It is not drawn.

long TestId;

See the CompoundNumber, ItemColour, ItemFont, ItemOffset, ItemPosition, ItemSize, StructureComment, and StructureId properties, return to Properties, the Developer's Reference, or the top of this document.



VersionString

The VersionString property returns version information about the control, the application, and the structure server used to submit the current chemical to the server (before version 1.0.9 of the control, it returned the current versions of the server, control, and application).

BSTR VersionString (short nObject);

The purpose of the version method is to enable the application developer to check the correct versions of software are running when the application starts, and to enable the database administrator to identify items of data which have been added to the database from software subsequently found to be buggy, to assist maintenance of database integrity.

The application can only set the version number for itself.

nObject can be any one of the following:

These identifies are currently defined as follows:

#define VERSION_APP 1
#define VERSION_ACTIVEX 2
#define VERSION_SERVER 4
#define VERSION_MOLFILE 5

Return to Methods, Developer's Reference, or the top of this document.



Weight

The Weight property contains the chemical's molecular weight.

double Weight;

The Weight can be calculated using the CalculateWeight method.

See the MF property, the CalculateWeight method, return to Properties, the Developer's Reference, or the top of this document.



Other Properties

This section discusses the remaining properties found in the control.



ArrowThickness

The ArrowThickness property specifies the thickness, in pixels, of the reaction arrow, when drawn;

short ArrowThickness

If the thickness is zero, the arrow is drawn as thinly as possible.

Return to Properties, the Developer's Reference, or the top of this document.



BondThickness

The BondThickness property specifies the thickness, in pixels, of the bonds when drawn;

short BondThickness

If the thickness is zero, the bond is drawn as thin as possible.

See the DoubleDistance property, return to Properties, the Developer's Reference, or the top of this document.



Chiral

The Chiral property specifies whether the chemical currently on display is marked as chiral.

BOOL Chiral;

Some appropriate text can be displayed according to ChiralText property.

Note that this property only affects the way the chemical is displayed in the control; it does not affect the chiral flag in the underlying .MOL file. As a result, changing this property will not affect the information sent to the server.

See the ChiralText property, return to Properties, the Developer's Reference, or the top of this document.



ChiralText

The ChiralText specifies the text which may be displayed when a chemical on display is chiral.

BSTR ChiralText;

The default value of this property is "Chiral". It will only be displayed when the Chiral property is set, and the item properties are given appropriate values.

See the Chiral, ItemColour, ItemDrawn, ItemFont, ItemOffset, ItemPosition, ItemSize properties, return to Properties, the Developer's Reference, or the top of this document.



DDEService

The DDEService property specifies the name of the service offered by the control using Dynamic Data Exchange;

BSTR DDEService;

If you are unfamiliar with Dynamic Data Exchange, then you should familiarise yourself with the concepts behind it before you use the control's DDE methods and properties. This control offers a DDE service and DDE client functionality, but only supports conversations and commands.

This property must be set before you use any of the controls DDE methods, even if you only want to act as a DDE client.

See DDE Methods, the DDE Timeout property, return to Properties, the Developer's Reference, or the top of this document.



DDETimeout

The DDETimeout property specifies the maximum time, in milliseconds, to wait for a DDE Server to respond when using the DDE client methods.

long DDETimeout;

If this number is zero, then there is no time limit.

See DDE Methods, the DDE Service property, return to Properties, the Developer's Reference, or the top of this document.



DoubleDistance

The DoubleDistance property specifies the relative space between lines in double and triple bonds.

double DoubleDistance;

This value is calculated relative to the average bond length of bonds drawn in the compound. Thus a double distance of 1.0 implies the lines are separated by the average bond length, which is probably a little excessive. The default distance is 0.15.

See the BondThickness property, return to Properties, the Developer's Reference, or the top of this document.



ExecutableWindowTitle

The ExecutableWindowTitle property identifies the name of the primary window of an executable.

BSTR ExecutableWindowTitle;

Please see ExecutableLaunch method for details of this property.

See the ExecutableLaunch method, Executable methods, return to Properties, the Developer's Reference, or the top of this document.



FireError

The FireError property indicated how errors are to be processed.

bool FireError;

If FireError is set to false (the default), errors are returned with function parameters. If it is set to TRUE, errors are raised as exceptions, as preferred by OLE. Note that certain system errors are always raised as exceptions.

Return to Properties, the Developer's Reference, or the top of this document.



Margin

The Margin property specifies the relative quantity of white space between the chemical being drawn and the edge of the control.

double Margin(boolean bHorizontal);

bHorizontal is true for the horizontal margin, and false for the vertical.

The Margin value is a percentage, with 100 representing nothing but white space, and zero representing no margin. You should always ensure you have some margin when drawing a .MOL file, because coördinates of atoms are specify the centre of the atom. The default value of both margins is 80.0.

See the ExecutableLaunch method, Executable methods, return to Properties, the Developer's Reference, or the top of this document.



MolFile

The MolFile property contains the content of the currently displayed .MOL file.

void MolFile(BSTR lpszMolFile);

If you set this property, you will change the chemical being displayed. You can load a file directly by using the LoadMolFile method.

See the LoadMolFile and SaveMolFile methods, return to Properties, the Developer's Reference, or the top of this document.



ReadOnly

The ReadOnly property can be used to prevent changes being made to the control.

bool ReadOnly;

When the control is set to ReadOnly, then neither Cut, LoadMolFile nor LoadRxnFile nor Paste work. You can still Clear the content of the control.

See the ExecutableLaunch method, Executable methods, return to Properties, the Developer's Reference, or the top of this document.



RxnFile

The RxnFile property contains the content of the currently displayed .RXN file.

void RxnFile(BSTR lpszRxnFile);

If you set this property, you will change the chemical being displayed. You can load a file directly by using the LoadRxnFile method.

See the LoadRxnFile and SaveRxnFile methods, return to Properties, the Developer's Reference, or the top of this document.



Zoom

The Zoom indicates by how much the displayed has been zoomed in.

double Zoom;

If Zoom is set to 1.0, no zooming is occuring. Numbers larger than 1.0 show the display is zoomed in. Numbers less than 1.0 are invalid.

Return to Properties, the Developer's Reference, or the top of this document.




Appendices

These appendices document some of the chemical assumptions made by the control.

Appendix 1 - Atomic Symbols




Appendix 1 - Symbols and Isotopes

This table specifies which atomic symbols, the atomic number, and the molecular weight used by the control.

"Ac", 89, 227.00000
"Ag", 47, 107.86800
"Al", 13, 26.98150
"Am", 95, 243.00000
"Ar", 18, 39.94800
"As", 33, 74.92100
"At", 85, 210.00000
"Au", 79, 196.96700
"B", 5, 10.81100
"Ba", 56, 137.34000
"Be", 4, 9.01220
"Bi", 83, 208.98000
"Bk", 97, 247.00000
"Br", 35, 79.90400
"C", 6, 12.01115
"Ca", 20, 40.08000
"Cd", 48, 112.40000
"Ce", 58, 140.12000
"Cf", 98, 251.00000
"Cl", 17, 35.45300
"Cm", 96, 247.00000
"Co", 27, 58.93800
"Cr", 24, 51.99600
"Cs", 55, 132.90500
"Cu", 29, 63.54600
"Dy", 66, 162.50000
"Er", 68, 167.25999
"Es", 99, 254.00000
"Eu", 63, 151.96001
"F", 9, 18.99840
"Fe", 26, 55.84700
"Fm", 100, 257.00000
"Fr", 87, 223.00000
"Ga", 31, 69.72000
"Gd", 64, 157.25000
"Ge", 32, 72.59000
"H", 1, 1.00797
"He", 2, 4.00260
"Hf", 72, 178.49001
"Hg", 80, 200.59000
"Ho", 67, 164.92999
"I", 53, 126.90440
"In", 49, 114.82000
"Ir", 77, 192.20000
"K", 19, 39.10200
"Kr", 36, 83.80000
"La", 57, 138.91000
"Li", 3, 6.93900
"Lr", 103, 256.00000
"Lu", 71, 174.97000
"Md", 101, 258.00000
"Mg", 12, 24.30500
"Mn", 25, 54.93800
"Mo", 42, 95.94000
"N", 7, 14.00670
"Na", 11, 22.98980
"Nb", 41, 92.90600
"Nd", 60, 144.24001
"Ne", 10, 20.17900
"Ni", 28, 58.71000
"No", 102, 259.00000
"Np", 93, 237.00000
"O", 8, 15.99940
"Os", 76, 190.20000
"P", 15, 30.97380
"Pa", 91, 231.00000
"Pb", 82, 207.19000
"Pd", 46, 106.40000
"Pm", 61, 147.00000
"Po", 84, 210.00000
"Pr", 59, 140.90700
"Pt", 78, 195.09000
"Pu", 94, 242.00000
"Ra", 88, 226.00000
"Rb", 37, 85.47000
"Re", 75, 186.20000
"Rh", 45, 102.90500
"Rn", 86, 222.00000
"Ru", 44, 101.07000
"S", 16, 32.06400
"Sb", 51, 121.75000
"Sc", 21, 44.96500
"Se", 34, 78.96000
"Si", 14, 28.08600
"Sm", 62, 150.35001
"Sn", 50, 118.69000
"Sr", 38, 87.62000
"Ta", 73, 180.94800
"Tb", 65, 158.92400
"Tc", 43, 98.90620
"Te", 52, 127.60000
"Th", 90, 232.03799
"Ti", 22, 47.90000
"Tl", 81, 204.37000
"Tm", 69, 168.93401
"U", 92, 238.03000
"V", 23, 50.94200
"W", 74, 183.85001
"Xe", 54, 131.30000
"Y", 39, 88.90500
"Yb", 70, 173.03999
"Zn", 30, 65.37000
"Zr", 40, 91.22000



Index

AboutBox method
Appearance property
Appendices
ArrowThickness property
ATOM_...
Atomic Symbols
BackColor property
BOND_...
BondThickness property
BorderStyle property
CalculateMF method
CalculateWeight method
CanCopy method
CanCut method
CanPaste method
Chemical Methods
Chiral property
ChiralText property
ClearEntryNumber method
ClearHeader method
Click event
Clear method
CompoundNumber property
Connect method
Copy method
CreateDate property
CreateUser property
COUNT_...
Cut method
DataType property
DblClick event
DDE Methods
DDEAddTopic method
DDECommand event
DDEConversationCommand method
DDEConversationStart method
DDEConversationEnd method
DDEDeleteTopic method
DDEGetTopic method
DDEInUse method
DDEService property
DDETimeout property
DDEXeq method
Display method
DoProperties method
DoubleDistance property
Error Codes
Events
Executable Methods
ExecutableClose method
ExecutableGetLastError method
ExecutableHide method
ExecutableIsRunning method
ExecutableLaunch method
ExecutablePostMessage method
ExecutablePostWndMessage method
ExecutablePredujiceTerminate method
ExecutableReuse method
ExecutableShow method
ExecutableWindowTitle property
ExperimentName property
FireError property
ForeColor property
GetAtomData method
GetAtomPosition method
GetBondData method
GetCount method
GetEntryNumber method
GetRevision method
GetQuantitySearchResults method
GetRange method
HasChanged method
hWnd property
Introduction
IsConnected method
IsLoggedOn method
Item Properties
ITEM_...
ItemColour property
ItemDrawn property
ItemFont property
ItemOffset property
ItemPosition property
ItemSize property
KeyDown event
KeyPress event
KeyUp event
LoadEnhMetaFile method
LoadMolFile method
LoadRxnFile method
LoadTGFFile method
Login method
Logout method
Margin property
Methods
MF property
ModUser property
MolFile property
MouseDown event
MouseMove event
MouseUp event
OCXERR_...
Other Properties
Paste method
Properties
ReadOnly property
Refresh method
RxnFile property
SaveEnhMetaFile method
SaveMolFile method
SaveRxnFile method
SaveTGFFile method
Server method
Server Properties
SearchKey method
SearchSimilar method
SearchStruct method
Standard Methods
Standard Properties
StructureComment property
StructureId property
StructureText property
StructureType property
SubmitStruct method
Symbols
TestId property
Top of document
Valencies
VersionString property
Weight property
Zoom property





Back to the top.





Version 1.4.26, 23rd June 1999
The Chem32S control, and this documentation, is (c) 1998-2000 Modgraph Consultants Inc. and Cyberspace Services Ltd..


cyberspace services limited has ceased trading
this archive is hosted by arts & ego
© 1978-2024 dylan harris