Some people have asked if they could take a look at the source for the WebCam
Vista Sidebar gadget. After a little bit of cleaning up, I'm posting it now for
you to take a look at. Here are some things worth mentioning:


1. Uses the DirectShow.NET library


2. I found some source in VB.NET and used that as a baseline (performed the
conversion and cleaned up stuff that really wasn't needed)


3. I am in no way a DirectX/DirectShow expert. Any questions sent my way will
likely result in a blank stare back at you :-) (though fwiw, I do pick up things
quickly and might be able to at least get you started on the correct path)


4. If you look at the source, you might think "I thought this was a Vista
Sidebar Gadget. Where is the gadget source?" That's the easy part. At the bottom
of this post is a link to my .NET Gadget Creator application that I wrote (with
instructions on how to use it with the WebCam control). That application will
allow you to take any .NET UserControl and convert it into a Vista Sidebar
Gadget. Just compile the WebCamControl2 control, and use the .NET Gadget Creator
to create an instant Vista Sidebar gadget.


5. You may receive an error when you run the provided test application saying
something along the lines of "invalid argument". This is a known issue and is
happens when more than one application tries to access the same camera. I
haven't looked into fixing this so if someone wants to take a stab at it, clue
me in on how to fix it.


When looking through the source (there isn't that much to it) pay attention
to the 2 primary methods. The first is the GetInterfaces method which
creates all the necessary DirectShow interfaces and then creates the connection
between DirectShow and your UserControl window (events are passed to the control
via Window messages).


The FindCaptureDevice method enumerates through your devices looking
for the 1st video device it finds that provides an input
(FilterCategory.InputDevice). This is done by creating a device class
enumerator. Currently, the source will just grab the first device that it sees.
If anyone is interested in knowing how to present the user with a list of all
input devices, I can write some code to do that as well. Just let me know.




 
103
 UCOMIEnumMoniker classEnum = null;


 
104
 UCOMIMoniker[] moniker = new UCOMIMoniker[1];


 
105
 object source = null;


 
106
 


 
107
 ICreateDevEnum devEnum = (ICreateDevEnum)(new CreateDevEnum());


 
108
 int hr = devEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out classEnum, CDef.None);


 
109
 DsError.ThrowExceptionForHR(hr);


 
110
 Marshal.ReleaseComObject(devEnum);


Once the class enumerator is created, I just grab the first one that was
found (assuming one was found) and bind it to an IBaseFilter object which I then
return.




 
117
 int none = 0;


 
118
 


 
119
 if (classEnum.Next(moniker.Length, moniker, out none) == 0)


 
120
{


 
121
     Guid
iid = typeof(IBaseFilter).GUID;


 
122
     moniker[0].BindToObject(null, null, ref iid, out source);


 
123
}


 
124
 else


 
125
{


 
126
     throw new ApplicationException("Unable to access video capture
device!"
);


 
127
}


 
128
 


 
129
 Marshal.ReleaseComObject(moniker[0]);


 
130
 Marshal.ReleaseComObject(classEnum);


 
131
 


 
132
 return (IBaseFilter)source;


Once the video input device is found and we have our base filter, we
associate it with an ICaptureGraphBuilder2 object by telling it render a video
stream through the preview pin of the input device(line 68 below of the
CaptureVideo method).






   51 private void CaptureVideo()


   52 {


   53     int hr = 0;


   54     IBaseFilter
sourceFilter = null;


   55     try


   56     {


   57         // create the
necessary DirectShow interfaces


   58         GetInterfaces();


   59 


   60         hr =
this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);


   61         DsError.ThrowExceptionForHR(hr);


   62 


   63         sourceFilter = FindCaptureDevice();


   64 


   65         hr =
this.graphBuilder.AddFilter(sourceFilter, "WebCamControl Video");


   66         DsError.ThrowExceptionForHR(hr);


   67 


   68         hr =
this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video,
sourceFilter, null, null);


   69         Debug.WriteLine(DsError.GetErrorText(hr));


   70         DsError.ThrowExceptionForHR(hr);


   71 


   72         Marshal.ReleaseComObject(sourceFilter);


   73 


   74         SetupVideoWindow();


   75 


   76         hr =
this.mediaControl.Run();


   77         DsError.ThrowExceptionForHR(hr);


   78 


   79         this.CurrentState
= PlayState.Running;


   80     }


   81     catch (Exception ex)


   82     {


   83         MessageBox.Show("An unrecoverable error has
occurred.\r\n"
+ ex.ToString());


   84     }


   85 }


Now, if you want to use that control in the Vista Sidebar, just download and
install the following application:

When you launch the application and click Next it will ask you to add .NET
assemblies. Click the Add button, navigate to the WebCamTest or WebCamControl2
bin directory and select the WebCamControl2.dll AND the DirectShowLib.dll
assemblies as shown below.


image


Click Next twice to get to the "Select UserControl
to Embed". Select the WebCamControl2.WebCamControl2 type and click Next. The
next screen allows you to enter the information about the gadget. I provided an
icon for you in the WebCamTest base directory. After you fill in the
information, keep clicking Next and the gadget will be built for you. Go into
the output directory you specified and you'll see the .gadget file. Simply
double click on this and if all goes well, you should be looking at your webcam
in the Vista Sidebar. Also, since you used the .NET Gadget Creator application,
your gadget will uninstall successfully even while it is running (see .NET
Sidebar Gadget Creator Update #2
for more information).


출처 : http://blogs.msdn.com/b/markhsch/archive/2007/11/19/c-webcam-user-control-source.aspx