DOBON.NETプログラミング道掲示板

■35111 / 親記事)  フォーム背景のみを半透明にしたい
  
□投稿者/ よっし〜 一般人(11回)-(2022/07/26(Tue) 13:31:15)
  • アイコン環境/言語:[VS2013] 
    分類:[.NET] 

    お疲れ様です。度々の投稿で申し訳ございませんが、おおしえくださいませ。

    先の投稿(読み出し元フォームの位置取得方法)でご教示頂き、「出来る!」と思って進めてたのですが・・・
    半透明のフォームを親フォームに重ねて表示したいのですが、半透明(Opacity)を設定すると、フォームに載せたコントロールごと半透明となってしまいます。
    添付の画像の様に「フォームだけを半透明」する方法はありませんでしょうか??
    ちなみに添付画像は半透明のフォームだけを重ねて表示し、別のOpacity=100%のフォームをさらに重ねております。
    (親フォームを合わせて3フォームを重ねています)
    出来るには出来るのですが、コードが煩雑になりますので、何か良い方法は無いかと模索しております。

    お忙しいとは思いますが、宜しくご教示のほどお願いいたします。
804×601 => 250×186
イメージ
1658809874.png
/18KB
マルチポストを報告
違反を報告
引用返信 削除キー/
■35112 / ResNo.1)  Re[1]: フォーム背景のみを半透明にしたい
□投稿者/ 魔界の仮面弁士 大御所(1438回)-(2022/07/26(Tue) 14:50:11)
  • アイコンNo35111に返信(よっし〜さんの記事)
    > 添付の画像の様に「フォームだけを半透明」する方法はありませんでしょうか??

    タイトルなし枠無しの Form の背景色を、普段使わない色にしておき、
    その色を TransparencyKey に指定すれば、フォーム部が全透過状態の
    「コントロール部だけのフォーム」ができあがります。
    https://dobon.net/vb/dotnet/form/transparencykey.html

    そのフォームを、Opacity プロパティを設定した別フォームの手前に配置すれば
    フォームの数を 3 つから 2 つに減らせると思います。
    https://dobon.net/vb/dotnet/form/opacity.html


    > フォームに載せたコントロールごと半透明となってしまいます。
    TransparencyKey や Opacity は、フォーム全体に対して一括適用されるため
    コントロール部のみを除外するといったことはできません。

    フォーム 1 つのまま、部分的な半透明化を実現するためには、
    UpdateLayeredWindow API を直接呼び出す必要があります。

    フォームサイズが固定なのであれば、フォームサイズの PNG ファイルを用意し、
    あらかじめその画像内の透明度情報で、不透明箇所と半透明箇所を塗り分けます。
    それを UpdateLayeredWindow API に渡して適用すればできます。

    https://wiki.onakasuita.org/pukiwiki/?UpdateLayeredWindow
    https://dobon.net/vb/bbs/log3-44/26446.html


違反を報告
引用返信 削除キー/
■35113 / ResNo.2)  Re[2]: フォーム背景のみを半透明にしたい
□投稿者/ よっし〜 一般人(12回)-(2022/07/26(Tue) 15:50:12)
  • アイコンNo35112に返信(魔界の仮面弁士さんの記事)

    魔界の仮面弁士様、毎度お世話になり、申し訳ございません。

    > タイトルなし枠無しの Form の背景色を、普段使わない色にしておき・・・
    > フォームの数を 3 つから 2 つに減らせると思います。
    現在も親の上に半透明シート(?)を表示させ、その上にLabelを配置したフォームを表示させております。

    > フォーム 1 つのまま、部分的な半透明化を実現するためには、UpdateLayeredWindow API を直接呼び出す必要があります。
    > フォームサイズが固定なのであれば、フォームサイズの PNG ファイルを用意し、
    > あらかじめその画像内の透明度情報で、不透明箇所と半透明箇所を塗り分けます。
    > それを UpdateLayeredWindow API に渡して適用すればできます。
    記載先をお教え頂きましたが、なかなかのボリュームですね。
    まぁ簡単にできない事は分かっておりますので、ちょっとゴリゴリと試してみたいと思います。

    まずは御礼まで・・どうも有り難うございました。


1044×727 => 250×174
イメージ
20220726153947-min.png
/14KB
違反を報告
引用返信 削除キー/
■35114 / ResNo.3)  Re[3]: フォーム背景のみを半透明にしたい
□投稿者/ 魔界の仮面弁士 大御所(1439回)-(2022/07/26(Tue) 16:42:28)
  • アイコン
    No35113に返信(よっし〜さんの記事)
    > 現在も親の上に半透明シート(?)を表示させ、その上にLabelを配置したフォームを表示させております。
    
    半透明シートを被せて、下の親フォームを操作不能にしたいという意図でしょうか。
    
    であれば、親フォームにフォームサイズの Panel を全体表示しておき、
    その Panel の背景に、親フォームの内容を描画してはどうでしょう。
    
    
    (1) 親フォームに Panel1 を配置。これが半透明モドキになる。
     Panel1 は普段、Visible = False にしておく。
    
    (2) その Panel1 内に、子コントロールとして黄色の Panel2 を置き、
     Panel2 内に Label1 や Button1 を置く。
     Button1_Click のイベントにて「Panel1.Hide()」を記述。
    
    (3) 半透明表示のために、以下を実行。
    
    'Panel1 は Visible = False な状態で開始する事
    Panel1.Visible = False
    
    Dim cr = Me.ClientRectangle
    Dim r = Me.RectangleToScreen(cr)
    Dim bmp As New Bitmap(cr.Width, cr.Height)
    Using g = Graphics.FromImage(bmp)
        '画面キャプチャ
        g.CopyFromScreen(r.Location, New Point(0, 0), r.Size)
        '半透明のスモークをかける
        Using b As New SolidBrush(Color.FromArgb(180, Color.DarkSlateGray))
            g.FillRectangle(b, cr)
        End Using
    End Using
    
    'Panel1を重ねて表示
    Dim oldBmp = Panel1.BackgroundImage
    Panel1.BackgroundImage = bmp
    If oldBmp IsNot Nothing Then
        oldBmp.Dispose()
    End If
    Panel1.BringToFront()
    Panel1.SetBounds(cr.X, cr.Y, cr.Width, cr.Height)
    Panel1.Visible = True

違反を報告
引用返信 削除キー/
■35115 / ResNo.4)  Re[4]: フォーム背景のみを半透明にしたい
□投稿者/ よっし〜 一般人(13回)-(2022/07/27(Wed) 12:14:45)
  • アイコンNo35114に返信(魔界の仮面弁士さんの記事)

    魔界の仮面弁士様、早速のご教示、有り難うございます。
    > 半透明シートを被せて、下の親フォームを操作不能にしたいという意図でしょうか。
    > であれば、親フォームにフォームサイズの Panel を全体表示しておき、
    > その Panel の背景に、親フォームの内容を描画してはどうでしょう。
    そうです。まさにそうです。
    先の投稿の画面はサンプルで親フォームはスッキリしておりますが、実際の親フォームはゴチャゴチャしておりますので、
    予めパネルを貼らずに、動的に貼る様にしたいと思います。
    今後の為に、サンプルだけ貼らして頂きます。
    どうも、有り難うございました。

    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
    Dim cr = Me.ClientRectangle
    Dim r = Me.RectangleToScreen(cr)
    Dim bmp As New Bitmap(cr.Width, cr.Height)
    Using g = Graphics.FromImage(bmp)
    '画面キャプチャ
    g.CopyFromScreen(r.Location, New Point(0, 0), r.Size)
    '半透明のスモークをかける
    Using b As New SolidBrush(Color.FromArgb(180, Color.DarkGray))
    g.FillRectangle(b, cr)
    End Using
    End Using

    Dim Pnl As New Panel
    Pnl.Parent = Me

    'Panel1を重ねて表示
    Dim oldBmp = Pnl.BackgroundImage
    Pnl.BackgroundImage = bmp
    If oldBmp IsNot Nothing Then oldBmp.Dispose()
    Pnl.BringToFront()
    Pnl.SetBounds(cr.X, cr.Y, cr.Width, cr.Height)
    Pnl.Visible = True
    Form4.ShowDialog(Me)
    Pnl.Visible = False
    Pnl.Dispose()
    End Sub


解決み!
違反を報告
引用返信 削除キー/
■35116 / ResNo.5)  Re[5]: フォーム背景のみを半透明にしたい
□投稿者/ 魔界の仮面弁士 大御所(1440回)-(2022/07/27(Wed) 13:50:17)
  • アイコンNo35115に返信(よっし〜さんの記事)
    > Form4.ShowDialog(Me)
    ShowDialog 後の Dispose の呼び出しが漏れているように見えました。
    https://dobon.net/vb/dotnet/form/showform.html

    Show の場合は、フォームが閉じられた時に自動的に Dispose され、メモリ上からアンロードされますが、
    ShowDialog の場合は、使用後に Dispose しないと、閉じられた後もメモリ上に残り続けます。


    それともあえてこの時点では Dispose しないようにしてあるだけで、
    別の場所で Dispose する仕様にしてあるのでしょうか。


    > Dim Pnl As New Panel
    > Pnl.Parent = Me
    > Dim oldBmp = Pnl.BackgroundImage

    これは冗長でしょう。

    新規パネルを、その都度生成するのであれば、
    上記の oldBmp は、常に Nothing ですよね。


    Dim cr = Me.ClientRectangle
    Dim r = Me.RectangleToScreen(cr)
    Using bmp As New Bitmap(cr.Width, cr.Height)
      Using g = Graphics.FromImage(bmp)
        g.CopyFromScreen(r.Location, New Point(0, 0), r.Size)
        Dim alpha As Integer = 255 * 80 \ 100 '不透明度 80%
        Using b As New SolidBrush(Color.FromArgb(alpha, SystemColors.AppWorkspace))
          g.FillRectangle(b, cr)
        End Using
      End Using
      Using pnl As New Panel()
        pnl.Parent = Me
        pnl.BackgroundImage = bmp
        pnl.BringToFront()
        pnl.SetBounds(cr.X, cr.Y, cr.Width, cr.Height)
        pnl.Visible = True

        'Using child As New Form4() With {.StartPosition = FormStartPosition.CenterParent}
        '  child.ShowDialog(Me)
        'End Using
        Form4.ShowDialog(Me)

        Me.Controls.Remove(pnl)
      End Using
    End Using
解決み!
違反を報告
引用返信 削除キー/



スレッド内ページ移動 / << 0 >>

このスレッドに書きこむ

Mode/  Pass/


- Child Tree -