• Vui lòng đọc nội qui diễn đàn để tránh bị xóa bài viết
  • Tìm kiếm trước khi đặt câu hỏi

Hiệu ứng Fading trong win Vista

Các mẹo vặt linh tinh không thuộc các nhóm trên

Điều hành viên: tungcan5diop, QUANITGROBEST

NovaFooc
Thành viên tâm huyết
Thành viên tâm huyết
Bài viết: 307
Ngày tham gia: T.Ba 11/08/2009 3:27 pm

Hiệu ứng Fading trong win Vista

Gửi bàigửi bởi NovaFooc » T.Sáu 21/08/2009 4:12 pm

Thủ thuật: Hiệu ứng Fading trong win Vista
Tác giả: MSDN, CodeGuru
Mô tả: Sử dụng hàm BeginBufferedAnimation có sẵn trong win Vista


Nếu ai đã chiêm ngưỡng qua giao diện Aero của win Vista thì thấy khi ta di con trỏ chuột qua các control nó sẽ từ từ sáng dần lên (chứ không 1 hit liền như XP). Chính xác tên hiệu ứng đó là gì thì mình không rõ, nhưng quen miệng gọi là Fading nên cứ tạm gọi vậy nhé.
Cách làm thì có nhiều, hôm nay mình sẽ giới thiệu cách sử dụng hàm api có sẵn trong win Vista để làm (XP không hỗ trợ trò này).

Không biết có phải search gà không mà lên mạng tìm được toàn source C++ (tại mình không rành C nên hơi bị uất), ngồi biên tập lại qua VB để ai thích thì tìm hiểu. Tham khảo chính tại http://msdn.microsoft.com/en-us/library/bb773252(VS.85,loband).aspxhttp://www.codeguru.com/cpp/w-p/vista/article.php/c15841/.

Vì sẽ sử dụng các hàm api nên các bác imports sẵn InteropServices để tí nữa còn dùng tới.
Đầu tiên sẽ là khai báo các hàm api, trong đó BeginBufferedAnimation là hàm quan trọng nhất.

Mã: Chọn hết

  1. Public Class VistaAPI
  2.     Public Enum BP_ANIMATIONSTYLE
  3.         BPAS_NONE
  4.         BPAS_LINEAR
  5.         BPAS_CUBIC
  6.         BPAS_SINE
  7.     End Enum
  8.  
  9.     Public Enum BP_BUFFERFORMAT
  10.         BPBF_COMPATIBLEBITMAP
  11.         BPBF_DIB
  12.         BPBF_TOPDOWNDIB
  13.         BPBF_TOPDOWNMONODIB
  14.     End Enum
  15.  
  16.     Public Structure BP_ANIMATIONPARAMS
  17.         Public cbSize As Integer
  18.         Public dwFlags As Integer
  19.         Public style As BP_ANIMATIONSTYLE
  20.         Public dwDuration As Integer
  21.     End Structure
  22.  
  23.     Public Structure BP_PAINTPARAMS
  24.         Public cbSize As Integer
  25.         Public dwFlags As Integer
  26.         Public prcExclude As IntPtr
  27.         Public pBlendFunction As IntPtr
  28.     End Structure
  29.  
  30.  
  31.     Public Structure BLENDFUNCTION
  32.         Public BlendOp As BlendOperation
  33.         Public BlendFlags As BlendFlags
  34.         Public SourceConstantAlph As Byte
  35.         Public AlphaFormat As AlphaFormat
  36.     End Structure
  37.     Public Enum BlendOperation As Byte
  38.         AC_SRC_OVER = &H0
  39.     End Enum
  40.     Public Enum BlendFlags As Byte
  41.         Zero = &H0
  42.     End Enum
  43.     Public Enum SourceConstantAlpha As Byte
  44.         Transparent = &H0
  45.         Opaque = &HFF
  46.     End Enum
  47.     Public Enum AlphaFormat As Byte
  48.         AC_SRC_ALPHA = &H1
  49.     End Enum
  50.  
  51.  
  52.     <DllImport("uxtheme.dll")> _
  53.     Public Shared Sub BufferedPaintInit()
  54.     End Sub
  55.  
  56.     <DllImport("uxtheme.dll")> _
  57.     Public Shared Sub BufferedPaintUnInit()
  58.     End Sub
  59.  
  60.     <DllImport("uxtheme.dll")> _
  61.     Public Shared Function BufferedPaintRenderAnimation(ByVal hwnd As IntPtr, ByVal hdc As IntPtr) As Boolean
  62.     End Function
  63.  
  64.     <DllImport("uxtheme.dll")> _
  65.     Public Shared Sub BufferedPaintStopAllAnimations(ByVal hwnd As IntPtr)
  66.     End Sub
  67.  
  68.     <DllImport("uxtheme.dll")> _
  69.     Public Shared Function BeginBufferedAnimation(ByVal hwnd As IntPtr, ByVal hdcTarget As IntPtr, ByRef rcTarget As Rectangle, ByVal dwFormat As BP_BUFFERFORMAT, ByVal pPaintParams As IntPtr, ByRef pAnimationParams As BP_ANIMATIONPARAMS, ByRef phdcFrom As IntPtr, ByRef phdcTo As IntPtr) As IntPtr
  70.     End Function
  71.  
  72.     <DllImport("uxtheme.dll")> _
  73.     Public Shared Sub EndBufferedAnimation(ByVal hbpAnimation As IntPtr, ByVal fUpdateTarget As Boolean)
  74.     End Sub
  75. End Class


