UWSCでバックグラウンドウインドウの表示を取得する
追記 20120528
uwsc4.8にて、chkimg,peekcolorがバックグラウンドに対応したため本記事はもはやゴミです(^^;;;
「UWSC」「バックグラウンド」で検索する人が多いようなので、ヒント第二弾。
第一弾は、
アプリケーションをバックグラウンド制御する - じゅんじゅんのきまぐれ
ですかね。
今度は、バックグラウンドウインドウの表示を取得する。
(限界はあるけど)
主旨
CHKIMGを行うのが主眼ではない。
(CHKIMG相当のことをスクリプトでやるのはパフォーマンス的にきつい)
SAVEIMGでも、バックグラウンドオプションがあるが、それだとファイル経由。
それをメモリー上で行うことを目標とした。
スクリプト
WindowImage.uws
OPTION EXPLICIT IFB GET_UWSC_NAME = "WindowImage.uws" THEN DIM path = "test.bmp" MSGBOX("Desktop: " + path + " " + WindowImage.Save(path)) MSGBOX("Window: " + path + " " + WindowImage.Save(path, IDTOHND(GETID(GET_FROMPOINT_WIN)))) MSGBOX("Window(client): " + path + " " + WindowImage.Save(path, IDTOHND(GETID(GET_FROMPOINT_WIN)),0,0,-1,-1,1)) ENDIF MODULE WindowImage DEF_DLL GetDC(hwnd): uint: user32 DEF_DLL CreateCompatibleBitmap(uint, int, int): uint: gdi32 DEF_DLL CreateCompatibleDC(uint): uint: gdi32 DEF_DLL SelectObject(uint, uint): uint: gdi32 DEF_DLL GetDeviceCaps(uint, int): int: gdi32 DEF_DLL ReleaseDC(hwnd, uint): int: user32 DEF_DLL BitBlt(uint, int, int, int, int, uint, int, int, uint): bool: gdi32 DEF_DLL GetDIBits(uint, uint, uint, uint, var byte[], var byte[], uint): int: gdi32 DEF_DLL PrintWindow(hwnd, uint, uint): bool: user32 DEF_DLL DeleteObject(uint): bool: gdi32 DEF_DLL CreateFileW(wstring, dword, dword, dword, dword, dword, dword): dword: kernel32 DEF_DLL WriteFile(dword, byte[], dword, var dword, dword): bool: kernel32 DEF_DLL CloseHandle(dword): bool: kernel32 PROCEDURE Log(msg) PRINT msg FEND FUNCTION GetBitCount(hDc) RESULT = GetDeviceCaps(hDc, 12) // 32/16bitは24bit扱いにする IF RESULT = 32 OR RESULT = 16 THEN RESULT = 24 // 8bitは未対応 IF RESULT = 8 THEN Log("Unsupported bit count.") FEND FUNCTION CalcLength(width, bitCount) RESULT = width * (bitCount / 8) IF RESULT Mod 4 <> 0 THEN RESULT = RESULT + 4 - (RESULT Mod 4) FEND PROCEDURE SetInt(var buf[], offset, data) DIM i FOR i = 0 TO 3 buf[offset + i] = data Mod 256 data = INT(data / 256) NEXT FEND FUNCTION PrivateGet(hwnd, x, y, w, h, var bitCount, var lineLen, var info[], var data[], cl) DIM hDc = GetDC(hwnd), i bitCount = GetBitCount(hDc) lineLen = CalcLength(w, bitCount) RESULT = (RESIZE(info, 39) = 39) IF RESULT THEN RESULT = (RESIZE(data, lineLen * h - 1) = lineLen * h - 1) // BITMAPINFOHEADER SetInt(info, 0, LENGTH(info)) // biSize SetInt(info, 4, w) // width SetInt(info, 8, h) // height SetInt(info, 12, 1) // biPlanes = 1固定 SetInt(info, 14, bitCount) FOR i = 16 TO 36 STEP 4 SetInt(info, i, 0) NEXT // ビットマップ取得 DIM hBitShot, hBitBuf, hShotDc = 0, hShotBit = 0, hBufDc = hDc, hBufBit = 0 IF RESULT AND (hDc <> 0) THEN hShotBit = CreateCompatibleBitmap(hDc, w, h) IF hShotBit <> 0 THEN hShotDc = CreateCompatibleDC(hDc) DIM x1 = 0, y1 = 0, x2 = x, y2 = y IFB x < 0 THEN x1 = -x x2 = 0 ENDIF IFB y < 0 THEN y1 = -y y2 = 0 ENDIF IFB hwnd <> 0 THEN IF hShotDc <> 0 THEN hBufBit = CreateCompatibleBitmap(hDc, x2 + w, y2 + h) IF hBufBit <> 0 THEN hBufDc = CreateCompatibleDC(hDc) IFB hBufDc <> 0 THEN hBitBuf = SelectObject(hBufDc, hBufBit) RESULT = PrintWindow(hwnd, hBufDc, cl) ENDIF ENDIF IFB hShotDc <> 0 THEN hBitShot = SelectObject(hShotDc, hShotBit) RESULT = BitBlt(hShotDc, x1, y1, w, h, hBufDc, x2, y2, $CC0020) ENDIF IF RESULT THEN RESULT = (GetDIBits(hShotDc, hShotBit, 0, h, data, info, 0) = h) IFB hBufBit <> 0 THEN SelectObject(hBufDc, hBitBuf) DeleteObject(hBufBit) ENDIF IF hBufDc <> hDc THEN DeleteObject(hBufDc) IFB hShotBit <> 0 THEN SelectObject(hShotDc, hBitShot) DeleteObject(hShotBit) ENDIF IF hShotDc <> 0 THEN DeleteObject(hShotDc) IF hDc <> 0 THEN ReleaseDC(hwnd, hDc) FEND FUNCTION Get(var bitCount, var lineLen, var info[], var data[], hwnd=0, x=0, y=0, w=-1, h=-1, cl=0) DIM id = HNDTOID(hwnd) IFB id = -1 THEN IF w = -1 THEN w = G_SCREEN_W IF h = -1 THEN h = G_SCREEN_H ELSEIF cl = 0 THEN IF w = -1 THEN w = STATUS(id, ST_WIDTH) IF h = -1 THEN h = STATUS(id, ST_HEIGHT) ELSE IF w = -1 THEN w = STATUS(id, ST_CLWIDTH) IF h = -1 THEN h = STATUS(id, ST_CLHEIGHT) ENDIF RESULT = PrivateGet(hwnd, x, y, w, h, bitCount, lineLen, info, data, cl) FEND FUNCTION Write(path, bitCount, lineLen, info[], data[], h=-1) DIM head[13] DIM headSize = LENGTH(head) + LENGTH(info) IF h = -1 THEN h = LENGTH(data) / lineLen DIM size = headSize + lineLen * h, written // BITMAPFILEHEADER SetInt(head, 0, 19778) // 'BM' SetInt(head, 2, size) // size SetInt(head, 6, 0) // reserve SetInt(head, 10, headSize) // bfOffBits // WriteFile DIM hFile = CreateFileW(path, $40000000, 0, 0, 2, $80, 0) RESULT = hFile > 0 IFB RESULT THEN RESULT = WriteFile(hFile, head, LENGTH(head), written, 0) RESULT = WriteFile(hFile, info, LENGTH(info), written, 0) RESULT = WriteFile(hFile, data, LENGTH(data), written, 0) ENDIF IF hFile > 0 THEN CloseHandle(hFile) FEND FUNCTION Save(path, hwnd=0, x=0, y=0, w=-1, h=-1, cl=0) DIM bitCount, lineLen, info[0], data[0] RESULT = Get(bitCount, lineLen, info, data, hwnd, x, y, w, h, cl) IF RESULT THEN RESULT = Write(path, bitCount, lineLen, info, data) FEND ENDMODULE
ま、興味の範囲なので、いろいろ適当です。
SAVEIMGと同じく、クライアントオプションをつけてますけど、XPとWin7で動作が違ったので、面倒になって適当です。
一応、clを1にすると、クライアントウインドウが対象になる、、、のです。
同様にバグが随所にある気がする、、、けど、あきた。