MCSD in a Nutshell: The Visual Basic Exams by James Foxall Unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. If you have technical questions or error reports, you can send them to booktech@oreilly.com. (Please specify the printing date of your copy.) This page was last updated March 31, 2003 Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification UNCONFIRMED errors and comments from readers: (xvi) 2nd paragraph, 4th sentence; Reads: "...when the questions on the text differ, ..." Should be: "...when the questions on the test differ, ..." Change "text" to "test" <2> The third paragraph states: The first exam I took was the Desktop exam, and I was surprised...at how many questions I encountered about packaging and deploying an application. It would seem that this is a topic for the Distributing exam... This observation seems to conflate the two definitions of "Distributing" an application (i.e., packaging components and creating an install set for deployment on one or more workstations or servers) and a "Distributed" application (i.e., an app architecture that is spread across multiple physical or logical tiers). The two usages of "distribute" here have totally different meanings and the two subjects areas are, in fact, quite distinct. The author might want to consider rewriting this paragraph in a future printing. (2) First item in table 1-1 under 70-176 (Desktop); "Access" should be changed to "Assess" as in the 70-175 column. {14} Figure 2-3: Given the example code preceeding the graphic of the form in Figure 2-3, the graphic is wrong. The column headers will not have any text in them (i.e., "Column 1", "Column 2", and "Column 3" will not appear in the form). The column headers will be blank. If you want the text to appear in the column headers, you must put the text in the ListView1.ColumnHeaders.Add(x,,"Column1") line of code. {16} 1st paragraph, 1st sentence; Reads: "...two different properties (LargeIcons and SmallIcons)." Should be: "...two different properties (Icons and SmallIcons)." There is no "LargeIcons" property. "Icons" is used for large icons. [23] list after 7th para; Extension for activeX document is .VBDs, not DLLs or EXEs. (25) First paragraph under Encapsulation heading; The phrase "the objects are comprised both of their code and..." should be reworded to "the objects comprise both their code and..." (34) Item 3 in the list; "Invoke" should be in constant width font. [54] skills assessment, question 2; The answer is "0", see page 36. I tested it as on pages 44 and 55. {59} Step 17; I used the Excel 9.0 object library, but I don't think that is a factor in this. The paragraph above titled "Releasing the Excel object" indicates that we are going to close Excel, not just the workbook. The statement in step 17 merely closes the workbook, and not the Excel application. To close the application, add another line like this: objExcel.Quit {67} Last paragraph; Book says: "To access the Project Properties dialog box shown in Figure 4-2, choose Project Properties from the Tools menu." Should be: "... from the Project menu." {69} 2nd para, headed :Giving your project a description; Text states that the project description is used in the References dialogue (for client binding)....this is not the case, the Project Name is always used. <70> Under Version Compatibility, there is an incorrect reference to Chapter 11. Version compatibility is covered in Chapter 13. (75) First paragraph; "Subs and" should be added to the first sentence, so that it reads: "... methods are publicly exposed subs and functions" [80] Last pp; The point of the Implements functionality in VB is polymorphism. The book misses this point entirly. The two fridges example should contain 3 classes: iFridge, StandardFridge, and DeluxeFridge. It should also contain a form. The form should have the line in the declarations section: Dim objFridge As iFridge and a button to toggle between Set objFridge = New StandardFridge and Set objFridge = New DeluxeFridge The point is that objFridge can be Early-Bound to either Class because both StandardFridge and DeluxeFridge contain the statement Implements iFridge [83] code at top of page; The code sample that you have at the top of the page doesn't do any delegation. You must add the method calls to the body of the overridden methods like you do the second code segment. The code at the top should call the new properties, or contain the body of the new properties and be called by the new properties. Example Private property get StandardFridge_Doors() as byte standardFridge_Doors = objsFridge.doors '* or StandardFridge_Doors = doors end property public property get Doors as byte doors = StandardFridge_Doors '* or Doors = objSfridge.doors end property {88-89} After last line on 88 OR Before first line on 89; The line of code: Call NotifyClients is missing. It should be between the line: Call PerformSomeAction() at the bottom of p. 88 and End Property at the top of p. 89 (90) I think the "Key points" heading should refer to callbacks and events, since most of the text that follows is a comparison between the two. {97} In Figure 4-11, change Object 4 in thread 2 to Object 2 and remove the circled D in the upper right corner. (108) The bullets about error handling should appear before the bullets about callbacks (going by the order covered in the chapter). {110} Question 5; The answer for question 5 is listed as c only. Answer a is also syntactically correct for a private method. If the definition of method in this book is public only (per 1st sentence on page 75), then the latter discussion of Friend procedures on page 75 needs to be amended since it talks about private properties AND methods. {117} Exercise 4.3, 1st para.; The last sentence states that the exercise "...will demonstrate how an error is raised at the calling statement in the parent class." This is not the case, the error is raised in the form class i.e. in the procedure at the top of the calling stack. This is because there are no error handlers in subsequent procedures lower down the stack including the parent class. [152] note at top of page; In the October 2000 edition, the text says of the SelectedControls collection that "you reference only index 0... Element 0 references all of the selected controls. No other index values are used at this time." This is not true. Take these steps to demonstrate that SelectedControls behaves like every other collection: 1. Create an ActiveX control with a Text property. 2. Add a PropertyPage that configures the Text property. 3. Add this code to the PropertyPage_ApplyChanges event procedure: Dim i As Long For i = 0 To SelectedControls.Count - 1 SelectedControls(i).Text = txtText.Text Next 4. In a Standard EXE test project, place four instances of the ActiveX control on a form. 5. Right-click on one instance and select Properties on the context menu. 6. With the Property Pages dialog still open, hold down CTRL and select the other three instances. (Foxall does not mention that a bug in VB causes the Property Pages dialog not to appear if the application developer first selects multiple controls.) 7. Enter a value for the Text property and click Apply or OK. 8. Observe that the Text property is changed on each instance of the control, demonstrating that the loop has addressed all four instances using values 0 through 3 for the index of the SelectedControls collection. I suspect that Foxall was misled by the fact that you always reference a single selected control using the syntax SelectedControls(0). However, the claim "Element 0 references all of the selected controls" should have set off alarm bells because it violates the fundamental behavior of a collection. Exactly HOW does Foxall imagine that a collection could reference each of its elements using a single index? [159] "On the Exams" note; In the October 2000 edition, the text claims: "You do not use a Call statement to invoke the ReadProperty method, but Call is required when using the WriteProperty method. You may be asked to demonstrate this understanding on the exam." There are two mistakes in this note. First, it is tautological to say that the ReadProperty method does not require the Call keyword. The method returns a value, just like a Function procedure. You only use the Call keyword to invoke a statement that does not return a value. Second, it is not true that the WriteProperty method requires the Call keyword. The Call keyword exists solely for backward compatibility with ancient BASIC; it is never required in any circumstance. I suspect that Foxall was misled by the behavior of the ActiveX Control Interface Wizard, coupled with the syntax difference between using or not using the Call keyword. The wizard spits a UserControl_WriteProperties event procedure such as the one shown in the screenshot on page 158. The Call keyword begins each line. It is true that if you run the wizard and then simply delete the Call keyword, you receive a syntax error message. However, the error is not that you left out the Call keyword; it is that you left in the parentheses surrounding the argument list. When you use the Call keyword to invoke a method, you must enclose its argument list in parentheses. When you simply invoke a method, you must not enclose its argument list in parentheses. This code is legal: Call PropBag.WriteProperty("Text", txtText, "") This code is also legal: PropBag.WriteProperty "Text", txtText, "" This code is not legal: PropBag.WriteProperty("Text", txtText, "") (160) First Owl; At the top of page 160, Foxall mentions that UserControl.PropertyChanged is a method, but in the "Owl", he says This statement could be entered as UserControl.PropertyChanged = "Value", but the reference to UserControl isn't necessary. This is the syntax of a property modification statement, not a method call. The correct syntax is: PropertyChanged "Value". or UserControl.PropertyChanged "Value", or Call UserControl.PropertyChanged("Value") but NOT UserControl.PropertyChanged = "Value" {162} figure 5-24; The code in the figure skips the last item of the array. You've confused the use of UBound() with an array and a count property on a collection. Ubound() returns the upper bound of the array, not the total number of items in the array, so subtracting one from the return value of this method will always ignore the last value in the array. {171} The first line on the page now reads: ' This code goes in the ReadProperties event. It should read: ' This code goes in the AmbientChanged event. {175} In Figure 5-26, "RunMode property" should read "UserMode property". (179) 4th paragraph; On the 4 th paragraph , the 4th and the 6th lines the words product category should be read as proerty category {180} 2nd Paragraph; In relation to October 2000 printing (although a review of changes made in the next printing does not indicate that the mistake has been rectified in subsequent printings.) In order for a property to be the default property at run time, so that the property can be accessed by using the object name without specifying a property, the (default) value needs to be selected in the Procedure ID list. The text states that you just need to check the "User Interface Default" checkbox. The following article describes the difference between Default Procedure ID and User Interface Default: http://support.microsoft.com/directory/article.asp?ID=KB;EN-US;Q193022& (191) 2nd bullet point; Third word, "method" should be "event." See p. 129 under the heading "Using the Paint Event to Create Owner-Draw Controls" which r eads, "The Paint event of the UserControl is the obvious place to put the code to draw the UserControl's interface." [191] 10th bullet down; On 10th bullet, page 191, text states: "Because container controls require add itional resources, you should only set a UserControl's ContainedControls prope rty to True if it is appropriate for the control." I submit that "ContainedControls property" should read "ControlContainer prope rty" by virtue of page 132, last paragraph, third sentence which states: "You should set a UserControl's ControlContainer property to True only if it is app ropriate for the control." I checked my Visual Basic 6 documentation, and only the ControlContainer prope rty can be set to True or False. The ContainedControls property returns a col lection of controls and cannot be set. [193] In the 2nd bullet, change Initialize to InitProperties (see p. 156). (202) question 49; question 49 should read: Which property returns a reference to the container on which a control is sited? (203) question 57; Question 57 reads: One bound property, and only one, must have which property set? The wording of this question doesn't agree with point 8 on page 195. {213} Section 4, Testing the Data-Bound control: I get a Type Mismatch Error when running Exercise 5-2: Creating a data-bound control. I can't find where the error is occuring so I assume it is occuring somewhere within the Data Control itself. I seemed to have followed the instructions in the book step by step. I set breakpoints to trap errors but no luck. If you find out, please let me know. Thanks! BTW, I'm running Windows NT VB 6.0 SP4. {213} Section 4. Testing the Data-Bound Control; In testing this control, I also got a Type Mismatch Error as did a previous submitter. After much investigation between the downloaded example that works and my example that didn't, I discovered that the following line in the .ctl source file needs to be in a particular place. Attribute Text.VB_MemberFlags = "3c" Of course the question is: where does this come from and how do I get it where it needs to be? This is the representation of the Procedure Attributes check boxes in the Data Binding Section. It is written to the first procedure of the property when the control is saved. It actually needs to be in the Property Get procedure which needs to be before the Property Let procedure in the source file. The manner in which my control was created (following the book) placed it last, therefore putting the above line in the Property Let procedure. The simple fix is to select Full Module View and move the Property Get procedure above the Property Let Procedure. To James Foxall's credit, I could not find any information about this in the help system. There was also no way to find it contexturally. As stated previously, breakpoints were of no help. Hopefully this will save a future headache or two. {218} In the 2nd tip, change "OLE control" to "OLE Container control." [220] In the sample code at the bottom of the page, swap the contents of the If and Else clauses, or put Not after If. [152] The note at the top of the page indicates that the SelectedControls collection reference zero (0) will reference ALL of the controls and no other index values are used as this time. Reading through MSDN (as of Oct 2000), it states that the zero reference (0) will refer to only the FIRST control selection. To make changes to all controls, you must cycle through each control. Which of these is correct? [210] Very top; The top of pg 210 is a continuation of 209: If SelectedControls(0).Value Then lbValue.ListIndex = 0 Else lbValue.ListIndex = 1 End If At the end of pg 209, there is other code that is placed the SelectionChanged event. It is implied that the code above is to be placed there too. Doing this causes VB to go into a continuous loop. I downloaded the this example and it looks like this code should be placed in the Apply Changes event instead [247] Question 3; The question located on page 247 is this: What benefits does an ActiveX document have over an embedded object? (pick two) a. You can control the scrolling behavior of an ActiveX document b. ActiveX documents do not expose your source code c. An ActiveX document can control some aspects of its container. d. ActiveX documents do not require a server application The answer (located on page 251)states a & c. Although the "a" answer is well documented, I do not follow "c". Especially since on page 219, the last sentence clearly states it doesnt expose source code. In addition, I found no material explicitly stating a container could be controlled with an ActiveX document. However, there is at least one negation aspect towards controlling the container (p. 228 in italicized letters). Wouldn't options "a & b" be the correct choice? [245] The 8th bullet now reads: Viewport properties always return values in twips, regardless of the ScaleMode of the UserDocument. It should read: Viewport properties always return values in the ScaleMode of the UserDocument. See the tip on p. 228, which is correct. [251] The correct answer for #15 is c. See change on pg. 245 above. {261} 2nd Paragraph from the bottom: ...using the References dialog box accessed by choosing References from the Tools menu... This advice works for VBA inside of Access, Word or Excel. It does not work for Visual Basic 6.0. In VB 6, References are found on the Project Menu. [269] The arguments on the bold line of the sample code need a second comma: ("Authors", , adcmdTable) adcmdTable must be the 3rd argument. [283] 3rd paragraph below Figure 7-6: You write: "...and to use a command you use its Commands collection. For example, to use a connection named BiblioConnection and manipulate a recordset created with a command named AllAuthors, you code use code such as this:...With DataEnvironment1.Recordsets("AllAuthors")...." This is confusing. You say to use the _Commands_ collection and then the code demonstrates the use of the _Recordsets_ collection. Data Environments have both a Commands collection and a Recordsets collection. Which one are you supposed to use? Please consider adding a sentence or two to clarify this. {290} Question 13; The question asks: "Which of the following is a valid way to execute a SQL statement?" The syntax implies that you have a SQL statement to execute, which you could do with answer b. D, on the other hand, GENERATES an internal SQL statement. ?291, 293? Is "d" also a correct answer for question 21? (292) Question 26: The question reads: "A transaction has been _initiated_ using CommitTrans...." Change to: "A transaction has been initiated using BeginTrans...." {294} Section 2. Creating a recordset using a Command object.; The description states that we'll use the Command object's Open method to create a recordset. The example code uses the Execute method since the Command object has no Open method. [327] 3rd Paragraph; The MCSD Exam objective from Microsoft (http://www.microsoft.com/traincert/exams/70- 175.asp) or (http://www.microsoft.com/traincert/exams/70-176.asp) has no objective related to Winsock Control- Why have you included this in your book on MCSD? Where is the bdpro.hlp on this site? Pg 440 suggests that it should be found on this site? ?336? Point #8: Point 8 reads: The user's application could be designed to send data back to the central application. To do this, the RemoteHost and RemotePort properties of the user's application would need to be set to the IP address and LocalPort properties of the central application, and the central application would also need to be place in listen mode. My question is: does the client's application also need to bind to it's local port before the SendData method is invoked? [353] Question No.5: The answer to No.5 should be C (GoForward, GoBack) and not A (NavigateForward, NavigateBack) for methods used to navigate history list of a WebBrowser control. {359} answers to Skills Assessment: Question 5 asked, "Which two methods are used to navigate the history of a WebBrowser control?" The book subsequently states that the answer is "a. NavigateForward, NavigateBack," although the correct answer is "c. GoForward, GoBack." {359} The "Changes made in the 1/01 reprint" page indicates that the answer for Question 11 was changed from "a" to "c." However, in the text of the chapter (page 315), the text says that a new instance of Internet Explorer is by default invisible. Therefore, shouldn't the answer to question 11 remain "a" as originally printed? {359} Top, first question on page. Question 43.; Question 43 reads:

