(c) 2002 Visual Studio Magazine 
Fawcette Technical Publications

Issue: July 2002
Section: Q&A
Authors: Karl E. Peterson and Juval Lowy

VB5, VB6	Let Users Drag URLs From IE
Listing 1	If your application might need to know a URL, you don't have to force your users to type it in; instead you can support them dragging it directly from a Web page displayed in Internet Explorer. In fact, this technique is limited only by what applications package up an OLE DataObject for dragging. Your application examines the DataObject's text component to see if it contains what might be a URL, and bases user feedback on this determination. 

Option Explicit

Private Sub Form_Load()
	Me.OLEDropMode = vbOLEDropManual
End Sub

Private Sub Form_OLEDragDrop(Data As DataObject, _
	Effect As Long, Button As Integer, Shift As _
	Integer, X As Single, Y As Single)
	Debug.Print Data.GetData(vbCFText)
End Sub

Private Sub Form_OLEDragOver(Data As DataObject, _
	Effect As Long, Button As Integer, Shift As _
	Integer, X As Single, Y As Single, State As _
	Integer)
	Dim txt As String
	Const vbDropEffectLink = 4

	' Test for URL in DataObject.
	txt = Data.GetData(vbCFText)
	' Your test(s) may vary.
	If InStr(LCase$(txt), "http:") <> 1 Then
		Effect = vbDropEffectNone
	End If
End Sub

C#	The Compiler Generates This Code Instead of the Foreach Statement 
Listing 2	The compiler gets an IEnumerator object and uses it to iterate over every element in the collection, followed by a call to dispose of the IEnumerator object. The compiler also generates error-handling statements. 

IEnumerator enumerator = 
	collection.GetEnumerator();
try
{
	while(enumerator.MoveNext())
	{
		string name = (string)enumerator.Current;
		Trace.WriteLine(name);
	}
}
finally
{
	IDisposable dispobable = enumerator as 
		IDisposable;
	if(dispobable!=null)
		dispobable.Dispose();
}

C#	Implement Your Custom Collection Using the Template Code
Listing 3	You enumerate IEnumerable directly on the collection, while you implement IEnumerator on a separate nested class. A nest class enables easier programming because it has visibility into the parent class members, and it provides for concurrent  iterations.

 public class NameCollection : IEnumerable
{
	protected string[] m_Names;
	public NameCollection()
	{
		m_Names = new string[]
			{"Alice","Bob","Charlie"};
	}
	public IEnumerator GetEnumerator()
	{
		return new MyEnumerator(this);
	}
	//nested class definition 
	protected class MyEnumerator : 
		IEnumerator,IDisposable
	{
		protected NameCollection m_Collection;
		protected int m_Current; 
		public MyEnumerator(NameCollection 
			collection)
		{
			m_Collection = collection;
			Reset();
		}
		public bool MoveNext()
		{
			m_Current++;
			if(m_Current < 
				m_Collection.m_Names.Length)
				return true;
			else
			{
				m_Current = -1;
				return false;
			}
		}
		public object Current
		{
			get			{
				if(m_Current == -1)
					throw new 
						InvalidOperationException();
				return m_Collection.m_Names
					[m_Current];
					//can access because nested
			}
		}
		public void Reset()
		{
			m_Current = -1;
		}
		public void Dispose()
		{
			//dispose of whatever needs disposing
		}	
	} 
}


