绘制光标多重显示(只绘制文字图标)GDI
Draw cursor multiple display (only draw text icon) GDI
我select在多种显示环境中显示并生成捕获的程序。
并尝试通过 select在多个显示器之间 dc 来绘制光标。
我用 bitblt 位图图像绘制光标,效果很好。
HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);
但是当我select从createDC multiple显示值时,
DISPLAY_DEVICEW info = { 0 };
info.cb = sizeof(DISPLAY_DEVICEW);
EnumDisplayDevicesW(NULL, 0, &info, EDD_GET_DEVICE_INTERFACE_NAME);
HDCC = CreateDC(info.DeviceName, NULL, NULL, NULL);
我正在努力获取其他显示图像。但是没有绘图光标。 (其他形式的光标不画,只画文字光标)
这是我的代码。
const int d_count = GetSystemMetrics(SM_CMONITORS); //I have 3 display and count is 3.
HDC hCaptureDC;
HDC HDCC;
HBITMAP hBitmap;
HGDIOBJ hOld;
BYTE *src;
bool GetMouse() {
CURSORINFO cursor = { sizeof(cursor) };
::GetCursorInfo(&cursor);
ICONINFOEXW info = { sizeof(info) };
::GetIconInfoExW(cursor.hCursor, &info);
BITMAP bmpCursor = { 0 };
GetObject(info.hbmColor, sizeof(bmpCursor), &bmpCursor);
POINT point;
GetCursorPos(&point);
bool res = DrawIconEx(hCaptureDC, point.x, point.y, cursor.hCursor, bmpCursor.bmWidth, bmpCursor.bmHeight, 0, NULL, DI_NORMAL);
return res;
}
void screencap(){
BITMAPINFO MyBMInfo;
BITMAPINFOHEADER bmpInfoHeader;
HWND m_hWndCopy= GetDesktopWindow();
GetClientRect(m_hWndCopy, &ImageRect);
const int nWidth = ImageRect.right - ImageRect.left;
const int nHeight = ImageRect.bottom - ImageRect.top;
MyBMInfo = { 0 };
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
bmpInfoHeader = { sizeof(BITMAPINFOHEADER) };
bmpInfoHeader.biWidth = nWidth;
bmpInfoHeader.biHeight = nHeight;
bmpInfoHeader.biPlanes = 1;
bmpInfoHeader.biBitCount = 32;
b_size = ((nWidth * bmpInfoHeader.biBitCount + 31) / 32) * 4 * nHeight;
//HDCC = CreateDC((L"Display"), NULL, NULL, NULL); //It's good.
DISPLAY_DEVICEW info = { 0 };
info.cb = sizeof(DISPLAY_DEVICEW);
EnumDisplayDevicesW(NULL, 0, &info, EDD_GET_DEVICE_INTERFACE_NAME);
HDCC = CreateDC(info.DeviceName, NULL, NULL, NULL); // It draws only text cursor.
hCaptureDC = CreateCompatibleDC(HDCC);
hBitmap = CreateCompatibleBitmap(HDCC, nWidth, nHeight);
hOld = SelectObject(hCaptureDC, hBitmap);
BitBlt(hCaptureDC, 0, 0, nWidth, nHeight, HDCC, 0, 0, SRCCOPY);
GetMouse();
SelectObject(hCaptureDC, hOld);
src = (BYTE*)malloc(b_size);
if (GetDIBits(hCaptureDC, hBitmap, 0, nHeight, src, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS)) {
if (RGBSaveBMP(src) == true)
free(src);
}
}
我正在使用 windows 10.
我该如何解决?
任何链接,想法,谢谢。
添加
不绘制光标....(文本光标除外。)
HDCC = CreateDC(TEXT("\\.\Display1"), NULL, NULL, NULL);
绘制光标..
HDCC = CreateDC(TEXT("Display"), NULL, NULL, NULL);
已解决:
现在,我改变了我的算法。
CreateDC(L"Display", NULL, NULL, NULL) 为所有监视器创建DC,那么你的问题是什么? – user2120666 4 月 22 日 15:37
这条评论很有帮助,但不够友善。 (或者我是愚蠢的。):(
HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);
HDCC 有 "All Virtual Screens" DC。
当我 select 编辑我需要的监视器时,相应地 select 编辑并使用该区域在虚拟屏幕上进行捕获。
HDC hCaptureDC = CreateCompatibleDC(HDCC);
HBITMAP hBitmap = CreateCompatibleBitmap(HDCC, nWidth, nHeight);
HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);
DEVMODE dev;
std::string str = "\\.\Display" + std::to_string(select);
std::wstring temp;
temp.assign(str.begin(), str.end());
EnumDisplaySettingsW(temp.c_str(), ENUM_CURRENT_SETTINGS, &dev);
printf("Display%d : (%d * %d) (%d, %d)\n", select, dev.dmPelsWidth, dev.dmPelsHeight, dev.dmPosition.x, dev.dmPosition.y);
nWidth = dev.dmPelsWidth;
nHeight = dev.dmPelsHeight;
nposx = dev.dmPosition.x;
nposy = dev.dmPosition.y;
hOld = SelectObject(hCaptureDC, hBitmap);
BitBlt(hCaptureDC, 0, 0, nWidth, nHeight, HDCC, nposx, nposy, SRCCOPY);
int colorcheck = GetSystemMetrics(SM_SAMEDISPLAYFORMAT);
CURSORINFO cursor = { sizeof(cursor) };
bool check = ::GetCursorInfo(&cursor);
bool check2 = ::GetCursorInfo(&cursor);
int count = ShowCursor(TRUE);
info = { sizeof(info) };
::GetIconInfoExW(cursor.hCursor, &info);
GetCursorPos(&point);
if (point.x > nWidth) {
point.x = point.x - nWidth;
}
else if (point.x < 0) {
point.x = nWidth + point.x;
}
if (point.y > nHeight) {
point.y = point.y - nHeight;
}
else if (point.y < 0) {
point.y = nHeight + point.y;
}
cursor.ptScreenPos.x = point.x;
cursor.ptScreenPos.y = point.y;
bool res = ::DrawIconEx(hCaptureDC, point.x, point.y, cursor.hCursor, 0, 0, 0, NULL, DI_NORMAL);
BYTE* src = (BYTE*)malloc(b_size);
GetDIBits(hCaptureDC, hBitmap, 0, nHeight, src, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS)
感谢评论!
关注MSDN得到EnumDisplayMonitor
可能会解决你的问题。
Use EnumDisplayMonitors to get the device name and pass it to
CreateDC.
你的调用GetClientRect(m_hWndCopy, &ImageRect);
是错误的。
The rectangle of the desktop window returned by GetWindowRect or
GetClientRect is always equal to the rectangle of the primary monitor,
for compatibility with existing applications.
所以您只捕获主要显示。
我select在多种显示环境中显示并生成捕获的程序。
并尝试通过 select在多个显示器之间 dc 来绘制光标。
我用 bitblt 位图图像绘制光标,效果很好。
HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);
但是当我select从createDC multiple显示值时,
DISPLAY_DEVICEW info = { 0 };
info.cb = sizeof(DISPLAY_DEVICEW);
EnumDisplayDevicesW(NULL, 0, &info, EDD_GET_DEVICE_INTERFACE_NAME);
HDCC = CreateDC(info.DeviceName, NULL, NULL, NULL);
我正在努力获取其他显示图像。但是没有绘图光标。 (其他形式的光标不画,只画文字光标)
这是我的代码。
const int d_count = GetSystemMetrics(SM_CMONITORS); //I have 3 display and count is 3.
HDC hCaptureDC;
HDC HDCC;
HBITMAP hBitmap;
HGDIOBJ hOld;
BYTE *src;
bool GetMouse() {
CURSORINFO cursor = { sizeof(cursor) };
::GetCursorInfo(&cursor);
ICONINFOEXW info = { sizeof(info) };
::GetIconInfoExW(cursor.hCursor, &info);
BITMAP bmpCursor = { 0 };
GetObject(info.hbmColor, sizeof(bmpCursor), &bmpCursor);
POINT point;
GetCursorPos(&point);
bool res = DrawIconEx(hCaptureDC, point.x, point.y, cursor.hCursor, bmpCursor.bmWidth, bmpCursor.bmHeight, 0, NULL, DI_NORMAL);
return res;
}
void screencap(){
BITMAPINFO MyBMInfo;
BITMAPINFOHEADER bmpInfoHeader;
HWND m_hWndCopy= GetDesktopWindow();
GetClientRect(m_hWndCopy, &ImageRect);
const int nWidth = ImageRect.right - ImageRect.left;
const int nHeight = ImageRect.bottom - ImageRect.top;
MyBMInfo = { 0 };
MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader);
bmpInfoHeader = { sizeof(BITMAPINFOHEADER) };
bmpInfoHeader.biWidth = nWidth;
bmpInfoHeader.biHeight = nHeight;
bmpInfoHeader.biPlanes = 1;
bmpInfoHeader.biBitCount = 32;
b_size = ((nWidth * bmpInfoHeader.biBitCount + 31) / 32) * 4 * nHeight;
//HDCC = CreateDC((L"Display"), NULL, NULL, NULL); //It's good.
DISPLAY_DEVICEW info = { 0 };
info.cb = sizeof(DISPLAY_DEVICEW);
EnumDisplayDevicesW(NULL, 0, &info, EDD_GET_DEVICE_INTERFACE_NAME);
HDCC = CreateDC(info.DeviceName, NULL, NULL, NULL); // It draws only text cursor.
hCaptureDC = CreateCompatibleDC(HDCC);
hBitmap = CreateCompatibleBitmap(HDCC, nWidth, nHeight);
hOld = SelectObject(hCaptureDC, hBitmap);
BitBlt(hCaptureDC, 0, 0, nWidth, nHeight, HDCC, 0, 0, SRCCOPY);
GetMouse();
SelectObject(hCaptureDC, hOld);
src = (BYTE*)malloc(b_size);
if (GetDIBits(hCaptureDC, hBitmap, 0, nHeight, src, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS)) {
if (RGBSaveBMP(src) == true)
free(src);
}
}
我正在使用 windows 10.
我该如何解决?
任何链接,想法,谢谢。
添加
不绘制光标....(文本光标除外。)
HDCC = CreateDC(TEXT("\\.\Display1"), NULL, NULL, NULL);
绘制光标..
HDCC = CreateDC(TEXT("Display"), NULL, NULL, NULL);
已解决:
现在,我改变了我的算法。
CreateDC(L"Display", NULL, NULL, NULL) 为所有监视器创建DC,那么你的问题是什么? – user2120666 4 月 22 日 15:37
这条评论很有帮助,但不够友善。 (或者我是愚蠢的。):(
HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);
HDCC 有 "All Virtual Screens" DC。
当我 select 编辑我需要的监视器时,相应地 select 编辑并使用该区域在虚拟屏幕上进行捕获。
HDC hCaptureDC = CreateCompatibleDC(HDCC);
HBITMAP hBitmap = CreateCompatibleBitmap(HDCC, nWidth, nHeight);
HDC HDCC = CreateDC((L"Display"), NULL, NULL, NULL);
DEVMODE dev;
std::string str = "\\.\Display" + std::to_string(select);
std::wstring temp;
temp.assign(str.begin(), str.end());
EnumDisplaySettingsW(temp.c_str(), ENUM_CURRENT_SETTINGS, &dev);
printf("Display%d : (%d * %d) (%d, %d)\n", select, dev.dmPelsWidth, dev.dmPelsHeight, dev.dmPosition.x, dev.dmPosition.y);
nWidth = dev.dmPelsWidth;
nHeight = dev.dmPelsHeight;
nposx = dev.dmPosition.x;
nposy = dev.dmPosition.y;
hOld = SelectObject(hCaptureDC, hBitmap);
BitBlt(hCaptureDC, 0, 0, nWidth, nHeight, HDCC, nposx, nposy, SRCCOPY);
int colorcheck = GetSystemMetrics(SM_SAMEDISPLAYFORMAT);
CURSORINFO cursor = { sizeof(cursor) };
bool check = ::GetCursorInfo(&cursor);
bool check2 = ::GetCursorInfo(&cursor);
int count = ShowCursor(TRUE);
info = { sizeof(info) };
::GetIconInfoExW(cursor.hCursor, &info);
GetCursorPos(&point);
if (point.x > nWidth) {
point.x = point.x - nWidth;
}
else if (point.x < 0) {
point.x = nWidth + point.x;
}
if (point.y > nHeight) {
point.y = point.y - nHeight;
}
else if (point.y < 0) {
point.y = nHeight + point.y;
}
cursor.ptScreenPos.x = point.x;
cursor.ptScreenPos.y = point.y;
bool res = ::DrawIconEx(hCaptureDC, point.x, point.y, cursor.hCursor, 0, 0, 0, NULL, DI_NORMAL);
BYTE* src = (BYTE*)malloc(b_size);
GetDIBits(hCaptureDC, hBitmap, 0, nHeight, src, (BITMAPINFO*)&bmpInfoHeader, DIB_RGB_COLORS)
感谢评论!
关注MSDN得到EnumDisplayMonitor
可能会解决你的问题。
Use EnumDisplayMonitors to get the device name and pass it to CreateDC.
你的调用GetClientRect(m_hWndCopy, &ImageRect);
是错误的。
The rectangle of the desktop window returned by GetWindowRect or GetClientRect is always equal to the rectangle of the primary monitor, for compatibility with existing applications.
所以您只捕获主要显示。