Domanda API controllo fotocamera

tuxon

Utente junior
8 Marzo 2018
20
3
3
milano
2016
1
Buonasera a tutti,
su una form sto implementando la possibilità di inserire foto prese dalla fotocamera (front o rear).

Uso un eseguibile (commandcam.exe) che richiamo con la sub sotto.

Visual Basic:
Private Sub CommandButton_PIC_Click()
    'ESISTE = Me.TextBox_controllo.Value
    'If ESISTE = "Waiting..." Then
    'MsgBox ("Item has to be loaded first")
    'Exit Sub
    'End If
    CommandButton_PIC.BackStyle = 1
    Dim RetVal
    Dim strName As String
    Dim strPath As String
    strName = "Image.bmp"
    ChDir (ThisWorkbook.Path & "\Foto")
    strPath = ThisWorkbook.Path & "\Foto"
    '/devnum 2 <------------------------------------------------------------- fotocamera posteriore "world"
    'RetVal = Shell("CommandCam.exe /devnum 2 /preview /delay 3000", vbHide)
    RetVal = Shell("CommandCam.exe /preview /delay 3000", vbHide)
    ' Wait until image file is definitely there
    While Dir(strName) <> "image.bmp"
    'While Dir(strName) = ""
    Wend
    Application.Wait (Now + TimeValue("00:00:01")) ' Short delay to let new file finish saving
 
    Data1 = Now()
    Data2 = Format(Data1, "yyyy.mm.dd_hh.mm.ss")
    Data4 = TextBoxITEM1.Caption
    Data22 = "Piano" & "_" & PIANO & "_" & "Item" & "_" & Data4 & "_" & rigacontrollo & "_" & foto & "_"
    Data3 = Data22 & Data2 & ".bmp"
    'MsgBox (Data3)
    'Set rngCell = ActiveCell
    Name strName As Data3
    strName = Data3
    'Me.Image1.Picture = LoadPicture(strPath & "\" & strName)
    Me.Controls("image" & foto).Picture = LoadPicture(strPath & "\" & strName)
    foto = foto + 1
    Exit Sub
 
    'CODICE PRECEDENTE PER INSERIMENTO IN CELLA
    colonnafoto = colonnazero + 10
    For i = 1 To 10
    If ActiveSheet.Cells(rigacontrollo, colonnafoto).Value = "X" Then
    colonnafoto = colonnafoto + 1
    End If
    Next
    Set rngCell = ActiveSheet.Cells(rigacontrollo, colonnafoto)
    ActiveSheet.Cells(rigacontrollo, colonnafoto).Value = "X"
    'Insert the picture
    On Error Resume Next
    ActiveSheet.Shapes(strName & rngCell.Address).Delete
    On Error GoTo 0
    ActiveSheet.Pictures.Insert(strPath & "\" & strName).Select
    Selection.Name = strName & rngCell.Address
    Selection.ShapeRange.Top = rngCell.Top
    Selection.ShapeRange.Left = rngCell.Left
    'scale the picture to the width of the column
    myScale = Application.Min(rngCell.Width / Selection.ShapeRange.Width, _
                              rngCell.Height / Selection.ShapeRange.Height)
    Selection.ShapeRange.ScaleWidth myScale, msoFalse, msoScaleFromTopLeft
    Selection.ShapeRange.IncrementLeft (rngCell.Width - Selection.ShapeRange.Width) / 2
    ActiveWorkbook.Save
    Application.Wait (Now + 0.00001)
    CommandButton_PIC.BackStyle = 0
End Sub

Con questo codice, su qualsiasi PC riesco ad aquisire foto da inserire su excel.
Il problema è che non posso scegliere io quando scattare, posso solo impostare un delay dopo il quale acquisisce l'immagine.
L'eseguibile Commandcam usa delle funzioni API, che credo si possano replicare su VBA.
Ho visto vecchi script che però funzionano solo su excel 32 bit (sulla 64 bit non funzionano neanche con l'upgrade del PTRSAFE function).

Mi servirebbe per poter vedere l'anteprima e poi scattare la foto.
Su VB6 ho un paio di codici che funzionano, ma solo su un PC, quando faccio i test su altri device a volte non funzionano.
Il commandcam invece funziona ovunque.
Pensate sia possibile implementare le API su excel, o inserire un pulsante "scatta"?


Ho fatto moltissimi tentativi tutti fallimentari.
Il codice dell'eseguibile è qua sotto.
C:
//
// CommandCam - A command line image grabber
// Copyright (C) 2012-2013 Ted Burke
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program (see the file "COPYING").
// If not, see <http://www.gnu.org/licenses/>.
//
// Website: https://batchloaf.wordpress.com
//
// To compile using the MSVC++ compiler:
//
//      cl CommandCam.cpp ole32.lib strmiids.lib oleaut32.lib
//
// Last modified 24-1-2013
//

// DirectShow header file
#include <dshow.h>

// This is a workaround for the missing header
// file qedit.h which seems to be absent from the
// Windows SDK versions 7.0 and 7.1.
// To use the items defined in this dll, the
// DexterLib namespace must be specified.
// The items in question are:
//
//      DexterLib::_AMMediaType
//      DexterLib::ISampleGrabber
//      DexterLib::IID_ISampleGrabber
//
#import "qedit.dll" raw_interfaces_only named_guids

// For some reason, these are not included in the
// DirectShow headers. However, they are exported
// by strmiids.lib, so I'm just declaring them
// here as extern.
EXTERN_C const CLSID CLSID_NullRenderer;
EXTERN_C const CLSID CLSID_SampleGrabber;

// DirectShow objects
HRESULT hr;
ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
IMoniker *pMoniker = NULL;
IPropertyBag *pPropBag = NULL;
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;
IBaseFilter *pCap = NULL;
IBaseFilter *pSampleGrabberFilter = NULL;
DexterLib::ISampleGrabber *pSampleGrabber = NULL;
IBaseFilter *pNullRenderer = NULL;
IMediaControl *pMediaControl = NULL;
char *pBuffer = NULL;

void exit_message(const char* error_message, int error)
{
    // Print an error message
    fprintf(stderr, error_message);
    fprintf(stderr, "\n");

    // Clean up DirectShow / COM stuff
    if (pBuffer != NULL) delete[] pBuffer;
    if (pMediaControl != NULL) pMediaControl->Release();
    if (pNullRenderer != NULL) pNullRenderer->Release();
    if (pSampleGrabber != NULL) pSampleGrabber->Release();
    if (pSampleGrabberFilter != NULL)
            pSampleGrabberFilter->Release();
    if (pCap != NULL) pCap->Release();
    if (pBuilder != NULL) pBuilder->Release();
    if (pGraph != NULL) pGraph->Release();
    if (pPropBag != NULL) pPropBag->Release();
    if (pMoniker != NULL) pMoniker->Release();
    if (pEnum != NULL) pEnum->Release();
    if (pDevEnum != NULL) pDevEnum->Release();
    CoUninitialize();

    // Exit the program
    exit(error);
}

int main(int argc, char **argv)
{
    // Capture settings
    int quiet = 0;
    int snapshot_delay = 2000;
    int show_preview_window = 0;
    int list_devices = 0;
    int list_devices_with_detail = 0;
    int device_number = 1;
    char device_name[255];
    char device_serial[255];
    char filename[255];

    // Other variables
    char char_buffer[100];

    // Default device name and output filename
    strcpy(device_name, "");
    strcpy(filename, "image.bmp");
 
    // First check if output messages should be suppressed
    int n;
    for (n=1 ; n < argc ; n++)
    {
        // Check next command line argument
        if (strcmp(argv[n], "/quiet") == 0)
        {
            // Enable preview window
            quiet = 1;
        }
    }
 
    // Information message
    if (!quiet)
    {
        fprintf(stdout, "\n");
        fprintf(stdout, "CommandCam  Copyright (C) 2012-2013 Ted Burke\n");
        fprintf(stdout, "This program comes with ABSOLUTELY NO WARRANTY;\n");
        fprintf(stdout, "This is free software, and you are welcome to\n");
        fprintf(stdout, "redistribute it under certain conditions;\n");
        fprintf(stdout, "See the GNU General Public License v3,\n");
        fprintf(stdout, "<http://www.gnu.org/licenses/gpl.txt>\n");
        fprintf(stdout, "\n");
        fprintf(stdout, "https://batchloaf.wordpress.com/CommandCam\n");
        fprintf(stdout, "This version 24-1-2013\n");
        fprintf(stdout, "\n");
    }
 
    // Parse command line arguments. Available options:
    //
    //      /delay DELAY_IN_MILLISECONDS
    //      /filename OUTPUT_FILENAME
    //      /devnum DEVICE_NUMBER
    //      /devname DEVICE_NAME
    //      /devserial DEVICE_SERIAL_NUMBER
    //      /preview
    //      /devlist
    //
    n = 1;
    while (n < argc)
    {
        // Process next command line argument
        if (strcmp(argv[n], "/quiet") == 0)
        {
            // This command line argument has already been
            // processed above, so just ignore it now.
        }
        else if (strcmp(argv[n], "/preview") == 0)
        {
            // Enable preview window
            show_preview_window = 1;
        }
        else if (strcmp(argv[n], "/devlist") == 0)
        {
            // Set flag to list devices rather than capture image
            list_devices = 1;
        }
        else if (strcmp(argv[n], "/devlistdetail") == 0)
        {
            // Set flag to list devices rather than capture image
            list_devices = 1;
            list_devices_with_detail = 1;
        }
        else if (strcmp(argv[n], "/filename") == 0)
        {
            // Set output filename to specified string
            if (++n < argc)
            {
                // Copy provided string into char buffer
                strcpy(char_buffer, argv[n]);

                // Trim inverted commas if present and copy
                // provided string into filename char array
                if (char_buffer[0] == '"')
                {
                    strncat(filename, char_buffer, strlen(char_buffer)-2);
                }
                else
                {
                    strcpy(filename, char_buffer);
                }
            }
            else exit_message("Error: no filename specified", 1);
        }
        else if (strcmp(argv[n], "/delay") == 0)
        {
            // Set snapshot delay to specified value
            if (++n < argc) snapshot_delay = atoi(argv[n]);
            else exit_message("Error: invalid delay specified", 2);

            if (snapshot_delay <= 0)
                exit_message("Error: invalid delay specified", 2);
        }
        else if (strcmp(argv[n], "/devnum") == 0)
        {
            // Set device number to specified value
            if (++n < argc) device_number = atoi(argv[n]);
            else exit_message("Error: invalid device number", 3);

            if (device_number <= 0)
                exit_message("Error: invalid device number", 3);
        }
        else if (strcmp(argv[n], "/devname") == 0)
        {
            // Set device number to specified value
            if (++n < argc)
            {
                // Copy device name into char buffer
                strcpy(char_buffer, argv[n]);

                // Trim inverted commas if present and copy
                // provided string into device_name
                if (char_buffer[0] == '"')
                {
                    strncat(device_name, char_buffer, strlen(char_buffer)-2);
                }
                else
                {
                    strcpy(device_name, char_buffer);
                }

                // Remember to choose by name rather than number
                device_number = 0;
            }
            else exit_message("Error: invalid device name", 4);
        }
        else if (strcmp(argv[n], "/devserial") == 0)
        {
            // Set device serial number to specified string
            if (++n < argc)
            {
                // Copy device name into char buffer
                strcpy(char_buffer, argv[n]);

                // Trim inverted commas if present and copy
                // provided string into device_serial
                if (char_buffer[0] == '"')
                {
                    strncat(device_serial, char_buffer, strlen(char_buffer)-2);
                }
                else
                {
                    strcpy(device_serial, char_buffer);
                }

                // Remember to choose by serial number rather than number
                device_number = 0;
            }
            else exit_message("Error: invalid device serial number", 5);
        }
        else
        {
            // Unknown command line argument
            fprintf(stderr, "Unrecognised option: %s\n", argv[n]);
            exit_message("", 6);
        }

        // Increment command line argument counter
        n++;
    }

    // Intialise COM
    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (hr != S_OK)
        exit_message("Could not initialise COM", 7);

    // Create filter graph
    hr = CoCreateInstance(CLSID_FilterGraph, NULL,
            CLSCTX_INPROC_SERVER, IID_IGraphBuilder,
            (void**)&pGraph);
    if (hr != S_OK)
        exit_message("Could not create filter graph", 8);

    // Create capture graph builder.
    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
            CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
            (void **)&pBuilder);
    if (hr != S_OK)
        exit_message("Could not create capture graph builder", 9);

    // Attach capture graph builder to graph
    hr = pBuilder->SetFiltergraph(pGraph);
    if (hr != S_OK)
        exit_message("Could not attach capture graph builder to graph", 10);

    // Create system device enumerator
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
            CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
    if (hr != S_OK)
        exit_message("Could not create system device enumerator", 11);

    // Video input device enumerator
    hr = pDevEnum->CreateClassEnumerator(
                    CLSID_VideoInputDeviceCategory, &pEnum, 0);
    if (hr != S_OK)
        exit_message("No video devices found", 12);

    // If the user has included the "/list" command line
    // argument, just list available devices, then exit.
    if (list_devices != 0)
    {
        if (!quiet) fprintf(stdout, "Available capture devices:\n");
        n = 0;
        while(1)
        {
            // Find next device
            hr = pEnum->Next(1, &pMoniker, NULL);
            if (hr == S_OK)
            {
                // Increment device counter
                n++;

                // Get device name
                hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
                VARIANT var;
                // Retrieve and print device name
                if (list_devices_with_detail)
                    if (!quiet) fprintf(stdout, "Capture device %d:\n", n);
                VariantInit(&var);
                hr = pPropBag->Read(L"FriendlyName", &var, 0);
                if (!quiet) fprintf(stdout, "  Device name: %ls\n", var.bstrVal);
                VariantClear(&var);
                // Retrieve and print device path
                if (list_devices_with_detail)
                {
                    VariantInit(&var);
                    hr = pPropBag->Read(L"DevicePath", &var, 0);
                    if (!quiet) fprintf(stdout, "  Device path: %ls\n\n", var.bstrVal);
                    VariantClear(&var);
                }
            }
            else
            {
                // Finished listing device, so exit program
                if (n == 0) exit_message("No devices found", 13);
                else exit_message("", 0);
            }
        }
    }

    // Get moniker for specified video input device,
    // or for the first device if no device number
    // was specified.
    VARIANT var;
    n = 0;
    while(1)
    {
        // Access next device
        hr = pEnum->Next(1, &pMoniker, NULL);
        if (hr == S_OK)
        {
            n++; // increment device count
        }
        else
        {
            if (device_number == 0)
            {
                fprintf(stderr,
                    "Video capture device %s not found\n",
                    device_name);
            }
            else
            {
                fprintf(stderr,
                    "Video capture device %d not found\n",
                    device_number);
            }
            exit_message("", 14);
        }

        // If device was specified by name or serial number...
        if (device_number == 0)
        {
            // Get video input device name
            hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
            if (hr == S_OK)
            {
                // Get current device name
                VariantInit(&var);
                hr = pPropBag->Read(L"FriendlyName", &var, 0);

                // Convert to a normal C string, i.e. char*
                sprintf(char_buffer, "%ls", var.bstrVal);
                VariantClear(&var);

                // Exit loop if current device name matched devname
                if (strcmp(device_name, char_buffer) == 0) break;

                // Get current device path
                VariantInit(&var);
                hr = pPropBag->Read(L"DevicePath", &var, 0);

                // Convert to a normal C string, i.e. char*
                sprintf(char_buffer, "%ls", var.bstrVal);
                VariantClear(&var);
             
                pPropBag->Release();
                pPropBag = NULL;

                // Exit loop if specified serial number appears in DevicePath
                if (strlen(device_serial) && strstr(char_buffer, device_serial)) break;
            }
            else
            {
                exit_message("Error getting device name and DevicePath", 15);
            }
        }
        else if (n >= device_number) break;
    }

    // Get video input device name
    hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
    VariantInit(&var);
    hr = pPropBag->Read(L"FriendlyName", &var, 0);
    if (!quiet) fprintf(stdout, "Capture device: %ls\n", var.bstrVal);
    VariantClear(&var);

    // Create capture filter and add to graph
    hr = pMoniker->BindToObject(0, 0,
                    IID_IBaseFilter, (void**)&pCap);
    if (hr != S_OK) exit_message("Could not create capture filter", 16);

    // Add capture filter to graph
    hr = pGraph->AddFilter(pCap, L"Capture Filter");
    if (hr != S_OK) exit_message("Could not add capture filter to graph", 17);

    // Create sample grabber filter
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL,
        CLSCTX_INPROC_SERVER, IID_IBaseFilter,
        (void**)&pSampleGrabberFilter);
    if (hr != S_OK)
        exit_message("Could not create Sample Grabber filter", 18);

    // Query the ISampleGrabber interface of the sample grabber filter
    hr = pSampleGrabberFilter->QueryInterface(
            DexterLib::IID_ISampleGrabber, (void**)&pSampleGrabber);
    if (hr != S_OK)
        exit_message("Could not get ISampleGrabber interface to sample grabber filter", 19);

    // Enable sample buffering in the sample grabber filter
    hr = pSampleGrabber->SetBufferSamples(TRUE);
    if (hr != S_OK)
        exit_message("Could not enable sample buffering in the sample grabber", 20);

    // Set media type in sample grabber filter
    AM_MEDIA_TYPE mt;
    ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
    mt.majortype = MEDIATYPE_Video;
    mt.subtype = MEDIASUBTYPE_RGB24;
    hr = pSampleGrabber->SetMediaType((DexterLib::_AMMediaType *)&mt);
    if (hr != S_OK)
        exit_message("Could not set media type in sample grabber", 21);

    // Add sample grabber filter to filter graph
    hr = pGraph->AddFilter(pSampleGrabberFilter, L"SampleGrab");
    if (hr != S_OK)
        exit_message("Could not add Sample Grabber to filter graph", 22);

    // Create Null Renderer filter
    hr = CoCreateInstance(CLSID_NullRenderer, NULL,
        CLSCTX_INPROC_SERVER, IID_IBaseFilter,
        (void**)&pNullRenderer);
    if (hr != S_OK)
        exit_message("Could not create Null Renderer filter", 23);

    // Add Null Renderer filter to filter graph
    hr = pGraph->AddFilter(pNullRenderer, L"NullRender");
    if (hr != S_OK)
        exit_message("Could not add Null Renderer to filter graph", 24);

    // Connect up the filter graph's capture stream
    hr = pBuilder->RenderStream(
        &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
        pCap,  pSampleGrabberFilter, pNullRenderer);
    if (hr != S_OK)
        exit_message("Could not render capture video stream", 25);

    // Connect up the filter graph's preview stream
    if (show_preview_window > 0)
    {
        hr = pBuilder->RenderStream(
                &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
                pCap, NULL, NULL);
        if (hr != S_OK && hr != VFW_S_NOPREVIEWPIN)
            exit_message("Could not render preview video stream", 26);
    }

    // Get media control interfaces to graph builder object
    hr = pGraph->QueryInterface(IID_IMediaControl,
                    (void**)&pMediaControl);
    if (hr != S_OK) exit_message("Could not get media control interface", 27);

    // Run graph
    while(1)
    {
        hr = pMediaControl->Run();

        // Hopefully, the return value was S_OK or S_FALSE
        if (hr == S_OK) break; // graph is now running
        if (hr == S_FALSE) continue; // graph still preparing to run

        // If the Run function returned something else,
        // there must be a problem
        fprintf(stderr, "Error: %u\n", hr);
        exit_message("Could not run filter graph", 28);
    }

    // Wait for specified time delay (if any)
    Sleep(snapshot_delay);

    // Grab a sample
    // First, find the required buffer size
    long buffer_size = 0;
    while(1)
    {
        // Passing in a NULL pointer signals that we're just checking
        // the required buffer size; not looking for actual data yet.
        hr = pSampleGrabber->GetCurrentBuffer(&buffer_size, NULL);

        // Keep trying until buffer_size is set to non-zero value.
        if (hr == S_OK && buffer_size != 0) break;

        // If the return value isn't S_OK or VFW_E_WRONG_STATE
        // then something has gone wrong. VFW_E_WRONG_STATE just
        // means that the filter graph is still starting up and
        // no data has arrived yet in the sample grabber filter.
        if (hr != S_OK && hr != VFW_E_WRONG_STATE)
            exit_message("Could not get buffer size", 29);
    }

    // Stop the graph
    pMediaControl->Stop();

    // Allocate buffer for image
    pBuffer = new char[buffer_size];
    if (!pBuffer)
        exit_message("Could not allocate data buffer for image", 30);

    // Retrieve image data from sample grabber buffer
    hr = pSampleGrabber->GetCurrentBuffer(
            &buffer_size, (long*)pBuffer);
    if (hr != S_OK)
        exit_message("Could not get buffer data from sample grabber", 31);

    // Get the media type from the sample grabber filter
    hr = pSampleGrabber->GetConnectedMediaType(
            (DexterLib::_AMMediaType *)&mt);
    if (hr != S_OK) exit_message("Could not get media type", 32);

    // Retrieve format information
    VIDEOINFOHEADER *pVih = NULL;
    if ((mt.formattype == FORMAT_VideoInfo) &&
        (mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
        (mt.pbFormat != NULL))
    {
        // Get video info header structure from media type
        pVih = (VIDEOINFOHEADER*)mt.pbFormat;

        // Print the resolution of the captured image
        if (!quiet) fprintf(stdout, "Capture resolution: %dx%d\n",
            pVih->bmiHeader.biWidth,
            pVih->bmiHeader.biHeight);

        // Create bitmap structure
        long cbBitmapInfoSize = mt.cbFormat - SIZE_PREHEADER;
        BITMAPFILEHEADER bfh;
        ZeroMemory(&bfh, sizeof(bfh));
        bfh.bfType = 'MB'; // Little-endian for "BM".
        bfh.bfSize = sizeof(bfh) + buffer_size + cbBitmapInfoSize;
        bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + cbBitmapInfoSize;

        // Open output file
        HANDLE hf = CreateFile(filename, GENERIC_WRITE,
                    FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
        if (hf == INVALID_HANDLE_VALUE)
            exit_message("Error opening output file", 33);

        // Write the file header.
        DWORD dwWritten = 0;
        WriteFile(hf, &bfh, sizeof(bfh), &dwWritten, NULL);
        WriteFile(hf, HEADER(pVih),
                    cbBitmapInfoSize, &dwWritten, NULL);

        // Write pixel data to file
        WriteFile(hf, pBuffer, buffer_size, &dwWritten, NULL);
        CloseHandle(hf);
    }
    else
    {
        exit_message("Wrong media type", 34);
    }

    // Free the format block
    if (mt.cbFormat != 0)
    {
        CoTaskMemFree((PVOID)mt.pbFormat);
        mt.cbFormat = 0;
        mt.pbFormat = NULL;
    }
    if (mt.pUnk != NULL)
    {
        // pUnk should not be used.
        mt.pUnk->Release();
        mt.pUnk = NULL;
    }

    // Clean up and exit
    if (!quiet) fprintf(stdout, "Captured image to %s", filename);
    exit_message("", 0);
}
 

giulianovac

Access/VBA Expert
Expert
9 Giugno 2018
1.675
304
83
Italy
2013 2019
122
Ma quello è il codice scritto in C++.
Immagino tu abbia anche l'eseguibile, il che sarebbe utile per fare dei test.

Ci do un'occhiata, ma non prometto niente...
 

giulianovac

Access/VBA Expert
Expert
9 Giugno 2018
1.675
304
83
Italy
2013 2019
122
Mi servirebbe per poter vedere l'anteprima e poi scattare la foto.
Da quello che ho visto qui:
non credo sia possibile, o per meglio puoi scattare la foto, poi magari visualizzarla con un programma di visualizzazione, e poi decidere se usarla o meno.

Puoi fare il /Preview, ma poi se scatti in un secondo momento l'immagine quasi sicuramente è cambiata.

Puoi cercare un alternativa
che permetta l'anteprima prima di scattare, ma non so se esiste un programma del genere.

In teoria potresti utilizzare il software stesso della webcam.
 

muni

Utente junior
25 Novembre 2018
58
6
8
2013
0
Io potrei modificare il codice C e ricompilarlo secondo le tue esigenze ma, come ti hanno detto, se fai una preview, non è detto che la foto successiva non sia cambiata. E poi scusa, se non imposti il ritardo, esegui uno scatto immediato. Non è quello che ti serve? O non ho capito cosa vorresti ...
 

tuxon

Utente junior
8 Marzo 2018
20
3
3
milano
2016
1
Ciao ragazzi,
vi allego l'excel che scatta le foto con il commandcam.

Nel periodo della preview l'immagine non è statica.
Per ora sto approfittando di un delay di 3 secondi (nell'allegato l'ho messo a 1) per "mettere a fuoco" , cercare di star fermo, e scattare.

E' un po' scomodo.

PS: non mi lascia allegare l'exe.
E' qua:
 

Allegati

tuxon

Utente junior
8 Marzo 2018
20
3
3
milano
2016
1
Mi scuso per il doppio post ma non posso più editare e mancava un'informazione.
M @muni con lo scatto immediato non vedo di preciso cosa fotografo, poi ci mette sempre un paio di secondi a mettere a fuoco
 

muni

Utente junior
25 Novembre 2018
58
6
8
2013
0
Quindi? Non ho capito come poterti aiutare spiegati meglio. Ti ripeto che si può anche modificare il sorgente C e ricompilarlo.
 

tuxon

Utente junior
8 Marzo 2018
20
3
3
milano
2016
1
Se fosse possibile, al posto del delay, ci vorrebbe un comando "scatta".

Ora lui fa:
Start
Anteprima dinamica in una finestra
Delay 3 secondi
Scatta in automatico

Servirebbe:
Start
Anteprima dinamica in una finestra
Scatto richiamato da comando

Non so se sia possibile mettere un pulsante di scatto sulla finestra di anteprima dell'exe, altrimenti lo metto sulla userform excel
 

cromagno

Excel/VBA Expert
Supermoderatore
Expert
9 Agosto 2015
6.369
365
83
39
Sardegna
2013 (64 bit)
189
Ciao a tutti,
ho scaricato il file allegato ma per poter funzionare dovrei scaricare anche "CommandCam.exe" (e non mi va visto che non mi servirebbe a nulla).... comunque, io non vedo il problema...
Il "Delay" è espresso in millisecondi, quindi impostalo a 1 (o a zero se lo permette) ed avrai uno scatto (quasi) istantaneo... o mi son perso qualche passaggio? :dubbioso:
 

muni

Utente junior
25 Novembre 2018
58
6
8
2013
0
Lo scatto non lo vuole istantaneo ma a comando dopo aver visto l'anteprima.

T @tuxon ... avrei una soluzione implementata a 32 bit ... se usi 64 bit non dovresti avere difficoltà a fare le piccole modifiche ... ma non posso provarla dato che non ho a disposizione il device.

Ti basta il sorgente C++ (e te lo ricompili) o vorresti il .exe ?
 

tuxon

Utente junior
8 Marzo 2018
20
3
3
milano
2016
1
Ciao cromagno @cromagno , avevo fatto dei tentativi ma erano usciti un po' di problemi.
Con delay 0 non vedo cosa sto realmente fotografando, uscivano male le foto
Con delay basso, se la zona da fotografare non è esatta (a volte devo fare le foto alle targhette matricolari degli impianti) e muovo il device, a volte non mette a fuoco in tempo

M @muni ciao, preferirei testare l'exe, non sono molto esperto in compilazione
 

muni

Utente junior
25 Novembre 2018
58
6
8
2013
0
L'idea è questa

1) aggiungere lo switch /shot al programma C++ per attivare la gestione dell'attesa di conferma da parte del processo Excel dopo l'anteprima

2) l'attesa di conferma si basa sull'attivazione di un "named event" che imposterai con tre linee (e qualche API) da Excel quando vorrai scattare

Quindi nel file Excel dovresti avere una prima fase (con un primo button) in cui lanci l'eseguibile per la preview in modalità shot

Codice:
RetVal = Shell("CommandCam.exe  /preview  /shot", vbHide)
così dovresti vedere l'anteprima e il programma dovrebbe attendere.

Poi una seconda fase, quando sarai pronto per lo scatto, userai un secondo button in cui esegui le 3 linee che danno il comando di proseguire per lo scatto; poi tutto il resto del codice che già hai per il trattamento del file, ovvero

Codice:
Private Declare Function CreateEvent Lib "kernel32" Alias "CreateEventA" (lpEventAttributes As Long, ByVal bManualReset As Long, ByVal bInitialState As Long, ByVal lpName As String) As Long
Private Declare Function SetEvent Lib "kernel32" (ByVal hEvent As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Codice:
    Dim hEvent As Long
  
    hEvent = CreateEvent(0, True, False, "CamEvent")
    SetEvent hEvent
    CloseHandle hEvent

.... gestione file immagine scattata ...
NON ho potuto fare delle prove reali. Quindi dimmi se qualcosa non va e vediamo.

Il sorgente C++ "modificato" è questo

Codice:
// CommandCam.cpp : definisce il punto di ingresso dell'applicazione console.
//

#include "stdafx.h"

#pragma warning(disable:4996)

#pragma comment(lib, "strmiids")

//
// CommandCam - A command line image grabber
// Copyright (C) 2012-2013 Ted Burke
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program (see the file "COPYING").
// If not, see <http://www.gnu.org/licenses/>.
//
// Website: https://batchloaf.wordpress.com
//
// To compile using the MSVC++ compiler:
//
//      cl CommandCam.cpp ole32.lib strmiids.lib oleaut32.lib
//
// Last modified 24-1-2013
//

// DirectShow header file
#include <dshow.h>

// This is a workaround for the missing header
// file qedit.h which seems to be absent from the
// Windows SDK versions 7.0 and 7.1.
// To use the items defined in this dll, the
// DexterLib namespace must be specified.
// The items in question are:
//
//      DexterLib::_AMMediaType
//      DexterLib::ISampleGrabber
//      DexterLib::IID_ISampleGrabber
//
#import "qedit.dll" raw_interfaces_only named_guids

// For some reason, these are not included in the
// DirectShow headers. However, they are exported
// by strmiids.lib, so I'm just declaring them
// here as extern.
EXTERN_C const CLSID CLSID_NullRenderer;
EXTERN_C const CLSID CLSID_SampleGrabber;

// DirectShow objects
HRESULT hr;
ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
IMoniker *pMoniker = NULL;
IPropertyBag *pPropBag = NULL;
IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;
IBaseFilter *pCap = NULL;
IBaseFilter *pSampleGrabberFilter = NULL;
DexterLib::ISampleGrabber *pSampleGrabber = NULL;
IBaseFilter *pNullRenderer = NULL;
IMediaControl *pMediaControl = NULL;
char *pBuffer = NULL;

void exit_message(const char* error_message, int error)
{
    // Print an error message
    fprintf(stderr, error_message);
    fprintf(stderr, "\n");

    // Clean up DirectShow / COM stuff
    if (pBuffer != NULL) delete[] pBuffer;
    if (pMediaControl != NULL) pMediaControl->Release();
    if (pNullRenderer != NULL) pNullRenderer->Release();
    if (pSampleGrabber != NULL) pSampleGrabber->Release();
    if (pSampleGrabberFilter != NULL)
        pSampleGrabberFilter->Release();
    if (pCap != NULL) pCap->Release();
    if (pBuilder != NULL) pBuilder->Release();
    if (pGraph != NULL) pGraph->Release();
    if (pPropBag != NULL) pPropBag->Release();
    if (pMoniker != NULL) pMoniker->Release();
    if (pEnum != NULL) pEnum->Release();
    if (pDevEnum != NULL) pDevEnum->Release();
    CoUninitialize();

    // Exit the program
    exit(error);
}

int main(int argc, char **argv)
{
    // Capture settings
    int shotmode = 0;
    int quiet = 0;
    int snapshot_delay = 2000;
    int show_preview_window = 0;
    int list_devices = 0;
    int list_devices_with_detail = 0;
    int device_number = 1;
    char device_name[255];
    char device_serial[255];
    char filename[255];

    // Other variables
    char char_buffer[100];

    // Default device name and output filename
    strcpy(device_name, "");
    strcpy(filename, "image.bmp");

    // First check if output messages should be suppressed
    int n;
    for (n = 1; n < argc; n++)
    {
        // Check next command line argument
        if (strcmp(argv[n], "/quiet") == 0)
        {
            // Enable preview window
            quiet = 1;
        }
    }

    // Information message
    if (!quiet)
    {
        fprintf(stdout, "\n");
        fprintf(stdout, "CommandCam  Copyright (C) 2012-2013 Ted Burke\n");
        fprintf(stdout, "This program comes with ABSOLUTELY NO WARRANTY;\n");
        fprintf(stdout, "This is free software, and you are welcome to\n");
        fprintf(stdout, "redistribute it under certain conditions;\n");
        fprintf(stdout, "See the GNU General Public License v3,\n");
        fprintf(stdout, "<http://www.gnu.org/licenses/gpl.txt>\n");
        fprintf(stdout, "\n");
        fprintf(stdout, "https://batchloaf.wordpress.com/CommandCam\n");
        fprintf(stdout, "This version 24-1-2013\n");
        fprintf(stdout, "\n");
    }

    // Parse command line arguments. Available options:
    //
    //        /shot (AG 12/07/2019)
    //
    //      /delay DELAY_IN_MILLISECONDS
    //      /filename OUTPUT_FILENAME
    //      /devnum DEVICE_NUMBER
    //      /devname DEVICE_NAME
    //      /devserial DEVICE_SERIAL_NUMBER
    //      /preview
    //      /devlist
    //
    n = 1;
    while (n < argc)
    {
        // Process next command line argument
        if (strcmp(argv[n], "/quiet") == 0)
        {
            // This command line argument has already been
            // processed above, so just ignore it now.
        }
        else if (strcmp(argv[n], "/preview") == 0)
        {
            // Enable preview window
            show_preview_window = 1;
        }
        else if (strcmp(argv[n], "/devlist") == 0)
        {
            // Set flag to list devices rather than capture image
            list_devices = 1;
        }
        else if (strcmp(argv[n], "/devlistdetail") == 0)
        {
            // Set flag to list devices rather than capture image
            list_devices = 1;
            list_devices_with_detail = 1;
        }
        else if (strcmp(argv[n], "/filename") == 0)
        {
            // Set output filename to specified string
            if (++n < argc)
            {
                // Copy provided string into char buffer
                strcpy(char_buffer, argv[n]);

                // Trim inverted commas if present and copy
                // provided string into filename char array
                if (char_buffer[0] == '"')
                {
                    strncat(filename, char_buffer, strlen(char_buffer) - 2);
                }
                else
                {
                    strcpy(filename, char_buffer);
                }
            }
            else exit_message("Error: no filename specified", 1);
        }
        //
        else if (strcmp(argv[n], "/shot") == 0)
        {
            // Set shot mode
            shotmode = 1;
        }
        //
        else if (strcmp(argv[n], "/delay") == 0)
        {
            // Set snapshot delay to specified value
            if (++n < argc) snapshot_delay = atoi(argv[n]);
            else exit_message("Error: invalid delay specified", 2);

            if (snapshot_delay <= 0)
                exit_message("Error: invalid delay specified", 2);
        }
        else if (strcmp(argv[n], "/devnum") == 0)
        {
            // Set device number to specified value
            if (++n < argc) device_number = atoi(argv[n]);
            else exit_message("Error: invalid device number", 3);

            if (device_number <= 0)
                exit_message("Error: invalid device number", 3);
        }
        else if (strcmp(argv[n], "/devname") == 0)
        {
            // Set device number to specified value
            if (++n < argc)
            {
                // Copy device name into char buffer
                strcpy(char_buffer, argv[n]);

                // Trim inverted commas if present and copy
                // provided string into device_name
                if (char_buffer[0] == '"')
                {
                    strncat(device_name, char_buffer, strlen(char_buffer) - 2);
                }
                else
                {
                    strcpy(device_name, char_buffer);
                }

                // Remember to choose by name rather than number
                device_number = 0;
            }
            else exit_message("Error: invalid device name", 4);
        }
        else if (strcmp(argv[n], "/devserial") == 0)
        {
            // Set device serial number to specified string
            if (++n < argc)
            {
                // Copy device name into char buffer
                strcpy(char_buffer, argv[n]);

                // Trim inverted commas if present and copy
                // provided string into device_serial
                if (char_buffer[0] == '"')
                {
                    strncat(device_serial, char_buffer, strlen(char_buffer) - 2);
                }
                else
                {
                    strcpy(device_serial, char_buffer);
                }

                // Remember to choose by serial number rather than number
                device_number = 0;
            }
            else exit_message("Error: invalid device serial number", 5);
        }
        else
        {
            // Unknown command line argument
            fprintf(stderr, "Unrecognised option: %s\n", argv[n]);
            exit_message("", 6);
        }

        // Increment command line argument counter
        n++;
    }

    // Intialise COM
    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (hr != S_OK)
        exit_message("Could not initialise COM", 7);

    // Create filter graph
    hr = CoCreateInstance(CLSID_FilterGraph, NULL,
        CLSCTX_INPROC_SERVER, IID_IGraphBuilder,
        (void**)&pGraph);
    if (hr != S_OK)
        exit_message("Could not create filter graph", 8);

    // Create capture graph builder.
    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
        CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2,
        (void **)&pBuilder);
    if (hr != S_OK)
        exit_message("Could not create capture graph builder", 9);

    // Attach capture graph builder to graph
    hr = pBuilder->SetFiltergraph(pGraph);
    if (hr != S_OK)
        exit_message("Could not attach capture graph builder to graph", 10);

    // Create system device enumerator
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
        CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum));
    if (hr != S_OK)
        exit_message("Could not create system device enumerator", 11);

    // Video input device enumerator
    hr = pDevEnum->CreateClassEnumerator(
        CLSID_VideoInputDeviceCategory, &pEnum, 0);
    if (hr != S_OK)
        exit_message("No video devices found", 12);

    // If the user has included the "/list" command line
    // argument, just list available devices, then exit.
    if (list_devices != 0)
    {
        if (!quiet) fprintf(stdout, "Available capture devices:\n");
        n = 0;
        while (1)
        {
            // Find next device
            hr = pEnum->Next(1, &pMoniker, NULL);
            if (hr == S_OK)
            {
                // Increment device counter
                n++;

                // Get device name
                hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
                VARIANT var;
                // Retrieve and print device name
                if (list_devices_with_detail)
                    if (!quiet) fprintf(stdout, "Capture device %d:\n", n);
                VariantInit(&var);
                hr = pPropBag->Read(L"FriendlyName", &var, 0);
                if (!quiet) fprintf(stdout, "  Device name: %ls\n", var.bstrVal);
                VariantClear(&var);
                // Retrieve and print device path
                if (list_devices_with_detail)
                {
                    VariantInit(&var);
                    hr = pPropBag->Read(L"DevicePath", &var, 0);
                    if (!quiet) fprintf(stdout, "  Device path: %ls\n\n", var.bstrVal);
                    VariantClear(&var);
                }
            }
            else
            {
                // Finished listing device, so exit program
                if (n == 0) exit_message("No devices found", 13);
                else exit_message("", 0);
            }
        }
    }

    // Get moniker for specified video input device,
    // or for the first device if no device number
    // was specified.
    VARIANT var;
    n = 0;
    while (1)
    {
        // Access next device
        hr = pEnum->Next(1, &pMoniker, NULL);
        if (hr == S_OK)
        {
            n++; // increment device count
        }
        else
        {
            if (device_number == 0)
            {
                fprintf(stderr,
                    "Video capture device %s not found\n",
                    device_name);
            }
            else
            {
                fprintf(stderr,
                    "Video capture device %d not found\n",
                    device_number);
            }
            exit_message("", 14);
        }

        // If device was specified by name or serial number...
        if (device_number == 0)
        {
            // Get video input device name
            hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
            if (hr == S_OK)
            {
                // Get current device name
                VariantInit(&var);
                hr = pPropBag->Read(L"FriendlyName", &var, 0);

                // Convert to a normal C string, i.e. char*
                sprintf(char_buffer, "%ls", var.bstrVal);
                VariantClear(&var);

                // Exit loop if current device name matched devname
                if (strcmp(device_name, char_buffer) == 0) break;

                // Get current device path
                VariantInit(&var);
                hr = pPropBag->Read(L"DevicePath", &var, 0);

                // Convert to a normal C string, i.e. char*
                sprintf(char_buffer, "%ls", var.bstrVal);
                VariantClear(&var);

                pPropBag->Release();
                pPropBag = NULL;

                // Exit loop if specified serial number appears in DevicePath
                if (strlen(device_serial) && strstr(char_buffer, device_serial)) break;
            }
            else
            {
                exit_message("Error getting device name and DevicePath", 15);
            }
        }
        else if (n >= device_number) break;
    }

    // Get video input device name
    hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));
    VariantInit(&var);
    hr = pPropBag->Read(L"FriendlyName", &var, 0);
    if (!quiet) fprintf(stdout, "Capture device: %ls\n", var.bstrVal);
    VariantClear(&var);

    // Create capture filter and add to graph
    hr = pMoniker->BindToObject(0, 0,
        IID_IBaseFilter, (void**)&pCap);
    if (hr != S_OK) exit_message("Could not create capture filter", 16);

    // Add capture filter to graph
    hr = pGraph->AddFilter(pCap, L"Capture Filter");
    if (hr != S_OK) exit_message("Could not add capture filter to graph", 17);

    // Create sample grabber filter
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL,
        CLSCTX_INPROC_SERVER, IID_IBaseFilter,
        (void**)&pSampleGrabberFilter);
    if (hr != S_OK)
        exit_message("Could not create Sample Grabber filter", 18);

    // Query the ISampleGrabber interface of the sample grabber filter
    hr = pSampleGrabberFilter->QueryInterface(
        DexterLib::IID_ISampleGrabber, (void**)&pSampleGrabber);
    if (hr != S_OK)
        exit_message("Could not get ISampleGrabber interface to sample grabber filter", 19);

    // Enable sample buffering in the sample grabber filter
    hr = pSampleGrabber->SetBufferSamples(TRUE);
    if (hr != S_OK)
        exit_message("Could not enable sample buffering in the sample grabber", 20);

    // Set media type in sample grabber filter
    AM_MEDIA_TYPE mt;
    ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
    mt.majortype = MEDIATYPE_Video;
    mt.subtype = MEDIASUBTYPE_RGB24;
    hr = pSampleGrabber->SetMediaType((DexterLib::_AMMediaType *)&mt);
    if (hr != S_OK)
        exit_message("Could not set media type in sample grabber", 21);

    // Add sample grabber filter to filter graph
    hr = pGraph->AddFilter(pSampleGrabberFilter, L"SampleGrab");
    if (hr != S_OK)
        exit_message("Could not add Sample Grabber to filter graph", 22);

    // Create Null Renderer filter
    hr = CoCreateInstance(CLSID_NullRenderer, NULL,
        CLSCTX_INPROC_SERVER, IID_IBaseFilter,
        (void**)&pNullRenderer);
    if (hr != S_OK)
        exit_message("Could not create Null Renderer filter", 23);

    // Add Null Renderer filter to filter graph
    hr = pGraph->AddFilter(pNullRenderer, L"NullRender");
    if (hr != S_OK)
        exit_message("Could not add Null Renderer to filter graph", 24);

    // Connect up the filter graph's capture stream
    hr = pBuilder->RenderStream(
        &PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
        pCap, pSampleGrabberFilter, pNullRenderer);
    if (hr != S_OK)
        exit_message("Could not render capture video stream", 25);

    // Connect up the filter graph's preview stream
    if (show_preview_window > 0)
    {
        hr = pBuilder->RenderStream(
            &PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
            pCap, NULL, NULL);
        if (hr != S_OK && hr != VFW_S_NOPREVIEWPIN)
            exit_message("Could not render preview video stream", 26);
    }

    // Get media control interfaces to graph builder object
    hr = pGraph->QueryInterface(IID_IMediaControl,
        (void**)&pMediaControl);
    if (hr != S_OK) exit_message("Could not get media control interface", 27);

    // Run graph
    while (1)
    {
        hr = pMediaControl->Run();

        // Hopefully, the return value was S_OK or S_FALSE
        if (hr == S_OK) break; // graph is now running
        if (hr == S_FALSE) continue; // graph still preparing to run

                                     // If the Run function returned something else,
                                     // there must be a problem
        fprintf(stderr, "Error: %u\n", hr);
        exit_message("Could not run filter graph", 28);
    }

    // Shot mode ore delay
    if (shotmode)
    {
        HANDLE ghCamEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("CamEvent"));
        DWORD dwWaitResult = WaitForSingleObject(ghCamEvent, INFINITE);
        CloseHandle(ghCamEvent);
    }
    else
        // Wait for specified time delay (if any)
        Sleep(snapshot_delay);

    // Grab a sample
    // First, find the required buffer size
    long buffer_size = 0;
    while (1)
    {
        // Passing in a NULL pointer signals that we're just checking
        // the required buffer size; not looking for actual data yet.
        hr = pSampleGrabber->GetCurrentBuffer(&buffer_size, NULL);

        // Keep trying until buffer_size is set to non-zero value.
        if (hr == S_OK && buffer_size != 0) break;

        // If the return value isn't S_OK or VFW_E_WRONG_STATE
        // then something has gone wrong. VFW_E_WRONG_STATE just
        // means that the filter graph is still starting up and
        // no data has arrived yet in the sample grabber filter.
        if (hr != S_OK && hr != VFW_E_WRONG_STATE)
            exit_message("Could not get buffer size", 29);
    }

    // Stop the graph
    pMediaControl->Stop();

    // Allocate buffer for image
    pBuffer = new char[buffer_size];
    if (!pBuffer)
        exit_message("Could not allocate data buffer for image", 30);

    // Retrieve image data from sample grabber buffer
    hr = pSampleGrabber->GetCurrentBuffer(
        &buffer_size, (long*)pBuffer);
    if (hr != S_OK)
        exit_message("Could not get buffer data from sample grabber", 31);

    // Get the media type from the sample grabber filter
    hr = pSampleGrabber->GetConnectedMediaType(
        (DexterLib::_AMMediaType *)&mt);
    if (hr != S_OK) exit_message("Could not get media type", 32);

    // Retrieve format information
    VIDEOINFOHEADER *pVih = NULL;
    if ((mt.formattype == FORMAT_VideoInfo) &&
        (mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
        (mt.pbFormat != NULL))
    {
        // Get video info header structure from media type
        pVih = (VIDEOINFOHEADER*)mt.pbFormat;

        // Print the resolution of the captured image
        if (!quiet) fprintf(stdout, "Capture resolution: %dx%d\n",
            pVih->bmiHeader.biWidth,
            pVih->bmiHeader.biHeight);

        // Create bitmap structure
        long cbBitmapInfoSize = mt.cbFormat - SIZE_PREHEADER;
        BITMAPFILEHEADER bfh;
        ZeroMemory(&bfh, sizeof(bfh));
        bfh.bfType = 'MB'; // Little-endian for "BM".
        bfh.bfSize = sizeof(bfh) + buffer_size + cbBitmapInfoSize;
        bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + cbBitmapInfoSize;

        // Open output file
        HANDLE hf = CreateFile(filename, GENERIC_WRITE,
            FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
        if (hf == INVALID_HANDLE_VALUE)
            exit_message("Error opening output file", 33);

        // Write the file header.
        DWORD dwWritten = 0;
        WriteFile(hf, &bfh, sizeof(bfh), &dwWritten, NULL);
        WriteFile(hf, HEADER(pVih),
            cbBitmapInfoSize, &dwWritten, NULL);

        // Write pixel data to file
        WriteFile(hf, pBuffer, buffer_size, &dwWritten, NULL);
        CloseHandle(hf);
    }
    else
    {
        exit_message("Wrong media type", 34);
    }

    // Free the format block
    if (mt.cbFormat != 0)
    {
        CoTaskMemFree((PVOID)mt.pbFormat);
        mt.cbFormat = 0;
        mt.pbFormat = NULL;
    }
    if (mt.pUnk != NULL)
    {
        // pUnk should not be used.
        mt.pUnk->Release();
        mt.pUnk = NULL;
    }

    // Clean up and exit
    if (!quiet) fprintf(stdout, "Captured image to %s", filename);
    exit_message("", 0);
}


NOTA: per caricare l'eseguibile ho aggiunto l'estensione .xls ... tu lo rinomini in modo che si chiami CommandCam.exe
 

Allegati

tuxon

Utente junior
8 Marzo 2018
20
3
3
milano
2016
1
giulianovac @giulianovac ciao Giuliano, uso le fotocamere integrate dei device (front e rear).
Ho già fatto delle prove con i comandi API ma non sono mai riuscito a farli funzionare.

Inoltre VBA non può interagire con la fotocamera se questa è già aperta dalla sua applicazione di Windows (nel senso che se apro l'applicazione fotocamera, e poi uso il commandcam, dà errore, idem per le funzioni API excel)

Bisogna richiamare le DLL (tipo la AVICAP) con codici come quelli sotto.
Ne ho provati moltissimi ma non ce ne sono di funzionanti.

Visual Basic:
Private Const WM_CAP_DRIVER_CONNECT As Long = 1034
Private Const WM_CAP_GRAB_FRAME As Long = 1084
Private Const WM_CAP_EDIT_COPY As Long = 1054
Private Const WM_CAP_DRIVER_DISCONNECT = 1035
Private Const WM_CAP_SEQUENCE = 1086
Private Const WM_CAP_GET_SEQUENCE_SETUP = 1089
Private Const WM_CAP_SET_SEQUENCE_SETUP = 1088
Private Const WM_CAP_FILE_SET_CAPTURE_FILE = 1044
Private Const WM_CAP_DLG_VIDEOSOURCE = 1066
Private Const WM_CAP_FILE_SAVEAS = 1047
Private Const WM_CAP_STOP = 1092


Visual Basic:
Option Explicit

Const WM_CAP As Long = &H400
Const WM_CAP_DRIVER_CONNECT As Long = WM_CAP + 10
Const WM_CAP_DRIVER_DISCONNECT As Long = WM_CAP + 11
Const WM_CAP_SAVEDIB = WM_CAP + 25
Const WM_CAP_EDIT_COPY As Long = WM_CAP + 30
Const WM_CAP_SET_PREVIEW As Long = WM_CAP + 50
Const WM_CAP_DLG_VIDEOFORMAT = WM_CAP + 41
Const WM_CAP_DLG_VIDEOSOURCE = WM_CAP + 42
Const WM_CAP_DLG_VIDEODISPLAY = WM_CAP + 43
Const WM_CAP_GET_VIDEOFORMAT = WM_CAP + 44
Const WM_CAP_SET_VIDEOFORMAT = WM_CAP + 45
Const WM_CAP_DLG_VIDEOCOMPRESSION = WM_CAP + 46
Const WM_CAP_SET_PREVIEWRATE = WM_CAP + 52
Const WM_CAP_SET_SCALE = WM_CAP + 53
Const WM_CAP_GRAB_FRAME = WM_CAP + 60
Const WM_CAP_GRAB_FRAME_NOSTOP = WM_CAP + 61
Const WM_CAP_STOP = WM_CAP + 68
Const WM_CLOSE = &H10
Const WM_DESTROY = &H2
Const WM_NCDESTROY = &H82
Const WM_QUIT = &H12

Const WS_CHILD As Long = &H40000000
Const WS_VISIBLE As Long = &H10000000
Const WS_POPUP As Long = &H80000000
Const HWND_BOTTOM As Long = 1
Const SWP_NOMOVE As Long = &H2
Public hWnd As Long
Declare Function TerminateProcess Lib "kernel32" (ByVal hProcess As Long, ByVal uExitCode As Long) As Long
Declare Function DestroyWindow Lib "user32" (ByVal hndw As Long) As Boolean
Declare Function GetDesktopWindow Lib "user32" () As Long
Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
   (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
 
Declare Function capCreateCaptureWindowA Lib "avicap32.dll" _
  (ByVal lpszWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, _
  ByVal nHeight As Long, ByVal hWndParent As Long, ByVal nID As Long) As Long
Declare Function capGetDriverDescriptionA Lib "avicap32.dll" _
  (ByVal wDriver As Long, ByVal lpszName As String, _
  ByVal cbName As Long, ByVal lpszVer As String, ByVal cbVer As Long) As Boolean

 
Sub WebCamClip()

  hWnd = 0
 
   If hWnd = 0 Then
  hWnd = capCreateCaptureWindowA("enwèye dont", WS_VISIBLE, 0, 0, 200, 200, GetDesktopWindow(), 0)
  SendMessage hWnd, WM_CAP_DRIVER_CONNECT, 0, 0
  SendMessage hWnd, WM_CAP_SET_PREVIEWRATE, 30, 0
  SendMessage hWnd, WM_CAP_SET_SCALE, 1, 0
  SendMessage hWnd, WM_CAP_SET_PREVIEW, 1, 0
  SendMessage hWnd, WM_CAP_GRAB_FRAME_NOSTOP, 0, 0
  SendMessage hWnd, WM_CAP_EDIT_COPY, 640, 480
 
   End If
 
End Sub

Public Sub concentrateur(qual2 As String, row As Integer)
 
 'effectue la capture d'image
  Module1.WebCamClip
 
  Sheets("Work").Activate
  If Sheets("work").ChartObjects.Count = 0 Then
  With Sheets("work").ChartObjects.Add(0, 0, 480, 320).Chart
  .Paste
End With
Sheets("work").ChartObjects(1).Select
 Else
  Sheets("work").ChartObjects(1).Select
   With Sheets("work").ChartObjects(1).Chart
   .Paste
   End With
  End If
End Sub
 

muni

Utente junior
25 Novembre 2018
58
6
8
2013
0
T @tuxon ... fammi sapere se provi la soluzione che ti ho proposto ...
 

giulianovac

Access/VBA Expert
Expert
9 Giugno 2018
1.675
304
83
Italy
2013 2019
122
Ho già fatto delle prove con i comandi API ma non sono mai riuscito a farli funzionare.
In alternativa alla proposta di M @muni (che se fossi in te proverei),

Vai a questo indirizzo

Nell'elenco dei file da scaricare trovi 2 progetti in VB6 (codice sorgente)

Easy Video Capture If you have a video capture card installed in you rcomputer, then you can create your own AVI files with this.

Advanced Video Capture (For expert programmers!). If you have a video capture card installed in you rcomputer, then you can create your own AVI files with this.

Il 1° è già compilato e ti mostra il preview della webcam. Vedi se interferisce con il tuo programma o meno.

Io non posso provare perché qui al lavoro non ho la webcam. :LOL:
 

tuxon

Utente junior
8 Marzo 2018
20
3
3
milano
2016
1
Grazie ragazzi, questa sera li scarico e faccio le prove (anch'io sono a lavoro :LOL: ).

Per quanto riguarda i codici VB6 penso di aver provato almeno 15-20 script; alla fine funzionanti ce ne sono 2 o 3, il problema di questi è che funzionano magari su un PC, mentre su un altro si vedono anteprima e immagine completamente neri
 

tuxon

Utente junior
8 Marzo 2018
20
3
3
milano
2016
1
Ciao ho provato il nuovo commandcam, però:
- l'ActiveMovie Window dopo circa 10 secondi che è aperta crasha
- passando dalla finestra anteprima alla userform per fare il shot freeza tutto (sia la movie che excel) e poi crasha

Provo ancora un po' di test
 

muni

Utente junior
25 Novembre 2018
58
6
8
2013
0
Bisogna vedere se con l'opzione di ritardo da 15 secondi senza shot va in crash o no.
In ogni caso bisogna provare cpn la webcam di persona
 

Sostieni ForumExcel

Aiutaci a sostenere le spese e a mantenere online la community attraverso una libera donazione!