728x90
반응형
728x170
▶ CameraControl.cs
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using DirectShowLib;
namespace TestProject
{
/// <summary>
/// 카메라 컨트롤
/// </summary>
[Guid("43878F19-1E0E-42d2-B72B-88A94418A302")]
[ComVisible(true)]
public partial class CameraControl : UserControl
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Field
////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary>
/// WM_GRAPHNOTIFY
/// </summary>
private int WM_GRAPHNOTIFY = Convert.ToInt32("0X8000", 16) + 1;
/// <summary>
/// 비디오 윈도우
/// </summary>
private IVideoWindow vidoeWindow = null;
/// <summary>
/// 미디어 컨트롤
/// </summary>
private IMediaControl mediaControl = null;
/// <summary>
/// 미디어 이벤트 확장
/// </summary>
private IMediaEventEx mediaEventEx = null;
/// <summary>
/// 그래프 빌더
/// </summary>
private IGraphBuilder graphBuilder = null;
/// <summary>
/// 캡처 그래프 빌더 2
/// </summary>
private ICaptureGraphBuilder2 captureGraphBuilder2 = null;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - CameraControl()
/// <summary>
/// 생성자
/// </summary>
public CameraControl()
{
InitializeComponent();
Load += UserControl_Load;
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Protected
//////////////////////////////////////////////////////////////////////////////// Event
#region 윈도우 프로시저 처리하기 - WndProc(message)
/// <summary>
/// 윈도우 프로시저 처리하기
/// </summary>
/// <param name="message">메시지</param>
protected override void WndProc(ref Message message)
{
if(message.Msg == WM_GRAPHNOTIFY)
{
HandleGraphEvent();
}
if(this.vidoeWindow != null)
{
this.vidoeWindow.NotifyOwnerMessage
(
message.HWnd ,
message.Msg ,
message.WParam.ToInt32(),
message.LParam.ToInt32()
);
}
base.WndProc(ref message);
}
#endregion
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 사용자 컨트롤 로드시 처리하기 - UserControl_Load(sender, e)
/// <summary>
/// 사용자컨트롤 로드시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void UserControl_Load(object sender, EventArgs e)
{
Resize += UserControl_Resize;
}
#endregion
#region 사용자 컨트롤 크기 변경시 처리하기 - Control_Resize(sender, e)
/// <summary>
/// 사용자 컨트롤 크기 변경시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void UserControl_Resize(object sender, EventArgs e)
{
if(this.vidoeWindow != null)
{
this.vidoeWindow.SetWindowPosition(0, 0, Width, ClientSize.Height);
}
}
#endregion
//////////////////////////////////////////////////////////////////////////////// Function
#region 인터페이스 설정하기 - SetInterfaces()
/// <summary>
/// 인터페이스 설정하기
/// </summary>
private void SetInterfaces()
{
this.graphBuilder = (IGraphBuilder)(new FilterGraph());
this.captureGraphBuilder2 = (ICaptureGraphBuilder2)(new CaptureGraphBuilder2());
this.mediaControl = (IMediaControl)this.graphBuilder;
this.vidoeWindow = (IVideoWindow)this.graphBuilder;
this.mediaEventEx = (IMediaEventEx)this.graphBuilder;
int resultHandle = this.mediaEventEx.SetNotifyWindow(Handle, WM_GRAPHNOTIFY, IntPtr.Zero);
DsError.ThrowExceptionForHR(resultHandle);
}
#endregion
#region 캡처 디바이스 찾기 - FindCaptureDevice()
/// <summary>
/// 캡처 디바이스 찾기
/// </summary>
/// <returns>베이스 필터 인터페이스</returns>
private IBaseFilter FindCaptureDevice()
{
UCOMIEnumMoniker ucomIEnumMoniker = null;
UCOMIMoniker[] uconIMonikerArray = new UCOMIMoniker[1];
object source = null;
ICreateDevEnum createDevEnum = (ICreateDevEnum)(new CreateDevEnum());
int resultHandle = createDevEnum.CreateClassEnumerator(FilterCategory.VideoInputDevice, out ucomIEnumMoniker, CDef.None);
DsError.ThrowExceptionForHR(resultHandle);
Marshal.ReleaseComObject(createDevEnum);
if(ucomIEnumMoniker == null)
{
throw new ApplicationException
(
"No video capture device was detected.\\r\\n\\r\\n" +
"This sample requires a video capture device, such as a USB WebCam,\\r\\n" +
"to be installed and working properly. The sample will now close."
);
}
int none = 0;
if(ucomIEnumMoniker.Next(uconIMonikerArray.Length, uconIMonikerArray, out none) == 0)
{
Guid guid = typeof(IBaseFilter).GUID;
uconIMonikerArray[0].BindToObject(null, null, ref guid, out source);
}
else
{
throw new ApplicationException("Unable to access video capture device!");
}
Marshal.ReleaseComObject(uconIMonikerArray[0]);
Marshal.ReleaseComObject(ucomIEnumMoniker);
return (IBaseFilter)source;
}
#endregion
#region 비디오 윈도우 셋업하기 - SetupVideoWindow()
/// <summary>
/// 비디오 윈도우 셋업하기
/// </summary>
private void SetupVideoWindow()
{
int resultHandle = 0;
resultHandle = this.vidoeWindow.put_Owner(Handle);
DsError.ThrowExceptionForHR(resultHandle);
resultHandle = this.vidoeWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren);
DsError.ThrowExceptionForHR(resultHandle);
UserControl_Resize(this, null);
resultHandle = this.vidoeWindow.put_Visible(OABool.True);
DsError.ThrowExceptionForHR(resultHandle);
}
#endregion
#region 비디오 캡처하기 - CaptureVideo()
/// <summary>
/// 비디오 캡처하기
/// </summary>
public void CaptureVideo()
{
int resultHandle = 0;
IBaseFilter sourceBaseFilter = null;
try
{
SetInterfaces();
resultHandle = this.captureGraphBuilder2.SetFiltergraph(this.graphBuilder);
DsError.ThrowExceptionForHR(resultHandle);
sourceBaseFilter = FindCaptureDevice();
resultHandle = this.graphBuilder.AddFilter(sourceBaseFilter, "WebCamControl Video");
DsError.ThrowExceptionForHR(resultHandle);
resultHandle = this.captureGraphBuilder2.RenderStream
(
PinCategory.Preview,
MediaType.Video,
sourceBaseFilter,
null,
null
);
Debug.WriteLine(DsError.GetErrorText(resultHandle));
DsError.ThrowExceptionForHR(resultHandle);
Marshal.ReleaseComObject(sourceBaseFilter);
SetupVideoWindow();
resultHandle = this.mediaControl.Run();
DsError.ThrowExceptionForHR(resultHandle);
}
catch(Exception exception)
{
MessageBox.Show("An unrecoverable error has occurred.\r\n" + exception.ToString());
}
}
#endregion
#region 그래프 이벤트 처리하기 - HandleGraphEvent()
/// <summary>
/// 그래프 이벤트 처리하기
/// </summary>
private void HandleGraphEvent()
{
int resultHandle = 0;
EventCode eventCode = 0;
int eventParameter1 = 0;
int eventParameter2 = 0;
while(this.mediaEventEx != null && this.mediaEventEx.GetEvent(out eventCode, out eventParameter1, out eventParameter2, 0) == 0)
{
resultHandle = this.mediaEventEx.FreeEventParams(eventCode, eventParameter1, eventParameter2);
DsError.ThrowExceptionForHR(resultHandle);
}
}
#endregion
#region 인터페이스 해제하기 - ReleaseInterfaces()
/// <summary>
/// 인터페이스 해제하기
/// </summary>
public void ReleaseInterfaces()
{
if(this.mediaControl != null)
{
this.mediaControl.StopWhenReady();
}
if(this.mediaEventEx != null)
{
this.mediaEventEx.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero);
}
if(this.vidoeWindow != null)
{
this.vidoeWindow.put_Visible(OABool.False);
this.vidoeWindow.put_Owner(IntPtr.Zero);
}
Marshal.ReleaseComObject(this.mediaControl);
this.mediaControl = null;
Marshal.ReleaseComObject(this.mediaEventEx);
this.mediaEventEx = null;
Marshal.ReleaseComObject(this.vidoeWindow);
this.vidoeWindow = null;
Marshal.ReleaseComObject(this.graphBuilder);
this.graphBuilder = null;
Marshal.ReleaseComObject(this.captureGraphBuilder2);
this.captureGraphBuilder2 = null;
}
#endregion
}
}
728x90
▶ MainForm.cs
using System;
using System.Windows.Forms;
namespace TestProject
{
/// <summary>
/// 메인 폼
/// </summary>
public partial class MainForm : Form
{
//////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
////////////////////////////////////////////////////////////////////////////////////////// Public
#region 생성자 - MainForm()
/// <summary>
/// 생성자
/// </summary>
public MainForm()
{
InitializeComponent();
}
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method
////////////////////////////////////////////////////////////////////////////////////////// Private
//////////////////////////////////////////////////////////////////////////////// Event
#region 재생 버튼 클릭시 처리하기 - playButton_Click(sender, e)
/// <summary>
/// 재생 버튼 클릭시 처리하기
/// </summary>
/// <param name="sender">이벤트 발생자</param>
/// <param name="e">이벤트 인자</param>
private void playButton_Click(object sender, EventArgs e)
{
if(this.playButton.Text == "캡처 시작")
{
this.playButton.Text = "캡처 종료";
this.xWebCamControl.CaptureVideo();
}
else
{
this.playButton.Text = "캡처 시작";
this.xWebCamControl.ReleaseInterfaces();
}
}
#endregion
}
}
※ 윈도우즈 7에서만 실행된다.
728x90
반응형
그리드형(광고전용)
'C# > WinForm' 카테고리의 다른 글
[C#/WINFORM] 폼 위치 설정하기 (0) | 2018.03.03 |
---|---|
[C#/WINFORM] 태스크바 위치 타입 구하기 (0) | 2018.03.03 |
[C#/WINFORM] ClickOnce 설치 파일 캐시 지우기 (0) | 2018.03.01 |
[C#/WINFORM] WIN32 API를 사용해 화면 캡처하기 (0) | 2018.02.18 |
[C#/WINFORM] TextBox 클래스 : 텍스트 필터 사용하기 (0) | 2018.02.18 |
[C#/WINFORM] DataGridView 클래스 : 달력 컨트롤 컬럼 사용하기 (0) | 2018.02.18 |
[C#/WINFORM] DataGridView 클래스 : 동적 콤보 박스 사용하기 (0) | 2018.02.18 |
[C#/WINFORM] TreeView 클래스 : 동적 노드 생성하기 (0) | 2018.02.18 |
[C#/WINFORM] WPF 사용자 컨트롤 사용하기 (0) | 2018.02.17 |
[C#/WINFORM] DataGridView 클래스 : 컬럼 헤더 병합하기 (0) | 2018.02.17 |
댓글을 달아 주세요