2013-05-11 180 views
13

我試圖在第一張圖片上放下整個窗體的陰影,除非是WPF而不是WinForm。現在我想在一個winform上放下相同的陰影。在無邊界WinForm上投下陰影

這是我want..¬

Windows Form Shadow

不this..¬

Windows Form Shadow

+0

http://stackoverflow.com/questions/3372303/dropshadow-for-wpf-borderless-window – 2013-05-11 04:29:14

+0

你見過這個鏈接http://stackoverflow.com/questions/2463519/drop-shadow-in通過嘗試覆蓋createparams -winforms控件? – Edper 2013-05-11 04:29:40

+1

@Edper覆蓋cp會給第二張圖片上的陰影 – 2013-05-11 04:46:19

回答

0

據我所知,在這樣做的沒有直接的方法的WinForms。

相反,可以按照此步驟由步驟:

1)創建使用Photoshop或任何其他工具具有所需陰影的圖像。 2)使用這張圖片作爲你的表格的背景圖片。
3)將窗體的FormBorderStyle屬性設置爲None。
4)你完成了!
5)注意:請確保以適當的格式(例如png)保存圖像,以便陰影效果可以工作。

+1

這可以在WinForms中完成。它可以使用分層窗口來實現。 – 2013-05-11 05:38:07

+0

@ByteBlast請你詳細說明一下,以便我們能夠感受開悟......我上面討論的方法是幾種可能的方法之一。 – 2013-05-11 08:16:19

+0

「在WinForms中沒有直接的方法。」 – 2013-05-11 08:37:11

32

在WinForms中,您可以覆蓋表單的受保護CreateParams屬性並將CS_DROPSHADOW標誌添加到類樣式中。例如:

public class ShadowedForm : Form { 
    protected override CreateParams CreateParams { 
     get { 
      const int CS_DROPSHADOW = 0x20000; 
      CreateParams cp = base.CreateParams; 
      cp.ClassStyle |= CS_DROPSHADOW; 
      return cp; 
     } 
    } 

    // ... other code ... 
} 

但是,一些注意事項…

  1. 此標誌只適用於頂層窗口。在Win32中,這意味着重疊和彈出窗口。它對子窗口(例如控件)沒有影響。我以爲我記得在某處聽說這個限制已經從Windows 8中刪除了,但是我找不到確認這一點的鏈接,而且我沒有安裝用於測試目的的Windows 8。

  2. 用戶可能完全禁用了此功能。如果是這樣,不管你如何要求,你都不會得到陰影。這是設計。您的應用程序不應嘗試重寫此請求。您可以通過P /調用SystemParametersInfo函數並傳遞SPI_GETDROPSHADOW標誌來確定是否啓用或禁用投影。

  3. Aero主題還爲頂級窗口添加陰影。此效果與CS_DROPSHADOW分開且不同,並且在啓用Aero時僅適用於。無法關閉個人窗口並關閉它。此外,由於Aero主題已從Windows 8中刪除,因此它不會有這些陰影。

+0

他已經有了陰影。 DWM pinvoke在Winforms中也同樣適用,使用OnHandleCreated。它在Win8中看起來*非常*差。 – 2013-05-11 08:41:34

+0

以及@HansPassant說,再次cp給出像第二張圖片一樣的陰影 – 2013-05-11 19:26:06

7

赫姆,,,剛剛過去的代碼,你會得到Windows 7的陰影 這樣>>>http://marcin.floryan.pl/wp-content/uploads/2010/08/WPF-Window-native-shadow.png

Imports System.Runtime.InteropServices 

Public Class IMSS_SplashScreen 
    Private aeroEnabled As Boolean 
    Protected Overrides ReadOnly Property CreateParams() As CreateParams 
     Get 
      CheckAeroEnabled() 
      Dim cp As CreateParams = MyBase.CreateParams 
      If Not aeroEnabled Then 
       cp.ClassStyle = cp.ClassStyle Or NativeConstants.CS_DROPSHADOW 
       Return cp 
      Else 
       Return cp 
      End If 
     End Get 
    End Property 
    Protected Overrides Sub WndProc(ByRef m As Message) 
     Select Case m.Msg 
      Case NativeConstants.WM_NCPAINT 
       Dim val = 2 
       If aeroEnabled Then 
        NativeMethods.DwmSetWindowAttribute(Handle, 2, val, 4) 
        Dim bla As New NativeStructs.MARGINS() 
        With bla 
         .bottomHeight = 1 
         .leftWidth = 1 
         .rightWidth = 1 
         .topHeight = 1 
        End With 
        NativeMethods.DwmExtendFrameIntoClientArea(Handle, bla) 
       End If 
       Exit Select 
     End Select 
     MyBase.WndProc(m) 
    End Sub 
    Private Sub CheckAeroEnabled() 
     If Environment.OSVersion.Version.Major >= 6 Then 
      Dim enabled As Integer = 0 
      Dim response As Integer = NativeMethods.DwmIsCompositionEnabled(enabled) 
      aeroEnabled = (enabled = 1) 
     Else 
      aeroEnabled = False 
     End If 
    End Sub 
End Class 
Public Class NativeStructs 
    Public Structure MARGINS 
     Public leftWidth As Integer 
     Public rightWidth As Integer 
     Public topHeight As Integer 
     Public bottomHeight As Integer 
    End Structure 
End Class 
Public Class NativeMethods 
    <DllImport("dwmapi")> _ 
    Public Shared Function DwmExtendFrameIntoClientArea(ByVal hWnd As IntPtr, ByRef pMarInset As NativeStructs.MARGINS) As Integer 
    End Function 
    <DllImport("dwmapi")> _ 
    Friend Shared Function DwmSetWindowAttribute(ByVal hwnd As IntPtr, ByVal attr As Integer, ByRef attrValue As Integer, ByVal attrSize As Integer) As Integer 
    End Function 
    <DllImport("dwmapi.dll")> _ 
    Public Shared Function DwmIsCompositionEnabled(ByRef pfEnabled As Integer) As Integer 
    End Function 
End Class 
Public Class NativeConstants 
    Public Const CS_DROPSHADOW As Integer = &H20000 
    Public Const WM_NCPAINT As Integer = &H85 
End Class 
+0

偉大的實現,但它似乎失去了它的投影時,控制失去/獲得焦點,或與其他窗口交互。你知道如何解決這個問題嗎? – series0ne 2014-11-10 09:16:20

+0

@seriesOne聽起來像只需要處理窗體大小調整事件並調用this.Update()或this.Refresh()。所以窗口被「強制」重新繪製,從而重繪陰影。我還沒有試過這個代碼,但我猜這就是爲什麼。 – SE13013 2015-07-17 08:37:32

11

這裏是我的C#實現。它與Al.Pertro's類似,但你會注意到當你失去焦點並重新獲得焦點時,陰影會重新繪製自己。

我也已經添加到代碼,以允許拖動鼠標。

public partial class Form1 : Form 
{ 
    [DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")] 
    private static extern IntPtr CreateRoundRectRgn 
    (
     int nLeftRect, // x-coordinate of upper-left corner 
     int nTopRect, // y-coordinate of upper-left corner 
     int nRightRect, // x-coordinate of lower-right corner 
     int nBottomRect, // y-coordinate of lower-right corner 
     int nWidthEllipse, // height of ellipse 
     int nHeightEllipse // width of ellipse 
    );   

    [DllImport("dwmapi.dll")] 
    public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset); 

    [DllImport("dwmapi.dll")] 
    public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize); 

    [DllImport("dwmapi.dll")] 
    public static extern int DwmIsCompositionEnabled(ref int pfEnabled); 

    private bool m_aeroEnabled;      // variables for box shadow 
    private const int CS_DROPSHADOW = 0x00020000; 
    private const int WM_NCPAINT = 0x0085; 
    private const int WM_ACTIVATEAPP = 0x001C; 

    public struct MARGINS       // struct for box shadow 
    { 
     public int leftWidth; 
     public int rightWidth; 
     public int topHeight; 
     public int bottomHeight; 
    } 

    private const int WM_NCHITTEST = 0x84;   // variables for dragging the form 
    private const int HTCLIENT = 0x1; 
    private const int HTCAPTION = 0x2; 

    protected override CreateParams CreateParams 
    { 
     get 
     { 
      m_aeroEnabled = CheckAeroEnabled(); 

      CreateParams cp = base.CreateParams; 
      if (!m_aeroEnabled) 
       cp.ClassStyle |= CS_DROPSHADOW; 

      return cp; 
     } 
    } 

    private bool CheckAeroEnabled() 
    { 
     if (Environment.OSVersion.Version.Major >= 6) 
     { 
      int enabled = 0; 
      DwmIsCompositionEnabled(ref enabled); 
      return (enabled == 1) ? true : false; 
     } 
     return false; 
    } 

    protected override void WndProc(ref Message m) 
    { 
     switch (m.Msg) 
     { 
      case WM_NCPAINT:      // box shadow 
       if (m_aeroEnabled) 
       { 
        var v = 2; 
        DwmSetWindowAttribute(this.Handle, 2, ref v, 4); 
        MARGINS margins = new MARGINS() 
        { 
         bottomHeight = 1, 
         leftWidth = 1, 
         rightWidth = 1, 
         topHeight = 1 
        }; 
        DwmExtendFrameIntoClientArea(this.Handle, ref margins); 

       } 
       break; 
      default: 
       break; 
     } 
     base.WndProc(ref m); 

     if (m.Msg == WM_NCHITTEST && (int)m.Result == HTCLIENT)  // drag the form 
      m.Result = (IntPtr)HTCAPTION; 

    } 

    public Form1() 
    { 
     m_aeroEnabled = false; 

     this.FormBorderStyle = FormBorderStyle.None; 

     InitializeComponent(); 
    } 
} 
+0

注意。如果在所有邊上將MARGINS結構設置爲-1,並從OnSizeChanged方法調用CreateRoundRectRgn,則也可以實現圓角邊緣 - 但是,當表單失去焦點時,這將導致陰影消失......任何想法? – series0ne 2015-01-28 15:18:55