Fragensteller
IDTExtensibility2

Frage
-
Guten Morgen / Tag / Abend!
Mein Problem ist es, dass ich mittels IDTExtensibility2 – Schnittstelle eine Verbindung zu einem anderen Programm aufbauen muss und dieses damit ferngesteuert werden muss. Habe die Umsetzung bereits in VB6 gehabt und jetzt soll das ganze in VB2005 umgeändert werden.
Ich habe es mehr oder weniger „mit Gewalt hingebogen“. Hat auch recht gut funktioniert und es blieb nur noch ein Fehler übrig, den ich aber nicht kapiere und nicht ausbessern kann.
Vollständigkeitshalber habe ich die beiden Module in beiden Versionen diesem Beitrag angehängt. Der Codebereicht wurde unten "rot" markiert!
Das Problem:
Datei: DDEFunctions.vb
Funktion: DDE_Init()
Zeile: 290
If DdeInitialize(g_lInstID, AddressOf DDECallback, APPCMD_CLIENTONLY Or MF_SENDMSGS Or MF_POSTMSGS, 0) Then …
Folgender Fehler wird ausgelöst:
Fehler 10
Der Ausdruck "AddressOf" kann nicht in "Long" umgewandelt werden, da "Long" kein Delegattyp ist.
...\Projects\OutlookRibbonXVB\OutlookRibbonXAddinVB\DDEFunctions.vb
290 37
Ich hoffe mir kann hier jemand helfen!
Mit freundlichen Grüßen
Freezer
VB6-Modul: DDEApi.bas
Option Explicit
Global g_lInstID As Long
Global g_hService As Long
Global g_hService2 As Long
Global g_hTopic As Long
Global g_hTopic2 As Long
Global g_hItem As Long
Global g_hDDEConv As Long
Global g_hDDEConvList As Long
Global g_hDDEPrevConv As Long
Global g_aryConvID() As Long
' See note in Command4_Click() concerning the magic number.
Public Const MAGIC_NUMBER = 3
'*************************************************************************
' DDEML Return Values
'*************************************************************************
Public Const DMLERR_NO_ERROR = 0
Public Const DMLERR_ADVACKTIMEOUT = &H4000
Public Const DMLERR_BUSY = &H4001
Public Const DMLERR_DATAACKTIMEOUT = &H4002
Public Const DMLERR_DLL_NOT_INITIALIZED = &H4003
Public Const DMLERR_DLL_USAGE = &H4004
Public Const DMLERR_EXECACKTIMEOUT = &H4005
Public Const DMLERR_INVALIDPARAMETER = &H4006
Public Const DMLERR_LOW_MEMORY = &H4007
Public Const DMLERR_MEMORY_ERROR = &H4008
Public Const DMLERR_NOTPROCESSED = &H4009
Public Const DMLERR_NO_CONV_ESTABLISHED = &H400A
Public Const DMLERR_POKEACKTIMEOUT = &H400B
Public Const DMLERR_POSTMSG_FAILED = &H400C
Public Const DMLERR_REENTRANCY = &H400D
Public Const DMLERR_SERVER_DIED = &H400E
Public Const DMLERR_SYS_ERROR = &H400F
Public Const DMLERR_UNADVACKTIMEOUT = &H4010
Public Const DMLERR_UNFOUND_QUEUE_ID = &H4011
'*************************************************************************
' DDEML Flags
'*************************************************************************
Public Const XCLASS_BOOL = &H1000&
Public Const XCLASS_DATA = &H2000&
Public Const XCLASS_FLAGS = &H4000&
Public Const XCLASS_NOTIFICATION = &H8000&
Public Const XTYPF_NOBLOCK = &H2& ' CBR_BLOCK doesn't seem to work
Public Const XTYP_ADVDATA = (&H10& Or XCLASS_FLAGS)
Public Const XTYP_ADVREQ = (&H20& Or XCLASS_DATA Or XTYPF_NOBLOCK)
Public Const XTYP_ADVSTART = (XCLASS_BOOL Or &H30&)
Public Const XTYP_ADVSTOP = (XCLASS_NOTIFICATION Or &H40&)
Public Const XTYP_CONNECT = (XCLASS_BOOL Or &H60& Or XTYPF_NOBLOCK)
Public Const XTYP_CONNECT_CONFIRM = (XCLASS_NOTIFICATION Or &H70& Or XTYPF_NOBLOCK)
Public Const XTYP_DISCONNECT = (XCLASS_NOTIFICATION Or &HC0& Or XTYPF_NOBLOCK)
Public Const XTYP_ERROR = (XCLASS_NOTIFICATION Or &H0& Or XTYPF_NOBLOCK)
Public Const XTYP_EXECUTE = (XCLASS_FLAGS Or &H50&)
Public Const XTYP_MASK = &HF0&
Public Const XTYP_MONITOR = (XCLASS_NOTIFICATION Or &HF0& Or XTYPF_NOBLOCK)
Public Const XTYP_POKE = (XCLASS_FLAGS Or &H90&)
Public Const XTYP_REGISTER = (XCLASS_NOTIFICATION Or &HA0& Or XTYPF_NOBLOCK)
Public Const XTYP_REQUEST = (XCLASS_DATA Or &HB0&)
Public Const XTYP_SHIFT = 4 ' shift to turn XTYP_ into an index
Public Const XTYP_UNREGISTER = (XCLASS_NOTIFICATION Or &HD0& Or XTYPF_NOBLOCK)
Public Const XTYP_WILDCONNECT = (XCLASS_DATA Or &HE0& Or XTYPF_NOBLOCK)
Public Const XTYP_XACT_COMPLETE = (XCLASS_NOTIFICATION Or &H80&)
Public Const CP_WINANSI = 1004 ' Default codepage for DDE conversations.
Public Const CP_WINUNICODE = 1200
Public Const CF_TEXT = 1
Public Const CBF_SKIP_ALLNOTIFICATIONS = &H3C0000
Public Const APPCLASS_MONITOR = &H1
Public Const APPCMD_CLIENTONLY = &H10&
Public Const MF_CALLBACKS = &H8000000
Public Const MF_CONV = &H40000000
Public Const MF_ERRORS = &H10000000
Public Const MF_HSZ_INFO = &H1000000
Public Const MF_LINKS = &H20000000
Public Const MF_POSTMSGS = &H4000000
Public Const MF_SENDMSGS = &H2000000
Public Const TIMEOUT_ASYNC = &HFFFF
Public Const QID_SYNC = &HFFFF
Public Const DDE_FACK = &H8000
Public Const DDE_FBUSY = &H4000
Public Const DDE_FNOTPROCESSED = &H0
Public Const EC_ENABLEALL = 0
'*************************************************************************
' DDEML Type Declarations
'*************************************************************************
Public Type SECURITY_QUALITY_OF_SERVICE
Length As Long
Impersonationlevel As Integer
ContextTrackingMode As Integer
EffectiveOnly As Long
End Type
Public Type CONVCONTEXT
cb As Long
wFlags As Long
wCountryID As Long
iCodePage As Long
dwLangID As Long
dwSecurity As Long
qos As SECURITY_QUALITY_OF_SERVICE
End Type
Public Type CONVINFO
cb As Long
hUser As Long
hConvPartner As Long
hszSvcPartner As Long
hszServiceReq As Long
hszTopic As Long
hszItem As Long
wFmt As Long
wType As Long
wStatus As Long
wConvst As Long
wLastError As Long
hConvList As Long
ConvCtxt As CONVCONTEXT
hwnd As Long
hwndPartner As Long
End Type
'*************************************************************************
' DDEML Function Declarations
'*************************************************************************
Public Declare Function DdeInitialize Lib "user32" Alias "DdeInitializeA" _
(pidInst As Long, _
ByVal pfnCallback As Long, _
ByVal afCmd As Long, _
ByVal ulRes As Long) As Integer
' Removed the alias.
Public Declare Function DdeUninitialize Lib "user32" _
(ByVal idInst As Long) As Long
' Removed the alias.
Public Declare Function DdeConnect Lib "user32" _
(ByVal idInst As Long, _
ByVal hszService As Long, _
ByVal hszTopic As Long, _
pCC As Any) As Long
' Removed the alias.
Public Declare Function DdeDisconnect Lib "user32" _
(ByVal hConv As Long) As Long
Public Declare Function DdeCreateStringHandle Lib "user32" Alias "DdeCreateStringHandleA" _
(ByVal idInst As Long, _
ByVal psz As String, _
ByVal iCodePage As Long) As Long
' Removed the alias.
Public Declare Function DdeFreeStringHandle Lib "user32" _
(ByVal idInst As Long, _
ByVal hsz As Long) As Long
' Removed the alias and changed the first parameter from "ByRef pData as Byte"
' to "ByVal pData as String".
Public Declare Function DdeClientTransaction Lib "user32" _
(ByVal pData As String, _
ByVal cbData As Long, _
ByVal hConv As Long, _
ByVal hszItem As Long, _
ByVal wFmt As Long, _
ByVal wType As Long, _
ByVal dwTimeout As Long, _
pdwResult As Long) As Long
' The API loader provides an alias of "DdeGetDataA" for this function.
' You need to remove it because the DLL entry point can't be found for
' the alias.
Public Declare Function DdeGetData Lib "user32" _
(ByVal hData As Long, _
ByVal pDst As String, _
ByVal cbMax As Long, _
ByVal cbOff As Long) As Long
Public Declare Function DdeQueryConvInfo Lib "user32" _
(ByVal hConv As Long, _
ByVal idTransaction As Long, _
pConvInfo As CONVINFO) As Long
Public Declare Function DdeQueryNextServer Lib "user32" _
(ByVal hConvList As Long, _
ByVal hConvPrev As Long) As Long
Public Declare Function DdeConnectList Lib "user32" _
(ByVal idInst As Long, _
ByVal hszService As Long, _
ByVal hszTopic As Long, _
ByVal hConvList As Long, _
pCC As CONVCONTEXT) As Long
Public Declare Function DdeDisconnectList Lib "user32" _
(ByVal hConvList As Long) As Long
Public Declare Function DdeQueryString Lib "user32" _
Alias "DdeQueryStringA" _
(ByVal idInst As Long, _
ByVal hsz As Long, _
ByVal psz As String, _
ByVal cchMax As Long, _
ByVal iCodePage As Long) As Long
' Removed the alias.
Public Declare Function DdeFreeDataHandle Lib "user32" _
(ByVal hData As Long) As Long
' Removed the alias.
Public Declare Function DdeGetLastError Lib "user32" _
(ByVal idInst As Long) As Long
Public Declare Function DdeEnableCallback Lib "user32" _
(ByVal idInst As Long, _
ByVal hConv As Long, _
ByVal wCmd As Long) As Long
Public Function DDECallback(ByVal uType As Long, ByVal uFmt As Long, ByVal hConv As Long, ByVal hszString1 As Long, ByVal hszString2 As Long, ByVal hData As Long, ByVal dwData1 As Long, ByVal dwData2 As Long) As Long
Dim lSize As Long
Dim sBuffer As String
Dim Ret As Long
'If gDbg Then OutputDebugString "[mtb] DDECallback() in client callback. uType: " & uType & vbCrLf
Select Case uType
' This is th eevent you'll receive when a server sends you a advisment.
Case XTYP_ADVDATA
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_ADVDATA" & vbCrLf
lSize = DdeGetData(hData, vbNullString, 0, 0)
' If size is 0 then there's no data to grab.
If (lSize > 0) Then
' Allocate a buffer for the return data.
sBuffer = String$(lSize - MAGIC_NUMBER, 0)
' Grab the data.
lSize = DdeGetData(hData, sBuffer, Len(sBuffer), 0)
' Print the contents of the buffer.
szDDECommand = sBuffer
End If
Case XTYP_ADVSTART
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_ADVSTART" & vbCrLf
Case XTYP_ADVSTOP
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_ADVSTOP" & vbCrLf
Case XTYP_CONNECT
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_CONNECT" & vbCrLf
Case XTYP_CONNECT_CONFIRM
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_CONNECT_CONFIRM" & vbCrLf
Case XTYP_DISCONNECT
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_DISCONNECT" & vbCrLf
Case XTYP_ERROR
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_ERROR" & vbCrLf
Case XTYP_EXECUTE
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_EXECUTE" & vbCrLf
Case XTYP_MASK
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_MASK" & vbCrLf
Case XTYP_MONITOR
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_MONITOR" & vbCrLf
Case XTYP_POKE
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_POKE" & vbCrLf
Case XTYP_REGISTER
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_REGISTER" & vbCrLf
g_hService2 = hszString2
lSize = DdeQueryString(g_lInstID, hszString2, vbNullString, 0, CP_WINANSI)
sBuffer = Space(lSize)
DdeQueryString g_lInstID, hszString2, sBuffer, lSize + 1, CP_WINANSI
sBuffer = UCase(sBuffer)
Case XTYP_REQUEST
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_REQUEST" & vbCrLf
Case XTYP_SHIFT
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_SHIFT" & vbCrLf
Case XTYP_UNREGISTER
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_UNREGISTER" & vbCrLf
Case XTYP_WILDCONNECT
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_WILDCONNECT" & vbCrLf
Case XTYP_XACT_COMPLETE
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_XACT_COMPLETE" & vbCrLf
End Select
DDECallback = 0
End Function
VB6-Modul: DDEFunctions.bas
Option Explicit
Dim bAdvise As Boolean
Global szServer As String
Global szTopic As String
Global szDDECommand As String
Global szLinkType As String
Public Function TranslateError()
Dim lRet As Long
If gDbg Then OutputDebugString "[mtb] TranslateError() return=" & lRet & vbCrLf
lRet = DdeGetLastError(g_lInstID)
Select Case lRet
Case DMLERR_NO_ERROR
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_NO_ERROR" & vbCrLf
Case DMLERR_ADVACKTIMEOUT
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_ADVACKTIMEOUT" & vbCrLf
Case DMLERR_BUSY
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_BUSY" & vbCrLf
Case DMLERR_DATAACKTIMEOUT
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_DATAACKTIMEOUT" & vbCrLf
Case DMLERR_DLL_NOT_INITIALIZED
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_NOT_INITIALIZED" & vbCrLf
Case DMLERR_DLL_USAGE
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_USAGE" & vbCrLf
Case DMLERR_EXECACKTIMEOUT
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_EXECACKTIMEOUT" & vbCrLf
Case DMLERR_INVALIDPARAMETER
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_INVALIDPARAMETER" & vbCrLf
Case DMLERR_LOW_MEMORY
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_LOW_MEMORY" & vbCrLf
Case DMLERR_MEMORY_ERROR
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_MEMORY_ERROR" & vbCrLf
Case DMLERR_NOTPROCESSED
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_NOTPROCESSED" & vbCrLf
Case DMLERR_NO_CONV_ESTABLISHED
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_NO_CONV_ESTABLISHED" & vbCrLf
' maybe restart here dde server CTI.exe
Case DMLERR_POKEACKTIMEOUT
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_POKEACKTIMEOUT" & vbCrLf
Case DMLERR_POSTMSG_FAILED
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_POSTMSG_FAILED" & vbCrLf
Case DMLERR_REENTRANCY
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_REENTRANCY" & vbCrLf
Case DMLERR_SERVER_DIED
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_SERVER_DIED" & vbCrLf
Case DMLERR_SYS_ERROR
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_SYS_ERROR" & vbCrLf
Case DMLERR_UNADVACKTIMEOUT
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_UNADVACKTIMEOUT" & vbCrLf
Case DMLERR_UNFOUND_QUEUE_ID
If gDbg Then OutputDebugString "[mtb] TranslateError() DMLERR_UNFOUND_QUEUE_ID" & vbCrLf
End Select
' MsgBox (lRet)
End Function
Private Function CheckData(sCommand As String) As Boolean
Dim bRet As Boolean
Select Case sCommand
Case "Execute"
If (szServer <> "") And (szTopic <> "") Then
bRet = True
End If
Case "Poke", "Request", "Advise"
If (szServer <> "") And (szTopic <> "") And (szLinkType <> "<None>") Then
bRet = True
End If
End Select
CheckData = bRet
End Function
Public Function DDE_Connect() As Long
Dim udtConvCont As CONVCONTEXT
Dim hDDEConv As Long
Dim rc As Integer
' Set up the conversation context structure.
udtConvCont.iCodePage = CP_WINANSI
udtConvCont.cb = Len(udtConvCont)
hDDEConv = 0
' Open the connection to the service.
hDDEConv = DdeConnect(g_lInstID, g_hService, g_hTopic, udtConvCont)
' Do we have a connection?
If hDDEConv Then
If gDbg Then OutputDebugString "[mtb] DDE_Connect() connection success." & vbCrLf
Else
If gDbg Then OutputDebugString "[mtb] DDE_Connect() connection failure." & vbCrLf
TranslateError
' restart DDE Server CTI.exe if gshutdown is false
If gShutDownActive = False Then
If gDbg Then OutputDebugString "[mtb] try reconnect to cti application: " & gstrProgramDir & "\cti.exe" & vbCrLf
rc = Shell(gstrProgramDir & "\cti.exe", vbNormalNoFocus)
End If
End If
DDE_Connect = hDDEConv
End Function
Private Sub DDE_CreateStringHandles(ByRef sTheService As String, ByRef sTheTopic As String, Optional ByRef sTheItem As String = "")
' Create the string handles for the service and topic. DDEML will not
' allow you to use standard strings. NOTE: Make sure to release the
' string handles once you are done with them.
g_hService = DdeCreateStringHandle(g_lInstID, sTheService, CP_WINANSI)
g_hTopic = DdeCreateStringHandle(g_lInstID, sTheTopic, CP_WINANSI)
' Only convert the item if we were passed a string otherwise you'll get a memory
' error.
If (sTheItem <> "") Then
g_hItem = DdeCreateStringHandle(g_lInstID, szLinkType, CP_WINANSI)
End If
End Sub
Private Sub DDE_FreeStringHandles()
' Release our string handles.
If (g_hService <> 0) Then
DdeFreeStringHandle g_lInstID, g_hService
DdeFreeStringHandle g_lInstID, g_hTopic
End If
If (g_hItem <> 0) Then
DdeFreeStringHandle g_lInstID, g_hItem
End If
g_hService = 0
g_hTopic = 0
g_hItem = 0
End Sub
Private Sub DDE_StartAdvise()
Dim lRet As Long
Dim lTransVal As Long
DDE_CreateStringHandles szServer, szTopic, szLinkType
' Open the conversation.
If (g_hDDEConv = 0) Then
g_hDDEConv = DDE_Connect
End If
If g_hDDEConv Then
' Perform the transaction.
lRet = DdeClientTransaction(0, 0, g_hDDEConv, g_hItem, CF_TEXT, XTYP_ADVSTART, 2000, lTransVal)
If (lRet) Then
If gDbg Then OutputDebugString "[mtb] DDE_StartAdvise() advise start success." & vbCrLf
' Enable the Advise Stop button and disable the Advise Start button.
'Command7.Enabled = True
'Command6.Enabled = False
Else
If gDbg Then OutputDebugString "[mtb] DDE_StartAdvise() advise start failure." & vbCrLf
End If
End If
DDE_FreeStringHandles
End Sub
Private Sub DDE_StopAdvise()
Dim lRet As Long
Dim lTransVal As Long
DDE_CreateStringHandles szServer, szTopic, szLinkType
If g_hDDEConv Then
lRet = DdeClientTransaction(0, 0, g_hDDEConv, g_hItem, CF_TEXT, XTYP_ADVSTOP, 2000, lTransVal)
If (lRet) Then
If gDbg Then OutputDebugString "[mtb] DDE_StopAdvise() advise stop success." & vbCrLf
' Disable the Advise Stop button.
'Command7.Enabled = False
'Command6.Enabled = True
Else
If gDbg Then OutputDebugString "[mtb] DDE_StopAdvise() advise stop failure." & vbCrLf
End If
End If
DDE_FreeStringHandles
End Sub
Public Function DDE_Execute()
Dim lRet As Long
Dim sValue As String
Dim x As Integer
If (CheckData("Execute")) Then
' Load the buffer.
sValue = szDDECommand
' Create the string handles.
DDE_CreateStringHandles szServer, szTopic
' Open the conversation.
If (g_hDDEConv = 0) Then
g_hDDEConv = DDE_Connect
End If
If g_hDDEConv Then
x = Len(sValue)
' Perform the transaction.
lRet = DdeClientTransaction(sValue, Len(sValue), g_hDDEConv, 0, 0, XTYP_EXECUTE, 2000, 0)
If (lRet) Then
If gDbg Then OutputDebugString "[mtb] DDE_Execute() execute success." & vbCrLf
Else
If gDbg Then OutputDebugString "[mtb] DDE_Execute() execute failure." & vbCrLf
TranslateError
End If
End If
' Release the memory.
DDE_FreeStringHandles
Else
'MsgBox "Please enter the required data for the transaction."
End If
End Function
Public Function DDE_Init()
'Dim oCtl As Control
' Debug.Print "------------------- Begin DDE Test -----------------------"
g_lInstID = 0
' Initialize the DDE subsystem. This only needs to be done once.
If DdeInitialize(g_lInstID, AddressOf DDECallback, APPCMD_CLIENTONLY Or MF_SENDMSGS Or MF_POSTMSGS, 0) Then
If gDbg Then OutputDebugString "[mtb] DDE_Init() initialize failure." & vbCrLf
TranslateError
Else
If gDbg Then OutputDebugString "[mtb] DDE_Init() initialize success." & vbCrLf
End If
' Enable the command buttons.
'For Each oCtl In Controls
' If ((TypeOf oCtl Is TextBox) Or (TypeOf oCtl Is ComboBox)) And (oCtl.Enabled = False) Then
' oCtl.Enabled = True
' End If
'Next
'Command1.Enabled = False
'Command5.Enabled = True
'Command8.Enabled = True
'Combo1.ListIndex = 0
End Function
Public Function DDE_Uninit()
'Dim oCtl As Control
' Make sure we don't have any open connections.
If (g_hDDEConv <> 0) Then
DDE_Disconnect
End If
' Tear down the initialized instance.
If g_lInstID Then
If DdeUninitialize(g_lInstID) Then
If gDbg Then OutputDebugString "[mtb] DDE_Uninit() uninitialize success." & vbCrLf
Else
If gDbg Then OutputDebugString "[mtb] DDE_Uninit() uninitialize failure." & vbCrLf
TranslateError
End If
g_lInstID = 0
End If
End Function
Public Function DDE_Disconnect()
' Disconnect the DDE conversation.
If g_hDDEConv Then
If DdeDisconnect(g_hDDEConv) Then
If gDbg Then OutputDebugString "[mtb] DDE_Disconnect() disconnect success." & vbCrLf
Else
If gDbg Then OutputDebugString "[mtb] DDE_Disconnect() disconnect failure." & vbCrLf
TranslateError
End If
g_hDDEConv = 0
End If
End Function
...und hier dann der konvertierte Code für VB2005:
VB2005-Modul: DDEApi.vb
Option Explicit On
Module DDEApi
Public g_lInstID As Long
Public g_hService As Long
Public g_hService2 As Long
Public g_hTopic As Long
Public g_hTopic2 As Long
Public g_hItem As Long
Public g_hDDEConv As Long
Public g_hDDEConvList As Long
Public g_hDDEPrevConv As Long
Public g_aryConvID() As Long
' See note in Command4_Click() concerning the magic number.
Public Const MAGIC_NUMBER As Byte = 3
'*************************************************************************
' DDEML Return Values
'*************************************************************************
Public Const DMLERR_NO_ERROR As Byte = 0
Public Const DMLERR_ADVACKTIMEOUT As Integer = &H4000
Public Const DMLERR_BUSY As Integer = &H4001
Public Const DMLERR_DATAACKTIMEOUT As Integer = &H4002
Public Const DMLERR_DLL_NOT_INITIALIZED As Integer = &H4003
Public Const DMLERR_DLL_USAGE As Integer = &H4004
Public Const DMLERR_EXECACKTIMEOUT As Integer = &H4005
Public Const DMLERR_INVALIDPARAMETER As Integer = &H4006
Public Const DMLERR_LOW_MEMORY As Integer = &H4007
Public Const DMLERR_MEMORY_ERROR As Integer = &H4008
Public Const DMLERR_NOTPROCESSED As Integer = &H4009
Public Const DMLERR_NO_CONV_ESTABLISHED As Integer = &H400A
Public Const DMLERR_POKEACKTIMEOUT As Integer = &H400B
Public Const DMLERR_POSTMSG_FAILED As Integer = &H400C
Public Const DMLERR_REENTRANCY As Integer = &H400D
Public Const DMLERR_SERVER_DIED As Integer = &H400E
Public Const DMLERR_SYS_ERROR As Integer = &H400F
Public Const DMLERR_UNADVACKTIMEOUT As Integer = &H4010
Public Const DMLERR_UNFOUND_QUEUE_ID As Integer = &H4011
'*************************************************************************
' DDEML Flags
'*************************************************************************
Public Const XCLASS_BOOL As Long = &H1000&
Public Const XCLASS_DATA As Long = &H2000&
Public Const XCLASS_FLAGS As Long = &H4000&
Public Const XCLASS_NOTIFICATION As Long = &H8000&
Public Const XTYPF_NOBLOCK As Long = &H2& ' CBR_BLOCK doesn't seem to work
Public Const XTYP_ADVDATA As Long = (&H10& Or XCLASS_FLAGS)
Public Const XTYP_ADVREQ As Long = (&H20& Or XCLASS_DATA Or XTYPF_NOBLOCK)
Public Const XTYP_ADVSTART As Long = (XCLASS_BOOL Or &H30&)
Public Const XTYP_ADVSTOP As Long = (XCLASS_NOTIFICATION Or &H40&)
Public Const XTYP_CONNECT As Long = (XCLASS_BOOL Or &H60& Or XTYPF_NOBLOCK)
Public Const XTYP_CONNECT_CONFIRM As Long = (XCLASS_NOTIFICATION Or &H70& Or XTYPF_NOBLOCK)
Public Const XTYP_DISCONNECT As Long = (XCLASS_NOTIFICATION Or &HC0& Or XTYPF_NOBLOCK)
Public Const XTYP_ERROR As Long = (XCLASS_NOTIFICATION Or &H0& Or XTYPF_NOBLOCK)
Public Const XTYP_EXECUTE As Long = (XCLASS_FLAGS Or &H50&)
Public Const XTYP_MASK As Long = &HF0&
Public Const XTYP_MONITOR As Long = (XCLASS_NOTIFICATION Or &HF0& Or XTYPF_NOBLOCK)
Public Const XTYP_POKE As Long = (XCLASS_FLAGS Or &H90&)
Public Const XTYP_REGISTER As Long = (XCLASS_NOTIFICATION Or &HA0& Or XTYPF_NOBLOCK)
Public Const XTYP_REQUEST As Long = (XCLASS_DATA Or &HB0&)
Public Const XTYP_SHIFT As Byte = 4 ' shift to turn XTYP_ into an index
Public Const XTYP_UNREGISTER As Long = (XCLASS_NOTIFICATION Or &HD0& Or XTYPF_NOBLOCK)
Public Const XTYP_WILDCONNECT As Long = (XCLASS_DATA Or &HE0& Or XTYPF_NOBLOCK)
Public Const XTYP_XACT_COMPLETE As Long = (XCLASS_NOTIFICATION Or &H80&)
Public Const CP_WINANSI As Long = 1004 ' Default codepage for DDE conversations.
Public Const CP_WINUNICODE As Long = 1200
Public Const CF_TEXT As Long = 1
Public Const CBF_SKIP_ALLNOTIFICATIONS As Long = &H3C0000
Public Const APPCLASS_MONITOR As Long = &H1
Public Const APPCMD_CLIENTONLY As Long = &H10&
Public Const MF_CALLBACKS As Long = &H8000000
Public Const MF_CONV As Long = &H40000000
Public Const MF_ERRORS As Long = &H10000000
Public Const MF_HSZ_INFO As Long = &H1000000
Public Const MF_LINKS As Long = &H20000000
Public Const MF_POSTMSGS As Long = &H4000000
Public Const MF_SENDMSGS As Long = &H2000000
Public Const TIMEOUT_ASYNC As Long = &HFFFF
Public Const QID_SYNC As Long = &HFFFF
Public Const DDE_FACK As Long = &H8000
Public Const DDE_FBUSY As Long = &H4000
Public Const DDE_FNOTPROCESSED As Long = &H0
Public Const EC_ENABLEALL As Long = 0
'*************************************************************************
' DDEML Type Declarations
'*************************************************************************
Public Structure SECURITY_QUALITY_OF_SERVICE
Dim Length As Long
Dim Impersonationlevel As Long
Dim ContextTrackingMode As Long
Dim EffectiveOnly As Long
End Structure
Public Structure CONVCONTEXT
Dim cb As Long
Dim wFlags As Long
Dim wCountryID As Long
Dim iCodePage As Long
Dim dwLangID As Long
Dim dwSecurity As Long
Dim qos As SECURITY_QUALITY_OF_SERVICE
End Structure
Public Structure CONVINFO
Dim cb As Long
Dim hUser As Long
Dim hConvPartner As Long
Dim hszSvcPartner As Long
Dim hszServiceReq As Long
Dim hszTopic As Long
Dim hszItem As Long
Dim wFmt As Long
Dim wType As Long
Dim wStatus As Long
Dim wConvst As Long
Dim wLastError As Long
Dim hConvList As Long
Dim ConvCtxt As CONVCONTEXT
Dim hwnd As Long
Dim hwndPartner As Long
End Structure
'*************************************************************************
' DDEML Function Declarations
'*************************************************************************
Public Declare Function DdeInitialize Lib "user32" Alias "DdeInitializeA" _
(ByVal pidInst As Long, _
ByVal pfnCallback As Long, _
ByVal afCmd As Long, _
ByVal ulRes As Long) As Integer
' Removed the alias.
Public Declare Function DdeUninitialize Lib "user32" _
(ByVal idInst As Long) As Long
' Removed the alias.
Public Declare Function DdeConnect Lib "user32" _
(ByVal idInst As Long, _
ByVal hszService As Long, _
ByVal hszTopic As Long, _
ByVal pCC As VariantType) As Long
' Removed the alias.
Public Declare Function DdeDisconnect Lib "user32" _
(ByVal hConv As Long) As Long
Public Declare Function DdeCreateStringHandle Lib "user32" Alias "DdeCreateStringHandleA" _
(ByVal idInst As Long, _
ByVal psz As String, _
ByVal iCodePage As Long) As Long
' Removed the alias.
Public Declare Function DdeFreeStringHandle Lib "user32" _
(ByVal idInst As Long, _
ByVal hsz As Long) As Long
' Removed the alias and changed the first parameter from "ByRef pData as Byte"
' to "ByVal pData as String".
Public Declare Function DdeClientTransaction Lib "user32" _
(ByVal pData As String, _
ByVal cbData As Long, _
ByVal hConv As Long, _
ByVal hszItem As Long, _
ByVal wFmt As Long, _
ByVal wType As Long, _
ByVal dwTimeout As Long, _
ByVal pdwResult As Long) As Long
' The API loader provides an alias of "DdeGetDataA" for this function.
' You need to remove it because the DLL entry point can't be found for
' the alias.
Public Declare Function DdeGetData Lib "user32" _
(ByVal hData As Long, _
ByVal pDst As String, _
ByVal cbMax As Long, _
ByVal cbOff As Long) As Long
Public Declare Function DdeQueryConvInfo Lib "user32" _
(ByVal hConv As Long, _
ByVal idTransaction As Long, _
ByVal pConvInfo As CONVINFO) As Long
Public Declare Function DdeQueryNextServer Lib "user32" _
(ByVal hConvList As Long, _
ByVal hConvPrev As Long) As Long
Public Declare Function DdeConnectList Lib "user32" _
(ByVal idInst As Long, _
ByVal hszService As Long, _
ByVal hszTopic As Long, _
ByVal hConvList As Long, _
ByVal pCC As CONVCONTEXT) As Long
Public Declare Function DdeDisconnectList Lib "user32" _
(ByVal hConvList As Long) As Long
Public Declare Function DdeQueryString Lib "user32" _
Alias "DdeQueryStringA" _
(ByVal idInst As Long, _
ByVal hsz As Long, _
ByVal psz As String, _
ByVal cchMax As Long, _
ByVal iCodePage As Long) As Long
' Removed the alias.
Public Declare Function DdeFreeDataHandle Lib "user32" _
(ByVal hData As Long) As Long
' Removed the alias.
Public Declare Function DdeGetLastError Lib "user32" _
(ByVal idInst As Long) As Long
Public Declare Function DdeEnableCallback Lib "user32" _
(ByVal idInst As Long, _
ByVal hConv As Long, _
ByVal wCmd As Long) As Long
Sub DDECallBackH()
End Sub
Public Function DDECallback(ByVal uType As Long, ByVal uFmt As Long, ByVal hConv As Long, ByVal hszString1 As Long, ByVal hszString2 As Long, ByVal hData As Long, ByVal dwData1 As Long, ByVal dwData2 As Long) As Long
Dim lSize As Long
Dim sBuffer As String
'Dim Ret As Long
'If gDbg Then OutputDebugString "[mtb] DDECallback() in client callback. uType: " & uType & vbCrLf
Select Case uType
' This is th eevent you'll receive when a server sends you a advisment.
Case XTYP_ADVDATA
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_ADVDATA" & vbCrLf
lSize = DdeGetData(hData, vbNullString, 0, 0)
' If size is 0 then there's no data to grab.
If (lSize > 0) Then
' Allocate a buffer for the return data.
sBuffer = Convert.ToString(lSize - MAGIC_NUMBER, 0)
' Grab the data.
lSize = DdeGetData(hData, sBuffer, Len(sBuffer), 0)
' Print the contents of the buffer.
szDDECommand = sBuffer
End If
Case XTYP_ADVSTART
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_ADVSTART" & vbCrLf
Case XTYP_ADVSTOP
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_ADVSTOP" & vbCrLf
Case XTYP_CONNECT
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_CONNECT" & vbCrLf
Case XTYP_CONNECT_CONFIRM
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_CONNECT_CONFIRM" & vbCrLf
Case XTYP_DISCONNECT
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_DISCONNECT" & vbCrLf
Case XTYP_ERROR
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_ERROR" & vbCrLf
Case XTYP_EXECUTE
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_EXECUTE" & vbCrLf
Case XTYP_MASK
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_MASK" & vbCrLf
Case XTYP_MONITOR
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_MONITOR" & vbCrLf
Case XTYP_POKE
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_POKE" & vbCrLf
Case XTYP_REGISTER
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_REGISTER" & vbCrLf
g_hService2 = hszString2
lSize = DdeQueryString(g_lInstID, hszString2, vbNullString, 0, CP_WINANSI)
sBuffer = Space(Convert.ToUInt16(lSize))
DdeQueryString(g_lInstID, hszString2, sBuffer, lSize + 1, CP_WINANSI)
sBuffer = UCase(sBuffer)
Case XTYP_REQUEST
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_REQUEST" & vbCrLf
Case XTYP_SHIFT
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_SHIFT" & vbCrLf
Case XTYP_UNREGISTER
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_UNREGISTER" & vbCrLf
Case XTYP_WILDCONNECT
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_WILDCONNECT" & vbCrLf
Case XTYP_XACT_COMPLETE
'If gDbg Then OutputDebugString "[mtb] DDECallback() XTYP_XACT_COMPLETE" & vbCrLf
End Select
DDECallback = 0
End Function
End Module
VB2005-Modul: DDEFunctions.vb
Option Explicit On
Module DDEFunctions
Dim bAdvise As Boolean
Public szServer As String
Public szTopic As String
Public szDDECommand As String
Public szLinkType As String
Public Function TranslateError()
Dim lRet As Long
If gDbg Then OutputDebugString("[mtb] TranslateError() return=" & lRet & vbCrLf)
lRet = DdeGetLastError(g_lInstID)
Select Case lRet
Case DMLERR_NO_ERROR
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_NO_ERROR" & vbCrLf)
Case DMLERR_ADVACKTIMEOUT
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_ADVACKTIMEOUT" & vbCrLf)
Case DMLERR_BUSY
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_BUSY" & vbCrLf)
Case DMLERR_DATAACKTIMEOUT
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_DATAACKTIMEOUT" & vbCrLf)
Case DMLERR_DLL_NOT_INITIALIZED
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_NOT_INITIALIZED" & vbCrLf)
Case DMLERR_DLL_USAGE
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_USAGE" & vbCrLf)
Case DMLERR_EXECACKTIMEOUT
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_EXECACKTIMEOUT" & vbCrLf)
Case DMLERR_INVALIDPARAMETER
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_INVALIDPARAMETER" & vbCrLf)
Case DMLERR_LOW_MEMORY
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_LOW_MEMORY" & vbCrLf)
Case DMLERR_MEMORY_ERROR
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_MEMORY_ERROR" & vbCrLf)
Case DMLERR_NOTPROCESSED
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_NOTPROCESSED" & vbCrLf)
Case DMLERR_NO_CONV_ESTABLISHED
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_NO_CONV_ESTABLISHED" & vbCrLf)
' maybe restart here dde server CTI.exe
Case DMLERR_POKEACKTIMEOUT
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_POKEACKTIMEOUT" & vbCrLf)
Case DMLERR_POSTMSG_FAILED
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_POSTMSG_FAILED" & vbCrLf)
Case DMLERR_REENTRANCY
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_REENTRANCY" & vbCrLf)
Case DMLERR_SERVER_DIED
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_SERVER_DIED" & vbCrLf)
Case DMLERR_SYS_ERROR
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_SYS_ERROR" & vbCrLf)
Case DMLERR_UNADVACKTIMEOUT
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_UNADVACKTIMEOUT" & vbCrLf)
Case DMLERR_UNFOUND_QUEUE_ID
If gDbg Then OutputDebugString("[mtb] TranslateError() DMLERR_UNFOUND_QUEUE_ID" & vbCrLf)
End Select
Return False
End Function
Private Function CheckData(ByVal sCommand As String) As Boolean
Dim bRet As Boolean
Select Case sCommand
Case "Execute"
If (szServer <> "") And (szTopic <> "") Then
bRet = True
End If
Case "Poke", "Request", "Advise"
If (szServer <> "") And (szTopic <> "") And (szLinkType <> "<None>") Then
bRet = True
End If
End Select
CheckData = bRet
End Function
Public Function DDE_Connect() As Long
Dim udtConvCont As CONVCONTEXT
Dim hDDEConv As Long
Dim rc As Integer
' Set up the conversation context structure.
udtConvCont.iCodePage = CP_WINANSI
udtConvCont.cb = Len(udtConvCont)
hDDEConv = 0
' Open the connection to the service.
hDDEConv = DdeConnect(g_lInstID, g_hService, g_hTopic, VariantType.Variant)
' Do we have a connection?
If Convert.ToBoolean(hDDEConv) Then
If gDbg Then OutputDebugString("[mtb] DDE_Connect() connection success." & vbCrLf)
Else
If gDbg Then OutputDebugString("[mtb] DDE_Connect() connection failure." & vbCrLf)
TranslateError()
' restart DDE Server CTI.exe if gshutdown is false
If gShutDownActive = False Then
If gDbg Then OutputDebugString("[mtb] try reconnect to cti application: " & gstrProgramDir & "\cti.exe" & vbCrLf)
rc = Shell(gstrProgramDir & "\cti.exe", vbNormalNoFocus)
End If
End If
DDE_Connect = hDDEConv
End Function
Private Sub DDE_CreateStringHandles(ByRef sTheService As String, ByRef sTheTopic As String, Optional ByRef sTheItem As String = "")
' Create the string handles for the service and topic. DDEML will not
' allow you to use standard strings. NOTE: Make sure to release the
' string handles once you are done with them.
Try
'g_hService = DdeCreateStringHandle(g_lInstID, sTheService, CP_WINANSI)
'g_hTopic = DdeCreateStringHandle(g_lInstID, sTheTopic, CP_WINANSI)
Catch ex As Exception
End Try
' Only convert the item if we were passed a string otherwise you'll get a memory
' error.
If (sTheItem <> "") Then
g_hItem = DdeCreateStringHandle(g_lInstID, szLinkType, CP_WINANSI)
End If
End Sub
Private Sub DDE_FreeStringHandles()
' Release our string handles.
If (g_hService <> 0) Then
DdeFreeStringHandle(g_lInstID, g_hService)
DdeFreeStringHandle(g_lInstID, g_hTopic)
End If
If (g_hItem <> 0) Then
DdeFreeStringHandle(g_lInstID, g_hItem)
End If
g_hService = 0
g_hTopic = 0
g_hItem = 0
End Sub
Private Sub DDE_StartAdvise()
Dim lRet As Long
Dim lTransVal As Long
DDE_CreateStringHandles(szServer, szTopic, szLinkType)
' Open the conversation.
If (g_hDDEConv = 0) Then
g_hDDEConv = DDE_Connect()
End If
If Convert.ToBoolean(g_hDDEConv) Then
' Perform the transaction.
lRet = DdeClientTransaction(Convert.ToString(0), 0, g_hDDEConv, g_hItem, CF_TEXT, XTYP_ADVSTART, 2000, lTransVal)
If (lRet) Then
If gDbg Then OutputDebugString("[mtb] DDE_StartAdvise() advise start success." & vbCrLf)
' Enable the Advise Stop button and disable the Advise Start button.
'Command7.Enabled = True
'Command6.Enabled = False
Else
If gDbg Then OutputDebugString("[mtb] DDE_StartAdvise() advise start failure." & vbCrLf)
End If
End If
DDE_FreeStringHandles()
End Sub
Private Sub DDE_StopAdvise()
Dim lRet As Long
Dim lTransVal As Long
DDE_CreateStringHandles(szServer, szTopic, szLinkType)
If g_hDDEConv Then
lRet = DdeClientTransaction(0, 0, g_hDDEConv, g_hItem, CF_TEXT, XTYP_ADVSTOP, 2000, lTransVal)
If (lRet) Then
If gDbg Then OutputDebugString("[mtb] DDE_StopAdvise() advise stop success." & vbCrLf)
' Disable the Advise Stop button.
'Command7.Enabled = False
'Command6.Enabled = True
Else
If gDbg Then OutputDebugString("[mtb] DDE_StopAdvise() advise stop failure." & vbCrLf)
End If
End If
DDE_FreeStringHandles()
End Sub
Public Function DDE_Execute()
Dim lRet As Long
Dim sValue As String
Dim x As Integer
If (CheckData("Execute")) Then
' Load the buffer.
sValue = szDDECommand
' Create the string handles.
DDE_CreateStringHandles(szServer, szTopic)
' Open the conversation.
If (g_hDDEConv = 0) Then
g_hDDEConv = DDE_Connect()
End If
If g_hDDEConv Then
x = Len(sValue)
' Perform the transaction.
lRet = DdeClientTransaction(sValue, Len(sValue), g_hDDEConv, 0, 0, XTYP_EXECUTE, 2000, 0)
If (lRet) Then
If gDbg Then OutputDebugString("[mtb] DDE_Execute() execute success." & vbCrLf)
Else
If gDbg Then OutputDebugString("[mtb] DDE_Execute() execute failure." & vbCrLf)
TranslateError()
End If
End If
' Release the memory.
DDE_FreeStringHandles()
Else
'MsgBox "Please enter the required data for the transaction."
End If
End Function
Public Function DDE_Init() As Boolean
'Dim oCtl As Control
' Debug.Print "------------------- Begin DDE Test -----------------------"
'g_lInstID = 0
' Initialize the DDE subsystem. This only needs to be done once.
If DdeInitialize(g_lInstID, AddressOf DDECallback, APPCMD_CLIENTONLY Or MF_SENDMSGS Or MF_POSTMSGS, 0) Then
If gDbg Then OutputDebugString("[mtb] DDE_Init() initialize failure." & vbCrLf)
TranslateError()
Else
If gDbg Then OutputDebugString("[mtb] DDE_Init() initialize success." & vbCrLf)
End If
'Enable the command buttons.
'For Each oCtl In Controls
' If ((TypeOf oCtl Is TextBox) Or (TypeOf oCtl Is ComboBox)) And (oCtl.Enabled = False) Then
' oCtl.Enabled = True
' End If
'Next
'Command1.Enabled = False
'Command5.Enabled = True
'Command8.Enabled = True
'Combo1.ListIndex = 0
Return False
End Function
Public Function DDE_Uninit() As Long
'Dim oCtl As Control
' Make sure we don't have any open connections.
If (g_hDDEConv <> 0) Then
DDE_Disconnect()
End If
' Tear down the initialized instance.
If Convert.ToBoolean(g_lInstID) Then
If Convert.ToBoolean(DdeUninitialize(g_lInstID)) Then
If gDbg Then OutputDebugString("[mtb] DDE_Uninit() uninitialize success." & vbCrLf)
Else
If gDbg Then OutputDebugString("[mtb] DDE_Uninit() uninitialize failure." & vbCrLf)
TranslateError()
End If
g_lInstID = 0
End If
End Function
Public Function DDE_Disconnect() As Long
' Disconnect the DDE conversation.
If g_hDDEConv Then
If DdeDisconnect(g_hDDEConv) Then
If gDbg Then OutputDebugString("[mtb] DDE_Disconnect() disconnect success." & vbCrLf)
Else
If gDbg Then OutputDebugString("[mtb] DDE_Disconnect() disconnect failure." & vbCrLf)
TranslateError()
End If
g_hDDEConv = 0
End If
End Function
End Module