2012-01-09 24 views
9

Version viết tắt:của Windows DropShadow 7 phong cách trong hình thức không biên giới

Mục tiêu: Một sâu, tối, Windows 7 DropShadow trong WinForm không biên giới trong C#


Các giải pháp hiện có đã biết 1: Kiểu đổ bóng kiểu XP đơn giản bằng cách sử dụng CreateParams.

Sự cố: Để yếu, nhẹ, xấu.


Được biết đến các giải pháp hiện có 2: Thay GDI của mẫu với bitmap.

Sự cố: Mất khả năng sử dụng điều khiển, chỉ hoạt động như màn hình giật gân.


Objective qua đường bưu điện này: Tìm một giải pháp trung bình cho vấn đề này hoặc tất cả cùng nhau tốt hơn một.

. . .

dài Version:

(Edit:. Tôi đề cập đến trình đơn thả bóng đi dọc theo biên giới của bất kỳ hình thức cửa sổ, nếu đó không phải là rõ ràng) Tôi hiểu rằng có một cách để làm cho dropshadows phong cách XP trong C# sử dụng:

C# Code 1 - Simple XP kiểu DropShadow (vấn đề: với ánh sáng, yếu, để xấu xí)

// Define the CS_DROPSHADOW constant 
private const int CS_DROPSHADOW = 0x00020000; 

// Override the CreateParams property 
protected override CreateParams CreateParams 
{ 
    get 
    { 
     CreateParams cp = base.CreateParams; 
     cp.ClassStyle |= CS_DROPSHADOW; 
     return cp; 
    } 
} 

Tuy nhiên, tôi đang cố gắng tìm ra cách làm cho chúng xuất hiện như trong Windows 7 (bóng tối hơn và lớn hơn) và không thể tìm ra cách tốt nhất để làm điều này.

Tôi có một phương pháp hiện nay được tạo ra sẽ cho phép tôi ghi đè lên toàn bộ hình thức GDI và xuất hiện như một màn hình splash sẽ (tín dụng không phải của tôi):

C# Mã 2: Thay thế hình thức GDI với Bitmap (Vấn đề: có thể 't sử dụng hình thức kiểm soát, khó có thể duy trì GUI)

public void SetBitmap(Bitmap bitmap, byte opacity) 
    { 
     if (bitmap.PixelFormat != PixelFormat.Format32bppArgb) 
      throw new ApplicationException("The bitmap must be 32ppp with alpha-channel."); 

     // 1. Create a compatible DC with screen; 
     // 2. Select the bitmap with 32bpp with alpha-channel in the compatible DC; 
     // 3. Call the UpdateLayeredWindow. 

     IntPtr screenDc = Win32.GetDC(IntPtr.Zero); 
     IntPtr memDc = Win32.CreateCompatibleDC(screenDc); 
     IntPtr hBitmap = IntPtr.Zero; 
     IntPtr oldBitmap = IntPtr.Zero; 

     try 
     { 
      hBitmap = bitmap.GetHbitmap(Color.FromArgb(0)); // grab a GDI handle from this GDI+ bitmap 
      oldBitmap = Win32.SelectObject(memDc, hBitmap); 

      Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height); 
      Win32.Point pointSource = new Win32.Point(0, 0); 
      Win32.Point topPos = new Win32.Point(Left, Top); 
      Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION(); 
      blend.BlendOp = Win32.AC_SRC_OVER; 
      blend.BlendFlags = 0; 
      blend.SourceConstantAlpha = opacity; 
      blend.AlphaFormat = Win32.AC_SRC_ALPHA; 

      Win32.UpdateLayeredWindow(this.Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA); 
     } 
     finally 
     { 
      Win32.ReleaseDC(IntPtr.Zero, screenDc); 
      if (hBitmap != IntPtr.Zero) 
      { 
       Win32.SelectObject(memDc, oldBitmap); 
       Win32.DeleteObject(hBitmap); 
      } 
      Win32.DeleteDC(memDc); 
     } 
    } 


    protected override CreateParams CreateParams 
    { 
     get 
     { 
      CreateParams cp = base.CreateParams; 
      cp.ExStyle |= 0x00080000; // This form has to have the WS_EX_LAYERED extended style 
      return cp; 
     } 
    } 

Tuy nhiên, điều này không cho tôi một nền tảng đầy đủ 32-bit (như tôi yêu cầu để thêm DropShadow bằng tay), nhưng tôi đã làm mất khả năng tạo ra hình thức các thành phần hiển thị.

Vì vậy, về cơ bản, tôi đang cố gắng tìm ra trung bình giữa hai phương pháp này. Một cái gì đó mà sẽ cho tôi bóng tối sâu và tối mà không làm mất chức năng khác/gây ra yêu cầu sơn lại quá mức.

+1

Câu hỏi của bạn chính xác là gì? Đây thực sự không phải là nơi để viết giải pháp cho bạn. –

+3

@Ramhound Câu hỏi rất đơn giản. Tôi đang tìm cách để chỉ đúng hướng về điều này. Câu hỏi của tôi được nghiên cứu kỹ và rõ ràng như tôi có thể làm được. Tôi chỉ muốn biết nếu có ai biết cách tốt hơn để tạo ra một dropshadow kiểu Windows 7. – Corylulu

+1

Bạn có thể thêm ảnh chụp màn hình hoặc mô hình kết quả mong muốn không? –

Trả lời

7

Được rồi, vì vậy sau khoảng 4 giờ động não và viết mã, cuối cùng tôi đã phát triển một giải pháp. Về cơ bản, tôi đã thực hiện 2 hình thức.

