だんだん暑くなってきました。そんなわけで見た目に涼しいグラスフレームのコードを書いてみたよ。
Vistaの特長である(でもHome Basicは未対応)グラスフレーム(ブラーともいう)についてです。通常はウィンドウを作成するとウィンドウ枠内は不透明になりますが、IEの上部やMedia Playerの下部なんかは通常のウィンドウより透明の領域が多いですよね(当然ながらVistaの話し)。このような透明領域を増やす、クライアント領域の拡張はDesktop Window Manager (DWM)のAPIを呼び出すことで簡単にできます。そのことが日本語でMSDNにもろ書いてます。
WPF アプリケーションへのグラス フレームの拡張
記事はC#だったのでVBのコードを置いておきますね。XAMLは記事と同じです。
Imports System.Runtime.InteropServices
Public Class NonClientRegionAPI
<StructLayout(LayoutKind.Sequential)> _
Structure MARGINS
Public cxLeftWidth As Integer
Public cxRightWidth As Integer
Public cyTopHeight As Integer
Public cyBottomHeight As Integer
End Structure
<DllImport("DwmApi.dll")> _
Public Shared Function DwmExtendFrameIntoClientArea(ByVal hwnd As IntPtr, ByRef pMarInset As MARGINS) As Integer
End Function
End Class
Private Sub OnLoaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Try
Dim mainWindowPtr = New WindowInteropHelper(Me).Handle
Dim mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr)
mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0)
' Get System Dpi
Dim desktop = System.Drawing.Graphics.FromHwnd(mainWindowPtr)
Dim DesktopDpiX = desktop.DpiX
Dim DesktopDpiY = desktop.DpiY
' Set Margins
Dim margins = New NonClientRegionAPI.MARGINS
' Extend glass frame into client area
' Note that the default desktop Dpi is 96dpi. The margins are
' adjusted for the system Dpi.
margins.cxLeftWidth = CInt((5 * (DesktopDpiX / 96)))
margins.cxRightWidth = CInt(5 * (DesktopDpiX / 96))
margins.cyTopHeight = CInt((CInt(topBar.ActualHeight) + 5) * (DesktopDpiX / 96))
margins.cyBottomHeight = CInt(5 * (DesktopDpiX / 96))
Dim hr = NonClientRegionAPI.DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, margins)
If hr < 0 Then
' DwmExtendFrameIntoClientArea Failed
End If
Catch ex As DllNotFoundException
Application.Current.MainWindow.Background = Brushes.White
End Try
End Sub
marginsに透明にする部分の大きさ上下左右それぞれに指定してます。一度設定してしまえばウィンドウの大きさが変更されたとしても問題ありません。ただ、実際にWPFアプリケーションで実行してみて気になったのは、ウィンドウの拡大時に一瞬 不透明の部分が黒く見えてしまって見栄えが気になる。ドラッグの操作によりウィンドウ幅が変わるけど、ウィンドウ上のコントロールが変更に少し遅れて追従してるのでコントロールの後ろにあるウィンドウ自身が見えるのです。根本的解決ではありませんが、ウィンドウすべての領域を透明に指定することで黒く見える領域(不透明領域)がなくなるのでマシな感じです。すべてを透明に指定するにはmarginsの各値を-1にするとできます。
MISAOに適用してみた結果。
ウィンドウを最大化すると不透明になり、通常は黒っぽい色になります。なので上のように黒い文字があると見えづらくなるので これはダメですね。