Dringede Hilfe...
-
Hi,
ich soll ein Kamera-Software-System implementieren.
Das Programm soll Bilder (Bitmaps)in Echtzeit aus einer Kamera
(über einen Frame-Grabber) liefern.Ich habe die Bild-Anzeige im Dialogfenster realisiert.
Nun das Problem ist, dass die Bild-Anzeige im ganzen Dialog-Fenster erfolgt
.Ich habe aber im selben Dialogfenster noch andere Elemente
(Buttons, Text-Felds etc.).
Meine Frage nun; wie kann ich die Bilder im Teil des Dialogfensters
und nicht im ganzen Fenster anzeigen?Soll ich die Bild-Anzeige mit einem Steuerungselement verbinden?
Wenn ja, welchen Typ soll das Steuerungselemt haben?
Und wie geht das?
Ich habe nicht viel Erfahrung mit MFC..
Momentan rufe ich in der OnInitDialog Funktion
die AfxBeginThread Funktion auf.
und so startet ein Thread für die Bild-Anzeige ..BOOL CPXC_GRAB_ImageDlg::OnInitDialog() { CDialog::OnInitDialog(); //erzeuge ein Thread und starte es AfxBeginThread(DisplayThreadProc, GetSafeHwnd(),THREAD_PRIORITY_ABOVE_NORMAL ); return TRUE; // return TRUE unless you set the focus to a control // AUSNAHME: OCX-Eigenschaftenseite muss FALSE zurückgeben. }Für jede Hilfe bin ich sehr sehr dankbar...
-
Du könntest die Bilder als Bitmap-Ressourcen im Ressourcen-Editor anlegen und dann mit
// Bitmap in PictureBox laden CBitmap bmpBitmap; bmpBitmap.LoadBitmap(ID_DES_BITMAPS); BITMAP bm; bmpBitmap.GetBitmap(&bm); CWnd* wnd = GetDlgItem(ID_DER_PICTUREBOX); CDC* pDC = wnd->GetDC(); CDC dcMem; dcMem.CreateCompatibleDC(pDC); dcMem.SelectObject(&bmpBitmap); CRect lRect; wnd->GetClientRect(&lRect); lRect.NormalizeRect(); pDC->StretchBlt(0,0,lRect.Width(),lRect.Height(),&dcMem,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);in einen Rahmen (PictureBox) laden. Die PictureBox ist im Ressourcen-Editor als 2. Element auf der Symbolleiste der Steuerelemente zu finden.
-
Ich danke Dir..
Nur das Problem ist, dass ich hier keine Bitmaps speichere und so diese laden kann.
Es ist wie laufender Video-Film.
Also ich weiss nicht, wie ich diese "Video-Anzeige" innerhalb des Dialogfensters mit einem Steuerungselement verbinden kann!!
Ich rufe ja die AfxBeginThread Funktion in der OnInitDialog Funktion und so startet ein Thread für die Video-Aufnahme.
Wie im Code gezeigt wurde.
Hier der Code noch einmalBOOL CPXC_GRAB_ImageDlg::OnInitDialog() { CDialog::OnInitDialog(); //erzeuge ein Thread und starte es AfxBeginThread(DisplayThreadProc, GetSafeHwnd(),THREAD_PRIORITY_ABOVE_NORMAL ); return TRUE; // return TRUE unless you set the focus to a control // AUSNAHME: OCX-Eigenschaftenseite muss FALSE zurückgeben. }Nun wie gesagt, man hat ja kein Bitmap-Objekt mit einer ID_,
sondern wird ein Thread gestartet und mit der Video-Aufnahme begonnen.
und diese "Thread-Funktion" rufe ich zur Zeit in OnInitDialog auf.
Also wie kann ich diese Funktion mit einem Steuerungselement verknüpfen!!?
Ich hoffe; die Problemstellung ist einigermaßen klar geworden.

-
Zeig mal den Teil wo der Thread das Bild darstellt.
-
Nur eine Idee..
Gehts vielleicht einfacher, wenn man innerhalb des Dialogs noch ein Dialog
(UnterDialog) erstellt, und dann diesem UnterDialog die Video-Anzeige zuordnet.
Würde es gehen? Wie?
-
UINT DisplayThreadProc(LPVOID pParam) { // LPVOID 32-Bit-Wert HDC hdc = GetDC((HWND) pParam); CPXC_DISPLAY display; static int iGrabIdx = 1; static int qidGrab[2]; iFrameCount = 0; bAcquire = TRUE; display.CreateDisplayBuffer(iImageX, iImageY, PIXEL_TYPE); for(;;) { if(!PXC_Error) { // Durchführung vom Thread anhalten if(::WaitForSingleObject(g_eventPause.m_hObject,0)==WAIT_OBJECT_0) ::WaitForSingleObject(g_eventContinue.m_hObject,INFINITE); if (GetKeyState(VK_LBUTTON) >= 0 && !PXC_Error) { // tausche den Index von 0 bis 1 oder umgekehrt aus iGrabIdx = (iGrabIdx == 1) ? 0 : 1; // Wenn es einen gültigen queue handle gibt, // überprüfe die Warteschlange auf ein abgeschlossenes Grabben. if(qidGrab[iGrabIdx]!= 0) { // Warte bis das Grabben beendet wird pxc.WaitFinished(hFG, qidGrab[iGrabIdx]); ++iFrameCount; qidGrab[iGrabIdx] = 0; } // Falls qidGrab leer ist, ein Grabben ist notwendig if(qidGrab[iGrabIdx] == 0) { qidGrab[iGrabIdx] = pxc.Grab(hFG, gpFrame[iGrabIdx], (short)iGrabType); } // display Frame display.ShowFrame(FrameLib, gpFrame[iGrabIdx], hdc, iImageX, iImageY, PIXEL_TYPE); } } // Thread beenden --> event g_eventStop if(::WaitForSingleObject(g_eventStop.m_hObject,0)==WAIT_OBJECT_0) break; } bAcquire = FALSE; return 0; // Thread-Ende }und hier die display.ShowFrame
void CPXC_DISPLAY::ShowFrame(FRAMELIB FrameLib, FRAME __PX_FAR *pFrame, HDC hdc, int iWidth, int iHeight, int iPixelType) { int i, iLen; BYTE *p; // Berechne die Länge iLen = iWidth * (((iPixelType & 0xFF) + 7) >> 3); // Image Zeile für Zeile vorm Anzeigen umdrehen p = gpBits; for(i=iHeight-1; i>=0; --i) { FrameLib.GetRow(pFrame, p, (short)i); p += iLen; } // Wenn es Grayscale ist, realiziere die Palette immer wenn angezeigt wird if(iPixelType == PBITS_Y8) GrayscalePalette(hdc, PXC_PALETTE_REALIZE); // SetDIBitsToDevice benötigt einen bitmap-header und einen Zeiger zum // Oberseite-Bild // Siehe MFC ::SetDIBitsToDevice( hdc, 0, 0, iWidth, iHeight, 0, 0, 0, iHeight, gpBits, (LPBITMAPINFO)&bmi, DIB_RGB_COLORS); }
-
Ich würde mal schätzen, das dein Livebild, vom Grabber auf alle Fälle Größer ist als dein angezeigter Dialog. Du brauchst doch lediglich bei SetDIBitsToDevice die Breite und Höhe des Zielbereiches anzupassen. Warum machst du dir überhaupt die Arbeit. Die meisten Framegrabber kommen doch mit einem schicken SDK vom Hersteller daher, wo man einfach mit den mitgelieferten Tools arbeitet und sich um solche Kram gar nicht ehr zu kümmern braucht.
-
Du hast recht TheBigW, aber es gibt spezielle features, die vom Hersteller nicht angeboten werden.
Ich es so gemacht, wie du mir gesagt hast, und es klappt.
Großes Danke..
Ich muss im selben Dialog neben der Video-Aufnahme eine Eizelbild-Aufnahme implementieren. Jetzt ist so, dass die Einzelbild-Aufnahme im selben "Fenster"
angezeigt wird, wo die Video-Aufnahme stattfindet.
Es soll aber wie gesagt, die Einzelbild-Aufnahme daneben angezeigt werden.
Ich habe es versucht, über die handle mit einem Steuerelement zu implementieren, aber haut nicht so richtig hin.
(GetDlgItem()) statt GetDC()void CPXC_GRAB_ImageDlg::OnAquireGrab() { CDC * pDC; if(grab.GetAquire()) { MessageBox("Für Einzel-Bildaufnahme soll zu erst die Video-Aufnahme gestoppt werden. Klicken Sie auf Aquirieren->Stoppen!", "PXC-Mitteilung", MB_OK); } else { grab.GrabImage(); pDC = GetDC(); //pDC = (CDC*) GetDlgItem(IDC_STAND_IMAGE); grab.ShowFrame(pDC); ReleaseDC(pDC); } }Weiß jemand, wie ich mit dem handle eines Steuerelementes verbinden kann??

Ich habe Steuerelement vom Typ CStatic...CStatic m_StandImage; // m_StandImage hat IDC_STAND_IMAGE
-
Das habe ich schon geschafft..
Wer sich interessiert, hier ist ein Code-Auszug..void CPXC_GRAB_ImageDlg::OnAquireGrab() { CDC * pImageCDC; /*if(grab.GetAquire()) { MessageBox("Für Einzel-Bildaufnahme sollen Sie die Video-Aufnahme stoppen. Klicken Sie auf Aquirieren->Stoppen!", "PXC-Mitteilung", MB_OK); } else {*/ grab.GrabImage(); m_pStandImage = (CStatic*)GetDlgItem(IDC_STAND_IMAGE); // Gerätekontext darauf holen pImageCDC = m_pStandImage->GetDC(); //pDC = GetDC(); //grab.ShowFrame(pDC); grab.ShowFrame(pImageCDC); ReleaseDC(pImageCDC); }Bleibt nur noch ein kleines Problem, und zwar, wie kann ich mein Bild an der Größe und Position des Steuerelements anpassen??
Danke im Vorraus
..
-
Warum nicht so?:
grab.GrabImage();
CDC* pDC = GetDlgItem(IDC_STAND_IMAGE)->GetDC();
grab.ShowFrame(pDC);
ReleaseDC(pDC);Nun zum wirkichen Problem: an Größe anpassen heißt ja, das du Pixel weglassen mußt. Wenn du das für ein Livebild selbst als Zoomfunktion realisieren willst ist das sehr Prozessorlastig.
Naiver Ansatz: Zoomfaktor von 50% heißt, jeder 2. Pixel wird weggelassen in x und y-Richtung - das mußt du dann für jedes Einzelbild tun. Das sollte aber beim SDK als fertige Funktion dabei sein (kenn zumindest keins, wo das nicht so ist). Darf man fragen, was es für ein Grabber ist?
-
Für das Live-Video bzw. Live-Bild brauche ich keine Anpassung.
Ich meine fürs Stand-Bild.
Ich habe ja ein Steuerelement mit dem die Anzeige des Standbildes verbunden ist.
Mein Stand-Bild wird nicht ganz richtig im Rahmen des Steuerelement angezeigt.
Meine Frage, wie kann ich zumindest die Position des Bildes anpassen, so es
richtig innerhalb des Rahmen angeziegt wird.
Oder auch umgekehrt, kann ich vielleicht das Steuerelement an Bild anpassen?Mein Framegrabber ist PXC200A von CyperOptics..
-
Oder auch umgekehrt, kann ich vielleicht das Steuerelement an Bild anpassen
Ja, wäre in Deinem Fall einfacher:
GetDlgItem(IDC_STAND_IMAGE)->MoveWindow( ... );
void MoveWindow( int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE );
-> Siehe MSDN