From 4e211bafb9d9a8b690916817170c62ba5d7e1e6e Mon Sep 17 00:00:00 2001 From: koldo Date: Sun, 4 May 2014 13:53:38 +0000 Subject: [PATCH] SysInfo: Refurbished Snap functions, now fully equal in Windows and Linux. Deprecated XWD support, now unnecessary. git-svn-id: svn://ultimatepp.org/upp/trunk@7350 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- bazaar/SysInfo/SysInfo.cpp | 26 ++- bazaar/SysInfo/SysInfo.h | 22 ++- bazaar/SysInfo/screengrab.cpp | 200 +++++++++++++++++------ bazaar/SysInfo/src.tpp/SysInfo$en-us.tpp | 51 ++++-- 4 files changed, 231 insertions(+), 68 deletions(-) diff --git a/bazaar/SysInfo/SysInfo.cpp b/bazaar/SysInfo/SysInfo.cpp index 15591ff66..da085d8a7 100644 --- a/bazaar/SysInfo/SysInfo.cpp +++ b/bazaar/SysInfo/SysInfo.cpp @@ -934,6 +934,7 @@ void GetWindowsList(Array &hWnd, Array &processId, Array & DWORD dwThreadId, dwProcessId; HINSTANCE hInstance; WCHAR str[MAX_PATH]; + int count; EnumWindows(EnumGetWindowsList, (LPARAM)&hWnd); for (int i = 0; i < hWnd.GetCount(); ++i) { @@ -942,7 +943,6 @@ void GetWindowsList(Array &hWnd, Array &processId, Array & dwThreadId = GetWindowThreadProcessId(reinterpret_cast(hWnd[i]), &dwProcessId); processId.Add(dwProcessId); hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId); - int count; if (count = GetModuleFileNameExW(hProcess, hInstance, str, sizeof(str)/sizeof(WCHAR))) { sstr = WString(str, count).ToString(); fileName << sstr; @@ -958,7 +958,7 @@ void GetWindowsList(Array &hWnd, Array &processId, Array & if (sstr == "TPClnt.dll") // VMWare Thinprint crashes SendMessageW() caption << ""; else if (IsWindowVisible(reinterpret_cast(hWnd[i]))) { - int count = int(SendMessageW(reinterpret_cast(hWnd[i]), WM_GETTEXT, sizeof(str)/sizeof(WCHAR), (LPARAM)str)); + count = int(SendMessageW(reinterpret_cast(hWnd[i]), WM_GETTEXT, sizeof(str)/sizeof(WCHAR), (LPARAM)str)); caption << WString(str, count).ToString(); } else caption << ""; @@ -1189,7 +1189,7 @@ void GetWindowsList(Array &hWnd, Array &processId, Array & if((ret == Success || ret > 0) && list != NULL) { String sret; for(i = 0; i < count; i++) - sret << list[i]; // << " "; + sret << list[i]; XFreeStringList(list); caption.Add(FromSystemCharset(sret)); } else @@ -1666,15 +1666,33 @@ bool TakeWindowPlacement(HWND hwnd, RECT &rcNormalPosition, POINT &ptMinPosition place.length = sizeof(place); bool ret = GetWindowPlacement(hwnd, &place); + if (!ret) + return false; ptMinPosition = place.ptMinPosition; ptMaxPosition = place.ptMaxPosition; rcNormalPosition = place.rcNormalPosition; showcmd = place.showCmd; //SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_SHOWNORMAL - //flags = place.flags; // Always 0 return ret; } +int Window_GetStatus(int64 windowId) +{ + WINDOWPLACEMENT place; + + place.length = sizeof(place); + bool ret = GetWindowPlacement((HWND)windowId, &place); + if (!ret) + return Null; + + switch(place.showCmd) { + case SW_SHOWMAXIMIZED: return WINDOW_MAXIMIZED; + case SW_SHOWMINIMIZED: return WINDOW_MINIMIZED; + case SW_SHOWNORMAL: return WINDOW_NORMAL; + } + return Null; +} + bool Window_GetRect(int64 windowId, long &left, long &top, long &right, long &bottom) { RECT rcNormalPosition; diff --git a/bazaar/SysInfo/SysInfo.h b/bazaar/SysInfo/SysInfo.h index 01da3953d..77dfce509 100644 --- a/bazaar/SysInfo/SysInfo.h +++ b/bazaar/SysInfo/SysInfo.h @@ -57,6 +57,16 @@ void GetWindowsList(Upp::Array &wid, Upp::Array &pid, Upp::Array &fileName, Upp::Array &title); Upp::Array GetWindowsList(); +bool Window_GetRect(int64 windowId, long &left, long &top, long &right, long &bottom); +bool Window_SetRect(int64 windowId, long left, long top, long right, long bottom); +void Window_Bottom(int64 windowId); +void Window_Top(int64 windowId); +void Window_TopMost(int64 windowId); + +enum WINDOW_STATUS { + WINDOW_MAXIMIZED, WINDOW_MINIMIZED, WINDOW_NORMAL}; +int Window_GetStatus(int64 windowId); + ///////////////////////////////////////////////////////////////////// // Process list bool GetProcessList(Upp::Array &pid, Upp::Array &pNames); @@ -109,13 +119,6 @@ bool CloseCDTray(String drive); ///////////////////////////////////////////////////////////////////// // Key and mouse keys -bool Window_GetRect(int64 windowId, long &left, long &top, long &right, long &bottom); -bool Window_SetRect(int64 windowId, long left, long top, long right, long bottom); -void Window_Bottom(int64 windowId); -void Window_Top(int64 windowId); -void Window_TopMost(int64 windowId); - - bool Mouse_GetPos(long &x, long &y); bool Mouse_SetPos(long x, long y, int64 windowId); @@ -135,10 +138,14 @@ void Mouse_RightDblClick(); void Keyb_SendKeys(String text, long finalDelay = 100, long delayBetweenKeys = 50); bool Window_SaveCapture(int64 windowId, String fileName, int left = -1, int top = -1, int width = -1, int height = -1); +Image Window_SaveCapture(int64 windowId, int left = -1, int top = -1, int width = -1, int height = -1); bool Snap_Desktop(String fileName); bool Snap_DesktopRectangle(String fileName, int left, int top, int width, int height); bool Snap_Window(String fileName, int64 handle); +Image Snap_Desktop(); +Image Snap_DesktopRectangle(int left, int top, int width, int height); +Image Snap_Window(int64 handle); bool GetKeyLockStatus(bool &caps, bool &num, bool &scroll); bool SetKeyLockStatus(bool caps, bool num, bool scroll); @@ -153,7 +160,6 @@ bool Record_Window(String fileName, int duration, int64 handle, double secsFrame void SetDesktopWallPaper(const char *path); - struct SystemSignature : DeepCopyOption { String manufacturer, productName, version, mbSerial; int numberOfProcessors; diff --git a/bazaar/SysInfo/screengrab.cpp b/bazaar/SysInfo/screengrab.cpp index dfbc05dca..52f95077c 100644 --- a/bazaar/SysInfo/screengrab.cpp +++ b/bazaar/SysInfo/screengrab.cpp @@ -1,7 +1,31 @@ #include "SysInfo_in.h" +#include +#include +#include + NAMESPACE_UPP + +bool Window_SaveCapture(int64 windowId, String fileName, int left, int top, int width, int height) +{ + Image img = Window_SaveCapture(windowId, left, top, width, height); + if (IsNull(img)) + return false; + + if (GetFileExt(fileName) == ".png") { + PNGEncoder encoder; + return encoder.SaveFile(fileName, img); + } else if (GetFileExt(fileName) == ".jpg") { + JPGEncoder encoder(90); + return encoder.SaveFile(fileName, img); + } else if (GetFileExt(fileName) == ".bmp") { + BMPEncoder encoder; + return encoder.SaveFile(fileName, img); + } else + return false; +} + #if defined(PLATFORM_WIN32) || defined (PLATFORM_WIN64) #if defined(__MINGW32__) @@ -10,65 +34,66 @@ NAMESPACE_UPP #define labs(x) abs(x) #endif -bool Window_SaveCapture(int64 windowId, String fileName, int left, int top, int width, int height) +Image Window_SaveCapture(int64 windowId, int left, int top, int width, int height) { - HWND windowIdH = reinterpret_cast(windowId); - if (windowIdH == 0) - windowIdH = GetDesktopWindow(); - - if (GetFileExt(fileName) != ".bmp") - fileName += ".bmp"; + HWND wH = reinterpret_cast(windowId); + if (wH == 0) + wH = GetDesktopWindow(); RECT rc; - GetWindowRect (windowIdH, &rc); + if (!GetWindowRect(wH, &rc)) + return Null; if (left == -1) left = rc.left; if (top == -1) top = rc.top; if (width == -1) - width = rc.right-rc.left; + width = rc.right - rc.left; if (height == -1) - height = rc.bottom-rc.top; + height = rc.bottom - rc.top; - HDC hDC = GetDC(0); - HDC memDC = CreateCompatibleDC (hDC); - HBITMAP hb = CreateCompatibleBitmap (hDC, width, height); - HBITMAP OldBM = (HBITMAP)SelectObject(memDC, hb); - BitBlt(memDC, 0, 0, width, height , hDC, left, top , SRCCOPY); - - FILE *file = NULL; + HDC hDC = NULL; + HDC memDC = NULL; + HBITMAP hb = NULL; + HBITMAP oldBM = NULL; + Image img = Null; + ImageBuffer b; + + if ((hDC = GetDC(0)) == NULL) + goto end; + if ((memDC = CreateCompatibleDC(hDC)) == NULL) + goto end; + if ((hb = CreateCompatibleBitmap(hDC, width, height)) == NULL) + goto end; + if ((oldBM = (HBITMAP)SelectObject(memDC, hb)) == NULL) + goto end; + if (!BitBlt(memDC, 0, 0, width, height , hDC, left, top, SRCCOPY)) + goto end; + BITMAPINFO bmpInfo; - BITMAPFILEHEADER bmpFileHeader; ZeroMemory(&bmpInfo, sizeof(BITMAPINFO)); bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - GetDIBits(hDC, hb, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS); + if (!GetDIBits(hDC, hb, 0, 0, NULL, &bmpInfo, DIB_RGB_COLORS)) + goto end; if(bmpInfo.bmiHeader.biSizeImage <= 0) bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biWidth*labs(bmpInfo.bmiHeader.biHeight)*(bmpInfo.bmiHeader.biBitCount+7)/8; - char *cbuf = new char[bmpInfo.bmiHeader.biSizeImage]; - LPVOID buf = cbuf; bmpInfo.bmiHeader.biCompression = BI_RGB; - GetDIBits(hDC, hb, 0, bmpInfo.bmiHeader.biHeight, buf, &bmpInfo, DIB_RGB_COLORS); - if((file = _wfopen(fileName.ToWString(),L"wb")) == NULL) - return false; - bmpFileHeader.bfReserved1 = 0; - bmpFileHeader.bfReserved2 = 0; - bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+bmpInfo.bmiHeader.biSizeImage; - bmpFileHeader.bfType = 19778; - bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); - fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, file); - fwrite(&bmpInfo.bmiHeader,sizeof(BITMAPINFOHEADER), 1, file); - fwrite(buf,bmpInfo.bmiHeader.biSizeImage, 1, file); - - delete[] cbuf; - fclose(file); + bmpInfo.bmiHeader.biHeight = -height; - SelectObject(hDC, OldBM); + b.Create(width, height); + if (!GetDIBits(hDC, hb, 0, height, ~b, (BITMAPINFO *)&bmpInfo.bmiHeader, DIB_RGB_COLORS)) + goto end; + + img = b; + +end: + SelectObject(hDC, oldBM); DeleteObject(hb); DeleteDC(memDC); ReleaseDC(0, hDC); - return true; + return img; } class ScreenGrab { @@ -425,19 +450,87 @@ bool ScreenGrab::GrabSnapshot() #ifdef PLATFORM_POSIX -bool Window_SaveCapture(int64 windowId, String fileName, int left, int top, int width, int height) +Window GetToplevelParent(_XDisplay *display, Window window) { + Window parent; + Window root; + Window *children; + unsigned int numChildren; + + while (true) { + if (0 == XQueryTree(display, window, &root, &parent, &children, &numChildren)) + return -1; + if (children) + XFree(children); + + if (window == root || parent == root) + return window; + else + window = parent; + } +} + +Image Window_SaveCapture(int64 windowId, int left, int top, int width, int height) { - if (GetFileExt(fileName) != ".xwd") - fileName += ".xwd"; + SetSysInfoX11ErrorHandler(); - String command; + _XDisplay *dpy = XOpenDisplay (NULL); + if (!dpy) { + SetX11ErrorHandler(); + return Null; + } + int screen = DefaultScreen(dpy); if (windowId == 0) - command = "xwd -root -silent -out \"" + fileName + "\""; - else - command = "xwd -id " + FormatLong(windowId) + " -silent -out \"" + fileName + "\""; + windowId = RootWindow(dpy, screen); + else { + windowId = GetToplevelParent(dpy, windowId); + if (windowId < 0) + return Null; + } - String strret; - return Sys(command, strret) >= 0; + XWindowAttributes rc; + if (!XGetWindowAttributes(dpy, windowId, &rc)) { + XCloseDisplay(dpy); + SetX11ErrorHandler(); + return Null; + } + + if (left == -1) + left = rc.x; + if (top == -1) + top = rc.y; + if (width == -1) + width = rc.width; + if (height == -1) + height = rc.height; + + XImage *image = XGetImage(dpy, windowId, 0, 0, width, height, XAllPlanes(), ZPixmap); + if (image == NULL) + return Null; + + ImageBuffer ib(width, height); + + unsigned long red_mask = image->red_mask; + unsigned long green_mask = image->green_mask; + unsigned long blue_mask = image->blue_mask; + + for (int y = 0; y < height; y++) { + RGBA *row = ib[y]; + for (int x = 0; x < width ; x++) { + unsigned long pixel = XGetPixel(image, x, y); + unsigned char blue = pixel & blue_mask; + unsigned char green = (pixel & green_mask) >> 8; + unsigned char red = (pixel & red_mask) >> 16; + (row + x)->r = red; + (row + x)->g = green; + (row + x)->b = blue; + } + } + XCloseDisplay(dpy); + SetX11ErrorHandler(); + + Image img; + img = ib; + return img; } #endif @@ -457,4 +550,19 @@ bool Snap_Window(String fileName, int64 handle) return Window_SaveCapture(handle, fileName); } +Image Snap_Desktop() +{ + return Window_SaveCapture(0); +} + +Image Snap_DesktopRectangle(int left, int top, int width, int height) +{ + return Window_SaveCapture(0, left, top, width, height); +} + +Image Snap_Window(int64 handle) +{ + return Window_SaveCapture(handle); +} + END_UPP_NAMESPACE \ No newline at end of file diff --git a/bazaar/SysInfo/src.tpp/SysInfo$en-us.tpp b/bazaar/SysInfo/src.tpp/SysInfo$en-us.tpp index 25f95a9f4..647a779ea 100644 --- a/bazaar/SysInfo/src.tpp/SysInfo$en-us.tpp +++ b/bazaar/SysInfo/src.tpp/SysInfo$en-us.tpp @@ -348,18 +348,33 @@ om])&] [s2; Giving this function the [%-*@3 windowId], it returns the window location in the screen in [%-*@3 left], [%-*@3 top], [%-*@3 right] and [%-*@3 bottom].&] -[s0; -|Returns true if the values got are valid.&] +[s2; Returns true if the values got are valid.&] [s3; &] -[s4; &] -[s5;:Window`_SetRect`(long`,long`,long`,long`,long`):%- [@(0.0.255) void]_[* Window`_SetR -ect]([@(0.0.255) int64]_[*@3 windowId], [@(0.0.255) long]_[*@3 left], +[s4;%- &] +[s5;:Window`_SetRect`(int64`,long`,long`,long`,long`):%- [@(0.0.255) bool]_[* Window`_Set +Rect]([_^int64^ int64]_[*@3 windowId], [@(0.0.255) long]_[*@3 left], [@(0.0.255) long]_[*@3 top], [@(0.0.255) long]_[*@3 right], [@(0.0.255) long]_[*@3 bottom])&] [s2; Giving this function the [%-*@3 windowId], it sets the window location in the screen in [%-*@3 left], [%-*@3 top], [%-*@3 right] and [%-*@3 bottom].&] -[s2; -|Returns true if the window is relocated correctly..&] -[s0; &] +[s2; Returns true if the values got are valid.&] [s3; &] +[s4;%- &] +[s5;:Window`_Bottom`(int64`):%- [@(0.0.255) void]_[* Window`_Bottom]([_^int64^ int64]_[*@3 wi +ndowId])&] +[s2; Moves [%-*@3 windowId] to the bottom of all windows.&] +[s3; &] +[s4;%- &] +[s5;:Window`_Top`(int64`):%- [@(0.0.255) void]_[* Window`_Top]([_^int64^ int64]_[*@3 windowId +])&] +[s2; Moves [%-*@3 windowId] to the top of the windows.&] +[s3; &] +[s4;%- &] +[s5;:Window`_TopMost`(int64`):%- [@(0.0.255) void]_[* Window`_TopMost]([_^int64^ int64]_[*@3 w +indowId])&] +[s2; Moves [%-*@3 windowId] as the topmost window.&] +[s3; &] +[s0; &] [ {{10000@1 [s0; [* Mouse and keyboard handling]]}}&] [s3; &] [s5;:Mouse`_GetPos`(long`&`,long`&`):%- [@(0.0.255) bool]_[* Mouse`_GetPos]([@(0.0.255) lon @@ -368,7 +383,7 @@ g]_`&[*@3 x], [@(0.0.255) long]_`&[*@3 y])&] left corner is (0, 0).&] [s2; Returns true if the operation has been done successfully.&] [s3; &] -[s4;%- &] +[s4; &] [s5;:Mouse`_SetPos`(long`,long`,int64`):%- [@(0.0.255) bool]_[* Mouse`_SetPos]([@(0.0.255) l ong]_[*@3 x], [@(0.0.255) long]_[*@3 y], [@(0.0.255) int64]_[*@3 windowId])&] [s2; Sets the mouse position to [%-*@3 x] [%-*@3 y] referenced to the @@ -473,7 +488,7 @@ ileName])&] [s2; Saves the desktop in [%-*@3 fileName].as an image file.&] [s2; Allowed formats are:&] [s2;i150;O0; Posix:-|xwd&] -[s2;i150;O0; Windows:-|bmp&] +[s2;i150;O0; Windows:-|bmp, png, jpg&] [s3; &] [s4;%- &] [s5;:Snap`_DesktopRectangle`(String`,int`,int`,int`,int`):%- [@(0.0.255) bool]_[* Snap`_D @@ -483,7 +498,7 @@ esktopRectangle]([_^String^ String]_[*@3 fileName], [@(0.0.255) int]_[*@3 left], [%-*@3 width ]and [%-*@3 height].in [%-*@3 fileName] as an image file.&] [s2; Allowed formats are:&] [s2;i150;O0; Posix:-|xwd&] -[s2;i150;O0; Windows:-|bmp&] +[s2;i150;O0; Windows:-|bmp, png, jpg&] [s3; &] [s4;%- &] [s5;:Snap`_Window`(String`,int64`):%- [@(0.0.255) bool]_[* Snap`_Window]([_^String^ String]_ @@ -492,7 +507,23 @@ esktopRectangle]([_^String^ String]_[*@3 fileName], [@(0.0.255) int]_[*@3 left], as an image file.&] [s2; Allowed formats are:&] [s2;i150;O0; Posix:-|xwd&] -[s2;i150;O0; Windows:-|bmp&] +[s2;i150;O0; Windows:-|bmp, png, jpg&] +[s3; &] +[s4;%- &] +[s5;:Snap`_Desktop`(`):%- [_^Image^ Image]_[* Snap`_Desktop]()&] +[s2; Returns the desktop image.&] +[s3;%- &] +[s4;%- &] +[s5;:Snap`_DesktopRectangle`(int`,int`,int`,int`):%- [_^Image^ Image]_[* Snap`_DesktopRec +tangle]([@(0.0.255) int]_[*@3 left], [@(0.0.255) int]_[*@3 top], [@(0.0.255) int]_[*@3 width], + [@(0.0.255) int]_[*@3 height])&] +[s2; Returns the image of a desktop rectangle defined by [%-*@3 left], +[%-*@3 top], [%-*@3 width ]and [%-*@3 height].&] +[s3; &] +[s4;%- &] +[s5;:Snap`_Window`(int64`):%- [_^Image^ Image]_[* Snap`_Window]([_^int64^ int64]_[*@3 handle]) +&] +[s2; Returns a window image defined by its [%-*@3 handle].&] [s3; &] [s4;%- &] [s5;:Record`_Desktop`(String`,int`,int`,bool`):%- [@(0.0.255) bool]_[* Record`_Desktop]([_^String^ S