Queen takes Rook, check.

First, there are two bold end tags, but no matching bold open tags. Shouldn't the first "" be a "", or is this a trick question? Secondly, when you use the InnerText property, the tags surrounding the replaced text are not affected. Therefore, provided the first bold tag above should be a "", shouldn't the answer to the question be letter "b". The book states the answer is letter "a", but the bold tags should not have been replaced. {359} Answers to Skills Assessment - Question 5; Which two methods are used to navigate the history list of a WebBrowser Control? a. NavigateForward, NavigateBack b. MoveForward, MoveBack c. GoForward, GoBack d. GoHome The correct answer is C, not A (as show in the answer key on p.359) [366] In step 9, remove the line "strDir = vData" before Do While and remove "strDir = strDir & vData" after the loop. The one after the loop does not hurt anything as vData will be zero length, but the 1st one causes the same data to be added twice. (366) Step 11 would be a great place to show the new Split function: Private Sub FillDirList(strDir As String) Dim vArray As Variant Dim vParse As Variant vArray = Split(strDir, vbCrLf) For Each vParse In vArray lstFiles.AddItem CStr(vParse) Next End Sub [372] Step 21: The syntax is wrong. There is a missing double quoted string in the second line. It should be: MainParagraph.innerHTML = "Advice is often worth what you " & _ "pay for it." instead of: MainParagraph.innerHTML = "Advice is often worth what you " & _ pay for it." {397} Change "#Const CompileIn = -1" to "#Const m_CompileIn = -1" to match the code and text below. [423] In the code sample, change the path to: App.Path & "\MyHelp.chm" to match the statement in the tip that follows. (Remove \Help so it actually is in the same folder as the application.) {427} 2nd Paragraph; The second sentance reads "The form's BorderStyle must be set to 1-fixed single or 2-sizable." The borderstyle 3-Fixed Dialog will work with the whatsthisbutton. [430] The tip correctly relates to cdlHelpContents while the text (1 place) and sample code (1 place) below use cdlHelpSetContents. They should all be changed to cdlHelpContents. {435} In the 7th bullet, change "Context ID property" to "HelpContextID property." [435] In the 8th bullet, change the 2nd sentence to something like: If the value is 0, the HelpContextID of the controls container is checked. This continues until a nonzero HelpContextID is found. [435] In the 8th bullet, the author incorrectly states that when pressing F1, if the active control's HelpContextID = 0, the HelpContextID of the Form is next examined. What should be stated is that if the active control's HelpContextID = 0, the HelpContextID of the active control's container is next examined. {436} In the 5th bullet, change "ContextID property" to "HelpContext property." [440] Exercise 10-1: I cannot find bdpro.hlp from http://vb.oreilly.com. I need the file to finish the exercise. [note: you can find that file at http://examples.oreilly.com/mcsdnut/] [462] Question 13: d is listed as correct answer, but it looks like it should have read "Favor Pentium Pro(tm)" vs. "Remove Safe for Pentium FDIV Checks". (481) 6th bullet from the bottom: Should this read as follows: A Server package is a package that runs on its own (vs. on) MTS process. {485} Q.10: I believe that the answer should be D. MTS refreshes packages but not individual components, a fact that may confirmed by researching MSDN (or pages 465 and 475-476). [487] The correct answer for #22 is b. See p. 478 or MSDN. [498] The section "Using the [Bootstrap] and [Bootstrap Files] sections of the Setup.lst file" now reads: The [Bootstrap] section contains all of the files that must be loaded on the user's computer before your application and all of its dependency files can be loaded... The [Bootstrap Files] section contains the specific information for each file that must be installed for the setup program and Visual Basic 6 runtime. The following is from the MSDN Library for VB6: - The Package and Deployment Wizard - Manually editing a Setup.lst File: The BootStrap Files section lists all the files that must be loaded on the user's machine before your application and dependency files can be loaded. These pre-install, or bootstrap, files include the core files required to run any Visual Basic application, such as the Visual Basic run-time DLL (Msvbvm60.dll). The setup program installs these files prior to installing and launching the main installation program. This seems to be conflicting information... ?498? The install argument shown in the template at the bottom of 498 and in Table 13-3 does not occur in the sample file at the top of 498. This is also true in MSDN. Remove install argument? [542] The 4th line of the big code block now reads: If avntSettings = Empty Then Exit Sub It should read: If IsEmpty(avntSettings) Then {543} The 2nd paragraph now reads: If you want to delete all of the keys under a specific section... It should read: If you want to delete an entire section... (The section as well as all keys under it are deleted by the example.) {543} Before "Key Facts" a new section should be added to discuss working with self-registering .exe files, introducing MyCom.Exe /UnRegserver. Look it up in MSDN; it is needed. [545] In the 1st bullet, change [Bootstrap] to [Bootstrap Files]. [545] The 6th bullet is very wrong. See p. 513: "Essentially, any file that is not installed as a system file (not installed into $(WinSysPathSysFile)) can be marked as shared." (545) last bullet: Starting on page 545 and continuing you refer to the Package and Deployment Wizard as the Setup Wizard. The Setup Wizard was retired (see p. 503) and replaced by the Package and Deployment Wizard. Perhaps "Setup Wizard" will continue as shorthand for the P & D Wizard, but since the tests make use of standard MS terms, your bullets should too. [548] In question 8, foil b should be [Bootstrap Files]. [549] Question 11 needs to be redone or removed. See error in 6th bullet on page 545 above. (549) Question 13; The text should read "A licensed control" rather than just "Licensed control". [552] answer to Question 2: The answer to Question 2 is b, not c. [552] answer to Question 10: The correct answer to question 10 is d, None of the Above. You did not include a disucussion of the Setup Wizard, therefore the correct answer cannot be c - Setup Wizard. A correct answer would be "Package and Deployment Wizard," but that was not an option. Therefore d, None of the Above, is correct. Consider replacing all references to the Setup Wizard with references to the Package and Deployment Wizard. (552) answer to Question 14: This question isn't clear. In theory, a developer could distribute the control, but it wouldn't work. Thus the answer could be true.