|
 |
|
2015/10/26(Mon) 20:47:20|NO.72528
タイトルの通り、すりガラス(Windows 10のアクションセンター)っぽいウィンドウ
を作りたい…と思い、自ウィンドウの1px左上のハンドルを取得してキャプってブラー…
まではしたのですが、まぁ当然うまくいかないケースがありますよね。
「じゃぁウィンドウ表示する前にキャプればいーじゃん」って思うかもしれませんが、
リアルタイム(といっても2〜fpsでいいのですが)で更新されないと違和感があって…
なので、ウィンドウの周り1pxのハンドルを取得して、GetWindowでZオーダーの関係を取得して
奥から描画してぼかしをかける…という方法でやってみたのですが、なんか収拾がつかなく
なってしまったので、どのような方法があるのかを質問させていただきます。
下のやつは、左上1pxのスクリプトです。ちなみに一応ドラッグで移動するようにしてますが、
最終的には固定するつもりなので、移動のことは考えなくていいです。
#uselib "user32.dll"
#cfunc GetWindowDC "GetWindowDC" int
#func ReleaseDC "ReleaseDC" int,int
#func GetWindowRect "GetWindowRect" int,int
#func WindowFromPoint "WindowFromPoint" int,int
#func GetParent "GetParent" int
#uselib "gdi32.dll"
#func BitBlt "BitBlt" int,int,int,int,int,int,int,int,int
#module
#deffunc gblur int p1 ;サンプル「gblur」のp2が無い版
gmode 3, ginfo_sx, ginfo_sy, 128
repeat p1
pos 1,0:gcopy ginfo(3):pos 0,0:gcopy ginfo(3),2,0
loop
repeat p1
pos 0,1:gcopy ginfo(3):pos 0,0:gcopy ginfo(3),0,2
loop
return
#global
dx=ginfo_dispx:dy=ginfo_dispy
wx=400:wy=200
dim rect,4
buffer 1,dx,dy
bgscr 0,wx,wy:hwindow.0=hwnd:title "終了はタスクバーかAlt+F4で":onclick gosub *move
repeat
windowfrompoint wx1-1,wy1-1
gsel 1
if hwndtarget!stat {
if stat {
hwndTarget=stat
GetParent hwndTarget
if stat!0 :hwndTarget=stat
}
color:boxf
GetWindowRect hwndTarget, varptr(rect)
xsrc=ginfo_wx1-rect(0):ysrc=ginfo_wy1-rect(1)
hdcTarget = GetWindowDC(hwndTarget)
BitBlt hdc,0,0,ginfo_winx,ginfo_winy,hdcTarget,xsrc,ysrc0x00CC0020
ReleaseDC hwndTarget, hdcTarget
gblur 4
}
gsel 0,2
redraw 0
color 36,36,36:boxf
gmode 3,sx,sy,128:gcopy 1
redraw
await 30
loop
*move
if wparam=1 :sendmsg hwindow.0,$000000A1,2,0
return
行数を減らしたため見づらいかもしれません…
EnumWindowsでデスクトップ上のハンドルをすべて取得した方が簡単な気がします。
…コールバック関数が使えればなぁ…
随分とワガママな質問でしかも長文申し訳ないのですが、
もしわかる方がいたら回答お願いします。

| |
|
2015/10/26(Mon) 20:52:08|NO.72529
…すみません。なんか上のでは動かないっぽいので…
#uselib "user32.dll"
#cfunc GetWindowDC "GetWindowDC" int
#func ReleaseDC "ReleaseDC" int,int
#func GetWindowRect "GetWindowRect" int,int
#func WindowFromPoint "WindowFromPoint" int,int
#func GetParent "GetParent" int
#uselib "gdi32.dll"
#func BitBlt "BitBlt" int,int,int,int,int,int,int,int,int
#module
#deffunc gblur int p1 ;サンプル「gblur」のp2が無い版
gmode 3, ginfo_sx, ginfo_sy, 128
repeat p1
pos 1,0:gcopy ginfo(3):pos 0,0:gcopy ginfo(3),2,0
loop
repeat p1
pos 0,1:gcopy ginfo(3):pos 0,0:gcopy ginfo(3),0,2
loop
return
#global
#define SRCCOPY 0x00CC0020
#define WM_NCLBUTTONDOWN $000000A1
#define HTCAPTION 2
dx=ginfo_dispx:dy=ginfo_dispy
wx=400:wy=200
dim rect,4
buffer 1,dx,dy
bgscr 0,wx,wy:hwindow.0=hwnd:title "終了はタスクバーかAlt+F4で"
onclick gosub *move
repeat
wx1=ginfo_wx1:wy1=ginfo_wy1
windowfrompoint wx1-1,wy1-1
gsel 1
if hwndtarget!stat {
if stat {
hwndTarget=stat
GetParent hwndTarget
if stat!0 :hwndTarget=stat
}
color:boxf
GetWindowRect hwndTarget, varptr(rect)
sx=wx:sy=wy
xsrc=ginfo_wx1-rect(0):ysrc=ginfo_wy1-rect(1)
hdcTarget = GetWindowDC(hwndTarget)
BitBlt hdc,0,0,sx,sy,hdcTarget,xsrc,ysrc,SRCCOPY
ReleaseDC hwndTarget, hdcTarget
gblur 4
}
gsel 0,2
redraw 0
color 36,36,36:boxf
gmode 3,sx,sy,128:gcopy 1
redraw
await 30
loop
*move
if wparam=1 :sendmsg hwindow.0,WM_NCLBUTTONDOWN,HTCAPTION,0
return
これなら動くはずです。本当にすみません。

| |
|
2015/10/26(Mon) 21:11:44|NO.72530
コールバック使えますよ。
2つ方法があります。
1.このhsptvのプラグイン・モジュール一覧でダウンロード出来るDLLを使う
2.この掲示板で公開されてるコールバックモジュールを使う
個人的には下がいいと思います。
というかすりガラスっぽいウィンドウを誰かソース公開してたような…
|
|
2015/10/26(Mon) 21:22:17|NO.72532
|
|
2015/10/26(Mon) 21:29:49|NO.72534
以前のスレにありました。
#include "hspcv.as"
#define WM_NCLBUTTONDOWN $000000A1
#define HTCAPTION 2
// デスクトップ描画モジュール
#module
#uselib "User32.dll"
#func SetWindowLong "SetWindowLongA" int, int, int
#cfunc GetWindowLong "GetWindowLongA" int, int
#func SetLayeredWindowAttributes "SetLayeredWindowAttributes" int, int, int, int
#cfunc BeginPaint "BeginPaint" int, var
#func PaintDesktop "PaintDesktop" int
#func EndPaint "EndPaint" int, var
#func InvalidateRect "InvalidateRect" int, int, int
#func UpdateWindow "UpdateWindow" int
#cfunc GetDC "GetDC" int
#uselib "Gdi32.dll"
#func BitBlt "BitBlt" int, int, int, int, int, int, int, int, int
#deffunc DrawDesktop
selid = ginfo_sel
if tempid == 0 : tempid = ginfo_newid
bgscr tempid, ginfo_dispx, ginfo_dispy, 2, 0, 0
oncmd gosub *paint, 0xF/*WM_PAINT*/
hwnd_t = hwnd
SetWindowLong hwnd_t, -20/*GWL_EXSTYLE*/, GetWindowLong(hwnd_t, -20/*GWL_EXSTYLE*/) | 0x80000/*WS_EX_LAYERED*/
SetLayeredWindowAttributes hwnd_t, 0, 0, 2/*ULW_ALPHA*/
gsel tempid, 1
InvalidateRect hwnd_t, 0, 0
UpdateWindow hwnd_t
oncmd gosub *paint2, 0xF/*WM_PAINT*/
gsel selid
BitBlt hdc, 0, 0, ginfo_dispx, ginfo_dispy, GetDC(hwnd_t), 0, 0, 0x00CC0020/*SRCCOPY*/
bgscr tempid, 1, 1, 2
gsel selid
return
*paint
dim ps, 9
PaintDesktop BeginPaint(hwnd_t, ps)
EndPaint hwnd_t, ps
*paint2
return
#global
#include "user32.as"
#define WM_VSCROLL $114
#define TBS_AUTOTICKS $1
#define TBM_SETPOS $405
#define TBM_SETTICFREQ $414
#define TBM_GETPOS $400
#uselib "dwmapi.dll"
#func DwmIsCompositionEnabled "DwmIsCompositionEnabled" var //定義
#func DwmGetColorizationColor "DwmGetColorizationColor" int,int
sound=50
gsel 0,-1
bgscr 12,550,350
buffer 1,ginfo_dispx,ginfo_dispy
DrawDesktop
cvbuffer 0,ginfo_dispx,ginfo_dispy //作業用CVバッファ
buffer 2,ginfo_dispx,ginfo_dispy
buffer 3,ginfo_winx,ginfo_winy
gsel 1
cvputimg 0 //HSPバッファからCVバッファ0にコピー
gsel 2
cvsmooth CV_BLUR,51,51,,0 //CVバッファ0をスムージング処理(数値は奇数限定)
cvgetimg 0 //CVバッファ0からHSPウィンドウにコピー
gsel 12
gcopy 2, ginfo_wx1, ginfo_wy1, ginfo_winx, ginfo_winy
pos 100,100
winobj "msctls_trackbar32","", ,$50000000|$1, 200, 30
hTbar=objinfo_hwnd(stat) : objskip stat,1 ;ハンドルを取得
sendmsg hTbar, TBM_SETPOS, 1, sound ;デフォの位置(0~100)
sendmsg hTbar, TBM_SETTICFREQ, 10 ;メモリの分割幅(0~100)
oncmd gosub *vscroll,WM_VSCROLL
repeat
mx = ginfo_mx
my = ginfo_my
getkey click,1
if(MoveScroll==1){
MoveScroll=0
gsel 1
cvputimg 0 //HSPバッファからCVバッファ0にコピー
gsel 2
BLUR_p1=sound
BLUR_p2=sound
BLUR_p1 | 1 //偶数だとエラーになるので奇数に
BLUR_p2 | 1
cvsmooth CV_BLUR,BLUR_p1,BLUR_p2,,0 //CVバッファ0をスムージング処理(数値は奇数限定)
cvgetimg 0 //CVバッファ0からHSPウィンドウにコピー
}
if (click == 1) && (clicko == 0) {
omx=mousex
omy=mousey
}
if(click==1&& mousex >=0 && mousex <=ginfo_winx && mousey >= 0 && mousey <=ginfo_winy/7 && MoveScroll==0){ //右クリ&& タイトルバー
gpx=mx-omx
gpy=my-omy
MoveWindow hwnd, mx-omx, my-omy, ginfo_winx, ginfo_winy, 0
}
gosub *Draw
clicko=click
await
loop
stop
*vscroll
if lparam=hTbar{ ;もし、トラックバーなら
sendmsg lparam, TBM_GETPOS
sound=stat
MoveScroll=1
}
return
*Draw
redraw 0
gsel 12
pos 0,0
gcopy 2, gpx, gpy, ginfo_winx, ginfo_winy
gmode 4,ginfo_winx,ginfo_winy/7,70
gcopy 3,0,0,ginfo_winx,ginfo_winy/7
redraw 1
return
コピペです。
汚いです。