Tiếp đến là thủ tục vẽ dòng chữ “Fading” lên màn hình (để minh hoạ thôi, cái này không cần quan tâm).

Mã: Chọn hết

  1. Const dispText As String = "Fading"
  2. Dim state As Boolean
  3. Dim dispFont(1) As Font, dispBrush(1) As Brush, dispFormat(1) As StringFormat, backBrush(1) As Drawing2D.LinearGradientBrush
  4.  
  5. Private Sub InitText()
  6.     dispFont(0) = New Font("Segoe UI", 50, FontStyle.Bold, GraphicsUnit.Pixel)
  7.     dispFont(1) = New Font("Segoe UI", 50, FontStyle.Bold, GraphicsUnit.Pixel)
  8.     dispBrush(0) = New SolidBrush(Color.FromArgb(64, 250, 100, 50))
  9.     dispBrush(1) = New SolidBrush(Color.FromArgb(250, 100, 50))
  10.     dispFormat(0) = New StringFormat()
  11.     dispFormat(0).Alignment = StringAlignment.Center
  12.     dispFormat(0).LineAlignment = StringAlignment.Center
  13.     dispFormat(1) = New StringFormat()
  14.     dispFormat(1).Alignment = StringAlignment.Center
  15.     dispFormat(1).LineAlignment = StringAlignment.Center
  16.     backBrush(0) = New Drawing2D.LinearGradientBrush(New Point(0, 0), New Point(0, 150), Color.FromArgb(50, 50, 50), Color.FromArgb(100, 100, 100))
  17.     backBrush(1) = New Drawing2D.LinearGradientBrush(New Point(0, 0), New Point(0, 150), Color.FromArgb(200, 200, 200), Color.FromArgb(150, 150, 150))
  18. End Sub
  19.  
  20. Private Sub RenderText(ByVal hdc As Integer, ByVal state As Boolean)
  21.     Dim i As Integer = CInt(state) * -1
  22.     Dim g As Graphics = Graphics.FromHdc(hdc)
  23.     g.FillRectangle(backBrush(i), rect)
  24.     g.DrawString(dispText, dispFont(i), dispBrush(i), Me.Width / 2, Me.Height / 2 - 50 / 4, dispFormat(i))
  25.     g.Dispose()
  26. End Sub

 
Để sử dụng được hàm BeginBufferedAnimation, chúng ta cần chuẩn bị những tham số cần thiết cho nó.

Mã: Chọn hết

  1. Dim aniDur As Integer
  2. Dim myHwnd As IntPtr, myHdc As IntPtr, myRect As Rectangle, myAni As New VistaAPI.BP_ANIMATIONPARAMS
  3.  
  4. Private Sub InitAnimation()
  5.     myHwnd = Me.Handle
  6.     myHdc = Me.CreateGraphics.GetHdc
  7.     myRect = Me.ClientRectangle
  8.     myAni.cbSize = Marshal.SizeOf(myAni)
  9.     myAni.style = VistaAPI.BP_ANIMATIONSTYLE.BPAS_LINEAR
  10.     myAni.dwDuration = aniDur
  11. End Sub


Các bác gọi 2 thằng InitTextInitAnimation trước khi bắt đầu thực hiện hiệu ứng Fading 1 lần là đủ. Và giờ nhúng các tham số vừa tạo vào BeginBufferedAnimation được rồi.

