⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hidgetdlg.cpp

📁 這個程序列使用一些小技巧來讀取一個手寫板的數據。這個手寫板是從市面上買回來的﹐沒有修改任何硬體﹐只須接上主機﹐啟動程式﹐用手寫板書寫﹐這個程序就會顯示從手寫板上輸出的數據
💻 CPP
字号:
// HIDGetDlg.cpp : implementation file
//

#include "stdafx.h"
#include "HIDGet.h"
#include "HIDGetDlg.h"
#include "Process.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define WM_THREADDATA	WM_USER + 1
#define WM_READDATA		WM_USER + 2

/////////////////////////////////////////////////////////////////////////////
// CHIDGetDlg dialog
struct _ThreadData
{
	HWND hWnd;
	HANDLE hDev;
	char cBuf[5];
	HANDLE hReadFinished;
}ThreadData;

LRESULT CALLBACK ReadThreadWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	ResetEvent(ThreadData.hReadFinished);
	OVERLAPPED ol;
	ol.hEvent = ThreadData.hReadFinished;
	ol.Offset = 0;
	ol.OffsetHigh = 0;

	DWORD wResult;
	DWORD wByteRead;
	switch(msg)
	{
		case WM_CLOSE:	CancelIo(ThreadData.hDev);
						CloseHandle(ThreadData.hReadFinished);
						DestroyWindow(hWnd);
						break;

		case WM_DESTROY:	PostQuitMessage(0);
							break;

		case WM_READDATA:	ReadFile(ThreadData.hDev, ThreadData.cBuf, 5,
									 &wByteRead, &ol);
							wResult = WaitForSingleObject(ThreadData.hReadFinished, 1000);
							if(wResult==WAIT_OBJECT_0)
								::PostMessage(ThreadData.hWnd, WM_THREADDATA, 0, 0);
							else if(wResult==WAIT_TIMEOUT)
								::PostMessage(hWnd, WM_READDATA, 0, 0);
							break;

		default:	return DefWindowProc(hWnd, msg, wParam, lParam);
	}

	return 0;
}

void ReadThread(CHIDGetDlg* pDlg)
{
	WNDCLASSEX wndclass;
	wndclass.cbSize = sizeof(WNDCLASSEX);
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0 ;
	wndclass.hbrBackground = NULL;
	wndclass.hCursor = NULL;
	wndclass.hIcon = NULL;
	wndclass.hIconSm = NULL;
	wndclass.hInstance = GetModuleHandle(NULL);
	wndclass.lpfnWndProc = ReadThreadWindowProc;
	wndclass.lpszClassName = "ReadThread";
	wndclass.lpszMenuName = NULL;
	wndclass.style = 0 ;
	RegisterClassEx(&wndclass);

	HWND hReadThreadWindow = ::CreateWindow("ReadThread", "", WS_POPUP,
											0, 0, 0, 0,	NULL, NULL,
											GetModuleHandle(NULL), NULL);
	pDlg->SetReadThreadHWND(hReadThreadWindow);
	ThreadData.hReadFinished = CreateEvent(NULL, TRUE, FALSE, NULL);
	SetEvent(pDlg->m_hReadThreadCreated);

	//start the message loop 
	MSG msg;
	while(GetMessage(&msg, NULL, NULL, NULL))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
}

CHIDGetDlg::CHIDGetDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CHIDGetDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CHIDGetDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CHIDGetDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CHIDGetDlg)
	DDX_Control(pDX, IDC_DATA_ED, m_edData);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CHIDGetDlg, CDialog)
	//{{AFX_MSG_MAP(CHIDGetDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_CLOSE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHIDGetDlg message handlers

BOOL CHIDGetDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	GetDeviceHandle();
	CreateReadThread();
	::PostMessage(m_hReadThread, WM_READDATA, 0, 0);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CHIDGetDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CHIDGetDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

HANDLE CHIDGetDlg::GetDeviceHandle(GUID guid, HANDLE hDev, DWORD wDevice)
{
    SP_DEVICE_INTERFACE_DATA interfaceDev;
    interfaceDev.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

    //Get interface
	DWORD wSize = 0;
    if(!SetupDiEnumDeviceInterfaces(hDev, NULL, &guid, wDevice, &interfaceDev) ||
 	   SetupDiGetDeviceInterfaceDetail(hDev, &interfaceDev, NULL, 0, &wSize, NULL))
		return INVALID_HANDLE_VALUE;

    //Create buffer
	SP_INTERFACE_DEVICE_DETAIL_DATA *pDeviceDetail;
	pDeviceDetail = (SP_INTERFACE_DEVICE_DETAIL_DATA*)malloc(wSize);
	pDeviceDetail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);

    if(!SetupDiGetDeviceInterfaceDetail(hDev, &interfaceDev, pDeviceDetail, wSize, &wSize, NULL))
    {
        free(pDeviceDetail);
        return INVALID_HANDLE_VALUE;
    }
	
    //Get device handle
    HANDLE hDevice = CreateFile(pDeviceDetail->DevicePath, GENERIC_READ,
								FILE_SHARE_READ, NULL, OPEN_EXISTING,
								FILE_FLAG_OVERLAPPED, NULL);
    free(pDeviceDetail);

    return hDevice;
}

