Programa de capturas utilizando GDI

Desde hace mucho tiempo me ha llamado la atención la WTL (Windows Template Library), así que decidí crear un pequeño programa utilizando dicha tecnología. Me gusta mucho que el tamaño de los ejecutables de WTL sea mucho más pequeños que los que genera MFC (Microsoft Foundation Classes) y que el código fuente sea abierto para que todo el mundo pueda verlo. Muchos de vosotros pensaréis que no hay mucha diferencia entre WTL y MFC, y en cierto modo es verdad. Son dos herramientas súper potentes para cualquiera que quiera desarrollar programas pequeños y rápidos.

Si a la hora del desarrollo te aparecen errores relacionados con las librerías, puede ser que tengas que instalar los componentes que te detallo más abajo:

He testeado el programa en Windows 7 y Windows XP. Realmente no sé qué tal funciona en otras plataformas.

Características

  • 1. Capturar pantalla completa
  • 2. Capturar ventana
  • 3. Capturar zona
  • 4. Zoom in
  • 5. Zoom out
  • 6. Copiar la imagen capturada a Paint
  • 7. Favoritos
  • 8. Copiar la imagen capturada al portapapeles
  • 9. Entorno (atajos)
  • 10. Visor de imágenes

Implementación

Enviamos la imagen capturada a Microsoft Paint

//Copy an image to the clipboard.
if (OpenClipboard())
{
    EmptyClipboard();
    CBitmap bmpCopy;

    BITMAP bm;
    if (GetObject(pImageData->m_bmpOri.m_hBitmap, sizeof(BITMAP), &bm))
        bmpCopy = (HBITMAP)CopyImage(pImageData->m_bmpOri.m_hBitmap, IMAGE_BITMAP, 0, 0, 0);
    ATLASSERT(::GetObjectType(bmpCopy.m_hBitmap) == OBJ_BITMAP);
    SetClipboardData(CF_BITMAP, bmpCopy.m_hBitmap);
    CloseClipboard();
}

if (IsClipboardFormatAvailable(CF_BITMAP))
{
    HWND                    hPaint;
    STARTUPINFO                si;
    PROCESS_INFORMATION        pi;

    memset(&si, 0, sizeof(STARTUPINFO));
    memset(&pi, 0, sizeof(PROCESS_INFORMATION));
    si.cb = sizeof(STARTUPINFO);

    wchar_t    szWindowDirector[MAX_PATH] = { 0 };
    CString    strMspaintLoc;

    GetSystemDirectory(szWindowDirector, MAX_PATH);
    strMspaintLoc.Format(L"%s\%s", szWindowDirector, L"mspaint.exe");
    if (CreateProcess(strMspaintLoc,
        NULL, NULL, NULL, FALSE,
        NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
    {
        //HWINEVENTHOOK hook =
        //    SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, NULL,
        //        WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
        /*ResumeThread(pi.hThread);*/
        //THIS PART NEEDS TO BE FIXED.
        while (TRUE)
        {
            Sleep(100);
            hPaint = FindWindow(L"MsPaintApp", NULL);
            ATLTRACE(L"findwindow Handle %Xn", hPaint);
            if (hPaint) break;
        }
    }
    else
    {
        MessageBox(L"Couldn't find mspaint program");
        return;
    }

    if (OpenClipboard())
    {
        CloseClipboard();

        if (SetForegroundWindow(hPaint))
        {
            //Ctrl + V (paste)
            INPUT ip;
            ip.type = INPUT_KEYBOARD;
            ip.ki.wScan = 0;
            ip.ki.time = 0;
            ip.ki.dwExtraInfo = 0;

            // Press the "Ctrl" key
            ip.ki.wVk = VK_CONTROL;
            ip.ki.dwFlags = 0; // 0 for key press
            SendInput(1, &ip, sizeof(INPUT));

            // Press the "V" key
            ip.ki.wVk = 'V';
            ip.ki.dwFlags = 0; // 0 for key press
            SendInput(1, &ip, sizeof(INPUT));

            // Release the "V" key
            ip.ki.wVk = 'V';
            ip.ki.dwFlags = KEYEVENTF_KEYUP;
            SendInput(1, &ip, sizeof(INPUT));

            // Release the "Ctrl" key
            ip.ki.wVk = VK_CONTROL;
            ip.ki.dwFlags = KEYEVENTF_KEYUP;
            SendInput(1, &ip, sizeof(INPUT));
        }
    }
}

Capturamos pantalla

CRect        rc;
ShowWindow(SW_MINIMIZE);
Sleep(100);

// Start to get an Image from the nearest screen (Prepare capture data)
CDC            dcWindow;
dcWindow.CreateDCW(L"DISPLAY", NULL, NULL, NULL);

// Get the nearest monitor rect
CMonitorInfo::GetMonitorRect(m_hWnd, rc);

CBitmap        bmp, oldbmp;
CDC            dcMem;
CClientDC    dc(m_hWnd);
dcMem.CreateCompatibleDC();
bmp.CreateCompatibleBitmap(dcWindow, rc.Width(), rc.Height());
oldbmp = dcMem.SelectBitmap(bmp);
dcMem.BitBlt(0, 0, rc.Width(), rc.Height(), dcWindow, rc.left, rc.top, SRCCOPY);

SetCaptureImage(&bmp);

dcMem.SelectBitmap(oldbmp);
ShowWindow(SW_RESTORE);

Capturamos ventana

void CMCFrameWnd::CaptureWindow()
{
    // Get full screen size.
    CRect        rcMonitor;

    ShowWindow(SW_MINIMIZE);
    Sleep(100);

    // Start to get an Image from the nearest screen (Prepare capture data)
    CDC            dcWindow;
    dcWindow.CreateDCW(L"DISPLAY", NULL, NULL, NULL);

    // Get the nearest monitor Rect
    CMonitorInfo::GetMonitorRect(m_hWnd, rcMonitor);

    CBitmap        bmp, oldbmp;
    CDC            dcMem;
    CClientDC    dc(m_hWnd);
    dcMem.CreateCompatibleDC();
    bmp.CreateCompatibleBitmap(dcWindow, rcMonitor.Width(), rcMonitor.Height());
    oldbmp = dcMem.SelectBitmap(bmp);
    dcMem.BitBlt(0, 0, rcMonitor.Width(),
    rcMonitor.Height(), dcWindow, rcMonitor.left, rcMonitor.top, SRCCOPY);
    dcMem.SelectBitmap(oldbmp);

    if (m_pwndTemparyScreenWnd != NULL)
        delete m_pwndTemparyScreenWnd;
    m_pwndTemparyScreenWnd = new CTemparyScreenWnd(this);
    m_pwndTemparyScreenWnd->mode = CTemparyScreenWnd::Mode::TEMPARYSCREEN_WINDOW;
    m_pwndTemparyScreenWnd->Create(m_hWnd, rcMonitor, 0, WS_POPUP | WS_VISIBLE, WS_EX_TOPMOST);
    m_pwndTemparyScreenWnd->GetWindowData();
    m_pwndTemparyScreenWnd->SetScreenImage(bmp);
    m_pwndTemparyScreenWnd->ShowMonitorScreen();
    SetForegroundWindow(m_pwndTemparyScreenWnd->m_hWnd);
}

Si quieres descargarte el proyecto completo, puedes hacerlo desde aquí.

Fuente: Taehoon Kim

Guardar

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP