opGDI.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. //#include "stdafx.h"
  2. #include "opGDI.h"
  3. #include <atlimage.h>
  4. #include <fstream>
  5. #include "../../winapi/WinApi.h"
  6. #include "./include/Image.hpp"
  7. #include "globalVar.h"
  8. #include "helpfunc.h"
  9. opGDI::opGDI()
  10. {
  11. _render_type = 0;
  12. dx_ = 0;
  13. dy_ = 0;
  14. // 4*2^22=16*2^20=16MB
  15. //_image_data = new byte[MAX_IMAGE_WIDTH*MAX_IMAGE_WIDTH * 4];
  16. }
  17. opGDI::~opGDI()
  18. {
  19. // SAFE_DELETE_ARRAY(_image_data);
  20. }
  21. long opGDI::BindEx(HWND hwnd, long render_type)
  22. {
  23. if (!::IsWindow(hwnd)) return 0;
  24. _hwnd = hwnd;
  25. _render_type = render_type;
  26. if (render_type == RDT_NORMAL) {
  27. RECT rc, rc2;
  28. ::GetWindowRect(_hwnd, &rc);
  29. ::GetClientRect(hwnd, &rc2);
  30. _width = rc2.right - rc2.left;
  31. _height = rc2.bottom - rc2.top;
  32. POINT pt = { 0 };
  33. ::ClientToScreen(hwnd, &pt);
  34. dx_ = pt.x - rc.left;
  35. dy_ = pt.y - rc.top;
  36. _hdc = ::GetDC(NULL);
  37. }
  38. else { // client size
  39. RECT rc, rc2;
  40. ::GetWindowRect(_hwnd, &rc);
  41. ::GetClientRect(hwnd, &rc2);
  42. _width = rc2.right - rc2.left;
  43. _height = rc2.bottom - rc2.top;
  44. POINT pt = { 0 };
  45. ::ClientToScreen(hwnd, &pt);
  46. dx_ = pt.x - rc.left;
  47. dy_ = pt.y - rc.top;
  48. /*setlog("dx=%d dy=%d", dx_, dy_);*/
  49. if (_render_type == RDT_GDI) {
  50. _hdc = ::GetDC(_hwnd);
  51. HWND topHwnd = WinApi::GetTopWindowSp(_hwnd);
  52. long dwExStyle = 0;
  53. if (GetPropA(topHwnd, "opstyle_flag")) {
  54. dwExStyle = GetWindowLongA(topHwnd, GWL_EXSTYLE);
  55. }
  56. else {
  57. dwExStyle = GetWindowLongA(topHwnd, GWL_EXSTYLE);
  58. SetPropA(topHwnd, "opstyle", (HANDLE)dwExStyle);
  59. SetPropA(topHwnd, "opstyle_flag", (HANDLE)HANDLE_FLAG_INHERIT);
  60. }
  61. // dmIsWindowTransParent((int)InfoStruct, (int)topHwnd, (int)&v44,
  62. // (int)&v42, (int)&v45);
  63. SetWindowLongA(topHwnd, GWL_EXSTYLE, dwExStyle | WS_EX_LAYERED);
  64. // SetWindowTransparent((int)InfoStruct, (int)topHwnd, 16711935, 0, 1);
  65. UpdateWindow(topHwnd);
  66. }
  67. else if (RDT_GDI_DX2 == render_type) {
  68. _hdc = ::GetDC(_hwnd);
  69. _device_caps = GetDeviceCaps(_hdc, BITSPIXEL);
  70. }
  71. else {
  72. HWND dx2TopHwnd = WinApi::GetTopWindowSp(_hwnd);
  73. GetPropA(dx2TopHwnd, "opstyle");
  74. long dx2ExStyle = 0;
  75. if (GetPropA(dx2TopHwnd, "opstyle_flag")) {
  76. dx2ExStyle = GetWindowLongA(dx2TopHwnd, GWL_EXSTYLE);
  77. }
  78. else {
  79. dx2ExStyle = GetWindowLongA(dx2TopHwnd, GWL_EXSTYLE);
  80. SetPropA(dx2TopHwnd, "opstyle", (HANDLE)dx2ExStyle);
  81. SetPropA(dx2TopHwnd, "opstyle_flag", (HANDLE)HANDLE_FLAG_INHERIT);
  82. }
  83. // dmIsWindowTransParent((int)InfoStruct, (int)dx2TopHwnd, (int)&v45,
  84. // (int)&v42, (int)&v44);
  85. SetWindowLongA(dx2TopHwnd, GWL_EXSTYLE, dx2ExStyle | WS_EX_LAYERED);
  86. // SetWindowTransparent((int)InfoStruct, (int)dx2TopHwnd, 0, 255, 2);
  87. UpdateWindow(dx2TopHwnd);
  88. // InfoStruct[11] = 3;
  89. _hdc = ::GetDC(_hwnd);
  90. }
  91. }
  92. if (_hdc == NULL) {
  93. setlog("hdc == NULL", _hdc);
  94. return 0;
  95. }
  96. //创建一个与指定设备兼容的内存设备上下文环境
  97. _hmdc = CreateCompatibleDC(_hdc);
  98. if (_hmdc == NULL) {
  99. setlog("CreateCompatibleDC false");
  100. return -2;
  101. }
  102. // updata_screen();
  103. return 1;
  104. }
  105. long opGDI::UnBindEx()
  106. {
  107. // setlog("bkgdi::UnBindEx()");
  108. _hbmpscreen = (HBITMAP)SelectObject(_hmdc, _hbmp_old);
  109. // delete[dwLen_2]hDib;
  110. if (_hdc) DeleteDC(_hdc);
  111. _hdc = NULL;
  112. if (_hmdc) DeleteDC(_hmdc);
  113. _hmdc = NULL;
  114. if (_hbmpscreen) DeleteObject(_hbmpscreen);
  115. _hbmpscreen = NULL;
  116. // if (_hbmp_old)DeleteObject(_hbmp_old); _hbmp_old = NULL;
  117. return 1;
  118. }
  119. bool opGDI::requestCapture(int x1, int y1, int w, int h, Image& img)
  120. {
  121. // step 1.判断 窗口是否存在
  122. if (!::IsWindow(_hwnd)) return 0;
  123. img.create(w, h);
  124. if (_render_type == RDT_NORMAL) { // normal 拷贝的大小为实际需要的大小
  125. //
  126. /* int w = rect.right - rect.left;
  127. int h = rect.bottom - rect.top;*/
  128. _hbmpscreen = CreateCompatibleBitmap(
  129. _hdc, w, h); //创建与指定的设备环境相关的设备兼容的位图
  130. _hbmp_old = (HBITMAP)SelectObject(
  131. _hmdc, _hbmpscreen); //选择一对象到指定的设备上下文环境中
  132. _bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
  133. _bfh.bfSize = _bfh.bfOffBits + w * h * 4;
  134. _bfh.bfType = static_cast<WORD>(0x4d42);
  135. _bih.biBitCount = 32; //每个像素字节大小
  136. _bih.biCompression = BI_RGB;
  137. _bih.biHeight = h; //高度
  138. _bih.biPlanes = 1;
  139. _bih.biSize = sizeof(BITMAPINFOHEADER);
  140. _bih.biSizeImage = w * h * 4; //图像数据大小
  141. _bih.biWidth = w; //宽度
  142. //对指定的源设备环境区域中的像素进行位块(bit_block)转换
  143. RECT rc;
  144. ::GetWindowRect(_hwnd, &rc);
  145. // setlog("rect left =%d top =%d, dx =%d, dy = %d", rc.left, rc.top, dx_,
  146. // dy_);
  147. int src_x = x1 + rc.left + dx_;
  148. int src_y = y1 + rc.top + dy_;
  149. if (BitBlt(_hmdc, 0, 0, w, h, _hdc, src_x, src_y, SRCCOPY)) {
  150. // ok
  151. }
  152. else {
  153. setlog("error in bitbit");
  154. }
  155. //函数获取指定兼容位图的位,然后将其作一个DIB—设备无关位图(Device-Independent
  156. // Bitmap)使用的指定格式复制到一个缓冲区中 _pmutex->lock();
  157. uchar* pshare = _shmem->data<byte>();
  158. fmtFrameInfo(pshare, _hwnd, w, h);
  159. GetDIBits(_hmdc, _hbmpscreen, 0L, (DWORD)h, pshare + sizeof(FrameInfo),
  160. (LPBITMAPINFO)&_bih, (DWORD)DIB_RGB_COLORS);
  161. //_pmutex->unlock();
  162. if (_hbmpscreen) DeleteObject(_hbmpscreen);
  163. _hbmpscreen = NULL;
  164. //将数据拷贝到目标注意实际数据是反的
  165. for (int i = 0; i < h; i++) {
  166. memcpy(img.ptr<uchar>(i), _shmem->data<byte>() + (h - 1 - i) * 4 * w,
  167. 4 * w);
  168. }
  169. }
  170. else if (RDT_GDI_DX2 == _render_type) {
  171. ATL::CImage image;
  172. image.Create(w, h, _device_caps);
  173. BitBlt(image.GetDC(), x1, y1, w, h, _hdc, 0, 0, SRCCOPY);
  174. img.read(&image);
  175. image.ReleaseDC();
  176. }
  177. else { // gdi ... 由于printwindow 函数的原因
  178. // 截取大小为实际的窗口大小,在后续的处理中,需要转化成客户区大小
  179. //
  180. RECT rc;
  181. ::GetWindowRect(_hwnd, &rc);
  182. int ww = rc.right - rc.left;
  183. int wh = rc.bottom - rc.top;
  184. // setlog("_w w=%d %d _h h=%d %d,dx=%d dy=%d", _width, w, _height, h, dx_,
  185. // dy_);
  186. _hbmpscreen = CreateCompatibleBitmap(
  187. _hdc, ww, wh); //创建与指定的设备环境相关的设备兼容的位图
  188. _hbmp_old = (HBITMAP)SelectObject(
  189. _hmdc, _hbmpscreen); //选择一对象到指定的设备上下文环境中
  190. _bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
  191. _bfh.bfSize = _bfh.bfOffBits + ww * wh * 4;
  192. _bfh.bfType = static_cast<WORD>(0x4d42);
  193. _bih.biBitCount = 32; //每个像素字节大小
  194. _bih.biCompression = BI_RGB;
  195. _bih.biHeight = wh; //高度
  196. _bih.biPlanes = 1;
  197. _bih.biSize = sizeof(BITMAPINFOHEADER);
  198. _bih.biSizeImage = ww * wh * 4; //图像数据大小
  199. _bih.biWidth = ww; //宽度
  200. //对指定的源设备环境区域中的像素进行位块(bit_block)转换
  201. if (_render_type == RDT_GDI) {
  202. ::PrintWindow(_hwnd, _hmdc, 0);
  203. }
  204. else {
  205. ::UpdateWindow(_hwnd);
  206. //::RedrawWindow(_hwnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE |
  207. //:RDW_ALLCHILDREN | RDW_FRAME);
  208. ::PrintWindow(_hwnd, _hmdc, 0);
  209. }
  210. //函数获取指定兼容位图的位,然后将其作一个DIB—设备无关位图(Device-Independent
  211. // Bitmap)使用的指定格式复制到一个缓冲区中 _pmutex->lock();
  212. uchar* pshare = _shmem->data<byte>();
  213. fmtFrameInfo(pshare, _hwnd, w, h);
  214. GetDIBits(_hmdc, _hbmpscreen, 0L, (DWORD)wh, pshare + sizeof(FrameInfo),
  215. (LPBITMAPINFO)&_bih, (DWORD)DIB_RGB_COLORS);
  216. if (_hbmpscreen) DeleteObject(_hbmpscreen);
  217. _hbmpscreen = NULL;
  218. //将数据拷贝到目标注意实际数据是反的(注意偏移)
  219. auto ppixels = _shmem->data<byte>() + sizeof(FrameInfo);
  220. for (int i = 0; i < h; i++) {
  221. memcpy(img.ptr<uchar>(i),
  222. ppixels + (wh - 1 - i - y1 - dy_) * 4 * ww + (x1 + dx_) * 4,
  223. 4 * w);
  224. }
  225. }
  226. return 1;
  227. }
  228. void opGDI::fmtFrameInfo(void* dst, HWND hwnd, int w, int h)
  229. {
  230. m_frameInfo.hwnd = (unsigned __int64)hwnd;
  231. m_frameInfo.frameId++;
  232. m_frameInfo.time = ::GetTickCount();
  233. m_frameInfo.width = w;
  234. m_frameInfo.height = h;
  235. m_frameInfo.fmtChk();
  236. memcpy(dst, &m_frameInfo, sizeof(m_frameInfo));
  237. }