void CHIDGetDlg::Show(CString str, long n)
{
	CString strN;
	strN.Format("%d", n);
	m_edData.ReplaceSel(str + ":" + strN + "\r\n");
}

void CHIDGetDlg::Show(CString str, CString s)
{
	m_edData.ReplaceSel(str + ":" + s + "\r\n");
}

void CHIDGetDlg::Clear()
{
	int nStart, nStop;
	m_edData.GetSel(nStart, nStop);
	m_edData.SetSel(0, nStop);
	m_edData.Clear();
}

void CHIDGetDlg::GetDeviceHandle()
{
    //Get HID GUID
    GUID guid;
    HidD_GetHidGuid(&guid);

    //Get all present HID interface
    HDEVINFO hDeviceInfo = SetupDiGetClassDevs(&guid, NULL, NULL,
											   DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
	if(hDeviceInfo==INVALID_HANDLE_VALUE) return;

	Clear();
	for(DWORD w=0; w<20; w++)
	{
		if((ThreadData.hDev = GetDeviceHandle(guid, hDeviceInfo, w))!=INVALID_HANDLE_VALUE)
		{

			HIDD_ATTRIBUTES att;
	        if(HidD_GetAttributes(ThreadData.hDev, &att))
			{
				PHIDP_PREPARSED_DATA pPreData;
				if(HidD_GetPreparsedData(ThreadData.hDev, &pPreData))
				{
					HIDP_CAPS cap;
					if(HidP_GetCaps(pPreData, &cap)==HIDP_STATUS_SUCCESS)
					{
						if(att.VendorID==2290 &&
						   att.ProductID==69 &&
						   att.VersionNumber==1 &&
						   cap.Usage==5 &&
						   cap.UsagePage==13)
						{
							HidD_FreePreparsedData(pPreData);
							break;
						}
					}
					HidD_FreePreparsedData(pPreData);
				}
			}
			CloseHandle(ThreadData.hDev);
			ThreadData.hDev = INVALID_HANDLE_VALUE;
		}
	}
    SetupDiDestroyDeviceInfoList(hDeviceInfo);
}

void CHIDGetDlg::OnClose() 
{
	// TODO: Add your message handler code here and/or call default
	::SendMessage(m_hReadThread, WM_CLOSE, 0, 0);
	if(ThreadData.hDev!=INVALID_HANDLE_VALUE)
		CloseHandle(ThreadData.hDev);

	CDialog::OnClose();
}

LRESULT CHIDGetDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam) 
{
	// TODO: Add your specialized code here and/or call the base class
	static long nCount = 0;

	if(message==WM_THREADDATA)
	{			
		CString str;
		str.Format("%d %d %d %d %d %d", nCount++, ThreadData.cBuf[0],
												  ThreadData.cBuf[1],
												  ThreadData.cBuf[2],
												  ThreadData.cBuf[3],
												  ThreadData.cBuf[4]);
		Show("Data", str);
		if(nCount>500)
		{
			Clear();
			nCount = 0;
		}
		::PostMessage(m_hReadThread, WM_READDATA, 0, 0);
	}

	return CDialog::DefWindowProc(message, wParam, lParam);
}

void CHIDGetDlg::CreateReadThread()
{
	ThreadData.hWnd = m_hWnd;
	m_hReadThreadCreated = CreateEvent(NULL, TRUE, FALSE, NULL);
	if(m_hReadThreadCreated)
	{
		DWORD threadID;
		if(0 != _beginthreadex(NULL, 0, (unsigned int (__stdcall *)(void *))ReadThread,
							   this, 0, (unsigned int*)&threadID))
			WaitForSingleObject(m_hReadThreadCreated, INFINITE);
		CloseHandle(m_hReadThreadCreated);
	}
}

void CHIDGetDlg::SetReadThreadHWND(HWND hWnd)
{
	m_hReadThread = hWnd;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -