[C++] Snapshot von Webcam machen

C Coder

Erfahrenes Mitglied
Hi!

Ich möchte gerne ein einfaches Bild von meiner Webcam bekommen OHNE irgendein Fenster erstellen zu müssen!

Gibts dafür ne Funktion, Code oder irgendwas aus dem OpenSource-Bereich?

Ich nutze Visual Studio 2002 unter XP
Bin echt am verzweifeln...
 
Harter Stoff, danke erstmal!

Wenns wirklich nicht ohne Fenster geht, gibts ne möglichkeit das zu verstecken,
das es nur als Prozess im Task-Manager auftaucht? (also nicht uner Anwendungen!)
 
Original geschrieben von C Coder
Harter Stoff, danke erstmal!

Wenns wirklich nicht ohne Fenster geht, gibts ne möglichkeit das zu verstecken,
das es nur als Prozess im Task-Manager auftaucht? (also nicht uner Anwendungen!)
Klar, es zu verstecken ist kein Problem.
Ich suche gerade ein Testprojekt, wo ich das mal gemacht habe, allerdings kann es noch eine Weile dauern, bis ich es finde. Und ich bin in den nächsten Tagen nicht online. Vielleicht kann ja auch Endurion was zum Thema sagen; der hat mir nämlich gezeigt , wie es geht.

Ah, ich habe es anscheinend schon einmal gepostet. Guck mal, ob dir das weiterhilft, und lass dich nicht von den Kommentaren irritieren -- die waren zu einer anderen Sache.
Code:
//... stdafx.h usw.

#include <vfw.h>

#pragma comment( lib, "vfw32.lib" )


// Der View hat ein Member für das Capturewindow
CChildView::CChildView()
{
  hwndCapture_  = 0;
}



/////////////////////////////////////////////////////////////////////
//-    OnCreate
/////////////////////////////////////////////////////////////////////
int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CWnd ::OnCreate(lpCreateStruct) == -1)
		return -1;
	
  InitCapture();

  Invalidate();
  return 0;
}


/////////////////////////////////////////////////////////////////////
//-    OnEraseBkgnd
/////////////////////////////////////////////////////////////////////
BOOL CChildView::OnEraseBkgnd(CDC* pDC) 
{
  return TRUE;
}

/////////////////////////////////////////////////////////////////////
//-  
//-    Videograbbing
//-  
/////////////////////////////////////////////////////////////////////
namespace
{
  BOOL StartCapture( HWND hwndCapture )
  {
    if ( hwndCapture == NULL )
    {
      return FALSE;
    }

    if ( !SendMessage( hwndCapture,WM_CAP_DRIVER_CONNECT, 0, 0 ) )
    {
      // kein Video-Input-Device gefunden
      DestroyWindow( hwndCapture );
      return FALSE;
    }

    SendMessage( hwndCapture, WM_CAP_SET_SCALE, (WPARAM)TRUE, 0 );
    SendMessage( hwndCapture, WM_CAP_SET_PREVIEW, 1, 0 );
    SendMessage( hwndCapture, WM_CAP_SET_PREVIEWRATE, 30, 0 );

    return TRUE;
  }

  void StopCapture( HWND hwndCapture )
  {
    if ( hwndCapture == NULL )
    {
      return;
    }
    SendMessage( hwndCapture, WM_CAP_STOP, 0, 0 );
    SendMessage( hwndCapture, WM_CAP_SET_PREVIEW, 0, 0 );
  }

  inline unsigned long C24TO15( unsigned long color )
  {
    return    ( ( ( ( color & 0xff0000 ) >> 16 ) >> 3 ) << 10 ) 
           |  ( ( ( ( color & 0x00ff00 ) >> 8  ) >> 3 ) << 5  ) 
           |  ( ( ( ( color & 0x0000ff ) >> 0  ) >> 3 ) << 0  ); 
  }
};

int CChildView::InitCapture()
{
  hwndCapture_  = capCreateCaptureWindow( "capture", 
                                        WS_OVERLAPPEDWINDOW,
                                        0,   0, 
                                        640,  480, 
                                        GetSafeHwnd(), 
                                        0 );
  
  ::SetWindowPos( hwndCapture_, NULL, 0, 0, 380, 285, SWP_NOZORDER );
  ::ShowWindow( hwndCapture_, SW_SHOW );
  StartCapture( hwndCapture_ );
  return 0;

}

void CChildView::OnDestroy() 
{
  if ( hwndCapture_ != NULL )
  {
    StopCapture( hwndCapture_ );
    ::SendMessage( hwndCapture_, WM_CAP_DRIVER_DISCONNECT, 0, 0 );
    ::DestroyWindow( hwndCapture_ );
    hwndCapture_ = NULL;
  }

	CWnd::OnDestroy();
}

void CChildView::OnDateiEinstellungen() 
{
  capDlgVideoFormat( hwndCapture_ );
}

/*-CaptureImage---------------------------------------------------------------+
 |                                                                            |
 +----------------------------------------------------------------------------*/
BOOL CChildView::CaptureImage()
{
  ::SendMessage( hwndCapture_, WM_CAP_GRAB_FRAME, 0, 0 );
  ::SendMessage( hwndCapture_, WM_CAP_EDIT_COPY, 0, 0 );

  if ( !::OpenClipboard( GetSafeHwnd() ) )
  {
    ::MessageBox( GetSafeHwnd(), "Konnte ClipBoard nicht anfordern.", "Fehler!", 0 );
    return FALSE;
  }
   
  HBITMAP hBitmap = (HBITMAP)GetClipboardData( CF_DIBV5 );
  if ( hBitmap == NULL )
  {
    CloseClipboard();
    ::MessageBox( GetSafeHwnd(), "Das Clipboard ist leer!", "Fehler", 0 );
    return FALSE;
  }
  
  BITMAPINFO* pInfo = ((BITMAPINFO*)hBitmap);
  LONG dwWidth      = pInfo->bmiHeader.biWidth;
  LONG dwHeight     = pInfo->bmiHeader.biHeight;
  WORD bitcount     = pInfo->bmiHeader.biBitCount;
  DWORD colorused   = pInfo->bmiHeader.biClrUsed;

  // für debugging
  //dh() << dwWidth << ", " << dwHeight << ", " << bitcount << ", " << colorused << "\n";
  //dh() << pInfo->bmiHeader.biSize << "\n"; 

  if ( bitcount == 24 )
  {
    int iLO = dwWidth;
    if ( iLO % 4 ) iLO += ( 4 - iLO % 4 );

    DWORD dwHeaderSize = 124;

    int targetwidth = m_pFrontPage->width();

    char* pBitmap = ( (char*) pInfo ) + dwHeaderSize + colorused * 4;

    for ( int j = 0; j < dwHeight; ++j )
    {
      for ( int i = 0; i < dwWidth; ++i )
      {
        unsigned long* pPixel = (unsigned long*)( pBitmap + i * 3 + j * iLO * 3 ); 
//#pragma TODO( "umbauen, damits auch für andere screenbreiten passt" )

        // HIER BEKOMMST DU JEDEN EINZELNEN PIXELWERT!  

        // das würde die pixel buffern:  
        //        (WORD)*( (WORD*)(m_pFrontPage->data()) + i + ( dwHeight - j - 1 ) *  targetwidth ) = C24TO15( *pPixel );
      }
    }
  }

  DeleteObject( hBitmap );
  CloseClipboard();

  return TRUE;
}

void CChildView::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
  CaptureImage();
  StartCapture( hwndCapture_ );
	CWnd::OnLButtonDblClk(nFlags, point);
}

void CChildView::OnEditCopy() 
{
  CaptureImage();
  StartCapture( hwndCapture_ );
}
 
Super Danke!
Das mit dem einzelnen Bild klappt jetzt schon sehr gut!

Nur jetzt hab ich son dämliches Fenster auf dem Desktop rumliegen...
Wie bekomme ich das jetzt versteckt(evtl. TrayLeiste oder service)?
 
Zuletzt bearbeitet:
Ich kann dir im Moment auch nicht genau sagen, wie es geht -- keine Zeit, zu stöbern -- und paste hier einfach mal einen Schnipsel aus einer Dialoganwendung, die auch als Shell-Icon existierte:
Code:
// zeitdlg.cpp:

NOTIFYICONDATA nidIcon;

BYTE        *pSound       = NULL;
BYTE        *pSoundAlarm  = NULL;

#define UPDATEFILE "Q:\\Zeitverwaltung\\Zeit_Exe\\Zeit.exe"

extern CZeitApp theApp;

void CZeitDlg::MakeIcon()
{
  nidIcon.cbSize  = sizeof( NOTIFYICONDATA );
  nidIcon.hWnd    = GetSafeHwnd();
  TRACE( "nidIcon.hWnd %u\n", nidIcon.hWnd );
  nidIcon.uID     = 0;
  nidIcon.uFlags  = NIF_TIP | NIF_ICON | NIF_MESSAGE;
  nidIcon.uCallbackMessage = WM_NOTIFY_SIZER;
  nidIcon.hIcon = theApp.LoadIcon( MAKEINTRESOURCE( IDR_MAINFRAME ) );
  wsprintf( nidIcon.szTip, "Zeitverwaltung" );
  Shell_NotifyIcon( NIM_ADD, &nidIcon );
  ::DestroyIcon( nidIcon.hIcon );
}

void CZeitDlg::DestroyIcon()
{
  nidIcon.cbSize  = sizeof( NOTIFYICONDATA );
  nidIcon.hWnd    = GetSafeHwnd();
  TRACE( "nidIcon.hWnd %u\n", nidIcon.hWnd );
  nidIcon.uID     = 0;
  Shell_NotifyIcon( NIM_DELETE, &nidIcon );
}

CZeitDlg::CZeitDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CZeitDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CZeitDlg)
	//}}AFX_DATA_INIT
	
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

  Create(IDD);
}
Hoffentlich habe ich keine wichtige Stelle vergessen. Viel Glück!

Ach so, MakeIcon() wird in OnInitDialog aufgerufen.
 
Zuletzt bearbeitet:
Ein einfaches ShowWindow( SW_HIDE ) sollte das Fenster auch aus der Taskleiste verbannen.

Ansonsten dem Fenster zusätzlich den Stil WS_EX_TOOLWINDOW verpassen. Das zwingt Windows auch, das Fenster nicht in die Taskleiste zu kleben.
 

Neue Beiträge

Zurück