Code:
Option Explicit
Private Type OLECOLOR
RedOrSys As Byte
Green As Byte
Blue As Byte
Type As Byte
End Type
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Private Declare Function GetSysColor Lib "user32" (ByVal nIndex As Long) As Long
Private Declare Function GetPixel Lib "gdi32" (ByVal hDC As Long, ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long
Private Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As Long
Private Declare Function SetWindowRgn Lib "user32" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Long) As Long
Private Declare Function GetWindowRgn Lib "user32" (ByVal hWnd As Long, ByVal hRgn As Long) As Long
Private Const RGN_OR = 2
Private Const RGN_XOR = 3
Public Sub PictureBoxMasking(ByVal PictureBox As VB.PictureBox, ByVal MaskColor As Long)
Dim Skin As Long, TempSkin As Long
Dim Width As Long, Height As Long, ScaleWidth As Long, ScaleHeight As Long
Dim X As Long, Y As Long, OffsetX As Long, OffsetY As Long
Dim WinMaskColor As Long, MemAutoRedraw As Boolean
WinMaskColor = WinColor(MaskColor)
With PictureBox
MemAutoRedraw = .AutoRedraw
.AutoRedraw = True
Select Case .ScaleMode
Case vbTwips
Width = .Width / Screen.TwipsPerPixelX
Height = .Height / Screen.TwipsPerPixelY
ScaleWidth = .ScaleWidth / Screen.TwipsPerPixelX
ScaleHeight = .ScaleHeight / Screen.TwipsPerPixelY
Case vbPixels
Width = .Width
Height = .Height
ScaleWidth = .ScaleWidth
ScaleHeight = .ScaleHeight
Case Else
Err.Raise Number:=1, Description:="ScaleMode property of picture box not set to twips or pixels"
End Select
OffsetX = (Width - ScaleWidth) / 2
OffsetY = (Height - ScaleHeight) / 2
For X = 0 To ScaleWidth - 1
For Y = 0 To ScaleHeight - 1
If GetPixel(.hDC, X, Y) <> WinMaskColor Then
If Skin <> 0 Then
TempSkin = CreateRectRgn(X + OffsetX, Y + OffsetY, X + OffsetX + 1, Y + OffsetY + 1)
CombineRgn Skin, Skin, TempSkin, RGN_OR
DeleteObject TempSkin
Else
Skin = CreateRectRgn(X + OffsetX, Y + OffsetY, X + OffsetX + 1, Y + OffsetY + 1)
End If
End If
Next Y
Next X
If .BorderStyle <> 0 Then
For X = 0 To Width - 1
For Y = 0 To Height - 1
If X < OffsetX Or Y < OffsetY Or X + OffsetX > Width - 1 Or Y + OffsetY > Height - 1 Then
If Skin <> 0 Then
TempSkin = CreateRectRgn(X, Y, X + 1, Y + 1)
CombineRgn Skin, Skin, TempSkin, RGN_OR
DeleteObject TempSkin
Else
Skin = CreateRectRgn(X, Y, X + 1, Y + 1)
End If
End If
Next Y
Next X
End If
.AutoRedraw = MemAutoRedraw
If GetWindowRgn(.hWnd, CreateRectRgn(0, 0, 0, 0)) <> 0 Then
TempSkin = CreateRectRgn(0, 0, 0, 0)
GetWindowRgn .hWnd, TempSkin
CombineRgn Skin, Skin, TempSkin, RGN_XOR
TempSkin = CreateRectRgn(0, 0, Width, Height)
CombineRgn Skin, Skin, TempSkin, RGN_XOR
DeleteObject TempSkin
End If
SetWindowRgn .hWnd, Skin, True
DeleteObject Skin
End With
End Sub
Public Sub PictureBoxClearMasking(ByVal PictureBox As VB.PictureBox)
Dim Skin As Long
Dim Width As Long, Height As Long
With PictureBox
Select Case .ScaleMode
Case vbTwips
Width = .Width / Screen.TwipsPerPixelX
Height = .Height / Screen.TwipsPerPixelY
Case vbPixels
Width = .Width
Height = .Height
Case Else
Err.Raise Number:=1, Description:="ScaleMode property of picture box not set to twips or pixels"
End Select
Skin = CreateRectRgn(0, 0, Width, Height)
SetWindowRgn .hWnd, Skin, True
DeleteObject Skin
End With
End Sub
Public Function WinColor(ByVal Color As Long) As Long
Dim SysColor As OLECOLOR
CopyMemory SysColor, Color, Len(SysColor)
If SysColor.Type = &H80 Then
WinColor = GetSysColor(SysColor.RedOrSys)
Else
WinColor = Color
End If
End Function
The function PictureBoxClearMasking is needed after you change the borderstyle at runtime, but then you need to re-mask everything: