//QM v2.9. Do not edit with text editor!!! //
24    2
AqJyvAypy[=m
  examples  65536 3AB51E24 0

  DDE server  65536 3AB523EC 1

  DDE_server  8 3AB5AA6F 2
 Run this.
 Then run dde_client to test.

out

DdeServerStart("QM" &dde_server_callback)

opt waitmsg 1
wait 60

  dde_server_callback  8 3AB5B7BE 2
 /DDE_server
function! action $topic $item str&data idInst hConv cbParam reserved

 Sample callback function that can be used with DdeServerStart.

 action - DDE action. One of XTYP_ constants, as used in the code below.
 topic - topic. On XTYP_DISCONNECT 0.
 item - item. Used only with XTYP_POKE and XTYP_REQUEST. With other actions 0.
 data - data. On XTYP_EXECUTE and XTYP_POKE it is the sent data or command string. On XTYP_REQUEST this function must store a string to return it to the client. Not used with other actions.
 idInst - DDE server's instance identifier. Can be used with DDE API functions.
 hConv - DDE conversation handle. On XTYP_CONNECT 0.
 cbParam - cbParam passed to DdeServerStart.
 reserved - currently not used.

 Return: 1 success, 0 failed.

 REMARKS
 This function will be called when clients connect, disconnect, ececute, poke or request.
 This function now just shows action and used arguments. To make it useful, edit it. For example, on XTYP_EXECUTE you can parse data and execute some code, for example run a macro.
 This function can use thread variables to store private data. The variables will not be shared between DDE servers, because a thread cannot have multiple DDE servers.


sel action
	case XTYP_CONNECT
	out "XTYP_CONNECT: topic='%s'" topic
	
	case XTYP_CONNECT_CONFIRM
	out "XTYP_CONNECT_CONFIRM: hConv=%i, topic='%s'" hConv topic
	
	case XTYP_DISCONNECT
	out "XTYP_DISCONNECT: hConv=%i" hConv
	
	case XTYP_EXECUTE
	out "XTYP_EXECUTE: hConv=%i, topic='%s', data='%s'" hConv topic data
	
	case XTYP_POKE
	out "XTYP_POKE: hConv=%i, topic='%s', item='%s', data='%s'" hConv topic item data
	
	case XTYP_REQUEST
	out "XTYP_REQUEST: hConv=%i, topic='%s', item='%s'" hConv topic item
	data="data"

ret 1

  dde_client  8 3AB5AE2F 2
 Run this to test DDE server.
 At first run DDE_server.


Dde d.Connect("QM" "topic")

if(!d.Execute2("data")) out "Execute2 failed"

if(!d.Poke2("item" "data")) out "Poke2 failed"

str s
if(!d.Request2("item" s)) out "Request2 failed"
else out s

  DDE server with dialog  65536 3AB523FB 1

  DDE_server_with_dialog  8 3AB5A893 6
\Dialog_Editor
function# hDlg message wParam lParam
if(hDlg) goto messages

str controls = "6 7 8"
str e6 e7 e8
e8="request data"
if(!ShowDialog("DDE_server_with_dialog" &DDE_server_with_dialog &controls _hwndqm)) ret

 BEGIN DIALOG
 0 "" 0x90C80AC8 0x0 0 0 223 135 "Dialog"
 1 Button 0x54030001 0x4 120 116 48 14 "OK"
 2 Button 0x54030000 0x4 170 116 48 14 "Cancel"
 3 Static 0x54000000 0x0 6 6 48 12 "Execute"
 4 Static 0x54000000 0x0 6 30 48 12 "Poke"
 5 Static 0x54000000 0x0 6 54 48 12 "Request"
 6 Edit 0x54230844 0x20000 56 4 96 18 ""
 7 Edit 0x54230844 0x20000 56 28 96 18 ""
 8 Edit 0x54231044 0x200 56 52 96 18 ""
 END DIALOG
 DIALOG EDITOR: "" 0x2030300 "*" "" ""

ret
 messages
sel message
	case WM_INITDIALOG
	out
	DdeServerStart("QM_dlg" &dde_server_callback2 hDlg)
	
	case WM_DESTROY
	case WM_COMMAND goto messages2
ret
 messages2
sel wParam
	case IDOK
	case IDCANCEL
ret 1

  dde_server_callback2  8 3AB5B24F 6
 /DDE_server_with_dialog
function! message $topic $item str&data idInst hConv hDlg reserved

 Callback function used with DDE_server_with_dialog.
 Parameters etc are documented in dde_server_callback.


sel message
	case XTYP_EXECUTE
	data.setwintext(id(6 hDlg))
	
	case XTYP_POKE
	data.setwintext(id(7 hDlg))
	
	case XTYP_REQUEST
	data.getwintext(id(8 hDlg))

ret 1

  dde_client2  8 3AB5A884 6
 Run this to test DDE server.
 At first run DDE_server_with_dialog.


Dde d.Connect("QM_dlg" "topic")

if(!d.Execute2("execute data")) out "Execute2 failed"

if(!d.Poke2("item" "poke data")) out "Poke2 failed"

str s
if(!d.Request2("item" s)) out "Request2 failed"
else out s

  functions  65536 3AB522F6 0

  DdeServerStart  8 3AB5B816 10
 /
function $serverName cbFunc [cbParam]

 Starts DDE server.
 Error if fails.
 DDE server receives DDE actions (Execute, Poke, Request) from applications that can work as DDE clients (send these actions). For example, run a macro when a client requests it. Clients also can be other threads in same process.

 serverName - server name. For example, it can be name of your macro or program.
 cbFunc - address of callback function. See <open>dde_server_callback</open>.
   The function will be called when clients connect, disconnect, ececute, poke or request.
 cbParam - some value to pass to the callback function.

 REMARKS
 A thread can have single DDE server.
 The thread must stay running after it calls this function. It must process messages. For example, use dialog, or message loop, or wait with opt waitmsg.
 The thread must not use QM DDE client functions.
 Supported actions: Execute, Poke, Request.
 Supported data formats: CF_UNICODETEXT, CF_TEXT.
 With Execute action, first data character must be ASCII. It is used to detect data format (CF_UNICODETEXT or CF_TEXT).
 Windows Vista/7 UAC:
   DDE server's process must not have higher integrity level than client processes.
   For example, if DDE server's process runs as Administrator, and client processes run as User, clients cannot connect.
   By default, QM runs as Administrator. Therefore DDE server should run in separate process, as User. Or let clients run as Administrator too.


#compile "____DdeServer"

__DdeServer- __t_ddes
__t_ddes.Start(serverName cbFunc cbParam)

err+ end _error

  DdeServerStop  8 3AB5B447 10
 /

 Stops DDE server started by DdeServerStart.
 Optional. Called implicitly when thread ends.
 This function stops DDE server of current thread. Don't call it from other thread.


#compile "____DdeServer"

__DdeServer- __t_ddes
__t_ddes.Stop

err+ end _error

  private  65600 3AB4AAC5 10

  ____DdeServer  0 3AB514C0 13
class __DdeServer -m_idinst -m_cbFunc -m_cbParam

  __DdeServer.Start  16 3AB79AF6 13
function $serverName cbFunc [cbParam]

Stop

m_cbFunc=cbFunc
m_cbParam=cbParam

if(DdeInitializeW(&m_idinst &__DdeServer_Callback CBF_SKIP_REGISTRATIONS|CBF_SKIP_UNREGISTRATIONS 0)) end ES_FAILED

#compile "Dde"
 in QM 2.3.2 __DdeStr renamed to ___DdeStr
#ifdef ___DdeStr
___DdeStr sn
#else
__DdeStr sn
#endif
if(!DdeNameService(m_idinst sn.Create(serverName m_idinst) 0 DNS_REGISTER)) Stop; end ES_FAILED

  __DdeServer.Stop  16 3AB5086C 13
if(!m_idinst) ret
DdeNameService(m_idinst 0 0 DNS_UNREGISTER)
DdeUninitialize(m_idinst)
m_idinst=0

  private  65600 3AB48DEB 13

  __DdeServer.Callback  16 3AB5B2B3 17
 /DDE_server
function# wType wFmt hConv hsz1 hsz2 hData dwData1 dwData2

 out "%i %i %i" hsz1 hsz2 hData

str s1 s2 s3
if(hsz1) GetStr(hsz1 s1)
if(hsz2) GetStr(hsz2 s2)
if(hData and !__DdeGetData(wFmt hData s3)) ret
int _r=1

sel wType
	case XTYP_CONNECT
	 out "XTYP_CONNECT: topic='%s'" s1
	
	case XTYP_CONNECT_CONFIRM
	 out "XTYP_CONNECT_CONFIRM: hConv=%i, topic='%s'" hConv s1
	
	case XTYP_DISCONNECT
	 out "XTYP_DISCONNECT: hConv=%i" hConv
	
	case XTYP_EXECUTE
	 out "XTYP_EXECUTE: hConv=%i, topic='%s', data='%s'" hConv s1 s3
	_r=DDE_FACK
	
	case XTYP_POKE
	 out "XTYP_POKE: hConv=%i, topic='%s', item='%s', data='%s'" hConv s1 s2 s3
	_r=DDE_FACK
	
	case XTYP_REQUEST
	 out "XTYP_REQUEST: hConv=%i, topic='%s', item='%s'" hConv s1 s2
	
	case else
	 outx wType
	ret

if(!call(m_cbFunc wType s1 s2 &s3 m_idinst hConv m_cbParam 0)) ret

if(wType!XTYP_REQUEST) ret _r

int n
sel wFmt
	case CF_UNICODETEXT s3.unicode; n=s3.len+2
	case CF_TEXT n=s3.len+1
	case else ret
ret DdeCreateDataHandle(m_idinst s3 n 0 hsz2 wFmt 0)

  __DdeServer_Callback  8 3AB4ACB6 17
 /
function# wType wFmt hConv hsz1 hsz2 hData dwData1 dwData2

__DdeServer- __t_ddes
ret __t_ddes.Callback(wType wFmt hConv hsz1 hsz2 hData dwData1 dwData2)

  __DdeServer.  16 3AB499EA 17
Stop

  __DdeServer.GetStr  16 3AB4A77D 17
function hStr str&s

_i=DdeQueryStringW(m_idinst hStr 0 0 CP_WINUNICODE)
BSTR b.alloc(_i)
DdeQueryStringW(m_idinst hStr b _i+1 CP_WINUNICODE)
s.ansi(b)

  __DdeGetData  8 3AB5AB31 17
function! cf hData str&sd

sel(cf) case [CF_UNICODETEXT,CF_TEXT,0] case else ret

lpstr s=DdeAccessData(hData &_i); if(!s or !_i) ret

if(!cf) cf=iif((_i&1 or s[1]) CF_TEXT CF_UNICODETEXT) ;;0 on execute

if(cf=CF_UNICODETEXT) sd.ansi(s -1 _i/2-1); else sd.left(s _i-1)

DdeUnaccessData(hData)
ret 1

  file  268500992 0

  