8

When I do a search through my entire project in visual studio for the word 'clipboard' I find no matches.

Yet somehow my program seems to be changing the contents of my clipboard to be equal to the .text property of a control on my form. How can this be?

I've identified the handler after which my clipboard always seems to be changed and added a messagebox to get the text from my clipboard to try and identify when it might be changed.

MessageBox.Show(Clipboard.GetText)

Even at the top of the sub handling the event my clipboard has already been changed to the .text property of a control. This is the only sub which handles this event and the clipboard always changes after this event.

This is a small winforms project written in vb.net.

More information:

My clipboard is getting set to the .text property of a label when I click on it. The labels are made here:

    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

even when I comment out the handler:

AddHandler lbl.DoubleClick, AddressOf subChangeTimesheetState

my clipboard is still changed.

Work around is available here:

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

Create a new class which inherits the label, vb code:

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
J. Scott Elblein
  • 4,013
  • 15
  • 58
  • 94
5uperdan
  • 1,481
  • 2
  • 14
  • 30
  • So if you remove the handler, does it not change? – Zach Johnson Jun 11 '13 at 15:48
  • 1
    What type of control is it? Just a textbox or something else? – G_P Jun 11 '13 at 15:49
  • Does the text get copied to the clipboard on double-click of the label or on just a click? What happens when commenting out the MouseClick handler as well? – G_P Jun 11 '13 at 16:00
  • possible duplicate of [Is there any way to disable the "double-click to copy" functionality of a .NET label?](http://stackoverflow.com/questions/2519587/is-there-any-way-to-disable-the-double-click-to-copy-functionality-of-a-net-l) – EricLaw Jun 11 '13 at 16:01
  • One of the answers there had the brilliantly simple solution of overriding the Text property, so the base Text remains empty. Everything adapts to that flawlessly, except that clipboard copy thing, which doesn't use the public property but the internal var. – Nyerguds Dec 21 '16 at 12:09

5 Answers5

18

It's not your code, it's a "feature" introduced in Windows Vista.

In Windows Vista, a Windows Shell programmer checked in a change (with no spec/justification in the changelist) that changed the default label control to copy its text to the clipboard when double-clicked.

This change typically doesn't impact C++ applications due to how they create/host the label control, but it impacts all VS.NET applications. I filed a bug against the (surprised) Framework team when I discovered this in the Win7 timeframe, but they were scared to fix the bug because it had been present for so long.

Here's the duplicate Is there any way to disable the "double-click to copy" functionality of a .NET label?

Community
  • 1
  • 1
EricLaw
  • 56,563
  • 7
  • 151
  • 196
  • +1. Such a great feature! I did not know you could do that. Does not work on messagebox class though, probably because it's COM under the hood. – Victor Zakharov Jun 11 '13 at 18:03
  • FWIW: I don't think MessageBox uses COM at all; you can call it in an application that never calls CoInitialize. – EricLaw Jun 17 '13 at 19:35
  • 3
    @Neolisk btw, not everybody knows that clicking on the MessageBox title bar and pressing Ctrl+C copies the whole MessageBox content to the clipboard. – Niki Romagnoli Oct 07 '15 at 07:10
4

The best way to get the label not to react on a double click is to override the class style by overriding the label class itself.

    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;
            }
        }
    }

This removes the CS_DBLCLKS window class style from the label. The only event that will be triggered from now is the Click event for every click that occurs.

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

t4nky
  • 427
  • 1
  • 5
  • 15
  • What if the problem is that a double click on the label is _required_ in the program in certain circumstances, but I don't want that to clear the clipboard, though? Think color palette in image editing program opening color picker on double click. – Nyerguds Dec 21 '16 at 12:07
1

I suppose there are a number of different ways to solve this same problem. Here is what I came up with (using an inherited label, tested on 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);
        }
    }
}

Some extra effort would have to be invested to preserve things like copied Excel fields and the like, although the principle would be the same. As mentioned, you could iterate over the clipboard for all available formats (or the ones you care about), and stuff those values into a Dictionary object, and then restore them afterwords. Text and pics covers it for me, in this case.

One worthwhile link to see on this subject is here: How do I backup and restore the system clipboard in C#?

Frog Pr1nce
  • 730
  • 9
  • 8
1

I have developed this code for Visual Basic NET. So that when double-clicking the Label control, its text is not automatically copied to Windows clipboard, its double-click event can also be used. What is required is to use a second Label with the same properties as the Label we are using.


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

1

I used a tricky solution, but probably is not what you was looking for.

I copied the contains of the clipboard in label_click using a variable, and then use it to replace the contains of the clipboard at the end of 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);
    }

Again, probably not what you was looking for, because it looks simple, but it works for me and maybe can help someone else.