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


HSPTV!掲示板


未解決 解決 停止 削除要請

2009
0204
sakureDWMのガラス効果で、ボタンの黒文字を透過させない方法3解決


sakure

リンク

2009/2/4(Wed) 17:15:00|NO.23213

VistaでDWMのガラス効果を利用したウィンドウを作ったのですが、
ボタンの文字色が暗い場合、透過してしまい
ウィンドウの背後によっては見えづらくなってしまいます。
ボタンに限って透過させないような方法は無いでしょうか?

//============================以下ソース
;初期化
screen 0, 400, 400
onexit *owari

;dwmapi登録
#uselib "dwmapi.dll"
#func DwmEnableBlurBehindWindow "DwmEnableBlurBehindWindow" int, int
#define DWM_BB_ENABLE 0x00000001
#define TRUE 0x00000001

;Dwmガラス効果有効
DWM_BLURBEHIND = DWM_BB_ENABLE, TRUE, 0
DwmEnableBlurBehindWindow hwnd, varptr(DWM_BLURBEHIND)

;画面黒
cls 4

;ボタン設置
pos 50,50
objsize 300,200 : objmode 2
font "MS UI Gothic",70
button gosub "■ボタン■",*BTN

;参考用グレースケール
color 200,200,200:mes "TEST TEST TEST"
repeat 25:a=10*cnt:color a,a,a:boxf a+75,350,a+100,400 :loop

stop

*BTN
return
*owari
end



この記事に返信する


flory

リンク

2009/2/5(Thu) 08:11:49|NO.23222

ちょっと気になったので調べてみました。

先に断っておきますが、このレスは提示された問題について中途半端な回答で終わっています。また、もしかするとものすごく見当外れなことを言っているかもしれません。そこのところを了解しておいてください。



本題。ボタンの文字が透過する現象について。

これを回避する方法を調べてみたところ、以下のような記述がありました。

>このGlass表示では、Formにマスクをかける様なイメージになっていて、Glass表示は純粋な黒が対象となるようです。なので、ほかのコントロールで表示している黒の文字などもGlass化されてしまいます。 それを回避する方法で一番簡単なのが、
>
>Application.SetCompatibleTextRenderingDefault(true);
>
>で、UseCompatibleTextRenderingをtrueに変更してやる方法です。 UseCompatibleTextRenderingについての説明はここでは省略させてもらいます。

参照:http://piece.coron.jp/weblog/archives/2007/05/14/012953/

ただし、これはC#(.NET?)についての記述ですので、このままHSPに持ってくることはできません。
そこで、UseCompatibleTextRenderingとは具体的に何なのか調べてみると、以下のような記述がありました。

>既定では、このプロパティは、Visual Basic 2005 の GDI テキスト レンダリング エンジンがアプリケーションのフォームに使用されることを示す False を返します。しかし、このプロパティを True を返すようにオーバーライドして、Visual Basic .NET 2002 および Visual Basic .NET 2003 で使用されている GDI+ テキスト レンダリング エンジンをアプリケーションのフォームで使用するように指定できます。

参照:http://msdn.microsoft.com/ja-jp/library/microsoft.visualbasic.applicationservices.windowsformsapplicationbase.usecompatibletextrendering.aspx

つまり、先ほどの回避策というのは、「文字をGDI+で描画する」というものだったわけです。

GDI+の大きな特徴としてアルファブレンドが使えることが挙げられます。
このことから予想される、ボタンの文字が透過する問題の原因は、「従来のGDIを用いた描画ではアルファブレンドの設定がされていないから」です。そして、それに対応する回避策は、「GDI+を用いてアルファ値を設定した描画を行う」ことです。


以上を踏まえた上で、HSP、DWM、GDI+などについて調べていくと、以下のようなソースが見つかりました。

参照:http://sprocket.babyblue.jp/temp/sample_hsp3_dwm_gdip.hsp

DwmExtendFrameIntoClientArea関数を使ってウィンドウ枠をクライアント領域まで拡張し、そこにGDI+を使って円を複数描画しています。
このソースでは円の色とアルファ値はランダムに変わるようになっています(randomizeでパラメータ指定されているので実際にはランダムではありません)が、そこをアルファ値255に固定してやれば、どんな色でも(GDIで描画したときに透過された黒色でも)透過されずに問題なく描画できるのがわかると思います。

