マルチモニタ環境のデスクトップキャプチャについて。
あいうえ子 2013/3/20(Wed) 23:55:19|NO.53117
4画面のマルチモニタ環境を所有しております。
各モニタがそれぞれバラバラな場所にあるため、一つのウィンドウから全体の状態を把握できたらと思いまして、
デスクトップ全体をキャプチャして縮小表示するソフトを作ってみました。
(http://chokuto.ifdef.jp/advanced/capturescreen.htmlを参考にさせていただきました)
#uselib "gdi32.dll"
#cfunc CreateDC "CreateDCA" sptr,sptr,sptr,int
#func DeleteDC "DeleteDC" int
#func BitBlt "BitBlt" int,int,int,int,int,int,int,int,int
#define NULL 0
#define SRCCOPY 0x00CC0020
#define CAPTUREBLT 0x40000000
wait 50
/* マルチモニタ環境の場合sxには横解像度の合計、syには最大の縦解像度を入力。
それ以外なら ginfo_dispx と ginfo_dispy を入力。 */
sx = ginfo_dispx : sy = ginfo_dispy
/* マルチモニタ環境の場合メインモニタの左上座標を0,0として左端のモニターの左上座標を入力
それ以外なら 0 を入力。 */
mlef = 0
/* 縮小の割合。1 で等倍。2 で1/2のサイズ */
rs = 5
; デスクトップ画面のサイズでバッファ画面を作成
buffer 0 , sx, sy
; スクリーン(1)を作成
screen 1, sx/rs ,sy/rs
repeat
gsel 0
; デスクトップ画面のデバイスコンテキスト取得
hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL)
; デスクトップ画面の画像をコピー
BitBlt hdc, 0, 0, sx, sy, hdcScreen, mlef, 0, SRCCOPY | CAPTUREBLT
; デバイスコンテキスト削除
DeleteDC hdcScreen
; 擬似マウスカーソルを表示
mx = ginfo_mx - mlef
my = ginfo_my
color 255,0,0
boxf mx,my,mx+10,my+10
; スクリーン(1)に縮小して描写
gsel 1
gzoom sx/rs ,sy/rs ,0, 0, 0 ,sx ,sy,1
await 100
loop
ここで二つ質問があります。
@スクリプトを実行するとマウスカーソルが点滅してしまいます。改善する方法はないでしょうか?
A実行中のスクリプトもキャプチャされるので目ざわりになってしまいます。キャプチャを回避する方法はありますでしょうか?
また、このスクリプトより簡素で軽量なスクリプトや、無駄な部分などがありましたら是非お教えください。
_hamyuu 2013/3/22(Fri) 08:37:15|NO.53142
マウスカーソルが点滅する現象は「BitBit」のパラメータ「CAPTUREBLT」が影響しています。
「 | CAPTUREBLT」を消せば点滅はなくなります。
↓を参考にしました。
http://technet.microsoft.com/ja-jp/magazine/2009.02.windowsconfidential.aspx
さらにレイヤードウインドウ(半透明ウィンドウなど)がキャプチャされなくなると思うので
HSPのウィンドウをレイヤードウィンドウ化すればHSPのウィンドウはキャプチャされないと思います。
実験していないのでもし間違っていたらすみません。
暇人 2013/3/22(Fri) 20:05:03|NO.53153
>スクリプトを実行するとマウスカーソルが点滅してしまいます。改善する方法はないでしょうか?
NO.53142で言われてるようにWin2000以降のBitBitの仕様って事らしい
ですが、消えるタイミング次第では見た目上は分からなく出来る
色々試してみたらCAPTUREBLT指定した場合BitBit中に走査線がVBlankタイミグになると
カーソルが画面から消えてるのが見えてしまうって事が分かった
BitBitの処理時間が短くなるように分割して実行し
絶対にVBlank前にコピー処理が終るようにすれば良い
>実行中のスクリプトもキャプチャされるので目ざわりになってしまいます。キャプチャを回避する方法はありますでしょうか?
NO.53142で言われてる方法で出来ます
が、Vista以降は無理みたい・・
WinXP環境のウィンドウ描画でティアリング(チラツキや波打つ現象)を無くすモジュール
http://hsp.tv/play/pforum.php?mode=pastwch&num=46392
↓のスクリプトは↑のモジュールを使ってます
#include "mod_d3d9vsync.hsp"
#uselib "gdi32.dll"
#cfunc CreateDC "CreateDCA" sptr,sptr,sptr,int
#func DeleteDC "DeleteDC" int
#func BitBlt "BitBlt" int,int,int,int,int,int,int,int,int
#define NULL 0
#define SRCCOPY 0x00CC0020
#define CAPTUREBLT 0x40000000
#uselib "user32.dll"
#func GetWindowLongA "GetWindowLongA" int , int
#func SetWindowLongA "SetWindowLongA" int , int , int
#func SetLayeredWindowAttributes "SetLayeredWindowAttributes" int , int , int , int
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 1
#define LWA_ALPHA 2
#define GWL_EXSTYLE -20
wait 50
/* マルチモニタ環境の場合sxには横解像度の合計、syには最大の縦解像度を入力。
それ以外なら ginfo_dispx と ginfo_dispy を入力。 */
sx = ginfo_dispx : sy = ginfo_dispy
dvsxmax=limit(sx/ginfo_dispx,1,10)+((sx\ginfo_dispx)>0)
dvsymax=limit(sy/ginfo_dispy,1,10)+((sy\ginfo_dispy)>0)
/* マルチモニタ環境の場合メインモニタの左上座標を0,0として左端のモニターの左上座標を入力
それ以外なら 0 を入力。 */
mlef = 0
/* 縮小の割合。1 で等倍。2 で1/2のサイズ */
rs = 5
; デスクトップ画面のサイズでバッファ画面を作成
buffer 0 , sx, sy
; スクリーン(1)を作成
screen 1, sx/rs ,sy/rs
//レイヤーウィンドウを設定
GetWindowLongA hwnd , GWL_EXSTYLE
SetWindowLongA hwnd , GWL_EXSTYLE , stat | WS_EX_LAYERED
SetLayeredWindowAttributes hwnd, 0, 255, LWA_ALPHA //ALPHAモードで不透明設定
width sx/rs ,sy/rs,0,0 //ウィンドウ再描画の代わり
//レイヤーウィンドウの左上座標とタイトル枠を含めたサイズを取得
wx1=ginfo_wx1
wy1=ginfo_wy1
wsx=ginfo_sizex
wsy=ginfo_sizey
//レイヤーウィンドウの下の画像一時コピー用バッファ
buffer 2 ,wsx ,wsy //レイヤーウィンドウと同サイズのバッファを確保
hdc2=hdc //デバイスコンテキスト
; デスクトップ画面のデバイスコンテキスト取得
hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL)
onexit *ext
d3d9vsync_init
if stat < 0 {
if -5 ! stat {dialog "GetRasterStatusを使用できない環境です":end}
}
dvymax=limit(int(((1.0*sx*sy)/(1920*1080))*4),1,100) //1920*1080を4分割でコピーするのを基準にして、分割数を算出
dvy=sy/dvymax
dvymax+=(sy\dvy)>0 //あまりが出たら分割数+1
repeat
gsel 0
mcnt=0
_dvy=0
repeat dvymax
repeat
_Sleep@mod_d3d9vsync 1
GetRasterStatus v,r //VBlankとラスター位置取得
if r<(ginfo_dispy/2) {break} //ラスターがデスクトップYサイズの半分より上なら抜ける
loop
if v{_Sleep@mod_d3d9vsync 1} //VBlank中ならスリープ1ms(1msあればVBlankを抜けられるだろうから)
mx(mcnt)=ginfo_mx - mlef
my(mcnt)=ginfo_my
mcnt++
; デスクトップ画面の画像をコピー(syをdvymax分割してコピー)
BitBlt hdc, 0, _dvy, sx, dvy, hdcScreen, mlef, _dvy, SRCCOPY | CAPTUREBLT
_dvy+dvy
loop
//Vista以降はCAPTUREBLT関係なくレイヤーウィンドウもコピーされてしまうらしい・・・
//レイヤーウィンドウ下の画像をバッファ2にコピー
BitBlt hdc2, 0, 0, wsx, wsy, hdcScreen, wx1, wy1, SRCCOPY
//バッファ2からバッファ0にコピー
BitBlt hdc, wx1-mlef, wy1, wsx, wsy, hdc2, 0, 0, SRCCOPY
mx(mcnt)=ginfo_mx - mlef
my(mcnt)=ginfo_my
mcnt++
; 擬似マウスカーソルを表示
color 255
repeat mcnt
boxf mx(cnt),my(cnt),mx(cnt)+10,my(cnt)+10
loop
; スクリーン(1)に縮小して描写
gsel 1
//gzoomは重いのでデスクトップより大きい分は分割してコピー
repeat dvsymax
cnty=cnt
repeat dvsxmax
pos cnt*sx/rs/dvsxmax,cnty*sy/rs/dvsymax
gzoom sx/rs/dvsxmax ,sy/rs/dvsymax ,0, cnt*sx/dvsxmax, cnty*sy/dvsymax ,sx/dvsxmax ,sy/dvsymax,1
redraw 1
redraw 0
await 100
loop
loop
wx1=ginfo_wx1
wy1=ginfo_wy1
wsx=ginfo_sizex
wsy=ginfo_sizey
loop
*ext
; デバイスコンテキスト削除
DeleteDC hdcScreen
end
XPsp3の環境だとカーソルの点滅も実行ウィンドウが写りこむこともなく成功するんですが・・・
Vista以降だとどうなるか・・・
DWM サムネイル APIがどうこうって所まで調べたけどVista以降は持って無いからこれ以上は分からない・・・
暇人 2013/3/22(Fri) 23:17:04|NO.53158
あ、バッファ2は不要だった(間違いがあったので削除修正して再掲載)
>//レイヤーウィンドウ下の画像をバッファ2にコピー
> BitBlt hdc2, 0, 0, wsx, wsy, hdcScreen, wx1, wy1, SRCCOPY
>//バッファ2からバッファ0にコピー
> BitBlt hdc, wx1-mlef, wy1, wsx, wsy, hdc2, 0, 0, SRCCOPY
これを
//レイヤーウィンドウ下の画像をバッファ0にコピー
BitBlt hdc, wx1-mlef, wy1, wsx, wsy, hdcScreen, wx1, wy1, SRCCOPY
に変更
あいうえ子 2013/3/23(Sat) 07:46:48|NO.53161
お二人ともありがとうございます。
>_hamyuu様
マウスカーソルの点滅は無くなりました。ありがとうございます。
ですが、Windows7の環境ですとレイヤーウィンドウもキャプチャされてしまうようです。
>暇人様
スクリプトを実行してしましたが、やはり全てキャプチャされてしまいます…
暇人 2013/3/23(Sat) 16:25:39|NO.53169
>スクリプトを実行してしましたが、やはり全てキャプチャされてしまいます…
やっぱりね・・・
もう一つ方法があるから後で書いてみる(今実験中だけど実行ウィンドウのサイズが大きいと使えないかも・・・)
XPだとSRCCOPY | CAPTUREBLT よりSRCCOPYだけの方がかなり軽いんだけどVista以降も同じかな?
同じならVista以降用にSRCCOPYだけ使った方が良いな・・・
暇人 2013/3/23(Sat) 22:21:06|NO.53186
出来たったぽい?
実行ウィンドウより下に走査線が来たら透明ウィンドウにして
コピー終ったら不透明にするって方法でXP環境では問題なく動いた
タイミングがシビアだから結局Vista以降でどうなるか分からないけど・・・
Vista以降用にCAPTUREBLTをなくしたので
カーソル点滅回避処理は省いてる
#include "mod_d3d9vsync.hsp"
#uselib "gdi32.dll"
#cfunc CreateDC "CreateDCA" sptr,sptr,sptr,int
#func DeleteDC "DeleteDC" int
#func BitBlt "BitBlt" int,int,int,int,int,int,int,int,int
#define NULL 0
#define SRCCOPY 0x00CC0020
#define CAPTUREBLT 0x40000000
#uselib "user32.dll"
#func GetWindowLongA "GetWindowLongA" int , int
#func SetWindowLongA "SetWindowLongA" int , int , int
#func SetLayeredWindowAttributes "SetLayeredWindowAttributes" int , int , int , int
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 1
#define LWA_ALPHA 2
#define GWL_EXSTYLE -20
wait 50
/* マルチモニタ環境の場合sxには横解像度の合計、syには最大の縦解像度を入力。
それ以外なら ginfo_dispx と ginfo_dispy を入力。 */
sx = ginfo_dispx : sy = ginfo_dispy
dv_sxmax=limit(sx/ginfo_dispx,1,10) //分割数
dv_symax=limit(sy/ginfo_dispy,1,10)
dv_sxsize=sx/dv_sxmax //分割サイズ
dv_sysize=sy/dv_symax
/* マルチモニタ環境の場合メインモニタの左上座標を0,0として左端のモニターの左上座標を入力
それ以外なら 0 を入力。 */
mlef = 0
/* 縮小の割合。%で設定、100で等倍。50 で1/2のサイズ */
percent = 20.0
rs = 100.0/percent
rsx=int((double(percent)/100)*sx)
rsy=int((double(percent)/100)*sy)
dv_rsxsize=rsx/dv_sxmax //分割サイズ(分割数はsx,syのを使用)
dv_rsysize=rsy/dv_symax
dv_sxmax+=((sx\ginfo_dispx)>0) //余ってる分があったら分割数+1(これはsx,syに対してなので注意)
dv_symax+=((sy\ginfo_dispy)>0)
; デスクトップ画面のサイズでバッファ画面を作成
buffer 0 , sx, sy
hdc0=hdc
; スクリーン(1)を作成
screen 1, rsx ,rsy
//レイヤードウィンドウを設定
GetWindowLongA hwnd , GWL_EXSTYLE
SetWindowLongA hwnd , GWL_EXSTYLE , stat | WS_EX_LAYERED
SetLayeredWindowAttributes hwnd, 0, 255, LWA_ALPHA //ALPHAモードで不透明設定
hwnd1=hwnd
width rsx ,rsy,0,0 //ウィンドウ再描画の代わり
//レイヤードウィンドウの左上座標とタイトル枠を含めたサイズを取得
wx1=ginfo_wx1
wy1=ginfo_wy1
wsx=ginfo_sizex
wsy=ginfo_sizey
dv_rsymax=limit(int(((1.0*wsx*wsy)/(ginfo_dispx*ginfo_dispy/10))),1,100) //1920*1080/10のサイズならコピーして大丈夫だったので、それ以上は分割(ちらつく場合は要調整)
dv_sizey=wsy/dv_rsymax
dv_rsymax+=(wsy\dv_rsymax)>0 //あまりが出たら分割数+1
//adjust 実行ウィンドウが大きいとチラつくのでラスター監視位置をずらす
adjust=0 //自分の環境ではYサイズが500超えるぐらいだと100程度で収まる(完全じゃないけど・・・)
pos 0,0
input adjust,32,20
//レイヤードウィンドウの下の画像一時コピー用バッファ
buffer 2 , wsx, wsy
hdc2=hdc
; デスクトップ画面のデバイスコンテキスト取得
hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL)
onexit *ext
d3d9vsync_init
if stat < 0 {
if -5 ! stat {dialog "GetRasterStatusを使用できない環境です":end}
}
mcntmax=4
dim mx,mcntmax
dim my,mcntmax
repeat
repeat dv_sxmax*dv_symax
_dvx=(cnt\dv_sxmax)*dv_sxsize
_dvy=(cnt/dv_sxmax)*dv_sysize
mx(mcnt\mcntmax)=ginfo_mx - mlef
my(mcnt\mcntmax)=ginfo_my
mcnt++
; デスクトップ画面の画像をコピー(syをdv_sxmax*dv_sxmax分割してコピー)
BitBlt hdc0, _dvx, _dvy, dv_sxsize, dv_sysize, hdcScreen, mlef+_dvx, _dvy, SRCCOPY
repeat
_Sleep@mod_d3d9vsync 1
GetRasterStatus v,r //VBlankとラスター位置取得
if v{break} //VBlank中
loop
repeat
GetRasterStatus v,r //VBlankとラスター位置取得
if r>(wy1+wsy-adjust) or ((wy1+wsy)>ginfo_dispy){break} //ラスターが実行ウィンドウより下なら抜ける
if ((wy1+wsy-adjust)-r)>150 {_Sleep@mod_d3d9vsync 1} //目的の位置まで150以上有ったら1msスリープ
loop
//実行ウィンドウより下に走査線が有る時に実行ウィンドウを透明にしてコピーして直ぐに不透明に戻す
SetLayeredWindowAttributes hwnd1, 0, 100, LWA_ALPHA //ALPHAモードで透明に設定
BitBlt hdc2, 0, (loopcnt\dv_rsymax)*dv_sizey, wsx, dv_sizey, hdcScreen, wx1, wy1+(loopcnt\dv_rsymax)*dv_sizey, SRCCOPY
SetLayeredWindowAttributes hwnd1, 0, 255, LWA_ALPHA //ALPHAモードで不透明設定
mx(mcnt\mcntmax)=ginfo_mx - mlef
my(mcnt\mcntmax)=ginfo_my
mcnt++
await 0
gsel 0
//バックバッファ2からバッファ0にコピー
if (cnt=((wx1-mlef)/dv_sxsize)+((wy1/dv_sysize)*dv_sxmax)) or (cnt=((wx1+wsx-mlef-1)/dv_sxsize)+(((wy1+wsy-1)/dv_sysize)*dv_sxmax)) {
gmode 0:pos wx1-mlef, wy1:gcopy 2, 0, 0, wsx, wsy //実行ウィンドウがある分割部分の処理の時だけコピー(デスクトップサイズより大きいのは想定してない)
}
; スクリーン(1)に縮小して描写
gsel 1
//gzoomは重いのでデスクトップより大きい分は分割してコピー
pos (cnt\dv_sxmax)*dv_rsxsize,(cnt/dv_sxmax)*dv_rsysize
gzoom dv_rsxsize ,dv_rsysize ,0, _dvx, _dvy ,dv_sxsize ,dv_sysize,1
; 擬似マウスカーソルを表示
color 255
repeat 4,mcnt\mcntmax
boxf (mx(cnt\mcntmax))/rs,my(cnt\mcntmax)/rs,(mx(cnt\mcntmax))/rs+2,my(cnt\mcntmax)/rs+2
loop
redraw 1
redraw 0
await 100
wx1=ginfo_wx1
wy1=ginfo_wy1
if wsx ! ginfo_sizex { //ウィンドウのりサイズに対応
//xをリサイズすると比率を変えずにサイズを変更できる
dv_rsxsize=ginfo_winx/dv_sxmax
dv_rsysize=int(double(dv_rsxsize)/(double(sx)/sy))
width dv_rsxsize,dv_rsysize
wsx=ginfo_sizex
wsy=ginfo_sizey
}else{
if wsy ! ginfo_sizey {//yのリサイズはxのサイズを変えない
dv_rsysize=ginfo_winy/dv_symax //ウィンドウのりサイズに対応
wsy=ginfo_sizey
}
}
loopcnt++
loop
loop
*ext
; デバイスコンテキスト削除
DeleteDC hdcScreen
end
キャプチャ元が大きくなっても負荷が増えないようにしたらわかり難くなったな・・・
暇人 2013/3/24(Sun) 19:29:32|NO.53217
少し画面更新が増えるようにしてみた
> if v{break} //VBlank中
これを
if v or (r<(wy1+wsy-adjust)){break} //VBlank中
に置き換え
無駄に1フレーム待ってたのを無くせるのと
Sleep 1でもVBlankやり過ごす事も有りそうなので・・・
あいうえ子 2013/3/24(Sun) 21:32:25|NO.53224
おお、消えています!すごい!
しかしやはり画面がちらついてしまいますね…
XPと7は根っから構造が違うのでしょうか…
暇人 2013/3/24(Sun) 22:57:02|NO.53228
>おお、消えています!すごい!
おぉ
>しかしやはり画面がちらついてしまいますね…
あら・・・
実行ウィンドウの同じような場所がちらつくなら
adjustの調節や実行ウィンドウの位置を動かしてなんとかなりそうだけど・・・
> repeat
> _Sleep@mod_d3d9vsync 1
> GetRasterStatus v,r //VBlankとラスター位置取得
> if v{break} //VBlank中
> loop
>
> repeat
> GetRasterStatus v,r //VBlankとラスター位置取得
> if r>(wy1+wsy-adjust) or ((wy1+wsy)>ginfo_dispy){break} //ラスターが実行ウィンドウより下なら抜ける
> if ((wy1+wsy-adjust)-r)>150 {_Sleep@mod_d3d9vsync 1} //目的の位置まで150以上有ったら1msスリープ
> loop
この部分を
repeat
GetRasterStatus v,r //VBlankとラスター位置取得
if v or (r<limit((wy1+wsy-adjust),1,ginfo_dispy)){break} //VBlank中
_Sleep@mod_d3d9vsync 1
loop
repeat
GetRasterStatus v,r //VBlankとラスター位置取得
if r>=limit((wy1+wsy-adjust),1,ginfo_dispy-wsy) or ((wy1+wsy)>ginfo_dispy){break} //ラスターが実行ウィンドウより下なら抜ける
if ((wy1+wsy-adjust)-r)>250 {_Sleep@mod_d3d9vsync 1} //目的の位置まで250以上有ったら1msスリープ
loop
に置き換えて(置き換えないと負数入力すると無限ループに・・・)
adjustのinputに-ginfo_dispy〜ginfo_dispyを入れて
ウィンドウの位置を変えたりして変化があるか試して欲しい
inputが負数までの入力を考えて無くて小さいから横64ぐらいにした方が良いかも
あいうえ子 2013/3/24(Sun) 23:18:16|NO.53230
しばらく実行していると、チラつきが止まる時がありますが、またしばらくするとちらついてしまいますね…。
うーん
暇人 2013/3/24(Sun) 23:49:33|NO.53232
報告ありがとう
>チラつきが止まる時がありますが、またしばらくするとちらついてしまいますね…。
やっぱりVista以降はOSが色々やっててやっかいだなぁ
DWMあたりいじれば何とかなりそうなならないような
自分じゃ試せないから手詰まり・・・
Vista以降はMagnification API使えって事かも
色々出来るみたいだが、Direct3Dの画面はキャプチャできないらしい・・・
あいうえ子 2013/3/25(Mon) 21:48:20|NO.53250
やはり難しいですか…透過は諦めます。
なんだか無駄なことに付き合わせてしまってすみません。
ありがとうございました。
暇人 2013/3/27(Wed) 23:50:13|NO.53291
まだやってたり・・・
妥協案って言うかインチキと言うか、そんな方法でやってみた
早い話定期的に書き換えるんじゃなく変化があったら書き換えるようにして
なるべくウィンドウ下の再コピーを減らす方法
実行ウィンドウの下に何も置かなければウィンドウに
マウスを乗せるまで再コピーしないから普段はらちらつかない
NO.53186のは計算間違いとか色々してるからそれも修正・・・
描画エリア内にマウスが入るとマウス透過する半透明
タイトルダブルクリックで設定ウィンドウ表示
alphaminはマウスを描画エリアに乗せたときの半透明値
alphamaxは通常時の半透明値
#include "mod_d3d9vsync.hsp"
#uselib "gdi32.dll"
#cfunc CreateDC "CreateDCA" sptr,sptr,sptr,int
#func DeleteDC "DeleteDC" int
#func BitBlt "BitBlt" int,int,int,int,int,int,int,int,int
#cfunc getPixel "GetPixel" int,int,int
#define NULL 0
#define SRCCOPY 0x00CC0020
#define CAPTUREBLT 0x40000000
#uselib "user32.dll"
#cfunc GetWindowLongA "GetWindowLongA" int , int
#func SetWindowLongA "SetWindowLongA" int , int , int
#func SetLayeredWindowAttributes "SetLayeredWindowAttributes" int , int , int , int
#func SetWindowPos "SetWindowPos" int, int, int, int, int, int, int
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 1
#define LWA_ALPHA 2
#define GWL_EXSTYLE -20
#define GWL_STYLE -16
#define WM_NULL 0x0000
#define WM_CREATE 0x0001
#define WM_DESTROY 0x0002
#define WM_MOVE 0x0003
#define WM_SIZE 0x0005
#define WM_PAINT 0x000F
#define WM_QUERYNEWPALETTE 0x030F
#define WM_SETREDRAW 0x000B
#define WM_NCLBUTTONDBLCLK 0x00A3
#const SWP_NOMOVE 0x02
#const SWP_NOSIZE 0x0001
#const SWP_NOZORDER 0x0004
#const SWP_NOACTIVATE 0x0010
#const SWP_FRAMECHANGED 0x020
#const SWP_SHOWWINDOW 0x040
#const SWP_HIDEWINDOW 0x080
#const SWP_NOCOPYBITS 0x0100
#const SWP_NOOWNERZORDER 0x0200
/* マルチモニタ環境の場合sxには横解像度の合計、syには最大の縦解像度を入力。
それ以外なら ginfo_dispx と ginfo_dispy を入力。 */
sx = ginfo_dispx: sy = ginfo_dispy
dv_sxmax=limit(sx/ginfo_dispx,1,10) //分割数
dv_symax=limit(sy/ginfo_dispy,1,10)
dv_sxsize=sx/dv_sxmax //分割サイズ
dv_sysize=sy/dv_symax
/* マルチモニタ環境の場合メインモニタの左上座標を0,0として左端のモニターの左上座標を入力
それ以外なら 0 を入力。 */
mlef = 0
/* 縮小の割合。%で設定、100で等倍。50 で1/2のサイズ */
percent = 40.0
rs = 100.0/percent
rsx=int((double(percent)/100)*sx)
rsy=int((double(percent)/100)*sy)
dv_rsxsize=rsx/dv_sxmax //分割サイズ(分割数はsx,syのを使用)
dv_rsysize=rsy/dv_symax
_dv_sxmax=dv_sxmax
_dv_symax=dv_symax
dv_sxmax+=((sx\ginfo_dispx)>0) //余ってる分があったら分割数+1(これはsx,syに対してなので注意)
dv_symax+=((sy\ginfo_dispy)>0)
; デスクトップ画面のサイズでバッファ画面を作成
buffer 0 , sx, sy
hdc0=hdc
wait 1
; スクリーン(1)を作成
screen 1, rsx ,rsy,2,0,0
hdc1=hdc
hwnd1=hwnd
//レイヤードウィンドウを設定
// STYLE(hwnd,追加STYLE,削除STYLE)
#define ctype STYLE(%1,%2,%3=0) %1,GWL_STYLE,((GetWindowLongA(%1,GWL_STYLE) | (%2)) | (%3)) ^ (%3)
#define ctype EXSTYLE(%1,%2=0,%3=0) %1,GWL_EXSTYLE,((GetWindowLongA(%1,GWL_EXSTYLE) | (%2)) | (%3)) ^ (%3)
#define WS_EX_TRANSPARENT $20
SetWindowLongA EXSTYLE(hwnd1,WS_EX_LAYERED)
alphamin=100
alphamax=255
ALPHA=alphamax
SetLayeredWindowAttributes hwnd1, 0, ALPHA, LWA_ALPHA //ALPHAモードで不透明設定
SetWindowPos hwnd1,0 ,0,0 ,0,0 ,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW
wait 1
//レイヤードウィンドウの左上座標とタイトル枠を含めたサイズを取得
wx1=ginfo_wx1
wy1=ginfo_wy1
wx2=ginfo_wx2
wy2=ginfo_wy2
wsx=ginfo_sizex
wsy=ginfo_sizey
dv_rsymax=limit(int(((1.0*wsx*wsy)/(ginfo_dispx*ginfo_dispy/10))),1,wsy) //1920*1080/20のサイズならコピーして大丈夫だったので、それ以上は分割,NO.53186の半分にした(ちらつく場合は要調整)
dv_sizey=wsy/dv_rsymax
o=dv_rsymax
dv_rsymax=wsy/dv_sizey+((wsy\dv_sizey)>0) //確実にdv_sizey*dv_sizeyがwsy以上になるようにする
//adjust 実行ウィンドウが大きいとチラつくのでラスター監視位置をずらす
adjust=0 //自分の環境ではYサイズが500超えるぐらいだと100程度で収まる(完全じゃないけど・・・)
//設定ウィンドウ非表示で設置
conf_id=100
screen conf_id, 220,80 ,8+2
title "設定"
pos 8,8
mes "adjust"
mes "alphamin"
mes "alphamax"
_alphamin=alphamin
_alphamax=alphamax
pos 80,16
input adjust,64,16
input _alphamin,64,16
alphamin_id=stat
input _alphamax,64,16
alphamax_id=stat
pos 145,16+19
button gosub "適用",*conf_set
//レイヤードウィンドウの下の画像一時コピー用バッファ
buffer 2 , wsx, wsy
hdc2=hdc
gsel 1,2
; デスクトップ画面のデバイスコンテキスト取得
hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL)
onexit gosub *exit
d3d9vsync_init
if stat < 0 {
if -5 ! stat {dialog "GetRasterStatusを使用できない環境です":end}
}
mcntmax=4
dim mx,mcntmax
dim my,mcntmax
oncmd gosub *wm_sub,WM_SIZ
oncmd gosub *wm_sub,WM_MOVE
oncmd gosub *wm_sub,WM_QUERYNEWPALETTE
oncmd gosub *wm_sub,WM_NCLBUTTONDBLCLK
copy_f=1 //実行ウィンドウの下をコピーさせるフラグ
repeat
repeat dv_sxmax*dv_symax
if ((wx1+4)<ginfo_mx) and ((wy1+22)<ginfo_my) and ((wx1-4+wsx)>ginfo_mx) and ((wy1-4+wsy)>ginfo_my) {//マウスが実行ウィンドウの描画エリア内に入った
if ALPHA ! alphamin {//半透明にしてマウス操作も下に透過する(WS_EX_TRANSPARENT)
copy_f++
ALPHA=alphamin
SetLayeredWindowAttributes hwnd1, 0, ALPHA, LWA_ALPHA
SetWindowLongA EXSTYLE(hwnd1,WS_EX_TRANSPARENT)
SetWindowPos hwnd1,0 ,0,0 ,0,0 ,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW
}
}else{ ///マウスが実行ウィンドウ描画エリア外
if ALPHA ! alphamax {//半透明を戻しタイトル枠をクリック出来る様にWS_EX_TRANSPARENTを削除
copy_f++
ALPHA=alphamax
SetWindowLongA EXSTYLE(hwnd1,0,WS_EX_TRANSPARENT)
SetWindowPos hwnd1,0 ,0,0 ,0,0 ,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW
}
}
_dvx=(cnt\dv_sxmax)*dv_sxsize
_dvy=(cnt/dv_sxmax)*dv_sysize
mx(mcnt\mcntmax)=ginfo_mx - mlef
my(mcnt\mcntmax)=ginfo_my
mcnt++
//実行ウィンドウに隣接するドットに変化があったかチェック(4ドット毎)
if (cnt=((wx1-mlef-1)/dv_sxsize)+((wy1/dv_sysize)*dv_sxmax)) or (cnt=((wx1+wsx-mlef)/dv_sxsize)+(((wy1+wsy)/dv_sysize)*dv_sxmax)) and (test=0) {
if (wx2-mlef)<sx{
repeat (wsy-1)/4,1
if (getPixel(hdc0,wx2-mlef, wy1+cnt*4) ! getPixel(hdcScreen,wx2,wy1+cnt*4)) {
copy_f++
break
}
loop
}
if (wx1-mlef)>0 and (test=0){
repeat (wsy-1)/4,1
if (getPixel(hdc0,wx1-mlef-1, wy1+cnt*4) ! getPixel(hdcScreen,wx1-1,wy1+cnt*4)) {
copy_f++
break
}
loop
}
if (wy1>0) and (test=0){
repeat (wsx-1)/4,1
if (getPixel(hdc0,wx1-mlef+cnt*4,wy1-1) ! getPixel(hdcScreen,wx1+cnt*4,wy1-1)){
copy_f++
break
}
loop
}
if (wy2<sy) and (test=0) {
repeat (wsx-1)/4,1
if (getPixel(hdc0,wx1-mlef+cnt*4,wy2) ! getPixel(hdcScreen,wx1+cnt*4,wy2)) {
copy_f++
break
}
loop
}
}
; デスクトップ画面の画像をコピー(syをdv_sxmax*dv_sxmax分割してコピー)
BitBlt hdc0, _dvx, _dvy, dv_sxsize, dv_sysize, hdcScreen, mlef+_dvx, _dvy, SRCCOPY
if copy_f {//実行ウィンドウ含む周辺で何か変化があった
if copy_f_bak=copy_f{//変化が終ったら実行ウィンドウの下を画像をhdc2にコピー
repeat
GetRasterStatus v,r //VBlankとラスター位置取得
if v or (r<limit((wy1+wsy-adjust),1,ginfo_dispy))*0{break} //VBlank中
_Sleep@mod_d3d9vsync 1
loop
repeat
GetRasterStatus v,r //VBlankとラスター位置取得
if r>=limit((wy1+wsy-adjust),1,ginfo_dispy-50) or ((wy1+wsy)>ginfo_dispy){break} //ラスターが実行ウィンドウより下なら抜ける
if (limit((wy1+wsy-adjust),1,ginfo_dispy))>250 {_Sleep@mod_d3d9vsync 1} //目的の位置まで250以上有ったら1msスリープ
loop
//実行ウィンドウより下に走査線が有る時に実行ウィンドウを透明にしてコピーして直ぐに不透明に戻す
SetLayeredWindowAttributes hwnd1, 0, 0, LWA_ALPHA //ALPHAモードで透明に設定
BitBlt hdc2, 0, ((wcnt-wcnt_bak)\dv_rsymax)*dv_sizey, wsx, dv_sizey, hdcScreen, wx1, wy1+((wcnt-wcnt_bak)\dv_rsymax)*dv_sizey, SRCCOPY
SetLayeredWindowAttributes hwnd1, 0, ALPHA, LWA_ALPHA //ALPHAモードで不透明設定
wcnt++
if (wcnt-wcnt_bak)>=dv_rsymax{copy_f=0:copy_f_bak=0:wcnt_bak=wcnt}//全てコピーされた
}else{//まだ変化中なので一旦抜ける
wcnt_bak=wcnt
}
copy_f_bak=copy_f
}
mx(mcnt\mcntmax)=ginfo_mx - mlef
my(mcnt\mcntmax)=ginfo_my
mcnt++
await 0
gsel 0
//バックバッファ2からバッファ0にコピー
if (cnt=((wx1-mlef)/dv_sxsize)+((wy1/dv_sysize)*dv_sxmax)) or (cnt=((wx1+wsx-mlef-1)/dv_sxsize)+(((wy1+wsy-1)/dv_sysize)*dv_sxmax)) {
gmode 0:pos wx1-mlef, wy1:gcopy 2, 0, 0, wsx, wsy //実行ウィンドウがある分割部分の処理の時だけコピー(デスクトップサイズより大きいのは想定してない)
}
; スクリーン(1)に縮小して描写
gsel 1
//gzoomは重いのでデスクトップより大きい分は分割してコピー
pos (cnt\dv_sxmax)*dv_rsxsize,(cnt/dv_sxmax)*dv_rsysize
gzoom dv_rsxsize ,dv_rsysize ,0, _dvx, _dvy ,dv_sxsize ,dv_sysize,1
; 擬似マウスカーソルを表示
perx=(1.0*ginfo_winx)/sx
pery=(1.0*ginfo_winy)/sy
color 255
repeat 4,mcnt\mcntmax
boxf perx*(mx(cnt\mcntmax)),pery*my(cnt\mcntmax),perx*(mx(cnt\mcntmax))+2,pery*my(cnt\mcntmax)+2
loop
redraw 1
redraw 0
await 100
gsel 1
if wsx ! ginfo_sizex { //ウィンドウのりサイズに対応
//xをリサイズすると比率を変えずにサイズを変更できる
dv_rsxsize=ginfo_winx/_dv_sxmax
dv_rsysize=int(double(dv_rsxsize*_dv_sxmax)/(double(sx)/sy))/_dv_symax
width dv_rsxsize*_dv_sxmax,dv_rsysize*_dv_symax
wsx=ginfo_sizex
wsy=ginfo_sizey
}else{
if wsy ! ginfo_sizey {//yのリサイズはxのサイズを変えない
dv_rsysize=ginfo_winy/_dv_symax //ウィンドウのりサイズに対応
width ginfo_winx,dv_rsysize*_dv_symax
wsy=ginfo_sizey
wsx=ginfo_sizex
}
}
wx1=ginfo_wx1
wy1=ginfo_wy1
wx2=ginfo_wx2
wy2=ginfo_wy2
loopcnt++
loop
loop
*wm_sub
if (WM_NCLBUTTONDBLCLK=iparam) and (wparam=2) and ((((lparam>>16)&$ffff)-wy1)<25){//タイトルダブルクリック
//設定ウィンドウ表示
gsel conf_id,1
width ,,wx1+wsx+8,wy1
}else{
copy_f++
}
return
//設定適用
*conf_set
gsel conf_id
alphamin=limit(_alphamin,0,limit(_alphamax-1,0,_alphamax))
alphamax=limit(_alphamax,alphamin+1,255)
objprm alphamin_id,alphamin
objprm alphamax_id,alphamax
gsel 1
return
*exit
if wparam =conf_id{//設定ウィンドウ閉じる
_alphamin=alphamin
_alphamax=alphamax
gsel conf_id
objprm alphamin_id,alphamin
objprm alphamax_id,alphamax
gsel conf_id,-1
return
}
; デバイスコンテキスト削除
DeleteDC hdcScreen
end
getPixelの動作がBitBltと同じか分からないから隣接ドットのチェックがどうなるか
BitBltと同じでレイヤードウィンドウも取得できるとしてやってるが・・・
レイヤードウィンドウをgetPixelするとどうなるか試して欲しい
#uselib "gdi32.dll"
#cfunc global CreateDC "CreateDCA" sptr,sptr,sptr,int
#func global DeleteDC "DeleteDC" int
#cfunc global getPixel "GetPixel" int,int,int
#uselib "user32.dll"
#cfunc GetWindowLongA "GetWindowLongA" int , int
#func SetWindowLongA "SetWindowLongA" int , int , int
#func SetLayeredWindowAttributes "SetLayeredWindowAttributes" int , int , int , int
#func ReleaseDC "ReleaseDC" int,int
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 1
#define LWA_ALPHA 2
#define GWL_EXSTYLE -20
#define GWL_STYLE -16
// STYLE(hwnd,追加STYLE,削除STYLE)
#define ctype STYLE(%1,%2,%3=0) %1,GWL_STYLE,((GetWindowLongA(%1,GWL_STYLE) | (%2)) | (%3)) ^ (%3)
#define ctype EXSTYLE(%1,%2=0,%3=0) %1,GWL_EXSTYLE,((GetWindowLongA(%1,GWL_EXSTYLE) | (%2)) | (%3)) ^ (%3)
#define WS_EX_TRANSPARENT $20
SetWindowLongA EXSTYLE(hwnd,WS_EX_LAYERED)
SetLayeredWindowAttributes hwnd, 0, 255, LWA_ALPHA
width 640 ,480,0,0 //ウィンドウ再描画の代わり
repeat
dc=CreateDC("DISPLAY", 0,0,0)
col=GetPixel( dc,ginfo_mx,ginfo_my)
color col&$ff,(col>>8)&$ff,(col>>16)
DeleteDC dc
boxf 0,0,32,32
redraw
wait 1
loop
XPは真っ白なウィンドウを透過して下の色を拾う
まぁ、BitBltの理屈と同じなんだろうけど・・・
_hamyuu 2013/3/28(Thu) 14:26:36|NO.53307
スレ主は不在..(?)な気がしたので、やたらと実験好きな自分が代わりに試してみました。
レイヤードウィンドウをGetPixelすると・・
Aeroありの場合は透過されずウィンドウの色が表示されます。
Aeroを切るとウィンドウを透過して下の色が表示されました。
やっぱりAeroがネックなようで・・・
暇人 2013/3/28(Thu) 19:05:50|NO.53309
報告ありがとう
>Aeroありの場合は透過されずウィンドウの色が表示されます。
>Aeroを切るとウィンドウを透過して下の色が表示されました。
予想通りの動作か・・・
今までただのマルチディスプレイと水平垂直拡張デスクトップの違いを気にしてなかったけど
ginfo_dispx(y)の値に影響ある事を忘れてた・・・
NO.53291のも含めてginfo_dispのサイズはメインのディスプレイの解像度だと思って作ってたから
拡張デスクトップで全部の合計が入ってたら分割処理されない・・・
暇人 2013/3/30(Sat) 03:40:39|NO.53342
NO.53291のは垂直方向に拡張してる場合
ウィンドウを下の画面にはみ出すと無限ループ(sleep 1は入るが)に
陥るので修正版(多分これで最後)
他にも少し修正して起動してから設定できる項目追加
更に起動時にデスクトップ領域と開始位置を取得して設定するようにした
capsizex キャプチャーする横サイズ
capsizey キャプチャーする縦サイズ
left キャプチャーする左側座標
top キャプチャーする上側座標
表示倍率 キャプチャーサイズを何%で表示するか(実効ウィンドウのサイズに影響するので大きいと処理が重くなる)
横分割数 キャプチャーを横何分割でするか(キャプチャー後の表示も同じく分割されるので多ければ処理が軽くなる)
縦分割数 キャプチャーを縦何分割でするか
#include "mod_d3d9vsync.hsp"
#uselib "gdi32.dll"
#cfunc CreateDC "CreateDCA" sptr,sptr,sptr,int
#func DeleteDC "DeleteDC" int
#func BitBlt "BitBlt" int,int,int,int,int,int,int,int,int
#cfunc getPixel "GetPixel" int,int,int
#cfunc CreateRectRgn "CreateRectRgn" int, int, int, int
#func DeleteObject "DeleteObject" int
#cfunc GetRegionData "GetRegionData" int, int, int
#func GetClipRgn "GetClipRgn" int, int
#func GetClipBox "GetClipBox" int,int
#define NULL 0
#define SRCCOPY 0x00CC0020
#define CAPTUREBLT 0x40000000
#uselib "user32.dll"
#cfunc GetWindowLongA "GetWindowLongA" int , int
#func SetWindowLongA "SetWindowLongA" int , int , int
#func SetLayeredWindowAttributes "SetLayeredWindowAttributes" int , int , int , int
#func SetWindowPos "SetWindowPos" int, int, int, int, int, int, int
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 1
#define LWA_ALPHA 2
#define GWL_EXSTYLE -20
#define GWL_STYLE -16
#define WM_NULL 0x0000
#define WM_CREATE 0x0001
#define WM_DESTROY 0x0002
#define WM_MOVE 0x0003
#define WM_SIZE 0x0005
#define WM_PAINT 0x000F
#define WM_QUERYNEWPALETTE 0x030F
#define WM_SETREDRAW 0x000B
#define WM_NCLBUTTONDBLCLK 0x00A3
#const SWP_NOMOVE 0x02
#const SWP_NOSIZE 0x0001
#const SWP_NOZORDER 0x0004
#const SWP_NOACTIVATE 0x0010
#const SWP_FRAMECHANGED 0x020
#const SWP_SHOWWINDOW 0x040
#const SWP_HIDEWINDOW 0x080
#const SWP_NOCOPYBITS 0x0100
#const SWP_NOOWNERZORDER 0x0200
// STYLE(hwnd,追加STYLE,削除STYLE)
#define ctype STYLE(%1,%2,%3=0) %1,GWL_STYLE,((GetWindowLongA(%1,GWL_STYLE) | (%2)) | (%3)) ^ (%3)
#define ctype EXSTYLE(%1,%2=0,%3=0) %1,GWL_EXSTYLE,((GetWindowLongA(%1,GWL_EXSTYLE) | (%2)) | (%3)) ^ (%3)
#define WS_EX_TRANSPARENT $20
d3d9vsync_init //d3d9vsyncはプライマリ ディスプレイ アダプタ固定
if stat < 0 {
if -5 ! stat {dialog "GetRasterStatusを使用できない環境です":end}
}
Raster=0
repeat
GetRasterStatus v,r //VBlankとラスター位置取得
if r>=Raster {Raster=r}else{if v=0{break}}//プライマリディスプレイのラスター数取得(アダプタ名取得してどうこうが面倒だったので・・・)
loop
; デスクトップ画面のデバイスコンテキスト取得
hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL)
dim ClipBox,4
GetClipBox hdcScreen,varptr(ClipBox) //プライマリディスプレイからのデスクトップ全体の矩形取得(縦横にずれてるのにも対応できる)
/* マルチモニタ環境の場合sxには横解像度の合計、syには最大の縦解像度を入力。
それ以外なら ginfo_dispx と ginfo_dispy を入力。 */
sx = ClipBox(2)-ClipBox : sy = ClipBox(3)-ClipBox(1)
_sx=sx : _sy=sy
/* マルチモニタ環境の場合メインモニタの左上座標を0,0として左端のモニターの左上座標を入力
それ以外なら 0 を入力。 */
mlef = ClipBox ,ClipBox(1)
_mlef=mlef ,mlef(1)
/* 縮小の割合。%で設定、100で等倍。50 で1/2のサイズ */
percent = 20
_percent=percent
//透明度の初期値
_alphamin=100 //マウスが実行ウィンドウの描画エリア内の時
_alphamax=255 //マウスが実行ウィンドウ描画エリア外の時
//adjust 実行ウィンドウが大きいとチラつくのでラスター監視位置をずらす
adjust=0 //自分の環境ではYサイズが500超えるぐらいだと100程度で収まる(完全じゃないけど・・・)
//分割サイズから分割数を出す
divsizx=1920
divsizy=1080
_divsizx=divsizx
_divsizy=divsizy
dv_sxmax=limit(sx/divsizx,1,100) //分割数
dv_symax=limit(sy/divsizy,1,100)
wt=100
_wt=wt
gosub *init
gsel 1,2
if mcntmax=0{
onexit gosub *exit
mcntmax=4
dim mx,mcntmax
dim my,mcntmax
oncmd gosub *wm_sub,WM_SIZ
oncmd gosub *wm_sub,WM_MOVE
oncmd gosub *wm_sub,WM_QUERYNEWPALETTE
oncmd gosub *wm_sub,WM_NCLBUTTONDBLCLK
}
copy_f=1 //実行ウィンドウの下をコピーさせるフラグ
repeat
repeat dv_sxmax*dv_symax
if ((wx1+4)<ginfo_mx) and ((wy1+22)<ginfo_my) and ((wx1-4+wsx)>ginfo_mx) and ((wy1-4+wsy)>ginfo_my) {//マウスが実行ウィンドウの描画エリア内に入った
if ALPHA ! alphamin {//半透明にしてマウス操作も下に透過する(WS_EX_TRANSPARENT)
copy_f++
ALPHA=alphamin
SetWindowLongA EXSTYLE(hwnd1,WS_EX_TRANSPARENT)
SetWindowPos hwnd1,0 ,0,0 ,0,0 ,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW
SetLayeredWindowAttributes hwnd1, 0, ALPHA, LWA_ALPHA
}
}else{ //マウスが実行ウィンドウ描画エリア外
if ALPHA ! alphamax {//半透明を戻しタイトル枠をクリック出来る様にWS_EX_TRANSPARENTを削除
copy_f++
ALPHA=alphamax
SetWindowLongA EXSTYLE(hwnd1,0,WS_EX_TRANSPARENT)
SetWindowPos hwnd1,0 ,0,0 ,0,0 ,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW
}
}
_dvx=(cnt\dv_sxmax)*dv_sxsize
_dvy=(cnt/dv_sxmax)*dv_sysize
//実行ウィンドウに隣接するドットに変化があったかチェック(4ドット毎四辺だけ比較だからテキストスクロールとかは見逃す可能性あり)
if ((wx2)>(mlef)) and ((wx1)<(mlef+sx)) and ((wy2)>(mlef(1))) and ((wy1)<(mlef(1)+sy)){
if (cnt=((wx1-mlef-1)/dv_sxsize)+(((wy1-mlef(1))/dv_sysize)*dv_sxmax)) or (cnt=((wx2-mlef)/dv_sxsize)+(((wy2-mlef(1))/dv_sysize)*dv_sxmax)) {
if ((wy1)<(mlef(1)+sy)) {
repeat (wsx-1)/4,1
Pixel=getPixel(hdcScreen,wx1+cnt*4,wy1-1)
if Pixel>=0{
if (getPixel(hdc10,cnt*4,0) ! Pixel){
copy_f++
break
}
}
loop
}
if ((wx1)<(mlef+sx)){
repeat (wsy-1)/4,1
Pixel=getPixel(hdcScreen,wx1-1,wy1+cnt*4)
if Pixel>=0{
if (getPixel(hdc11,1, cnt*4) ! Pixel) {
copy_f++
break
}
}
loop
}
if ((wy2)>(mlef(1))) {
repeat (wsx-1)/4,1
Pixel=getPixel(hdcScreen,wx1+cnt*4,wy2)
if Pixel>=0{
if (getPixel(hdc10,cnt*4,1) ! Pixel) {
copy_f++
break
}
}
loop
}
if ((wx2)>=(mlef)) {
repeat (wsy-1)/4,1
Pixel=getPixel(hdcScreen,wx2,wy1+cnt*4)
if Pixel>=0{
if (getPixel(hdc11,0, cnt*4) ! Pixel) {
copy_f++
break
}
}
loop
}
//キャプチャー範囲外にデスクトップがあった場合でも比較できるように実行ウィンドウの周辺1ドットをコピー
BitBlt hdc10, 0, 0, wsx, 1, hdcScreen, wx1,wy1-1, SRCCOPY
BitBlt hdc10, 0, 1, wsx, 1, hdcScreen, wx1,wy2, SRCCOPY
BitBlt hdc11, 1, 0, 1, wsy, hdcScreen, wx1-1,wy1, SRCCOPY
BitBlt hdc11, 0, 0, 1, wsy, hdcScreen, wx2,wy1, SRCCOPY
}
}
; デスクトップ画面の画像をコピー(syをdv_sxmax*dv_sxmax分割してコピー)
BitBlt hdc0, _dvx, _dvy, dv_sxsize, dv_sysize, hdcScreen, mlef+_dvx, mlef(1)+_dvy, SRCCOPY
if copy_f {//実行ウィンドウ含む周辺で何か変化があった
if copy_f_bak=copy_f{//変化が終ったら実行ウィンドウの下を画像をhdc2にコピー
repeat
GetRasterStatus v,r //VBlankとラスター位置取得
if v or (r>(Raster-100)){break} //VBlank中
_Sleep@mod_d3d9vsync 1
loop
if r>(Raster-100){
_Sleep@mod_d3d9vsync 1
GetRasterStatus v,r //VBlankとラスター位置取得
if r>(Raster-100){
repeat
GetRasterStatus v,r //VBlankとラスター位置取得
if v {break} //VBlank中
loop
}
}
repeat
GetRasterStatus v,r //VBlankとラスター位置取得
if r>=limit((ginfo_wy2-adjust),1,Raster-50) or ((ginfo_wy2)>Raster){break} //ラスターが実行ウィンドウより下なら抜ける
if (limit((ginfo_wy2-adjust),1,Raster))>150 {_Sleep@mod_d3d9vsync 1} //目的の位置まで150以上有ったら1msスリープ
loop
//実行ウィンドウより下に走査線が有る時に実行ウィンドウを透明にしてコピーして直ぐに不透明に戻す(もしかしたら他の方法で見えなくしたほうが軽いのかもしれない・・・)
//SetLayeredWindowAttributesがウィンドウの大きさで凄く処理時間が増える・・・
SetLayeredWindowAttributes hwnd1, 0, 0, LWA_ALPHA //ALPHAモードで透明に設定
BitBlt hdc2, 0, ((wcnt-wcnt_bak)\dv_rsymax)*dv_sizey, wsx, dv_sizey, hdcScreen, wx1, wy1+((wcnt-wcnt_bak)\dv_rsymax)*dv_sizey, SRCCOPY
SetLayeredWindowAttributes hwnd1, 0, ALPHA, LWA_ALPHA //ALPHAモードで不透明設定
wcnt++
if (wcnt-wcnt_bak)>=dv_rsymax{copy_f=0:copy_f_bak=0:wcnt_bak=wcnt}//全てコピーされた
}else{//まだ変化中なので一旦抜ける
wcnt_bak=wcnt
}
copy_f_bak=copy_f
}
mx(mcnt\mcntmax)=ginfo_mx - mlef
my(mcnt\mcntmax)=ginfo_my - mlef(1)
mcnt++
await 0
gsel 0
//バックバッファ2からバッファ0にコピー
if (cnt=((wx1-mlef)/dv_sxsize)+(((wy1-mlef(1))/dv_sysize)*dv_sxmax)) or (cnt=((wx1+wsx-mlef-1)/dv_sxsize)+((((wy1-mlef(1))+wsy-1)/dv_sysize)*dv_sxmax)) {
gmode 0:pos wx1-mlef, wy1-mlef(1):gcopy 2, 0, 0, wsx, wsy //実行ウィンドウがある分割部分の処理の時だけコピー(デスクトップサイズより大きいのは想定してない)
}
; スクリーン(1)に縮小して描写
gsel 1
//gzoomは重いのでデスクトップがdv_sxsize*dv_sysizeより大きい分は分割してコピー
pos (cnt\dv_sxmax)*dv_rsxsize,(cnt/dv_sxmax)*dv_rsysize
gzoom dv_rsxsize ,dv_rsysize ,0, _dvx, _dvy ,dv_sxsize ,dv_sysize,1
; 擬似マウスカーソルを表示
perx=(1.0*ginfo_winx)/sx
pery=(1.0*ginfo_winy)/sy
color 255
repeat mcnt,mcnt\mcntmax
boxf perx*(mx(cnt\mcntmax)),pery*my(cnt\mcntmax),perx*(mx(cnt\mcntmax))+2,pery*my(cnt\mcntmax)+2
loop
redraw 1
redraw 0
await wt
gsel 1
if wsx ! ginfo_sizex { //ウィンドウのりサイズに対応
//横をリサイズすると比率を変えずにサイズを変更できる
dv_rsxsize=ginfo_winx/dv_sxmax
dv_rsysize=int(double(dv_rsxsize*dv_sxmax)/(double(sx)/sy))/dv_symax
width dv_rsxsize*dv_sxmax,dv_rsysize*dv_symax
wsx=ginfo_sizex
wsy=ginfo_sizey
}else{
if wsy ! ginfo_sizey {//縦のリサイズは横のサイズを変えない
dv_rsysize=ginfo_winy/dv_symax //ウィンドウのりサイズに対応
width ginfo_winx,dv_rsysize*dv_symax
wsy=ginfo_sizey
wsx=ginfo_sizex
}
}
wx1=ginfo_wx1
wy1=ginfo_wy1
wx2=ginfo_wx2
wy2=ginfo_wy2
loopcnt++
loop
loop
*wm_sub
if init_f=0 {
if (WM_NCLBUTTONDBLCLK=iparam) and (wparam=2) and ((((lparam>>16)&$ffff)-wy1)<25){//タイトルダブルクリック
//設定ウィンドウ表示
gsel conf_id,0
width ,,wx1+wsx+8,wy1
gsel conf_id,1
}else{
copy_f++
}
}
return
//設定適用
*conf_set
stat_id=stat
gsel conf_id
alphamin=limit(_alphamin,0,limit(_alphamax-1,0,_alphamax))
alphamax=limit(_alphamax,alphamin+1,255)
objprm alphamin_id,alphamin
objprm alphamax_id,alphamax
if stat_id=ALL_id {
sx=limit(_sx,128,ClipBox(2)-ClipBox)
sy=limit(_sy,128,ClipBox(3)-ClipBox(1))
mlef=limit(_mlef,-(ClipBox(2)-ClipBox),ClipBox(2)-ClipBox)
mlef(1)=limit(_mlef(1),-(ClipBox(3)-ClipBox(1)),ClipBox(3)-ClipBox(1))
percent=limit(_percent,1,1000)
dv_sxmax=limit(_dv_sxmax,1,100)
dv_symax=limit(_dv_symax,1,100)
objprm sx_id,sx
objprm sy_id,sy
objprm mlef_id,mlef
objprm mlef_id(1),mlef(1)
objprm percent_id,percent
objprm dv_sxmax_id,dv_sxmax
objprm dv_symax_id,dv_symax
gosub *init
}
gsel 1
return
*exit
if wparam =conf_id {//設定ウィンドウ閉じる
if init_f=0 {
gsel conf_id
objprm alphamin_id,alphamin
objprm alphamax_id,alphamax
objprm sx_id,sx
objprm sy_id,sy
objprm mlef_id,mlef
objprm mlef_id(1),mlef(1)
objprm percent_id,percent
objprm dv_sxmax_id,dv_sxmax
objprm dv_symax_id,dv_symax
gsel conf_id,-1
}
return
}
; デバイスコンテキスト削除
DeleteDC hdcScreen
end
*init
init_f=1
dv_sxsize=sx/dv_sxmax //分割サイズ
dv_sysize=sy/dv_symax
dv_sxmax+=((sx-dv_sxsize*dv_sxmax)>0) //余ってる分があったら分割数+1
dv_symax+=((sy-dv_sysize*dv_symax)>0)
dv_sxsize=sx/dv_sxmax //分割サイズ
dv_sysize=sy/dv_symax
percent=int(percent)
_percent=percent
rs = 100.0/percent
rsx=int((double(percent)/100)*sx)
rsy=int((double(percent)/100)*sy)
dv_rsxsize=rsx/dv_sxmax //分割サイズ(分割数はsx,syのを使用)
dv_rsysize=rsy/dv_symax
_dv_sxmax=dv_sxmax
_dv_symax=dv_symax
; デスクトップ画面のサイズでバッファ画面を作成
buffer 0 , sx, sy
hdc0=hdc
syscolor 15
boxf
wait 1
; スクリーン(1)を作成
screen 1, rsx ,rsy,2,wx1,wy1
hdc1=hdc
hwnd1=hwnd
//レイヤードウィンドウを設定
SetWindowLongA EXSTYLE(hwnd1,WS_EX_LAYERED)
alphamin=_alphamin
alphamax=_alphamax
ALPHA=alphamax
SetLayeredWindowAttributes hwnd1, 0, ALPHA, LWA_ALPHA //ALPHAモードで不透明設定
SetWindowPos hwnd1,0 ,0,0 ,0,0 ,SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_SHOWWINDOW
wait 1
//レイヤードウィンドウの左上座標とタイトル枠を含めたサイズを取得
wx1=ginfo_wx1
wy1=ginfo_wy1
wx2=ginfo_wx2
wy2=ginfo_wy2
wsx=ginfo_sizex
wsy=ginfo_sizey
dv_rsymax=limit(int(((1.0*wsx*wsy)/(1920*1080/5))),1,wsy) //BitBltよりALPHA値変更の方が重かったので細かい分割は意味無いかも・・・
dv_sizey=wsy/dv_rsymax
dv_rsymax=wsy/dv_sizey+((wsy-dv_sizey*dv_rsymax)>0) //確実にdv_sizey*dv_sizeyがwsy以上になるようにする
// getPixelチェック用バッファ
buffer 10,wsx ,2 //横上下ライン用
hdc10=hdc
buffer 11,2 ,wsy //縦左右ライン用
hdc11=hdc
//設定ウィンドウ非表示で設置
if conf_id=0 {
conf_id=100
screen conf_id, 220,256 ,8+2,wx1+wsx+8,wy1
syscolor 15
boxf
color
title "設定"
pos 8,8
mes " adjust"
mes " await"
mes
mes "alphamin"
mes "alphamax"
mes
mes "capsizex"
mes "capsizey"
mes " left"
mes " top"
mes "表示倍率"
mes "横分割数"
mes "縦分割数"
_alphamin=alphamin
_alphamax=alphamax
pos 80,12
input adjust,64,16
input wt,64,16
pos 80,ginfo_cy+20
input _alphamin,64,16
alphamin_id=stat
input _alphamax,64,16
alphamax_id=stat
gcy=ginfo_cy
pos 153,ginfo_cy-26
button gosub "ALPH適用",*conf_set
ALPH_id=stat
objsize 64,18,18
pos 80,gcy+22
input _sx,64,16
sx_id=stat
input _sy,64,16
sy_id=stat
input _mlef,64,16
mlef_id=stat
input _mlef(1),64,16
mlef_id(1)=stat
input _percent,64,16
percent_id=stat
input _dv_sxmax,64,16
dv_sxmax_id=stat
input _dv_symax,64,16
dv_symax_id=stat
pos 156,ginfo_cy-8
button gosub "ALL適用",*conf_set
ALL_id=stat
}else{
gsel conf_id
width ,,wx1+wsx+8,wy1
}
//レイヤードウィンドウの下の画像一時コピー用バッファ
buffer 2 , wsx, wsy
hdc2=hdc
init_f=0
return
_hamyuu 2013/3/30(Sat) 21:45:14|NO.53350
実行したらこんな感じになりました。
https://www.dropbox.com/s/l2glowm8wnrodrf/capture.mp4
何か・・バグってる?
暇人 2013/3/30(Sat) 22:57:19|NO.53352
報告ありがとう
なんかウィンドウの影の部分が何か影響してそう・・・
もし出来たらで良いんで
> ; スクリーン(1)に縮小して描写
> gsel 1
このgselの下あたりに
title strf("%d %d %d %d ",loopcnt ,copy_f ,ALPHA ,r)
を挿入して数値を見て欲しい
半透明で見難いだろうから
>//透明度の初期値
> _alphamin=100 //マウスが実行ウィンドウの描画エリア内の時
これを200ぐらいにして
カーソルをウィンドウ外に移動してる状態で
loopcntは同じ速度で動き続けてcopy_fも増え続けてALPHAは255の場合
getPixelの動作が想定と違ってる可能性が高い・・・
その場合
↓の行から
>
>//実行ウィンドウに隣接するドットに変化があったかチェック(4ドット毎四辺だけ比較だからテキストスクロールとかは見逃す可能性あり)
> if ((wx2)>(mlef)) and ((wx1)<(mlef+sx)) and ((wy2)>(mlef(1))) and ((wy1)<(mlef(1)+sy)){
・
・
・
> BitBlt hdc11, 0, 0, 1, wsy, hdcScreen, wx2,wy1, SRCCOPY
> }
> }
>
↑までを/**/でコメントアウトして試して欲しい
titleが更新されないとか凄く遅い場合走査線待ちが上手くいってない可能性・・・
_hamyuu 2013/4/3(Wed) 22:12:40|NO.53412
かなり返事遅れちゃってすみません!
やってみました。
とりあえずタイトル入れただけ↓
https://www.dropbox.com/s/3a0pqnn1hwow350/capture2-a.mp4
動きが・・w
コメントアウトするとこんな感じに↓
https://www.dropbox.com/s/oq0qwilblce7611/capture2-b.mp4
スムーズになった!
暇人 2013/4/3(Wed) 22:58:46|NO.53416
報告ありがとう
>とりあえずタイトル入れただけ↓
ウィンドウ隣接するドットのチェックが上手く動いてないのは確実かな・・・
後loopcntの増加も遅いからGetRasterStatusのところで上手くいってないな・・・
>コメントアウトするとこんな感じに↓
半透明の濃度で影の濃さも変るし
ウィンドウの影の外側をチェックするぐらいしかないか・・・
てか、ウィンドウ範囲きっちり切り取っても影が残っちゃうし・・・
そういや影の部分をGetPixelすると影を含まないのかな?
_hamyuu 2013/4/4(Thu) 00:48:31|NO.53418
GetPixelすると影の色も取得しちゃいますね。
自分には実験することくらいしかできそうにない...
あいうえ子 2013/4/4(Thu) 03:39:03|NO.53420
おお…なんだか頑張っていただいてますね
正直なにがなんだかサッパリですw
NO.53342にNO.53352を適用させて実行したところ比較的スムーズに動作いたしました。
暇人 2013/4/4(Thu) 22:15:55|NO.53444
報告ありがとう
>GetPixelすると影の色も取得しちゃいますね。
周辺のドットをコピーしたときとGetPixelでチェックしたときで色が変ってるのかな・・・
>NO.53342にNO.53352を適用させて実行したところ比較的スムーズに動作いたしました。
やっぱり影の部分もウィンドウとして処理しないとダメなんだねぇ
でも、結局DWMの同期のタイミングと画面が確定する要素が分からないから
この方法じゃ点滅を防ぐのは無理だな・・・