В OpenCV, кажется, действие двойного щелчка также вызывает событие одного щелчка. Вот пример кода. Single_click () всегда вызывается перед double_click ().
Можно ли вызвать double_click () без предварительного запуска single_click ()?
Спасибо!
void double_click() {
std::cout << "Double click.\n";
}
void thisMouseCallBack(int event, int x, int y, int flags, void *param) {
if (event == cv::EVENT_LBUTTONDOWN) {
single_click();
}
if (event == cv::EVENT_LBUTTONDBLCLK) {
double_click();
}
}
int main() {
cv::Mat testImg(100, 500, CV_8UC3);
cv::namedWindow("thisWindow");
cv::setMouseCallback("thisWindow", thisMouseCallBack, NULL);
cv::imshow("thisWindow", testImg);
cv::waitKey(-1);
return 0;
}
Чтобы различать двойные и одиночные щелчки (т. Е. Запускать только событие двойного щелчка при двойном щелчке и пропускать событие одиночного щелчка), стандартный способ сделать это использует таймер.
Запустите таймер (~ 100-200 мс) по первому клику, но не вызывайте single_click
, Если таймер завершает работу до того, как будет получен другой клик, позвоните single_click
, Но если еще один щелчок получен до окончания таймера, отмените таймер и вызовите double_click
,
Однако, как отмечает Роб Кеннеди выше, это приведет к небольшой задержке, поэтому будьте осторожны с объектами, где вы хотите различать одиночный и двойной щелчок. В большинстве графических интерфейсов один щелчок — это операция выбора, а двойной щелчок — это операция «открыть» или «выполнить», поэтому имеет смысл выбрать объект перед его активацией.
Я написал следующий код, и он работает.
UINT TimerId;
int clicks;
VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
KillTimer(NULL, TimerId);
if (clicks < 2 && !double_click){
MessageBox(hWnd, L"Show Widget", L"Widget", MB_OK);
}
clicks = 0;
}LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
TCHAR szHello[MAX_LOADSTRING];
LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
UINT uID;
UINT uMouseMsg;
uID = (UINT)wParam;
uMouseMsg = (UINT)lParam;
if (uMouseMsg == WM_LBUTTONDBLCLK){
double_click = true;
MessageBox(hWnd, L"Double click", L"CAPT", MB_OK);
return 0;
}
if (uMouseMsg == WM_LBUTTONDOWN){
double_click = false;
clicks++;
//single click opens context menu
if (clicks == 1){
TimerId = SetTimer(NULL, 0, 500, &TimerProc);
}
return 0;
}
,...
}