Introduction
Welcome to the second article in the .NET secrets series!
I’m Karl Moore and, once again, you’re reading another bundle of secrets I’ve adapted from my soon-to-be-released book, VB .NET and ASP.NET Secrets.
This week, I’m continuing to look at Windows application secrets. Today, we’ll figure:
- The .NET method of checking for a previous instance
- How to convert the contents of a RichTextBox control to HTML
- What you need to do to support dragging-and-dropping from Windows Explorer
- The exact code you need to capture the screen, quickly and easily
Got any .NET tips and tricks of your own? I’d love to hear about them and possibly formulate them into this series (with full credit given, naturally!). Drop me a line—karl@karlmoore.com.
But without further ado… the secrets!
The .NET Way of Checking for Previous Instances
There are times when it’s useful to check whether another instance of your application is running. For example, when starting up your program, you may want to check whether another version is already running in the background and, if it is, give that instance the focus.
In Visual Basic 6, you had the App.PrevInstance property to do this. In VB.NET, we need to check whether the current process is running more than once. That’s what our code does here, encapsulated in the PrevInstance function. It returns a True if your application is already running on the same machine:
Public Function PrevInstance() As Boolean If Diagnostics.Process.GetProcessesByName _ (Diagnostics.Process.GetCurrentProcess.ProcessName) _ .Length > 1 Then Return True Else Return False End If End Function
You might use this code as so:
If PrevInstance() = True Then ' Get all previous instances Dim Processes() As Process Processes = _ Diagnostics.Process.GetProcessesByName( _ Diagnostics.Process.GetCurrentProcess.ProcessName) ' Activate the first instance AppActivate(Processes(0).Id) ' Exit the current instance Application.Exit() End If
Top Tip: There’s a little bug you may run into when using this code that turns the hair of most developers a funny shade of gray. If your application name is greater than fifteen characters, and running on either Windows NT or 2000, your code won’t be able to tell whether a previous instance is running. Weird, but true. Solution: upgrade to XP or higher, or change your application name (Project > Properties).
Converting RTF to HTML
One amazingly common developer request is a method of converting the contents of a RichTextBox control to HTML. But, unless you’re willing to spend hundreds on a third-party text editing control, you’re out of luck. Even in VB.NET, Microsoft has chosen to remain ignorant to this much desired feature.
So, you need to do it yourself—and the following chunk of code I’ve put together should get you started. Just pass it a RichTextBox control as a parameter and it’ll return a string of HTML, ready for you to perhaps save to a file.
It doesn’t handle more complicated features, such as images or tables; however, it will easily cope with fonts, sizes, colors, bold, italic, and paragraphs. Of course, you’re more than welcome to expand it to suit your needs exactly.
You can call this code, as so:
strHTML = ConvertToHtml(RichTextBox1)
And here’s the actual ConvertToHTML function:
Public Function ConvertToHTML(ByVal Box As RichTextBox) _ As String ' Takes a RichTextBox control and returns a ' simple HTML-formatted version of its contents Dim strHTML As String Dim strColour As String Dim blnBold As Boolean Dim blnItalic As Boolean Dim strFont As String Dim shtSize As Short Dim lngOriginalStart As Long Dim lngOriginalLength As Long Dim intCount As Integer ' If nothing in the box, exit If Box.Text.Length = 0 Then Exit Function ' Store original selections, then select first character lngOriginalStart = 0 lngOriginalLength = Box.TextLength Box.Select(0, 1) ' Add HTML header strHTML = "<html>" ' Set up initial parameters strColour = Box.SelectionColor.ToKnownColor.ToString blnBold = Box.SelectionFont.Bold blnItalic = Box.SelectionFont.Italic strFont = Box.SelectionFont.FontFamily.Name shtSize = Box.SelectionFont.Size ' Include first 'style' parameters in the HTML strHTML += "<span style=""font-family: " & strFont & _ "; font-size: " & shtSize & "pt; color: " _ & strColour & """>" ' Include bold tag, if required If blnBold = True Then strHTML += "<b>" End If ' Include italic tag, if required If blnItalic = True Then strHTML += "<i>" End If ' Finally, add our first character strHTML += Box.Text.Substring(0, 1) ' Loop around all remaining characters For intCount = 2 To Box.Text.Length ' Select current character Box.Select(intCount - 1, 1) ' If this is a line break, add HTML tag If Box.Text.Substring(intCount - 1, 1) = _ Convert.ToChar(10) Then strHTML += "<br>" End If ' Check/implement any changes in style If Box.SelectionColor.ToKnownColor.ToString <> _ strColour _ Or Box.SelectionFont.FontFamily.Name _ <> strFont Or _ Box.SelectionFont.Size <> shtSize _ Then strHTML += "</span><span style=""font-family: " _ & Box.SelectionFont.FontFamily.Name & _ "; font-size: " & Box.SelectionFont.Size & _ "pt; color: " & _ Box.SelectionColor.ToKnownColor.ToString & """>" End If ' Check for bold changes If Box.SelectionFont.Bold <> blnBold Then If Box.SelectionFont.Bold = False Then strHTML += "</b>" Else strHTML += "<b>" End If End If ' Check for italic changes If Box.SelectionFont.Italic <> blnItalic Then If Box.SelectionFont.Italic = False Then strHTML += "</i>" Else strHTML += "<i>" End If End If ' Add the actual character strHTML += Mid(Box.Text, intCount, 1) ' Update variables with current style strColour = Box.SelectionColor.ToKnownColor.ToString blnBold = Box.SelectionFont.Bold blnItalic = Box.SelectionFont.Italic strFont = Box.SelectionFont.FontFamily.Name shtSize = Box.SelectionFont.Size Next ' Close off any open bold/italic tags If blnBold = True Then strHTML += "" If blnItalic = True Then strHTML += "" ' Terminate outstanding HTML tags strHTML += "</span></html>" ' Restore original RichTextBox selection Box.Select(lngOriginalStart, lngOriginalLength) ' Return HTML Return strHTML End Function
Top Tip: Looking to turn HTML back into text? Check out my “Converting HTML to Text, Easily” tip in the “More .NET Secrets” chapter of my book, VB.NET and ASP.NET Secrets for a ready-to-run algorithm.
Our code doing its stuff: translating RTF into HTML
Drag and Drop from Windows Explorer
Dragging and dropping within your application is pretty simple stuff. Simply set a couple of properties and you’re rocking: look up ‘drag and drop, Windows Forms’ in the Help Index for more information. But what if you want to drag and drop from another application, such as Windows Explorer?
One of the most commonly requested, yet infrequently answered Windows form questions is, “How can I let my users drag and drop files and folders directly into my applications?”. Simple, just follow these three easy steps:
- Change the AllowDrop property of the control you want users to drop the files onto to True. This could be a ListBox control, a Panel control, or even your form itself.
- Add code to the DragOver event of the control, so the typical ‘copy’ icon is displayed when files are dragged over:
- Finally, add code to the DragDrop event of the control, to receive and process information about the dropped files:
' As dragged over, check data is file drop If e.Data.GetDataPresent(DataFormats.FileDrop) Then ' Display the copy (or other) icon e.Effect = DragDropEffects.Copy End If
' Check this is a file drop If (e.Data.GetDataPresent(DataFormats.FileDrop)) Then ' Retrieve list of files and loop through string array Dim strFiles() As String = e.Data.GetData( _ DataFormats.FileDrop) Dim intCount As Integer For intCount = 0 To strFiles.Length MessageBox.Show(strFiles(intCount)) Next End If
And that’s it! In three simple steps, your application is ready to interoperate with Windows Explorer or any other application supporting the standard Windows file drag and drop routines.
Of course, here we’re simply displaying the dropped files or folders in a message box here; however, you could be doing something much more exciting: generating an MP3 play list; processing special work files; loading documents into your own mini word processor. The possibilities are endless.
Dragging and dropping from Windows Explorer
Capturing the Screen, Quick and Easy
When it comes to showing people how to capture the screen, most VB.NET authors I’ve seen tend to revert to the old-school method of working: using the API. There is, however, a better way.
The following function is called GetScreenCapture and returns an Image object. It captures the screen by running a series of “Print Screen” key presses, which puts a screen grab on the Clipboard, ready for my nifty little function to devour and return. My function accepts a FullScreen argument, too: Pass True to capture the whole screen, or False to capture just the active window.
Here’s the code:
Public Function GetScreenCapture( _ Optional ByVal FullScreen As Boolean = False) As Image ' Captures the current screen and returns as an Image ' object Dim objSK As SendKeys Dim imgCapture As Image If FullScreen = True Then ' Print Screen pressed twice here as some systems ' grab active window "accidentally" on first run objSK.SendWait("{PRTSC 2}") Else objSK.SendWait("%{PRTSC}") End If Dim objData As IDataObject = Clipboard.GetDataObject() Return objData.GetData(DataFormats.Bitmap) End Function
And here are a couple of examples demonstrating how to use that Image object—firstly, saving it as a file; and secondly, using it to set the Image property of a PictureBox control:
GetScreenCapture(True).Save("c:screengrab.bmp") PictureBox1.Image = GetScreenCapture()
My sample application, capturing the active window (again and again)
Next Time
Coming up in part three of Windows Secrets, check out:
- How to ‘Reset’ a Form
- The Facts on Visual Inheritance
- Secrets of Working with the System Tray
- Best of All Worlds: Creating an Ultra-Thin Client
See you next time!
# # #