Initial Commit
This commit is contained in:
736
database/MercuryMail/RESOURCE/winpmdde.txt
Normal file
736
database/MercuryMail/RESOURCE/winpmdde.txt
Normal file
@@ -0,0 +1,736 @@
|
||||
Pegasus Mail for Windows DDE (Dynamic Data Exchange) Interface
|
||||
Copyright (c) 1997-1999, David Harris, All Rights Reserved.
|
||||
----------------------------------------------------------------
|
||||
|
||||
Revision history:
|
||||
* WinPMail v3.11: added IDENTITY and VOLATILE keywords to MESSAGE topic.
|
||||
* WinPMail v3.12: added RICHTEXT keyword to MESSAGE topic, and STATUS
|
||||
keyword to ENVIRONMENT topic
|
||||
|
||||
Pegasus Mail v2.54 and later incorporates support for Windows DDE to allow
|
||||
interprocess communication. This document describes the topics supported by
|
||||
WinPMail and the syntax of the commands sent to them. It is not a tutorial
|
||||
on DDE, and assumes that you either understand how to use DDE, or are using
|
||||
an environment (such as Microsoft Word's WordBasic language) that
|
||||
simplifies the process of using DDE commands.
|
||||
|
||||
One of the most powerful features of DDE is that it allows transparent
|
||||
communication between 16-bit and 32-bit applications: so, by using DDE, you
|
||||
can communicate with either the 16- or the 32-bit version of WinPMail
|
||||
without having to be worried about the differences between the two.
|
||||
|
||||
Pegasus Mail's DDE interface has been designed to be as simple to use as
|
||||
possible, and depends on simple strings for commands. It should be possible
|
||||
to use DDE to interact with Pegasus Mail from almost any environment.
|
||||
|
||||
|
||||
|
||||
Service and Topic Names
|
||||
-----------------------
|
||||
|
||||
Under DDE, a "service name" is the name of an application that can accept
|
||||
DDE connections: when you connect to a service application, you specify a
|
||||
particular set of commands or operations in which you are interested - this
|
||||
set of commands is known as a "topic". Pegasus Mail uses the service name
|
||||
"WinPMail" and exports the following topics:
|
||||
|
||||
"System" The standard DDE system topic
|
||||
"Environment" Accepts DDE Requests (transactions of type XTYP_REQUEST)
|
||||
and returns information about the environment of the
|
||||
running copy of WinPMail, such as directories and
|
||||
usernames.
|
||||
"Message" Accepts DDE Poke commands to create and send e-mail
|
||||
messages. A DDE Client can either create and manipulate
|
||||
standard Pegasus Mail message editor windows, filling
|
||||
in whichever blanks are required, or it can create
|
||||
messages without a window.
|
||||
"TCP" Provides access via DDE Poke commands to WinPMail's
|
||||
TCP/IP-based mail services.
|
||||
|
||||
|
||||
|
||||
The "Environment" topic
|
||||
-----------------------
|
||||
|
||||
The "Environment" DDE topic allows client applications to obtain
|
||||
information about the running copy of Pegasus Mail. To use this command,
|
||||
send a DDE Request command (a transaction of type XTYP_REQUEST) the the
|
||||
"Environment" topic with the "item" parameter set to the environment item
|
||||
you wish to retrieve, selected from the following list:
|
||||
|
||||
USER - Returns the name of the user running WinPMail
|
||||
HOMEBOX - Returns the full path to the user's home mail directory
|
||||
NEWBOX - Returns the full path to the user's new mail directory
|
||||
MODE - Returns either "Standalone" or "Network"
|
||||
VERSION - Returns the version of WinPMail, expressed as a four
|
||||
digit hexadecimal number ("0254" for v2.54) followed
|
||||
by a space and either "16" or "32" to indicate the
|
||||
version of WinPMail that is running.
|
||||
BASEDIR - The directory from which WinPMail was run
|
||||
TCP - If WinPMail's TCP/IP services are available, returns
|
||||
the path to the WINSOCK.DLL in use, otherwise returns
|
||||
the single character "N".
|
||||
NEWMAIL - Returns the number of mail messages in the user's new
|
||||
mail folder.
|
||||
STATUS - Returns the status of the last mail delivery operation
|
||||
|
||||
-- Example: -----------------------------------
|
||||
|
||||
In WordBasic (MS-Word 7) the following Macro opens a connection to
|
||||
WinPMail, retrieves the current version, and displays it:
|
||||
|
||||
Sub MAIN
|
||||
channel = DDEInitiate("WinPMail", "Environment")
|
||||
a$ = DDERequest$(channel, "version")
|
||||
DDETerminate channel
|
||||
MsgBox a$
|
||||
End Sub
|
||||
|
||||
A longer example in C is shown as Appendix A: in this document.
|
||||
|
||||
|
||||
|
||||
The "Message" topic
|
||||
-------------------
|
||||
|
||||
Client applications use the "Message" topic to create and send electronic
|
||||
mail messages using WinPMail. Once a connection has been established to the
|
||||
"Message" topic, the client Pokes data at WinPMail (using XTYP_POKE
|
||||
transactions). The string parameter in the Poke command should be set to
|
||||
"Message" - other values may be added in future. The data itself contains
|
||||
the commands and parameters.
|
||||
|
||||
The following commands can be Poked as data to WinPMail:
|
||||
|
||||
New : <"Message"> or <"Window">
|
||||
If the parameter is "Window", then WinPMail creates a standard
|
||||
message editing window, and subsequent message commands will change
|
||||
the controls and settings in that window. If the parameter is
|
||||
"Message", then a data structure representing the message is
|
||||
allocated internally and subsequent message commands will fill in the
|
||||
fields within that structure.
|
||||
|
||||
Defaults : Y
|
||||
Tells WinPMail to apply the user's regular message setting default
|
||||
values to the message. This command is only valid when the
|
||||
"New: message" command has been sent - it has no effect on message
|
||||
editing windows created using "New: window", since they always use
|
||||
default values automatically.
|
||||
|
||||
To : <address> [, <address> ...]
|
||||
Fills in the "To" field for the message or window. The parameter may
|
||||
be any address WinPMail would normally accept, and you may include
|
||||
more than one address by separating them with commas. The same rules
|
||||
apply to the Cc: and Bcc: fields.
|
||||
|
||||
Cc : <address> [, <address> ...]
|
||||
Fills in the "Cc:" (Carbon Copy) field for the message.
|
||||
|
||||
Bcc : <address> [, <address> ...]
|
||||
Fills in the "Bcc:" (Blind Carbon Copy) field for the message.
|
||||
|
||||
Subject : <string>
|
||||
Fills in the subject field of the message.
|
||||
|
||||
Reply-to : <address>
|
||||
Sets the optional reply address for the message.
|
||||
|
||||
Copyself : <'Y'> or <'N'>
|
||||
Selects whether or not a copy-to-self should be made of the message.
|
||||
|
||||
Confirm-delivery : <'Y'> or <'N'>
|
||||
Selects whether or not to request confirmation of delivery
|
||||
|
||||
Confirm-reading : <'Y'> or <'N'>
|
||||
Selects whether or not to request confirmation of reading
|
||||
|
||||
Urgent : <'Y'> or <'N'>
|
||||
Selects whether or not the message should be marked as "urgent"
|
||||
|
||||
Encrypted : <encryptor-name><,><passphrase><,><flags>
|
||||
Chooses an encryption method for the message. "Encryptor-name" is
|
||||
the tagname of the encryptor you wish to use (use "PM-BUILTIN" to
|
||||
select Pegasus Mail's built-in encryptor). You can find the tagname
|
||||
for an encryptor in the "Form tagname" line of the encryptor's .FFF
|
||||
file. "passphrase" is the password for the message. If it contains
|
||||
a comma, then it must be quoted using " and ". "flags" is either
|
||||
1 to encrypt the message, 2 to sign the message, or 3 to encrypt
|
||||
and sign the message.
|
||||
|
||||
Signature : <number>
|
||||
Chooses the signature you wish to attach to the message. "number"
|
||||
is 1 - 9, corresponding to the signature sets shown in WinPMail's
|
||||
Tools | Signatures preferences page, or 0 to disable signatures.
|
||||
|
||||
Mime : <'Y'> or <'N'>
|
||||
Indicates whether or not MIME support should be turned on for
|
||||
this message. MIME support affects the way attachments and
|
||||
international characters are handled by WinPMail. We strongly
|
||||
recommend that you turn MIME on wherever possible.
|
||||
|
||||
Attach : <path><,><filename><,><attachment-type><,><encoding>
|
||||
Attach a file to the message. "path" should be the full path
|
||||
to the file - do not assume that the current directory in your
|
||||
client application will be the same as the current directory in
|
||||
Pegasus Mail. "filename" is the name Pegasus Mail should include
|
||||
in the message as the real name of the file (you will typically
|
||||
use this when you have to create a temporary file but want to
|
||||
send it under the original file's name). If "filename" is "-",
|
||||
WinPMail will automatically use the filename portion of "path".
|
||||
"attachment-type" should be textual information describing the
|
||||
attachment; it must not contain spaces. If you set this field to
|
||||
a single dash ("-"), WinPMail will use its internal routines to
|
||||
try to work out the most appropriate type information for the
|
||||
file. "encoding" is used to select the type of encoding for the
|
||||
attachment: we strongly recommend that you set this value to 0,
|
||||
which will allow WinPMail to choose the most appropriate encoding
|
||||
for you. Possible values are:
|
||||
0 - Pegasus Mail decides.
|
||||
1 - No encoding - the file is not altered (local mail only)
|
||||
2 - ASCII encoding - the file is normalised to CR/LF line
|
||||
endings and is not otherwise encoded in transit.
|
||||
3 - UUencoding - the file is uuencoded
|
||||
4 - BinHex - the file is transformed using the BinHex 4.0 method.
|
||||
5 - MIME - the file is transformed using the MIME BASE64 method.
|
||||
|
||||
File : <filename>
|
||||
Indicates the name of a file containing the text WinPMail should
|
||||
use as the body of the message. Note that this file is NOT an
|
||||
attachment - it is expected to be plain text.
|
||||
|
||||
Data : <String>
|
||||
Adds "string" to the body of the message as a single line. Poke
|
||||
this command repeatedly to build up a message line by line.
|
||||
WinPMail automatically adds the CR/LF termination to each line.
|
||||
Poking this command with no <string> parameter will print a blank
|
||||
line in the message (but the ':' must still be present).
|
||||
|
||||
Identity : <identity_name>
|
||||
Sets the identity Pegasus Mail should use when processing this
|
||||
message. For more information on Identities, see the Pegasus Mail
|
||||
help file. You can specify any valid identity name as the parameter
|
||||
to this command. The default is the user's current identity.
|
||||
|
||||
Volatile : <'Y'> or <'N'> (Default is 'Y')
|
||||
(Only meaningful when using Pegasus Mail's built-in SMTP mailer).
|
||||
Setting this flag to 'Y' tells Pegasus Mail that the message should
|
||||
be written straight into Final Form in the queue when it is sent.
|
||||
If you want your message to be reloadable from Pegasus Mail's
|
||||
"Review queued mail" option, you should set this to 'N'. If your
|
||||
message contains attachments that you plan to delete once the
|
||||
message has been sent, you must not set this field to 'N'.
|
||||
|
||||
Richtext : <'Y'> or <'N'> (Default is 'N')
|
||||
Set the "rich text" flag in the message.
|
||||
|
||||
Send
|
||||
This command sends the message. Note that it has no parameters and
|
||||
no ':'. It has no effect when "Window" was used as the parameter to
|
||||
the "New:" command.
|
||||
|
||||
Restore
|
||||
This command brings WinPMail to the top and activates the Message
|
||||
Editing Window created using the "New: Window" command. Note that it
|
||||
has no parameters and no ':'. For messages created using the
|
||||
"New: Message" command, this command will simply bring WinPMail to
|
||||
the top without taking any other action.
|
||||
|
||||
|
||||
-- Example: -----------------------------------
|
||||
|
||||
In WordBasic (MS-Word 7) the following Macro opens a connection to
|
||||
WinPMail, and sends a message with no window.
|
||||
|
||||
Sub MAIN
|
||||
channel = DDEInitiate("WinPMail", "Message")
|
||||
DDEPoke channel, "Message", "New: Message"
|
||||
DDEPoke channel, "Message", "Defaults: Y"
|
||||
DDEPoke channel, "Message", "To: David"
|
||||
DDEPoke channel, "Message", "Subject: Test from Word"
|
||||
DDEPoke channel, "Message", "Data: Hi there!"
|
||||
DDEPoke channel, "Message", "Send"
|
||||
DDETerminate channel
|
||||
End Sub
|
||||
|
||||
|
||||
|
||||
The "TCP" topic
|
||||
---------------
|
||||
|
||||
The commands in this topic allow clients to control Pegasus Mail's
|
||||
built-in TCP/IP-based mail protocols. Before using these commands, a
|
||||
client should usually use the "TCP" request to the "Environment" topic to
|
||||
determine whether or not TCP/IP services are enabled and available.
|
||||
Clients interact with this topic by Poking data at it in a similar manner
|
||||
to that used to access the "Message" topic. The following commands can be
|
||||
poked at this topic:
|
||||
|
||||
Get
|
||||
Tells Pegasus Mail to download mail using the current TCP/IP
|
||||
settings defined for the program.
|
||||
|
||||
Send
|
||||
Tells Pegasus Mail to send any messages currently waiting in
|
||||
the queue to be sent out.
|
||||
|
||||
Both
|
||||
Tells Pegasus Mail to check for new mail, then to send any messages
|
||||
currently waiting in the queue, in that order.
|
||||
|
||||
Restore
|
||||
Brings Pegasus Mail to the front and gives it focus.
|
||||
|
||||
|
||||
-- Example: -----------------------------------
|
||||
|
||||
In WordBasic (MS-Word 7) the following Macro opens a connection to
|
||||
WinPMail, tells it to download new mail, then brings it to the front:
|
||||
|
||||
Sub MAIN
|
||||
channel = DDEInitiate("WinPMail", "TCP")
|
||||
DDEPoke channel, "TCP", "Get"
|
||||
DDEPoke channel, "TCP", "Restore"
|
||||
DDETerminate channel
|
||||
End Sub
|
||||
|
||||
|
||||
|
||||
Pegasus Mail and the Windows Registry
|
||||
-------------------------------------
|
||||
|
||||
Starting with v2.54, WinPMail updates the Windows registry with a certain
|
||||
amount of information each time it is run. DDE Client Applications can use
|
||||
this registry information to work out how to find a copy of Pegasus Mail to
|
||||
run if none is active, and what commandline is appropriate.
|
||||
|
||||
The 32-bit version of WinPMail creates the following keys:
|
||||
|
||||
HKEY_CURRENT_USER\Software\Pegasus Mail\Version
|
||||
HKEY_CURRENT_USER\Software\Pegasus Mail\BaseDir
|
||||
HKEY_CURRENT_USER\Software\Pegasus Mail\Command
|
||||
|
||||
The "version" key contains the WinPMail version, expressed in exactly the
|
||||
same way as the return from the DDE "Environment" topic's "Version"
|
||||
request. The "BaseDir" key contains the directory where the WinPMail
|
||||
executable file is located, and the "command" key contains the full
|
||||
commandline that was used to invoke the most recently-run copy of Pegasus
|
||||
Mail.
|
||||
|
||||
Both the 16- and 32-bit versions of WinPMail create the following keys:
|
||||
|
||||
HKEY_CLASSES_ROOT\Software\Pegasus Mail\Version
|
||||
HKEY_CLASSES_ROOT\Software\Pegasus Mail\BaseDir
|
||||
HKEY_CLASSES_ROOT\Software\Pegasus Mail\Command
|
||||
|
||||
These keys are formatted in exactly the same way as those shown above.
|
||||
32-bit applications should always attempt to find the HKEY_CURRENT_USER
|
||||
keys before the HKEY_CLASSES_ROOT keys, since doing so ensures that
|
||||
multiple user configurations are respected under Windows 95 and NT.
|
||||
|
||||
|
||||
|
||||
Appendix A: Using DDE from C programs
|
||||
-------------------------------------
|
||||
|
||||
The source code shown here can be used as a model for interacting with
|
||||
any DDE-aware application. It presents a simple dialog with "Service",
|
||||
"Topic" and "Command" fields, request selector radio buttons that allow
|
||||
the user to select between XTYP_EXECUTE, XTYP_REQUEST and XTYP_POKE
|
||||
transactions, and three buttons - one to open/close a connection, a
|
||||
"quit" button, and a "Do it" button, that sends the command. If a
|
||||
connection is established using the "Open" button, then the "Do it"
|
||||
button will send the command to that connection, otherwise it will
|
||||
establish a connection, send the command, then close the connection.
|
||||
|
||||
This code was written for Borland C++ v4.52 and should be linked using
|
||||
Borland's BWCC.LIB or BWCC32.LIB in order to present the proper dialog
|
||||
appearance.
|
||||
|
||||
|
||||
--------------- DDECLI.C --------------------------------------------
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ddeml.h>
|
||||
|
||||
DWORD idInst = 0L; // DDE instance identifier
|
||||
HINSTANCE hInstance;
|
||||
HCONV mconv;
|
||||
HSZ ghszServSrv;
|
||||
HSZ ghszServTop;
|
||||
|
||||
#pragma warn -par
|
||||
#pragma warn -use
|
||||
|
||||
|
||||
HDDEDATA EXPENTRY DDECallback (WORD wType, // transaction type
|
||||
WORD wFmt, // clipboard format
|
||||
HCONV hConv, // handle of the conversation
|
||||
HSZ hsz1, // handle of a string
|
||||
HSZ hsz2, // handle of a string
|
||||
HDDEDATA hData, // handle of a global memory object
|
||||
DWORD dwData1, // transaction-specific data
|
||||
DWORD dwData2) // transaction-specific data
|
||||
{
|
||||
// Nothing need be done here...
|
||||
return (HDDEDATA) NULL;
|
||||
}
|
||||
|
||||
|
||||
BOOL SendShellCommand (DWORD idInst, char *service, char *topic, LPSTR lpCommand)
|
||||
{
|
||||
HSZ hszServSrv; // Service is "DDESERV"
|
||||
HSZ hszServTop; // Topic is "MAIL"
|
||||
HCONV hconv; // handle of conversation
|
||||
int nLen; // length of command string
|
||||
HDDEDATA hData; // return value of DdeClientTransaction
|
||||
DWORD dwResult; // result of transaction
|
||||
BOOL bResult=FALSE; // TRUE if this function is successful
|
||||
|
||||
if (mconv == NULL)
|
||||
{
|
||||
// create string handle to service/topic
|
||||
hszServSrv = DdeCreateStringHandle (idInst, service, CP_WINANSI);
|
||||
hszServTop = DdeCreateStringHandle (idInst, topic, CP_WINANSI);
|
||||
|
||||
// attempt to start conversation with server app
|
||||
hconv = DdeConnect (idInst, hszServSrv, hszServTop, NULL);
|
||||
}
|
||||
else
|
||||
hconv = mconv;
|
||||
|
||||
if (hconv != NULL)
|
||||
{
|
||||
// get length of the command string
|
||||
nLen = lstrlen ((LPSTR) lpCommand);
|
||||
|
||||
// send command to server app
|
||||
hData = DdeClientTransaction (
|
||||
(LPBYTE) lpCommand, // data to pass
|
||||
nLen + 1, // length of data
|
||||
hconv, // handle of conversation
|
||||
NULL, // handle of name-string
|
||||
CF_TEXT, // clipboard format
|
||||
XTYP_EXECUTE, // transaction type
|
||||
20000, // timeout duration
|
||||
&dwResult); // points to transaction result
|
||||
|
||||
if (hData)
|
||||
bResult = TRUE;
|
||||
|
||||
if (mconv == NULL)
|
||||
// end conversation
|
||||
DdeDisconnect (hconv);
|
||||
}
|
||||
|
||||
if (mconv == NULL)
|
||||
{
|
||||
// free service/topic string handle
|
||||
DdeFreeStringHandle(idInst, hszServSrv);
|
||||
DdeFreeStringHandle(idInst, hszServTop);
|
||||
}
|
||||
|
||||
if (bResult == FALSE)
|
||||
MessageBox (NULL, "SendShellCommand failed", "DDE Client", MB_OK);
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
BOOL SendPoke (DWORD idInst, char *service, char *topic, LPSTR lpCommand)
|
||||
{
|
||||
HSZ hszServSrv; // Service is "DDESERV"
|
||||
HSZ hszServTop; // Topic is "MAIL"
|
||||
HCONV hconv; // handle of conversation
|
||||
int nLen; // length of command string
|
||||
HDDEDATA hData; // return value of DdeClientTransaction
|
||||
DWORD dwResult; // result of transaction
|
||||
BOOL bResult=FALSE; // TRUE if this function is successful
|
||||
|
||||
if (mconv == NULL)
|
||||
{
|
||||
// create string handle to service/topic
|
||||
hszServSrv = DdeCreateStringHandle (idInst, service, CP_WINANSI);
|
||||
hszServTop = DdeCreateStringHandle (idInst, topic, CP_WINANSI);
|
||||
|
||||
// attempt to start conversation with server app
|
||||
hconv = DdeConnect (idInst, hszServSrv, hszServTop, NULL);
|
||||
}
|
||||
else
|
||||
hconv = mconv;
|
||||
|
||||
if (hconv != NULL)
|
||||
{
|
||||
// get length of the command string
|
||||
nLen = lstrlen ((LPSTR) lpCommand);
|
||||
|
||||
// send command to server app
|
||||
hData = DdeClientTransaction (
|
||||
(LPBYTE) lpCommand, // data to pass
|
||||
nLen + 1, // length of data
|
||||
hconv, // handle of conversation
|
||||
hszServTop, // handle of name-string
|
||||
CF_TEXT, // clipboard format
|
||||
XTYP_POKE, // transaction type
|
||||
20000, // timeout duration
|
||||
&dwResult); // points to transaction result
|
||||
|
||||
if (hData)
|
||||
bResult = TRUE;
|
||||
|
||||
if (mconv == NULL)
|
||||
// end conversation
|
||||
DdeDisconnect (hconv);
|
||||
}
|
||||
|
||||
if (mconv == NULL)
|
||||
{
|
||||
// free service/topic string handle
|
||||
DdeFreeStringHandle(idInst, hszServSrv);
|
||||
DdeFreeStringHandle(idInst, hszServTop);
|
||||
}
|
||||
|
||||
if (bResult == FALSE)
|
||||
MessageBox (NULL, "SendPoke failed", "DDE Client", MB_OK);
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
BOOL SendShellRequest (DWORD idInst, char *service, char *topic, char *cmd)
|
||||
{
|
||||
HSZ hszServSrv; // Service is "DDESERV"
|
||||
HSZ hszServTop; // Topic is "MAIL"
|
||||
HSZ item;
|
||||
HCONV hconv; // handle of conversation
|
||||
int nLen; // length of command string
|
||||
HDDEDATA hData; // return value of DdeClientTransaction
|
||||
DWORD dwResult; // result of transaction
|
||||
BOOL bResult=FALSE; // TRUE if this function is successful
|
||||
char *str;
|
||||
DWORD x;
|
||||
|
||||
if (mconv == NULL)
|
||||
{
|
||||
// create string handle to service/topic
|
||||
hszServSrv = DdeCreateStringHandle (idInst, service, CP_WINANSI);
|
||||
hszServTop = DdeCreateStringHandle (idInst, topic, CP_WINANSI);
|
||||
|
||||
// attempt to start conversation with server app
|
||||
hconv = DdeConnect (idInst, hszServSrv, hszServTop, NULL);
|
||||
}
|
||||
else
|
||||
hconv = mconv;
|
||||
|
||||
if (hconv != NULL)
|
||||
{
|
||||
// send command to server app
|
||||
item = DdeCreateStringHandle (idInst, cmd, CP_WINANSI);
|
||||
hData = DdeClientTransaction (
|
||||
NULL, // data to pass
|
||||
0, // length of data
|
||||
hconv, // handle of conversation
|
||||
item, // handle of name-string
|
||||
CF_TEXT, // clipboard format
|
||||
XTYP_REQUEST, // transaction type
|
||||
20000, // timeout duration
|
||||
&dwResult); // points to transaction result
|
||||
|
||||
if (hData)
|
||||
{
|
||||
if ((str = (char *) DdeAccessData (hData, &x)) != NULL)
|
||||
{
|
||||
strcpy (cmd, str);
|
||||
bResult = TRUE;
|
||||
DdeUnaccessData (hData);
|
||||
}
|
||||
|
||||
DdeFreeDataHandle (hData);
|
||||
}
|
||||
|
||||
DdeFreeStringHandle (idInst, item);
|
||||
|
||||
if (mconv == NULL)
|
||||
// end conversation
|
||||
DdeDisconnect (hconv);
|
||||
}
|
||||
|
||||
if (mconv == NULL)
|
||||
{
|
||||
// free service/topic string handle
|
||||
DdeFreeStringHandle (idInst, hszServSrv);
|
||||
DdeFreeStringHandle (idInst, hszServTop);
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
|
||||
int FAR PASCAL _export dummy_proc (HWND hDialog, UINT wMsg,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
BOOL fProcessed = TRUE;
|
||||
DWORD dwResult;
|
||||
RECT r;
|
||||
HWND hControl;
|
||||
char buffer [256], service [80], topic [80];
|
||||
|
||||
switch (wMsg)
|
||||
{
|
||||
case WM_INITDIALOG :
|
||||
CheckRadioButton (hDialog, 104, 106, 104);
|
||||
break;
|
||||
|
||||
case WM_SETFOCUS :
|
||||
SetFocus (GetDlgItem (hDialog, 101));
|
||||
break;
|
||||
|
||||
case WM_COMMAND :
|
||||
if (GET_WM_COMMAND_ID(wParam, lParam) == IDCANCEL)
|
||||
{
|
||||
EndDialog (hDialog, IDCANCEL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (GET_WM_COMMAND_ID(wParam, lParam) == 120)
|
||||
{
|
||||
if (mconv == NULL)
|
||||
{
|
||||
GetDlgItemText (hDialog, 101, service, sizeof (service));
|
||||
GetDlgItemText (hDialog, 102, topic, sizeof (topic));
|
||||
ghszServSrv = DdeCreateStringHandle (idInst, service, CP_WINANSI);
|
||||
ghszServTop = DdeCreateStringHandle (idInst, topic, CP_WINANSI);
|
||||
|
||||
// attempt to start conversation with server app
|
||||
mconv = DdeConnect (idInst, ghszServSrv, ghszServTop, NULL);
|
||||
if (mconv == NULL)
|
||||
MessageBox (NULL, "Connection failed!", "DDE Client",
|
||||
MB_OK | MB_ICONEXCLAMATION);
|
||||
else
|
||||
SetDlgItemText (hDialog, 120, "Close");
|
||||
}
|
||||
else
|
||||
{
|
||||
DdeDisconnect (mconv);
|
||||
mconv = NULL;
|
||||
DdeFreeStringHandle (idInst, ghszServSrv);
|
||||
DdeFreeStringHandle (idInst, ghszServTop);
|
||||
SetDlgItemText (hDialog, 120, "Open");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (GET_WM_COMMAND_ID(wParam, lParam) == IDOK)
|
||||
{
|
||||
GetDlgItemText (hDialog, 101, service, sizeof (service));
|
||||
GetDlgItemText (hDialog, 102, topic, sizeof (topic));
|
||||
GetDlgItemText (hDialog, 103, buffer, sizeof (buffer));
|
||||
hControl = GetDlgItem (hDialog, 107);
|
||||
if (IsDlgButtonChecked (hDialog, 105)) // Request
|
||||
{
|
||||
if (SendShellRequest (idInst, service, topic, buffer))
|
||||
{
|
||||
Edit_ReplaceSel (hControl, "Request successful:\r\n ");
|
||||
Edit_ReplaceSel (hControl, buffer);
|
||||
Edit_ReplaceSel (hControl, "\r\n");
|
||||
}
|
||||
else
|
||||
Edit_ReplaceSel (hControl, "Request failed.\r\n");
|
||||
}
|
||||
else if (IsDlgButtonChecked (hDialog, 104))
|
||||
{
|
||||
if (SendShellCommand (idInst, service, topic, buffer))
|
||||
Edit_ReplaceSel (hControl, "Command successful.\r\n");
|
||||
else
|
||||
Edit_ReplaceSel (hControl, "Command failed.\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SendPoke (idInst, service, topic, buffer))
|
||||
Edit_ReplaceSel (hControl, "Poke successful.\r\n");
|
||||
else
|
||||
Edit_ReplaceSel (hControl, "Poke failed.\r\n");
|
||||
Edit_SetSel (GetDlgItem (hDialog, 103), 0, 999);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fProcessed = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
return fProcessed;
|
||||
}
|
||||
|
||||
|
||||
int PASCAL WinMain (HINSTANCE __hInstance, HINSTANCE hPrevInstance,
|
||||
LPSTR lpszCmdLine, int nCmdShow)
|
||||
{
|
||||
MSG msg;
|
||||
HWND hWndFrame;
|
||||
WNDCLASS wc;
|
||||
FARPROC DDEProc, dlgProc;
|
||||
|
||||
if (hPrevInstance != NULL)
|
||||
return 0;
|
||||
|
||||
hInstance = __hInstance;
|
||||
|
||||
// get proc instance for our DDEML callback
|
||||
DDEProc = MakeProcInstance ((FARPROC) DDECallback, hInstance);
|
||||
|
||||
// register this app with the DDEML
|
||||
if (DdeInitialize (&idInst, // receives instance ID
|
||||
(PFNCALLBACK) DDEProc, // address of callback function
|
||||
APPCMD_CLIENTONLY, // this is a client app
|
||||
0L)) // reserved
|
||||
{
|
||||
#ifndef __FLAT__ // FreeProcInstance is obsolete under Win32
|
||||
FreeProcInstance (DDEProc);
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dlgProc = MakeProcInstance ((FARPROC) dummy_proc, hInstance);
|
||||
DialogBox (hInstance, "CLIENT", NULL, dlgProc);
|
||||
DdeUninitialize (idInst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--------------- DDECLI.DEF ----------------------------------------
|
||||
NAME DDECLI
|
||||
DESCRIPTION 'DDE Test Client'
|
||||
EXETYPE WINDOWS
|
||||
DATA MOVEABLE MULTIPLE PRELOAD
|
||||
CODE MOVEABLE DISCARDABLE
|
||||
HEAPSIZE 27500
|
||||
STACKSIZE 16500
|
||||
|
||||
--------------- DDECLI.RC -----------------------------------------
|
||||
|
||||
CLIENT DIALOG 180, 121, 246, 168
|
||||
STYLE WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
CLASS "bordlg"
|
||||
CAPTION "DDE Test Client"
|
||||
FONT 8, "MS Sans Serif"
|
||||
{
|
||||
RTEXT "Service name:", -1, 15, 15, 60, 8
|
||||
CONTROL "winpmail", 101, "EDIT", ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP, 83, 13, 102, 12
|
||||
RTEXT "Topic name:", -1, 15, 30, 60, 8
|
||||
CONTROL "message", 102, "EDIT", ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP, 83, 28, 102, 12
|
||||
RTEXT "Command/request:", -1, 14, 45, 61, 8
|
||||
EDITTEXT 103, 83, 43, 102, 12, ES_AUTOHSCROLL | WS_BORDER | WS_TABSTOP
|
||||
RTEXT "Transaction type:", -1, 15, 65, 60, 8
|
||||
CONTROL "Execute", 104, "BorRadio", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 85, 64, 47, 10
|
||||
CONTROL "Request", 105, "BorRadio", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 133, 64, 43, 10
|
||||
CONTROL "Poke", 106, "BorRadio", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 184, 64, 32, 10
|
||||
LTEXT "Results / Diagnostics", -1, 12, 82, 78, 8
|
||||
EDITTEXT 107, 10, 92, 228, 69, ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP
|
||||
DEFPUSHBUTTON "Do it", IDOK, 192, 12, 43, 14
|
||||
PUSHBUTTON "Quit", IDCANCEL, 192, 42, 43, 14
|
||||
CONTROL "", -1, "BorShade", BSS_GROUP | BSS_CAPTION | BSS_LEFT | WS_CHILD | WS_VISIBLE, -5, -7, 257, 180
|
||||
PUSHBUTTON "Open", 120, 192, 27, 43, 14
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user