Rabbit Remote Control 0.0.30
Loading...
Searching...
No Matches
ScreenWindows.cpp
1// Author: Kang Lin <kl222@126.com>
2// 双屏/多显示器截屏: https://blog.csdn.net/problc/article/details/7063324
3// 获取屏幕的分辨率(多屏幕或者单屏幕): https://blog.csdn.net/yousss/article/details/98848775
4/*
5 * Windows中接入多个显示器时,可设置为复制和扩展屏。
6 * 1、设置为复制屏幕时,多个显示器的分辨率是一样的,位置为0~分辨率值
7 * 2、设置为扩展屏幕时,显示器之间的关系比较复杂些。首先Windows系统会识别一个主显示器,
8 * 这个可以在屏幕分辨率中更改。多个显示器之间的位置关系也可以再屏幕分辨率中更改。
9 * 其中主显示器的位置为(0,0)到(width,height),其他显示器位置由与主显示器的位置关系决定,
10 * 在主显示器左上,则为负数,用0减去长宽;在右下,则由主显示器的分辨率加上长宽。
11 * 其中驱动或用mouse_event处理时也是一样,主显示器为0~65535,
12 * 其他显示器根据主显示器的相对位置确定。
13 *
14 * -----------------------------------------------------------------------------
15 * | Virtual Screen |
16 * | ------------ |
17 * | | | |
18 * | | Screen1 | (0,0) |
19 * | | | / |
20 * | ------------ / |
21 * | ------------ ------------ |
22 * | | | | | |
23 * | | Screen2 | | Primary | |
24 * | | | | Screen3 | |
25 * | ------------ ------------ |
26 * | |
27 * | |
28 * | |
29 * | |
30 * | |
31 * | |
32 * -----------------------------------------------------------------------------
33 */
34
35#include "ScreenWindows.h"
36#include <Windows.h>
37#include <QLoggingCategory>
38
39Q_DECLARE_LOGGING_CATEGORY(logDW)
40
41CScreen* CScreen::Instance()
42{
43 static CScreen* p = nullptr;
44 if(!p) p = new CScreenWindows();
45 return p;
46}
47
48CScreenWindows::CScreenWindows(QObject *parent) : CScreen(parent)
49{
50 m_Format = QImage::Format_ARGB32;
51}
52
53CScreenWindows::~CScreenWindows()
54{
55 qDebug(logDW, "CScreenWindows::~CScreenWindows");
56}
57
58int CScreenWindows::Width()
59{
60 if(m_Screen.isNull())
61 GetImage(false);
62 if(m_Screen.isNull())
63 return GetSystemMetrics(SM_CXSCREEN);
64 return m_Screen.width();
65}
66
67int CScreenWindows::Height()
68{
69 if(m_Screen.isNull())
70 GetImage(false);
71 if(m_Screen.isNull())
72 return GetSystemMetrics(SM_CYSCREEN);
73 return m_Screen.height();
74}
75
76int CScreenWindows::VirtualTop()
77{
78 return GetSystemMetrics(SM_XVIRTUALSCREEN);
79}
80
81int CScreenWindows::VirtualLeft()
82{
83 return GetSystemMetrics(SM_YVIRTUALSCREEN);
84}
85
86int CScreenWindows::VirtualWidth()
87{
88 return GetSystemMetrics(SM_CXVIRTUALSCREEN);
89}
90
91int CScreenWindows::VirtualHeight()
92{
93 return GetSystemMetrics(SM_CYVIRTUALSCREEN);
94}
95
96int CScreenWindows::VisibleMonitorCount()
97{
98 return GetSystemMetrics(SM_CMONITORS);
99}
100
101QImage::Format CScreenWindows::GetFormat(int index)
102{
103 return m_Format;
104}
105
106int CScreenWindows::SetFormat(QImage::Format f)
107{
108 m_Format = f;
109 return 0;
110}
111
112QImage CScreenWindows::GetScreen(int index)
113{
114 int nRet = GetImage(true);
115 if(nRet) return QImage();
116
117 if(QImage::Format_Invalid == m_Format)
118 m_Format = m_Screen.format();
119 if(m_Screen.format() != m_Format && QImage::Format_Invalid != m_Format)
120 m_Screen = m_Screen.convertToFormat(m_Format);
121 return m_Screen;
122}
123
124int CScreenWindows::GetImage(bool bBuffer)
125{
126 int nRet = -1;
127
128 if(!m_Screen.isNull() && !bBuffer)
129 return 0;
130
131 HDC dc = NULL;
132 HDC memDc = NULL;
133 HBITMAP bitmap = NULL;
134
135 do{
136 //dc = = CreateDC( _T("DISPLAY"),NULL,NULL,NULL ); // Primary screen
137 dc = GetDC(GetDesktopWindow()); // Multi-screen
138 if(NULL == dc)
139 {
140 qCritical(logDW,
141 "GetDC fail: %d",
142 GetLastError());
143 break;
144 }
145
146 memDc = CreateCompatibleDC(dc);
147 if(NULL == memDc)
148 {
149 qCritical(logDW,
150 "CreateCompatibleDC fail: %d",
151 GetLastError());
152 break;
153 }
154
155 int ScreenWidth = GetDeviceCaps(dc, HORZRES); // pixel
156 int ScreenHeight = GetDeviceCaps(dc, VERTRES); // pixel
157 bitmap = CreateCompatibleBitmap(dc, ScreenWidth, ScreenHeight);
158 if(NULL == bitmap)
159 {
160 qCritical(logDW,
161 "CreateCompatibleBitmap fail: %d",
162 GetLastError());
163 break;
164 }
165 HGDIOBJ oldBitmap = SelectObject(memDc, bitmap);
166 if(NULL == oldBitmap)
167 {
168 qCritical(logDW,
169 "SelectObject fail: %d",
170 GetLastError());
171 break;
172 }
173 if(!BitBlt(memDc, 0, 0, ScreenWidth, ScreenHeight, dc, 0, 0, SRCCOPY))
174 {
175 qCritical(logDW,
176 "BitBlt fail: %d",
177 GetLastError());
178 break;
179 }
180
181 if(HasCursor())
182 {
183 //TODO: There is a bug
184 POINT point;
185 ::GetCursorPos(&point);
186 HCURSOR hCursor = ::GetCursor();
187 ::DrawIcon(memDc, point.x, point.y, hCursor);
188 }
189
190 //SelectObject(memDc, oldBitmap);
191
192 // Get the bitmap format information
193 BITMAPINFO bi;
194 memset(&bi, 0, sizeof(bi));
195 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
196 bi.bmiHeader.biBitCount = 0;
197
198 if(bBuffer)
199 {
200 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
201 bi.bmiHeader.biWidth = ScreenWidth;
202 bi.bmiHeader.biHeight = ScreenHeight;
203 bi.bmiHeader.biPlanes = 1;
204 bi.bmiHeader.biBitCount = 32;
205 bi.bmiHeader.biCompression = BI_RGB;
206 bi.bmiHeader.biSizeImage = 0;
207 bi.bmiHeader.biXPelsPerMeter = 0;
208 bi.bmiHeader.biYPelsPerMeter = 0;
209 bi.bmiHeader.biClrUsed = 0;
210 bi.bmiHeader.biClrImportant = 0;
211
212 if(m_Screen.isNull() || m_Screen.format() != QImage::Format_ARGB32)
213 m_Screen = QImage(ScreenWidth, ScreenHeight, QImage::Format_ARGB32);
214
215 // Get image
216 if (!::GetDIBits(memDc, bitmap, 0, ScreenHeight,
217 m_Screen.bits(), (BITMAPINFO*)&bi, DIB_RGB_COLORS))
218 {
219 qCritical(logDW,
220 "Get image fail: %d",
221 GetLastError());
222 break;
223 }
224
225 m_Screen = m_Screen.mirrored();
226 nRet = 0;
227 } else {
228 // Get image format
229 if (!::GetDIBits(memDc, bitmap, 0, ScreenHeight, NULL, (BITMAPINFO*)&bi, DIB_RGB_COLORS))
230 {
231 qCritical(logDW,
232 "unable to determine device pixel format: %d",
233 GetLastError());
234 break;
235 }
236 // if (!::GetDIBits(memDc, bitmap, 0, ScreenHeight, NULL, (BITMAPINFO*)&bi, DIB_RGB_COLORS))
237 // {
238 // qCritical(logDW,
239 // "unable to determine pixel shifts/palette: %d",
240 // GetLastError());
241 // break;
242 // }
243
244 if(bi.bmiHeader.biBitCount > 8)
245 {
246 switch(bi.bmiHeader.biCompression)
247 {
248 case BI_RGB:
249 // Default RGB layout
250 switch (bi.bmiHeader.biBitCount) {
251 case 16:
252 // RGB 555 - High Colour
253 qInfo(logDW, "16-bit High Colour");
254 m_Screen = QImage(ScreenWidth, ScreenHeight, QImage::Format_RGB555);
255 break;
256 case 24:
257 qInfo(logDW, "24-bit High Colour");
258 m_Screen = QImage(ScreenWidth, ScreenHeight, QImage::Format_RGB888);
259 break;
260 case 32:
261 // RGB 888 - True Colour
262 qInfo(logDW, "32-bit High Colour");
263 m_Screen = QImage(ScreenWidth, ScreenHeight, QImage::Format_ARGB32);
264 break;
265 default:
266 qCritical(logDW, "bits per pixel %u not supported", bi.bmiHeader.biBitCount);
267 break;
268 };
269 break;
270 case BI_BITFIELDS:
271 // Default RGB layout
272 switch (bi.bmiHeader.biBitCount) {
273 case 16:
274 // RGB 555 - High Colour
275 qInfo(logDW, "16-bit High Colour");
276 m_Screen = QImage(ScreenWidth, ScreenHeight, QImage::Format_RGB555);
277 break;
278 case 32:
279 // RGB 888 - True Colour
280 qInfo(logDW, "32-bit High Colour");
281 m_Screen = QImage(ScreenWidth, ScreenHeight, QImage::Format_ARGB32);
282 break;
283 default:
284 qCritical(logDW, "bits per pixel %u not supported", bi.bmiHeader.biBitCount);
285 break;
286 };
287 break;
288 }
289
290 nRet = 0;
291 } else {
292 qCritical(logDW, "bi.bmiHeader.biBitCount < 8");
293 }
294 }
295
296 } while(0);
297
298 DeleteObject(bitmap);
299 DeleteDC(memDc);
300 ReleaseDC(NULL, dc);
301
302 return nRet;
303}
The CScreen class.
Definition Screen.h:14