Long version: I need to have a Visual Basic ActiveX control communicate
with another application via DDE. As far as I can tell, I do not have the
ability to dynamically change the LinkMode property of controls within an
ActiveX control, so normal Visual Basic DDE commands are not acceptable. I
can then either use Windows messaging, specifically SendMessage and
PostMessage, or the DDEML. I can't find much support for either. It seems
no one has ever attempted this. Using Windows messaging in a test project,
with one module and one form, I have listed below my code so far. I'm using
Excel as my DDE Server testbed. I've tried running the same macro using a
TextBox with normal Visual Basic DDE commands, so I know I've got the right
Application, Topic, and execution string. I'm open to any suggestions
anyone might have about this. My only thought is that I need to respond to
the WM_DDE_ACK message sent from Excel by my WM_DDE_INITIATE and
WM_DDE_EXECUTE calls, but I have no idea how to do that.
J
Option Explicit
Private Const GMEM_DDESHARE = &H2000
Private Const WM_DDE_FIRST = &H3E0
Private Const WM_DDE_INITIATE = (WM_DDE_FIRST)
Private Const WM_DDE_TERMINATE = (WM_DDE_FIRST + 1)
Private Const WM_DDE_ADVISE = (WM_DDE_FIRST + 2)
Private Const WM_DDE_UNADVISE = (WM_DDE_FIRST + 3)
Private Const WM_DDE_ACK = (WM_DDE_FIRST + 4)
Private Const WM_DDE_DATA = (WM_DDE_FIRST + 5)
Private Const WM_DDE_REQUEST = (WM_DDE_FIRST + 6)
Private Const WM_DDE_POKE = (WM_DDE_FIRST + 7)
Private Const WM_DDE_EXECUTE = (WM_DDE_FIRST + 8)
Private Const WM_DDE_LAST = (WM_DDE_FIRST + 8)
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal
lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA"
(ByVal lpString As String) As Integer
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal wFlags As Long,
ByVal dwBytes As Long) As Long
Private Declare Function GlobalDeleteAtom Lib "kernel32" (ByVal nAtom As
Integer) As Integer
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As
Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As
Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As
Long
Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" (ByVal
lpString1 As String, ByVal lpString2 As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam() As
Integer) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA"
(ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As
Any) As Long
Public Sub Main()
Dim R1&
Dim R2%
Dim Handle As Long
Dim LinkForm As New Form1
Dim AppTopicAtom(1) As Integer
Dim Cmd$
Dim hCmd&
Dim lpCmd&
' Get the handle of the DDE Server
Handle = FindWindow(vbNullString, "Microsoft Excel - Book1")
' Assign the DDE Server app and topic names to atoms
AppTopicAtom(0) = GlobalAddAtom("Excel")
AppTopicAtom(1) = GlobalAddAtom("Sheet1")
' Initiate the DDE conversation
R1& = SendMessage(Handle, WM_DDE_INITIATE, LinkForm.hwnd, AppTopicAtom)
Debug.Print "DDE_INITIATE = " & R1&
' Delete the app and topic atoms
R2% = GlobalDeleteAtom(AppTopicAtom(0))
R2% = GlobalDeleteAtom(AppTopicAtom(1))
' Build the string
Cmd$ = "[RUN(" & Chr$(34) & "Macro2" & Chr$(34) & ")]" & vbNullChar
' Allocate a handle to memory for PostMessage
hCmd& = GlobalAlloc(GMEM_DDESHARE, Len(Cmd$))
If hCmd& > 0 Then
' Lock changes to the handle to a pointer
lpCmd& = GlobalLock(hCmd&)
If lpCmd& > 0 Then
' Copy the string to the pointer
R1& = lstrcpy(lpCmd&, Cmd$)
If R1& > 0 Then
' Unlock the handle
R1& = GlobalUnlock(hCmd&)
' Post the message
R1& = PostMessage(Handle, WM_DDE_EXECUTE, LinkForm.hwnd,
hCmd&)
Debug.Print "DDE_EXECUTE = " & R1&
End If
End If
End If
' Free the handle
R1& = GlobalFree(hCmd&)
' Terminate the DDE conversation
AppTopicAtom(0) = 0
AppTopicAtom(1) = 0
R1& = SendMessage(Handle, WM_DDE_TERMINATE, LinkForm.hwnd, AppTopicAtom)
End
End Sub
Jay Robinson
jsro...@iquest.net
I'm not sure if you can do it with Send/Postmesage or not but, you can do it
with the DDEML API because i have done this. I wrapped the DDEML API into an
ActiveX DLL just for the reasons you said. I currently offer this for sale.
If your interested, I will Email you a demo that demonstrates it's use with
Excel if you like. If you want to do it on your own thats fine, I can shoot
some pieces of code your way. I definetely enjoyed that project and it can
be done. My new release uses Implements as well as regular change events for
better performance.
GaryB
Jay S. Robinson <jsro...@iquest.net> wrote in message
news:0%5j3.47$n4....@news1.iquest.net...