📄 tchstub.cpp
字号:
if ((0 != (Flags&TouchSamplePreviousDownFlag)) &&
(0 == (Flags&TouchSampleDownFlag)) ) // for the first sample with the pen up
{
// check for errors, stop and report them if so. Ignore short strokes as the measurement is likely to be inaccurate
//@todo - should this be every stroke, or average out for 5 strokes, or maybe every 5th stroke?
if (nTicksNow - nStrokeStartTick > SMALL_STROKE_THRESHOLD)
{
// calculate statistics
if (nTicksNow != nStrokeStartTick)
samplesPerSecond = (sampleCount*1000)/(nTicksNow - nStrokeStartTick);
if (nLongIntervalCount)
nLongIntervalAvg = nLongIntervalSum/nLongIntervalCount;
else
nLongIntervalAvg = 0;
if (nPointSkips)
{
nPointSkipAvg = nPointSkipSum/nPointSkips;
}
else
nPointSkipAvg = 0;
if (nLongIntervalCount > 0 || nPointSkips > 0 || samplesPerSecond < POINT_RATE_THRESHOLD)
{
if( !_bNoDbgMsg )
{
static HANDLE hThread = NULL;
DWORD dwExitCode = 0;
// Check the Exit code of the Error message thread to see if there is a thread already running.
// If the thread is still active, skip this message. (This will be always logged to the file.)
if( hThread )
GetExitCodeThread(hThread, &dwExitCode);
if( NULL == hThread || STILL_ACTIVE != dwExitCode)
{
EnterCriticalSection(&csErrMsg);
// Fill the global error message buffer.
wsprintf(_szErrorMsg,
TEXT("TRANSCRIBER MAY NOT WORK WELL GIVEN THE CURRENT POINT RATE AND LATENCY! ")
TEXT("INKSAMP2 at osfiles\\PUBLIC\\COMMON\\OAK\\DEMOS can help debug this.\n")
TEXT("Samples per second: %d (100 min) \n Long intervals: %d (0 Max) \n Avg. long interval duration %d\n Total long interval duration %d\n Ink skips %d (0 max)\n Avg Ink Skip squared %d."),
samplesPerSecond, nLongIntervalCount, nLongIntervalAvg, nLongIntervalSum, nPointSkips, nPointSkipAvg);
LeaveCriticalSection(&csErrMsg);
// Create a new thread to display the error message, to make sure that we are not blocking the
// touch driver thread so that touch driver will be active even with the message box.
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TchMessageBoxThread, NULL, 0, NULL);
if( NULL == hThread )
{
MYERRORMSG(1, (__TEXT("Couldn't create touchstub window thread.\r\n")));
}
// Since we have shown this msg once, turn off the message box.
_bNoDbgMsg = TRUE;
}
}
// Log the error to a log file also.
HANDLE hFile;
// Open/Create the log file.
hFile = CreateFile(TEXT("\\tchDbg.log"), GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
DWORD dw = 0;
int len;
int i;
TCHAR szBuffer[2*MAX_PATH];
unsigned char strLogMsg[2*MAX_PATH];
// Check if the log file already exist and we just opened it.
if( 0 == GetLastError() )
{
// This file did not exist before, so write the header information for the log.
SetFilePointer(hFile, 0, NULL, FILE_END);
wsprintf(szBuffer, L"TRANSCRIBER MAY NOT WORK WELL GIVEN THE CURRENT POINT RATE AND LATENCY! \n"
L"INKSAMP2 at osfiles\\PUBLIC\\COMMON\\OAK\\DEMOS can help debug this.\n"
L"Log contains the following values:\n"
L"Samples per second: (100 min), Long intervals: (0 Max), Avg. long interval duration, Total long interval duration, Ink skips (0 max), Avg Ink Skip squared.\n" );
len = _tcslen(szBuffer);
for (i = 0; i < len; i ++)
strLogMsg[i] = (unsigned char)szBuffer[i];
strLogMsg[len] = 0;
WriteFile(hFile, strLogMsg, len, &dw, NULL);
}
// Make sure we are at the end of the file.
SetFilePointer(hFile, 0, NULL, FILE_END);
// Fill the buffer
wsprintf(szBuffer, L"%d , %d , %d , %d , %d , %d \n",
samplesPerSecond, nLongIntervalCount, nLongIntervalAvg, nLongIntervalSum, nPointSkips, nPointSkipAvg);
// Copy the Wide char string to uchar string.
len = _tcslen(szBuffer);
for (i = 0; i < len; i ++)
strLogMsg[i] = (unsigned char)szBuffer[i];
strLogMsg[len] = 0;
// Write the string to the log file.
WriteFile(hFile, strLogMsg, len, &dw, NULL);
CloseHandle(hFile);
}
}
}
}
#endif
if (NULL == *_phStubWnd)
IsStubWndExist();
dwTick = GetTickCount();
// Check if we need to send this point to system or transcriber.
// If we are are in Out Of Memory state (Indicated by Tch thread in high priority), which prevents us from
// communicating with transcriber, we need to send the points to system instead of transcriber.
if( _hClientWnd==NULL ||
_bTchThreadHighPriority ||
*_phStubWnd==NULL ||
(Flags&TouchSampleValidFlag)==0 ||
(Flags&TouchSampleIgnore)!=0)
{
#ifdef DEBUG1
wsprintf(str, TEXT(" *** CgrCallback - sending point to (%x) *** \n"), v_pfnCgrPointCallback);
OutputDebugString( str);
#endif
(*v_pfnCgrPointCallback)(Flags, X, Y);
return 0;
}
// PostMessage(*_phStubWnd, WM_STUB_TABLET, dwTick,((Flags<<26)|((X&0x01FFF)<<13)|(Y&0x01FFF)));
// StubCallback2(dwTick, Flags, X, Y);
#ifdef DEBUG1
wsprintf(str, TEXT(" *** CgrCallback - Transcriber is eating point (%d,%d) to hwnd %x*** \n"), X, Y, _hClientWnd);
OutputDebugString( str);
#endif
SendPtToSelf(Flags, X, Y);
return 0;
}
/* *********************************************************************************** */
// This takes points off the internal Touch Driver queue (Q2) and decides where to send them
// - either to Transcriber, or back to the system
void StubCallback2(
DWORD dwTick0,
TOUCH_PANEL_SAMPLE_FLAGS Flags,
INT X,
INT Y
)
{
DWORD dwTick = dwTick0;
TOUCH_PANEL_SAMPLE_FLAGS FlagsToDll = Flags, FlagsToWnd = Flags;
#if WRITE_STATISTICSINNER // turn on to see points we place into the queue for the app
{
static int _iStat1Writes = 0;
static int _iStat1Current = 0;
static short _iStat1Buf[MAX_STATS][3] = {0};
static int count = 0;
_iStat1Buf[_iStat1Current][0] = (short)Flags;
_iStat1Buf[_iStat1Current][1] = (short)X;
_iStat1Buf[_iStat1Current][2] = (short)Y;
_iStat1Current++;
if(_iStat1Current==MAX_STATS)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
int i;
_iStat1Current = 0;
hFile = CreateFile(L"\\tchlogInner.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
DWORD dw = 0;
int len;
int j;
SetFilePointer(hFile, 0, NULL, FILE_END);
for (i = 0; i < MAX_STATS; i++)
{
TCHAR str[64];
unsigned char str2[64];
wsprintf(str, L"%d %d %d %d %c%c", count++, (int)_iStat1Buf[i][1], (int)(3000 - _iStat1Buf[i][2]), (int)_iStat1Buf[i][0], (TCHAR)13, (TCHAR)10);
len = _tcslen(str);
if(len > 62)
len = 62;
for (j = 0; j < len; j ++)
str2[j] = (unsigned char)str[j];
str2[len] = 0;
WriteFile(hFile, str2, len, &dw, NULL);
}
CloseHandle(hFile);
}
}
}
#endif
// if we don't have a callig client window or bad sample or we are ignoring it,
// or we are in Out Of Memory state (Indicated by Tch thread in high priority), which prevents us from
// communicating with transcriber, pass back to the system (so the app "underneath" transcriber will get them)
if(_hClientWnd==NULL ||
_bTchThreadHighPriority ||
(Flags&TouchSampleValidFlag)==0 ||
(Flags&TouchSampleIgnore)!=0)
{
(*v_pfnCgrPointCallback)(Flags, X, Y);
#ifdef DEBUG2
OutputDebugString(L"CgrTouch Point 1\n");
#endif
return;
}
// Intercept points here
//1. test window at stroke begining
// 0x07 means pen down, valid, callib, but pen wasn't down for the previous pt
if(Flags==0x07)
{
if(!IsWindow(_hClientWnd))
{
_hClientWnd = NULL;
(*v_pfnCgrPointCallback)(Flags, X, Y);
#ifdef DEBUG2
OutputDebugString(L"CgrTouch Point 2\n");
#endif
return;
}
// set flags
_iClientFlags = (int)GetWindowLong(_hClientWnd, 0);
//just adjust
if((_iClientFlags&TABLET_TEST_FIRST_POINT)!=0 &&
!SendMessage(_hClientWnd, WM_PEGREC_FIRSTPOINT, 0, MAKELPARAM(X, Y)))
{
_iClientFlags = TABLET_ALL_TO_SYSTEM;
}
if((_iClientFlags&TABLET_SMART_TO_SYSTEM)!=0)
_iClientFlags = _iClientFlags&(~TABLET_ALL_TO_SYSTEM);
if((_iClientFlags&TABLET_SAVE_FOCUS_WND)!=0)
{
//@todo - do we need FindForegroundFocusWindow( ) instead of GetForegroundWindow( )?
_hLastTouchFocusWnd = GetForegroundWindow();
}
begTick = dwLastDelayTick = dwTick;
_begX = iLastDelayX = X;
_begY = iLastDelayY = Y;
bClick = FALSE;
bDelay = FALSE;
bNear = TRUE;
} // if(flgs==07)
if((_iClientFlags&TABLET_SMART_TO_SYSTEM)!=0)
{
//2. Is still near?
if( bNear &&
Flags==0x0f /*inter point*/ &&
(Flags&TouchSampleDownFlag)!=0 &&
(_begX-X>=iMaxClickDist || _begX-X<=-iMaxClickDist ||
_begY-Y>=iMaxClickDist || _begY-Y<=-iMaxClickDist))
{ // decision = no click and no initial delay => stop NEAR
bNear = FALSE;
if((_iClientFlags&TABLET_SEND_RELEASE_MSG)!=0)
SendPtToWnd((TouchSamplePreviousDownFlag|TouchSampleDownFlag|TouchSampleIgnore), X, Y);
iLastDelayX = X;
iLastDelayY = Y;
dwLastDelayTick = dwTick;
{
HANDLE hThread=GetCurrentThread();
SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST);
}
}
// IS CLICK?
if( bNear &&
Flags==0x0d /*LAST PT*/ &&
(_iClientFlags&TABLET_CLICK_TO_SYSTEM)!=0 &&
dwTick-begTick < dwMaxClickTime &&
begTick-_dwLastSendedTick > dwMinPauseBeforeClick)
{ //yes - it's click
HWND hWndFgr = GetForegroundWindow();
BOOL bPermition = TRUE;
bClick = TRUE;
_dwLastSendedTick = 0;
if((_iClientFlags&(TABLET_SEND|TABLET_NEED_PERMITION))!=0)
bPermition = (BOOL)SendMessage(_hClientWnd, WM_PEGREC_MOUSECLICK, (WPARAM)hWndFgr, MAKELPARAM(_begX, _begY));
else
PostMessage(_hClientWnd, WM_PEGREC_MOUSECLICK, (WPARAM)hWndFgr, MAKELPARAM(_begX, _begY));
// simulate a click to the app "below" Transcriber (since we already ate the points)
if((_iClientFlags&TABLET_NEED_PERMITION)==0 || bPermition)
{
(*v_pfnCgrPointCallback)(0x07, _begX+1, _begY+1);
(*v_pfnCgrPointCallback)(0x0f, _begX, _begY);
(*v_pfnCgrPointCallback)(0x0f, _begX, _begY);
(*v_pfnCgrPointCallback)(0x0f, _begX, _begY);
(*v_pfnCgrPointCallback)(0x0D, _begX, _begY);
}
else
{
#ifdef DEBUG2
OutputDebugString(L"CgrTouch Point 3\n");
#endif
return;
}
}
// we delay points to see if we should either treat this as a selection or see if
// we should send the point to the application "underneath" Transcriber,
// or tap and hold.
// IS INITIAL DELAY?
if( bNear &&
Flags==0x0f /*intermediate point*/ &&
(_iClientFlags&TABLET_STARTDELAY_TO_SYSTEM)!=0 &&
(dwTick-begTick>1200 ||
(dwTick-begTick>dwMinStartDelayTime &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -