26

This is really annoying. I'm using the label as part of a list item user control, where the user can click it to select the list item and double-click it to rename it. However, if you had a name in the clipboard, double-clicking the label will replace it with the text of the label!

I've also check the other labels in the application, and they will also copy to the clipboard on a doubleclick. I have not written any clipboard code in this program, and I am using the standard .NET labels.

Is there any way to disable this functionality?

David Carroll
  • 375
  • 3
  • 6
  • 2
    Just a guess -- have you tried handling the MouseDoubleClick event and doing nothing? – Austin Salonen Mar 25 '10 at 21:45
  • I can reproduce this on my Vista machine, but not on two my XP machines. –  Mar 25 '10 at 22:08
  • 2
    Austin - that doesn't work, unfortunately. The text is copied to the clipboard before the event is fired. – Richard Watson Dec 28 '10 at 21:26
  • I'm using the DevExpress label control and it does not seem to have this behaviour. I was unaware that the original label had that functionality. – Pierre-Alain Vigeant Dec 28 '10 at 21:46
  • Is it just me or this is not working when I use the standard .Net Label? – Pierre-Alain Vigeant Dec 28 '10 at 21:51
  • Hi Pierre-Alain. It only happens in some versions of Windows, so maybe you won't see it on your machine but some of your customers/users might. – Richard Watson Dec 29 '10 at 17:28
  • It only happens on some labels in the application I'm working on.. really wierd – granaker Mar 08 '13 at 14:01
  • 5
    This was a "feature" introduced by a Windows Shell programmer during the Windows Vista timeframe. He checked in the change with no explanation. The .NET Framework team didn't notice until it was pointed out to them in the Win7 timeframe, and by the time they learned of it, they were scared of changing the framework to disable the unwanted behavior. – EricLaw Jun 11 '13 at 16:02

6 Answers6

7

I was able to do it using a combination of the other answers given. Try creating this derived class and replace any labels you wish to disable the clipboard functionality with it:

Public Class LabelWithOptionalCopyTextOnDoubleClick
    Inherits Label

    Private Const WM_LBUTTONDCLICK As Integer = &H203

    Private clipboardText As String

    <DefaultValue(False)> _
    <Description("Overrides default behavior of Label to copy label text to clipboard on double click")> _
    Public Property CopyTextOnDoubleClick As Boolean

    Protected Overrides Sub OnDoubleClick(e As System.EventArgs)
        If Not String.IsNullOrEmpty(clipboardText) Then Clipboard.SetData(DataFormats.Text, clipboardText)
        clipboardText = Nothing
        MyBase.OnDoubleClick(e)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If Not CopyTextOnDoubleClick Then
            If m.Msg = WM_LBUTTONDCLICK Then
                Dim d As IDataObject = Clipboard.GetDataObject() 
                If d.GetDataPresent(DataFormats.Text) Then
                    clipboardText = d.GetData(DataFormats.Text)
                End If
            End If
        End If

        MyBase.WndProc(m)
    End Sub

End Class
TKTS
  • 1,261
  • 1
  • 11
  • 17
  • This worked for me, thank you. I feel like this answer should be marked as the correct one now since it preserves the content that was already on the clipboard. – Cuthbert May 21 '13 at 18:11
  • 1
    Of course, this only preserves the text. If the clipboard contains anything in those formats tricky to handle in managed code, you're out of luck. I think the best way to save and restore all contents would be pair of unmanaged functions. – Medinoc Dec 05 '13 at 16:38
  • Much better then to just go over `Clipboard.GetDataObject().GetFormats()` and make a `Dictionary` containing _everything_, and restore that afterwards. Though, I'm using Jaex' solution; it's much simpler. – Nyerguds Dec 21 '16 at 11:56
6

When internal text value is empty then double clicking on label not trying to copy text value to clipboard. This method more cleaner than other alternatives I think:

using System;
using System.Windows.Forms;

public class LabelNoCopy : Label
{
    private string text;

    public override string Text
    {
        get
        {
            return text;
        }
        set
        {
            if (value == null)
            {
                value = "";
            }

            if (text != value)
            {
                text = value;
                Refresh();
                OnTextChanged(EventArgs.Empty);
            }
        }
    }
}
Jaex
  • 4,204
  • 2
  • 34
  • 56
  • 1
    Indeed, I tested this, and it seems it only uses the Label's private text variable for the clipboard thing, and not the public property. Very peculiar, but it seems the Paint function does use the public property, so this override works fine, making this a very quick and clean fix. – Nyerguds Dec 21 '16 at 11:54
  • For some reason this randomly stopped working in some projects I have. No clear indication why; it's implemented exactly like in some other projects where it _does_ work fine. In fact it's using the same whole custom control I built up with it (a colour palette for indexed images). – Nyerguds Mar 03 '20 at 07:23
  • Well, not sure what caused it, but I got around it by adding a Boolean that controls whether to make the Text property return its value or null, and overriding the `OnPaint` method to only allow it through while performing `Base.OnPaint` (I added an extra function to still get the text in my own code, of course). Then, somehow, the problem mysteriously resolved itself anyway, and the Text property stopped getting called on double click. Honestly not sure how or why. – Nyerguds Mar 03 '20 at 10:15
3

I have found this post. The last poster seems to have been given a solution by Microsoft, albeit not a perfect solution.

J. Scott Elblein
  • 4,013
  • 15
  • 58
  • 94
Klaus Byskov Pedersen
  • 117,245
  • 29
  • 183
  • 222
  • 2
    The solution presented in that post seems to clear out the clipboard, which is more of a sidestep. But a little preferable to the earlier behavior, in my opinion. – David Carroll Mar 25 '10 at 23:19
2

TKTS solution converted to C#

For beginners: (add new class, build, go to designer and from toolbox drag and drop position named 'LabelWithOptionalCopyTextOnDoubleClick')

using System.ComponentModel;
using System.Windows.Forms;
using System;

public class LabelWithOptionalCopyTextOnDoubleClick : Label
{
    private const int WM_LBUTTONDCLICK = 0x203;
    private string clipboardText;

    [DefaultValue(false)]
    [Description("Overrides default behavior of Label to copy label text to clipboard on double click")]
    public bool CopyTextOnDoubleClick { get; set; }

    protected override void OnDoubleClick(EventArgs e)
    {
        if (!string.IsNullOrEmpty(clipboardText))
            Clipboard.SetData(DataFormats.Text, clipboardText);
        clipboardText = null;
        base.OnDoubleClick(e);
    }

    protected override void WndProc(ref Message m)
    {
        if (!CopyTextOnDoubleClick)
        {
            if (m.Msg == WM_LBUTTONDCLICK)
            {
                IDataObject d = Clipboard.GetDataObject();
                if (d.GetDataPresent(DataFormats.Text))
                    clipboardText = (string)d.GetData(DataFormats.Text);
            }
        }
        base.WndProc(ref m);
    }

}
michal-mad
  • 432
  • 4
  • 11
1

My solution (terribly ugly, but it seems to work) was to copy clipboard text to a local variable on single-click, and restore it on double-click if the clipboard differs from the local variable. Obviously the precursor to a double-click is the first single-click, which is why it works.

I'm going to star this question because I'd love a cleaner method!

Richard Watson
  • 2,584
  • 1
  • 23
  • 30
  • That's a "workaround" literally... good though. You also need to check for the data type, as it's not always `String` which is in the clipboard... also if the clipboard was even having some data in the first place. – Sreenikethan I Jun 30 '17 at 09:26
0

I tried the solutions posted above, and they did not work for me. =( Following that basic idea, though (thanks to above), I arrived here, and this seems to work (a little cleaner too). (running 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 (and cautionary) link to see on this subject is here: How do I backup and restore the system clipboard in C#?

Frog Pr1nce
  • 730
  • 9
  • 8