Интеграция InTuch с приложением на C++
Добавлено:
Пн апр 16, 2012 2:22 pm
Drimascus
Добрый день, уважаемые господа. Я начинающий специалист и мне необходима Ваша помощь. В InTuch мной был создан тег (например level3). Как реализовать консольное приложение на с++, которое c помощью DDE выводило изменяющееся значение этого тега на экран? Заранее большое смпасибо.
Re: Интеграция InTuch с приложением на C++
Добавлено:
Пн апр 16, 2012 3:07 pm
LexSL
Доброго дня!
На С++ Вам необходимо следующие функции из библитеки user32.dll использовать:
DdeInitialize, DdeUninitialize, DdeCreateStringHandle, DdeFreeStringHandle, DdeConnect, DdeDisconnect и прочее...
Поищите в инете описание этих функций с примерами, думаю будет все понятно, если в С++ не новичек...
а так, для C# написана очень полезная (для меня
) сборка
http://ndde.codeplex.com/.
- Код: Выделить всё
using Ndde.Client;
....
..
DDEClient client = new DDEClient("view","Tagname");
client.Connect();
string Tag1 = client.Request("Tag1",1000).TrimEnd('\0');
string Tag1Comment = client.Request("Tag1.Comment",1000).TrimEnd('\0');
string Tag1DateTime = client.Request("Tag1.DateString",1000).TrimEnd('\0') + " " + client.Request("Tag1.TimeString",1000).TrimEnd('\0');
//DDE обмен в нашем случае в формате CF_TEXT. InTouch возвращает все значения в виде строки с \0\0\0 в конце, поэтому обрезаем.
double Tag1Value = Convert.ToDouble(Tag1);
client.Disconnect();
Также в архиве со сборкой есть примеры, как получать значения по подписке (организация "горячего" канала)
Re: Интеграция InTuch с приложением на C++
Добавлено:
Пн апр 16, 2012 3:34 pm
Drimascus
Проблема в том, что используется древняя ОС WIndows NT 4.0 и можно писать только на VS 6.0 и я от этого в шоке. Последний раз использовал С++ лет 8 назад)) в институте.
Я использовал функции, которые Вы привели в своем ответе. Ниже идет пример кода, в котором я пытался вызвать эти функции. Но у меня так и не вышло ничего, вот и очень прошу Вас привести маленький примерчик передачи значения тега из Intuch в приложение на с++, с дальнейшм выводом его на экран
#include "stdafx.h"
#include "windows.h"
#include "ddeml.h"
#include "stdio.h
DWORD inst = 0, res;
char ItemData1[256] = "5", ItemData2[256] = "2";
HDDEDATA CALLBACK exitFunction(UINT uType,UINT uFmt,HCONV hconv,HSZ hsz1,HSZ hsz2,HDDEDATA hdata,DWORD dwData1,DWORD dwData2)
// Программа выхода для обработки запросов от клиентов DDE.
{char forTopic[256] = "", forItem[256] = "", forData[256] = "", forWho[256] = "";
switch (uType & XCLASS_MASK)
{case XCLASS_BOOL : // Подтверждения.
switch (uType)
{case XTYP_CONNECT : case XTYP_CONNECT+XTYPF_NOBLOCK : // Запрос на соединение.
DdeQueryString(inst,hsz1,forTopic,sizeof(forTopic),CP_WINANSI);
DdeQueryString(inst,hsz2,forItem,sizeof(forItem),CP_WINANSI);
printf("Connect %s:%s\n",forTopic,forItem);
return (HDDEDATA)TRUE;
case XTYP_ADVSTART : case XTYP_ADVSTART+XTYPF_NOBLOCK : // Запрос на обновление данных.
DdeQueryString(inst,hsz1,forTopic,sizeof(forTopic),CP_WINANSI);
DdeQueryString(inst,hsz2,forItem,sizeof(forItem),CP_WINANSI);
printf("Start advise %s:%s\n",forTopic,forItem);
printf(" %s=%s",forTopic,forItem);
printf("\n\r");
return (HDDEDATA)TRUE;
case XTYP_ADVSTOP : case XTYP_ADVSTOP+XTYPF_NOBLOCK : // Окончание запроса на обновление данных.
DdeQueryString(inst,hsz1,forTopic,sizeof(forTopic),CP_WINANSI);
DdeQueryString(inst,hsz2,forItem,sizeof(forItem),CP_WINANSI);
printf("Stop advise %s:%s\n",forTopic,forItem);
return (HDDEDATA)TRUE;
default : // Прочие запросы.
printf("bool %d\n",(uType & ~(XCLASS_MASK)));
return (HDDEDATA)TRUE;
}
case XCLASS_DATA : // Блоки данных.
switch (uType)
{case XTYP_REQUEST : // Запрос на чтение данных.
DdeQueryString(inst,hsz1,forTopic,sizeof(forTopic),CP_WINANSI);
DdeQueryString(inst,hsz2,forItem,sizeof(forItem),CP_WINANSI);
if (!strcmpi(forTopic,"TOPIC1") && ! strcmpi(forItem,"ITEM1"))
strcpy(forData,ItemData1);
else if (!strcmpi(forTopic,"TOPIC1") && ! strcmpi(forItem,"ITEM2"))
strcpy(forData,ItemData2);
else return NULL;
printf("request %s:%s = %s\n",forTopic,forItem,forData);
return DdeCreateDataHandle(inst,(unsigned char *)forData,strlen(forData),0,hsz2,CF_TEXT,0);
default :
printf("data %d\n",(uType & ~(XCLASS_MASK)));
return NULL;
}
case XCLASS_FLAGS : // Флаги.
switch (uType)
{case XTYP_POKE : // Запрос на обновление данных.
DdeQueryString(inst,hsz1,forTopic,sizeof(forTopic),CP_WINANSI);
DdeQueryString(inst,hsz2,forItem,sizeof(forItem),CP_WINANSI);
DdeGetData(hdata,(unsigned char *)forData,sizeof(forData),0);
if (!strcmpi(forTopic,"TOPIC1") && ! strcmpi(forItem,"ITEM1")) strcpy(ItemData1,forData);
else if (!strcmpi(forTopic,"TOPIC1") && ! strcmpi(forItem,"ITEM2")) strcpy(ItemData1,forData);
else return NULL;
printf("poke %s:%s = %s\n",forTopic,forItem,forData);
return (HDDEDATA)DDE_FACK;
default :
printf("flag %d %d\n",(uType & ~(XCLASS_MASK)),uType == XTYP_POKE);
return NULL;
}
case XCLASS_NOTIFICATION: // Извещения.
// printf("note %d\n",(uType & ~(XCLASS_MASK)));
return NULL;
default :
printf("undef %d\n",(uType & ~(XCLASS_MASK)));
return NULL;
}
}
int main(int argc, char* argv[])
{
DdeInitialize(&inst,exitFunction,MF_CALLBACKS|MF_CONV|MF_ERRORS|MF_HSZ_INFO|MF_LINKS|MF_POSTMSGS|MF_SENDMSGS,0);
HSZ Sservice = DdeCreateStringHandle(inst,"OUN",CP_WINANSI);
DdeNameService(inst,Sservice,0,DNS_REGISTER);
printf("reg=%d\n",DdeGetLastError(inst));
MessageBox (NULL, "Сервер DDE запущен. Нажмите OK для завершения работы","ВНИМАНИЕ!", 0);
DdeNameService(inst,Sservice,0,DNS_UNREGISTER);
DdeFreeStringHandle(inst,Sservice);
DdeUninitialize(inst);
return 0;
}
Re: Интеграция InTuch с приложением на C++
Добавлено:
Пн апр 16, 2012 4:29 pm
LexSL
Перво-наперво: зачем вам создавать и регистрировать в системе DDE-сервер?
Drimascus писал(а):HSZ Sservice = DdeCreateStringHandle(inst,"OUN",CP_WINANSI);
DdeNameService(inst,Sservice,0,DNS_REGISTER);
Этого делать нет необходимости - InTouch сам является DDE-сервером!!! Имя сервиса = view, имя топика для доступа к тегам, созданным в InTouch = Tagname.
И рекомендую к прочтению и повторению вот эту статейку:
http://frolov-lib.ru/books/bsp/v17/ch3_5.htm, тем более что у вас "древний" NT.
Там есть есть раздел, посвященный как раз созданию клиента.
Re: Интеграция InTuch с приложением на C++
Добавлено:
Пн апр 16, 2012 5:46 pm
Drimascus
Большое спасибо за полезные ссылки, сейчас этим буду заниматься, надеюсь, что получится. Но все же, мне бы хотелось увидеть такой пример, который я просил, т.к. в инете такого я и не нашел. Заранее спасибо...
Re: Интеграция InTuch с приложением на C++
Добавлено:
Пн апр 16, 2012 6:02 pm
LexSL
Drimascus писал(а):Но все же, мне бы хотелось увидеть такой пример, который я просил, т.к. в инете такого я и не нашел.
Пожалуйста, почаще пользуйтесь поиском, это от "авторов" -- microsoft
http://support.microsoft.com/kb/279721/ruиз примера:
- Код: Выделить всё
...
int main(int argc, char* argv[])
{
char szApp[] = "EXCEL";
char szTopic[] = "C:\\Test.xls";
char szItem1[] = "R1C1";
...
Для вас же будет так:
- Код: Выделить всё
...
int main(int argc, char* argv[])
{
char szApp[] = "view";
char szTopic[] = "Tagname";
char szItem1[] = "level3";
...
До выполнения программы InTouch должен быть запущен, тег level3 создан
Re: Интеграция InTuch с приложением на C++
Добавлено:
Пн апр 16, 2012 6:11 pm
LexSL
Кстати, сам хотел спросить - на NT вроде же можно поставить Framework 1.1, не пробовали?
Re: Интеграция InTuch с приложением на C++
Добавлено:
Пн апр 16, 2012 7:16 pm
Drimascus
Большое спасибо)) результат тега был выведен на экран. По поводу Framework 1.1 - да его можно поставить, но приложения под NT можно писать только на VS 6.0 и более ранних версиях, увы это так...
Еще раз спасибо за оказанную помощь. Я с InTouch воюю только второй день. Вы очень помогли. Теперь буду разбираться, как постоянно отслеживать изменение результата, то есть реализовать с C++ такой вариант, как работа InTouch с Excel....
Re: Интеграция InTuch с приложением на C++
Добавлено:
Пн апр 16, 2012 7:18 pm
Drimascus
Когда изменение тега отображается в Excel по команде =view|TagName|level3
Re: Интеграция InTuch с приложением на C++
Добавлено:
Пн апр 16, 2012 8:03 pm
LexSL
LexSL писал(а):Теперь буду разбираться, как постоянно отслеживать изменение результата, то есть реализовать с C++ такой вариант, как работа InTouch с Excel....
Для начала, я думаю, будет достаточно таймера, в обработчик которого и нужно подсунуть выполнение запроса по DDE. Учтите только, что таймеру промежуток времени не надо ставить в миллисекунды, потому что может не успеть ответ от предыдущего запроса придти. Мне, например, хватало обновления каждые 5 сек.
Это уже вы сами решайте, в зависимости от "жесткости" требований по обновлению.
А отслеживать постоянно изменения - это организация "горячего" канала(подписка) - нужна callback функция.
Re: Интеграция InTuch с приложением на C++
Добавлено:
Вт апр 17, 2012 10:54 am
Drimascus
А примерчик не подскажете?
Re: Интеграция InTuch с приложением на C++
Добавлено:
Вт апр 17, 2012 10:55 am
Drimascus
на основе текущего примера...
Re: Интеграция InTuch с приложением на C++
Добавлено:
Вт апр 17, 2012 12:12 pm
LexSL
Попробуйте так, сам не проверял...
ключевые слова - SetTimer, KillTimer
- Код: Выделить всё
#include <windows.h>
...
//объявляете функцию обратного вызова:
void CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
DDERequest(idInst, hConv, szItem1, szDesc1);
}
int main(....
{
MSG Msg;
int Counter=0;
...
iReturn = DdeInitialize(&idInst, (PFNCALLBACK)DdeCallback,
APPCLASS_STANDARD | APPCMD_CLIENTONLY, 0 );
if (iReturn!=DMLERR_NO_ERROR)
{
printf("DDE Initialization Failed: 0x%04x\n", iReturn);
Sleep(1500);
return 0;
}
....
...
//устанавливаем таймер на 5 сек
UINT TimerId = SetTimer(NULL, 0, 5000, &TimerProc);
if (!TimerId)
{
printf("Error set timer");
return 0;
}
while (GetMessage(&Msg, NULL, 0, 0))
{
++Counter;
if (Msg.message == WM_TIMER)
cout << "Counter: " << Counter << "; timer message\n";
else
cout << "Counter: " << Counter << "; message: " << Msg.message << '\n';
DispatchMessage(&Msg);
}
KillTimer(NULL, TimerId);
DdeDisconnect(hConv);
DdeUninitialize(idInst);
Sleep(3000);
return 1;
}
Re: Интеграция InTuch с приложением на C++
Добавлено:
Вт апр 17, 2012 3:37 pm
Drimascus
Большое спасибо, будем пробовать
Re: Интеграция InTuch с приложением на C++
Добавлено:
Вт апр 17, 2012 4:05 pm
LexSL
LexSL писал(а):- Код: Выделить всё
KillTimer(NULL, TimerId);
DdeDisconnect(hConv);
DdeUninitialize(idInst);
Sleep(3000);
return 1;
Я конечно, дико извиняюсь
, только после цикла while (GetMessage(...)) до строк, где таймер уничтожается и происходит дисконнект, дело не дойдет
чтобы корректно убрать таймер из системы и сделать дисконнект, надо еще обрабатывать сообщение WM_QUIT