Page xvi
in order to find the corresponding IUnknown, BSTR, and SAFEARRAY, and VARIANT data types
You can useUse these programming techniques to enhance your everyday coding productivity by minimizingmaximizing code reuse
Page xx
CoRegisterClassObject and CoGetClassObject APIs to offerproffer your own application-level singleton objects
Page xxi
enabling a host of Win32 API calls from with VB, AddressOf also enables
Page xxiii
if you try to interact with windows at the level of creation and window procedures.
Page 5
string conversion issues (see Chapter 14), weI recommend that you use
Page 6
'Equivalent to Long12 = Long21
Page 7
Dim String1 As String
Dim String2 As String
Dim pString1 As Long
String1 = "PowerVB"
String2 = String$(7, 0)
'These four operations all do the same thing
'Try one: this requires a typelib CopyMemory declare
CopyMemory ByVal String2, ByVal String1, 14
'Try two: Use StrPtr to guarantee no ANSI/UNICODE munging
CopyMemory ByVal StrPtr(String2), _
ByVal StrPtr(String1), 14
'Try three: Get the string's pointer from VarPtr
CopyMemory pString1, ByVal VarPtr(String1), 4
CopyMemory ByVal String2, ByVal pString1, 14
'Try four: Demonstrate VBoost.Assign instead
VBoost.Assign pString1, ByVal VarPtr(String1)
CopyMemory ByVal String2, ByVal pString1, 14
Page 9
This file registers with the name "VBoost Object Implementation (6.0)."
Page 16
appropriate descriptor to enable you to access array elements
Page 20
'Output (Intel uses biglittle-endian integer layout)
Page 21
.fFeatures = FADF_AUTO Or FADF_STATIC Or _
FADF_FIXEDSIZE
Page 23
Put your array in a structure and add a termination code to using lightweight objects.
The first blocksuses a lock count on the array
Page 39
You can also calculate the element countsize by using the formula VBoost.UDif(VarPtr(elem(1)), VarPtr(elem(0))).
SafeArrays use a rowcolumn-major layout, unlike C++, which uses a columnrow-major layout.
Page 40
SafeArrayCreate takes an array of SafeArrayBound elements in rowcolumn-major (VB) order, but the descriptor itself stores the list in reverse order, which is really columnrow-major (C++) order.
Page 42
In other words, VB makes your objects a persistable class, ActiveX control
Page 43
Second, if a reference supports an IID, the same IID must be supported by all references that the object returns.
The controlling IUnknown object then maps
Page 44
RHLS=LHS means that the type of the left-hand variable
Page 47
The QI that comes after the function call seems really bizarre because happens after the function returns. If the QI fails, then you will get a type mismatch error in the caller after the function has completed successfully. If the extra QI isn't enough to scare you away from such calls, the amount of code generated in order to handle them should be. In the case of ByVal calls, the AddRef/Release call happens in the callee, so there is no extra IUnknown work to be done by the caller. However, inIn the case of ByRef calls, the entire IUnknown burden falls on the caller, so theextra type checking code is generated everywhere the function is called with a mismatched type.
Page 51
Function GetDispatch(ByVal pUnkUR As IUnknownUnrestricted) _As
As Object
Page 54
The first member of any COM object is a pointer to the vtable
Page 55
IDispatch uses an ID based system, where each function
Page 58
Remember that using a With statement against an object is equivalent to assigning the object to a local variable.
Page 60
See the November 19991998 Visual Basic Programmer's Journal for the article "Inspect Dynamic Objects."
Page 64
section of Chapter 3,using a QueryInterface for IDispatch can have
lose a key feature ParamArray feature: the ability to pass a ByRef vVariant.
Page 67
registered it with regsvr32. (Or run Setup on the book's CD.)
Page 70
you can access the native function's event prototypes directly
Page 71
the type library the UDTs are contained in is the OCA back on
Page 81
By breaking this procedure in two, suddenly the code suddenly becomes reusable.
Page 85
By simply pointing a variable in each class to the same data, we you can eliminate the notification
Page 91
With delegation code that runs against any vtable entry, we you can use the same vtable
Page 92
An IUnknown hook is very similar to a blind delegator, but an IUnknown hook modifies
Page 94 (sidebar)
VBoost releases the datareference and returns the E_NOINTERFACE error.
Page 95 (sidebar)
You may want to toggle in the C++ version of the DLLVBoost objects during debugging
Page 97
so the earliest you can aggregate the object is in the Class_Initialize.
AggregateData is defined in VBoostTypes6.TlbOlb and has four members
this object is treated as a blind aggregate; a: A QI call is forwarded
Page 98
The native interfaces supported by Class2 are not wrapped, and the _Class1 interface supported by _Class1 is wrapped with a blind delegator that makes it act like a native part of Class12.
Page 99
with the DrawImpl class and adds a native method, or Area, that calculates the area
Page 105
There are no circular references in this system, but there are a couple big
Page 111
'long value
VBoost.AssignSwap pObj, Obj
.ItemData(.NewIndex) = pObj
End With
Page 116
Friend Property Get ChildInternal( _ByVal Index As Long) As
ByVal Index As Long) As Child Child
Set Child = InternalChildChildInternal(Index).GetExternalChild
Page 120
but the first instance in whichof each specific class of object you create a specific class of object.
Page 122
most-common values hidden in VBoostTypesObjCreate.
Page 126
adding capabilities to thea main application
dependent DLLs starting with the DLL's directory, not in the directory
Page 132
a reference to ObjCreate.oOlb and include the OcxLoader.Bas, COMDllLoader.Bas, and FunctionDelegator.Bas files.
'OcxLoader.Bas
Page 133
'fTargetAbsolute: An optional flag indicating that the
' TargetOCX argument is an absolute, not a
' relative path.
'not have run, so the VBoost object hasmay not have been
'been created.
Set pCF = GetDllClassObject( _App.Path & "\" &
App.Path & "\" & TargetOcx, _
Page 135
HookData.pIIDs(0) = IIDFromString( _
strIIDI__IQuickActivate)
VBoost.AggregateUnknown _
Wrapper, HookData.AggData, _HookData.pIIDs,
HookData.pIIDs, LoadData.Hook
Page 137
If you havewant the form to support menus
The DynamicMDI sample also has sample code (contained in LookupCLSID.Bas) that registers a public context object (discussed in "Custom Class Objects" in this chapter) and code that determines a CLSID from an OCX or DLL based on a class name (contained in LookupCLSID.Bas).
Page 138
Once your project includes have a direct type-library reference
Page 139
publish the CLSID with which you registered instead.
Page 145
When you need a block of memory to create thean object, you call the heap's allocate function.
Page 154
If m_PrevCursor <> vbHourGlass Then
With Screen
'Don't touch if someone else changed it.
If MousePointer = vbHourGlass Then
Page 156
without turning the structure into a full-blown VB class.
Page 157
.pVTablem_pVTable = VarPtr(.VTable(0))
Page 158
StringFromGUID2 pguid, StrPtr(GuidString)
Page 164
the code in the calling function is approximately one-third the size of code for the non-HRESULT functions.
Page 174
If you specify adUseIIDs as one of the AggregateData flags, VBoost doesn't query
Page 184
ByVal Index As Integer) As Linked Point
Page 188 (occurs three times)
X As Single, Y As Single)
Page 189
(and the AutoRedraw solution doesn't go very far towards demonstrating lightweight objects.)).
Page 190 (occurs three times)
X As Single, Y As Single)
Page 205
you can only guarantee that you gotget the same item back
Page 207
that you can call from the immediate paneby calling. ClearROT calls HideObject on all
Page 209
Dim strGuid As String * 38
StringForromGUID2 _
Getting a reference to the object out of the ROT just became
Page 211
Errors in Figure 10.1: External Process should point to Mashaling Layer and ROT should point to ROTHook Object
hold strong references to the ROTHook objects, but the only
Page 231
Sample: DLLDllRegisterServer
Page 232
[uuid(8F633501-459A-11d3-AB5C-D4123C10000), odl]
Once you have a function pointer--pfnDllRegisterServer--you can callpass the pointer to InitDelegator (pfnDllRegisterServer) and assign
Page 235
I have rarely seenrarely see a sort routine written in straight VB that didn'tdoesn't make me cringe. Sort routines, regardless of the algorithm used, compare and swap
the elements in an array. Comparing elements in VB is straightforward, but itstraight VB requires a new sort routine for each type of array to be sorted. Having a new
routine for each data type wasn'tisn't quite enough to evoke a shudder; the shudder generally requires an examination of the swapping code. Although
swapping elements may seem straightforward, it iscan be extremely expensive for pointerString, Variant, and structure types because VB always performs a deep copy.
Page 239
QuickSort VarPtr(Strings(LBound(Strings)), _
UBound(Strings) - LBound(Strings) + 1, _
4, AddressOf CompareStrings
Page 242
'Assembly code we're using to make aread the stack pointer.
Page 244
stack pointerframe before prolog (ebp points here)
Page 246
VB cannot handle the misaligned stack and Y crashes.
Page 247
However, with the FunctionDelegator object, you can now come very close.
get away with writing C code and letting the C compiler generate assembly.
Page 250
displays an addressof 00401033
Page 252
Public Function InIDE() As Boolean
Debug.Assert Not TestIDE(InIDE)On Error Resume Next
End Function Debug.Assert 1 \ 0
Private Function TestIDE(Test As Boolean) As Boolean InIDE = Err
Test = TrueOn Error GoTo 0
End Function
Function First( ByVal Value As Double, _
Page 253
pushed on the stack whenever you call a function, so the address of the next instruction
Page 255 (footnote)
See http://www.jprobbins.comhttp://www.wintellect.com/robbins for other article references.
Page 256
pointer to a class instance coded into the function, and a pointer to that function.
Page 271
If you let the QueryInterface sequence readreach the primary object
Base object is both the controlling IUnknown and the delegator fordelegatee of the wrapped object.
Page 285
QS = Queue size, then number of tasks queued per thread
ART = QS * b (QS b + 1) / 2 * Slice * PCO * b (1 + b TO / QS b ) b
Page 287
using CreateObject to create a worker thread runs Sub Main a second time.
Page 297
CopyMemory WD, CacheWD, LenB(CacheWD)
CacheWDm_Workers.Remove strKey
Page 303
ByVal ReturnDataPtr As Long) As Long
If fDoIncrement Then
Page 304
TheAccessing m_ReturnDataPtr access is safe if the ThreadData class
If Not IsEmpty(m_ReturnData) Then
T:If Not IsEmpty(m_ReturnData) Then
Page 305
T:If Not IsEmpty(m_ReturnData) Then
Page 306
Public Function DoStuff(Data As Variant, _
Data As Variant, ByVal ProgressPtr As Long, ByVal ReturnDataPtr As Long, _
ByVal ReturnDataPtr As Long, ByVal CritSectPtr As Long) As Long
LeaveCriticalSection m_pCritSect
End Sub
'ThreadData class., also pass Parent.CritSect to DoStuff
If Not IsEmpty(m_ReturnData) Then
Page 307
T:If Not IsEmpty(m_ReturnData) Then
T:If Not IsEmpty(m_ReturnData) Then
Page 313
Second, it owns a handle to the callingworker thread.
providing an efficient mechanism for signaling- completion.
Page 317
Optional ByVal fReturnThreadHandle As Boolean = False) _
As Long
Page 319
'The new thread should not own the controlling thread
Page 328
allocate the data in a memory block that lives longer than theCreateWorkerThread's stack.
Page 329
Error in Figure 13.4: The long dotted line should be extended to more clearly go from GetWorkerOutput to OutputData.
Page 331
'ThreadLaunch interface definition, ThreadLaunch.cls
'Called to create a new worker thread
Page 334
'ThreadStart procedure, ThreadProc.bas
Page 342
'ThreadControl class, in ThreadControl.cls
Page 343
Optional ByVal fReturnThreadHandle As Boolean = False) _
As Long
Page 344
fSignaled As Boolean '*TB.ThreadSignalPtr changed (CT:RW)
Page 349
'Frees any leftover Variant information and
'the controller.
Erase .pSA
Page 374
For iFields = 0 To _
.TokenizeLines(strLine, iStoppedAt, strFields) - 1
Page 386
extensive discussion of methods that don't return in an HRESULT.
Page 387
three pronged approach to gain this low-level of control of the typelibs
greater range of function and interface thatthan it can produce.
Page 389
These flags are primarily for marshaling interfaces,. Any ByRef type
Page 393
If you want to explicitly unload a DLL, either for memory reasons or to upgrade it dynamically
enable upgrading it without closing your application, you need to perform
Page 394
End Type
'Typelib equivalent, UNICODE
} TLibFLStringField;
'Calling code, UNICODE
If cBytes > 3876 Then cBytes = 3876
CopyMemory FLSF.TheString(0), ByVal strData, cBytes
Page 395
} TLibFLStringField;
'Calling code, ANSI
Page 403
Private Sub IPersistHistory_SetPositionCookie ( _
Page 404
Private Sub UserControl_ReadProperties( _
(PropBag As PropertyBag)
Page 406
You must be very careful not to not use the oleautomation or dual
You have to worry about registry settings not only when you marshal
Page 407
Although the IRecordInfo is needed only for marshaling, thereto store a record in a Variant and to marshal an array. There is no way to know if marshaling will be required an array will be marshalled when the array or Variant it is created.
Page 416
The interface identifier is used during thea Set statement to verify that thea running objects supports the IID promised by its design-time typelib description.
Page 418
You can make VB register movemore (or less) typelib information
Page 420 (add as third bulleted paragraph)
You can add help information to enums, records, public properties, and other places where the VB IDE does not accept help text. You can also provide an external program
that allows you to provide custom help information for every help field in the type library. This includes the ability to create localized satellite DLLs for your
ActiveX components. See the CD for more information on implementing the IModifyHelpData interface.
Page 423
you have to replace only a single function instead of an entire multi-function entire vtable.
Page 428
Frozen events are generally not a problem with modal forms in a compiled application.
If you subclass using a control, you can actually hitsafely stop at a breakpoint while debugging.
Page 433
Case WM_GETMINMAXINFO
With g_DerefMinMaxInfo
Page 435
You don't need to show a fully functional control at design time.
Page 442
the HasDC property. ThisUse this property tellsto tell VB to borrow device contexts as needed instead of caching them
Page 443
HasDC includesis one of the two properties added to controls in VB6 to reduce resource usage.
Page 449
Objects to facilitate aggregating VB objects.
However, you are not freedo not need to redistribute the OLB
(unless you send a gift copy of the book along with it).with the DLL. The OLB is needed at compile-time only.
Page 453
Dim pDst As Long, pSrc As Long
'(void*)pDst = (void*)pDstpSrc
Page 454
AssignZero is used to zero out a pointer.
One underhanded but highly convenient use of AssignAddRef is possible withapplicable to UserControl variables.
Page 455
VB's compiler does not allow you to assign the private base class to a variable or pass it to a normal parameter.
Page 459
Changing BufferBlocks does not automatically trigger a compaction; you must explicitly call Compact
Page 461
You can redirect IID_IDispatch with adPrimaryDispatch, with adMapIIDs, or in the QIHookMapIID function on the IQIHook interface.
Page 463
adDelayDontCacheResolved stops the aggregator from keeping the resolved reference, so IDelayCreation_Create iscan be
called multiple times for multiple requests for the same IID. No request is made even
if a reference for thisthe IID is currently in use.
Page 465
Dim AggData(0) As AggregateData
Page 470
IQIARHook adds uhAddRef and uhRelease. As you can with HookQI, you can use the Flags property
|