04.08.2013 Views

Un-Mapping Mapped Network Drives Andrew Coates - dFPUG-Portal

Un-Mapping Mapped Network Drives Andrew Coates - dFPUG-Portal

Un-Mapping Mapped Network Drives Andrew Coates - dFPUG-Portal

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Improving the interface<br />

Figure 1 illustrates the new Visual Basic project.<br />

The first order of business is addressing the first<br />

limitation of too much functionality (yes, I know that<br />

sounds funny). The following code is associated with the<br />

grid control. Most of the code deals with the visual<br />

characteristics of the grid—location and size. The most<br />

important method is the SetDataSource Member.<br />

Remember, in VFP, an ADO RecordSet can’t be bound to<br />

the DataGrid control. This is how you can get around that<br />

limitation. Pass the ADO RecordSet to the control, and<br />

have the control do the binding for you within its<br />

boundaries! It works like a charm.<br />

Private Sub UserControl_Initialize()<br />

'When the control is dropped onto the form,<br />

'the grid must be positioned in the upper-<br />

'left corner of the container.<br />

With DataGrid<br />

.Left = 0<br />

.Top = 0<br />

End With<br />

End Sub<br />

Private Sub UserControl_Resize()<br />

'When the container is resized, we want the<br />

'grid to also resize.<br />

With DataGrid<br />

.Width = ScaleWidth<br />

.Height = ScaleHeight<br />

End With<br />

End Sub<br />

'WARNING! DO NOT REMOVE OR MODIFY<br />

'THE FOLLOWING COMMENTED LINES!<br />

'MemberInfo=14<br />

Public Sub SetDataSource(recordset As ADODB.recordset)<br />

Set DataGrid.DataSource = recordset<br />

End Sub<br />

With this design, the services of our grid control<br />

are very granular. Its only purpose is to accept an<br />

ADO RecordSet and display the data. We’ll reserve the<br />

more complicated tasks of responding to events for<br />

another control.<br />

The other control in the Visual Basic project consists<br />

of one user interface element—a Label control. There’s<br />

quite a lot of code behind this control—far too much to<br />

Figure 1. The new Visual Basic ActiveX control project contains<br />

two ActiveX controls.<br />

print in its entirety. However, I’ll highlight the most<br />

important pieces of code.<br />

Going back to the limitations of the first design, no<br />

public interfaces existed to make the ADO DataSource<br />

variable. Also, all of the events in the previous design<br />

were private. This meant that while the control within its<br />

boundaries recognized the event, no mechanism existed<br />

for the control to surface those events to its own interface.<br />

This means that any application environment hosting the<br />

control wouldn’t have the ability to have its own code<br />

execute when those events have fired. After all, that’s<br />

what it’s all about—having the ability to attach VFP code<br />

to ADO events.<br />

The first lines of code in the VB ActiveX control<br />

are as follows:<br />

Dim WithEvents oconn As ADODB.Connection<br />

Dim WithEvents ors As ADODB.recordset<br />

This provides that ability to the ActiveX control to<br />

respond to events that each of these objects will fire. The<br />

previous design took advantage of this ability and<br />

attached Visual Basic code to those events. In the old<br />

design, when an ADO connection was established, a<br />

MessageBox dialog box appeared, stating that the ADO<br />

connection was complete. While not very useful, it served<br />

to illustrate how events could be trapped. Visual Basic<br />

code is nice, but we work in VFP. We need the ability to<br />

surface these events so that VFP code can be used.<br />

Custom events<br />

Remember when VFP 3.0 was released back in 1995? We<br />

were given the ability to define our own methods and<br />

properties. Defining events, on the other hand, was<br />

something that wasn’t—and still isn’t—-provided. I, for<br />

one, didn’t see the big deal in this. After all, there are<br />

hundreds of events already defined. Why would I need<br />

more? As you’ll see, the ability to define custom events is<br />

a very powerful capability.<br />

To illustrate the power of events, I’ll focus on the<br />

MoveComplete event of the ADO RecordSet object. This<br />

event fires whenever the record changes. This event gets<br />

fired as a result of invoking the MoveFirst, MovePrevious,<br />

MoveNext, or MoveLast methods. The MoveComplete<br />

event also fires when an ADO RecordSet is first opened.<br />

Before looking at the custom event, let’s take a look at<br />

the code for the internal event that gets fired:<br />

Private Sub ors_MoveComplete( _<br />

ByVal adReason As ADODB.EventReasonEnum, _<br />

ByVal pError As ADODB.Error, _<br />

adStatus As ADODB.EventStatusEnum, _<br />

ByVal pRecordset As ADODB.recordset)<br />

RaiseEvent movecomplete(adReason, pError, _<br />

adStatusCancel, pRecordset)<br />

End Sub<br />

In this code, the internal ors_RecordSet object<br />

variable will respond to the MoveComplete event. This<br />

code block, in turn, will fire. The code to key on is the<br />

RaiseEvent statement. Notice that another MoveComplete<br />

16 FoxTalk December 1998<br />

http://www.pinpub.com

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!