HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2013
0320
あいうえ子マルチモニタ環境のデスクトップキャプチャについて。23解決


あいうえ子

リンク

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

ここで二つ質問があります。

.好リプトを実行するとマウスカーソルが点滅してしまいます。改善する方法はないでしょうか?

⊆孫埣罎離好リプトもキャプチャされるので目ざわりになってしまいます。キャプチャを回避する方法はありますでしょうか?

また、このスクリプトより簡素で軽量なスクリプトや、無駄な部分などがありましたら是非お教えください。



この記事に返信する


_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の同期のタイミングと画面が確定する要素が分からないから
この方法じゃ点滅を防ぐのは無理だな・・・



ONION software Copyright 1997-2018(c) All rights reserved.