Last week Bob Powell [MVP] suggested that I use a NativeWindow class to
solve this problem. I've just had the time to get back to this and not
being
a former C++ person, etc., etc., etc. maybe someone can help with this.
Far be it from me to leave a hint like that hanging in the air ;-)
See after my signature. (lots of lovely interop)
--
Bob Powell [MVP]
Visual C#, System.Drawing
Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm
Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm
All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
Imports System
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data
Imports System.Runtime.InteropServices
'
' * The example below explains how to use a NativeWindow With the
WS_EX_LAYERED style set to create a window that sits on top of everything.
' * This uses only one window which is mostly transparent. The transparency
is obtained by using some garish color like magenta on the background and
using the SetLayeredWindowAttributes API to create the transparency key.
' *
' * The window draws on top of everything including the desktop but is a
true window so better managed than raw desktop drawing.
' *
'
Namespace LayeredWindowTest
'/ <summary>
'/ Summary description for Form1.
'/ </summary>
Public Class Form1
Inherits System.Windows.Forms.Form
Private WithEvents timer1 As System.Windows.Forms.Timer
Private button1 As System.Windows.Forms.Button
Private textBox1 As System.Windows.Forms.TextBox
Private listBox1 As System.Windows.Forms.ListBox
Private components As System.ComponentModel.IContainer
Public Sub New()
'
' Required for Windows Form Designer suppoTest
'
InitializeComponent()
End Sub 'New
'
' TODO: Add any constructor code after InitializeComponent call
'
'/ <summary>
'/ Clean up any resources being used.
'/ </summary>
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub 'Dispose
#Region "Windows Form Designer generated code"
'/ <summary>
'/ Required method for Designer suppoTest - do not modify
'/ the contents of this method with the code editor.
'/ </summary>
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container
Me.timer1 = New System.Windows.Forms.Timer(Me.components)
Me.button1 = New System.Windows.Forms.Button
Me.textBox1 = New System.Windows.Forms.TextBox
Me.listBox1 = New System.Windows.Forms.ListBox
Me.SuspendLayout()
'
' timer1
'
Me.timer1.Enabled = True
Me.timer1.Interval = 50
'
' button1
'
Me.button1.Location = New System.Drawing.Point(56, 48)
Me.button1.Name = "button1"
Me.button1.TabIndex = 0
Me.button1.Text = "button1"
'
' textBox1
'
Me.textBox1.Location = New System.Drawing.Point(168, 144)
Me.textBox1.Name = "textBox1"
Me.textBox1.TabIndex = 1
Me.textBox1.Text = "textBox1"
'
' listBox1
'
Me.listBox1.Location = New System.Drawing.Point(24, 88)
Me.listBox1.Name = "listBox1"
Me.listBox1.Size = New System.Drawing.Size(120, 95)
Me.listBox1.TabIndex = 2
'
' Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Controls.Add(listBox1)
Me.Controls.Add(textBox1)
Me.Controls.Add(button1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub 'InitializeComponent
#End Region
'/ <summary>
'/ The main entry point for the application.
'/ </summary>
<STAThread()> _
Shared Sub Main()
Application.Run(New Form1)
End Sub 'Main
Private x As Integer = 30
Private y As Integer = 30
Private dir As Integer = 1
Private Sub timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs)
Handles timer1.Tick
x += dir
y += dir
If x > Me.Width - 30 OrElse x < 30 Then
dir = -dir
End If
lwt.Location = New Point(10, 10)
lwt.Size = New Size(x, y)
End Sub 'timer1_Tick
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Handles MyBase.Load
lwt.Create(Me)
lwt.Show()
End Sub 'Form1_Load
Private lwt As New LayeredWindowTest
End Class 'Form1
Class LayeredWindowTest
Inherits NativeWindow
<DllImport("User32.dll")> _
Public Shared Function MoveWindow(ByVal hWnd As IntPtr, ByVal X As Integer,
ByVal Y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal
bRepaint As Integer) As Integer
End Function
<DllImport("User32.dll")> _
Public Shared Function ShowWindow(ByVal hWnd As System.IntPtr, ByVal cmdShow
As Short) As Integer
End Function
<DllImport("User32.dll")> _
Public Shared Function BeginPaint(ByVal p As IntPtr, ByRef ps As
PAINTSTRUCT) As IntPtr
End Function
<DllImport("User32.dll")> _
Public Shared Function EndPaint(ByVal p As IntPtr, ByRef ps As PAINTSTRUCT)
As Integer
End Function
<DllImport("User32.dll")> _
Public Shared Function SetLayeredWindowAttributes(ByVal hWnd As IntPtr,
ByVal clrKey As COLORREF, ByVal bAlpha As Byte, ByVal dwFlags As Integer) As
Integer
End Function
Private _internalLocation As POINT
Private _location As POINT
Public Property Location() As POINT
Get
Return _location
End Get
Set(ByVal Value As POINT)
_location = Value
Dim tp As New Point(Value.X, Value.Y)
tp = _parent.PointToScreen(tp)
_internalLocation.X = tp.X
_internalLocation.Y = tp.Y
If Not Me.Handle.Equals(IntPtr.Zero) Then
MoveWindow(Me.Handle, _internalLocation.X, _internalLocation.Y, _size.Width,
_size.Height, 1)
End If
End Set
End Property
Private _size As Size
Public Property Size() As Size
Get
Return _size
End Get
Set(ByVal Value As Size)
_size = Value
If Not Me.Handle.Equals(IntPtr.Zero) Then
MoveWindow(Me.Handle, _internalLocation.X, _internalLocation.Y, _size.Width,
_size.Height, 1)
End If
End Set
End Property
Private _parent As Control
Public Sub Create(ByVal parent As Control)
Me._parent = parent
Dim cp As New CreateParams
cp.Style = CInt(WSDefs.WS_POPUP)
cp.ClassStyle = CInt(CSDefs.CS_OWNDC)
cp.ExStyle = cp.ExStyle Or (CInt(WSDefs.WS_EX_LAYERED) Or
CInt(WSDefs.WS_EX_TOPMOST))
cp.ClassName = Nothing
cp.Caption = Nothing
cp.X = -2
cp.Y = -2
cp.Width = 1
cp.Height = 1
cp.Parent = parent.Handle
CreateHandle(cp)
End Sub 'Create
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
Case CInt(WMDefs.WM_PAINT)
Dim g As Graphics
Dim ps As New PAINTSTRUCT
g = Graphics.FromHdc(BeginPaint(m.HWnd, ps))
g.SmoothingMode = SmoothingMode.None
g.Clear(Color.Magenta)
Dim clipRect As Rectangle = Me._parent.ClientRectangle
clipRect.Offset(-Me.Location.X, -Me.Location.Y)
Dim p As New Pen(Color.Red, 3)
g.SmoothingMode = SmoothingMode.AntiAlias
g.DrawEllipse(p, 2, 2, Me.Size.Width - 4, Me.Size.Height - 4)
p.Dispose()
g.Dispose()
EndPaint(m.HWnd, ps)
m.Result = New IntPtr(0)
Case Else
MyBase.WndProc(m)
End Select
End Sub 'WndProc
Public Sub Show()
If Not Me.Handle.Equals(IntPtr.Zero) Then
ShowWindow(Me.Handle, CShort(SWDefs.SW_SHOWNOACTIVATE))
Dim cr As New COLORREF
cr.Color = Color.Magenta
SetLayeredWindowAttributes(Me.Handle, cr, 0, CInt(LWADefs.LWA_COLORKEY))
End If
End Sub 'Show
End Class 'LayeredWindowTest
Public Enum WMDefs
WM_NULL = &H0
WM_CREATE = &H1
WM_DESTROY = &H2
WM_MOVE = &H3
WM_SIZE = &H5
WM_ACTIVATE = &H6
WA_INACTIVE = 0
WA_ACTIVE = 1
WA_CLICKACTIVE = 2
WM_SETFOCUS = &H7
WM_KILLFOCUS = &H8
WM_ENABLE = &HA
WM_SETREDRAW = &HB
WM_SETTEXT = &HC
WM_GETTEXT = &HD
WM_GETTEXTLENGTH = &HE
WM_PAINT = &HF
WM_CLOSE = &H10
WM_QUERYENDSESSION = &H11
WM_QUERYOPEN = &H13
WM_ENDSESSION = &H16
WM_QUIT = &H12
WM_ERASEBKGND = &H14
WM_SYSCOLORCHANGE = &H15
WM_SHOWWINDOW = &H18
WM_WININICHANGE = &H1A
WM_SETTINGCHANGE = WM_WININICHANGE
WM_DEVMODECHANGE = &H1B
WM_ACTIVATEAPP = &H1C
WM_FONTCHANGE = &H1D
WM_TIMECHANGE = &H1E
WM_CANCELMODE = &H1F
WM_SETCURSOR = &H20
WM_MOUSEACTIVATE = &H21
WM_CHILDACTIVATE = &H22
WM_QUEUESYNC = &H23
WM_GETMINMAXINFO = &H24
WM_PAINTICON = &H26
WM_ICONERASEBKGND = &H27
WM_NEXTDLGCTL = &H28
WM_SPOOLERSTATUS = &H2A
WM_DRAWITEM = &H2B
WM_MEASUREITEM = &H2C
WM_DELETEITEM = &H2D
WM_VKEYTOITEM = &H2E
WM_CHARTOITEM = &H2F
WM_SETFONT = &H30
WM_GETFONT = &H31
WM_SETHOTKEY = &H32
WM_GETHOTKEY = &H33
WM_QUERYDRAGICON = &H37
WM_COMPAREITEM = &H39
WM_GETOBJECT = &H3D
WM_COMPACTING = &H41
WM_COMMNOTIFY = &H44
WM_WINDOWPOSCHANGING = &H46
WM_WINDOWPOSCHANGED = &H47
WM_POWER = &H48
PWR_OK = 1
PWR_FAIL = &HFFFF
PWR_SUSPENDREQUEST = 1
PWR_SUSPENDRESUME = 2
PWR_CRITICALRESUME = 3
WM_COPYDATA = &H4A
WM_CANCELJOURNAL = &H4B
WM_NOTIFY = &H4E
WM_INPUTLANGCHANGEREQUEST = &H50
WM_INPUTLANGCHANGE = &H51
WM_TCARD = &H52
WM_HELP = &H53
WM_USERCHANGED = &H54
WM_NOTIFYFORMAT = &H55
NFR_ANSI = 1
NFR_UNICODE = 2
NF_QUERY = 3
NF_REQUERY = 4
WM_CONTEXTMENU = &H7B
WM_STYLECHANGING = &H7C
WM_STYLECHANGED = &H7D
WM_DISPLAYCHANGE = &H7E
WM_GETICON = &H7F
WM_SETICON = &H80
WM_NCCREATE = &H81
WM_NCDESTROY = &H82
WM_NCCALCSIZE = &H83
WM_NCHITTEST = &H84
WM_NCPAINT = &H85
WM_NCACTIVATE = &H86
WM_GETDLGCODE = &H87
WM_SYNCPAINT = &H88
WM_NCMOUSEMOVE = &HA0
WM_NCLBUTTONDOWN = &HA1
WM_NCLBUTTONUP = &HA2
WM_NCLBUTTONDBLCLK = &HA3
WM_NCRBUTTONDOWN = &HA4
WM_NCRBUTTONUP = &HA5
WM_NCRBUTTONDBLCLK = &HA6
WM_NCMBUTTONDOWN = &HA7
WM_NCMBUTTONUP = &HA8
WM_NCMBUTTONDBLCLK = &HA9
WM_NCXBUTTONDOWN = &HAB
WM_NCXBUTTONUP = &HAC
WM_NCXBUTTONDBLCLK = &HAD
WM_INPUT = &HFF
WM_KEYFIRST = &H100
WM_KEYDOWN = &H100
WM_KEYUP = &H101
WM_CHAR = &H102
WM_DEADCHAR = &H103
WM_SYSKEYDOWN = &H104
WM_SYSKEYUP = &H105
WM_SYSCHAR = &H106
WM_SYSDEADCHAR = &H107
WM_UNICHAR = &H109
WM_KEYLAST = &H108
UNICODE_NOCHAR = &HFFFF
WM_IME_STARTCOMPOSITION = &H10D
WM_IME_ENDCOMPOSITION = &H10E
WM_IME_COMPOSITION = &H10F
WM_IME_KEYLAST = &H10F
WM_INITDIALOG = &H110
WM_COMMAND = &H111
WM_SYSCOMMAND = &H112
WM_TIMER = &H113
WM_HSCROLL = &H114
WM_VSCROLL = &H115
WM_INITMENU = &H116
WM_INITMENUPOPUP = &H117
WM_MENUSELECT = &H11F
WM_MENUCHAR = &H120
WM_ENTERIDLE = &H121
WM_MENURBUTTONUP = &H122
WM_MENUDRAG = &H123
WM_MENUGETOBJECT = &H124
WM_UNINITMENUPOPUP = &H125
WM_MENUCOMMAND = &H126
WM_CHANGEUISTATE = &H127
WM_UPDATEUISTATE = &H128
WM_QUERYUISTATE = &H129
UIS_SET = 1
UIS_CLEAR = 2
UIS_INITIALIZE = 3
UISF_HIDEFOCUS = &H1
UISF_HIDEACCEL = &H2
UISF_ACTIVE = &H4
WM_CTLCOLOR = &H19
WM_CTLCOLORMSGBOX = &H132
WM_CTLCOLOREDIT = &H133
WM_CTLCOLORLISTBOX = &H134
WM_CTLCOLORBTN = &H135
WM_CTLCOLORDLG = &H136
WM_CTLCOLORSCROLLBAR = &H137
WM_CTLCOLORSTATIC = &H138
MN_GETHMENU = &H1E1
WM_MOUSEFIRST = &H200
WM_MOUSEMOVE = &H200
WM_LBUTTONDOWN = &H201
WM_LBUTTONUP = &H202
WM_LBUTTONDBLCLK = &H203
WM_RBUTTONDOWN = &H204
WM_RBUTTONUP = &H205
WM_RBUTTONDBLCLK = &H206
WM_MBUTTONDOWN = &H207
WM_MBUTTONUP = &H208
WM_MBUTTONDBLCLK = &H209
WM_MOUSEWHEEL = &H20A
WM_XBUTTONDOWN = &H20B
WM_XBUTTONUP = &H20C
WM_XBUTTONDBLCLK = &H20D
WM_MOUSELAST = &H20D
WHEEL_DELTA = 120
XBUTTON1 = &H1
XBUTTON2 = &H2
WM_PARENTNOTIFY = &H210
WM_ENTERMENULOOP = &H211
WM_EXITMENULOOP = &H212
WM_NEXTMENU = &H213
WM_SIZING = &H214
WM_CAPTURECHANGED = &H215
WM_MOVING = &H216
WM_POWERBROADCAST = &H218
PBT_APMQUERYSUSPEND = &H0
PBT_APMQUERYSTANDBY = &H1
PBT_APMQUERYSUSPENDFAILED = &H2
PBT_APMQUERYSTANDBYFAILED = &H3
PBT_APMSUSPEND = &H4
PBT_APMSTANDBY = &H5
PBT_APMRESUMECRITICAL = &H6
PBT_APMRESUMESUSPEND = &H7
PBT_APMRESUMESTANDBY = &H8
PBTF_APMRESUMEFROMFAILURE = &H1
PBT_APMBATTERYLOW = &H9
PBT_APMPOWERSTATUSCHANGE = &HA
PBT_APMOEMEVENT = &HB
PBT_APMRESUMEAUTOMATIC = &H12
WM_DEVICECHANGE = &H219
WM_MDICREATE = &H220
WM_MDIDESTROY = &H221
WM_MDIACTIVATE = &H222
WM_MDIRESTORE = &H223
WM_MDINEXT = &H224
WM_MDIMAXIMIZE = &H225
WM_MDITILE = &H226
WM_MDICASCADE = &H227
WM_MDIICONARRANGE = &H228
WM_MDIGETACTIVE = &H229
WM_MDISETMENU = &H230
WM_ENTERSIZEMOVE = &H231
WM_EXITSIZEMOVE = &H232
WM_DROPFILES = &H233
WM_MDIREFRESHMENU = &H234
WM_IME_SETCONTEXT = &H281
WM_IME_NOTIFY = &H282
WM_IME_CONTROL = &H283
WM_IME_COMPOSITIONFULL = &H284
WM_IME_SELECT = &H285
WM_IME_CHAR = &H286
WM_IME_REQUEST = &H288
WM_IME_KEYDOWN = &H290
WM_IME_KEYUP = &H291
WM_MOUSEHOVER = &H2A1
WM_MOUSELEAVE = &H2A3
WM_NCMOUSELEAVE = &H2A2
WM_WTSSESSION_CHANGE = &H2B1
WM_TABLET_FIRST = &H2C0
WM_TABLET_LAST = &H2DF
WM_CUT = &H300
WM_COPY = &H301
WM_PASTE = &H302
WM_CLEAR = &H303
WM_UNDO = &H304
WM_RENDERFORMAT = &H305
WM_RENDERALLFORMATS = &H306
WM_DESTROYCLIPBOARD = &H307
WM_DRAWCLIPBOARD = &H308
WM_PAINTCLIPBOARD = &H309
WM_VSCROLLCLIPBOARD = &H30A
WM_SIZECLIPBOARD = &H30B
WM_ASKCBFORMATNAME = &H30C
WM_CHANGECBCHAIN = &H30D
WM_HSCROLLCLIPBOARD = &H30E
WM_QUERYNEWPALETTE = &H30F
WM_PALETTEISCHANGING = &H310
WM_PALETTECHANGED = &H311
WM_HOTKEY = &H312
WM_PRINT = &H317
WM_PRINTCLIENT = &H318
WM_APPCOMMAND = &H319
WM_THEMECHANGED = &H31A
WM_HANDHELDFIRST = &H358
WM_HANDHELDLAST = &H35F
WM_AFXFIRST = &H360
WM_AFXLAST = &H37F
WM_PENWINFIRST = &H380
WM_PENWINLAST = &H38F
WM_USER = &H400
WM_REFLECT = &H2000
WM_APP = &H8000
End Enum 'WMDefs
Public Enum CSDefs
CS_VREDRAW = &H1
CS_HREDRAW = &H2
CS_DBLCLKS = &H8
CS_OWNDC = &H20
CS_CLASSDC = &H40
CS_PARENTDC = &H80
CS_NOCLOSE = &H200
CS_SAVEBITS = &H800
CS_BYTEALIGNCLIENT = &H1000
CS_BYTEALIGNWINDOW = &H2000
CS_GLOBALCLASS = &H4000
CS_IME = &H10000
CS_DROPSHADOW = &H20000
End Enum 'CSDefs
Public Enum LWADefs
LWA_COLORKEY = &H1
LWA_ALPHA = &H2
End Enum 'LWADefs
<Flags()> _
Public Enum SWDefs
SW_HIDE = 0
SW_SHOWNORMAL = 1
SW_NORMAL = 1
SW_SHOWMINIMIZED = 2
SW_SHOWMAXIMIZED = 3
SW_MAXIMIZE = 3
SW_SHOWNOACTIVATE = 4
SW_SHOW = 5
SW_MINIMIZE = 6
SW_SHOWMINNOACTIVE = 7
SW_SHOWNA = 8
SW_RESTORE = 9
SW_SHOWDEFAULT = 10
SW_FORCEMINIMIZE = 11
SW_MAX = 11
End Enum 'SWDefs
Public Enum WSDefs
WS_OVERLAPPED = &H0
WS_POPUP = &H80000000
WS_CHILD = &H40000000
WS_MINIMIZE = &H20000000
WS_VISIBLE = &H10000000
WS_DISABLED = &H8000000
WS_CLIPSIBLINGS = &H4000000
WS_CLIPCHILDREN = &H2000000
WS_MAXIMIZE = &H1000000
WS_CAPTION = &HC00000 ' WS_BORDER or WS_DLGFRAME
WS_BORDER = &H800000
WS_DLGFRAME = &H400000
WS_VSCROLL = &H200000
WS_HSCROLL = &H100000
WS_SYSMENU = &H80000
WS_THICKFRAME = &H40000
WS_GROUP = &H20000
WS_TABSTOP = &H10000
WS_MINIMIZEBOX = &H20000
WS_MAXIMIZEBOX = &H10000
WS_TILED = WS_OVERLAPPED
WS_ICONIC = WS_MINIMIZE
WS_SIZEBOX = WS_THICKFRAME
WS_TILEDWINDOW = WS_OVERLAPPEDWINDOW
'
' * Common Window Styles
'
WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED Or _
WS_CAPTION Or _
WS_SYSMENU Or _
WS_THICKFRAME Or _
WS_MINIMIZEBOX Or _
WS_MAXIMIZEBOX)
WS_POPUPWINDOW = (WS_POPUP Or _
WS_BORDER Or _
WS_SYSMENU)
WS_CHILDWINDOW = WS_CHILD
'
' * Extended Window Styles
'
WS_EX_DLGMODALFRAME = &H1
WS_EX_NOPARENTNOTIFY = &H4
WS_EX_TOPMOST = &H8
WS_EX_ACCEPTFILES = &H10
WS_EX_TRANSPARENT = &H20
WS_EX_MDICHILD = &H40
WS_EX_TOOLWINDOW = &H80
WS_EX_WINDOWEDGE = &H100
WS_EX_CLIENTEDGE = &H200
WS_EX_CONTEXTHELP = &H400
WS_EX_RIGHT = &H1000
WS_EX_LEFT = &H0
WS_EX_RTLREADING = &H2000
WS_EX_LTRREADING = &H0
WS_EX_LEFTSCROLLBAR = &H4000
WS_EX_RIGHTSCROLLBAR = &H0
WS_EX_CONTROLPARENT = &H10000
WS_EX_STATICEDGE = &H20000
WS_EX_APPWINDOW = &H40000
WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_CLIENTEDGE)
WS_EX_PALETTEWINDOW = (WS_EX_WINDOWEDGE Or WS_EX_TOOLWINDOW Or
WS_EX_TOPMOST)
WS_EX_LAYERED = &H80000
WS_EX_NOINHERITLAYOUT = &H100000 ' Disable inheritence of mirroring by
children
WS_EX_LAYOUTRTL = &H400000 ' Right to left mirroring
WS_EX_COMPOSITED = &H2000000
WS_EX_NOACTIVATE = &H8000000
End Enum 'WSDefs
Public Structure COLORREF
Public _color As Integer
Public Property Color() As Color
Get
Return ColorTranslator.FromWin32(_color)
End Get
Set(ByVal Value As Color)
_color = ColorTranslator.ToWin32(Value)
End Set
End Property
End Structure 'COLORREF
Public Structure PAINTSTRUCT
Public hdc As IntPtr
Public fErase As Integer
Public rcPaint As RECT
Public fRestore As Integer
Public fIncUpdate As Integer
Public rgbReserved1 As Long
Public rgbReserved2 As Long
Public rgbReserved3 As Long
Public rgbReserved4 As Long
End Structure 'PAINTSTRUCT
<StructLayout(LayoutKind.Sequential)> _
Public Structure RECT
Public left As Integer
Public top As Integer
Public right As Integer
Public bottom As Integer
Public ReadOnly Property Width() As Integer
Get
Return right - left
End Get
End Property
Public ReadOnly Property Height() As Integer
Get
Return bottom - top
End Get
End Property
End Structure 'RECT
End Namespace 'LayeredWindowTest