項目背景
設備中運動控制由運動控制器進行控制,產品有多個點位需要拍攝,這些點位可以由產品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