Question PlaceHolder

You already have everything you need. I suggest that you make some effort on your own behalf. You have a class and a code example of how to use that class. You don't need anything else.
 
[/COLOR]The project is incomplete

Please provide a sample application
[/INDENT]
[/COLOR]

Works fine for me, once I added a new class and pasted the code into it I was able to call Watermark.Set() and when I ran the program it shows my text in the textbox when nothing else was typed in. Typing removes my cue text and erasing it puts the message back.

The only thing I can think of would be to make it work more like the ToolTip where if there's a Watermark control on the form each TextBox would get a new "Property" in visual designer where you can set the cue text.
 
The only thing I can think of would be to make it work more like the ToolTip where if there's a Watermark control on the form each TextBox would get a new "Property" in visual designer where you can set the cue text.

Done!
VB.NET:
Imports System.Runtime.InteropServices

<ComponentModel.ProvideProperty("Watermark", GetType(Control))>
Public Class Watermark
    Inherits ComponentModel.Component
    Implements ComponentModel.IExtenderProvider

    Public ReadOnly Property WatermarksByControl As New Dictionary(Of Control, String)

    Public Function CanExtend(extendee As Object) As Boolean Implements ComponentModel.IExtenderProvider.CanExtend
        Return TypeOf extendee Is Control
    End Function

    Public Function GetWatermark(control As Control) As String
        Dim watermark As String = Nothing

        WatermarksByControl.TryGetValue(control, watermark)

        Return watermark
    End Function

    Public Sub SetWatermark(control As Control, watermark As String)
        If WatermarksByControl.ContainsKey(control) Then
            If watermark Is Nothing Then
                WatermarksByControl.Remove(control)
            Else
                WatermarksByControl(control) = watermark
            End If
        ElseIf watermark IsNot Nothing Then
            WatermarksByControl.Add(control, watermark)
        End If

        Const EM_SETCUEBANNER = &H1501
        Const CB_SETCUEBANNER = &H1703

        Dim retainOnFocus As New IntPtr(1)
        Dim msg = EM_SETCUEBANNER

        If TypeOf control Is ComboBox Then
            msg = CB_SETCUEBANNER
        End If

        SendMessage(New HandleRef(control, control.Handle),
                    msg,
                    retainOnFocus,
                    watermark)
    End Sub

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
    Private Shared Function SendMessage(hWnd As HandleRef,
                                        msg As Integer,
                                        wParam As IntPtr,
                                        lParam As String) As IntPtr
    End Function

End Class
There might be some rough edges on that but I did a quick test and it worked. You can add a Watermark class to your project with that code and build, then add a Watermark component to a form from the Toolbox. You'll then get a 'Watermark on Watermark1' pseudo-property on each control, just as you would get 'ToolTip on ToolTip1' if you added a ToolTip.
 
Done!
There might be some rough edges on that but I did a quick test and it worked. You can add a Watermark class to your project with that code and build, then add a Watermark component to a form from the Toolbox. You'll then get a 'Watermark on Watermark1' pseudo-property on each control, just as you would get 'ToolTip on ToolTip1' if you added a ToolTip.
Sweet thanks, I was intending to get to this over the weekend but it seems to work great.
I'll play with it and see if it has issues working like that, I think the intent is to have this for only TextBoxes and ComboBoxes (where the TextBox is visible of course) and it might have issues with other controls.
 
I think the intent is to have this for only TextBoxes and ComboBoxes (where the TextBox is visible of course) and it might have issues with other controls.

The ProvideProperty attribute only let's you specify one type, so you must either specify Control or declare two different types to handle TextBoxes and ComboBoxes. The latter may be preferable but I did test my code with a Button and, while there was no cue text visible, setting it didn't seem to cause any problems.
 
The ProvideProperty attribute only let's you specify one type, so you must either specify Control or declare two different types to handle TextBoxes and ComboBoxes. The latter may be preferable but I did test my code with a Button and, while there was no cue text visible, setting it didn't seem to cause any problems.
That's what I was going to check for, making sure things other than CB's and TB's simply "did nothing" when setting that property. Good to know that's how it works.
 
The ProvideProperty attribute only let's you specify one type, so you must either specify Control or declare two different types to handle TextBoxes and ComboBoxes. The latter may be preferable but I did test my code with a Button and, while there was no cue text visible, setting it didn't seem to cause any problems.
You can filter controls with CanExtend, including checking if a TextBox has Multiline turned on. This has direct effect in designer.

Another quirk is that if control handle is recreated you have to set watermark again, it is common to attach HandleCreated event for this purpose. (repro: for example change a textbox RightToLeft at runtime)

I would add DefaultValue attribute, IContainer constructor, and disposing cleanups including remove watermarks when component is deleted in designer!
 
You can filter controls with CanExtend, including checking if a TextBox has Multiline turned on. This has direct effect in designer.
Of course! *facepalm* Should have thought of that.
Another quirk is that if control handle is recreated you have to set watermark again, it is common to attach HandleCreated event for this purpose. (repro: for example change a textbox RightToLeft at runtime)

I would add DefaultValue attribute, IContainer constructor, and disposing cleanups including remove watermarks when component is deleted in designer!
That all sounds reasonable.
 
Back
Top