My ultimate goal here is to try and display a small list of monitor thumbnails on a dialog. This is so that the user can click on one of those thumbnails and I then perform a certain action for them.
I have found out how to use EnumDisplayMonitors
to get the array of monitor rectangles from a question here on SO:
struct MonitorRects
{
std::vector<RECT> rcMonitors;
std::vector<CString> strMonitorNames;
static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
{
MonitorRects* pThis = reinterpret_cast<MonitorRects*>(pData);
pThis->rcMonitors.push_back(*lprcMonitor);
MONITORINFOEX sMI{};
sMI.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(hMon, &sMI);
pThis->strMonitorNames.push_back(sMI.szDevice);
return TRUE;
}
MonitorRects()
{
EnumDisplayMonitors(nullptr, nullptr, MonitorEnum, (LPARAM)this);
}
};
I extended it (for the timebeing) to also remember the list of monitor names. For now, I display the list of monitor names in a CListBox
for the user to select that way, but eventually I want a list of display thumbnails.
So my next task was to try and create a screen grab and initially copy it to the clipboard. I thought I would try to paste it into a image editor, just to see if I had captured the right information. So I created this function (based on code on the internet):
BOOL CCenterCursorOnScreenDlg::CaptureRect(const CRect& rcCapture, CImage &rImage)
{
// destroy the currently contained bitmap to create a new one
rImage.Destroy();
// create bitmap and attach it to this object
if (!rImage.Create(rcCapture.Width(), rcCapture.Height(), 32, 0))
{
AfxMessageBox(L"Cannot create image!", MB_ICONERROR);
return FALSE;
}
// create virtual screen DC
CDC dcScreen;
dcScreen.CreateDC(_T("DISPLAY"), nullptr, nullptr, nullptr);
// copy the contents from the virtual screen DC
BOOL bRet = ::BitBlt(rImage.GetDC(), 0, 0, rcCapture.Width(), rcCapture.Height(),
dcScreen.m_hDC, rcCapture.left, rcCapture.top,
SRCCOPY | CAPTUREBLT);
// do cleanup and return
dcScreen.DeleteDC();
rImage.ReleaseDC();
if (!(OpenClipboard() &&
EmptyClipboard() &&
::SetClipboardData(CF_BITMAP, (HBITMAP)rImage)))
AfxMessageBox(L"Error copying image to clipboard", MB_ICONERROR);
CloseClipboard();
return bRet;
}
I encounter two issues:
- When I paste the clipboard into HyperSnap the image is blank. I anticipated it being of the display in question.
- HyperSna "froze" and I had to crash it.
I used this code to create the image in the dialog:
CRect rcMonitor = m_monitors.rcMonitors.at(0);
CImage img;
CaptureRect(rcMonitor, img);
Update
If I do this:
rImage.Save(L"d:\\testthumb.jpg", Gdiplus::ImageFormatJPEG);
And manually open the JPG it is correctly captured of the screen. So in this instance my issue was copying that CImage
to the clipboard. Not that I really need to do that (as my ultimate goal is a list of thumbnails the user can click. But I best stick with the one question for now.