Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Double-clicking .NET Label control copies its text to clipboard on Vista+?

Tags:

c#

.net

vb.net

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: Work around 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

like image 481
5uperdan Avatar asked Jun 11 '13 15:06

5uperdan


3 Answers

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?

like image 105
EricLaw Avatar answered Nov 15 '22 22:11

EricLaw


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

like image 35
t4nky Avatar answered Nov 15 '22 20:11

t4nky


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#?

like image 33
Frog Pr1nce Avatar answered Nov 15 '22 22:11

Frog Pr1nce