Mã: Chọn hết

  1. Private Sub RePaint()
  2.     If Not VistaAPI.BufferedPaintRenderAnimation(myHwnd, myHdc) Then
  3.         If aniDur = 0 Then
  4.             Exit Sub
  5.         End If
  6.  
  7.         Dim hdcFrom As IntPtr, hdcTo As IntPtr
  8.         Dim hbpAnimation As IntPtr = VistaAPI.BeginBufferedAnimation( _
  9.          myHwnd, _
  10.          myHdc, _
  11.          myRect, _
  12.          VistaAPI.BP_BUFFERFORMAT.BPBF_DIB, _
  13.          IntPtr.Zero, _
  14.          myAni, _
  15.          hdcFrom, _
  16.          hdcTo)
  17.  
  18.         If hbpAnimation <> IntPtr.Zero Then
  19.             If hdcFrom <> IntPtr.Zero Then
  20.                 RenderText(hdcFrom, state)
  21.             End If
  22.             If hdcTo <> IntPtr.Zero Then
  23.                 RenderText(hdcTo, Not state)
  24.             End If
  25.             VistaAPI.EndBufferedAnimation(hbpAnimation, True)
  26.             aniDur = 0
  27.             state = Not state
  28.         End If
  29.     End If
  30. End Sub


Một điều rất là bình thường như lúc ta dùng các hàm api khác, khi form vừa được nạp (nói chung là trước khi BeginBufferedAnimation được gọi) thì nên gọi BufferedPaintInit để win “chuẩn bị tinh thần” vẽ cảnh động. Và dùng xong thì cũng báo lại cho win biết để nó dành đất cho những đứa khác, trước khi form đóng ta gọi thêm BufferedPaintStopAllAnimations, BufferedPaintUnInit.

Hàm BufferedPaintRenderAnimation khi được gọi sẽ tạo 1 timer gửi liên tục thông điệp WM_PAINT để tạo cảnh động (khi nào xong thì nó thôi không gửi nữa). Bắt thông điệp đó là xong.

Mã: Chọn hết

  1. Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
  2.     If m.Msg = VistaAPI.WM_PAINT Then RePaint()
  3.     MyBase.WndProc(m)
  4. End Sub


Tới đây coi như xong xuôi gần hết rồi, để hiệu ứng chạy thì thêm vài dòng nữa thôi.

Mã: Chọn hết

  1. Private Sub StartAnimation()
  2.     aniDur = 500
  3.     myAni.dwDuration = aniDur
  4.     Invalidate()
  5. End Sub


Thích hiệu ứng chạy lúc nào thì gọi em StartAnimation lúc đó nhé.

Khi dùng hàm BeginBufferedAnimation, tham số pPaintParams đã bị bỏ qua. Nếu ai thích dùng thì tự sửa lại một chút là được (công dụng của nó cũng tự tìm hiểu luôn nha).
Đoạn dưới http://www.codeguru.com/cpp/w-p/vista/article.php/c15841/ viết :
The fifth parameter to BeginBufferedAnimation is a pointer to a BP_PAINTPARAMS structure. This can be NULL if you don't need it. Because the buffered animation technique will keep off-screen buffers alive and will reuse them in future buffered painting calls, it is important to remember that the contents of the off-screen buffer is not erased by default. So, either you fill the off-screen buffer yourself with a certain color to erase the previous drawing (as I did in my example above), or you can use the BP_PAINTPARAMS structure to force BeginBufferedAnimation to clear the off-screen buffer with ARGB = {0,0,0,0}. You also can change clipping behavior on the off-screen buffer and specify blending parameters. The blending parameters are used to control blending operations when EndBufferedAnimation copies the contents of the off-screen buffer to the destination.


Trong lúc khai báo các hàm api có thể thấy tất cả đều thuộc thư viện uxtheme.dll. Dĩ nhiên chẳng ai thiết kế cái control to bằng... cái màn hình nên sẽ dể hiểu tại sao khi ta áp dụng hàm BufferedPaintRenderAnimation trên một vùng màn hình lớn thì nó không được mượt (nghe cái ông ở trên nói win 7 đã fix vấn đề này nhưng mình chưa thử nên không dám khẳng định).

Đây là source code hoàn chỉnh, ai thích thì down về nghiên cứu.
Tập tin đính kèm
FadingEffect.zip
(24.78 KiB) Đã tải 602 lần



Quay về “[.NET] Mẹo vặt khác”

Đang trực tuyến

Đang xem chuyên mục này: Không có thành viên nào trực tuyến.1 khách