したがって、ボタンの文字なども、GDI+を用いて適切に描画してやれば透過されないのではないかと思われます(未確認です)。


ただ、私はGDI+について詳しく知っているわけではないので、GDI+を用いた描画についてはご自分で調べていただくことになります。。。すいません。
ボタンならオーナードローとかする必要があるのかな???


……てっとり早い解決法としては、DWM_BLURBEHIND構造体でリージョンを指定して、ボタンだけブラーを適用しなければ良いと思います。が、これも未確認です。



sakure

リンク

2009/2/6(Fri) 08:19:59|NO.23239

floryさま 情報が大変助けになりました。

当初は参考URLのスクリプトを参考にGDI+で試行錯誤してたのですが、
BitBltにNOTSRCCOPYをつけるとアルファチャンネルも反転する事が分かったので
HSPバッファで用意したイメージを
ボタンにBitBltする方法する方法に落ち着きました。

オーナードローはとりあえず簡易処理でアニメ無しになってます。
どうでしょうか?

//=============================以下ソース
#uselib "gdi32"
#func BitBlt "BitBlt" sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr,sptr

#uselib "dwmapi.dll"
#func DwmEnableBlurBehindWindow "DwmEnableBlurBehindWindow" int, int
#func DwmExtendFrameIntoClientArea "DwmExtendFrameIntoClientArea" int, int

#define BM_SETSTYLE 0x00F4
#define BS_OWNERDRAW 0x0000000B
#define WM_DRAWITEM 0x002B
#define ODT_BUTTON 4

;DRAWITEMSTRUCT(抜粋)
#define DIS_CtlType 0; UINT CtlType;
#define DIS_hDC 6; HDC hDC;

*main
ButtonNum=4 ;ボタンの数
size=100 ;ボタンのサイズ
dim hwndODB,ButtonNum ;ボタンハンドル
dim objectID,ButtonNum ;ボタンID

//screen #0
screen 0, 370, 500: cls 4
mainhwnd=hwnd

//buffer #1 画像
buffer 1,size,size, , 500,100 : cls 2
picName = dir_exe+"\\sample\\ssaver\\Aruface.bmp"
exist picName
if strsize!-1 {
picload picName,1
} else {
color:circle 0,0,100,100,1:color 255,255:circle 3,3,97,97,1:
color:boxf 30,20,33,40:boxf 67,20,70,40:boxf 30,57,70,60
}
hdc_pic = hdc

//buffer 黒マスク用(実際は白)
buffer 2,size,size,, 650,100:cls
hdc_bk = hdc

//ボタン描画
gsel 0
pos 10,10 : objsize size,size : font "MS UI Gothic",10

;ボタン生成
repeat ButtonNum
mes ;スペース空け
button gosub "BTN"+cnt,*BTN ;設置
objectID.cnt=stat ;ID記憶
hwndODB.cnt =objinfo(objectID.cnt, 2) ;ハンドル記憶
sendmsg hwndODB.cnt, BM_SETSTYLE, BS_OWNERDRAW, 0 ;オーナードロー
loop

//オーナードロー
oncmd gosub *DRAWITEM, WM_DRAWITEM ;WM_DRAWITEM
onexit *owari

//Glass効果
MARGINS = -1, -1, -1, -1
DwmExtendFrameIntoClientArea hwnd, varptr(MARGINS)

stop

*DRAWITEM
wp=wparam
lp=lparam
dupptr DIS, lp, 48, 4
if DIS.DIS_CtlType!ODT_BUTTON:return

//buffer #1 から画像を転送
; NOTSRCCOPY 0x330008 '色反転転送(アルファも反転) ;これで黒ベースになる
BitBlt DIS.DIS_hDC, 0, 0, size, size, hdc_bk, 0, 0, 0x330008
; SRCPAINT 0xEE0086 'OR演算転送 ;黒ベースにORで描く
BitBlt DIS.DIS_hDC, 0, 0, 100, 100, hdc_pic, 0, 0, 0xEE0086
return

*btn
btnId=stat
color : boxf : color 255,255,255 : pos 120,50+(110*btnId) : font "MS UI Gothic",30
mes "< HI ! Button "+btnId+""
return

*owari
end



sakure

リンク

2009/2/6(Fri) 13:03:24|NO.23241

いちおう当方では動いているので、解決ということで!



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