Articles on this Page
- 09/15/11--08:08:_Toggle Between Widows 8...
- 09/19/11--05:28:_How To Print the Content...
- 09/25/11--12:43:_SharePoint 2010 Picture...
- 09/26/11--03:01:_How to populate a...
- 09/29/11--01:33:_How to copy and paste a...
- 10/02/11--23:30:_How to search for an...
- 10/06/11--04:39:_How to display a...
- 10/09/11--22:26:_How to save ListView...
- 10/13/11--13:57:_How To Print a Windows...
- 10/16/11--22:26:_How to Serialize and...
- 10/19/11--12:31:_SharePoint 2010 And...
- 10/20/11--00:45:_How to Create a Numerals...
- 10/24/11--02:35:_Three ListView Tips and...
- 10/31/11--11:11:_How To Search for...
- 11/07/11--00:39:_How to Bold text in a...
- 11/12/11--13:09:_Web Essentials - a look...
- 11/14/11--08:23:_How to compress the size...
- 11/27/11--06:11:_Metro Visual Basic Hello...
- 11/28/11--08:19:_How to read text file...
- 12/05/11--09:29:_How to identify an item...
- 12/19/11--10:59:_Book Review: Murach's...
- 12/20/11--04:08:_VS 11 Developer Preview(s)
- 12/27/11--07:01:_How to populate a combo...
- 12/30/11--06:31:_Three and a half simple...
- 01/04/12--03:50:_How to filter files in...
More Channels
- Jan 29: Peanutbutter kisses
- Nov 24: sona9
- Nov 28: EYEZMAZE --FLASH GAME--
- Nov 30: games - ABC Science (Australian...
- Jan 29: 波動展望テキスト+
- Jan 28: Bettor | Latest Cycling Articles
- Dec 11: atlanta private inve | Keyword Feed
- Dec 17: トップページ更新情報
- Jan 28: finanztreff.de / EMPFEHLUNGEN
- Dec 13: The html blog
- Nov 24: noctiluca
- Jan 28: ボーダーコリー ハチ...
- Jan 15: Comments for Meme.ro Portal - Blog
- Dec 26: Sarabande.jp
- Nov 28: Afiliados
- Nov 29: Newsvine - Buckeye Voter's...
- Nov 24: Web标准教程
- Nov 28: Mexico Connect -- Latest Content...
- Jan 26: 春香ビューティフルラ...
- Jan 27: WordPress.com News
- Jan 26: 目指せ!!...
- Jan 4: Twitter / bboynichin
- Jan 27: マニアの戯言
- Nov 24: = Whim Disc Review =
- Nov 24: ◆ユーリ◇しろくろ探...
- Jan 28: 海の見えるレストラン...
- Jan 1: リカリズムな日常
- Dec 18: blog.mibelleinc.com
- Jan 28: Entertainment News and Views :...
- Jan 15: 灰鷹巢城
- Jan 5: あっちいってお|ョω・`)
- Jan 17: さくらの日記。
- Nov 28: Urlesque
- Dec 22: E葬儀屋
- Jan 27: Etsy Shop for FiddleheadsForFiona
- Jan 27: Trickster.ntreev.net Event News
- Nov 28: Komentarze do wpisu Grafika...
- Dec 5: 電子レンジ調理器とキ...
- Nov 29: エクセル式アフィリエ...
- Jan 29: IBTimes.com : Lawyer Topic
- Nov 29: Dj Hatber (yaprostodj.pdj.ru)
- Nov 28: David Hemp news from ESPN...
- Jan 28: NRK - Helse-, forbruk- og...
- Nov 29: Comments on David Baddiel...
- Nov 28: Tibia - gra MMORPG
- Dec 31: Twitter / Favorites from jackkwild
- Jan 29: つぶよりのつぶやき...
- Dec 18: ....。
- Jan 25: ケロブウ王国
- Nov 24: ほのぼの。ヘラまま日記
|
|
Are you the publisher? Claim this channel |
|
Channel Description:
Latest Articles in this Channel:
- 09/15/11--08:08: Toggle Between Widows 8 Metro Interface and Windows 8 Starndard Interface (chan 2127976)
- 09/19/11--05:28: How To Print the Content of a Windows Forms ListView (chan 2127976)
- 09/25/11--12:43: SharePoint 2010 Picture Library Slideshow Web Part Image Size (chan 2127976)
- 09/26/11--03:01: How to populate a ListView from a text file (chan 2127976)
- 09/29/11--01:33: How to copy and paste a section of a PictureBox image (chan 2127976)
- 10/02/11--23:30: How to search for an item in a ListView (chan 2127976)
- 10/06/11--04:39: How to display a countdown timer (chan 2127976)
- 10/09/11--22:26: How to save ListView content to a text file (chan 2127976)
- 10/13/11--13:57: How To Print a Windows Forms ListBox to a selected printer (chan 2127976)
- the next string in the list box,
- the font that we created earlier
- A Brush that determines the color of the text, and
- the distance down the printer page to start printing this item.
- 10/16/11--22:26: How to Serialize and Deserialize ListView data (chan 2127976)
- 10/19/11--12:31: SharePoint 2010 And Excel Services when switching to Claims Based Authentication. (chan 2127976)
- 10/20/11--00:45: How to Create a Numerals Only TextBox (chan 2127976)
- 10/24/11--02:35: Three ListView Tips and Tricks (chan 2127976)
- 10/31/11--11:11: How To Search for Multiple Occurrences of a String in a ListView (chan 2127976)
- 11/07/11--00:39: How to Bold text in a Windows Forms ListView (chan 2127976)
- Set the UseItemStyleForSubItems property to False so that only the first column is affected.
- Enumerate through the ListView items and apply Bold font to the ListViewItem by its name (lvi):
- 11/12/11--13:09: Web Essentials - a look at the VS Extension (chan 2127976)
- Live Web Preview, right in Visual Studio. (Allows you to preview your site in real time as your editing it)
- Support for Live CSS Updating in the Live Web Preview (Allows you to preview css changes to your site as you make them)
- The Color Glyph (Shows a preview of color codes in your text editor.)

- The ability to add Javascript and CSS file directly from the context menu in the solution explorer.

- 11/14/11--08:23: How to compress the size of an image file at runtime (chan 2127976)
- A NumericUpDown named qualityLevel
- A button named btnCompress
- Two picture boxes named PictureBox1 and PictureBox2
- An OpenFileDialog named OpenFileDialog1
- Display the open file dialog
- If the user chooses a file, create an image using the selected file as the source.
- Display the image in its original form in the first picture box.
- Create a file name for the compressed file.
- Call the compress and save method on that image.
- Show the user that something’s happened by displaying the reduced image in the second picture box. This also lets them check the quality of the reduced size image.
- 11/27/11--06:11: Metro Visual Basic Hello World Application (chan 2127976)
- 11/28/11--08:19: How to read text file content into a List (of String) (chan 2127976)
- Checks that the element isn’t empty. (This can happen, for instance, if the line ends with a comma – which line 2 does)
- Then adds that element to the List ….
- ….While at the same time removing any unwanted spaces from the string (for example the spaces in front of cherry in the fourth line).
- 12/05/11--09:29: How to identify an item or sub item the users selects in a ListView (chan 2127976)
- Firstly, it gets the SubItem that the cursor is currently over.
- Then – because this particular property happens to return some additional information that we don’t need – the code strips off the first 18 characters. (If you’re curious, you can comment out this line)
- For the same reason, the code removes the final characters from the string that the ListViewHitTestInfo returns.
- For demo purposes, this code sample then displays the selection in a text box.
- 12/19/11--10:59: Book Review: Murach's ASP.NET 4 Web Programming with VB 2010 (chan 2127976)
- 12/20/11--04:08: VS 11 Developer Preview(s) (chan 2127976)
- 12/27/11--07:01: How to populate a combo box with an enumeration (chan 2127976)
- 12/30/11--06:31: Three and a half simple tips (chan 2127976)
- It's less typing.
- The intention of the variable is clearer. The reader doesn't have to hunt through code, thinking "I wonder what sr5 means?"
- It avoids "variable not initialized" errors.
- By not declaring a variable until you're ready to use it, you can keep its scope smaller. This code can be placed anywhere in a block, and the later you do so, the simpler your debugging becomes.
- 01/04/12--03:50: How to filter files in an OpenFileDialog (chan 2127976)
- Description of the first file type or types - e.g. “Image Files (*.png *.jpg *.bmp)
- followed by a Pipe symbol
- followed by an asterisk, a period, and the first extension – e.g. *.png
- followed by a semi-colon
- followed by further file extensions, with a semi-colon between each extension
- If you want to display more than one line in the file type combo box, repeat steps 1 to 5 above for each extension or group of extensions you want to include.
Use the Windows key.
If you are in Metro press it to switch to the Windows 7 interface.
If you are in the Windows 7 interface press it to switch to the Metro interface.
Introduction
I tweaked this code a while back when I just wanted to take a screenshot of the contents of a ListView. Essentially, it just uses BitBlt to grab all the required content, stores it as a temporary image, and then uses the standard PrintPage method to print it out.
The ListView
Here’s a screenshot of the list view I’ve used:
While I was experimenting with the printing, I found that I got a better printed result if I increased the font size on the list view.
The Code
Here’s the code for the Windows Form:
1 Public Class Form1
2 Friend WithEvents prntDoc As New System.Drawing.Printing.PrintDocument
3 Friend Print_Image As Image
4 Declare Auto Function BitBlt Lib "GDI32.DLL" (
5 ByVal hdcDest As IntPtr,
6 ByVal nXDest As Integer,
7 ByVal nYDest As Integer,
8 ByVal nWidth As Integer,
9 ByVal nHeight As Integer,
10 ByVal hdcSrc As IntPtr,
11 ByVal nXSrc As Integer,
12 ByVal nYSrc As Integer,
13 ByVal dwRop As Int32) As Boolean
14
15 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
16 MakeImage()
17 End Sub
18
19 Private Sub MakeImage()
20 Dim prnDialog As New PrintDialog
21 Application.DoEvents()
22 Me.Refresh()
23 Application.DoEvents()
24 'Get a Graphics Object from the form
25 Dim FormG As Graphics = ListView1.CreateGraphics
26 'Create a bitmap from that graphics
27 Dim i As New Bitmap(ListView1.Width, ListView1.Height, FormG)
28 'Create a Graphics object in memory from that bitmap
29 Dim memG As Graphics = Graphics.FromImage(i)
30 'get the IntPtr's of the graphics
31 Dim HDC1 As IntPtr = FormG.GetHdc
32 Dim HDC2 As IntPtr = memG.GetHdc
33 'get the picture
34 BitBlt(HDC2, 0, 0, ListView1.ClientRectangle.Width, ListView1.ClientRectangle.Height, HDC1, 0, 0, 13369376)
35 'Clone the bitmap so we can dispose this one
36 Me.Print_Image = CType(i.Clone(), Image)
37 'Clean Up
38 FormG.ReleaseHdc(HDC1)
39 memG.ReleaseHdc(HDC2)
40 FormG.Dispose()
41 memG.Dispose()
42 i.Dispose()
43 prnDialog.Document = prntDoc
44 Dim r As DialogResult = prnDialog.ShowDialog
45 If r = DialogResult.OK Then
46 prntDoc.Print()
47 End If
48 End Sub
49
50 Private Sub prntDoc_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles prntDoc.PrintPage
51 e.Graphics.DrawImage(Print_Image, 20, 90)
52 End Sub
53 End Class
54
Firstly, it creates a couple of variables, one for the PrintDocument that’s going to be created, and one for the image that will be built using BitBlt.
As you can see, BitBlt is at the heart of this task, and the next block of code comprises the BitBlt API . Jumping to the core method in line 19 that creates the image for printing, you’ll see how BitBlt is used to make a copy of the area of the Windows Form that’s occupied by the list view.
Once a copy of the list view has been taken and assigned to the Image named Print_Image, the user is shown a standard print dialog. Once they hit the OK button in that dialog, the PrintPage method of the print document is called and this uses the standard DrawImage method to print the image to the printer page. You can change the values for the left and top points (currently 20 and 90) if you want to reposition the printed list view on the printer page.
Summary
You’ll probably realise that although I’m capturing a list view here, this same procedure can be used for any area of the form, or any individual control, that you want to print out.
Well although the Picture Library Slideshow Web Part is a great OOTB feature, one thing that bugged me when I first started playing with it was the fact that it shrinks the size of the pictures that it displays with no means of overriding the size it decides to make them.
But with some simple jQuery in a Content Editor WebPart we can easily overcome this.
<script>
$(document).ready(function() {
var divList = $("div[id^='MSOPictureLibrarySlideshowWebPart']");
var currImage= $("img[id$='curr']");
divList.height('100%');
divList.width('100%');
currImage.height('125%');
currImage.width('125%');
});</script>
Introduction
The source of your data for a ListView can come from various sources and, if your requirements, a text file can sometimes be all you need. Because of the way the ListView is structured, there are a couple of things you need to look out for.
The ListView
Here’s a screenshot of the ListView I’m using as the example:
The text file
The only reason for showing you the text file is to point out that it uses the “-“ symbol to break up the data into the required columns:
Brian Bilbro - ( bbilbro@hotmail.com )- Module Communicator code and architecture
Fredi Gertsch- ( fredi@gerts.ch ) - Tab Administrator
John Dyer - (http://www.revjon.com) - Revjon Studios
Robin Lilly, Vanessa Monzon - N/A
Tom Trefz & Scott Willhite -NK - PopupCalendar.js (original by Tom, localization & Netscape by Scott)
Richard Cox - ( http://www.bydesignwebsights.com )- Search engine optimization at the Tab level ( Description, KeyWords, Title )
Dino Esposito - ( http://weblogs.asp.net/despos )- Personalization architecture from MSDN magazine ( Cutting Edge - March 2004 )
Jeff Martin- ( http://www.jeffmartin.com )- move ViewState to bottom of page for better search engine spidering
Jonathan de Halleux - ( http://www.dotnetwiki.org )- PA Installer
David Haggard -( http://www.newcovenant.com )- function to obfuscate sensitive data to prevent collection by robots and spiders and crawlers
Vicenc Masanas - ( http://lacolla.europe.webmatrixhosting.net ) - SMTP authentication
Joe Brinkman - ( http://www.tag-software.net )- Module Action Menu concept
Patrick Santry - ( http://www.wwwcoder.com ) - PayPal price checking and account checking
M. Murali Dharan - ( http://www.phpbuilder.com/columns/dhar20040217.php3 )- Search Engine Concepts
Craig Dunn - ( http://users.bigpond.com/conceptdevelopment/ ) - Search Engine Concepts ( Searcharoo )
Stan Schultes - ( http://www.vbnetexpert.com ) - RSS Generator ( Visual Studio Magazine - April 2004 )
James Clarkson - ( http://www.blogolith.com ) - Favicon per portal
Scott Mitchell - ( http://4guysfromrolla.com ) - URL Rewriting
Scott Stokes- ( http://www.adverageous.com )- File Manager UI ( based on DNNExplorer )
Michael Beller - ( http://www.lightshippartners.com ) - Database model for abstraction and refactoring of the core database
Sebastian Leupold - ( http://www.gamma-concept.de ) - German resource files
Using that symbol was my choice, and I could have opted for another character, symbol, or even a combination such as “-//-“ .
The code that populates the ListView
Here’s the code that will read the file and allocate the sections of text to the columns of the ListView:
1 Imports System.IO
2
3 Public Class Form2
4
5 Private Sub Form2_Load(sender As Object, e As System.EventArgs) Handles Me.Load
6 ListView1.View = View.Details
7 ListView1.Columns.Add("Name", 176)
8 ListView1.Columns.Add("Contact Information", 266)
9 ListView1.Columns.Add("Expertise", 276)
10
11 Try
12 ' Declare StreamReader and pass the Path of the ini file to be read as a Parameter
13 Dim MyStream As New StreamReader("C:\Temp\Contributors.txt")
14 ' A string array to hold each line as it is read
15 Dim strTemp() As String
16 ' Code that reads the file line by line
17 Do While MyStream.Peek <> -1 ' Use Peek to read the file until there are no more lines
18 Dim LVItem As New ListViewItem
19 ' Split the line using the - delimiter
20 strTemp = MyStream.ReadLine.Split("-"c)
21 ' Assign the content of the first element of the array to the first column
22 LVItem.Text = strTemp(0).ToString
23 ' Then add the item to the ListView
24 ListView1.Items.Add(LVItem)
25 ' Assign the content of the second element to the next column
26 LVItem.SubItems.Add(strTemp(1).ToString)
27 ' Check if there is a third section. If so, assign it to the next column
28 If strTemp.Length > 2 Then LVItem.SubItems.Add(strTemp(2).ToString)
29 Loop
30
31 MyStream.Close() ' Close the StreamReader
32 Catch ex As Exception
33 MessageBox.Show("Error reading file." & ex.Message)
34 End Try
35 End Sub
36 End Class
I think that the commenting fairly well explains exactly how it works.
I chose to set the properties in lines 6 to 9 here in the code. I could of course have set them using the properties window instead.
The test in line 28 is important, because if strTemp(2) is empty then you’ll get an error at runtime that will cause the display to stop rendering fully.
The only other point I wanted to make is that, if you look at the Dino Esposito entry, you’ll see that not all the information is shown. That’s because there is an additional “-“ in that piece of text, and as a result the words “March 2004” at the end of his entry are not shown in the ListView. In fact, they have been saved, but they will be in element (3) of strTemp and the code doesn’t do anything with that element. To avoid this kind of problem, it’s usually better to use a delimiter that won’t occur naturally, such as the “-//-“ example I gave earlier.
Summary
Populating a ListView from a text file is relatively easy, as long as you ensure that the delimiter will work properly and that you’ve accounted for all elements of the string array you use with the Split function.
Introduction
This is just a quick and dirty way to copy a section of image from one picture box and paste the selected area into a second picture box.
Here’s the basic Windows Form with two PictureBox controls at design time:
The code
Private Sub btnCopyPart_Click(sender As System.Object, e As System.EventArgs) Handles btnCopyPart.Click
'Grab the content of the first PictureBox and save it as a bitmap
Dim sourcebmp As New Bitmap(picImage.Image)
' Create an empty bitmap the size of the second PictureBox
Dim destinationbmp As New Bitmap(picDestination.Width, picDestination.Height)
' Create a Graphics object for the destination
Dim gr As Graphics = Graphics.FromImage(destinationbmp)
' Set the size of the area you want to copy
Dim selectionrectangle As New Rectangle(140, 20, 270, 400)
' Set the size of the destination rectangle to match the size of the second PictureBox
Dim destinationrectangle As New Rectangle(0, 0, picDestination.Width, picDestination.Height)
' Draw selected area on to the destination bitmap.
gr.DrawImage(sourcebmp, destinationrectangle, selectionrectangle, GraphicsUnit.Pixel)
' Set the drawn destination bitmap as the image of the second PictureBox
picDestination.Image = destinationbmp
End Sub
I hope that the detailed commenting makes it clear how this works. You can change the start points and the size of the selection rectangle to grab the required area. Of course, you may want to expand this to let the user select an area and I plan to cover that in a later blog.
The result of the above will be:
Introduction
Sometimes the list of entries in a ListView is so large that you need to give the user the means of finding a particular item. Here’s one way of doing that.
The user interface
Here’s the Windows Form I’m using for the demonstration:
The user enters the search term, hits the Find button and if a match is found that row will be selected. If no match is found, then a message will appear in the label (that currently just has a dash as its content).
The Code for the Search
Starting with the function that carries out the search:
53 Private Function FindItem(ByVal LV As ListView, ByVal TextToFind As String) As Integer
54
55 ' Loop through LV’s ListViewItems.
56 For i As Integer = 0 To LV.Items.Count - 1
57 If Trim(LV.Items(i).Text) = Trim(TextToFind) Then
58 ' If found, return the row number
59 Return (i)
60 End If
61 For subitem As Integer = 0 To LV.Items(i).SubItems.Count - 1
62 If Trim(LV.Items(i).SubItems(subitem).Text) = Trim(TextToFind) Then
63 ' If found, return the row number
64 Return (i)
65 End If
66 Next
67 Next
68 ' If not found, then return -1.
69 Return -1
70 End Function
you can see that the name of the list view and the search term are passed in as parameters. The first part of the For-Next loop checks if the search term exists in the first column of the list view. If it does, then the index number of that row is returned.
If it’s not found in the first column, then the remaining columns of that row are checked. Again, if a match is found, the index number of the row is returned.
The loop continues until either a match is found or the end of the list view is reached. If the end is reached, then a value of –1 is returned.
The Calling Code
Here’s the code in the click event of the Find button:
37 Private Sub btnFind_Click(sender As System.Object, e As System.EventArgs) Handles btnFind.Click
38 ListView1.MultiSelect = False
39 ListView1.FullRowSelect = True
40
41
42 Dim checkInt As Integer = FindItem(ListView1, TextBox1.Text)
43 If checkInt <> -1 Then
44 ListView1.Items(checkInt).Selected = True
45 ListView1.Focus()
46
47 Else
48 Label1.Text = "Search string not found"
49 End If
50
51 End Sub
I’ve set MultiSelect to False so that only the first occurrence is returned. The setting of FullRowSelect in line 39 is optional, but I prefer to use it.
The FindItem function is called and then the If-Then-Else block deals with the returned result. If the result isn’t –1 then a match has been found. That row number is then selected.
Because the last user action was the clicking of the button, the button will still have focus, so the selection in the list view won’t be highlighted (and you’d be tempted to think that the function had failed). Setting the Focus on to the list view solves this issue.
If the returned value is –1, then a message is shown in the label to let the user know.
How to deal with hidden rows
In most cases, the row being searched for won’t be one of the rows that is currently visible. So, if a match is found and that row is selected, once again the user probably won’t be aware of the successful match. The easiest way to deal with this is to add:
ListView1.SelectedItems(0).EnsureVisible()
to the code immediately after the ListView1.Focus() statement. If the SelectedItems(0) has you confused, the way it works is that SelectedItems is a collection of rows that are currently selected. Because in this example we’re just looking for the first occurrence, we know that it will be element 0 of that collection. (I plan to deal with multiple results in a follow-up blog). So the relevant lines of code will now be:
43 If checkInt <> -1 Then
44 ListView1.Items(checkInt).Selected = True
45 ListView1.Focus()
46 ListView1.SelectedItems(0).EnsureVisible()
47 Else
48 Label1.Text = "Search string not found"
49 End If
This will cause the list view to scroll to the selected and highlighted row.
Introduction
Going through some of my old posts this morning, I saw that this question seems to have been asked a lot. So I thought it was worth posting up an easy way of doing it.
Here’s the form at design time:
The label with the text of “Countdown finished” has its Visibility property set to False. So when the application first runs, the user sees:
The controls
Here’s a quick rundown of the controls used in this example:
| Control Type | Name | Purpose | Notes |
| Label | lblElapsed | Displays the countdown in minutes and seconds | Font set to Bold and Font Size 18 |
| Label | Label1 | Displays the instructions to the user | |
| Label | lblFinished | Displays a message when the countdown in complete | Visible property set to False. Foreground Red. FontSize = 22 |
| TextBox | txtMinutes | Allows the user to set the countdown time | |
| Button | btnStart | Start the countdown | |
| Timer | Timer1 | Counts down the elapsed time |
The code
Here’s how it works:
4 Dim tspn As New TimeSpan()
5
6 Private Sub btnStart_Click(sender As System.Object, e As System.EventArgs) Handles btnStart.Click
7
8 If IsNumeric(txtMinutes.Text) AndAlso CInt(txtMinutes.Text) > 0 Then
9 tspn = New TimeSpan(0, CInt(txtMinutes.Text), 0)
10 Timer1.Enabled = True
11 Else
12 MessageBox.Show("Please enter a numeric value in the text box", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
13 End If
14
15 End Sub
16
17 Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
18 tspn = tspn.Subtract(New TimeSpan(0, 0, 1))
19
20 lblElapsed.Text = String.Format(" {0} Mins : {1} Secs", tspn.Minutes, tspn.Seconds)
21 If tspn.Minutes = 0 AndAlso tspn.Seconds = 0 Then
22 Timer1.Stop()
23 lblFinished.Visible = True
24 End If
25
26 End Sub
Line 4 creates a new TimeSpan object. As it’s name suggests, this object represents a given period of time.
When the user clicks the button, Line 8 checks that a valid number has been entered. If it has, then the TimeSpan object is given the number of minutes the user entered. Note that the TimeSpan takes three values there – they represent, hour, minute and second values. Hour and second have been set to zero for this example, but you can change the code if you need to.
Line 10 then kickstarts the timer.
If the user had failed to enter a valid number in the text box, then Line 12, points out their error and the timer isn’t started.
The Timer Tick event occurs every second, so Line 18 ensures that as each second passes, one second is subtracted from the initial valur of the TimeSpan.
Then, the display is updated to show how many minutes and seconds still remain in the TimeSpan.
Next, in Line 21 a check is made to see if there is zero time left in the TimeSpan. If so, the timer is stopped. (If you didn’t do this,the timer would continue deducting seconds and the display would show negative times). As the countdown is complete, as an optional extra, the user is shown a message. This is done simply by making the previously hidden lblFinished label visible.
Summary
And that’s all there is to it. TimeSpans do seem to cause a lot of confusion, so if you’ve found yourself stuck on what seems like a fairly trivial task, it’ll probably be because you didn’t get the TimeSpan syntax right.
Introduction
Sometimes you might need to take a copy of what’s displayed in a ListView and save it. There are several options and one of these is simply to save it to a plain text file.
Saving to a known file name
If you know the file name, then you can use the following code:
Private Sub SaveToKnownFile(LV As ListView, FilePathAndName As String)
Dim sw As New StreamWriter(FilePathAndName)
For i As Integer = 0 To LV.Items.Count - 1
sw.Write(LV.Items(i).Text)
For subItemIndex As Integer = 1 To LV.Items(i).SubItems.Count - 1
sw.Write(":::" & LV.Items(i).SubItems(subItemIndex).Text)
Next
sw.Write(Environment.NewLine)
Next
sw.Close()
End Sub
You’ll see that I’ve hard-coded the separator characters as “:::”. These are the characters that any code that wants to read the data back from the file will need to use in order to split the lines back into the separate entries for the columns in the list view. I’ve found that it’s usually better to use some combination of characters that won’t come up in standard text writing. For instance, if you just used a comma as the delimiter then you’ll probably find that your data won’t be split correctly when you read it back, because commas are so common in everyday text.
So, you might want to expand the method to allow for a delimiter to be included as a parameter:
Private Sub SaveToKnownFileWithDelimiter(LV As ListView, FilePathAndName As String, Delimiter As String)
Dim sw As New StreamWriter(FilePathAndName)
For i As Integer = 0 To LV.Items.Count - 1
sw.Write(LV.Items(i).Text)
For subItemIndex As Integer = 1 To LV.Items(i).SubItems.Count - 1
sw.Write(Delimiter & LV.Items(i).SubItems(subItemIndex).Text)
Next
sw.Write(Environment.NewLine)
Next
sw.Close()
End Sub
And you could call it with something like this:
Private Sub btnSave_Click(sender As System.Object, e As System.EventArgs) Handles btnSave.Click
SaveToKnownFileWithDelimiter(ListView1, "C:\Temp\Contributors3.txt", "@@--@@")
End Sub
Letting the user select a file
You won’t always want to hard code the file path and name, so you can build in a save dialog and take out FilePathAndName :
Private Sub UseSaveFileDialogToSave(LV As ListView, Delimiter As String)
Dim sw As StreamWriter
Dim sfDialog As New SaveFileDialog
sfDialog.Filter = "Text Files (*.txt)|*.txt"
If sfDialog.ShowDialog = DialogResult.OK And sfDialog.FileName <> "" Then
If File.Exists(sfDialog.FileName) Then
sw = New StreamWriter(sfDialog.FileName)
Else
MessageBox.Show("Error with file selection")
End If
For i As Integer = 0 To LV.Items.Count - 1
sw.Write(LV.Items(i).Text)
For subItemIndex As Integer = 1 To LV.Items(i).SubItems.Count - 1
sw.Write(Delimiter & LV.Items(i).SubItems(subItemIndex).Text)
Next
sw.Write(Environment.NewLine)
Next
sw.Close()
End If
End Sub
Summary
You can use these simple methods to save ListView data to a text file. You can see how to write the data back from the text file to the ListView in this earlier blog item.
Introduction
Here’s an easy way you If you have a list of items in a list box and print them out to a printer. This version lets the user choose a printer from the PrintDialog first.
The Windows Form
It’s a very simple form – just a list box and a button:
The code that does the printing
You start by adding an Imports statement for the System.Drawing.Printing class.
Imports System.Drawing.Printing
Next, you create a PrintDocument. Essentially this object will hold whatever it is we decide we want to print. In this case, we know it will be the contents of the list box. Note that it’s declared WithEvents.
Private WithEvents docToPrint As New PrintDocument
And the reason it’s declared with events is because next we’re going to create the PrintPage event:
Private Sub document_PrintPage(ByVal sender As Object,
ByVal e As System.Drawing.Printing.PrintPageEventArgs) _
Handles docToPrint.PrintPage
This event handler really does all the important work. First, it creates a Font object that describes which font to use, what font size it will be, and whether any font attributes will be set, such as bold or italic. or this example, I’m staying with fairly plain text, but you can change these settings to whatever you want.
Dim printFont As New Font("Arial", 15, System.Drawing.FontStyle.Regular)
The next line creates an integer that will be used to move the print head down the printed page. You’ll see how this works in a moment.
Dim YPosition As Integer = 40
I picked the value of 40 to create the amount of space between the lines that looked right to me. You can of course change this – and you would need to if, for instance, you used a larger font.
The final four lines of the PrintPage event print the content.
For Each hotel As String In lstHotels.Items
e.Graphics.DrawString(hotel, printFont, System.Drawing.Brushes.Black, 25, YPosition)
YPosition += 40
Next
As you can see, each item in the list box is dealt with separately. The DrawString method is passed the following parameters:
Then, to set the print head up for the next line, the YPosition value is increased, and this moves the start position down the page.
The calling code
If you want to give the user the opportunity to select a printer, you can create and display a PrintDialog. Actually, the PrintDialog has a whole bunch of properties that you can configure, if you want to give the user even more options. But for this example, I’m just going to keep those choices to the minimum.
Private Sub Button1_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
Dim PrintDialog1 As New PrintDialog
Dim result As DialogResult = PrintDialog1.ShowDialog()
If result = DialogResult.OK Then docToPrint.Print()
End Sub
Essentially, what happens here is that when the user clicks the OK button of the dialog, the PrintDocument’s Print method is called. The page will then be printed, with each item of the list box in turn on a new line.
Summary
So, there it is – an easy way to print out the items in a list box to the printer.
Introduction
Although you’ll most often use serialization to store objects in a file, you can use it to store the data from a ListView. Here’s how.
Serialize the data
The following code serializes a ListView’s data to a file:
Private Sub SerializeListViewData(LV As ListView, ByVal filename As String)
' Create a FileStream and get the file to write to.
Dim FS As FileStream = File.Create(filename)
' Create a Binary Formatter for Serialization process
Dim BinFmtr As New BinaryFormatter
' Create an arraylist as temp storage for listview items data
Dim alSavedLV As New ArrayList
' Iterate through the ListView's listitem collection and add
' each to the temporary ArrayList
For item As Integer = 0 To lv.Items.Count - 1
' Add next item/subitem to the arraylist
alSavedLV.Add(LV.Items(item))
Next
' Serialize the complete arraylist to the file
' The arraylist contains all the listview data
BinFmtr.Serialize(FS, alSavedLV)
' Close the FileStream
FS.Close()
End Sub
The first step is to create a FileStream that will create the pipeline from the data to the file it’s going to be stored in. This FileStream will be passed the path and name of the target file
Next, you create a BinaryFormatter object that will do the serialization for you. Note that you need to have an Imports statement pointing to System.Runtime.Serialization.Formatters.Binary to access this.
You can’t directly serialize the columns and rows from the ListView to the file, so what you do is create a collection and then serialize this. One collection type that works well is the ArrayList. The next line of code creates this.
Then, you read each row of data from the ListView into the ArrayList.
Finally, you take that BinaryFormatter, use its Serialize method, passing in the FileStream (to connect to the file) and the ArrayList(to give access to the ListView data).
Deserialize the data to a ListView
The serialized data is fine where it is, but presumably at some point you may want to pipe it back into the ListView. To do that, you use a similar approach. You create a FileStream, a BinaryFormatter, and an ArrayList again.
Then, you use the Deserialize method of the BinaryFormatter object and read the data from the file into the ArrayList.
Once the ArrayList holds the data, you can iterate through it, read the content, cast each element to ListViewItem, and then add the ListViewItem to the ListView.
Here’s the code that does this:
Private Sub DeserializeToListView(ByVal LV As ListView, ByVal filename As String)
' Create a FileStream to access the storage file
Dim FS As FileStream = File.Open(filename, FileMode.Open)
' Create a Binary Formatter for Serialization process
Dim BinFmtr As New BinaryFormatter
' Create an arraylist as temp storage for listview items data
Dim alSavedLV As New ArrayList
' Deserialize the data from the file and put it in the arraylist
alSavedLV = CType(BinFmtr.Deserialize(FS), ArrayList)
' Read the arraylist contents into the listview
Dim lvi As ListViewItem
For item As Integer = 0 To alSavedLV.Count - 1
lvi = New ListViewItem
lvi = CType(alSavedLV(item), ListViewItem)
LV.Items.Add(lvi)
Next
' Done with the FileStream
FS.Close()
End Sub
Summary
Once you understand the tools you can use – FileStream, BinaryFormatter, and ArrayList – serializing and deserializing is a trivial task.
Doing some work for a customer on SharePoint 2010 where I hadn't setup the initial environment & came across an interesting situation which had me pulling what little hair I have out, so thought I'd create a quick blog post in case anyone else stumbles upon this situation in the future.
The web app had initially been setup using Classic Mode Authentication but due to access being required with both Windows & Forms Based Authentication using the SQL provider mechanism I needed to change it to Claims Based Authentication. This all went relatively smoothly apart from one tiny problem....
Previously to the switch over spreadsheets had been opening nicely in the browser with Excel Services however after the change over, they were getting the error that the user did not have permissions to open the file in the browser. This was easily remedied by jumping into Global Settings for excel services changing the File Access Method from Impersonation over to using the Process account instead, and I also setup the Unattended Service Account which for some reason they hadn't done in the initial install.
Then tried opening the file in the browser again only to be confronted with a new error "The workbook cannot be opened." This had me scratching my head for a little while until I looked in the event log where I found that the Service Account being used for Excel Services hadn't been given any rights on the content database. After which the fix was easy to implement with the following PowerShell commands
$webApp = Get-SPWebApplication "http://YourSharePointSite"
$webApp.GrantAccessToProcessIdentity("YourDomain\ExcelServicesAccountName")
Hopefully this will save someone else a bit of time.
Introduction
If you want to restrict the user input into a text box, you can check what the current key press is and then decide if it’s an allowed key or not. At the other end of the scale, you can create a standalone user control that can be added to the Toolbox, and have instances of it dragged on to forms across several projects. This article looks at an approach half way between the two.
The TextBox code
In a Windows Forms application, create a new class and name it NumericTextBox. Add an Inherits statement as shown below that will make this class inherit from the standard TextBox class:
Public Class NumericTextBox
Inherits TextBox
The next step is to identify the keys that we will allow the user to use in this text box. One way of doing this is to create an array that holds the Ascii key codes for allowed keys.
In our case, this will obviously be the numerals 0 to 9, but we probably also want to allow things like the period, comma, delete and backspace key. So, these are all added to the array.
' Allowed keys
Dim allowedKeys As Short() = {8, 44, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 127}
With that in place, the reminder of the code overrides the KeyPress event of the text box and checks if the current key press is allowed or not.
Protected Overrides Sub OnKeyPress(ByVal e As KeyPressEventArgs)
Dim KeyAscii As Short = CShort(Asc(e.KeyChar))
MyBase.OnKeyPress(e)
' Check if this key is allowed
If allowedKeys.Contains(KeyAscii) Then
Exit Sub
Else ' Ignore input
e.Handled = True
Beep()
End If
End Sub
When the user presses a key, the value of that key is stored as a KeyChar property. So, firstly, this code casts the key char to a Short value named KeyAscii before it then allows the text box standard key press code to continue.
Then it checks to see if the current key press Ascii code is one of the ones contained in that array of allowed values. if it is, then the code lets the key press go through. if it’s not an allowed key, then the Handled property of the KeyPressEventArgs is set to True. This effectively tells the key press handler that this key press has been dealt with and instructs it not to consider it any further. In other words, that key press is to be ignored. Optionally, you can warn the user by playing the Beep sound.
At its most basic, that’s all that’s needed. Here’s a summary of the code so far:
Public Class NumericTextBox
Inherits TextBox
' Allowed keys
Dim allowedKeys As Short() = {8, 44, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 127}
Protected Overrides Sub OnKeyPress(ByVal e As KeyPressEventArgs)
Dim KeyAscii As Short = CShort(Asc(e.KeyChar))
MyBase.OnKeyPress(e)
' Check if this key is allowed
If allowedKeys.Contains(KeyAscii) Then
Exit Sub
Else ' Ignore input
e.Handled = True
Beep()
End If
End Sub
End Class
The next step is to use the NumericTextBox in a form.
Using the text box in a form
After you Build the project, go to the Windows Form code page and add the following code:
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
Dim numericTextBox As New NumericTextBox
With numericTextBox
.Left = 20
.Top = 50
.Name = "ntxtPrincipal"
Me.Controls.Add(numericTextBox)
End With
End Sub
Now, when you run the application, the new NumericTextBox will have been added, and the user will only be able to add those allowed characters into it.
A couple of options
As all experienced developers know, if it’s possible for a user to foul up the input, they probably will at some time. So one basic safety check you may want to include is to stop them entering more than one period character.
This is easy to implement. Change the code for the NumericTextBox class as shown:
' Allowed keys
Dim allowedKeys As Short() = {8, 44, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 127}
Private periodUsed As Boolean = False
Protected Overrides Sub OnKeyPress(ByVal e As KeyPressEventArgs)
Dim KeyAscii As Short = CShort(Asc(e.KeyChar))
MyBase.OnKeyPress(e)
If KeyAscii = 46 AndAlso periodUsed = True Then
e.Handled = True
End If
' Check if this key is allowed
If allowedKeys.Contains(KeyAscii) Then
If KeyAscii = 46 Then periodUsed = True
Exit Sub
Else ' Ignore input
e.Handled = True
Beep()
End If
End Sub
I’ve highlighted the changes. First, I added a Boolean that keeps track of whether a period has already been entered. Then before the code even checks if the current key press is an allowed one, it specifically checks to see if this key press is a period and the text box already contains a period. If this is the situation, then this attempt to enter another period is blocked by the use of the e.Handled = True line. The final action is to switch that Boolean to True the first time the user enters a period.
Summary
That’s a very basic numerals only text box. You can of course expand the options to control what the user is allowed to enter, if you want a text box that, for instance, only allows certain letters. Or certain letters and numbers, and so on.
Introduction
The ListView is a really useful control for display data, but it’s not always easy to see how to get it to look just the way you want. Here are a few tips and tricks.
First, there’s how to change the color of alternative lines, then there’s how to insert a new line of data at runtime. Finally, how to find an item in a ListView and change it.
Change the color of alternate lines
To enhance the look of the otherwise plain white background, you can inject color into alternate lines:
The code is quite simple:
Private Sub ChangeAlternateColors(LV As ListView)
Dim color1 As Color = System.Drawing.Color.LightBlue
Dim color2 As Color = System.Drawing.Color.Beige
Dim alternator As Integer
Dim lvi As ListViewItem
For Each lvi In LV.Items
If alternator Mod 2 = 0 Then
lvi.BackColor = color1
Else : lvi.BackColor = color2
End If
alternator += 1
Next
End Sub
The key that makes this work is Integer variable named alternator. As the code enumerates through each line of the ListView, this variable increments by 1. Then, a check is made to see if the value of alternator is odd or even. That’s what the
If alternator Mod 2 = 0 Then
line does. If the line number is even, then color1 is used as the background; otherwise color2 is used. Simple, but effective.
Insert a new item into a specific row of a ListView
If you want to programmatically add a new item, there are a couple of options. if it’s just a question of adding text to the first column, then you can use this approach:
ListView1.Items.Insert(3, "James May")
In this example, the name is inserted as a new row (which is of course the fourth row down, because the ListView Items are zero indexed).
In reality, you’ll usually want to insert data in other columns too. This takes a slightly more verbose approach, but it’s still easy:
With ListView1
.Items.Insert(3, "James May")
.Items.Item(3).SubItems.Add("www.bbc.co.uk/topgear")
.Items.Item(3).SubItems.Add("Technology, cars, engineering, aeroplanes, flying")
End With
You can see the result here:
James May has been added to the fourth line.
Find an item and change it
If you need to programmatically find a particular item in the ListView, and then edit the content, you can use code like this:
Private Sub FindAndChangeAnItem(LV As ListView, SearchText As String, ReplacementText As String)
For i As Integer = 0 To LV.Items.Count - 1
If Trim(LV.Items(i).Text) = SearchText Then
LV.Items(i).Text = ReplacementText
End If
Next
End Sub
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
FindAndChangeAnItem(ListView1, "James May", "James A. May")
End Sub
This example only looks in the first column.
And, as before, in the real world things are seldom as easy as just needing to change something in column 1. So if you need to dig deeper into the other columns, then you can search the subitems too, find the search term,and make the change:
Private Sub FindAndChangeASubItem(LV As ListView, SearchText As String, ReplacementText As String)
For i As Integer = 0 To LV.Items.Count - 1
If Trim(LV.Items(i).Text) = SearchText Then
LV.Items(i).Text = ReplacementText
Exit Sub
Else
For subitems As Integer = 0 To LV.Items(i).SubItems.Count - 1
If Trim(LV.Items(i).SubItems(subitems).Text) = SearchText Then
LV.Items(i).SubItems(subitems).Text = ReplacementText
Exit Sub
End If
Next
End If
Next
End Sub
Calling code:
FindAndChangeASubItem(ListView1, "www.bbc.co.uk/topgear", "http:www.jamesmay.com")
Summary
These little tips and tricks can change your ListView experience from one that’s quite limited and frustrating, to something that makes you realize that it’s a really useful control that you’ll be happy to use.
Introduction
In an earlier blog I showed how to search for a word or phrase in any column of a list view, and then select and highlight any rows that contained the search word or phrase. In that first example, I restricted the search in two ways.
Firstly, I stopped as soon as the search string had been found once (and so ignoring the situation where the same term might occur several times). Secondly, and perhaps more importantly, that example required the search term to be matched exactly with what appeared in any of the columns. In other words, if the search term was ‘Jeff’, then it wouldn’t be found as a match in a column that contained the phrase ‘Jeff Martin’. In many real world scenarios, this simply won’t cut it, so let’s move on to the next stage and build in these features.
Contains – not Equals
The key to the partial match search is to use the Contains string function in place of the “=” symbol approach we first used. As you’d expect from the name, Contains will return a value of True if the string contains the search term within any part of its whole length. So, it will return True for ‘Jeff’ in Jeff Martin, or True for ‘Mar’ in Jeff Martin, or even True for ‘ff M’ in Jeff Martin. You get the picture.
Here’s part of the code for the function that carries out the search:
Private Function FindPartialItems(ByVal LV As ListView, ByVal TextToFind As String) As List(Of Integer)
' Loop through LV’s ListViewItems.
For i As Integer = 0 To LV.Items.Count - 1
If Trim(LV.Items(i).Text).Contains(Trim(TextToFind)) Then
As you can see, the Contains function is used to check if the first column contains the search term. Trim is used to remove spaces either side of the search term and the text in the column, simply to avoid any matches that might fail just because one side has a space and the other doesn’t.
Storing the row numbers where a match is found
Let’s look at a bit more of the procedure to see what happens if a match is found:
Private Function FindPartialItems(ByVal LV As ListView, ByVal TextToFind As String) As List(Of Integer)
Dim rowsFound As New List(Of Integer)
' Loop through LV’s ListViewItems.
For i As Integer = 0 To LV.Items.Count - 1
If Trim(LV.Items(i).Text).Contains(Trim(TextToFind)) Then
' If found, add to collection
rowsFound.Add(i)
End If
At this stage, a List(Of Integer) has been added, and this will be used to hold the row numbers where matches are found. List(Of T) is probably a bit of a sledgehammer for this task, but I find it much easier to work with than other options, such as an array of ints.
So, if the text in the first column of the current row is found to contain the search term, the row number is added to the list.
Checking the remaining columns
That’s the first column dealt with, so next the code will check the remaining columns.
Private Function FindPartialItems(ByVal LV As ListView, ByVal TextToFind As String) As List(Of Integer)
Dim rowsFound As New List(Of Integer)
' Loop through LV’s ListViewItems.
For i As Integer = 0 To LV.Items.Count - 1
If Trim(LV.Items(i).Text).Contains(Trim(TextToFind)) Then
' If found, add to collection
rowsFound.Add(i)
End If
For subitem As Integer = 0 To LV.Items(i).SubItems.Count - 1
If Trim(LV.Items(i).SubItems(subitem).Text).Contains(Trim(TextToFind)) Then
' If found, note the row number unless the same search term was found in an earlier column of this row
If Not rowsFound.Contains(i) Then rowsFound.Add(i)
End If
Next
Next
The nested loop For subitem As Integer … checks through each of the remaining columns of the current row. Again, it uses the Contains method to see if there’s a match to be found.
Then, we want to deal with the case where the search phrase occurs more than once in the same row. To avoid duplicate numbers in the list of rows, you’ll see that the Contains method is used again for a different purpose:
If Not rowsFound.Contains(i) Then rowsFound.Add(i)
This time it makes sure that a row number is only added to the list once.
Returning the result
The final task, once the whole list view has been processed is to return the list of integers:
Return rowsFound
So the complete FindPartialItems method looks like this:
Private Function FindPartialItems(ByVal LV As ListView, ByVal TextToFind As String) As List(Of Integer)
Dim rowsFound As New List(Of Integer)
' Loop through LV’s ListViewItems.
For i As Integer = 0 To LV.Items.Count - 1
If Trim(LV.Items(i).Text).Contains(Trim(TextToFind)) Then
' If found, add to collection
rowsFound.Add(i)
End If
For subitem As Integer = 0 To LV.Items(i).SubItems.Count - 1
If Trim(LV.Items(i).SubItems(subitem).Text).Contains(Trim(TextToFind)) Then
' If found, note the row number unless the same search term was found in an earlier column of this row
If Not rowsFound.Contains(i) Then rowsFound.Add(i)
End If
Next
Next
' Return the resulting collection of rows
Return rowsFound
End Function
The Calling Code
All that remains is to write some code that uses this search method:
Private Sub Button_Click(sender As System.Object, e As System.EventArgs) Handles btnPartialSearch.Click
ListView1.FullRowSelect = True
ListView1.MultiSelect = True
Dim foundRows As New List(Of Integer)
foundRows = FindPartialItems(ListView1, TextBox1.Text)
If foundRows.Count = 0 Then Label1.Text = "Search string not found"
For i As Integer = 0 To foundRows.Count - 1
ListView1.Items(foundRows(i)).Selected = True
Next
ListView1.Focus()
ListView1.SelectedItems(0).EnsureVisible()
End Sub
This is similar to the calling code used in the earlier blog. The main changes are that MultiSelect is now set to true. Obviously, if we’re returning a list of potentially multiple hits, we want to able to highlight them all.
Next, a temporary list of integers is created and the search function called. Once a result has been returned, it first tests that there has been at least one match. If not, a message is displayed.
Then, if there are one or more matches, the row numbers can be pulled from the list of integers and each of those rows is selected.
Finally, as in the earlier blog, the focus is handed off to the list view to bring the highlights to life, and if necessary the list is scrolled to reveal the first matching row.
Introduction
Sometimes you’ll want to highlight items in a ListView to grab the user’s attention. One way you can do this is to programmatically apply Bold font weight to text.
Bold all items in the first column
Let’s say you have a ListView like the one below:
To bold all the text in the first column is particularly easy. There are only two steps:
For Each lvi As ListViewItem In ListView1.Items
lvi.UseItemStyleForSubItems = False
' lvi.SubItems(0).Font = New Font(ListView1.Font, FontStyle.Bold)
lvi.Font = New Font(ListView1.Font, FontStyle.Bold)
Next
Using ‘lvi.Font’ in this example is effectively the same as using lvi.SubItems(0).Font. So, this would work just as well:
For Each lvi As ListViewItem In ListView1.Items
lvi.UseItemStyleForSubItems = False
lvi.SubItems(0).Font = New Font(ListView1.Font, FontStyle.Bold)
'lvi.Font = New Font(ListView1.Font, FontStyle.Bold)
Next
Bold all items in a selected column
The second example above should make it clear what we need to do to bold one of the other columns. You simply change the index of the target column and use the same code:
For Each lvi As ListViewItem In ListView1.Items
lvi.SubItems(2).Font = New Font(ListView1.Font, FontStyle.Bold)
Next
The result will be:
Bold only items that contain a search term
Let’s take a scenario where you want to highlight all items in the second column that contain the string ‘web’ as part of its text.
For Each lvi As ListViewItem In ListView1.Items
If lvi.SubItems(1).Text.Contains("web") Then
lvi.UseItemStyleForSubItems = False
lvi.SubItems(1).Font = New Font(ListView1.Font, FontStyle.Bold)
End If
In my example, the result will be:
Of course, you could use this kind of code to search for an exact entry, not just a substring. In that case, you’d use something like
If lvi.SubItems(1).Text.Contains(" (fredi@gerts.ch )”) Then
But bear in mind that spaces might mean that sometimes you don’t get a match you think exists. You can use the Trim function to strip out unimportant space characters.
And you can search through the whole ListView for a partial or exact match if you tweak the above code a little.
Recently I was browsing through the extensions available for Visual Studio when I came across this handly little extension called Web Essentials.
Ive been using this extension for a few weeks now and figured it was time for me to share the wealth.
For any web developer this extension is a nice tool to have in your arsenal, I know I enjoy having it in mine.
A few features of the Web Essentials extension that I favor the most are
If your interested in checking out the full list of features you can find the documentation here
Happy Coding!
Introduction
This came up as a question on VB City recently, where the poster wanted to reduce image file sizes before saving to a database as a BLOB. It turns out that it’s easier to do than you might think. If you have an Image object, you can use its Save method to store it to your hard drive or other storage media. At the same time, you can use an encoder parameter that sets the quality of the saved image.
Here’s how to do it:
The core code
This method takes the image to be compressed, the path and file name that you want to use for the save, and a quality level between 1 and 100. The lower the value of the quality level parameter, the greater the compression. Of course, as you increase the compression (i.e. the lower the number), the quality of the saved file will reduce. So you’ll often have to experiment to find the best compromise between size and quality.
Private Sub CompressAndSaveImage(ByVal img As Image, ByVal fileName As String, ByVal quality As Long)
Dim parameters As New EncoderParameters(1)
parameters.Param(0) = New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality)
img.Save(fileName, GetCodecInfo("image/jpeg"), parameters)
End Sub
You’ll see that the second parameter of the Save method calls another method called GetCodecInfo and passes in a string that represents a mime type. Here’s that second method, which loops through all image encoders on the system and returns the one that’s required for the selected image type. In the event that a non-existent image type is passed in to this method, an error is thrown.
Private Shared Function GetCodecInfo(ByVal mimeType As String) As ImageCodecInfo
For Each encoder As ImageCodecInfo In ImageCodecInfo.GetImageEncoders()
If encoder.MimeType = mimeType Then
Return encoder
End If
Next encoder
Throw New ArgumentOutOfRangeException(String.Format("'{0}' not supported", mimeType))
End Function
Finally, you call the compress and save image method, passing in the required arguments. For example:
CompressAndSaveImage(selectedImage, reducedImage, 50)
where selectedImage is an image object, reducedImage is a string that defines the path and file name to save, and 50 represents the quality level.
So, that’s all the core code you need to compress an image file. Let’s take a look at how you can make it available to your users.
Adding a user interface
Here’s one way of using it:
The key controls on this form are:
The code is as follows:
First, add Imports statements :
Imports System.Drawing.Imaging
Imports System.IO
Then, declare a form level variable to keep track of the user’s choice of compression/quality level:
Dim level As Long = 50
Catch the user’s choice of quality level when it changes from the default of 50:
Private Sub qualityLevel_ValueChanged(sender As System.Object, e As System.EventArgs) Handles qualityLevel.ValueChanged
btnCompress.Enabled = True
level = CLng(qualityLevel.Value)
End Sub
Finally, when the user clicks the button, do the following:
Private Sub btnCompress_Click(sender As System.Object, e As System.EventArgs) Handles btnCompress.Click
' Get user's choice of file
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim selectedImage As Image = Image.FromFile(OpenFileDialog1.FileName)
' Display it
PictureBox1.Image = Image.FromFile(OpenFileDialog1.FileName)
' Create a name for the reduced file
Dim reducedImage As String = "C:\Temp\Reduced_" & OpenFileDialog1.SafeFileName
' Compress and save the reduced file
CompressAndSaveImage(selectedImage, reducedImage, level)
' Display the reduced image so that user can compare quality
PictureBox2.Image = Image.FromFile(reducedImage)
PictureBox2.SizeMode = PictureBoxSizeMode.StretchImage
End If
End Sub
Final Note
That works well, although you still need to build in real world checks, such as making sure the user selects an image file type from the open file dialog, and so on. Another small problem is that the code will fail if the reduced file name already exists. You can code round this in several ways, according to your preference, but one way would be simply to tell the user about the problem:
If Not File.Exists(fileName) Then
img.Save(fileName, GetCodecInfo("image/jpeg"), parameters)
Else
MessageBox.Show("Reduced file already exists.")
End If
You could extend this code so that it either automatically deletes an existing file or asks the user to authorise the deletion before proceeding. I’d also be tempted to add a couple more labels to the form and show the user the original file size and the reduced file size. You can use FileInfo objects for this.
Summary
This is a useful little procedure that you can use when you want to reduce the size of an image file, but want to be able to judge the loss of quality.
Introduction
I was looking through some questions I answered a while back and came across this problem where someone wanted to read text from a file, strip out the commas, and then store the individual items in an in-memory List. Here’s the way I did it:
The text file
Here’s the structure of a text file that we want to use. This is just an example:
All red berries, Blackcurrant, Strawberry, Cranberry
Banana, Pineapple,
Rhubarb, Pear, Granny Smith Apple
Other apple, cherry, damson
grape
plum, mandarin orange
Code that reads the file
The first step is to create the List that will hold the items:
Dim stockList As New List(Of String)
Next, we need to access the text file and set up some variables that we’ll use to store the data as we process it:
Try
Dim file_name As String = "C:\Temp\stockList.txt"
Dim stream_reader As New IO.StreamReader(file_name)
Dim line As String
Dim ReadResult() As String
The first line identifies the path and name of the source file. The second line creates a StreamReader that will be used to get the text from the source file. If you use an Imports statement for System.IO at the top of the file, you can drop the “IO.” part of the code.
The variable named “line” will hold all the characters in each line of the file as it’s being read. Finally, the array “ReadResult” will temporarily hold each sub-string from a line of text in the file. So, to take the first line as an example, ReadResult would hold four strings -
All red berries
Blackcurrant
Strawberry
Cranberry
Now, the code for the reading, processing, and adding to the List tasks:
' Read the file one line at a time.
line = stream_reader.ReadLine()
Do While Not (line Is Nothing)
' Trim the line in case there are any leading or trailing spaces in file line
line = line.Trim()
' split using comma chars
ReadResult = line.Split(",")
' Populate List
For i As Integer = 0 To ReadResult.Length - 1
If ReadResult(i).Length > 0 Then stockList.Add(ReadResult(i).Trim.ToString)
Next
' Move on to the next line.
line = stream_reader.ReadLine()
Loop
The ReadLine method does what you’d expect, and reads a complete line from the file. It then stores that line in the String variable named “line”.
Next, the Do While Loop first removes any leading or trailing spaces from the line. Don’t be confused here: This only affects spaces at the very beginning of line, such as the third line in the file that has spaces before the first word, or spaces at the very end of the line.
The Split function reads the line of text and splits it up whenever it finds a comma. It then assigns each chunk of text to one of the elements in the ReadResult array.
Now that ReadResult has the split contents of the line, the next step is pass those strings to the List. The code block begins with a For statement that ensures that each element of the ReadResult array will be read in turn.
The next line starts with an If statement and might look a bit complicated. But really all it does is:
The last action in the loop is to move the reader down to the next line in the text file.
Finally in the reading and processing stage, the StreamReader is closed and a message box is used if there’s any problem accessing the file or processing the text:
Catch exc As Exception
' Report all errors.
MessageBox.Show(exc.Message.ToString, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Displaying the result
For the purposes of demonstration, I’ve added code that will fill a list box with the individual items:
For Each Str As String In stockList
ListBox1.Items.Add(Str)
Next
The result in the windows form when this code runs looks like this:
Introduction
Here’s a little ListView trick that might come in useful sometimes. The user selects an individual sub item in a list view and you want to know what they selected.
The code
You can code the MouseDown event of the ListView to identify the selection:
Dim usersSelection As String = String.Empty
Private Sub ListView1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseDown
Dim info As ListViewHitTestInfo = ListView1.HitTest(e.X, e.Y)
usersSelection = info.SubItem.ToString
usersSelection = usersSelection.Substring(18)
usersSelection = usersSelection.Substring(0, usersSelection.Length - 1)
Me.TextBox1.Text = usersSelection
End Sub
How it works
The first line creates a String variable that will store the user’s selection.
Then, in the MouseDown event, an instance of the ListViewHitTestInfo class named ‘info’ is created. This object can return information about the ListView if it’s passed information such as the current location of the cursor. That’s where the ListView’s HitTest function is used and, as you can see, this function is passed in the current X and Y points of the mouse cursor (e,X and e.Y). Alternatively, you can pass in e.Location in place of the X and Y values and this seems to work just as well.
In the next few lines, I’ve purposely broken the code into three steps just to make it easier to read. You could of course put this all in one line of code. It works like this:
The result
Here’s an example that shows this in action:
If the full row selection is confusing, you can turn it off in the properties window. That way, it’s a bit more obvious where the user is clicking:
You can see the cursor position here.
Summary
This code returns items (i.e. column 1 text) and sub items (any other column). If – as in my example – you let the user see an area of the list view that doesn’t contain a column (i.e. the blank area at the right hand side), you’ll need to code agains the user clicking in that area. As it stands, the system will crash. You can do this very simply by testing with:
If Not info.SubItem Is Nothing Then
. . .
It’s also possible to include code that returns the index number of the selected column text of the column header of the selected column, although that’s not really a requirement you’re likely to need often.
Murach's ASP.NET 4 Web Programming with VB 2010
This is the first Murach book that I have the chance to read and I love the "paired-paged" layout, the organisation and the overall flow of the book.
The paired-paged layout gives the reader information and explanations on the left side and code samples, guidelines, descriptions on the right.
Starting out the book takes you through the basics of ASP.NET and moves you right into real world scenerios and concepts.
Reaching the end of the book you will have learned a great deal about the core concepts of asp.net, making web applications responsive and secure.
By far one of the best programming books on my shelf.
No matter the skill level, this book is a great read and full of knowledge!
Click here to check out the page on Murach's website.
Thanks Murach!!
The descriptions on Microsoft’s site don’t make it very clear that there are two separate versions of the Visual Studio 11 preview that you can download and try. The one you’ll probably find first is the almost complete VS preview here.
This is pretty much the whole package in terms of the changes they’ve made to the Windows 7/Win 32 base version. The best advice generally is to install it somewhere other than your main system – a separate partition, on a spare machine, or in a virtual machine. VMware and Virtual Box both seem to do the job nicely.
Just for the heck of it, I have tried installing a copy on my main machine, and uninstalled it without causing any problems to the original VS 2010 that was also installed. But that’s no guarantee that it’ll work as smoothly for you, so as they used to say on Hill Street Blues, “Be careful out there”.
I said ‘pretty much’ the whole package, but of course the much talked about Metro UI is a Windows 8 feature and so you can’t get at it with the Windows 7 based preview. If you want to play with Metro then you need to download the much bigger package from here
Now this is an installation that you definitely want to keep well away from your workaday system. Again, most people seem to install this in a virtual machine and the most successful one seems to be Oracle’s Virtual Box.
Although I’ve used both VMWare and Virtual Box extensively in the past, and found them both to be excellent, intuitive tools, my Windows 8 experience wasn’t quite so good. I’m sure this has more to do with the fact that it’s a developer preview than any fault with the VMs. But I had issues with speed (not unusual for VMs, but more obvious on this occasion) and also some problems with display resolution and size.
So I thought I’d try and find an alternative that still let me use my main developer machine. Dual booting usually leads to frustration, and is especially tricky when one of the OSs isn’t fully baked. And you wouldn't get good odds on a clean and successful uninstall at some later stage either. The route I took was to use Paragon’s Hard Disk Manager tool.
The key feature of this tool that I needed was the ability to hide a partition. That way I could have Win 7 on one partition, Win 8 on another, and when I booted up the system only the one I wanted at that particular time would be visible to the system.
And so that’s what I did – created two partitions on the drive, one of them hidden. I then installed Windows 8 preview on the second partition. I used a DVD I‘d created from the original downloaded iso to install the Windows 8 OS. One thing I did find is that I had to leave this disk in the tray when I rebooted, although I ignored the ‘Boot from CD/DVD’ message each time I ran it after the first installation. I really don’t know why it seemed to need that, but anyway, it worked OK.
When I wanted to go back to my Windows 7 installation, I rebooted with the Paragon Recovery Disk in the CD tray (you’ve got a recovery disk right?). The Paragon menu software then let me switch the partitions back (i.e. hiding the Windows 8 one, and making the Windows 7 one available).
Of course, this only works well if you’re happy to be restricted to the one OS at a time, which I was. Although I have the full Paragon Hard Disk Manager 11 Suite, which is an exceptionally useful tool, you can in fact create and hide partitions with their free version of Partition Manager (although currently on offer at $9.95 it probably wouldn’t break the bank to get the retail version, which has more features).
Windows 8, with its Metro UI tiles, is interesting, but takes some getting used to. The ‘immersive’ experience, that Microsoft like to talk up, generally means that you find yourself searching around for some way to minimize, resize, or even close down a running Metro UI app. Like most people, I find the way it switches back to desktop (Windows 7) mode a bit jarring, although I realise that you can’t magically “Metrofy” all those old applications.
I’m most interested in seeing if all those long hours I’ve put in learning WPF and Silverlight over the past few years will be useful for creating Metro apps with XAML. I’m optimistic that they will be. The namespaces and classes may have changed, but the underlying approach seems very similar.
This is one of those simple things that comes into the category of “I know how to do it, but, umm, it’s been a while, and now I’ve forgotten how!”
So, here’s an enumeration of strings:
Public Enum QuestionCategory
Art
Music
People
Places
Science
Words
Miscellaneous
BeginsWith
Inventions
History
Animals
Legends
End Enum
If I want to populate a combo box named cboCategories with these strings, I can use the following code:
Me.cboCategories.DataSource = System.Enum.GetValues(GetType(QuestionCategory))
Then, when I want to know the user’s selection, I use:
Me.cboCategories.SelectedValue.ToString()
That’s it!
Happy holidays. Here are a few easy programming tips that can improve your technique. They're aimed at beginners, as well as more experienced programmers who started with VB Classic.
TIP 1: Combine variable declaration and initialization.
The following two code snippets are equivalent:
Dim sr5 As Decimal ... sr5 = Math.Sqrt(5)
Dim sr5 As Decimal = Math.Sqrt(5)
However, I strongly prefer the second usage, because:
TIP 2: Use Booleans to help document, and to avoid recoding the same test condition.
Again, here are the "before" and "after" versions:
Dim emp As New EmployeeRec
If (HoursWorked > 40) Then
emp.RegHours = 40
emp.HasOT = True
emp.OTHours = HoursWorked - 40
Else
emp.RegHours = HoursWorked
emp.HasOT = False
End If
Dim emp As New EmployeeRec
Dim WorkedOT As Boolean = (HoursWorked > 40)
If (WorkedOT) Then
emp.RegHours = 40
emp.OTHours = HoursWorked - 40
Else
emp.RegHours = HoursWorked
End If
emp.HasOT = WorkedOT
In this case, the second version doesn't benefit from significantly briefer code (although it often does). The benefits are readability, and a more obvious mapping of the condition to the EmployeeRec.HasOT attribute. I could have shortened this further by using emp.HasOT directly instead of introducing the Boolean, but it would have been less illustrative.
TIP 2A: Use the shorthand boolean assignment.
The assignment of WorkedOT in the above example is much shorter than the code below. So don't do it this way:
Dim WorkedOT As Boolean
If (HoursWorked > 40) Then
WorkedOT = True
Else
WorkedOT = False
End If
TIP 3: Use variables to prevent multiple calls to functions.
Again, before and after:
If CalculateOTPay(HoursWorked, HourlyRate) > 0 Then ... emp.OTPay = CalculateOTPay(HoursWorked, HourlyRate) Else emp.OTPay = 0 End If
Dim PayOT As Decimal = CalculateOTPay(HoursWorked, HourlyRate) If (PayOT > 0) Then ... emp.OTPay = PayOT Else emp.OTPay = 0 End If
It's really important to avoid the first usage. Running complicated functions multiple times can be expensive in run time. And worse, in some cases you may get a different answer! For example, if the function returns "seats available" and someone else just booked a seat. Or if the date changes. Or if the function communicates with a sensitive hardware gauge that measures continually changing values like network traffic or conveyor belt speed. Trust me, there are more examples.
Thanks for reading. Happy new year to all.
Introduction
I don’t know what it is about the syntax for the Filter property of the open file dialog, but it often seems to take me longer than it should to get it to work the way I want. If you’ve had problems too, then this may help you.
Step 1: create the OpenFileDialog
Although you can drag an open file dialog from the toolbox, it’s just as easy to create it on the fly:
Dim openfiledlg As New OpenFileDialog
Step 2: Create a With block
You can write code that’s easier to follow if you use a With block:
With openfiledlg
End With
Step 3: (Optionally) set a default path
You can make life easier by setting a value on the InitialDirectory property:
With openfiledlg
.InitialDirectory = "C:\Images"
End With
Step 4: Set the Filter property
So here’s the usually tricky bit. To start with a typical example:
.Filter = "Image Files (*.png *.jpg *.bmp) |*.png; *.jpg; *.bmp|All Files(*.*) |*.*"
Then, to break this down, first look at the sub string from Image Files to the first pipe (|) symbol:
.Filter = "Image Files (*.png *.jpg *.bmp)
This is what the user will see in the file type combo box at the bottom right corner of the dialog.
It’s traditional to show the user the file extensions of a given category – such as the three shown here – but it isn’t mandatory. You could just use the string ‘Image Files’ on its own, for instance.
The next part:
|*.png; *.jpg; *.bmp
tells the dialog what file types to filter in and allow to be displayed. In most cases you’ll use same file extensions as you used in the display. Note that you need to insert semi-colons between the file extensions to identify where one extension ends and the next one begins.
The last part of the Filter property code in this example simply adds a second choice of file type. This time, it’s the standard catch-all of the universal wild card:
|All Files(*.*) |*.*"
You can see this as the second choice in the file type combo box above.
Because there’s only one extension being used, there’s no need to include a semi-colon after the extension.
So, to summarize the syntax of the Filter property, it’s:
Step 5: (Optionally) Set a value on the FilterIndex property
If you have a long list of extensions and you want to encourage the user to home in on a particular one first, you can set the FilterIndex property to make one of the file type combo box items display first.
.FilterIndex = 3
Unusually, this value isn’t zero based, so you set it to 3, for example, to make the third item in the combo box the default selection.
Summary
And that’s all there is to it. I think it’s combination of multiple pipes and semi-colons that makes this task look trickier than it really is.