| |
|
2015/10/27(Tue) 18:24:50|NO.72550
回答ありがとうございます。
>kanamaru さん
あっ そういえばモジュール探してませんでした。
今まですりガラスウィンドウのスクリプトはいくつも見たのですが…どれも違う感じです。
>スペース さん
最初は僕もこういうのを作ってみたのですが、やはり向こう側の様子を更新しないと
違和感が… なんで僕ってこういう所ばっかりこだわるんでしょうか…
>n さん
だいぶ前のスレで壁紙が見えるツールがあって、それみたいにしようとも思ったのですが…
やはりOSのGUIとの統一感を出すためには、自分のウィンドウのすぐ下が見えた方が
いいのかな…とか思ってしまいます。
あぁ、なんで僕ってこういう所(略
あと、Bitbltはストアアプリとかスタートメニューとかがキャプチャできないみたいです。
もうブラーかけるのやめて、タスクバーみたいにする方向を検討しています。
(Win10使ってる方は分かるかも知れませんが、タスクバーはブラーがかかってません)
ですが、もしこれから同じことで悩む人の為にも、できる限りやってみたいと思います。
もし良い方法をご存知の方はぜひ教えてください。
自分の周囲1pxにあるウィンドウのハンドルを取得する方法をもう一度試してみます。
…Aeroとは別にすりガラスっぽく表示できるようにならないかなぁ(ボソッ
|
|
2015/10/27(Tue) 18:35:52|NO.72551
|
|
2015/10/27(Tue) 18:41:20|NO.72552
個人的に前からやりたいとは思っていたので、いい機会なので自分も少し挑戦してみようかな・・・
|
|
2015/10/27(Tue) 23:04:24|NO.72573
全てのウィンドウを個別に取得。ついでにデスクトップの壁紙も取得して表示するだけ。
うぅ〜ん重い・・・
#include "d3m.hsp"
#include "hspcv.as"
#define Bura cvputimg 0:cvsmooth CV_GAUSSIAN,21,21,,0:cvgetimg 0,1//ブラー
#define WM_NCLBUTTONDOWN $000000A1
#define HTCAPTION 2
// デスクトップ描画モジュール
#module
#uselib "User32.dll"
#func SetWindowLong "SetWindowLongA" int, int, int
#cfunc GetWindowLong "GetWindowLongA" int, int
#func SetLayeredWindowAttributes "SetLayeredWindowAttributes" int, int, int, int
#cfunc BeginPaint "BeginPaint" int, var
#func PaintDesktop "PaintDesktop" int
#func EndPaint "EndPaint" int, var
#func InvalidateRect "InvalidateRect" int, int, int
#func UpdateWindow "UpdateWindow" int
#cfunc GetDC "GetDC" int
#uselib "Gdi32.dll"
#func BitBlt "BitBlt" int, int, int, int, int, int, int, int, int
#deffunc DrawDesktop
selid = ginfo_sel
if tempid == 0 : tempid = ginfo_newid
Screen tempid, ginfo_dispx, ginfo_dispy, 2, 0, 0
oncmd gosub *paint, 0xF/*WM_PAINT*/
hwnd_t = hwnd
SetWindowLong hwnd_t, -20/*GWL_EXSTYLE*/, GetWindowLong(hwnd_t, -20/*GWL_EXSTYLE*/) | 0x80000/*WS_EX_LAYERED*/
SetLayeredWindowAttributes hwnd_t, 0, 0, 2/*ULW_ALPHA*/
gsel tempid, 1
InvalidateRect hwnd_t, 0, 0
UpdateWindow hwnd_t
oncmd gosub *paint2, 0xF/*WM_PAINT*/
gsel selid
BitBlt hdc, 0, 0, ginfo_dispx, ginfo_dispy, GetDC(hwnd_t), 0, 0, 0x00CC0020/*SRCCOPY*/
bgscr tempid, 1, 1, 2
gsel selid
return
*paint
dim ps, 9
PaintDesktop BeginPaint(hwnd_t, ps)
EndPaint hwnd_t, ps
*paint2
return
#global
#module
; ======== API 関数の定義 ========
#uselib "user32.dll"
#func global FindWindowEx "FindWindowExA" sptr,sptr,sptr,sptr
#func global GetWindowLong "GetWindowLongA" sptr,sptr
#func global IsIconic "IsIconic" sptr
#func global GetWindowText "GetWindowTextA" sptr,sptr,sptr
#cfunc GetDC "GetDC" int
#cfunc GetWindowDC "GetWindowDC" int
#func ReleaseDC "ReleaseDC" int,int
#cfunc GetForegroundWindow "GetForegroundWindow"
#cfunc GetDesktopWindow "GetDesktopWindow"
#func GetWindowRect "GetWindowRect" int,int
#func GetClientRect "GetClientRect" int,int
#uselib "gdi32.dll"
#func BitBlt "BitBlt" int,int,int,int,int,int,int,int,int
#define NULL 0
#define SRCCOPY 0x00CC0020
#define CAPTUREBLT 0x40000000
; ======== 指定されたウィンドウのキャプチャ ========
#deffunc CaptureWindow
//ウィンドウタイトルとウィンドウハンドルを取得。
//以下ページからコピペ
//http://hsp.tv/play/pforum.php?mode=pastwch&num=32730
hwnd_=0
sdim wtitle, 129
dim Hwndls,129
WindowLs=0
repeat
FindWindowEx 0 ,hwnd_, 0, 0
hwnd_=stat
if hwnd_=0 : break
GetWindowLong hwnd_, -8
if stat!=0 : continue
GetWindowLong hwnd_, -16
if (stat & 0x10CA0000)!=0x10CA0000 and (stat & 0x16080000)!=0x16080000 : continue
IsIconic hwnd_
if stat !=0 : continue
GetWindowText hwnd_, varptr(wtitle), 128
if wtitle="":continue
if wtitle!タイトル@:Hwndls.WindowLs=hwnd_:WindowLs+1//ウィンドウハンドルを記録し、カウンタに+1。ifは自分のウィンドウが表示されないように。
loop
repeat WindowLs//ハンドル取得後にBitbltをやるとウィンドウのZ順が逆に成る為。わざわざ処理を分ける必要あり。
hwnd_=Hwndls.(WindowLs-cnt-1)//ハンドルを代入
//ウィンドウのサイズ取得
dim rect, 4//RECT構造体
GetWindowRect hwnd_, varptr(rect)
sx = rect(2) - rect(0):sy = rect(3) - rect(1)
; 画像をコピー
hdcTarget = GetWindowDC(hwnd_)//ハンドルからDC取得
BitBlt hdc, rect(0),rect(1), sx, sy, hdcTarget, 0, 0, SRCCOPY | CAPTUREBLT
loop
ReleaseDC hwndTarget, hdcTarget//デバイスコンテキスト解放
return エラーフラグ//正常終了時 stat = 0
#global
win_x = 500 :win_y = 500//ウィンドウサイズ
deskX=ginfo_dispx//デスクトップの
deskY=ginfo_dispy//X、Yサイズを取得
cvbuffer 0,win_x,win_y//CVバッファ初期化
buffer 3,deskX,deskY:DrawDesktop//デスクトップの壁紙。nさんが貼ってくれたスクリプトから流用。
buffer 1,deskX,deskY//壁紙とウィンドウを合成
buffer 4,win_x,win_y//テンポラ。
bgscr 0,win_x,win_y:gsel 0,2//メインウィンドウ
font "メイリオ",25,17
タイトル="擬似Aero"
title ""+タイトル
repeat
mx = ginfo_mx//何度か使うので、変数に現在のスクリーン上のマウス位置を記録
my = ginfo_my
gsel 0
gwposx=ginfo_wx1
gwposy=ginfo_wy1
if ginfo_act=0:getkey 左クリック,1:else:左クリック=0
getkey ブラーフラグ,17//Ctrlでブラーあり
getkey esc,27:if esc=1:end//escで終了
if 左クリック = 1 and 左クリックbac = 0 or cnt = 0 :win_mx=mousex:win_my=mousey//ドラック処理
if 左クリック = 1:{
win_pos_x = mx-win_mx : win_pos_y=my-win_my
if win_pos_x<=0:win_pos_x=0
if win_pos_y<=0:win_pos_y=0
}
redraw 0
gsel 1
pos 0,0:gcopy 3,0,0,deskX,deskY//デスクトップの壁紙を描画して
CaptureWindow//ウィンドウを描画
gsel 4//ブラーを掛ける処理。全体にかけると重い為、必要最低限の範囲
pos 0,0:gcopy 1,gwposx,gwposy,win_x,win_y//でもcvgetimgが枠なしウィンドウに対応したい無いっぽいので一旦bufferに描く必要あり。
if ブラーフラグ=1:Bura//ブラーを掛ける
gsel 0
pos 0,0:gcopy 4,0,0,win_x,win_y//メインウィンドウにcopy
//情報表示
情報=""+d3getfps()+"fps\nwin_pos_x:"+win_pos_x+"\nwin_pos_y:"+win_pos_y+"\nwin_mx:"+win_mx+"\nwin_my:"+win_my+"\ncnt:"+cnt+""
color 255,255,255
pos 99,0:mes 情報
pos 101,0:mes 情報
pos 100,-1:mes 情報
pos 100,1:mes 情報
color 0,0,0
pos 100,0:mes 情報
//情報表示
左クリックbac=左クリック//1フレーム前の情報を記録
line 0,0,0,500:line 0,0,499,0:line 0,499,500,499:line 499,0,499,500//見やすいように、ウィンドウに枠を表示。
redraw 1
if 左クリック=1:width ,,win_pos_x,win_pos_y//ウィンドウ位置を変更。redrawの間にwidthを書くとラグが増えるので、最後の方に書いたほうがいいかも?
mx_bac=mx:my_bac=my
await 17-(cnt\3=0)
loop

| |
|
2015/10/28(Wed) 20:33:37|NO.72589
>kanamaru さん
このスクリプトも見てみたのですが、どうやらレイヤードウィンドウをキャプチャしない
方法みたいでこちらでは上手く動きませんでした。
なんでレイヤードウィンドウもキャプチャするようにしたんだろ…
>スペース さん
ス、スゴい…
なんだか感動してしまいました。
ロースペックな環境でも文字などの背景としては十分な速度が出ていました。
回答ありがとうございました。解決です!
|
|