Mẫu # 1: Tạo DropShadow bằng cách sửa đổi và kết hợp 8 hình ảnh (4 góc gradient +4 gradient tuyến tính cho mỗi hướng) và thiết lập chúng như là một nền tảng sử dụng mã thứ hai tôi được đăng trên đây (C# Mã 2: Thay thế biểu mẫu GDI bằng Bitmap). Code khá nhiều giải thích nó.

public partial class Dropshadow : Form 
{ 

    public Dropshadow(Form parentForm) 
    { 
     /*This bit of code makes the form click-through. 
      So you can click forms that are below it in z-space */ 
     int wl = GetWindowLong(this.Handle, -20); 
     wl = wl | 0x80000 | 0x20; 
     SetWindowLong(this.Handle, -20, wl); 

     InitializeComponent(); 

     //Makes the start location the same as parent. 
     this.StartPosition = parentForm.StartPosition; 

     parentForm.Activated += ParentForm_Activated; //Fires on parent activation to do a this.BringToFront() 
     this.Deactivate += This_Deactivated; //Toggles a boolean that ensures that ParentForm_Activated does fire when clicking through (this) 
     parentForm.Closed += ParentForm_Closed; //Closes this when parent closes 
     parentForm.Move += ParentForm_Move; //Follows movement of parent form 

     //Draws border with standard bitmap modifications and merging 
     /* Omitted function to avoid extra confusion */ 
     Bitmap getShadow = DrawBlurBorder(parentForm.ClientSize.Width, parentForm.ClientSize.Height); 
     /* **This code was featured in the original post:** */ 
     SetBitmap(getShadow, 255); //Sets background as 32-bit image with full alpha. 

     this.Location = Offset; //Set within DrawBlurBorder creates an offset 

    } 
    private void ParentForm_Activated(object o, EventArgs e) 
    { 
     /* Sets this form on top when parent form is activated.*/ 
     if (isBringingToFront) 
     { 
      /*Hopefully prevents recusion*/ 
      isBringingToFront = false; 
      return; 
     } 

     this.BringToFront(); 


     /* Some special tweaks omitted to avoid confusion */ 
    } 
    private void This_Deactivated(object o, EventArgs e) 
    { 
     /* Prevents recusion. */ 
     isBringingToFront = true; 
    } 
    /* Closes this when parent form closes. */ 
    private void ParentForm_Closed(object o, EventArgs e) 
    { 
     this.Close(); 
    } 
    /* Adjust position when parent moves. */ 
    private void ParentForm_Move(object o, EventArgs e) 
    { 
     if(o is Form) 
      this.Location = new Point((o as Form).Location.X + Offset.X, (o as Form).Location.Y + Offset.Y); 
    } 
} 

Mẫu # 2: Đây chỉ ra mắt dưới dạng DropShadow lúc khởi động và tôi cũng tạo ra một số giao diện cho phép hội nhập sâu hơn và linh hoạt mà tôi bỏ qua để tránh thêm bối rối. Về cơ bản phương pháp để đảm bảo rằng các hình thức Dropshadow đã không lấy đi các nhấp chuột từ các hình thức hoạt động và sẽ không buộc người dùng phải bấm vào một nút hai lần nếu các hình thức Dropshadow là trên đầu trang.

+1

Tôi không biết nếu đây là cách tốt nhất để làm điều này nhưng tôi nghĩ nó khá thông minh. –

3

Xin cảm ơn, Corylulu.

Lớp khả thi là here.

var f = new Dropshadow(this) 
{ 
    BorderRadius = 40, 
    ShadowColor = Color.Blue 
}; 

f.RefreshShadow(); 

DEMO

Các DrawShadow tạo ra một bóng như bitmap, nhưng chưa hoàn hảo. Lớp học này không hoàn hảo, nhưng nó hoạt động.

BTW, tôi không biết cách ẩn biểu mẫu bóng trong thanh tác vụ. Đặt ShowInTaskBar = false sẽ trường hợp biểu mẫu biến mất.

EDIT

Tôi viết lại lớp, bây giờ nó trông như thế này, một DropShadow thực.

Nguồn là here.

Một điều bạn nên biết là lớp học này không xem xét border-radius (có biểu mẫu css).

bất động sản chính là

  • ShadowColor
  • ShadowV
  • ShadowH
  • ShadowSpread
  • ShadowBlur

Khu nghỉ dưỡng là giống như css box-shadow, xem here

Những propertyies

  • ShadowSpread
  • ShadowBlur
  • ShadowColor

yêu cầu bạn tay gọi RefreshShadow().

Đi tới demo project

+0

Điều thú vị về vấn đề ShowInTaskbar. Tôi dường như không có cùng một vấn đề. Tôi sẽ tìm ra mã mà tôi có và gửi cho bạn nếu bạn muốn. Đó là mã rất cũ, do đó, nó không chính xác tối ưu hóa. – Corylulu

+0

Phiên bản của tôi được tham gia nhiều hơn một chút và tôi quên chính xác lý do: P nhưng đây là tất cả những gì tôi đã làm để làm cho mã hoạt động tốt. Một số có thể là cụ thể cho những gì tôi đã cố gắng để làm, nhưng tôi chủ yếu đã cố gắng để có tất cả những điều đó. http://pastie.org/8588447 – Corylulu

+0

Tôi tạo một dự án mới để kiểm tra dropshadow, tìm ra 'ShowInTaskBar' là tốt. Bây giờ, phần khó khăn là vẽ một bitmap bóng. Tôi muốn sử dụng tham số được mô tả [ở đây] (http://www.w3schools.com/cssref/css3_pr_box-shadow.asp) .Tôi nhận thấy rằng bạn vẽ bóng sử dụng hình ảnh, không thể thay đổi được. – wener

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