You implement the cut, copy, and paste functionality as part of the textbox control. So why is it that so few VB 6 applications (or any other internal enterprise applications) do not have an edit menu with Cut, Copy, and Paste options (for simplicity throughout the rest of this chapter, I will call these options edit functionality)? Simply put, implementing the functionality took a lot of work and planning in VB 6. With .NET, this becomes a nonissue. And because of your application's architecture, implementing it becomes even easier.
So, how is the edit functionality that a menu or toolbar provides different from the textbox implementation of it? There is no difference in functionality (both use the Clipboard to hold data), but you need to be able to target the control that has the focus and to be able to invoke that call without being in the form on which the control is located. There are many different ways to implement this, but the solution covered in this section is probably the simplest to implement. This solution involves creating an interface that provides method signatures for your edit methods.
Note | Interfaces are available for use in VB 6, but they are slightly more difficult to implement. Many developers did not use interface inheritance in VB 6, and they overlooked this solution. |
Tip | If you are only using textboxes and richtextboxes, then this entire setup is unnecessary because you can call the cut, copy, or paste method of the control to perform the needed functionality. However, this does not allow you to implement the functionality for a control such as a combo box or a listbox like this method of implementation will allow. |
All your MDI form has to do is to check to see if the active form implements the ICutCopyPaste interface you will create. The real issue is not how to implement the edit functionality for a textbox, but how to make this functionality extensible for other types of controls and to access that functionality using the menu items.
Note | Because there are so many permutations of the Undo method, describing how to implement it would take many more pages to explain. Consider that the undo must be available if you press the Backspace key, perform a cut or paste operation, highlight text, press any key, and so on. If you decide to create your own routines to handle the Undo, it should be fairly easy for you to extend this code. |
So let's create your interface and implement it. Add a new class module to the NorthwindTraders project and call it UIInterfaces. Delete the class module code that is created by default and add the code in Listing 6-8 to the UIInterfaces module.
Listing 6-8: The UIInterface Module
Option Explicit On Option Strict On Public Interface ICutCopyPaste Sub Cut() Sub Copy() Sub Paste() End Interface
In the frmEditBase form, add the following implementation line:
Implements ICutCopyPaste
Let's start by implementing the Cut method. Add the code in Listing 6-9 to the frmEditBase class and afterward, you will walk through it.
Listing 6-9: The Cut Method
Public Sub Cut() Implements ICutCopyPaste.Cut Dim txt As TextBoxBase If TypeOf ActiveControl Is TextBoxBase Then txt = CType(ActiveControl, TextBoxBase) txt.Cut End If End Sub
Tip | If you are using Visual Studio .NET (VS .NET) 1.1, the methods will have already been created for you so you will just need to modify the methods to match those in Listing 6-10. Listing 6-10: The Copy Method
Public Sub Copy() Implements ICutCopyPaste.Copy Dim txt As TextBoxBase If TypeOf ActiveControl Is TextBoxBase Then txt = CType(ActiveControl, TextBoxBase) txt.Copy Else Clipboard.SetDataObject(ActiveControl.Text) End If End Sub |
The first thing that occurs is a check of the type of the active control. In this case, you are only implementing the cut routine if the control derives from the TextBoxBase class.
Note | You can easily edit this functionality to work for the textbox part of a drop-down list. But even this can be tricky because you have to check the style of the combo box before you can make it work (Cut does not work on a drop-down listbox). |
Once you have confirmed that it is a type of TextBoxBase control, you perform the conversion to a TextBoxBase control so that you can manipulate the object correctly. Next you call the following line of code:
txt.Cut
This line simply invokes the Cut method on the TextBoxBase control.
Now you will implement the Copy method. To do this, add the code in Listing 6-10 to the frmEditBase class.
Here you are doing something slightly different because this method only copies data. Again, you are checking to see if this is a TextBoxBase—but for a slightly different reason. If it is a type of TextBoxBase, you convert the object again and send the selected text to the Clipboard. However, if it is not a type of TextBoxBase, you simply send the value of the text property of the control to the Clipboard. This is fairly simple to get away with because almost every control that a user could be editing will have the text property.
Note | In specific instances, you may have to modify this code because of controls that may not have a text property or when you need to copy something other than text. |
Next you need to implement the last and final method of the interface, the Paste method. Add the code in Listing 6-11 to the frmEditBase class.
Listing 6-11: The Paste Method
Public Sub Paste() Implements ICutCopyPaste.Paste Dim txt As TextBoxBase If TypeOf ActiveControl Is TextBoxBase Then txt = CType(ActiveControl, TextBoxBase) txt.Paste End If End Sub
Again, this code is easy to implement. You only run this code if the active control is a type of TextBoxBase. You are simply calling the Paste method of the control.
Now every form that inherits from your frmEditBase form automatically implements the ICutCopyPaste interface. Now you need to hook up this functionality to the frmMain menu click events. Add the code in Listing 6-12 to the frmMain form.
Listing 6-12: The CutCopyPaste Method
Private Sub CutCopyPaste(ByVal strMenu As String) Dim objCCPU As ICutCopyPaste Dim t As System.Type If ActiveMdiChild Is Nothing Then Exit Sub Try t = ActiveMdiChild.GetType If Not t.GetInterface("ICutCopyPaste") Is Nothing Then objCCPU = CType(Me.ActiveMdiChild, ICutCopyPaste) Select Case strMenu Case "Cu&t" objCCPU.Cut() Case "&Copy" objCCPU.Copy() Case "&Paste" objCCPU.Paste() End Select End If Catch exc As Exception LogException(exc) End Try End Sub
This routine invokes the methods on your interface contained in the base edit form class. Let's look at some of this code in detail:
Dim objCCPU As ICutCopyPaste Dim t As System.Type
The objCCPU is the declaration of your interface through which you will access all of your interface calls. Just as with the remoting calls, you are operating on the interface definitions not directly on your base class. The t variable is declared so that you can examine the form upon which you want to operate, as you will see next:
t = ActiveMdiChild.GetType If Not t.GetInterface("ICutCopyPaste") Is Nothing Then objCCPU = CType(Me.ActiveMdiChild, ICutCopyPaste)
The first line retrieves the type information from your object so that you can examine it. Next, you call the GetInterface method that, in one of its overloaded methods, accepts the string name of the interface for which you are querying. If the interface is implemented by the object you are testing, then you will receive that type back. If it is not implemented, you will get nothing back.
Note | Reflection is an extremely powerful tool that should not be overlooked. Although you are not truly using the reflection namespace classes here, this is a method of reflection. Chapter 10, "Using Reflection," covers reflection in detail. |
If the interface is implemented, you can assign the object to your interface variable by performing a conversion on it. After that, you simply invoke the specific methods on the interface.
Now you need to hook up this method to the menu click event. Edit the MainMenu_Click event so that the following Case statement is added to the Select Case statement:
Case "Cu&t", "&Copy", "&Paste" CutCopyPaste(mnu.Text)
That was not too painful, and every form you create after this that inherits from the base edit form automatically has this functionality.
Tip | This may seem like a roundabout way of implementing an edit functionality interface, but it is really the most reusable way to do this. This set of methods gives you the ability to implement editing capabilities on any control that you want because you can control all of the aspects of what actually takes place during the cut or paste process. |