Converting VB DDE Client program to VC++

G

Guest

Hi all,

I am trying to connect to a electromyograph machine for my thesis project,
and I have a VB DDE client whose DDE functionality I want to convert to VC++.
However I can't make my VC++ version connect to the DDE server somehow --
DdeConnect(idInst,hszService, hszTopic, NULL) is not working

I am not sure if it's because DDEML doesn't support the connection, or if
it's because my code is incorrect (I'm not familiar with VB, so I'm just
guessing on how the service/topic strings should look like in C++).

Thanks so much!
Cindy

-----------------------------------------------------
Here is the VB program frm:
-----------------------------------------------------
VERSION 5.00
Begin VB.Form DDEForm
Caption = "Destination"
ClientHeight = 5655
ClientLeft = 60
ClientTop = 345
ClientWidth = 4740
LinkTopic = "SAM1|DDEForm"
ScaleHeight = 5655
ScaleWidth = 4740
StartUpPosition = 3 'Windows Default
Begin VB.CommandButton Command1
Caption = "Command1"
Height = 495
Left = 3120
TabIndex = 11
Top = 2880
Visible = 0 'False
Width = 1215
End
Begin VB.TextBox saveFileName
Height = 375
Left = 1560
TabIndex = 9
Text = "c:\cpi\data\test"
Top = 1680
Width = 2655
End
Begin VB.ComboBox Combo1
Height = 315
Left = 240
Style = 2 'Dropdown List
TabIndex = 8
Top = 2280
Width = 1335
End
Begin VB.Timer Timer1
Interval = 5000
Left = 240
Top = 5040
End
Begin VB.CommandButton Poke
Caption = "Poke"
Height = 495
Index = 2
Left = 1680
TabIndex = 7
Top = 3360
Width = 1215
End
Begin VB.TextBox Text2
Height = 495
Index = 2
Left = 240
TabIndex = 6
Top = 3360
Width = 1215
End
Begin VB.CommandButton Poke
Caption = "Poke"
Height = 495
Index = 1
Left = 1680
TabIndex = 5
Top = 2760
Width = 1215
End
Begin VB.TextBox Text2
Height = 495
Index = 1
Left = 240
TabIndex = 4
Top = 2760
Width = 1215
End
Begin VB.TextBox Text2
Height = 495
Index = 0
Left = 3000
LinkTimeout = -1
TabIndex = 3
Top = 2160
Visible = 0 'False
Width = 1215
End
Begin VB.CommandButton Request
Caption = "Request"
Height = 495
Left = 3120
TabIndex = 2
Top = 840
Width = 1215
End
Begin VB.CommandButton Poke
Caption = "Poke"
Height = 495
Index = 0
Left = 1680
TabIndex = 1
Top = 2160
Width = 1215
End
Begin VB.TextBox Text1
Height = 495
Left = 240
LinkTimeout = 5000
TabIndex = 0
Text = "Text1"
Top = 240
Width = 4095
End
Begin VB.Label Label1
Caption = "Aquire File Name:"
Height = 375
Left = 120
TabIndex = 10
Top = 1680
Width = 1335
End
End
Attribute VB_Name = "DDEForm"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Const AUTOMATIC = 1, MANUAL = 2, NONE = 0
Dim FileOpen As Boolean
Dim AppReady As Boolean
Dim FileNum3 As Integer
Dim buffer() As Byte


Private Sub Option1_Click()

End Sub

Private Sub AutomaticLink_Click()

Request.Visible = False 'No need for button with automatic link.
Text1.LinkMode = NONE 'Clear DDE Link.

Text1.LinkMode = AUTOMATIC 'Reestablish new LinkMode.

End Sub


Private Sub Command1_Click()
Text2(0).LinkExecute Text2(0).Text

End Sub

Private Sub Combo1_Change()
If Combo1.Text = "FILE" Then
Text2(0).Text = Combo1.Text & " " & saveFileName.Text
Else
Text2(0).Text = Combo1.Text
End If
End Sub

Private Sub Combo1_Click()
If Combo1.Text = "FILE" Then
Text2(0).Text = Combo1.Text & " " & saveFileName.Text
Else
Text2(0).Text = Combo1.Text
End If

End Sub

Private Sub Form_Load()
Dim z As Long
AppReady = False

'This procedure will start the VB source application.

z = Shell("c:\cpi\sam2", 1)
z = DoEvents() 'Causes Windows to finish processing Shell command.

Combo1.AddItem "FILE"
Combo1.AddItem "START"
Combo1.AddItem "STOP"
Combo1.AddItem "AQUIRE"
Combo1.AddItem "HIDE"
Combo1.AddItem "SHOW"
Combo1.AddItem "SETUP"
Combo1.AddItem "BEGIN"
If Combo1.Text = "FILE" Then
Text2(0).Text = Combo1.Text & " " & saveFileName.Text
Else
Text2(0).Text = Combo1.Text
End If
Text1.LinkMode = NONE 'Clears DDE link if it already exists.

Do While Not AppReady
DoEvents
Loop

Text1.LinkTopic = "sam2|frmDDE" 'Sets up link with VB source.
Text1.LinkItem = "Text1" 'Set link to text box on source.
Text1.LinkMode = MANUAL 'Establish a manual DDE link.

For i = 0 To 2
Text2(i).LinkTopic = "sam2|frmDDE" 'Sets up link with VB source.
Select Case i
Case 0
Text2(i).LinkItem = "Text2" 'Set link to text box
on source.
Case 1
Text2(i).LinkItem = "Text3" 'Set link to text box
on source.
Case 2
Text2(i).LinkItem = "Text4" 'Set link to text box
on source.
End Select
Text2(i).LinkMode = MANUAL 'Establish a manual DDE link.
Next i

