Rabbit Remote Control 0.0.30
Loading...
Searching...
No Matches
DesktopWindows.cpp
1// Author: Kang Lin <kl222@126.com>
2
3// 双屏/多显示器截屏: https://blog.csdn.net/problc/article/details/7063324
4// 获取屏幕的分辨率(多屏幕或者单屏幕): https://blog.csdn.net/yousss/article/details/98848775
5/*
6 * Windows中接入多个显示器时,可设置为复制和扩展屏。
7 * 1、设置为复制屏幕时,多个显示器的分辨率是一样的,位置为0~分辨率值
8 * 2、设置为扩展屏幕时,显示器之间的关系比较复杂些。首先Windows系统会识别一个主显示器,
9 * 这个可以在屏幕分辨率中更改。多个显示器之间的位置关系也可以再屏幕分辨率中更改。
10 * 其中主显示器的位置为(0,0)到(width,height),其他显示器位置由与主显示器的位置关系决定,
11 * 在主显示器左上,则为负数,用0减去长宽;在右下,则由主显示器的分辨率加上长宽。
12 * 其中驱动或用mouse_event处理时也是一样,主显示器为0~65535,
13 * 其他显示器根据主显示器的相对位置确定。
14 *
15 * -----------------------------------------------------------------------------
16 * | Virtual Screen |
17 * | ------------ |
18 * | | | |
19 * | | Screen1 | (0,0) |
20 * | | | / |
21 * | ------------ / |
22 * | ------------ ------------ |
23 * | | | | | |
24 * | | Screen2 | | Primary | |
25 * | | | | Screen3 | |
26 * | ------------ ------------ |
27 * | |
28 * | |
29 * | |
30 * | |
31 * | |
32 * | |
33 * -----------------------------------------------------------------------------
34 */
35
36#include "DesktopWindows.h"
37#include <Windows.h>
38#include <QLoggingCategory>
39
40Q_LOGGING_CATEGORY(logDW, "DesktopWindows")
41
42CDesktopWindows::CDesktopWindows(QObject *parent) : CDesktop(parent)
43{
44 m_DC = GetDesktopDC();
45 m_MemDC = NULL;
46 m_Bitmap = m_DesktopBitmap = NULL;
47 m_Width = m_Height = 0;
48
49 m_MemDC = CreateCompatibleDC(m_DC);
50 if(m_MemDC)
51 {
52 m_DesktopBitmap = CreateCompatibleBitmap(m_DC, Width(), Height());
53 if(NULL == m_DesktopBitmap)
54 qCritical(logDW,
55 "CreateCompatibleBitmap fail: %d",
56 GetLastError());
57 } else
58 qCritical(logDW,
59 "CreateCompatibleDC fail: %d",
60 GetLastError());
61
62 if(m_DesktopBitmap)
63 {
64 HGDIOBJ oldBitmap = SelectObject(m_MemDC, m_DesktopBitmap);
65 if(NULL == oldBitmap)
66 qCritical(logDW, "SelectObject fail: %d", GetLastError());
67
68 m_Desktop = QImage(Width(), Height(), QImage::Format_ARGB32);
69 }
70}
71
72CDesktopWindows::~CDesktopWindows()
73{
74 if(m_Bitmap)
75 DeleteObject(m_Bitmap);
76 if(m_DesktopBitmap)
77 DeleteObject(m_DesktopBitmap);
78 if(m_MemDC)
79 DeleteDC(m_MemDC);
80 ReleaseDC(NULL, m_DC);
81}
82
83CDesktop* CDesktop::Instance()
84{
85 static CDesktop* p = nullptr;
86 if(!p) p = new CDesktopWindows();
87 return p;
88}
89
90HDC CDesktopWindows::GetDesktopDC()
91{
92 // The following methods can all get the desktop
93 //m_DC = CreateDCA("DISPLAY",NULL,NULL,NULL ); // Primary screen
94 //m_DC = GetWindowDC(NULL);
95 m_DC = GetDC(GetDesktopWindow()); // Multi-screen;
96
97 return m_DC;
98}
99
100int CDesktopWindows::Width()
101{
102 return GetSystemMetrics(SM_CXVIRTUALSCREEN);
103 //return GetDeviceCaps(m_DC, HORZRES); // Primary screen pixel
104}
105
106int CDesktopWindows::Height()
107{
108 return GetSystemMetrics(SM_CYVIRTUALSCREEN);
109 //return GetDeviceCaps(m_DC, VERTRES); // Primary screen pixel
110}
111
112QImage CDesktopWindows::GetDesktop()
113{
114 do{
115 if(!BitBlt(m_MemDC, 0, 0, Width(), Height(), m_DC, 0, 0, SRCCOPY))
116 {
117 qCritical(logDW,
118 "BitBlt fail: %d",
119 GetLastError());
120 break;
121 }
122
123 //SelectObject(memDc, oldBitmap);
124
125 // Get the bitmap format information
126 BITMAPINFO bi;
127 memset(&bi, 0, sizeof(bi));
128 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
129 bi.bmiHeader.biBitCount = 0;
130
131 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
132 bi.bmiHeader.biWidth = Width();
133 bi.bmiHeader.biHeight = Height();
134 bi.bmiHeader.biPlanes = 1;
135 bi.bmiHeader.biBitCount = 32;
136 bi.bmiHeader.biCompression = BI_RGB;
137 bi.bmiHeader.biSizeImage = 0;
138 bi.bmiHeader.biXPelsPerMeter = 0;
139 bi.bmiHeader.biYPelsPerMeter = 0;
140 bi.bmiHeader.biClrUsed = 0;
141 bi.bmiHeader.biClrImportant = 0;
142
143 // Get image
144 if (!::GetDIBits(m_MemDC, m_DesktopBitmap, 0, Height(),
145 m_Desktop.bits(), (BITMAPINFO*)&bi, DIB_RGB_COLORS))
146 {
147 qCritical(logDW,
148 "Get image fail: %d",
149 GetLastError());
150 break;
151 }
152
153 m_Desktop = m_Desktop.mirrored();
154 } while(0);
155
156 return m_Desktop;
157}
158
159QImage CDesktopWindows::GetDesktop(int x, int y, int width, int height)
160{
161 QImage img;
162 bool bChange = false;
163
164 do{
165 if(NULL == m_DC)
166 {
167 qCritical(logDW,
168 "GetDC fail: %d",
169 GetLastError());
170 return img;
171 }
172
173 if(width != m_Width || height != m_Height
174 || NULL == m_MemDC || NULL == m_Bitmap)
175 {
176 bChange = true;
177 m_Width = width;
178 m_Height = height;
179 if(-1 == width) m_Width = Width();
180 if(-1 == height) m_Height = Height();
181 }
182
183 if(bChange)
184 {
185 DeleteObject(m_Bitmap);
186
187 m_Bitmap = CreateCompatibleBitmap(m_DC, m_Width, m_Height);
188 if(NULL == m_Bitmap)
189 {
190 qCritical(logDW,
191 "CreateCompatibleBitmap fail: %d",
192 GetLastError());
193 break;
194 }
195 HGDIOBJ oldBitmap = SelectObject(m_MemDC, m_Bitmap);
196 if(NULL == oldBitmap)
197 {
198 qCritical(logDW,
199 "SelectObject fail: %d",
200 GetLastError());
201 break;
202 }
203 }
204
205 if(!BitBlt(m_MemDC, 0, 0, m_Width, m_Height, m_DC, x, y, SRCCOPY))
206 {
207 qCritical(logDW,
208 "BitBlt fail: %d",
209 GetLastError());
210 break;
211 }
212
213 //SelectObject(memDc, oldBitmap);
214
215 // Get the bitmap format information
216 BITMAPINFO bi;
217 memset(&bi, 0, sizeof(bi));
218 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
219 bi.bmiHeader.biBitCount = 0;
220
221 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
222 bi.bmiHeader.biWidth = m_Width;
223 bi.bmiHeader.biHeight = m_Height;
224 bi.bmiHeader.biPlanes = 1;
225 bi.bmiHeader.biBitCount = 32;
226 bi.bmiHeader.biCompression = BI_RGB;
227 bi.bmiHeader.biSizeImage = 0;
228 bi.bmiHeader.biXPelsPerMeter = 0;
229 bi.bmiHeader.biYPelsPerMeter = 0;
230 bi.bmiHeader.biClrUsed = 0;
231 bi.bmiHeader.biClrImportant = 0;
232
233 img = QImage(m_Width, m_Height, QImage::Format_ARGB32);
234
235 // Get image
236 if (!::GetDIBits(m_MemDC, m_Bitmap, 0, m_Height,
237 img.bits(), (BITMAPINFO*)&bi, DIB_RGB_COLORS))
238 {
239 qCritical(logDW,
240 "Get image fail: %d",
241 GetLastError());
242 break;
243 }
244
245 img = img.mirrored();
246 } while(0);
247
248 DeleteObject(m_Bitmap);
249
250 return img;
251}
252
253QImage CDesktopWindows::GetCursor(QPoint &pos, QPoint &posHot)
254{
255 QImage img;
256 return img;
257}
258
259QPoint CDesktopWindows::GetCursorPosition()
260{
261 QPoint pos;
262 return pos;
263}