wincc的n个经典问题解答之三.docx
《wincc的n个经典问题解答之三.docx》由会员分享,可在线阅读,更多相关《wincc的n个经典问题解答之三.docx(11页珍藏版)》请在冰豆网上搜索。
wincc的n个经典问题解答之三
wincc的n个经典问题解答之三
41:
用C编程解决授权点数不够用的问题(acsun提供)
当需要的工艺参数超过WinCC版本限制的Tag数目,可以用C语言编程实现多个工艺参数打包成一个Tag传送.例如某个配料称重系统有146个参数超过了WinCC的128个Tag的限制就可以用C语言编程决这一问题而不需要购买更高的授权.
基本思想就是把多个参数在下位机内存中连续排列然后在WinCC中定义一个Tag它的长度是多个参数之和取得这个Tag后编程将其分成多个参数
例如下位机有两个参数LTN44001和LTN44023都是16位整数分别存放在DD99.DW146和DD99.DW148
在WinCC中定义一个外部Tag命名为PackageTag类型为32位整数并联地址为DD99.DBD146再定义两个内部tag名为LTN44001和LTN44023在GlobalScript全局脚本中C语言编程如下
Union
{
LongDword
IntWord[2]
}union
Union.Dword=GetTagDword("PackageTag")
SetTagWord("LTN44001",Union.Word[0])
SetTagWord("LTN44023",Union.Word[0])
这样两个参数LTN44001和LTN44023就通过一个Tag传送上来了理论上只要下位机内存足够可以传送任意数量的参数而不受WinCC版本外部Tag数目的限制.
42:
如何在WinCC里用C语言调用SQL语言?
1、创建一个SQL文件。
此文件在ISQL中创建,文件内容是所希望执行的SQL语句。
2、在WinCC的CScript中编写程序调用此SQL文件,如以下程序所示:
#include"apdefap.h"
voidOnLButtonDown(char*lpszPictureName,
char*lpszObjectName,
char*lpszPropertyName,
UINTnFlags,intx,inty)
{
char*a="C:
\\SIEMENS\\Common\\SQLANY\\ISQL-q-b-c
UID=DBA;PWD=SQL;DBF=E:
\\testsql\\testsqlRT.DB;
DBN=CC_testsql_99-12-03_12:
48:
26R;
READ
E:
\\testsql\\test.sql";
printf("%s\r\n",a);
ProgramExecute(a);
}
下面是一个简单的SQL文件内容:
select*frompde#hd#t#test;
outputtoE:
\\test2.txtFORMATascii
注意:
文件名及路径中不要带空格。
43:
如何整点启动归档?
在"GlobalScript"下的Projectfunctions编写函数:
cyclicarchive
BOOLcyclicarchive()
{
#pragmacode("kernel32.dll");
voidGetLocalTime(SYSTEMTIME*lpst);
#pragmacode();
SYSTEMTIMEtime;
Intt1;
GetLocalTime(&time);
t1=time.wMinute;
if(t1==00)
{
SetTagBit("startarchive",1);
return(BOOL)(GetTagBit("startarchive"));
}
}
在Tagloging中的"Propertiesofprocesstag"中的"ArchiveTag"tab下的Archivingtype选择Cycle-selective,在"Event"标签下的"StartEvent"内选择cyclicarchive函数。
44:
如何在按键组合被禁用的情况下,从WinCC运行环境进入WinCCControlCenter?
最好是做一个按钮,该按钮需要用用户权限保护,在该钮中编写如下C-action:
低于WinCC5.0版本:
#pragmacode("user32.dll");
BOOLSetForegroundWindow(HWND);
#pragmacode();
HWNDhandle;
handle=FindWindow("MCPFrameWndClass",NULL);
If(!
SetForegroundWindow(handle))
Printf("\r\nSetForegroundfails");
WinCC5.0版本以及更高的版本:
#pragmacode("user32.dll");
BOOLSetForegroundWindow(HWND);
#pragmacode();
HWNDhandle;
handle=FindWindow("WinCCExplorerFrameWndClass",NULL);
If(!
SetForegroundWindow(handle))
Printf("\r\nSetForegroundfails");
45:
WinCC如何实现鼠标OnMouseOVer事件?
用WINDOWAPI函数GetCusorPos获取当前鼠标位置,用GetWindowRect函数获取窗口位置,两值相减得鼠标在WINCCframe上的相对位置。
用全局脚本(设定为1s定时刷新),然后获取要OnMouseOver事件的物体的位置,并与鼠标位置相比较,如一致则触发自己定义的动作。
#include"apdefap.h"
intgscAction(void)
{
#pragmacode("user32.dll");
BOOLGetCusorPos(POINTlpPoint);//获取鼠标的位置(绝对位置-对应屏幕分辨率)
BOOLGetWindowRect(HWNDhwnd,LPRECTlpRect);//获取窗体_位置
#pragmacode();
POINTpPos;
RECTrRec;
HWNDhwnd;
BOOLbRet,bRet2;
longlLeft,lTop,lWidth,lHeight;
longlX,lY;
charszStr[100];
hwnd=FindWindow(NULL,"WinCC-Runtime-");//如语言为中文应为"WinCC运行系统-"
if(hwnd==0){printf("\r\nError!
WinCcHandleis%d",hwnd);gotoover;}
bRet=GetCursorPos(&pPos);
if(bRet==0)gotoover;
bRet2=GetWindowRect(hwnd,&rRec);
if(bRet2==0)gotoover;
lX=pPos.x-rRec.left;//鼠标对{置
lY=pPos.y-rRec.top;//鼠标_位置
//如果为非全屏模式,需将上述数值中的高height判断减去标题栏的宽度
//printf("TheCurrentCusorPosisx:
%d,y:
%d\r\n",pPos.x,pPos.y);
//printf("TheCusorPosinWindowisx:
%d,y:
%d\r\n",pPos.x-lLeft2,pPos.y-lTop2);
lLeft=GetLeft("NewPdl0.Pdl","Text1");//Return-Type:
longint
lTop=GetTop("NewPdl0.Pdl","Text1");//Return-Type:
longint
lWidth=GetWidth("NewPdl0.Pdl","Text1");//Return-Type:
longint
lHeight=GetHeight("NewPdl0.Pdl","Text1");//Return-Type:
longint
if((lX>=lLeft)&&(lY>=lTop)&&(lX<=lLeft+lWidth)&&(lY<=lTop+lHeight)){
sprintf(szStr,"%d,%d",lX,lY);
SetText("NewPdl0.Pdl","Text1",szStr);//Return-Type:
char*
}
//printf("TheText1Posisx:
%d,y:
%d\r\n",lLeft2,lTop-lTop2);
over:
return0;
}
46:
如何实现ASP与WinCCV6数据库sqlserver2000的连接?
WinCCV6用ODK获取DSN名,{后生成网址字符串,再用shellExecuteA函数打开网页
//----------------------------------------------------------------------------------
#pragmacode("shell32.dll")
longShellExecuteA(HWND,LPCTSTR,LPCTSTR,LPCTSTR,LPCTSTR,int);
#pragmacode()
chardsnStr[100];
HWNDhwnd;
sprintf(dsnStr,"http:
//dcount/test.asp?
dsnStr=%s",GetDSN
(1));//Return-Type:
LPCTSTR
printf("\r\n%s",dsnStr);
hwnd=FindWindow(NULL,"WinCC-Runtime");
ShellExecuteA(hwnd,"open",dsnStr,NULL,"C:
\\",SW_SHOWNORMAL);
//-------------------------------------------------------------------------------------
ASP方面需要注意的是连接字符串的形式与普通acessODBC不太一样,而且需要用户名和密码
由于WINCC封装的sa用户的密码暂时不知道,所以必须用SQLServerEnterPriseManager建立自己的用户,添加systemAdministrator权限就可以了!
否则会出现错误提示
MicrosoftOLEDBProviderforSQLServer错误'80040e4d'
Loginfailedforuser'sa'.
'--------------------------------------------------------------------------------------
dsnStr=request("dsnStr")
setconn=server.createobject("adodb.connection")
setrs=server.createobject("adodb.recordset")
conn.Provider="sqloledb"
conn.open"Server=DCOUNT\WINCC;Database="&dsnStr&";UID=dcount;pwd=;"
rs.open"select*fromtest",conn,1,1
response.writers.recordcount
dowhilenotrs.eof
response.writers("f1")&"---"&rs("f2")&"---"&rs("f3")
rs.movenext
loop
rs.close
conn.close
47:
如何在退出WINCC监控时直接关闭电脑?
1.利用动态向导
2.在脚本中加入DMExitWinCCEx(DM_SDMODE_SYSTEM);也可以
48:
如何通过WINCCAPI函数读出当前报警消息?
1、使用GMsgFunction中读出当前报警信息的ID(dwMsgNr);
2、使用MSRTGetMsgCSData函数读出该报警信息ID对应文本库TEXTLIB中的文本ID(dwTextID1);
3、使用MSRTGetMsgText函数读出该文本ID的文本。
信息到达处理:
如果读取文本成功,则置文本变量MSG。
信息离去处理:
如果MsgNr与上一次相同,则复位MSG,如果不是,则继续保持信息。
具体函数说明请看ODK文档
BOOLGMsgFunction(char*pszMsgData)
{
#pragmacode("msrtcli.dll")
#include"msrtapi.h"
#pragmacode();
MSG_TEXT_STRUCTtMeld;
MSG_CSDATA_STRUCTsM;
CMN_ERRORerr;
BOOLbRet;
DWORDdwTextID1;
DWORDdwMsgNum;
charszMsg[255];
#defineTAG_MSG"MSG"
MSG_RTDATA_STRUCTmRT;
memset(&mRT,0,sizeof(MSG_RTDATA_STRUCT));
if(pszMsgData!
=NULL)
{
printf("Meldung:
%s\r\n",pszMsgData);
sscanf(pszMsgData,"%ld,%ld,%04d.%02d.%02d,%02d:
%02d:
%02d:
%03d,%ld,%ld,%ld,%d,%d",
&mRT.dwMsgNr,//Meldungsnummer
&mRT.dwMsgState,//StatusMSG_STATE_COME,.._GO,.._QUIT,.._QUIT_SYSTEM
&mRT.stMsgTime.wYear,//Tag
&mRT.stMsgTime.wMonth,//Monat
&mRT.stMsgTime.wDay,//Jahr
&mRT.stMsgTime.wHour,//Stunde
&mRT.stMsgTime.wMinute,//Minute
&mRT.stMsgTime.wSecond,//Sekunde
&mRT.stMsgTime.wMilliseconds,//Millisekunde
&mRT.dwTimeDiff,//ZeitdauerderanstehendenMeldung
&mRT.dwCounter,//InternerMeldungsz?
hler
&mRT.dwFlags,//Flags(intern)
&mRT.wPValueUsed,
&mRT.wTextValueUsed);
//**************************************************************************************codefordcount
if(mRT.dwMsgState==MSG_STATE_COME)//信息到达处理
{
dwMsgNum=mRT.dwMsgNr;
printf("\r\nTheAlarmMessageNois%d!
\r\n",dwMsgNum);
bRet=MSRTGetMsgCSData(dwMsgNum,&sM,&err);
if(bRet==TRUE)
{
dwTextID1=sM.dwTextID[0];
printf("\r\nTheTextIDofTheMessageNr%dis%d!
\r\n",dwMsgNum,dwTextID1);
bRet=MSRTGetMsgText(1,dwTextID1,&tMeld,&err);
if(bRet==TRUE)
{
sprintf(szMsg,"%s",tMeld.szText);
printf("\r\nTheTextofTextID%dis%s!
\r\n",dwTextID1,szMsg);
}
}
}
if(mRT.dwMsgState==MSG_STATE_GO)//信息离去处理
{
dwMsgNum=mRT.dwMsgNr;
if(dwMsgNum==GetTagDWord(TAG_MSG_NR))SetTagChar(TAG_MSG,"");
}
//**************************************************************************************codefordcount
//Meldungsdateneinlesen
//Prozesswertelesen,fallsgew?
?
?
?
?
?
?
§?
?
?
1nscht
}
printf("Nr:
%d,St:
%x,%d-%d-%d%d:
%d:
%d.%d,Dur:
%d,Cnt%d,Fl%d\r\n",
mRT.dwMsgNr,mRT.dwMsgState,mRT.stMsgTime.wDay,mRT.stMsgTime.wMonth,mRT.stMsgTime.wYear,
mRT.stMsgTime.wHour,mRT.stMsgTime.wMinute,mRT.stMsgTime.wSecond,mRT.stMsgTime.wMilliseconds,mRT.dwTimeDiff,
mRT.dwCounter,mRT.dwFlags);
SetTagChar(TAG_MSG,szMsg);
return(TRUE);
}
49:
如何实现用户登陆日志(wincc中用c脚本实现?
)(柳树成林原创)
用户登陆日志:
(包括用户的登陆退出信息,以便查询在什么时间段是哪个用户在使用这个监控软件)
#include"apdefap.h"
intgscAction(void)
{
#pragmacode("kernel32.dll")
VOIDGetLocalTime(LPSYSTEMTIMElpSystemTime);
#pragmacode()
char*username;
charbuf[128];
staticcharpreuser[128];
unsigneda,b,c,d,e,f;
FILE*fp;
SYSTEMTIMEsysTime;
//读取系统时间,并且复制给变量a,b,c,d,e,f
GetLocalTime(&sysTime);
a=sysTime.wHour;
b=sysTime.wMinute;
c=sysTime.wSecond;
f=sysTime.wYear;
e=sysTime.wMonth;
d=sysTime.wDay;
//得到当前用户名称
username=GetTagChar("@CurrentUser");
fp=fopen("c:
\\wincclog.txt","a+");
if(strcmp(username,preuser)!
=0)//如果当前用户名称和前一个用户名不同
{
if((strcmp(username,"")!
=0)&&(strcmp(preuser,"")==0))//如果当前用户名称不空同时前一个用户名为空
{
sprintf(buf,"用户:
%s\t登陆时间是:
\t%d-%d-%d,%d-%d-%d\n",username,a,b,c,d,e,f);
fputs(buf,fp);
}
else
{
if((strcmp(username,"")==0)&&(strcmp(preuser,"")!
=0))//如果当前用户名称为空同时前一个用户名不空
{
sprintf(buf,"用户:
%s\t退出时间是:
\t%d-%d-%d,%d-%d-%d\n",preuser,a,b,c,d,e,f);
fputs(buf,fp);
}
else
{
sprintf(buf,"用户:
%s\t退出时间是:
\t%d-%d-%d,%d-%d-%d\n",preuser,a,b,c,d,e,f);
fputs(buf,fp);
sprintf(buf,"用户:
%s\t登陆时间是:
\t%d-%d-%d,%d-%d-%d\n",username,a,b,c,d,e,f);
fputs(buf,fp);
}
}
}
strcpy(preuser,username);
fclose(fp);
return0;
}
50:
在wincc画面编辑器里注册的OCX控件,由于开发时没有考虑到wincc标准控件中具备层次哪个属性!
所以不能够通过画面编辑器里的菜单进行设置OCX控件的层次关系!
建议不要把wincc中注册的OCX控件和wincc本身的标准控件重叠放置,否则wincc本身的标准控件将被覆盖!