c++ - 没有标题的 Visual Studio 2008 MFC 拖动对话框并检测所有鼠标事件

标签 c++ mfc

我被要求向现有程序添加新功能。该程序由一个没有标题/边框的对话框组成。我需要几样东西:

  1. 当用户在对话框区域内简单地点击时,关闭它;
  2. 当用户在其区域内按下鼠标并拖动时移动对话框

这是我目前的发现:

void MyDialog::onMessageReceived(UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
    case WM_LBUTTONDOWN:
        lastX=LOWORD(lParam);
        lastY=HIWORD(lParam);
        SendMessage(DlgHandle, WM_NCLBUTTONDOWN, HTCAPTION, NULL);
        break;
    case WM_LBUTTONUP:
        if (LOWORD(lParam)==lastX && HIWORD(lParam)==lastY)
            onKillButtonClick();
        break;
}}

编辑: 这个函数是这样调用的:

INT_PTR CALLBACK MyDialog::dialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    _this->onMessageReceived(uMsg, wParam, lParam);
} 

移动窗口效果很好,但看起来 WM_LBUTTONUP 事件丢失了。我必须单击两次才能将其解雇。 希望有人能帮助我...

编辑: 使用 Spy++,我看到 WM_LBTTONUP 被触发,但紧接在一个新的 WM_NCLBUTTONDOWN 被发射之后。

最佳答案

首先,我同意 Michael Walz 的观点——这是一个非常令人困惑的行为:鼠标松开事件的处理取决于它是否移动了……如果它移动了一点点怎么办?我宁愿用不同的操作关闭此对话框 - 单击图标、右键单击等。

但是,让用户移动无标题窗口的正确方法是处理 WM_NCHITTEST 消息并返回 HTCAPTION:

case WM_NCHITTEST:
    SetWindowLong(hDlg, DWL_MSGRESULT, HTCAPTION);
    return HTCAPTION;

不幸的是,Windows 随后将接管所有鼠标事件,因此,如您所见,您将永远不会获得 WM_LBUTTONUP。您可以选择设置一个短计时器,看看用户是否开始移动您的窗口;当您收到 WM_ENTERSIZEMOVE 消息时取消它。如果该计时器触发 - 关闭您的窗口。是的,这也很尴尬,但仅此而已。

另一种方法是自己处理移动:

static bool bDragging(false), bMoved(false);
static POINT pt1 = {}, pt2 = {};
static RECT r;
switch (message)
{
case WM_LBUTTONDOWN:
    GetWindowRect(hDlg, &r);
    pt1 = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
    ClientToScreen(hDlg, &pt1);
    bDragging = true;
    bMoved = false;
    break;
case WM_MOUSEMOVE:
    if (bDragging)
    {
        pt2 = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
        ClientToScreen(hDlg, &pt2);
        if (pt2.x != pt1.x || pt2.y != pt1.y)
        {
            OffsetRect(&r, pt2.x - pt1.x, pt2.y - pt1.y);
            SetWindowPos(hDlg, 0, r.left, r.top, 0, 0, SWP_NOSIZE);
            pt1 = pt2;
            bMoved = true;
        }
    }
    break;
case WM_LBUTTONUP:
    bDragging = false;
    if (!bMoved)
        PostMessage(hDlg, WM_COMMAND, IDCANCEL, 0);
    bMoved = false;
    break;
}
return (INT_PTR)FALSE;

关于c++ - 没有标题的 Visual Studio 2008 MFC 拖动对话框并检测所有鼠标事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36175021/

相关文章:

c++ - libzip 无法关闭文件

c++ - 如何将 CS_DROPSHADOW 应用于 CDialog 的子类

c++ - 如何从 MFC 应用程序调用函数的 Win32 API 版本?

c++ - 写入大于2Gb的文件

c++ - 我从 Wireshark 获得了 C 数组形式的数据,现在我在以正常形式解码它时遇到了麻烦

c++ - 了解构造函数概念

c++ - 第二个无效响应在我的验证循环中被接受

mfc - 在 Windows 7 中将显示更改为 125% 时,MFC 中的控件被切断

c++ - 如何为 ON_COMMAND 处理程序声明 ID?

c++ - Windows 上的远程音响系统