createevent(createevent js)
React 事件委托
DOM事件发生之后,React通过事件委托减大部分事件代理至Document层.
1 .ReactEventListener:负责给元素绑定事件
2 .ReactEventEmitter:暴露接口给React组件层用于添加事件订阅
3 .EventPluginHub负责管理和注册各种插件
4 .事件分发的时候.React事件系统使用了插件机制来管理不同的事件
1 .可以进行浏览器原生事件的封装,对浏览器兼容性进行处理
2 .React通过syntheticEvent实现跨平台的事件机制
3 .原生事件的升级和改造.
1 .负责事件类型blur,focus,click,submit,touchMove,mouseMove,scroll,drag,load
2 .事件模型符合标准的捕获执行,冒泡流程,可以比较简单的绑定在document上面,和原生DOM事件式一一对应的关系,比较好处理
1 .负责事件类型
mouseEnter,mouseLeave,pointerEbnter,pointerLeave
2 .负责处理一些不支持冒泡的事件
1 .负责事件
onTouchTap
2 .为了解决ios移动端300ms点击延迟.onTouchTap这个事件会忽略300ms后的onClick事件
1 .自定义change事件
1 .为表单元素规范化了select事件,用于input,textarea,contentEditable元素
1 .befoerInput事件以及composition事件.当用户使用拼音输入法输入汉字的时候,这个事件就会被触发
1 .form 的submit,reset
2 .媒体触发事件,video/audio的相关事件onplaying,onprogress,onratechange事件.
1 .discreateEvent离散事件
2 .UserblockingEvent用户阻塞事件:这些事件会阻塞用户的交互,优先级是1
3 .continuousEvent连续事件.优先级是2,最高,不会被打断
串口读不到数据,错误在哪里?
帖了这么多代码还不够啊,你的布尔变量comOpened和hCom的赋值不在这里,有没有调试过这两个值会不会有问题?譬如你的comOpened和comOpened在执行到read()之前根本没有得到机会被初始化为FALSE和NULL的话,这两个变量很有有可能存储的是非零的垃圾值,这样的状态进入到read后也还是会跳过if语句,使hCom未被打开就被ReadFile了。 因此,问题可能不是出在这里,而是其他地方的初始化问题,下断点再看看呢!
如何用C语言控制计算机串口
基本方法是使用CreateFile来建立一个串口文件,然后用overlap的方式进行读写
#define SERAIL_PORT_BUF_MAX (1024*8)
typedef HRESULT (*PFN_CMD_PARSE_DATA)(HANDLE hParseApp, LPCSTR szRspCmd, int nCmdLen);
class CUsbSrvApp// : public CWinApp
{
public:
CUsbSrvApp();
~CUsbSrvApp();
BOOL OnSendData(const char *szBuf, int nLen);// 发送数据
int ComConnect(CString strPort); // 连接COM口
HANDLE OpenComPort(CString strPort, int nBaudRate, int nDataBits, int nStopBits, int nParity, int nFlowCtrlType); // 打开串口
void Close(); // 关闭串口
HANDLE m_hCom;
BOOL m_bConnected;
OVERLAPPED m_OverlappedRead;
OVERLAPPED m_OverlappedWrite;
CWinThread *m_pThread;
PFN_CMD_PARSE_DATA m_pRspCmdFunc; // 用来处理接受数据的CALLBACK
HANDLE m_hParseApp;
};
CUsbSrvApp::CUsbSrvApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
m_bConnected = false;
m_hCom = NULL;
m_pRspCmdFunc = NULL;
}
CUsbSrvApp::~CUsbSrvApp()
{
}
//打开串口通信,并返回串口句柄
HANDLE CUsbSrvApp::OpenComPort(CString strPortName,
int nBaudRate,
int nDataBits,
int nStopBits,
int nParity,
int nFlowCtrlType)
{
DCB dcb;
COMMTIMEOUTS CommTimeOuts ;
COMMCONFIG ComConfig;
HANDLE hComPort;
CString strPort;
strPort.Format("\\\\.\\%s",strPortName); // COM口的文件名应该是 \\.\COMXX
//打开窗口其实就是创建一个文件
hComPort = CreateFile(strPort,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
NULL);
if (INVALID_HANDLE_VALUE == hComPort)
return INVALID_HANDLE_VALUE;
// 设置一些COM口通讯参数和OVERLAP
CommTimeOuts.ReadIntervalTimeout = -1;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0x1388;
SetCommTimeouts( m_hCom, CommTimeOuts ) ;
SetDefaultCommConfig(strPortName, ComConfig, sizeof(COMMCONFIG));
GetCommState(m_hCom, dcb ) ;
dcb.BaudRate = nBaudRate;
dcb.ByteSize = nDataBits;
dcb.StopBits = nStopBits;
dcb.fParity = (NOPARITY != nParity);
dcb.Parity = nParity;
//set the receive char
dcb.EvtChar = 0x0D;
switch(nFlowCtrlType)
{
case 0: //no flow control
break;
case 1://HARD_FLOW_CTRL:
dcb.fOutxCtsFlow = TRUE;
dcb.fOutxDsrFlow = TRUE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = TRUE;
dcb.fRtsControl = RTS_CONTROL_TOGGLE;
break;
case 2://SOFT_FLOW_CTRL:
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
break;
}
BuildCommDCB(_T("baud=115200 parity=N data=8 stop=1"),dcb);
SetCommState(hComPort, dcb ) ;
SetCommMask(hComPort, 0);
SetCommMask(hComPort, EV_RXCHAR|EV_CTS|EV_DSR|EV_RLSD|EV_RING);
SetupComm( hComPort, SERAIL_PORT_BUF_MAX,SERAIL_PORT_BUF_MAX) ;
//clear read and write buffer
PurgeComm( hComPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
return hComPort;
}
void CUsbSrvApp::Close()
{
if(m_bConnected)
{
m_bConnected = false;
CloseHandle(m_hCom);
m_hCom = NULL;
}
}
// 这个线程是监视串口数据,一旦有数据则读取并调用CALLBACK通知客户端
UINT ReceiveComData(LPVOID pParam)
{
CUsbSrvApp *pUsbSrv = (CUsbSrvApp *)pParam;
HANDLE hComPort = pUsbSrv-m_hCom;
DWORD dwEvtMask=0;
DWORD dwErrorFlags;
SetCommMask( hComPort, EV_RXCHAR);
OVERLAPPED osRead;
osRead.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
DWORD dwTransfer = 0;
while(pUsbSrv-m_bConnected)
{
if( !WaitCommEvent( hComPort, dwEvtMask,osRead))
{
if( GetLastError()== ERROR_IO_PENDING)
{
WaitForSingleObject(osRead.hEvent, INFINITE);
if(dwEvtMaskEV_RXCHAR==EV_RXCHAR)
{
COMSTAT ComStat={0} ;
DWORD dwReadLen = 0;
DWORD dwBytesRead = 0;
DWORD dwTotalLen = 0;
ClearCommError(hComPort, dwErrorFlags, ComStat );
dwTotalLen = ComStat.cbInQue;
dwReadLen = (SERAIL_PORT_BUF_MAX dwTotalLen)?dwTotalLen:SERAIL_PORT_BUF_MAX;
BYTE *pBuf = new BYTE[dwTotalLen+1];
memset(pBuf, 0 , dwTotalLen+1);
DWORD nReadBufLen=0;
while(dwTotalLen0)
{
if(FALSE == ReadFile( hComPort, pBuf+nReadBufLen,dwReadLen, dwBytesRead,pUsbSrv-m_OverlappedRead))
{
if(GetLastError() == ERROR_IO_PENDING)
{
GetOverlappedResult(hComPort,osRead, dwTransfer, TRUE );
}
break;
}
nReadBufLen +=dwBytesRead;
dwTotalLen -=dwBytesRead;
dwReadLen -= dwBytesRead;
dwReadLen = (SERAIL_PORT_BUF_MAXdwReadLen)?dwReadLen:SERAIL_PORT_BUF_MAX;
}
if(pUsbSrv-m_pRspCmdFunc!=NULLnReadBufLen!=0)
{
pUsbSrv-m_pRspCmdFunc(pUsbSrv-m_hParseApp, (char*)pBuf,nReadBufLen);
}
delete pBuf;
ClearCommError(hComPort, dwErrorFlags, ComStat );
int len =0;//= m_retList.GetSize();
}//endif if(dwEvtMaskEV_RXCHAR==EV_RXCHAR)
}//endif if( GetLastError()== ERROR_IO_PENDING)
}//endif if( !WaitCommEvent( hComPort, dwEvtMask,o))
else
{
if(GetLastError() == ERROR_IO_PENDING) {
GetOverlappedResult(hComPort, osRead, dwTransfer, TRUE ); // sleep thread
}
}
Sleep(1);
} //endwhile while(m_bConnected)
return 0;
}
int CUsbSrvApp::ComConnect(CString strPort)
{
int nBaudRate = 115200;
int nDataBits = 8;
int nStopBits = 1;
int nParity = 0;
int nFlowCtrl = 1;
if (NULL != m_hCom || m_bConnected)
{
return 0;
}
m_hCom = OpenComPort(strPort,nBaudRate,nDataBits,nStopBits,nParity,nFlowCtrl);
if( INVALID_HANDLE_VALUE == m_hCom)
{
m_hCom = NULL;
return 0;
}
memset( m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_pThread = AfxBeginThread( ReceiveComData,(void*)this,THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED ,NULL );
if( NULL == m_pThread )
{
CloseHandle( m_hCom );
m_hCom = NULL;
return FALSE;
}
else
{
m_bConnected = TRUE;
m_pThread-ResumeThread( );
}
return TRUE;
}
int CUsbSrvApp::OnSendData(const char *szBuf, int nLen)
{
BOOL bWriteStat;
BOOL bWrite = TRUE;
DWORD dwBytesWrite = 0;
DWORD dwBytesWritten = 0;
int dwByteswrittenTotal = 0;
if (NULL == m_hCom)
return 0;
int nSentTimes=0;
while(dwByteswrittenTotalnLennSentTimes10)
{
nSentTimes++;
dwBytesWrite = nLen-dwByteswrittenTotal;
bWriteStat = WriteFile( m_hCom, szBuf+dwByteswrittenTotal, dwBytesWrite, dwBytesWritten, m_OverlappedWrite );
if( !bWriteStat)
{
if ( GetLastError() == ERROR_IO_PENDING )
{
dwBytesWritten = 0;
bWrite = FALSE;
}
}
if (!bWrite)
{
bWrite = TRUE;
bWriteStat = GetOverlappedResult(m_hCom, // Handle to COMM port
m_OverlappedWrite, // Overlapped structure
dwBytesWritten, // Stores number of bytes sent
TRUE); // Wait flag
//deal with the error code
}
dwByteswrittenTotal += dwBytesWritten;
}
if(dwByteswrittenTotalnLen)
return 0;
else
return 1;
}
createeventa是什么函数
CreateEvent是一个Windows API函数。它用来创建或打开一个命名的或无名的事件对象。如果想为对象指定一个访问掩码,应当使用CreateEventEx函数。
vc++中,关于WaitForSingleObject和CreateEvent的用法
ExitHandle是一个标志事件,你可以把它理解为一个BOOL类型的变量
WaitForSingleObject是在指定的时间内等待这个事件发生,如果发生,返回值就是WAIT_OBJECT_0,你可以理解为在指定的时间内判断ExitHandle是否为真.
虽然效果上和BOOL变量类似,但实际上工作原理复杂的多,这涉及到WINDOWS的线程切换及线程同步等相关知识,有兴趣你可以仔细看下相关资料.
如何使用多媒体定时器
Timer定时器是由应用程序响应定时消息WM_TIMER实现定时。Timer定时器是IBM PC硬件和ROM BIOS构造的定时器的简单扩充。PC的ROM初始化8253定时器来产生硬件中断08H,而08H中断的频率为18.2Hz,即至少每隔54.925 ms中断一次。此外,这个定时消息的优先权太低,只有在除WM_PAINT外的所有消息被处理完后,才能得到处理。多媒体定时器也是利用系统定时器工作的,但它的工作机理和普通定时器有所不同。首先,多媒体定时器可以按精度要求设置8253的T/C0通道的计数初值,使定时器不存在54.945ms的限制;其次,多媒体定时器不依赖于消息机制,而是用函数产生一个独立的线程,在一定的中断次数到达后,直接调用预先设置好的回调函数进行处理,不必等到应用程序的消息队列为空,从而切实保障了定时中断得到实时响应,使其定时精度可达1ms。(4)在TimerThread.h文件中定义宏,代码如下:#define WM_THREADMSG WM_USER+1(5)在TimerThread.h文件中定义数据结构,代码如下:typedef struct THREAD_PARAM{ HWND hWnd; int nTime; HANDLE hTimerEvent; HANDLE hExitEvent;}_THREAD_PARAM;(6)在CWinThread类中添加成员变量,代码如下:public: THREAD_PARAM* m_pThreadParam;(7)在CTimerThread类中重载CWinThread::Run函数,代码如下:// TimerThread.cpp int CTimerThread::Run(){ while (TRUE) { //等待定时事件 while (WAIT_TIMEOUT == WaitForSingleObject(m_pThreadParam-hTimerEvent, 200)) { //等待退出事件 if (WaitForSingleObject(m_pThreadParam-hExitEvent, 0) == WAIT_OBJECT_0) { ::AfxEndThread(0); } } m_pThreadParam-nTime += 100; //向主线程窗口发送消息 ::PostMessage(m_pThreadParam-hWnd, WM_THREADMSG, 0, 0); //复位定时事件 ResetEvent(m_pThreadParam-hTimerEvent); }}(8)在CDemoDlg类中添加成员变量,代码如下:// DemoDlg.cpp private: UINT m_nTimerID; CTimerThread* m_pTimerThread; THREAD_PARAM m_ThreadParam;(9)在CDemoDlg类的构造函数和析构函数中添加如下代码:// DemoDlg.cpp CDemoDlg::CDemoDlg(CWnd* pParent /*=NULL*/) : CDialog(CDemoDlg::IDD, pParent){ // … m_nTimerID = 0; m_pTimerThread = NULL; m_ThreadParam.nTime = 0; m_ThreadParam.hTimerEvent = CreateEvent(NULL, TRUE, FALSE, NULL); m_ThreadParam.hExitEvent = CreateEvent(NULL, TRUE, FALSE, NULL);}CDemoDlg::~CDemoDlg(){ //取消定时器 if (m_nTimerID != 0) { timeKillEvent(m_nTimerID); } //结束定时线程 if (m_pTimerThread != NULL) { //设置退出事件 SetEvent(m_ThreadParam.hExitEvent); //等待定时线程结束 ::WaitForSingleObject(m_pTimerThread-m_hThread, INFINITE); delete m_pTimerThread; m_pTimerThread = NULL; } CloseHandle(m_ThreadParam.hTimerEvent); CloseHandle(m_ThreadParam.hExitEvent);}(10)在CDemoDlg类中为重载CDialog::OnInitDialog函数,代码如下:// DemoDlg.cpp BOOL CDemoDlg::OnInitDialog(){ CDialog::OnInitDialog(); // … SetDlgItemInt(IDC_TIME, 0); return TRUE;}(11)在CDemoDlg类中为WM_THREADMSG添加消息处理函数,代码如下:// DemoDlg.cpp BEGIN_MESSAGE_MAP(CDemoDlg, CDialog) //{{AFX_MSG_MAP(CDemoDlg) // … ON_MESSAGE(WM_THREADMSG, OnMsgFunc) //}}AFX_MSG_MAPEND_MESSAGE_MAP() LRESULT CDemoDlg::OnMsgFunc(){ SetDlgItemInt(IDC_TIME, m_ThreadParam.nTime); return 1;}(12)在CDemoDlg类中为Button控件添加BN_CLICKED消息处理函数,代码如下:// DemoDlg.cpp void CDemoDlg::OnTest1(){ //取消定时器 if (m_nTimerID != 0) { timeKillEvent(m_nTimerID); } //结束定时线程 if (m_pTimerThread != NULL) { //设置退出事件 SetEvent(m_ThreadParam.hExitEvent); //等待定时线程结束 ::WaitForSingleObject(m_pTimerThread-m_hThread, INFINITE); delete m_pTimerThread; m_pTimerThread = NULL; } m_ThreadParam.hWnd = GetSafeHwnd(); m_ThreadParam.nTime = 0; SetDlgItemInt(IDC_TIME, 0); TIMECAPS tc; //获得定时器分辨率 if (timeGetDevCaps(tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) { return; } UINT nResolution = min(max(tc.wPeriodMin, 1), tc.wPeriodMax); UINT nInterval = 100; if (nInterval nResolution) { nInterval = nResolution; } //设置定时最小分辨率 timeBeginPeriod(nResolution); //设置定时器 m_nTimerID = timeSetEvent(nInterval, nResolution, (LPTIMECALLBACK)m_ThreadParam.hTimerEvent, (DWORD)this, TIME_PERIODIC | TIME_CALLBACK_EVENT_SET); //创建定时线程 m_pTimerThread = (CTimerThread*)AfxBeginThread(RUNTIME_CLASS(CTimerThread), THREAD_PRIORITY_ABOVE_NORMAL, 0, CREATE_SUSPENDED); m_pTimerThread-m_bAutoDelete = FALSE; m_pTimerThread-m_pThreadParam = m_ThreadParam; m_pTimerThread-ResumeThread();}void CDemoDlg::OnTest2(){ //取消定时器 if (m_nTimerID != 0) { timeKillEvent(m_nTimerID); } //结束定时线程 if (m_pTimerThread != NULL) { //设置退出事件 SetEvent(m_ThreadParam.hExitEvent); //等待定时线程结束 ::WaitForSingleObject(m_pTimerThread-m_hThread, INFINITE); delete m_pTimerThread; m_pTimerThread = NULL; }}