Text1.LinkTopic = "sam2|frmDDE" 'Sets up link with VB source.
Text1.LinkItem = "Text1" 'Set link to text box on source.
Text1.LinkMode = MANUAL 'Establish a manual DDE link.

AutomaticLink_Click

If FileOpen = False Then
FileNum3 = FreeFile
Open "Outputdata.txt" For Output As #FileNum3
FileOpen = True
End If


End Sub

Private Sub ManualLink_Click()

Request.Visible = True 'Make request button valid.
Text1.LinkMode = NONE 'Clear DDE Link.
Text1.LinkMode = MANUAL 'Reestablish new LinkMode.

End Sub

Private Sub Form_Unload(Cancel As Integer)
Close #FileNum3
End Sub

Private Sub Poke_Click(Index As Integer)

'With any DDE link, this button will be visible, and when it's
'selected, will poke information from the destination application
'into the source application.
Text2(Index).LinkPoke

End Sub

Private Sub Request_Click()

'With a manual DDE link, this button will be visible, and when
'selected it will request an update of information from the source
'application to the destination application.
Text1.LinkRequest

End Sub

Private Sub Text1_Change()
Print #FileNum3, Text1.Text
End Sub
Private Sub Timer1_Timer()
Timer1.Enabled = False
AppReady = True
End Sub

-----------------------------------------------------
Here are snippets of my VC++ code that deals with the DDE:
-----------------------------------------------------
//Initialize DDE
UINT ui;

idInst = 0;
HINSTANCE hinst;

ui = DdeInitialize(&idInst, // receives instance identifier
(PFNCALLBACK) DdeCallback, // pointer to callback function
CBF_FAIL_EXECUTES | // filter XTYPE_EXECUTE
CBF_SKIP_ALLNOTIFICATIONS, // filter notifications
0);

if (ui != DMLERR_NO_ERROR)
{
richTextBox1->Text = "Failed to initialize as DDE client\n";
}

//Now try connecting to server
LPSTR lpszService = "c:\\CPI\\SAM2.EXE";
LPSTR lpszTopic = "frmDDE";
LPSTR lpszItem = "FILE c:\\CPI\\data\\MyFileName";

HSZ hszTopic = DdeCreateStringHandle(idInst, lpszTopic, CP_WINANSI);
HSZ hszService = DdeCreateStringHandle(idInst, lpszService, CP_WINANSI);
hconvNew = DdeConnect(idInst,hszService, hszTopic, NULL);

// Free the HSZs now
DdeFreeStringHandle(idInst, hszTopic);
DdeFreeStringHandle(idInst, hszService);

if (!hconvNew)
{
richTextBox1->AppendText("Couldn't connect to: ");
richTextBox1->AppendText(lpszService);
richTextBox1->AppendText(lpszTopic);
richTextBox1->AppendText("\n");
return;
}

// Try to get the item we are interrested in
DWORD dwResult;

HSZ hszItem = DdeCreateStringHandle(idInst,lpszItem,CP_WINANSI);

HDDEDATA hDDEData =
DdeClientTransaction(NULL,0,hconvNew,hszItem,CF_TEXT,XTYP_REQUEST,1000,&dwResult);

DdeFreeStringHandle(idInst, hszItem);

if (hDDEData)
{
// Lock the data so we can access it
BYTE FAR* pData;
DWORD dwLength;
pData = DdeAccessData(hDDEData, &dwLength);

if (pData)
{
// Just show it
richTextBox1->AppendText( (*pData).ToString() );
richTextBox1->AppendText("\n");
}

// Done with the data
DdeUnaccessData(hDDEData);
DdeFreeDataHandle(hDDEData);

}
else
{
richTextBox1->AppendText("couldn't get any data");
}


----------------------------------------

// Callback function for DDE messages
static HDDEDATA CALLBACK DdeCallback(UINT wType,
UINT wFmt,
HCONV hConv,
HSZ hsz1,
HSZ hsz2,
HDDEDATA hDDEData,
DWORD dwData1,
DWORD dwData2)
{
BYTE FAR *pData;
DWORD dwLength;

switch (wType)
{
case XTYP_ADVDATA:
return (HDDEDATA) DDE_FACK;

case XTYP_DISCONNECT:
return (HDDEDATA) NULL;

default:
return NULL;
break;
}
}
 
B

Brian Gideon

Cindy said:
//Now try connecting to server
LPSTR lpszService = "c:\\CPI\\SAM2.EXE";
LPSTR lpszTopic = "frmDDE";
LPSTR lpszItem = "FILE c:\\CPI\\data\\MyFileName";

The service name looks wrong to me. Shouldn't it just be "sam2"?
 
G

Guest

Yes, I have tried changing the service name, and it seems to connect now (at
least hconvNew is returning 1), thanks so much for the tip!

However, I still can't get the commands to my server, and I've been trying
different Item names. Right now I'm using (in VC++):

LPSTR lpszItem = "FILE c:\\CPI\\data\\MyFileName";

and I'm sending this command by:

HSZ hszItem = DdeCreateStringHandle(idInst,lpszItem,CP_WINANSI);

HDDEDATA hDDEData =
DdeClientTransaction(NULL,0,hconvNew,hszItem,CF_TEXT,XTYP_REQUEST,1000,&dwResult);


I've also tried using XTYP_POKE, but to no avail. Does anyone have any
suggestions?

Your help is much appreciated!
Cindy
 
B

Brian Gideon

Hi,

I apologize for the extremely late reply. Somehow I lost track of this
thread. Anyway, have you tried the XTYP_EXECUTE transaction type?

Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top