双击.net标签控件将其文本复制到Vista+的剪贴板上



当我在visual studio中搜索整个项目中的'clipboard'这个词时,我没有找到匹配项。

然而不知何故,我的程序似乎正在改变我的剪贴板的内容等于我的窗体上的控件的.text属性。这怎么可能呢?

我已经确定了处理程序,之后我的剪贴板似乎总是被更改,并添加了一个消息框来获取剪贴板中的文本,以尝试确定何时可能会更改。

MessageBox.Show(Clipboard.GetText)

即使在子处理事件的顶部,我的剪贴板已经被更改为控件的.text属性。这是唯一处理此事件的子程序,并且剪贴板总是在此事件发生后更改。

这是一个用vb.net编写的小型winforms项目。

更多信息:

当我点击它时,我的剪贴板被设置为标签的。text属性。标签在这里:

    For i = 0 To lstTupChildren.Count - 1
        Dim lbl As New Label()
        lbl.Size = New System.Drawing.Size(250, 25)
        lbl.Font = New System.Drawing.Font("Calibri (body)", 10)
        lbl.Text = i + 1 & ". " & lstTupChildren(i).Item1
        lbl.Location = New System.Drawing.Point(0, 25 * i)
        If lstTupChildren(i).Item3 = True Then lbl.BackColor = Color.GreenYellow Else lbl.BackColor = Color.Orange 'sets the colour depending on whether the timesheet is active'
            Me.Controls.Add(lbl)
            AddHandler lbl.DoubleClick, AddressOf subChangeTimesheetState 'adds handler for double click to change status
            'adds handlers for moving the overlay
            AddHandler lbl.MouseDown, AddressOf Form_MouseDown
            AddHandler lbl.MouseMove, AddressOf Form_MouseMove
            'adds handler for hide context menu'
            AddHandler lbl.MouseClick, AddressOf subRightClickMenu
        Next

,即使我注释掉了处理程序:

AddHandler lbl.DoubleClick, AddressOf subChangeTimesheetState

我的剪贴板仍在更改。

可以在这里使用:

http://www.aspnet-answers.com/microsoft/NET-WinForms-Controls/32231136/double-click-label-and-its-text-appears-on-the-clipboard.aspx

创建一个继承标签的新类,vb代码:

Public Class myLabel
    Inherits Label
    Private WM_GETTEXT As Integer = &HD
    Private WM_LBUTTONDBLCLK As Integer = &H203
    Private doubleclickflag As Boolean = False
    Protected Overrides Sub WndProc(ByRef m As Message)
        If m.Msg = WM_LBUTTONDBLCLK Then
            doubleclickflag = True
        End If
        If m.Msg = WM_GETTEXT AndAlso doubleclickflag Then
            doubleclickflag = False
            Return
        End If
        MyBase.WndProc(m)
    End Sub
End Class

这不是你的代码,这是Windows Vista引入的"功能"。

在Windows Vista中,一个Windows Shell程序员检查了一个更改(在更改列表中没有说明/说明),该更改更改了默认的标签控件,当双击时将其文本复制到剪贴板。

这个变化通常不会影响c++应用程序,因为它们是如何创建/托管标签控件的,但它会影响所有VS.NET应用程序。当我在Win7的时间框架内发现这个问题时,我向(惊讶的)框架团队提交了一个错误,但他们害怕修复这个错误,因为它已经存在了很长时间。

这是副本有没有办法禁用"双击复制"?.NET标签的功能?

让标签在双击时不做出反应的最好方法是通过重写标签类本身来重写类样式。

    private class SingleClickLabel : Label
    {
        protected override CreateParams CreateParams
        {
            get
            {
                new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
                CreateParams cp = base.CreateParams;
                cp.ClassStyle &= ~0x0008;
                cp.ClassName = null;
                return cp;
            }
        }
    }

这将从标签中删除CS_DBLCLKS窗口类样式。从现在开始,唯一将被触发的事件是每次点击发生的Click事件。

看:http://msdn.microsoft.com/en-us/library/windows/desktop/ff729176 (v = vs.85) . aspxhttp://msdn.microsoft.com/en-us/library/system.windows.forms.createparams (v = vs.110) . aspx

我想有很多不同的方法来解决这个问题。以下是我想到的(使用继承标签,在Windows Server 2012 R2上测试):

public class MyLabel : System.Windows.Forms.Label
{
    private const int WM_LBUTTONDBLCLK = 0x203;
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_LBUTTONDBLCLK)
        {
            string sSaved = Clipboard.GetText();
            System.Drawing.Image iSaved = Clipboard.GetImage();
            base.WndProc(ref m);
            if (iSaved != null) Clipboard.SetImage(iSaved);
            if (!string.IsNullOrEmpty(sSaved)) Clipboard.SetText(sSaved);
        }
        else
        {
            base.WndProc(ref m);
        }
    }
}

需要投入一些额外的努力来保存复制的Excel字段之类的东西,尽管原理是一样的。如前所述,您可以在剪贴板上迭代所有可用格式(或您关心的格式),并将这些值填充到Dictionary对象中,然后在结束后恢复它们。在这种情况下,文本和图片对我来说已经涵盖了。

这里有一个值得一看的链接:如何在c#中备份和恢复系统剪贴板?

我为Visual Basic . NET开发了这个代码。这样,当双击Label控件时,其文本不会自动复制到Windows剪贴板中,其双击事件也可以使用。需要的是使用第二个Label,它的属性与我们正在使用的Label相同。


Private TimeSpan1 As New TimeSpan
Private CursorPos1 As Point
Private Declare Function GetDoubleClickTime Lib "user32" Alias "GetDoubleClickTime" () As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    With Label2
        .Text = Label1.Text
        .BackColor = Label1.BackColor
        .Location = Label1.Location
        .Size = Label1.Size
        ' and other visual properties (if different)
    End With
End Sub
Private Sub Label1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
    Handles Label1.MouseDown, Label2.MouseDown
    sender.SendToBack()  
    If (CursorPos1.X = Cursor.Position.X) And (CursorPos1.Y = Cursor.Position.Y) Then
        TimeSpan1 = Now - CDate(Label1.Tag)
        If TimeSpan1.TotalMilliseconds < GetDoubleClickTime Then
           
        '  Label1_DoubleClick event code 
        End If
    End If
    CursorPos1 = Cursor.Position
    Label1.Tag = Now
End Sub

我使用了一个棘手的解决方案,但可能不是你想要的。

我用一个变量复制了label_click中剪贴板的内容,然后用它来替换label_DoubleClick末尾的剪贴板的内容。

private void label_Click(object sender, EventArgs e)
    {
       clipboardString = Clipboard.GetText();
    }
private void label_DoubleClick(object sender, EventArgs e)
    {
    //........
        Clipboard.SetText(clipboardString,TextDataFormat.Text);
    }

再次,可能不是你想要的,因为它看起来很简单,但它适用于我,也许可以帮助别人。

最新更新