Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 72 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
72
Dung lượng
299,41 KB
Nội dung
034 31240-9 APP F 4/27/00 1:13 PM Page 701 Using MFC’s Helper Classes 701 One of the most useful aspects of these array classes is their capability to grow dynamically Normal C/C++ arrays are predefined in size and can be extended only by lots of messy reallocations of memory The collection classes hide these reallocations so that you can simply call the Add() member of an array object to add a new value For example, to add strings to a CStringArray, you can use code similar to this: CStringArray myStringArray; myStringArray.Add(“Red”); myStringArray.Add(“Green”); myStringArray.Add(“Blue”); You can then find the size of an array by calling the GetSize() function; for example, the following line used after the previous lines would return three items into nNumberOfItems: int nNumberOfItems = myStringArray.GetSize(); You can also set the array to a specific size using the corresponding SetSize() function, which will extend or truncate the array to the specified size you pass Values can be set to the array by using the SetAt() function that passes a zero-based index and the value to be stored SetAt() will assert whether the index is larger than the current array size You can then retrieve values from the array using the GetAt() function, which will return the value at the index position that you specify You might use these functions with a CWordArray like this: CWordArray myWordArray; myWordArray.SetSize(20); myWordArray.SetAt(0,200); myWordArray.SetAt(19,500); TRACE(“Value at index position 19 is %d\n”, myWordArray.GetAt(19)); These lines will set the first element of a 20-element array to 200 and the last to 500 and display the value 500 when executed You can still grow the array by calling the Add() function and find the uppermost valid index by calling GetUpperBound(), which will return the zero-based index, or –1 if there are no elements present You can use the [ ] operators to set and get values at a specific index just like a normal C++ array For example, the GetAt() and SetAt() functions in the previous lines could be replaced with the [ ] operators like this: myWordArray[0] = 200; myWordArray[19] = 500; TRACE(“Value at index position 19 is %d\n”, myWordArray.GetAt[19]); F 034 31240-9 APP F 4/27/00 1:13 PM Page 702 702 Appendix F Using the InsertAt() and RemoveAt() functions, you can insert or remove items at a specific position, which results in all the items shifting up or down by one or more elements The InsertAt() function has two forms; the first needs an index position and an element to insert there You can also optionally pass it a count to insert multiple copies of the specified element The second form lets you insert another whole array at a specified index position The RemoveAt() function needs only one parameter to specify the index value of the item to be removed, but you can also optionally pass a count as the second parameter to remove a number of elements The remaining array elements will then be shifted down to fill the gap You can remove all the elements of an array by calling the RemoveAll() function MANAGING MEMORY WITH CObArray AND CPtrArray You must be careful to delete objects that you have allocated with new and stored in a CObArray or CPtrArray because these arrays only hold pointers to the elements (not elements themselves) Therefore, a RemoveAll() call will only remove the pointers to the objects and not free the memory used by the objects themselves Using the List Classes There are only three categories of lists as shown in Table F.2 and a template for your own types (discussed later) There is seldom any need to have a list of simple integer values Instead, you would probably need a linked list of your own CObject-derived classes or pointers to a number of C++ classes or structures TABLE F.2 THE LIST-BASED COLLECTION CLASSES Class Name Type of Variable Held CObList CObject—Pointers CPtrList void*—Pointers CStringList CString—Text to any CObject-derived objects to memory addresses holding any type of data strings Linked lists are several objects linked to each other in a sequential fashion like carriages on a train There is a definite head and tail position, but every other element knows only its immediate neighbor A POSITION variable keeps track of a current position in a list You can declare multiple POSITION variables to track different places in the same list 034 31240-9 APP F 4/27/00 1:13 PM Page 703 Using MFC’s Helper Classes 703 Each list’s member functions then use a POSITION variable to find the head, tail, or next and previous elements in the list You can add elements to a list by calling the AddHead() or AddTail() functions or by inserting items into a specific position using the InsertBefore() or InsertAfter() functions Each function then returns a POSITION value to indicate the position of the new added item For example, you can construct a four-element list of CString items like this: CStringList listMyStrings; POSITION pos; pos = listMyStrings.AddHead(“Hand”); listMyStrings.AddTail(“Forearm”); listMyStrings.InsertBefore(pos,”Fingers”); listMyStrings.AddTail(“Elbow”); These lines will produce a linked list of CString strings from head to tail like this: Fingers-Hand-Forearm-Elbow You can also pass other similar list objects to the AddHead() and AddTail() functions to add another list to the head or tail of the current list When you’ve constructed a list, you can iterate through its members using a POSITION variable The head or tail positions can be found by calling GetHeadPosition() or GetTailPosition(), respectively These functions both return a POSITION value indicating the current position in the list You can then pass the POSITION variable as a reference to GetNext() or GetPrev() to find the next or previous element in the list These functions then return the specific object and adjust the current position When the end of the list is reached, the POSITION variable will be set to NULL For example, the following lines will iterate through the previous listMyStrings, displaying each element in turn: POSITION posCurrent = listMyStrings.GetHeadPosition(); while(posCurrent) TRACE(“%s\n”, listMyStrings.GetNext(posCurrent); You can find specific list elements by using the Find() function, which returns a POSITION value if the search parameter you pass is found You can also optionally pass a position value, from which you can start the search For example, you can search for the string Fingers in the previous list by calling the Find() function like this: POSITION posFingers = Find(“Fingers”); If the searched-for element isn’t found, a NULL value will be returned F 034 31240-9 APP F 4/27/00 1:13 PM Page 704 704 Appendix F There is also a FindIndex() function that will find the nth element from the head of the list (where n is the passed parameter) You can find out how many elements are in the list by calling the GetCount() member function, which returns the number of elements and doesn’t need any parameters The value of elements at a specific position can be retrieved or reset by using the GetAt() and SetAt() functions, which are used in a similar way to their array equivalents, but by passing a POSITION value rather than an array index You can remove elements from the list by using the RemoveAt() function and passing the POSITION value to identify the element to be removed For example, to remove the Fingers item from the previous example, you might code the following: RemoveAt(posFingers); Using the Map Classes The map classes work by associating a type value (or element) with a key value that can be used to look up the element The various map classes, and their key values and associated element types, are shown in Table F.3 TABLE F.3 THE MAP-BASED COLLECTION CLASSES Class Name Key Type Element Type CMapWordToOb WORD—16-bit unsigned value CObject— CObject-derived objects CMapWordToPtr WORD—16-bit unsigned value void*— Pointers to memory CMapPtrToPtr void*—Pointers to memory void*— CMapPtrToWord CMapStringToOb Pointers to memory void*—Pointers to memory WORD—16-bit CString—Text CObject— strings unsigned value CObject-derived objects CMapStringToPtr CString—Text void*— strings Pointers to memory 034 31240-9 APP F 4/27/00 1:13 PM Page 705 Using MFC’s Helper Classes Class Name Element Type CString—Text CString—Text strings CMapStringToString Key Type 705 strings You can insert elements into a map by using the SetAt() function and passing a key value as the first parameter and your element value as the second For example, if you must store your own CObject-derived objects indexed by a string value, you can use the CMapStringToOb class and add elements like this: CMapStringToOb mapPlanetDetails; mapPlanetDetails.SetAt(“Mercury”,new CPlanetDets ➥(4878, 0.054, 57.91, 87.969)); mapPlanetDetails.SetAt(“Venus”,new CPlanetDets ➥(12100, 0.815, 108.21, 224.701)); mapPlanetDetails.SetAt(“Earth”,new CPlanetDets ➥(12756, 1.000, 149.60, 365.256)); In the previous example, CPlanetDets is a CObject-derived class with a constructor that takes four planetary detail parameters The new objects are then associated with the planet names as keys You can also use the [ ] operator overload instead of SetAt() by enclosing the key value inside the square brackets like this: mapPlanetDetails[“Mars”] = new CPlanetDets ➥(6762, 0.107, 227.94, 686.98); After you have set data to a map, you can retrieve it by calling the Lookup() member function by passing the key value and a reference to a variable to hold the associated element value if found If the element isn’t found, a FALSE value is returned from Lookup() For example, to retrieve details about a planet from the previous example, you can use these lines: CPlanetDets* pMyPlanet = NULL; if (mapPlanetDetails.Lookup(“Earth”,(CObject*&)pMyPlanet)) TRACE(“Sidereal Period = %d days\n”, pMyPlanet->m_dSidereal); The (CObject*&) cast is used to cast the pMyPlanet object pointer to a generic CObject pointer reference The GetCount() function will return the number of elements current in the map These elements can be removed by calling the RemoveKey() function and passing the key of the element to be removed like this: mapPlanetDetails.RemoveKey(“Jupiter”); F 034 31240-9 APP F 706 4/27/00 1:13 PM Page 706 Appendix F Remember to delete the allocated objects RemoveKey() just removes the pointer to the object—not the object itself—so it won’t free up the used memory You can also remove all the elements by calling RemoveAll() You can iterate through the list of associations using the GetNextAssoc() function, which needs parameters that reference a current POSITION holding variable, a key variable, and an element variable You can find the position of the first element by calling GetFirstPosition(), which returns the POSITION value for the first element To iterate through the associations, you might code the following: POSITION pos = mapPlanetDetails.GetStartPosition(); while(pos!=NULL) { CString strPlanet; CPlanet* pMyPlanet; mapPlanetDetails.GetNextAssoc(pos,strPlanet, (CObject*&)pMyPlanet); TRACE(“%s has a diameter of %d km\n”,strPlanet, pMyPlanet->m_dDiameter); } When GetNextAssoc() returns, pos will hold the position for the next association or NULL if there are no more The key and element values (strPlanet and pMyPlanet in the previous example) will be set to each key-element pair in turn Because of a map’s capability to retrieve sparse data quickly and efficiently, it is often advantageous to use a map as a memory cache for a slow database lookup For example, in the following lines, the planet details associated with strPlanetName are required When first called, this code won’t have a mapped version of the required planet, so it will have to call GetPlanetFromSlowDB() to find it Because it then stores the retrieved planet in the mapPlanetDetails map, when it is next called with the same strPlanetName, the details can be quickly returned from the cached version in memory: CPlanetDets* pMyPlanet = NULL; if (mapPlanetDetails.Lookup(strPlanetName, ➥(CObject*&)pMyPlanet) == FALSE) { pMyPlanet = GetPlanetFromSlowDB(strPlanetName); mapPlanetDetails.SetAt(strPlanetName,pMyPlanet); } return pMyPlanet; This technique is easy to implement and can transform your application’s speed when you are using slow retrieval devices such as databases or files 034 31240-9 APP F 4/27/00 1:13 PM Page 707 Using MFC’s Helper Classes 707 Creating Custom Collection Classes You might want to customize the collection classes to use your own objects rather than the generic CObject-derived classes Customization offers several benefits because you can make an array, list, or map that will accept and return only your specific type of object If you accidentally try to add the wrong sort of object to a customized array, list, or map, the compiler will issue an error message to notify you The other advantage is that you don’t have to cast generic CObject* pointers (that is, from a CObArray) back to your specific object to use it This sort of customization is known as type-safety; in large programs it can be invaluable for stopping accidental assignments of the wrong class A set of templates, CArray, Clist, and CMap, lets you easily create an array, list, or map to store, use, and return objects of your specified type only Templates are a complex subject, but you don’t have to worry about writing templates; the MFC-provided templates defined in the afxtempl.h header file will for these type-safe collection classes For the scope of this section, it is best to think of templates as large macros that generate lots of code based on your parameters when compiled The templates will give you access to all the normal functions in the array, list, or map classes discussed in the previous sections However, instead of using generic CObjectbased parameters and returned values, you can define your own types as parameters and return values To use the templates in your program, you’ll need to include the following header line in each module (.cpp/.h file) that uses the template definitions: #include “afxtempl.h” You can then define your own custom type-safe class using the template syntax like this for an array of custom objects: CArray myCustomClassArray; The < and > symbols used in the definition should be thought of as angle brackets (not greater-than or less-than conditional operators) The previous line uses the CArray template to create an instance of myCustomClassArray The first CMyCustomClass* parameter specifies types of object pointers you want the array to return when you use GetAt() and other access functions The second CMyCustomClass* specifies the type that should be used for the input parameter definitions Then all the functions that store objects, such as SetAt() and Add(), will accept only pointers to objects of your specific CMyCustomClass F 034 31240-9 APP F 4/27/00 1:13 PM Page 708 708 Appendix F For example, you can create an array that takes and returns only pointers to the specific CPlanetDets class, defined (and implemented) like this: class CPlanetDets : public CObject { public: CPlanetDets(double dDiameter,double dGravity, ➥double dDistFromSun,double dSidereal): m_dDiameter(dDiameter), m_dGravity(dGravity), m_dDistFromSun(dDistFromSun), m_dSidereal(dSidereal) {} double m_dDiameter,m_dGravity,m_dDistFromSun,m_dSidereal; }; To declare a type-safe CArray-based array called myPlanetArray, you can then code the following line: CArray myPlanetArray; This declares that myPlanetArray can only accept pointers to a CPlanetDets object and return pointers to a CPlanetDets object You might then use the new array like this: myPlanetArray.Add(new CPlanetDets ➥(4878, 0.054, 57.91, 87.969)); myPlanetArray.Add(new CPlanetDets ➥(12100, 0.815, 108.21, 224.701)); myPlanetArray.Add(new CPlanetDets ➥(12756, 1.000, 149.60, 365.256)); for(int i=0;im_dDiameter); These lines create three new CPlanetDets type objects and add them to the array The last line displays the diameter in the TRACE macro without needing to cast the returned value from myPlanetArray[i] because it’s already a pointer of the CPlanetDets* type However, later you might forget the exact nature of myPlanetArray and try to add a CStatic object instead: myPlanetArray.Add(new CStatic()); Fortunately, the compiler will spot the transgression and issue a compiler error such as ‘Add’ : cannot convert parameter from ‘class ➥CStatic *’ to ‘class CPlanetDets * However, the error wouldn’t have been spotted if you had been using a CObArray to hold the planet details: CObArray myPlanetArray; 034 31240-9 APP F 4/27/00 1:13 PM Page 709 Using MFC’s Helper Classes 709 The CStatic object would be happily stored along with the CPlanetDets objects, causing untold havoc when you try to retrieve the CStatic object, thinking it’s a CPlanetDets object The template used to generate type-safe lists is CList; it takes the same general form as CArray: CList myCustomClassList; Again, the first parameter is the required returned object type, and the second parameter specifies the accepted object types for functions that accept elements for storage All the functions available for lists are available for your own specific type-safe customized lists, again checking and returning your specified types Therefore, the equivalent list-based code for the planet storing array would be coded like this: CList myPlanetList; myPlanetList.AddTail(new CPlanetDets ➥(4878, 0.054, 57.91, 87.969)); myPlanetList.AddTail(new CPlanetDets ➥(12100, 0.815, 108.21, 224.701)); myPlanetList.AddTail(new CPlanetDets ➥(12756, 1.000, 149.60, 365.256)); POSITION pos = myPlanetList.GetHeadPosition(); while(pos) TRACE(“Diameter = %f\n”,myPlanetList ➥GetNext(pos)->m_dDiameter); The template for customized maps differs from the list and arrays in that it needs four parameters: an input and a return value for both the key and element value So the general form is like this: CMap myCustomClassMap; The first parameter, MyType, specifies the internally stored key value for each map association This can be any of the basic types such as int, WORD, DWORD, double, float, or CString, or it can be a pointer to your own specific type The second parameter, MyArgType, specifies the argument type used to pass key values in and out of the map functions The third parameter, CMyCustomClass *, is how you want the internal element values to be stored (as specific type-safe pointers to your objects) The fourth parameter, CMyCustomClassArg *, specifies the argument type used to pass your element values in and out of the map functions For example, to associate the planet details with their names, you might code the following: F 034 31240-9 APP F 4/27/00 710 1:13 PM Page 710 Appendix F CMap myPlanetMap; myPlanetMap.SetAt(“Mercury”, new CPlanetDets(4878, 0.054, 57.91, 87.969)); myPlanetMap.SetAt(“Venus”, new CPlanetDets(12100, 0.815, 108.21, 224.701)); myPlanetMap.SetAt(“Earth”, new CPlanetDets(12756, 1.000, 149.60, 365.256)); CPlanetDets* pPlanet = NULL; if (myPlanetMap.Lookup(“Venus”,pPlanet)) TRACE(“Diameter = %f\n”,pPlanet->m_dDiameter); The map declaration indicates that the objects should be stored internally as CStrings but use LPCSTR (pointers to constant character arrays) to pass values into and out of the map The planet’s details themselves will be both stored internally and accessed as pointers to CPlanetDets objects (such as CPlanetDets*) POTENTIAL PROBLEMS WHEN USING THE MAP’S INTERNAL HASH KEY TYPES You must be wary of the conversion between the passed parameters and the internal hash key storage system For example, if you were to replace the CString in the previous example with another LPCSTR for the internal storage object, the Lookup() would fail to find “Venus” because it would be comparing the pointer values (to different instances of “Venus”) rather than the contents of the strings Using the Coordinate-Handling Classes Because Windows is a graphically oriented environment, you’ll often need to hold point positions, rectangles, and sizes Three MFC classes help store and manipulate these coordinates: CPoint, CRect, and CSize Each has several member functions and operator overloads that take much of the work out of adding, constructing, and finding derivatives of these coordinates Also several of the MFC and GDI functions understand their types or underlying types as parameter values, so you don’t have to perform any messy mangling operations to pass them into functions Using the CPoint Class encapsulates a POINT structure that just holds an x and y position to represent a point on a two-dimensional surface You can always access x and y members directly to get or set their current values like this: CPoint 035 31240-9 index 4/27/00 758 1:13 PM Page 758 ModArtDll application ModArtDll application MFC DLL CModArt class declaration, 411 NewLine function, 411-416 project file, 410 testing, 413-414 regular DLL, 416 header file, 417 ModArtClearDrawing function, 421-422 ModArtDraw function, 421 ModArtNewDrawing function, 418 ModArtSerialize function, 421 module definition file, 422 NewLine function, 419-420 project file, 417 testing, 423-426 ModArtDraw function, 421 ModArtInit function, 428 ModArtNewDrawing function, 427 modeless dialog windows, 92 see also dialog windows modifier keys (Web Browser application), 532 mouse events handling OnMouseDownMsfgrid function, 194 OnMouseUpMsfgrid function, 195 SDI application, 209-211 messages, 48 Mouse drawing program application shell, 49 OnLButtonDown function, 56 OnMouseMove function, 49-50, 54-55 tracking mouse coordinates, 53-55 Move function, 319 MoveFirst function, 319, 372 MoveLast function, 319 MoveNext function, 319 MovePrev function, 319 moving toolbars, 10 Multiple Document Interface, see MDI applications multiplication operator (*), 549 multitasking, 430 arrays, 433 clean-up procedures, 466-468 idle processing threads, 431 building, 457-459 continuous tasks, 459 OnIdle function, 455 starting, 456 stopping, 456 independent threads, 431, 460 creating, 432 main thread function, 461 priorities, 432-433 stack size, 433 starting, 462-463 stopping, 462-463 suspended mode, 433 trigging from view object, 463-464 thread synchronization, 434-435 critical sections, 436 events, 439-440 mutexes, 436-438 semaphores, 438-439 mutexes, 436-438 m_ prefix, 33 m_ofn property (CFileDialog class), 102 N \n string, 247 naming conventions constructors, 564 menus, 119 toolbars, 247 variables global, 554 local, 554 m_ prefix, 33 Navigate function, 524 navigating recordsets ADO, 352-353 GetCurRecord function, 298 GetFirstRecord function, 299 GetLastRecord function, 301 GetNextRecord function, 299 GetPrevRecord function, 300 MoveFirst function, 372 ODBC, 319-320 OnBfirst function, 307 OnBlast function, 308 OnDataFirst function, 371 the Web, 523-524 nCharSet argument (CreateFont function), 127-128 nClipPrecision argument (CreateFont function), 128 035 31240-9 index 4/27/00 1:14 PM Page 759 OnBeginPrinting function nEscapement argument (CreateFont function), 126 nested classes, 566-569 networks, 496-497 debugging across, 685 Internet applications, 519 protocols, 497 sockets, 497 closing connections, 503, 517-519 controls, 505-508 creating, 498-500 error handling, 504 event handling, 503-504 listening for messages, 501 opening connections, 500-501, 511-514 ports, 498 receiving messages, 502-503, 516-517 sending messages, 502, 515-516 socket class, 509-511 new keyword, 666 NewDataSet function, 310 NewDrawing function, 398, 480 library module, 389 regular DLL, 418 NewLine function, 399-401, 480 library module, 386-388 MFC DLL, 411-416 regular DLL, 419-420 NEWTEXTMETRICEX structure, 124 nHeight argument (CreateFont function), 126 NOINTEGRALHEIGHT combo box style, 264 nOrientation argument (CreateFont function), 126 NORMAL thread priority, 432 NormalizeRect function, 717 nOutPrecision argument (CreateFont function), 128 nPitchAndFamily argument (CreateFont function), 129 nQuality argument (CreateFont function), 128 NULL-terminated strings, 726 NumberSquiggles property (Squiggle control), 483 nWeight argument (CreateFont function), 126-127 nWidth argument (CreateFont function), 126 O object IDs (controls), 44-45 Object Linking and Embedding (OLE), 180 debugging objects, 684 exceptions, 673-674 see also ActiveX controls object-oriented design encapsulation, 380 inheritance, 380-381 Car class example, 572-576 Human class example, 569-572 objects adding to classes, 708-709 ADO, see ADO containers, 700-702 positioning, 450-452 ODBC (Open Database Connectivity), 316-317 Administrator, 322 data source configuration, 322-323 759 database connections, 317 exceptions, 672-673 records adding, 331-334 deleting, 334-335 recordsets closing, 319 editing, 320-321 navigating, 319-320 opening, 317-318 sample application application shell, 324-325 CDbOdbcSet constructor, 331 control properties, 325-327 control variables, 328 Database field variables, 329 DoDataExchange function, 330 record management, 331-335 ODBC Microsoft Access Setup dialog box, 323 OEMCONVERT combo box style, 264 Offset function, 712 OLE (Object Linking and Embedding), 180 debugging objects, 684 exceptions, 673-674 see also ActiveX controls OLE/COM Object Viewer tool, 697 OnAccept function, 504, 510, 513 OnBbitmap function, 173-174 OnBclose function, 518 OnBconnect function, 512 OnBcustomdialog function, 98-99 OnBeginPrinting function, 655 035 31240-9 index 4/27/00 760 1:14 PM Page 760 OnBfirst function OnBfirst function, 307 OnBlast function, 308 OnBsend function, 515-516 OnBwhichoption function, 99 OnCbemployed function, 309, 312 OnCbonidle function, 456 OnCbthread1 function, 464 OnCbthread2 function, 465 OnChangeEsamptext function, 136 OnChangeInterval function, 75 OnClick function, 487 OnClose function, 504, 517-518 OnClrmsg function, 38-39 OnConnect function, 504, 513 OnContextMenu function, 117, 238-239 OnCreate function, 248-249, 265-266 OnDataFirst function, 371 OnDestroy function, 467 OnDocumentComplete function, 529 OnDraw function, 397, 426, 638-641 compared to OnPrint, 642 CSquiggleCtrl class, 486 SDI application, 212 OnEndPrinting function, 655 OnExit function, 36 OnFileopen function, 91, 103 OnGoBack function, 531 OnGoNext function, 531 OnHello function, 19, 114 OnHelpAbout function, 114-115 OnIdle function, 431, 457-460 OnInitDialog function, 34-35, 511 ActiveX application, 192-193 clock timer, 71-72 counting timer, 76 drawing program, 60-61 Fonts application, 133-135 Graphics application, 161-162 OnKeyDown function, 57-58, 61-62 OnLButtonDown function, 56 OnMouseDownMsfgrid function, 194 OnMouseMove function, 49-50, 54-55 OnMouseUpMsfgrid function, 195 OnNewAddress function, 527 OnNewDocument function, 303, 366, 395, 424, 469 SDI application, 221 Spinner application, 454-455 OnOK function, 36 OnOpenDocument function, 304 OnPaint function, 167, 171-172, 176, 714 OnPreparePrinting function, 648 OnPrint function, 638 compared to OnDraw, 642 overriding, 641-643 OnReceive function, 504, 516 OnRecordDelete function, 334 OnRecordNew function, 333 OnRSelection function, 164 OnRType function, 508 OnRunpgm function, 42-43 OnSelchangeLfonts function, 138 OnSelChangeWidth function, 267 OnSend function, 504 OnSetCursor function, 62-63 OnShwmsg function, 37-38 OnStarttime function, 76-77 OnStoptimer function, 77 OnTimer function clock timer, 73 counting timer, 77-79 OnUpdateIndicatorColor function, 273-274 OnUpdateViewColorbar function, 255 OnViewColorbar function, 256 OnViewRefresh function, 534 OnViewStop function, 533 OnYesnocancel functions, 88-89 ON_COMMAND_RANGE message map, 236 Open Database Connectivity, see ODBC Open function, 318 OPENFILENAME structure, 102 opening database connections, 350-351 databases, 351-352 documents OnNewDocument function, 303-304 OnOpenDocument function, 304-305 recordsets, 317-318 socket connections, 500-501, 511-514 operators address-of (&), 554-555 assignment (=), 549 binary AND (&), 51-52 attribute flags, 52-53 OR (|), 52 extraction operator (>>), 548 035 31240-9 index 4/27/00 1:14 PM Page 761 print jobs indirection (*), 554-556 logical, 550 AND (&&), 51 OR (||), 52 mathematical, 549 overloads, 711-712 COleDateTime class, 722 CRect class, 716 CSize class, 718 redirection (