|
Visual Basic 2005 Cookbook(c) Solutions for VB 2005 Programmers Authors: Patrick T., Craig J. Published year: 2006 Pages: 247-248/400 |
Recipe 10.17. Getting Display DimensionsProblemYou want to determine the dimensions of the user 's screen at runtime, including both the entire screen and just the working area that doesn't include the task bar. Also, you want to determine the number of monitors on the user's system, the screen dimensions of each, and which screen is currently active. SolutionSample code folder: Chapter 10\ScreenInfo Access this information from the Screen object, which includes an array of objects, one for each screen on the system. DiscussionThe following code extracts information from each Screen object returned by the Screen.AllScreens property, then formats the various data items returned for easy review:
Dim result As New System.Text.StringBuilder
Dim scanScreen As Screen
' ----- Include some summary data.
result.Append("Number of screens: ")
result.AppendLine(Screen.AllScreens.Length.ToString)
result.AppendLine( )
' ----- Process each installed screen.
For Each scanScreen In Screen.AllScreens
result.AppendLine("Device Name: " & _
GetTerminatedString(scanScreen.DeviceName))
result.AppendLine("Bounds: " & _
scanScreen.Bounds.ToString)
result.AppendLine("Working Area: " & _
scanScreen.WorkingArea.ToString)
result.AppendLine("Is Primary: " & _
scanScreen.Primary.ToString)
result.AppendLine( )
Next scanScreen
MsgBox(result.ToString( ))
The device name returned by the scanScreen.DeviceName property may include an old C-style terminating null character (ASCII 0), so you must to add a custom function to extract just the part you need: Private Function GetTerminatedString( _ ByVal sourceString As String) As String ' ----- Return all text of a string up to the first ' null character. Dim index As Integer index = sourceString.IndexOf(vbNullChar) If (index > -1) Then Return sourceString.Substring(0, index) Else Return sourceString End If End Function As shown in Figure 10-25, the system used for testing this code had only one monitor, with a screen resolution of 1680 x 1050 pixels and a working area of 1680 x 990 pixels (the working area is slightly smaller because the task bar was showing along the bottom edge of the screen). Figure 10-25. The Screen.AllScreens array provides information about any monitors on your system
|
Recipe 10.18. Speeding Up Image ProcessingProblemYou want to implement some image-processing algorithms, and you want the operations to be reasonably fast. SolutionSample code folder: Chapter 10\LockImage Use the InteropServices.Marshal.LockBits() method to prevent the operating system from moving the bitmap data around in memory. This greatly speeds up the program's access to the pixel data. This recipe presents a LockImage class that wraps the LockBits() functionality for easy use. DiscussionThe LockImage class presented in this recipe and the remaining recipes in this chapter contains several image-processing methods . (The full LockImage class is listed in Recipe 10.21.) The goal is to provide enough examples to enable you to design your own image-processing functionality. The processing function demonstrated in this recipe is Mirror() , a method of the LockImage class that flips an image left and right. To see how it works, create a form with a PictureBox on it that has its Dock property set to Fill and its SizeMode property set to StretchImage . Load a picture into its Image property, and add the following code to its Click event: Private Sub PictureBox1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles PictureBox1.Click ' ----- Mirror-image the bitmap. Dim mirrorIt As New LockImage mirrorIt.Image = PictureBox1.Image mirrorIt.Mirror( ) PictureBox1.Image = mirrorIt.Image End Sub When you click on the picture, this procedure creates an instance of the LockImage class, copies the PictureBox 's image to it, calls the Mirror() method to process the image, and then copies the image back into the PictureBox . This is the pattern for using any of the processing methods of the LockImage class. Now let's look at the portions of the LockImage class that relate to the mirroring processs. First, you must import the requisite namespaces. InteropServices.Marshal is required for its LockBits() method. The class defines a few class-level variables : Imports System.Drawing.Imaging Imports System.Runtime.InteropServices.Marshal Public Class LockImage Private BaseImage As Bitmap Private BaseImageWidth As Integer Private BaseImageHeight As Integer Private TotalPixels As Integer Private ImageAddress As IntPtr Private ImageContent As BitmapData Private ImageBuffer( ) As Integer The Image property stores or retrieves the bitmap image to be locked and processed : Public Property Image( ) As Bitmap ' ----- User access to the relevant image. Get Return BaseImage End Get Set(ByVal Value As Bitmap) Dim canvas As Graphics BaseImage = New Bitmap(Value.Width, _ Value.Height, Value.PixelFormat) canvas = Graphics.FromImage(BaseImage) canvas.DrawImage(Value, 0, 0, _ Value.Width, Value.Height) canvas.Dispose( ) End Set End Property The LockTheImage() method provides the important core functionality of this class; with it, you can lock down the bits of the bitmap and present the pixel data in an integer array for efficient processing. All pixel processing in the methods you create, such as the Mirror() method presented later, will process in place the integer pixel data stored in ImageBuffer() . Each 32-bit integer in ImageBuffer() represents a single pixel. The most significant byte is alpha, the opacity value. The next most significant byte is for red, then green, and the least significant byte is for blue. Each of these four values ranges from to 255 . Two other variables of importance for your image-processing methods are BaseImageWidth and BaseImageHeight . The ImageBuffer() array is one-dimensional, so these two values are required to determine the rectangular layout of the pixels: Private Sub LockTheImage( ) ' ----- Lock the image in memory. How much room ' do we need? BaseImageWidth = BaseImage.Width BaseImageHeight = BaseImage.Height TotalPixels = BaseImageWidth * BaseImageHeight ' ----- Create a stable (locked) area in memory. It ' will store 32-bit color images. ReDim ImageBuffer(TotalPixels - 1) ImageContent = BaseImage.LockBits( _ New Rectangle(0, 0, BaseImageWidth, _ BaseImageHeight), ImageLockMode.ReadWrite, _ PixelFormat.Format32bppRgb) ImageAddress = ImageContent.Scan0 ' ----- Associate the buffer and the locked memory. Copy(ImageAddress, ImageBuffer, 0, TotalPixels) End Sub The Mirror() method works by locating the first and last pixels of each row of the image, then swapping the pixels at those locations. The next and previous pixels in the row are swapped next, and this continues until all pixels in the row have been swapped. Here is the code for the Mirror() method: Public Sub Mirror( ) ' ----- Make a left-to-right mirror image. Dim pixelIndex1 As Integer Dim pixelIndex2 As Integer Dim holdPixel As Integer Dim down As Integer ' ----- Lock the image for speed. LockTheImage( ) ' ----- Process each row of the image. For down = 0 To BaseImageHeight - 1 ' ----- Process each column, up to halfway across. pixelIndex1 = down * BaseImageWidth pixelIndex2 = pixelIndex1 + BaseImageWidth - 1 Do While pixelIndex1 < pixelIndex2 ' ----- Swap two pixels. holdPixel = ImageBuffer(pixelIndex1) ImageBuffer(pixelIndex1) = _ ImageBuffer(pixelIndex2) ImageBuffer(pixelIndex2) = holdPixel pixelIndex1 += 1 pixelIndex2 -= 1 Loop Next down ' ----- Finished. Unlock the image. UnlockTheImage( ) End Sub The UnlockTheImage( ) method restores the processed pixel data in ImageBuffer( ) to the bitmap, ready to be retrieved by the code that uses the class: Private Sub UnlockTheImage( ) ' ----- Unlock the memory area. Copy(ImageBuffer, 0, ImageAddress, TotalPixels) Image.UnlockBits(ImageContent) ImageContent = Nothing ReDim ImageBuffer(0) End Sub Figure 10-26 shows a sample picture just before being flipped ; Figure 10-27 shows the picture immediately afterwards. Figure 10-26. An image about to be flipped horizontally
See AlsoRecipe 10.21 includes the full source code for the LockImage class. Figure 10-27. The same image after the Mirror( ) method has worked its magic
|
|
Visual Basic 2005 Cookbook(c) Solutions for VB 2005 Programmers Authors: Patrick T., Craig J. Published year: 2006 Pages: 247-248/400 |