📄 tryshotdlg.cpp
字号:
// tryshotDlg.cpp : implementation file
//
#include "stdafx.h"
#include "tryshot.h"
#include "tryshotDlg.h"
#include "D:\Program Files\DXSDK\Samples\C++\DirectShow\common\dshowutil.cpp"
//#include "D:\Program Files\DXSDK_90\Samples\C++\DirectShow\common\dshowutil.cpp"
#include "PersonalInfoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// Constants
#define WM_CAPTURE_BITMAP WM_APP + 1
/*
* Dib文件头标志(字符串"BM",写DIB时用到该常数)
*/
#define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
// Global data
BOOL g_bOneShot=FALSE;
HWND g_hwnd=0;
// Structures
typedef struct _callbackinfo
{
double dblSampleTime;
long lBufferSize;
BYTE *pBuffer;
BITMAPINFOHEADER bih;
} CALLBACKINFO;
CALLBACKINFO cb={0};
// Note: this object is a SEMI-COM object, and can only be created statically.
// We use this little semi-com object to handle the sample-grab-callback,
// since the callback must provide a COM interface. We could have had an interface
// where you provided a function-call callback, but that's really messy, so we
// did it this way. You can put anything you want into this C++ object, even
// a pointer to a CDialog. Be aware of multi-thread issues though.
//
class CSampleGrabberCB : public ISampleGrabberCB
{
public:
// these will get set by the main thread below. We need to
// know this in order to write out the bmp
long lWidth;
long lHeight;
CTryshotDlg * pOwner;
TCHAR m_szCapDir[MAX_PATH]; // the directory we want to capture to
TCHAR m_szSnappedName[MAX_PATH];
BOOL bFileWritten;
CSampleGrabberCB( )
{
pOwner = NULL;
ZeroMemory(m_szCapDir, sizeof(m_szCapDir));
ZeroMemory(m_szSnappedName, sizeof(m_szSnappedName));
bFileWritten = FALSE;
}
// fake out any COM ref counting
//
STDMETHODIMP_(ULONG) AddRef() { return 2; }
STDMETHODIMP_(ULONG) Release() { return 1; }
// fake out any COM QI'ing
//
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv)
{
if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown )
{
*ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
return NOERROR;
}
return E_NOINTERFACE;
}
// we don't implement this interface for this example
//
STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample )
{
return 0;
}
// The sample grabber is calling us back on its deliver thread.
// This is NOT the main app thread!
//
// !!!!! WARNING WARNING WARNING !!!!!
//
// On Windows 9x systems, you are not allowed to call most of the
// Windows API functions in this callback. Why not? Because the
// video renderer might hold the global Win16 lock so that the video
// surface can be locked while you copy its data. This is not an
// issue on Windows 2000, but is a limitation on Win95,98,98SE, and ME.
// Calling a 16-bit legacy function could lock the system, because
// it would wait forever for the Win16 lock, which would be forever
// held by the video renderer.
//
// As a workaround, copy the bitmap data during the callback,
// post a message to our app, and write the data later.
//
STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize )
{
// this flag will get set to true in order to take a picture
//
if( !g_bOneShot )
return 0;
if (!pBuffer)
return E_POINTER;
//-----当取得一个Sample后,进行动目标检测,暂时屏蔽掉后几帧的检测-------
g_bOneShot=FALSE;//检测结束再检测下一帧
if( cb.lBufferSize < lBufferSize )
{
delete [] cb.pBuffer;
cb.pBuffer = NULL;
cb.lBufferSize = 0;
}
cb.dblSampleTime = dblSampleTime;
if (!cb.pBuffer)
{
cb.pBuffer = new BYTE[lBufferSize];
cb.lBufferSize = lBufferSize;
}
if( !cb.pBuffer )
{
cb.lBufferSize = 0;
return E_OUTOFMEMORY;
}
memcpy(cb.pBuffer, pBuffer, lBufferSize);
PostMessage(g_hwnd, WM_CAPTURE_BITMAP, 0, 0L);
return 0;
}
// This function will be called whenever a captured still needs to be
// displayed in the preview window. It is called initially within
// CopyBitmap() to display the captured still, but it is also called
// whenever the main dialog needs to repaint and when we transition
// from video capture mode back into still capture mode.
//
// This is the implementation function that writes the captured video
// data onto a bitmap on the user's disk.
//
void PlaySnapSound(void)
{
TCHAR szSound[MAX_PATH];
const TCHAR szFileToPlay[] = { TEXT("\\media\\click.wav\0") };
int nSpaceAllowed = MAX_PATH - NUMELMS(szFileToPlay);
int nSpaceUsed=0;
nSpaceUsed = GetWindowsDirectory(szSound, nSpaceAllowed);
if (nSpaceUsed && nSpaceUsed <= nSpaceAllowed)
{
_tcscat( szSound, szFileToPlay );
sndPlaySound(szSound, SND_ASYNC);
}
}
BOOL IsHandMoving( double dblSampleTime, BYTE * pBuffer, long lBufferSize, BYTE * pBback)
{
double kLevel=7050240;//640*480*3=921600_20%有色度变化255的15%||30%认为有动目标28200960
// 18432000 14100480 7050240
BOOL bflg=FALSE;
double dtemp=0;
for (int nIndex=0;nIndex<lBufferSize;nIndex++)//-----比较当前照片pBuffer和背景照片pBback上是否有运动目标,且目标足够大------
{
dtemp=dtemp+(double)abs((double)*(pBuffer+nIndex)-(double)*(pBback+nIndex));//_______存在符合条件的动目标就返回TRUE________
}
if (dtemp>kLevel)
{
bflg=TRUE;//超过门限,表明有动目标
}
return bflg;
}
};
//////////////////////////////////////////////////////////////////
//
// This semi-COM object will receive sample callbacks for us
//
//////////////////////////////////////////////////////////////////
CSampleGrabberCB mCB;
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTryshotDlg dialog
CTryshotDlg::CTryshotDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTryshotDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTryshotDlg)
m_CaptureNumb = 3;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
mFilterGraph=NULL;
m_naccumul=0;
lWidth=640;
lHeight=480;
m_pBmem=new BYTE[lWidth*lHeight*3*m_CaptureNumb];//RGB
m_pBback=new BYTE[lWidth*lHeight*3];//存放背景照片
m_pTemp=new BYTE[lWidth*lHeight*3];//存放临时照片
pnCtrlVal=new BYTE[8];
pnCtrlVal[0]=0;
pnCtrlVal[1]=8;
pnCtrlVal[2]=4;
pnCtrlVal[3]=12;
pnCtrlVal[4]=2;
pnCtrlVal[5]=10;
pnCtrlVal[6]=6;
pnCtrlVal[7]=14;
//闪光等控制选择
b_havesettingPersonalInformation=FALSE;
b_TestLightFlag=FALSE;
}
void CTryshotDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTryshotDlg)
DDX_Control(pDX, IDC_VW4, m_V4);
DDX_Control(pDX, IDC_VW3, m_V3);
DDX_Control(pDX, IDC_VW2, m_V2);
DDX_Control(pDX, IDC_VW1, m_V1);
DDX_Control(pDX,IDC_VW0,mVideoWindow);
DDX_Text(pDX, IDC_PHOTO_NUMB, m_CaptureNumb);
DDV_MinMaxInt(pDX, m_CaptureNumb, 1, 4);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTryshotDlg, CDialog)
//{{AFX_MSG_MAP(CTryshotDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_SETPHOTONUMB, OnSetphotonumb)
ON_BN_CLICKED(IDC_EMEND, OnEmend)
ON_BN_CLICKED(IDC_LOAD_PIC, OnLoadPic)
ON_BN_CLICKED(IDC_BUTTON_INPUTNAME, OnButtonInputname)
ON_BN_CLICKED(IDC_BUTTON_TESTLIGHT, OnButtonTestlight)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTryshotDlg message handlers
BOOL CTryshotDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
CreateGraph();
mVideoWindow.ModifyStyle(0,WS_CLIPCHILDREN);
m_V1.ModifyStyle(0,WS_CLIPCHILDREN);
m_V2.ModifyStyle(0,WS_CLIPCHILDREN);
m_V3.ModifyStyle(0,WS_CLIPCHILDREN);
m_V4.ModifyStyle(0,WS_CLIPCHILDREN);
//--------设定按钮的状态---------
GetDlgItem(IDOK)->EnableWindow(FALSE);
GetDlgItem(IDC_PHOTO_NUMB)->EnableWindow(FALSE);
GetDlgItem(IDC_SETPHOTONUMB)->EnableWindow(FALSE);
GetDlgItem(IDC_EMEND)->EnableWindow(FALSE);
g_hwnd=GetSafeHwnd();
return TRUE; // return TRUE unless you set the focus to a control
}
void CTryshotDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CTryshotDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
refreshsubwnd();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -