MFC 单击并移动/拖动对话框窗口

Posted

技术标签:

【中文标题】MFC 单击并移动/拖动对话框窗口【英文标题】:MFC click and move/drag dialog window 【发布时间】:2015-05-08 17:36:54 【问题描述】:

我目前正在完成一些交给我的代码。它是在 2005 年前在 Visual Studio 中用 MFC 编写的,被搁置了,现在被带到了我这里。

虽然我知道 C++,但在过去的大约 2 个月里,我一直在研究代码和学习 MFC,并且它们开始融合在一起。

代码的 GUI 是嵌入在不可见对话窗口中的 SWF 闪存文件。我没有 SWF 文件的源代码,因此将来可能会在 WPF 或其他东西中重做它。我将 WMMode 设置为“Window”,因为在透明/不透明模式下它无法正确显示,每次捕获鼠标事件时它都会闪烁/闪烁。

无论如何,在 Win XP/Vista 中,单击并拖动 Flash 控件是有效的。在 Windows 7/8.1 中,它不会移动。

很高兴提供所需的任何和所有信息。我仍然对 MFC 对话框有点不知所措,所以不确定你们都想看到什么。

我发现了这个问题:Moving window by click-drag on a control

这看起来解决了很多问题。但是,我不希望整个控件像这样可以点击,只有顶部。不幸的是,在 MS 资源视图中,ActiveX 控件是空白的,因为 SWF 仅在运行时加载;我试图为这类事情寻找资源,但这非常困难,因为我不确定要使用的技术术语。

编辑

我已尝试通过创建一个非常简单的 MFC 应用程序来实现这一点,该应用程序只有一个静态文本控件,没有其他任何东西。我试图通过单击静态文本来使其工作(尽管我可能会将自己画到一个角落,因为它没有内置的 lButtonDown 事件)。

以下是相关代码:

class MyDialog : public CDialog

public:
    MyDialog(CWnd* pParent = NULL) : CDialog(MyDialog::IDD, pParent)
        
    // Dialog Data, name of dialog form
    enum IDD = INTERFACE1 ;
protected:
    virtual void DoDataExchange(CDataExchange* pDX)  CDialog::DoDataExchange(pDX); 
    //Called right after constructor. Initialize things here.
    virtual BOOL OnInitDialog()
    
        CDialog::OnInitDialog();
        pText = (CStatic *)GetDlgItem(ID_TEXT);

        pText->SetWindowTextW(_T("Hello World!"));

        return true;
    

    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);

private:
    CStatic * pText;

public:
    DECLARE_MESSAGE_MAP()
;

BEGIN_MESSAGE_MAP(MyDialog, CDialog)
    ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

重写方法:

afx_msg void MyDialog::OnLButtonDown(UINT nFlags, CPoint point)

    CWnd::OnNcLButtonDown(HTCAPTION, point);


我还尝试将 nFlags 设置为 0x2、调用 OnLButtonDown(与 onNcLButtonDown 相对)以及其他各种事情。消息触发但窗口不移动(它确实从标题栏移动,正常)。我错过了什么?

【问题讨论】:

看来您已经解决了问题。您覆盖 OnLButtonDown 并传递 WM_NCLBUTTONDOWN。如果你只想要这个,让我们说窗口的顶部然后检查鼠标位置,如果鼠标不在正确的位置,不要做任何事情? 感谢您的回复。我已经编辑了我上面的帖子,你能提供任何进一步的见解吗? 【参考方案1】:

实际上让我们用ON_WM_NCHITTEST() 来试试这段代码。如果您在客户区的任意位置单击鼠标,这将拖动对话框(客户区充当标题)。有一行rc.bottom = rc.top + 100 如果您取消注释,那么它只会在您单击顶部时拖动(我随机选择了数字 100)。

//declare:
afx_msg LRESULT OnNcHitTest(CPoint point);

BEGIN_MESSAGE_MAP(MyDialog, CDialog)
    ON_WM_NCHITTEST()
END_MESSAGE_MAP()

LRESULT MyDialog::OnNcHitTest(CPoint point)

    ScreenToClient(&point);

    CRect rc;
    GetClientRect(&rc);

    //rc.bottom = rc.top + 100; 

    if (rc.PtInRect(point))
        return HTCAPTION;

    return CDialog::OnNcHitTest(point);

第二个选项: 如果我们想通过单击子控件来移动对话框,并且该控件捕获了鼠标,请尝试使用此方法。 ***注意,请测试以确保控件在移动后正常工作。

BOOL MyDialog::PreTranslateMessage(MSG *msg)

    if (msg->message == WM_MOUSEMOVE && (msg->wParam & MK_LBUTTON)) 
     
        CPoint p; 
        GetCursorPos(&p); 
        CRect r; 
        ActiveX->GetWindowRect(&r); 
        if (r.PtInRect(p)) 
         
            ReleaseCapture(); 
            SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, 0);
            SendMessage(WM_NCLBUTTONUP, HTCAPTION, 0);
            return 1;
        
    
    return CDialogEx::PreTranslateMessage(msg);

【讨论】:

非常酷,谢谢!它实际上只适用于空白客户区,但我创建的静态文本控件将忽略所有单击和移动命令。但是,这给了我一些东西可以玩。非常感谢您的帮助,我会回复进一步的意见! 我想我理解错了。您的对话框中有第 3 方控件,并且您想通过单击第 3 方控件来移动整个对话框?你可能需要钩子。 “需要钩子”?什么意思? 顺便说一句,虽然在我正在工作的项目中使用的是 activeX 控件,但我正在尝试在我的实验应用程序中使用静态文本控件来执行此操作。 使用OnNcHitTest 如果它适用于您的 ActiveX。如果它不起作用,那么我使用PreTranslateMessage 添加了第二种方法,这与您之前发布的类似。

以上是关于MFC 单击并移动/拖动对话框窗口的主要内容,如果未能解决你的问题,请参考以下文章

在 MFC 中拖动子对话框时如何移动父对话框?

MFC-单击按钮打开对话框

关于MFC 在一个对话框内有两个控件,在其中一个控件内点击拖动到另一控件松开,然后交换控件的位置怎么实现?

MFC如何隐藏对话框?

MFC SDI 和对话框

对话框窗口中的消息框(VS 2012,MFC C++)