MFC 按鈕按下彈起事件

項目背景

​ 設備中運動控制由運動控制器進行控制,產品有多個點位需要拍攝,這些點位可以由產品CAD映射,即將CAD中的拍攝座標映射到設備座標系,那麼需要人工標定基準點位,建立CAD座標系與設備座標系之間的聯繫。在人工標定時,控制器驅動各軸(X,Y,Z)到達指定位置後記錄座標。

​ 每次驅動一個軸,按下方向按鈕時,指定軸朝指定方向運動,鬆開按鈕則運動停止。並且要求運動過程中在界面的編輯框內實時顯示軸的當前位置。

​ 注意需要考慮擴展性,即未來可能增加多個這樣的按鈕。

實現

​ 按下“+”按鈕正向運動,按下“-”負向運動,則可模擬爲正向計數和負向計數。由一個變量保存計數值,需要另開一個線程實時將計數值顯示在編輯框中。此外,按下按鈕和彈出按鈕屬於兩個事件,重寫一個集成CButton的類,按下和彈起按鈕後將消息傳給對話框處理。

重寫按鈕類

  • 新建繼承自CButton的類 RealButton,在類中重寫 OnWndMsg函數。
#pragma once
#include "afxwin.h"
class RealButton :
	public CButton
{
public:
	RealButton();
	~RealButton();
	virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);
};
#include "stdafx.h"
#include "RealButton.h"
RealButton::RealButton()
{
}
RealButton::~RealButton()
{
}
BOOL RealButton::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	// TODO:  在此添加專用代碼和/或調用基類
	int ID;
	switch (message)
	{
	case WM_LBUTTONDOWN:
		 ID = GetDlgCtrlID();
		::PostMessage(GetParent()->m_hWnd, ID, 1, 0);
		break;		
	case WM_LBUTTONUP:
		ID = GetDlgCtrlID();
		::PostMessage(GetParent()->m_hWnd, ID, 0, 0);
		break;
	}
	return CButton::OnWndMsg(message, wParam, lParam, pResult);
}
  • 將按鈕和重寫了類進行綁定。
//聲明
RealButton m_positive;
RealButton m_negetive;

//在 DoDataExchange 函數中綁定
DDX_Control(pDX, IDC_POSITTIVE, m_positive);
DDX_Control(pDX, IDC_NEGETIVE, m_negetive);
  • 計數函數。
//全局變量,保存當前值和方向
static int g_value = 0;
static int g_dir = 0;

//開始動作
void CKeyTestDlg::GetValue(int Dir)
{
	m_press = true;
	while (m_press)
	{
		if (1 == Dir)
		{
			++g_value;
		}
		else
		{
			--g_value;
		}
		SetDlgItemInt(IDC_VALUE, g_value);
		Sleep(100);
	}	
}

//停止
void CKeyTestDlg::StopMove()
{
	m_press = false;
}
  • 開啓線程。
//聲明
HANDLE m_hMoveThread;
HANDLE m_evtQuit;
HANDLE m_evtMove;

//創建線程
m_evtQuit = ::CreateEvent(NULL, false, false, NULL);
m_evtMove = ::CreateEvent(NULL, false, false, NULL);
DWORD dwThreadID;		 //線程ID
//創建點亮光源線程
m_hMoveThread = CreateThread(NULL, 0, pMoveThread, this, NULL, &dwThreadID);

//線程響應函數
static DWORD WINAPI pMoveThread(LPVOID lpParam)
{
	CKeyTestDlg *pDlg = (CKeyTestDlg *)lpParam;
	HANDLE hEvent[2];
	hEvent[0] = pDlg->m_evtQuit;	//線程關閉
	hEvent[1] = pDlg->m_evtMove;		//拍照消息
	while (TRUE)
	{
		DWORD dwRet = 0;
		dwRet = WaitForMultipleObjects(2, hEvent, FALSE, INFINITE);
		DWORD n = dwRet - WAIT_OBJECT_0;
		if (0 == n)
		{
			TRACE(_T("退出線程"));
			break;
		}
		else if (1 == n)
		{
			pDlg->GetValue(g_dir);
		}
	}
	return 0;
}
  • 對話框重寫 OnWndMsg 函數。
BOOL CKeyTestDlg::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	// TODO:  在此添加專用代碼和/或調用基類
	switch (message)
	{
	case IDC_POSITTIVE://“+”按鈕的ID號
		if (wParam == 1)
		{
            //按鈕按下
			g_dir = 1;
			SetEvent(m_evtMove);
		}
		else
		{
            //按鈕彈起
			StopMove();
		}
		break;
	case IDC_NEGETIVE://“-”按鈕的ID號
		if (wParam == 1)
		{
			g_dir = 0;
			SetEvent(m_evtMove);
		}
		else
		{
			StopMove();
		}
		break;

	}
	return CDialogEx::OnWndMsg(message, wParam, lParam, pResult);
}
  • 最後不要忘了,重寫 Close 消息處理函數,關閉線程。
void CKeyTestDlg::OnClose()
{
	// TODO:  在此添加消息處理程序代碼和/或調用默認值
	SetEvent(m_evtQuit);//線程退出

	CloseHandle(m_evtMove);
	m_evtMove = NULL;
	CloseHandle(m_evtQuit);
	m_evtQuit = NULL;

	CloseHandle(m_hMoveThread);
	m_hMoveThread = NULL;
	CDialogEx::OnClose();
}

代碼鏈接://download.csdn.net/download/u010354182/12259501

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章