如何防止在“打开文件”对话框中双击时,同时触发其下方窗体的单击事件?

13

我有一个自定义控件,它本质上是一个绘图画布,并且有一个使用它来编辑文件的程序。 然而,当打开一个新文件时,会发生非常奇怪的事情。

如果用户在打开文件对话框(标准的TOpenDialog控件)中双击文件,而不是选择一个项目并按ENTER键,则位于其下方的画布将注册单击事件,最终在加载完成后立即执行绘制操作。

显然,这不是这样做的预期行为。 我之前注意到,当您双击鼠标时,双击消息会在第二次单击消息之前到达。 我认为对话框框可能会因为双击而关闭,然后第二个单击消息到达并被发送到现在适当坐标处的任何内容。

有没有办法让这种情况停止发生? 我无法告诉我的代码“在加载后,只需吃掉下一个单击”,因为它可能是通过“ENTER”键打开的,那么它将错过第一个合法单击。 有人能想出更好的处理方法吗? (使用Windows 7,如果有区别的话。)


我猜你想要一个适用于XP和Vista的解决方案,包括两个对话框。 - David Heffernan
1
有没有可能提供一个代码示例来复制?在空项目中不会注册表单上的点击。 - Sertac Akyuz
我经常看到它,在Windows 7上。(也许在不同的操作系统上会有所不同?) - Mason Wheeler
4个回答

7
如果出现“第二次点击消息”,那么就有问题了。 (首先,Windows没有“点击”消息,只有鼠标按下和鼠标松开的消息。)双击的顺序如下:鼠标按下、鼠标松开、双击、鼠标松开。对话框在双击消息和第二个鼠标松开消息之间消失。如果您的控件接收到鼠标松开消息并将其视为完整的点击,则可以解释该问题,并且您需要停止;单击始终是一对鼠标按下和鼠标松开消息。如果您还没有获得这两个消息,则不算单击。

问题看起来好像控件实际上捕获了鼠标弹起事件而不是单击事件(我的意思是,好像它被设置为捕获前者而不是后者)。 - Andriy M
太好了!是的,我使用了一个标志位方法来解决Down事件触发的问题。只有当picturebox真正被点击时,Down事件才会被触发: private void pictureBox1_MouseD(object sender, MouseEventArgs e) { picturebox_sel_clicked = true; Console.WriteLine("D"); } - elle0087

1
我用以下方法解决了这个问题(当然,这只是一个变通方法):
    CFileDialog my_file_dialog(...);
    if ( my_file_dialog.DoModal()!=IDOK )
        return;

    CString fileName= my_file_dialog.GetPathName();

    //...

    CSelectItemsDlg dlg;


    // Avoid that the double-click on the CFileDialog sends the WM_LBUTTONUP message to the next window causing the Unselect of an item that is under the mouse cursor.
    // http://www.experts-exchange.com/Programming/System/Windows__Programming/Q_10287063.html#a2476475
    MSG msg;
    while(PeekMessage(&msg,0,WM_LBUTTONUP,WM_LBUTTONUP,PM_REMOVE));

    int DoModalRes = dlg.DoModal();

你可以相信我让我的老板笑得很开心 :)


1
实际上,这是在图片框中触发了第二个鼠标抬起事件,导致了事件处理程序的调用。这似乎是一个OpenFileDialog的bug。需要为鼠标抬起事件添加IsMouseCaptured的检查,因为一次点击包括鼠标按下和鼠标抬起,而不仅仅是鼠标抬起。

0
Private IsMouseDown As Boolean
Private Sub picNenIn_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles picNenIn.MouseDown
    IsMouseDown = True
    'Code
End Sub
Private Sub picNenIn_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles picNenIn.MouseMove
    If IsMouseDown Then
        'Code
    End If
End Sub
Private Sub picNenIn_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles picNenIn.MouseUp
    IsMouseDown = False
    'Code
End Sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接