这是一次健全检查,因为我失去了我的。
我有一个方法IsCaptured()
,它将枚举状态成员与给定值进行比较并返回bool
。我结合使用鼠标阈值检查来确定是否应该发送拖动开始消息并开始拖动操作。问题是当它不应该被鼠标移动时触发。我添加了跟踪消息如下:
TRACE(L"%s\n", (IsCaptured()) ? L"true" : L"false");
CPoint delta = pt - m_trackMouse;
static CPoint thresh(GetSystemMetrics(SM_CXDRAG), GetSystemMetrics(SM_CYDRAG));
if (IsCaptured() &&
abs(delta.x) >= thresh.x || abs(delta.y) >= thresh.y)
{
TRACE(L"%s\n", (IsCaptured()) ? L"true" : L"false");
// Send message to enter drag mode
bool bDrag = ::SendMessage(m_trackWnd, WM_DD_BEGIN, ::GetDlgCtrlID(m_trackWnd), (LPARAM)(void*)&m_info) != 0;
// ...
}
现在奇怪的部分,输出:
false
false
该方法是这样实现的,m_dragState
设置为NONE
,直到拦截了一个按钮:
enum { NONE, CAPTURED, DRAGGING };
bool IsCaptured() const { return m_dragState == CAPTURED; }
我尝试重建整个解决方案无济于事。我正在运行VS2010 Debug 64位,该程序是一个单线程MFC应用程序。什么$ @#!正在这里?
答案 0 :(得分:8)
你的输出没什么奇怪的。 &&
的优先级高于||
,这就是您
if (IsCaptured() &&
abs(delta.x) >= thresh.x || abs(delta.y) >= thresh.y)
被解释为
if ((IsCaptured() && abs(delta.x) >= thresh.x) ||
abs(delta.y) >= thresh.y)
即。如果符合abs(delta.y) >= thresh.y
条件,则整个if
条件的结果完全不依赖于您的IsCaptured()
。
编译器并不关心您在换行符中“表达”了您的意图。运算符优先级很重要。换行没有。
你显然打算做的是
if (IsCaptured() &&
(abs(delta.x) >= thresh.x || abs(delta.y) >= thresh.y))
请注意在||
子表达式的操作数周围放置额外大括号。
答案 1 :(得分:1)
将此视为:
(IsCaptured() && abs(delta.x) >= thresh.x || abs(delta.y) >= thresh.y)
这样:
(false && true) || true
你的IsCaptured()不一定是真的进步,所以在两个打印输出中它很可能都是假的。
答案 2 :(得分:0)
您应该首先确保两个假的不同时引用第一条跟踪线。
如果第二条跟踪线在这里实际打印为假,您可能手上有经典的竞争条件,需要防范它。