Chapter 13 (User Interface Design) Samples
Listing 13.1. Use of State Machine to Experiment with Two Different UI Layouts
#Const PLAYFIELD_ON_BOTTOM = 0 'Show PLAYFIELD below UI '#Const PLAYFIELD_ON_BOTTOM = 1 'Show PLAYFIELD above UI '------------------------------------------------------------- 'EVENT HANDLER: Called when form is loaded '------------------------------------------------------------- Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load 'Set the shared properties of our visual interface SetStartControlPositionAndState() 'Set the dynamic properties based on the state we're entering StateChangeForGameUI(GameUIState.startScreen) End Sub '------------------------------------------------------------- 'The state machine that drives showing hand hiding buttons '------------------------------------------------------------- Private Enum GameUIState startScreen = 1 waitForNextQuestion = 2 waitForUserToStateKnowledge = 4 waitForUserToAnswerMultipleChoice = 8 End Enum 'Current state of game Private m_GameUIState As GameUIState '============================================================ 'State machine used for driving the user interface '============================================================ Private Sub StateChangeForGameUI(ByVal newGameUIState As _ GameUIState) m_GameUIState = newGameUIState Select Case (newGameUIState) Case GameUIState.startScreen buttonAskQuestion.Visible = True buttonAskQuestion.Text = "Start" 'Hide the text box textBoxAskQuestion.Visible = False SetAnswerButtonVisibility(False) SetDifficultyButtonVisibility(False) Case GameUIState.waitForNextQuestion setQuestionText("List answer details here... " + vbCrLf + _ "Lots of space to write..." + vbCrLf + _ "Waiting for user to select next question...") textBoxAskQuestion.Visible = True buttonAskQuestion.Text = "Next" buttonAskQuestion.Visible = True 'Make sure the button is displayed on top buttonAskQuestion.BringToFront() SetAnswerButtonVisibility(False) SetDifficultyButtonVisibility(False) #If PLAYFIELD_ON_BOTTOM <> 0 Then 'PLAYFIELD is below UI textBoxAskQuestion.Height = pictureBoxGameBoard.Top - 2 #Else 'PLAYFIELD is above user controls textBoxAskQuestion.Top = pictureBoxGameBoard.Top + _ pictureBoxGameBoard.Height + 2 textBoxAskQuestion.Height = Me.Height - _ textBoxAskQuestion.Top #End If Case GameUIState.waitForUserToStateKnowledge SetTextForVocabularyQuestion() textBoxAskQuestion.Visible = True buttonAskQuestion.Visible = False SetAnswerButtonVisibility(False) SetDifficultyButtonVisibility(True) #If PLAYFIELD_ON_BOTTOM <> 0 Then 'PLAYFIELD is below UI textBoxAskQuestion.Height = _ buttonShowAnswers_AdvancedVersion.Top - 2 #Else 'PLAYFIELD is above user controls textBoxAskQuestion.Top = _ buttonShowAnswers_AdvancedVersion.Top + _ buttonShowAnswers_AdvancedVersion.Height + 2 textBoxAskQuestion.Height = Me.Height - _ textBoxAskQuestion.Top #End If Case GameUIState.waitForUserToAnswerMultipleChoice buttonAskQuestion.Visible = False SetDifficultyButtonVisibility(False) 'Enable the buttons so they can be clicked by the user SetAnswerButtonEnabled(True) SetAnswerButtonVisibility(True) #If PLAYFIELD_ON_BOTTOM <> 0 Then 'PLAYFIELD is below UI textBoxAskQuestion.Height = buttonAnswer0.Top - 2 #Else 'PLAYFIELD is above user controls 'Position the text box to make good use of the screen textBoxAskQuestion.Top = buttonAnswer5.Top + _ buttonAnswer5.Height + 2 textBoxAskQuestion.Height = Me.Height - _ textBoxAskQuestion.Top #End If End Select End Sub '============================================================= 'Sets up the shared layout of our user interface. 'These are all the items whose positions will remain fixed 'The user interface state machine will make changes to other 'properties '============================================================= Private Sub SetStartControlPositionAndState() pictureBoxGameBoard.Width = 240 pictureBoxGameBoard.Height = 176 'Set the size of the multiple-choice answer buttons Const answerButtons_dx As Integer = 117 Const answerButtons_dy As Integer = 18 buttonAnswer0.Width = answerButtons_dx buttonAnswer0.Height = answerButtons_dy buttonAnswer1.Size = buttonAnswer0.Size buttonAnswer2.Size = buttonAnswer0.Size buttonAnswer3.Size = buttonAnswer0.Size buttonAnswer4.Size = buttonAnswer0.Size buttonAnswer5.Size = buttonAnswer0.Size buttonShowAnswers_AdvancedVersion.Width = answerButtons_dx buttonShowAnswers_AdvancedVersion.Height = 24 buttonShowAnswers_SimpleVersion.Size = _ buttonShowAnswers_AdvancedVersion.Size 'Pixels between adjacent buttons Const dx_betweenButtons As Integer = 3 Const dy_betweenButtons As Integer = 2 Const answerbuttons_beginX As Integer = 3 'Make a background image for our bitmap, so we can see it 'in our testing Dim gameBoard As System.Drawing.Bitmap gameBoard = New System.Drawing.Bitmap( _ pictureBoxGameBoard.Width, pictureBoxGameBoard.Height) Dim gameboard_gfx As System.Drawing.Graphics gameboard_gfx = System.Drawing.Graphics.FromImage(gameBoard) gameboard_gfx.Clear(System.Drawing.Color.Yellow) Dim myPen As System.Drawing.Pen = New System.Drawing.Pen( _ System.Drawing.Color.Blue) gameboard_gfx.DrawRectangle(myPen, 2, 2, _ gameBoard.Width - 4, gameBoard.Height - 6) myPen.Dispose() gameboard_gfx.Dispose() pictureBoxGameBoard.Image = gameBoard 'Position the text box that contains the questions we ask 'as well as detailed answers to users textBoxAskQuestion.Left = 0 textBoxAskQuestion.Width = 240 buttonAskQuestion.Width = 64 buttonAskQuestion.Height = 20 #If PLAYFIELD_ON_BOTTOM <> 0 Then 'PLAYFIELD is below UI Const answerbuttons_beginY As Integer = 42 Const showanswers_beginY As Integer = 77 '--------------------------------------------- 'Set up the "Easy" or "Hard" option buttons for the game '--------------------------------------------- buttonShowAnswers_AdvancedVersion.Top = showanswers_beginY buttonShowAnswers_SimpleVersion.Top = showanswers_beginY '--------------------------------------------- 'Set up the multiple-choice answers '--------------------------------------------- 'Set the control that the others will line up based on buttonAnswer0.Top = answerbuttons_beginY 'Place Picture Box below the controls pictureBoxGameBoard.Top = _ (answerButtons_dy + dy_betweenButtons) * 3 + _ answerbuttons_beginY buttonAskQuestion.Top = 0 buttonAskQuestion.Left = 174 textBoxAskQuestion.Top = 0 #Else 'PLAYFIELD is above user controls Const answerbuttons_beginY As Integer = 174 '-------------------------------------------------------- 'Set up the "Easy" or "Hard" option buttons for the game '-------------------------------------------------------- buttonShowAnswers_AdvancedVersion.Top = answerbuttons_beginY buttonShowAnswers_SimpleVersion.Top = answerbuttons_beginY '--------------------------------------------- 'Set up the multiple-choice answers '--------------------------------------------- 'Set the control that the others will line up based on buttonAnswer0.Top = answerbuttons_beginY pictureBoxGameBoard.Top = 0 buttonAskQuestion.Top = answerbuttons_beginY buttonAskQuestion.Left = 174 #End If buttonShowAnswers_AdvancedVersion.Left = answerbuttons_beginX buttonShowAnswers_SimpleVersion.Left = _ buttonShowAnswers_AdvancedVersion.Left + _ answerButtons_dx + dx_betweenButtons pictureBoxGameBoard.Left = 0 pictureBoxGameBoard.Width = 240 pictureBoxGameBoard.Height = 172 buttonAnswer0.Left = answerbuttons_beginX buttonAnswer1.Left = buttonAnswer0.Left + answerButtons_dx + _ dx_betweenButtons buttonAnswer1.Top = buttonAnswer0.Top 'next row buttonAnswer2.Left = buttonAnswer0.Left buttonAnswer2.Top = buttonAnswer0.Top + answerButtons_dy + _ dy_betweenButtons buttonAnswer3.Left = buttonAnswer2.Left + answerButtons_dx + _ dx_betweenButtons buttonAnswer3.Top = buttonAnswer2.Top 'next row buttonAnswer4.Left = buttonAnswer2.Left buttonAnswer4.Top = buttonAnswer2.Top + answerButtons_dy + _ dy_betweenButtons buttonAnswer5.Left = buttonAnswer4.Left + answerButtons_dx + _ dx_betweenButtons buttonAnswer5.Top = buttonAnswer4.Top End Sub '------------------------------------------------------------- 'A helper function that enables us to set the visibility 'state of the buttons that show vocabulary answers '------------------------------------------------------------- Private Sub SetAnswerButtonVisibility(ByVal visibleState _ As Boolean) buttonAnswer0.Visible = visibleState buttonAnswer1.Visible = visibleState buttonAnswer2.Visible = visibleState buttonAnswer3.Visible = visibleState buttonAnswer4.Visible = visibleState buttonAnswer5.Visible = visibleState End Sub '------------------------------------------------------------- 'A helper function called to set the visibility state of some 'controls '------------------------------------------------------------- Private Sub SetDifficultyButtonVisibility(ByVal visibleState _ As Boolean) buttonShowAnswers_AdvancedVersion.Visible = visibleState buttonShowAnswers_SimpleVersion.Visible = visibleState End Sub '------------------------------------------------------------- 'A helper function that enables us to set the visibility 'of the buttons that show vocabulary answers '------------------------------------------------------------- Private Sub SetAnswerButtonEnabled(ByVal enabledState _ As Boolean) buttonAnswer0.Enabled = enabledState buttonAnswer1.Enabled = enabledState buttonAnswer2.Enabled = enabledState buttonAnswer3.Enabled = enabledState buttonAnswer4.Enabled = enabledState buttonAnswer5.Enabled = enabledState End Sub '------------------------------------------------------------- 'Sets the text in the text box and buttons necessary 'to ask a question. ' 'In a real implementation, this function would look up 'the vocabulary questions dynamically '------------------------------------------------------------- Private Sub SetTextForVocabularyQuestion() setQuestionText("What is the English word for 'der Mensch'?") buttonAnswer0.Text = "Four" buttonAnswer1.Text = "Person" buttonAnswer2.Text = "Three" buttonAnswer3.Text = "To Jump" buttonAnswer4.Text = "Newspaper" buttonAnswer5.Text = "Brother" End Sub 'Called to evaluate a user selected a multiple-choice answer Private Sub evaluateMultipleChoiceAnswer(ByVal buttonClicked _ As Button, ByVal selection As Integer) 'Note: In the non-prototype implementation, the correct 'answer would be a dynamic value, not always "button #1" 'If the user did not select the correct answer, disable 'the button pressed If (selection <> 1) Then 'The answer selected was not the correct one buttonClicked.Enabled = False Else 'User got the right answer, move on with the game StateChangeForGameUI(GameUIState.waitForNextQuestion) End If End Sub 'Abstracts setting the question text Sub setQuestionText(ByVal textIn As String) textBoxAskQuestion.Text = textIn End Sub '------------------------------------------------------------- 'EVENT HANDLER: User wants to see next question '------------------------------------------------------------- Private Sub buttonAskQuestion_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles buttonAskQuestion.Click SetTextForVocabularyQuestion() StateChangeForGameUI(GameUIState.waitForUserToStateKnowledge) End Sub '------------------------------------------------------------- 'EVENT HANDLER: 'User wants to answer the question displayed and what's 'the hardest list of options possible to challenge him/her '------------------------------------------------------------- Private Sub buttonShowAnswers_AdvancedVersion_Click( _ ByVal sender As Object, ByVal e As System.EventArgs) _ Handles buttonShowAnswers_AdvancedVersion.Click 'Set the state of the game to show the multiple-choice 'options StateChangeForGameUI( _ GameUIState.waitForUserToAnswerMultipleChoice) End Sub '------------------------------------------------------------- 'EVENT HANDLER: 'User wants to answer the question displayed and what's 'the simplest list of options possible to challenge him/her '------------------------------------------------------------- Private Sub buttonShowAnswers_SimpleVersion_Click( _ ByVal sender As Object, ByVal e As System.EventArgs) _ Handles buttonShowAnswers_SimpleVersion.Click 'Set the state of the game to show the multiple-choice 'options StateChangeForGameUI( _ GameUIState.waitForUserToAnswerMultipleChoice) End Sub 'EVENT HANDLER: A multiple-choice answer button was clicked Private Sub buttonAnswer0_Click(ByVal sender As Object, ByVal _ e As System.EventArgs) Handles buttonAnswer0.Click evaluateMultipleChoiceAnswer(buttonAnswer0, 0) End Sub 'EVENT HANDLER: A multiple-choice answer button was clicked Private Sub buttonAnswer1_Click(ByVal sender As Object, ByVal _ e As System.EventArgs) Handles buttonAnswer1.Click evaluateMultipleChoiceAnswer(buttonAnswer1, 1) End Sub 'EVENT HANDLER: A multiple-choice answer button was clicked Private Sub buttonAnswer2_Click(ByVal sender As Object, ByVal _ e As System.EventArgs) Handles buttonAnswer2.Click evaluateMultipleChoiceAnswer(buttonAnswer2, 2) End Sub 'EVENT HANDLER: A multiple-choice answer button was clicked Private Sub buttonAnswer3_Click(ByVal sender As Object, ByVal _ e As System.EventArgs) Handles buttonAnswer3.Click evaluateMultipleChoiceAnswer(buttonAnswer3, 3) End Sub 'EVENT HANDLER: A multiple-choice answer button was clicked Private Sub buttonAnswer4_Click(ByVal sender As Object, ByVal _ e As System.EventArgs) Handles buttonAnswer4.Click evaluateMultipleChoiceAnswer(buttonAnswer4, 4) End Sub 'EVENT HANDLER: A multiple-choice answer button was clicked Private Sub buttonAnswer5_Click(ByVal sender As Object, ByVal _ e As System.EventArgs) Handles buttonAnswer5.Click evaluateMultipleChoiceAnswer(buttonAnswer5, 5) End Sub
Listing 13.2. Dynamic Creation of Controls on a Form at Runtime
'------------------------------------------------------------- 'Counter for the number of button controls we create '------------------------------------------------------------- Private m_nextNewButtonIndex As Integer '------------------------------------------------------------- 'EVENT HANDLER: Click event handler for the button we have ' on our form. ' 'This function creates a new button, attaches it to our 'form and hooks up a "Click" event handler for it '------------------------------------------------------------- Private Sub buttonCreateNewButtons_Click(ByVal sender As _ System.Object, ByVal e As System.EventArgs) _ Handles buttonCreateNewButtons.Click 'Eventually we will start creating new buttons off the 'bottom of the screen, so lets stop at 8 If (m_nextNewButtonIndex > 8) Then Return End If '----------------------------------------------------- 'Create the button (not yet attached to our form) 'set its location, size, and text '----------------------------------------------------- Const newButtonHeight As Integer = 15 Dim newButton As System.Windows.Forms.Button newButton = New System.Windows.Forms.Button newButton.Width = 100 newButton.Height = newButtonHeight newButton.Left = 2 newButton.Top = (newButtonHeight + 2) * m_nextNewButtonIndex newButton.Text = "New Button " + _ m_nextNewButtonIndex.ToString() '----------------------------------------------------- 'Attach an event handler to the "Click" event of this 'control. '----------------------------------------------------- AddHandler newButton.Click, _ AddressOf Me.ClickHandlerForButtons '----------------------------------------------------- 'Attach this button to the form. This will actually 'create the button on the form! '----------------------------------------------------- newButton.Parent = Me 'Increment our counter for the next button we create m_nextNewButtonIndex = m_nextNewButtonIndex + 1 End Sub '--------------------------------------------------------- 'Event handler we will dynamically hook up to our new 'buttons '--------------------------------------------------------- Private Sub ClickHandlerForButtons(ByVal sender As Object, _ ByVal e As System.EventArgs) Dim buttonCausingEvent As Button = _ CType(sender, System.Windows.Forms.Button) 'Bring up a message box announcing that we have received 'the event MsgBox("Click event from:" + vbCrLf + buttonCausingEvent.Text) End Sub
Listing 13.3. A Filtering TextBox That Takes the Format ###-##-####
Option Strict On Imports System '-------------------------------------------------------------- 'This class is a control derived from the TextBox control. 'It uses all the drawing behavior of the TextBox, but adds 'a filter on the text box contents ensuring that only text 'that meets the format: ' ###-##-#### 'can be entered. This matches the format of Social Security 'numbers used in the United States. '-------------------------------------------------------------- Public Class SocialSecurityTextBox Inherits System.Windows.Forms.TextBox Private m_inputIsFullValidEntry As Boolean '------------------------------------------------------------- 'Indicates whether we have a full 'Social Security number '------------------------------------------------------------- Public ReadOnly Property IsFullValidInput() As Boolean Get Return m_inputIsFullValidEntry End Get End Property 'A string builder we will use often Private m_sb As System.Text.StringBuilder 'The maximum length of our processed string Const SSNumberLength As Integer = 11 '------------------------------------------------------------- 'Constructor '------------------------------------------------------------- Public Sub New() 'Allocate our string builder and give us a few extra 'characters of room to work in by default m_sb = New System.Text.StringBuilder(SSNumberLength + 5) m_inputIsFullValidEntry = False End Sub '------------------------------------------------------------- 'Format incoming text to make sure it is in the format: ' ' SS Format : ###-##-#### ' char index: 01234567890 ' ' (in) inString : Text we want to format ' (in/out) selectionStart: Current insert point in the text, ' this will get moved if it needs to ' based on appends or deletes we make '------------------------------------------------------------- Private Function formatText_NNN_NN_NNNN(ByVal inString As _ String, ByRef selectionStart As Integer) As String Const firstDashIndex As Integer = 3 Const secondDashIndex As Integer = 6 'Clear out the old data, and place the input string into 'the string builder so we can work on it. m_sb.Length = 0 m_sb.Append(inString) '--------------------------------------------------- 'Go through each character in the string up until 'we reach the maximum length of our formatted text '--------------------------------------------------- Dim currentCharIndex As Integer currentCharIndex = 0 While ((currentCharIndex < m_sb.Length) AndAlso _ (currentCharIndex < SSNumberLength)) Dim currentChar As Char currentChar = m_sb(currentCharIndex) If ((currentCharIndex = firstDashIndex) OrElse _ (currentCharIndex = secondDashIndex)) Then '------------------------------------------------------- 'The character needs to be a "-" '------------------------------------------------------- If (currentChar <> "-"c) Then 'Insert a dash m_sb.Insert(currentCharIndex, "-") 'If we added a character before the insert point 'advance the insert point If (currentCharIndex <= selectionStart) Then selectionStart = selectionStart + 1 End If End If 'This character is fine now, advance to the next char currentCharIndex = currentCharIndex + 1 Else '------------------------------------------------------- 'The character needs to be a digit '------------------------------------------------------- If (System.Char.IsDigit(currentChar) = False) Then 'Remove a character m_sb.Remove(currentCharIndex, 1) 'If we removed a character before the insert point 'retreat the insert point If (currentCharIndex < selectionStart) Then selectionStart = selectionStart - 1 End If 'Don't advance the char count, we need to look at 'the character that took the place of the one we 'have removed Else 'The character is a digit, all is well. currentCharIndex = currentCharIndex + 1 End If End If End While 'If we are over the length, truncate it If (m_sb.Length > SSNumberLength) Then m_sb.Length = SSNumberLength End If 'Return our new string Return m_sb.ToString() End Function Private m_in_OnChangeFunction As Boolean Protected Overrides Sub OnTextChanged(ByVal e As EventArgs) '---------------------------------------------------- 'If we change the .Text property, we will get called 're-entrantly. In this case we want to do nothing, and 'just exit the function without passing on the event 'to anyone else. '---------------------------------------------------- If (m_in_OnChangeFunction = True) Then Return End If 'Note that we are now in the OnChanged function 'so we can detect re-entrancy (see code above) m_in_OnChangeFunction = True 'Get the current .Text property Dim oldText As String = Me.Text 'Get the current SelectionStart Index Dim selectionStart As Integer = Me.SelectionStart 'Format the string so it meets our needs Dim newText As String = formatText_NNN_NN_NNNN(oldText, _ selectionStart) 'If the text differs from the original, update the '.Text property If (oldText <> newText) Then 'This will cause us to get called reentrantly Me.Text = newText 'Update the location of the insert point Me.SelectionStart = selectionStart End If 'Because we have just forced the text entry into the 'right format, if the length matches the length of 'the Social Security number we know that it is in 'the format ###-##-####. If (Me.Text.Length = SSNumberLength) Then 'Yes, we have a full Social Security number m_inputIsFullValidEntry = True Else 'No, we do note have a full Social Security number yet m_inputIsFullValidEntry = False End If 'Call our base class and let anyone who wants 'to know that the text has changed get called MyBase.OnTextChanged(e) 'Note that we are exiting our code now and want to turn 'off the re-entrancy check. m_in_OnChangeFunction = False End Sub Protected Overrides Sub OnKeyPress( _ ByVal e As System.Windows.Forms.KeyPressEventArgs) 'Because we know we don't want any letters in our input, _ 'just ingore them if we detect them. Dim keyPressed As Char = e.KeyChar If (System.Char.IsLetter(keyPressed)) Then 'Tell the system we have handled the event e.Handled = True Return End If 'Process the keypress as normal MyBase.OnKeyPress(e) End Sub End Class
Listing 13.4. Code in Form to Create the Custom TextBox Control
'----------------------------------------------------------- 'The variable to hold our new text box control '----------------------------------------------------------- Private m_filteredTextBox As SocialSecurityTextBox '----------------------------------------------------------- 'EVENT HANDLER: Create an instance of our custom control ' and place it onto the Form '----------------------------------------------------------- Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click 'Create, position, and host the control m_filteredTextBox = New SocialSecurityTextBox m_filteredTextBox.Bounds = _ New System.Drawing.Rectangle(2, 2, 160, 20) 'Hook up the event handler AddHandler m_filteredTextBox.TextChanged, _ AddressOf Me.textBox_TextChanged 'Set the parent m_filteredTextBox.Parent = Me 'Select the control m_filteredTextBox.Focus() 'Disable this button so a second SocialSecurityTextBox does 'not get created on top of this one Button1.Enabled = False End Sub '--------------------------------------------------------------- 'EVENT HANDLER: This gets dynamically hooked up when the control ' is created '--------------------------------------------------------------- Private Sub textBox_TextChanged(ByVal sender As Object, _ ByVal e As System.EventArgs) If (m_filteredTextBox.IsFullValidInput = True) Then label1.Text = "FULL SOCIAL SECURITY NUMBER!!!" Else Label1.Text = "Not full input yet..." End If End Sub
Listing 13.5. Code in Form to Demonstrate Use of Transparencies
'------------------------------------------------------- 'Dimensions for our bitmaps and the onscreen PictureBox '------------------------------------------------------- Const bitmap_dx As Integer = 200 Const bitmap_dy As Integer = 100 '------------------------------------------------------- 'Creates and draws the background image '------------------------------------------------------- Private m_backgroundBitmap As System.Drawing.Bitmap Sub CreateBackground() If (m_backgroundBitmap Is Nothing) Then m_backgroundBitmap = New Bitmap(bitmap_dx, bitmap_dy) End If 'Make the bitmap white Dim gfx As System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(m_backgroundBitmap) gfx.Clear(System.Drawing.Color.White) 'Draw a bunch of text in black Dim myBrush As System.Drawing.Brush myBrush = New System.Drawing.SolidBrush( _ System.Drawing.Color.Black) Dim y As Integer For y = 0 To bitmap_dy Step 15 gfx.DrawString("I am the BACKGROUND IMAGE...hello", _ Me.Font, myBrush, 0, y) Next 'Clean up myBrush.Dispose() gfx.Dispose() End Sub '------------------------------------------------------- 'Creates and draws the foreground image '------------------------------------------------------- Private m_foregroundBitmap As System.Drawing.Bitmap Sub CreateForeground() If (m_foregroundBitmap Is Nothing) Then m_foregroundBitmap = New Bitmap(bitmap_dx, bitmap_dy) End If 'Make the whole bitmap blue Dim gfx As System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(m_foregroundBitmap) gfx.Clear(System.Drawing.Color.Blue) 'Draw some shapes in yellow Dim yellowBrush As System.Drawing.Brush yellowBrush = New System.Drawing.SolidBrush( _ System.Drawing.Color.Yellow) gfx.FillEllipse(yellowBrush, 130, 4, 40, 70) gfx.FillRectangle(yellowBrush, 5, 20, 110, 30) gfx.FillEllipse(yellowBrush, 60, 75, 130, 20) 'Clean up yellowBrush.Dispose() gfx.Dispose() End Sub '------------------------------------------------------- 'Sets the size and left hand location of the PictureBox '------------------------------------------------------- Private Sub SetPictureBoxDimensions() PictureBox1.Width = bitmap_dx PictureBox1.Height = bitmap_dy PictureBox1.Left = 20 End Sub '-------------------------------------------------------------- 'EVENT HANDLER: Display the background image in the PictureBox '-------------------------------------------------------------- Private Sub buttonDrawBackground_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles buttonDrawBackground.Click SetPictureBoxDimensions() CreateBackground() PictureBox1.Image = m_backgroundBitmap End Sub '-------------------------------------------------------------- 'EVENT HANDLER: Display the foreground image in the PictureBox '-------------------------------------------------------------- Private Sub buttonDrawForeground_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles buttonDrawForeground.Click SetPictureBoxDimensions() CreateForeground() PictureBox1.Image = m_foregroundBitmap End Sub '-------------------------------------------------------------- 'EVENT HANDLER: Overlay the FOREGROUND image ON TOP OF the ' BACKGROUND image. Use a TRANSPARENCY MASK ' so that the color YELLOW in the FOREGROUND ' image becomes transparent and shows the ' contents of the BACKGROUND IMAGE '-------------------------------------------------------------- Private Sub buttonDrawBackgroundPlusForeground_Click(ByVal _ sender As Object, ByVal e As System.EventArgs) _ Handles buttonDrawBackgroundPlusForeground.Click SetPictureBoxDimensions() CreateForeground() CreateBackground() 'Get the grahics of the background image because that 'is what we are going to draw on top of. Dim gfx As System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(m_backgroundBitmap) '-------------------------------------------------------- 'Create an ImageAttributes class. This class enables us 'to set the TRANSPARANCY COLOR for our draw operation '-------------------------------------------------------- Dim trasparencyInfo As System.Drawing.Imaging.ImageAttributes trasparencyInfo = New System.Drawing.Imaging.ImageAttributes '-------------------------------------------------------- 'Set the transparency color '-------------------------------------------------------- trasparencyInfo.SetColorKey(System.Drawing.Color.Yellow, _ System.Drawing.Color.Yellow) 'Set our drawing rectangle Dim rect As System.Drawing.Rectangle = _ New System.Drawing.Rectangle(0, 0, _ m_backgroundBitmap.Width, _ m_backgroundBitmap.Height) '-------------------------------------------------------- 'Draw the FOREGROUND on top of the BACKGROUND bitmap and 'use the transparency color in the ImageAttributes to 'give us a transparent window onto the background '-------------------------------------------------------- gfx.DrawImage(m_foregroundBitmap, _ rect, _ 0, 0, _ m_foregroundBitmap.Width, _ m_foregroundBitmap.Height, _ System.Drawing.GraphicsUnit.Pixel, _ trasparencyInfo) 'Cleanup gfx.Dispose() 'Show the results in the bitmap PictureBox1.Image = m_backgroundBitmap End Sub
Listing 13.6. Code in Form to Demonstrate Loading of Embedded Resources
'-------------------------------------------------------- 'Load the image and display it in a PictureBox '-------------------------------------------------------- Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click LoadImageFromResource() PictureBox1.Image = m_myBitmapImage End Sub Private m_myBitmapImage As System.Drawing.Bitmap '------------------------------------------- 'Loads an image that is stored as a binary 'resource inside our assembly '------------------------------------------- Public Sub LoadImageFromResource() 'If we have already loaded the bitmap 'no point in doing it again. If Not (m_myBitmapImage Is Nothing) Then Return End If '---------------------------------------------------- 'Get a reference to our application's binary assembly '---------------------------------------------------- Dim thisAssembly As System.Reflection.Assembly = _ System.Reflection.Assembly.GetExecutingAssembly() '------------------------------------------- 'Get the name of the assembly '------------------------------------------- Dim thisAssemblyName As System.Reflection.AssemblyName = _ thisAssembly.GetName() Dim assemblyName As String = thisAssemblyName.Name '-------------------------------------------------------- 'Stream the image in from our assembly and create an 'in-memory bitmap ' 'Note: The ResourceStream name is CASE SENSITIVE ' be sure the image name matches EXACTLY with ' filename of the image file you add to the project '-------------------------------------------------------- m_myBitmapImage = New System.Drawing.Bitmap( _ thisAssembly.GetManifestResourceStream( _ assemblyName + ".MyImage.PNG")) End Sub
|