不規則な形の窓

開始する



スプラッシュスクリーンであろうとデスクトップウィジェットであろうと、「不規則な」(長方形ではない)形状のウィンドウが必要になる場合があります。



画像





Windows APIには、次のような「間違った」ウィンドウを作成できるいくつかの関数があります。CreateEllipticRgnCreateRectRgnCreatePolygonRgnCreateRoundRectRgnCombineRgnなど。不快なクローブ、本格的な影を作ることは不可能であり、複雑な形状のウィンドウを作成するコードを書くには、多くの労力が必要になることがあります。



Windows 2000以降、ウィンドウは拡張されたWS_EX_LAYEREDスタイルを持ち、ウィンドウを階層化し、そのようなウィンドウを操作するためにいくつかのAPI関数が追加されました。 この関数を使用すると、アルファチャネルを考慮して、 PNGなどの画像に基づいてウィンドウを作成できます。 事前に準備された画像に基づいてウィンドウの形状を作成することは、領域を操作するよりもはるかに便利で簡単ですが、この方法にも欠点があります。 単純な方法で、ボタン、テキストフィールドなどのコンポーネントを多層ウィンドウに表示することは不可能です。これは、オペレーティングシステムがウィンドウの再描画プロセス全体を処理し、標準のWM_PAINTメッセージがウィンドウに送信されなくなったためです。 ほとんどの場合、すべての種類のスクリーンセーバー、ウィジェット、およびその他の装飾は、追加のコンポーネントの存在を必要としないか、最小限の数でそれらを必要とするため、不足に目をつぶることができます。





さらに、多層ウィンドウの使用の小さな実例を示したいと思います。 すべてがAPI関数を呼び出すことになるため、プログラミング言語はどれでもかまいませんが、Visual Studioを職場にインストールしているので、 VB.NETで記述します。 APIで使用される関数については説明しません。記事の目的は実用的なアプリケーションを示すことなので、MSDN Webサイトの説明へのリンクを以下に示します。



  1. まず、お気に入りのグラフィックエディタで将来のウィンドウを描画する必要があります。Photoshopでペイントし、常に不規則な形状で、常に透明で、多層ウィンドウの魅力をすべて感じて、 PNG形式で保存します 。 私はそのようなステッカーを手に入れました:

    画像

  2. 次に、Visual Studioで新しいプロジェクトを作成し、「Sticker」という名前でリソースに画像を追加します。プロジェクト内の唯一のフォームから不要なヘッダーと境界線をすべて削除します。

  3. プロセスで必要になるAPI関数と構造を定義する必要があります。 通常、これは別のクラスで行います。

     Namespace System Public Class Win32API Public Const WS_EX_LAYERED = &H80000 Public Const ULW_ALPHA As Int32 = &H2 Public Const AC_SRC_OVER As Byte = &H0 Public Const AC_SRC_ALPHA As Byte = &H1 ' ()' <StructLayout(LayoutKind.Sequential)> _ Public Structure Point Public x As Int32 Public y As Int32 Public Sub New(ByVal x As Int32, ByVal y As Int32) Me.x = x Me.y = y End Sub End Structure '' <StructLayout(LayoutKind.Sequential)> _ Public Structure Size Public cx As Int32 Public cy As Int32 Public Sub New(ByVal cx As Int32, ByVal cy As Int32) Me.cx = cx Me.cy = cy End Sub End Structure '     ' <StructLayout(LayoutKind.Sequential, Pack:=1)> _ Public Structure BLENDFUNCTION Public BlendOp As Byte Public BlendFlags As Byte Public SourceConstantAlpha As Byte Public AlphaFormat As Byte Public Sub New(ByVal BledOp As Byte, ByVal BlendFlags As Byte, ByVal SourceContrastAlpha As Byte, ByVal AlphaFormat As Byte) Me.BlendOp = BledOp Me.BlendFlags = BlendFlags Me.SourceConstantAlpha = SourceContrastAlpha Me.AlphaFormat = AlphaFormat End Sub End Structure '         ' <DllImport("user32.dll")> _ Public Shared Function GetDC(ByVal hWnd As IntPtr) As IntPtr End Function '     ' <DllImport("gdi32.dll")> _ Public Shared Function CreateCompatibleDC(ByVal hDC As IntPtr) As IntPtr End Function ' ' <DllImport("user32.dll", ExactSpelling:=True)> _ Public Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Integer End Function ' ' <DllImport("gdi32.dll")> _ Public Shared Function DeleteDC(ByVal hdc As IntPtr) As Boolean End Function '    ' <DllImport("gdi32.dll", ExactSpelling:=True)> _ Public Shared Function SelectObject(ByVal hDC As IntPtr, ByVal hObject As IntPtr) As IntPtr End Function ' ' <DllImport("gdi32.dll")> _ Public Shared Function DeleteObject(ByVal hObject As IntPtr) As Boolean End Function '  ' <DllImport("user32.dll")> _ Public Shared Function UpdateLayeredWindow(ByVal hwnd As IntPtr, ByVal hdcDst As IntPtr, ByRef pptDst As Win32API.Point, ByRef psize As Win32API.Size, ByVal hdcSrc As IntPtr, ByRef pprSrc As Win32API.Point, ByVal crKey As Int32, ByRef pblend As Win32API.BLENDFUNCTION, ByVal dwFlags As Int32) As Boolean End Function End Class End Namespace
          
          









  4. このコードと後続のすべてのコードは、プロジェクト内の唯一のフォームのクラスで記述されています。 最初に、いくつかのローカル変数を記述する必要があります。それらはプロセスで必要になります。

      Private _ScreenDC As IntPtr = IntPtr.Zero Private _MemDC As IntPtr = IntPtr.Zero Private _BitmapHandle As IntPtr = IntPtr.Zero Private _OldBitmapHandle As IntPtr = IntPtr.Zero Private _Size As Win32API.Size = Nothing Private _PoinSource As Win32API.Point = Nothing Private _TopPos As Win32API.Point = Nothing Private _Blend As Win32API.BLENDFUNCTION = Nothing Private _Opacity As Byte = 255 Private bmpDest As Bitmap = Nothing Private bmpSrc As Bitmap = Nothing
          
          





  5. ウィンドウを階層化します。 .NETでは、CreateParamsクラスプロパティをオーバーライドすることにより、作成直前にウィンドウにいくつかのプロパティを割り当てることができます( CreateWindowEx API関数を呼び出す)。

      Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams Get Dim CP As CreateParams = MyBase.CreateParams CP.ExStyle = CP.ExStyle Or Win32API.WS_EX_LAYERED Return CP End Get End Property
          
          





  6. 画像と一般的な透明度(0〜255)に基づいて、多層ウィンドウを更新する関数を作成します。

      Public Sub SetImage(ByRef Bitmap As Bitmap, ByVal Opacity As Byte) '    ' _ScreenDC = Win32API.GetDC(0) '    ' _MemDC = Win32API.CreateCompatibleDC(_ScreenDC) ' ' _BitmapHandle = IntPtr.Zero '  ' _OldBitmapHandle = IntPtr.Zero Try '  ' _BitmapHandle = Bitmap.GetHbitmap(Color.FromArgb(0)) '     ' _OldBitmapHandle = Win32API.SelectObject(_MemDC, _BitmapHandle) '  ,      ' _Size = New Win32API.Size(Bitmap.Width, Bitmap.Height) _PoinSource = New Win32API.Point(0, 0) _TopPos = New Win32API.Point(Me.Left, Me.Top) '  BLENDFUNCTION' _Blend = New Win32API.BLENDFUNCTION(Win32API.AC_SRC_OVER, 0, Opacity, Win32API.AC_SRC_ALPHA) '  ' Win32API.UpdateLayeredWindow(Me.Handle, _ScreenDC, _TopPos, _Size, _MemDC, _PoinSource, 0, _Blend, Win32API.ULW_ALPHA) Finally Win32API.ReleaseDC(IntPtr.Zero, _ScreenDC) If _BitmapHandle <> IntPtr.Zero Then Win32API.SelectObject(_MemDC, _OldBitmapHandle) Win32API.DeleteObject(_BitmapHandle) End If Win32API.DeleteDC(_MemDC) _Size = Nothing _PoinSource = Nothing _TopPos = Nothing _Blend = Nothing End Try End Sub
          
          





  7. フォームのインスタンスをロードするとき、画像を作成し(ステッカーにテキストを書き込むだけで静的)、それを更新関数に渡します。

      Private Sub FormSticker_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load bmpSrc = My.Resources. bmpDest = New Bitmap(bmpSrc.Width, bmpSrc.Height) Using g As Graphics = Graphics.FromImage(bmpDest) With g .InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor .SmoothingMode = Drawing2D.SmoothingMode.AntiAlias .TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAlias ' ' .DrawImage(bmpSrc, 0, 0, bmpSrc.Width, bmpSrc.Height) ' ' Dim sf As New StringFormat(StringFormatFlags.LineLimit) sf.Alignment = StringAlignment.Center sf.LineAlignment = StringAlignment.Center .DrawString("       ", Me.Font, New SolidBrush(Me.ForeColor), New Rectangle(10, 10, bmpDest.Width - 20, bmpDest.Height - 20), sf) End With End Using Me.SetImage(bmpDest, Me._Opacity) bmpDest.Dispose() End Sub
          
          







まあ、それはすべてのようです、私たちはそれを起動し、私たちがやったことを見てください(結果は最初の画像にあります)。



参照資料


  1. 使用される構造と機能の説明

    PointSizeGetDCReleaseDCDeleteDCSelectObjectDeleteObjectUpdateLayeredWindow
  2. サンプルソース


継続するには...




All Articles