📄 captureframe.cpp
字号:
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// CaptureFrame.cpp:
// implementation of the CCaptureFrame class.
// Copyright
// (c) 1998 School of Information Systems, UEA
// Author
// Farzad Pezeshkpour
// Revision
// 1998/12/03
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#include "stdafx.h"
#include "utility.h"
#include "CaptureFrame.h"
#include "resource.h"
#include "menuitem.h"
#include <sstream>
#undef AVICapSM
//#pragma warning (disable : 4005)
#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)
//#pragma warning (default : 4005)
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// Static Declarations
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
CCaptureFrame *CCaptureFrame::m_pFrame = NULL;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCaptureFrame::CCaptureFrame()
: CWindowImpl <CCaptureFrame> (),
m_hVfwWnd(NULL),
m_bPreview(false),
m_bStretch(false),
m_bProportional(false),
m_pFormat(NULL),
m_hIC(NULL),
m_dwFrames(0)
{
m_vcaps.wDeviceIndex = 99;
}
CCaptureFrame::~CCaptureFrame()
{
ReleaseIC ();
if (m_hVfwWnd != NULL) {
::SetParent (m_hVfwWnd, GetDesktopWindow());
SetFrameCallback (false);
capDriverDisconnect(m_hVfwWnd);
m_hVfwWnd = NULL;
}
DestroyWindow();
}
CWndClassInfo& CCaptureFrame::GetWndClassInfo ()
{
static CWndClassInfo wc =
{
{ sizeof(WNDCLASSEX), CS_NOCLOSE|CS_HREDRAW|CS_VREDRAW, StartWindowProc,
0, 0, 0, LoadIcon (_Module.GetModuleInstance(), MAKEINTRESOURCE(IDI_ICON2)), 0, (HBRUSH)(COLOR_WINDOW+1), MAKEINTRESOURCE(IDR_MENU1), "MatlabVfwFrame", 0 },
NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
};
return wc;
}
LRESULT CCaptureFrame::OnInitMenuPopup(WPARAM wParam, LPARAM lParam)
{
// We don't process the system menu (yet)
if (((BOOL)HIWORD(lParam))) {
return 1;
}
LRESULT result;
CMenuItem mi;
mi.m_hMenu = (HMENU) wParam;
UINT uiPos = (UINT) LOWORD (lParam);
// Hack - this functionality should be provided by an overridable
// baseclass member
if (uiPos == 0) {
UpdateDeviceMenu (mi.m_hMenu);
return 0;
}
UINT count = (UINT)::GetMenuItemCount (mi.m_hMenu);
for (UINT i = 0; i < count; i++) {
mi.m_nIndex = i;
mi.m_nId = ::GetMenuItemID (mi.m_hMenu, mi.m_nIndex);
wParam = MAKEWPARAM (mi.m_nId, CN_COMMAND_UI);
ProcessWindowMessage (m_hWnd, WM_COMMAND, wParam, ((LPARAM) &mi), result, 0);
}
return 0;
}
void CCaptureFrame::OnUpdatePreview (CMenuItem *pItem)
{
pItem->SetCheck(m_bPreview);
}
void CCaptureFrame::OnPreview ()
{
SetPreview (!m_bPreview);
}
HWND CCaptureFrame::Create(HWND hWndParent, RECT & rcPos, LPCTSTR sszWindowName, DWORD dwStyle, DWORD dwExStyle, UINT nID)
{
HWND hWnd = CWindowImpl<CCaptureFrame>::Create(hWndParent, rcPos, sszWindowName, dwStyle, dwExStyle, nID);
m_hVfwWnd = capCreateCaptureWindow ("VfwCapture", WS_CHILD|WS_VISIBLE, 0, 0, 320, 240, hWnd, 4456);
ConnectDevice (0);
return hWnd;
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// EmptyDeviceList
// Ensures that the list of devices is empty
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void CCaptureFrame::EmptyDeviceList()
{
for (WORD wIndex = 0; wIndex < 10; wIndex++)
m_sDevices[wIndex] = "";
}
std::string *CCaptureFrame::GetDriverList ()
{
BuildDeviceList();
return m_sDevices;
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// BuildDeviceList
// Clears the current device list and re-reads the system
// video devices
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void CCaptureFrame::BuildDeviceList()
{
EmptyDeviceList ();
char szDeviceName[80];
char szDeviceVersion[80];
for (WORD wIndex = 0; wIndex < 10; wIndex++)
{
if (capGetDriverDescription (wIndex, szDeviceName,
sizeof (szDeviceName), szDeviceVersion,
sizeof (szDeviceVersion)))
{
m_sDevices[wIndex] = szDeviceName;
}
}
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// UpdateDeviceMenu
// Called by the framework to rebuild the device menu
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void CCaptureFrame::UpdateDeviceMenu(HMENU hMenu)
{
BuildDeviceList ();
int count = GetMenuItemCount (hMenu);
while (count-- > 0) {
::RemoveMenu (hMenu, 0, MF_BYPOSITION);
DrawMenuBar();
}
UINT iDriver = 99; // default value indicating no match
UINT iNext = 0;
MENUITEMINFO mi;
mi.cbSize = sizeof(mi);
mi.fMask = MIIM_DATA | MIIM_ID | MIIM_TYPE;
mi.fType = MFT_STRING;
mi.wID = ID_DEVICEMENU_0;
mi.dwTypeData = "";
for (WORD wIndex = 0; wIndex < 10; wIndex++) {
if (!m_sDevices[wIndex].empty()) {
mi.wID = ID_DEVICEMENU_0 + wIndex;
mi.dwTypeData = (char*)m_sDevices[wIndex].c_str();
if (::InsertMenuItem (hMenu, iNext, TRUE, &mi)) {
if (m_vcaps.wDeviceIndex == wIndex)
iDriver = iNext;
DrawMenuBar ();
++iNext;
}
}
}
// set the check button
if (iDriver < 10)
::CheckMenuRadioItem (hMenu, 0, iNext-1, iDriver, MF_BYPOSITION);
}
void CCaptureFrame::OnSelectDriver (DWORD dwId)
{
dwId -= ID_DEVICEMENU_0;
SetDriver(dwId);
}
bool CCaptureFrame::SetDriver (DWORD dwId)
{
if (dwId > 9) return false;
if (m_sDevices[dwId].empty ()) return false;
capDriverDisconnect(m_hVfwWnd);
m_vcaps.wDeviceIndex = 99;
ConnectDevice((WORD)dwId);
return true;
}
bool CCaptureFrame::ConnectDevice(WORD index)
{
bool ok = true;
if (index > 9 || m_hVfwWnd == NULL) ok = false;
ok = ok && capDriverConnect(m_hVfwWnd, index);
ok = ok && capDriverGetCaps(m_hVfwWnd, &m_vcaps, sizeof(m_vcaps));
ok = ok && capPreviewRate(m_hVfwWnd, 20); // rate, in milliseconds
if (ok) {
ReleaseIC();
RetrieveFormat();
ResetSize();
}
return ok;
}
bool CCaptureFrame::SetPreview (bool bPreview)
{
bool ok = true;
if (m_hVfwWnd == NULL) ok = false;
ok = ok && capPreview(m_hVfwWnd, bPreview);
if (ok)
m_bPreview = bPreview;
return ok;
}
LRESULT CCaptureFrame::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
SetSize ();
return 0;
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// OnUpdateStretch
// Called before the Stretch Item in the Window menu is updated
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void CCaptureFrame::OnUpdateStretch (CMenuItem *pItem)
{
pItem->SetCheck(m_bStretch);
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// OnStretch
// Called when the Stretch item in the Window menu is activated
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void CCaptureFrame::OnStretch ()
{
SetStretch (!m_bStretch);
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// SetStretch
// Called to (un)set the stretching of the preview window
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
bool CCaptureFrame::SetStretch (bool bStretch)
{
bool ok = (m_hVfwWnd != NULL);
ok = ok && capPreviewScale (m_hVfwWnd, bStretch);
if (ok) {
m_bStretch = bStretch;
SetSize();
RedrawWindow ();
}
return ok;
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// DeleteFormat
// Delete an existing video format
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void CCaptureFrame::DeleteFormat ()
{
if (m_pFormat) {
delete ((LPBYTE)m_pFormat);
m_pFormat = NULL;
}
}
void CCaptureFrame::RetrieveFormat ()
{
DeleteFormat();
DWORD dwSize;
dwSize = capGetVideoFormatSize(m_hVfwWnd);
m_pFormat = (LPBITMAPINFO)new BYTE [dwSize];
capGetVideoFormat(m_hVfwWnd, m_pFormat, dwSize);
}
void CCaptureFrame::ResetSize ()
{
if (m_hVfwWnd == NULL || m_pFormat == NULL) return;
RECT cr;
RECT wr;
RECT pos;
GetClientRect (&cr);
GetWindowRect (&wr);
pos = wr;
wr.right -= wr.left;
wr.bottom -= wr.top;
wr.left = wr.top = 0;
// calculate the size of the frame
cr.right = wr.right - cr.right;
cr.bottom = wr.bottom - cr.bottom;
pos.right = m_pFormat->bmiHeader.biWidth + cr.right;
pos.bottom = m_pFormat->bmiHeader.biHeight + cr.bottom;
MoveWindow (pos.left, pos.top, pos.right, pos.bottom);
}
void CCaptureFrame::SetFrameCallback (bool bSet) {
if (m_hVfwWnd == NULL) return;
if (bSet) {
m_pFrame = this;
capSetCallbackOnFrame (m_hVfwWnd, FrameCallback);
} else {
m_pFrame = NULL;
capSetCallbackOnFrame (m_hVfwWnd, NULL);
}
}
LRESULT PASCAL CCaptureFrame::FrameCallback (HWND hWnd, LPVIDEOHDR lpVHdr)
{
if (m_pFrame != NULL)
m_pFrame->m_queue.AppendFrame (m_pFrame->m_pFormat, lpVHdr->lpData);
return (LRESULT) TRUE ;
}
void CCaptureFrame::Grab(WORD wCount)
{
if (m_hVfwWnd == NULL) {
std::string *pStr = new std::string("capture window not created yet.");
throw pStr;
}
m_dwFrames = wCount;
m_queue.SetSize (wCount);
m_queue.ClearBuffer();
SetFrameCallback (true);
//capCaptureSequenceNoFile (m_hVfwWnd);
for (WORD i = 0; i < wCount; i++)
capGrabFrameNoStop (m_hVfwWnd);
SetFrameCallback (false);
}
void CCaptureFrame::ReleaseIC()
{
if (m_hIC != NULL) {
ICClose (m_hIC);
m_hIC = NULL;
}
}
void CCaptureFrame::GetMatlabArrays (int lower, int upper,
mxArray *plhs[], int nlhs)
{
m_queue.GetMatlabArrays (lower, upper, plhs, nlhs, m_hIC);
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// OnUpdateFormatDlg
// Called before the "Format Dlg" item in the Configure menu is
// updated
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void CCaptureFrame::OnUpdateFormatDlg (CMenuItem *pItem)
{
pItem->Enable(m_hVfwWnd != NULL && m_vcaps.fHasDlgVideoFormat);
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// OnUpdateSourceDlg
// Called before the "Source Dlg" item in the Configure menu is
// updated
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void CCaptureFrame::OnUpdateSourceDlg (CMenuItem *pItem)
{
pItem->Enable(m_hVfwWnd != NULL && m_vcaps.fHasDlgVideoSource);
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
// OnUpdateDisplayDlg
// Called before the "Display Dlg" item in the Configure menu is
// updated
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void CCaptureFrame::OnUpdateDisplayDlg (CMenuItem *pItem)
{
pItem->Enable(m_hVfwWnd != NULL && m_vcaps.fHasDlgVideoDisplay);
}
bool CCaptureFrame::ConfigureSource ()
{
if (m_hVfwWnd != NULL && m_vcaps.fHasDlgVideoSource) {
capDlgVideoSource (m_hVfwWnd);
ReleaseIC();
RetrieveFormat();
if (!m_bStretch)
ResetSize();
return true;
} else
return false;
}
bool CCaptureFrame::ConfigureFormat()
{
if (m_hVfwWnd != NULL && m_vcaps.fHasDlgVideoFormat) {
capDlgVideoFormat (m_hVfwWnd);
ReleaseIC();
RetrieveFormat();
if (!m_bStretch)
ResetSize();
return true;
} else
return false;
}
bool CCaptureFrame::ConfigureDisplay ()
{
if (m_hVfwWnd != NULL && m_vcaps.fHasDlgVideoDisplay) {
capDlgVideoDisplay (m_hVfwWnd);
ReleaseIC();
RetrieveFormat();
if (!m_bStretch)
ResetSize();
return true;
} else
return false;
}
void CCaptureFrame::OnHide ()
{
ShowWindow (SW_HIDE);
}
void CCaptureFrame::OnShow ()
{
ShowWindow (SW_SHOWDEFAULT);
}
void CCaptureFrame::OnShow (bool bShow)
{
ShowWindow (bShow ? SW_SHOWDEFAULT : SW_HIDE);
}
void CCaptureFrame::SetSize()
{
RECT r;
GetClientRect (&r);
WORD height = r.bottom;
WORD width = r.right;
WORD imwidth = 0;
WORD imheight = 0;
if (m_pFormat != NULL) {
imwidth = (WORD) m_pFormat->bmiHeader.biWidth;
imheight = (WORD) m_pFormat->bmiHeader.biHeight;
}
WORD x = (width - imwidth) / 2;
WORD y = (height - imheight) / 2;
if (m_bStretch) {
::MoveWindow (m_hVfwWnd, 0, 0, width, height, FALSE);
} else {
::MoveWindow (m_hVfwWnd, x, y, imwidth, imheight, FALSE);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -