2013-05-11 32 views
13

Tôi đang cố gắng để thả một bóng xung quanh toàn bộ hình thức giống như hình ảnh đầu tiên, ngoại trừ đó là một WPF không phải là một WinForm. bây giờ tôi muốn thả cùng một bóng trên một winform.Thả bóng trên một WinForm không biên giới

Đây là những gì tôi want..¬

Windows Form Shadow

Không this..¬

Windows Form Shadow

+0

http://stackoverflow.com/questions/3372303/dropshadow-for-wpf-borderless-window –

+0

Bạn đã thấy liên kết này http://stackoverflow.com/questions/2463519/drop-shadow-in -winforms-kiểm soát bằng cách cố gắng ghi đè lên các createparams? – Edper

+1

@Edper ghi đè cp sẽ cung cấp cho bóng trong hình ảnh thứ hai –

Trả lời

0

Theo như tôi biết, không có cách nào trực tiếp để làm điều này trong WinForms.

Thay vào đó, bạn có thể làm theo bước này theo từng bước:

1) Tạo hình ảnh có bóng thả mong muốn bằng photoshop hoặc bất kỳ công cụ nào khác.
2) Sử dụng hình ảnh này làm hình nền của biểu mẫu của bạn.
3) Đặt thuộc tính FormBorderStyle của biểu mẫu thành Không.
4) Bạn đã hoàn tất!
5) Lưu ý: Đảm bảo lưu hình ảnh ở định dạng thích hợp (chẳng hạn như png) để hiệu ứng đổ bóng có thể hoạt động.

+1

Điều này có thể được thực hiện trong WinForms. Nó có thể đạt được bằng cách sử dụng các cửa sổ nhiều lớp. –

+0

@ByteBlast bạn có thể vui lòng xây dựng để chúng tôi có thể cảm thấy giác ngộ ... Phương pháp tôi đã thảo luận ở trên là một trong nhiều cách có thể. –

+0

"Không có cách trực tiếp để làm điều này trong WinForms." –

32

Trong WinForms, bạn chỉ có thể ghi đè thuộc tính được bảo vệ của biểu mẫu CreateParams và thêm cờ CS_DROPSHADOW vào kiểu lớp. Ví dụ:

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 ... 
} 

Nhưng, một vài điều nên cẩn thận & hellip;

  1. Cờ này chỉ hoạt động trên các cửa sổ cấp cao nhất. Trong Win32-nói, đó có nghĩa là chồng chéo và cửa sổ popup. Nó không ảnh hưởng đến cửa sổ con (ví dụ: điều khiển). Tôi nghĩ rằng tôi nhớ nghe ở đâu đó rằng giới hạn này đã được gỡ bỏ từ Windows 8, nhưng tôi không thể tìm thấy một liên kết xác nhận điều này và tôi không có Windows 8 được cài đặt cho mục đích thử nghiệm.

  2. Có thể người dùng đã tắt hoàn toàn tính năng này. Nếu vậy, bạn sẽ không nhận được bóng đổ, bất kể bạn hỏi họ như thế nào. Đó là do thiết kế. Ứng dụng của bạn không nên thử và ghi đè yêu cầu này. Bạn có thể xác định xem bóng thả được bật hay tắt bằng cách P/Gọi hàm SystemParametersInfo và chuyển cờ SPI_GETDROPSHADOW.

  3. Chủ đề Aero cũng thêm bóng vào cửa sổ cấp cao nhất. Hiệu ứng này tách biệt với CS_DROPSHADOW và chỉ hoạt động chỉ khi Aero được bật. Không có cách nào để tắt và bật cho từng cửa sổ riêng lẻ. Hơn nữa, kể từ khi chủ đề Aero đã được gỡ bỏ từ Windows 8, nó sẽ không bao giờ có những bóng tối.

+0

Anh ấy đã có dropshadow đó. Ghim DWM hoạt động tốt trong Winforms, sử dụng OnHandleCreated. Tất cả đều trông * rất * nghèo trong Win8. –

+0

cũng như @HansPassant cho biết và một lần nữa các cp cho cùng một bóng giống như hình ảnh thứ hai –

7

Humm ,,, Chỉ cần quá khứ mã và bạn sẽ nhận được các cửa sổ 7 Drop Shadow như thế này >>>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

Thực hiện tuyệt vời, nhưng nó có vẻ mất bóng thả khi điều khiển mất/tăng tập trung, hoặc khi tương tác với các cửa sổ khác. Bạn có biết cách giải quyết vấn đề này không? – series0ne

+0

@seriesMột số âm thanh như bạn chỉ cần xử lý sự kiện thay đổi kích thước biểu mẫu và gọi this.Update() hoặc this.Refresh(). do đó, cửa sổ là "buộc" để sơn lại chính nó do đó cũng sơn lại bóng tối. Tôi chưa thử mã này, nhưng tôi đoán đó là lý do tại sao. – SE13013

11

Dưới đây là tôi C# thực hiện. Nó tương tự như Al.Pertro, nhưng bạn sẽ nhận thấy rằng khi bạn mất tập trung và lấy lại sự tập trung, bóng sẽ tự vẽ lại.

Tôi cũng đã thêm vào mã để cho phép kéo chuột.

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

Lưu ý. nếu bạn đặt cấu trúc MARGINS thành -1 trên tất cả các cạnh và gọi CreateRoundRectRgn từ phương thức OnSizeChanged của bạn, bạn cũng có thể đạt được các cạnh tròn - tuy nhiên điều này làm cho bóng thả biến mất khi biểu mẫu mất tiêu điểm ... bất kỳ ý tưởng nào? – series0ne

Các vấn đề liên quan