Results 1 to 23 of 23

Thread: Drawing on the screen with an overlay Window

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Arrow Drawing on the screen with an overlay Window

    Hello all.

    I have a bit of an issue here. I made a "Colour picker" dialog in my program with which you can pick the colour at the mouse.
    It is a simple topmost form with an OnPaint handler used to draw a coloured border around the cursor:

    It uses a transparency key to make the non-drawn parts of the form transparent.

    It uses the following code to prevent the mouse from clicking through the screen:
    Code:
            Window.FromControl(Me).ExStyle(Window.ExStyles.Layered) = True
            Window.FromControl(Me).ExStyle(Window.ExStyles.Transparent) = False
    It sets Layered to True and Transparent to False. This works in Windows 7, but on a XP machine it fails.
    When moving the mouse the event does not go to the forms' event handler and you can just click through.
    For a screen region selector I simply made a screenshot, but I want the Colour Picker to remain updated.
    (just in case you want to get the colour of an animated control)

    How can I get this to work on a Windows XP machine?

  2. #2

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    Anyone?

  3. #3
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Drawing on the screen with an overlay Window

    You could layer another borderless form on top of or underneath the selector. Set its transparency to a low value, e.g 1%. It will be invisible, but will still catch click events instead of passing them through to the form underneath. Use the Owner/Owned relation to keep them together in the Z-order.

    Incidentally, you may like to consider making the whole selector an Owned Form instead of Topmost; that will avoid the irritation of the selector staying on top when another application is activated.

    BB

  4. #4

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    The issue is that this 1% transparency window will change the colors on the screen. For example, a white 1% opacity form would add 1% of 255 (3 or so) pixel value to all colors on the screen. The color selector must be 100% precise; so the "Top borderless form" must be 100% transparent yet clickable.

    If it was that easy I would have done that already, but unfortunately it is not possible in my case.

    EDIT

    BTW the greyish middle cross is a cross cursor I added in paint, it is not visible on the actual screenshot.
    I use a DC wrapper to get the pixel values:
    1. Get hDC of desktop
    2. Use GetPixel API to get the color from the Hdc
    3. Release the Hdc
    I could monitor the cursor position and keydown state in a timer, but the messages would be redirected to the underlying screen.
    For example, if you want to capture the color on a button it would click the button when "activating". (clicking the mouse)

  5. #5
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Drawing on the screen with an overlay Window

    Quote Originally Posted by bergerkiller View Post
    The issue is that this 1% transparency window will change the colors on the screen. For example, a white 1% opacity form would add 1% of 255 (3 or so) pixel value to all colors on the screen. The color selector must be 100% precise; so the "Top borderless form" must be 100% transparent yet clickable.

    If it was that easy I would have done that already, but unfortunately it is not possible in my case.

    EDIT

    BTW the greyish middle cross is a cross cursor I added in paint, it is not visible on the actual screenshot.
    I use a DC wrapper to get the pixel values:

    I could monitor the cursor position and keydown state in a timer, but the messages would be redirected to the underlying screen.
    For example, if you want to capture the color on a button it would click the button when "activating". (clicking the mouse)
    I take it that means you are using ROP = SrcCopy|CaptureBLT to get the colour (if you used SrcCopy only or Graphics.CopyFromScreen the transparent layer would be "invisible"). Never mind, if you are capturing from a mouse click, you can switch the "invisible" form's opacity to 0% immediately before the capture and back to a minimum opacity afterwards. Then you will capture the pure colour, but the click still won't be passed through to the button underneath. The actual minimum to intercept mouse events is 1/255.

    BB

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    That would cause flickering + lag, since the color is updated in a timer each 1/5 of a second. It would have to set/reset the transparency each time.

    There is no way to make a 100% transparent form top most and selectable?

    Here is the full code I use right now:
    vb Code:
    1. Imports System.Windows.Forms
    2.  
    3. Public Class ScreenColorPicker
    4.     Private _c As Color = Color.FromArgb(255, 255, 255, 255)
    5.     Private _p As New Point(0, 0)
    6.     Private _dc As API.DC
    7.  
    8.     Public ReadOnly Property SelectedColor() As Color
    9.         Get
    10.             Return _c
    11.         End Get
    12.     End Property
    13.     Private Sub ScreenColorPicker_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    14.         Window.FromControl(Me).ExStyle(Window.ExStyles.Layered) = True
    15.         Window.FromControl(Me).ExStyle(Window.ExStyles.Transparent) = False
    16.         Me._dc = Window.GetDesktop().GetDC()
    17.         Timer1.Start()
    18.     End Sub
    19.     Private Sub ScreenColorPicker_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
    20.         Window.FromControl(Me).ExStyle = 0
    21.         _dc.Dispose()
    22.         Timer1.Stop()
    23.     End Sub
    24.     Private Sub ScreenColorPicker_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
    25.         Dim p As New Pen(_c)
    26.         p.Width = 20
    27.         e.Graphics.DrawRectangle(p, _p.X - (50 - p.Width / 2), _p.Y - (50 - p.Width / 2), 100 - p.Width, 100 - p.Width)
    28.         e.Graphics.DrawRectangle(Pens.Black, _p.X - 50 + p.Width, _p.Y - 50 + p.Width, 100 - p.Width * 2, 100 - p.Width * 2)
    29.         e.Graphics.DrawRectangle(Pens.Black, _p.X - 50, _p.Y - 50, 100, 100)
    30.     End Sub
    31.  
    32.     Private Sub ScreenColorPicker_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
    33.         INVA()
    34.         _p = e.Location
    35.         INVB()
    36.     End Sub
    37.  
    38.     Private r As Region
    39.     Private Sub INVA()
    40.         Dim rect As New Rectangle(_p.X - 50, _p.Y - 50, 100, 100)
    41.         rect.Inflate(1, 1)
    42.         r = New Region(rect)
    43.     End Sub
    44.     Private Sub INVB()
    45.         Dim rect As New Rectangle(_p.X - 50, _p.Y - 50, 100, 100)
    46.         rect.Inflate(1, 1)
    47.         r.Union(rect)
    48.         Me.Invalidate(r)
    49.     End Sub
    50.     Private Sub ScreenColorPicker_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
    51.         If e.Button = Windows.Forms.MouseButtons.Left Then
    52.             _c = _dc.GetPixel(e.X, e.Y)
    53.             Me.DialogResult = Windows.Forms.DialogResult.OK
    54.         Else
    55.             Me.DialogResult = Windows.Forms.DialogResult.Cancel
    56.         End If
    57.         Me.Close()
    58.     End Sub
    59.     Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
    60.         Dim nc As Color = _c.GetPixel(Cursor.Position)
    61.         If nc <> _c Then
    62.             _c = nc
    63.             INVA()
    64.             INVB()
    65.         End If
    66.     End Sub
    67. End Class

    DC:
    vb Code:
    1. Public Class DC
    2.         Implements System.IDisposable
    3.  
    4.         Private Declare Function BitBlt Lib "gdi32" (ByVal hdc As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As CopyPixelOperation) As Boolean
    5.         Private Declare Function GetPixel Lib "gdi32" Alias "GetPixel" (ByVal hdc As IntPtr, ByVal X As Int32, ByVal Y As Int32) As Int32
    6.         Private Declare Function SetPixel Lib "gdi32" Alias "SetPixel" (ByVal hdc As IntPtr, ByVal X As Int32, ByVal Y As Int32, ByVal crColor As UInt32) As UInt32
    7.         Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Boolean
    8.         Private Declare Function GetClipBox Lib "gdi32" (ByVal hdc As IntPtr, ByRef lprc As WRECT) As Integer
    9.         Private Declare Function GetClipRgn Lib "gdi32" (ByVal hdc As IntPtr, ByRef hrgn As Region) As Integer
    10.         Private Declare Function GetRandomRgn Lib "gdi32" (ByVal hdc As IntPtr, ByRef hrgn As Region, ByVal inum As Integer) As Integer
    11.  
    12.         Private managedtype As DCSource
    13.         Private managedobject As Object
    14.         Private managedgraphics As Graphics
    15.         Private hdc As IntPtr
    16.         Private _disposed As Boolean
    17.         Public Enum DCSource
    18.             None
    19.             Handle
    20.             Graphics
    21.         End Enum
    22.         Sub New(ByVal g As Graphics)
    23.             Me.managedobject = g
    24.             Me.managedtype = DCSource.Graphics
    25.             Me.hdc = g.GetHdc
    26.         End Sub
    27.         Sub New(ByVal hwnd As IntPtr, ByVal hdc As IntPtr)
    28.             Me.managedobject = hwnd
    29.             Me.managedtype = DCSource.Handle
    30.             Me.hdc = hdc
    31.         End Sub
    32.         Sub New()
    33.             Me.managedobject = Nothing
    34.             Me.managedtype = DCSource.None
    35.         End Sub
    36.         Public ReadOnly Property Source() As DCSource
    37.             Get
    38.                 Return Me.managedtype
    39.             End Get
    40.         End Property
    41.         Public Sub SetPixel(ByVal X As Integer, ByVal Y As Integer, ByVal C As Color)
    42.             SetPixel(Me.hdc, X, Y, C.ToArgb)
    43.         End Sub
    44.         Public Function GetPixel(ByVal X As Integer, ByVal Y As Integer) As Color
    45.             Return ColorTranslator.FromOle(GetPixel(Me.hdc, X, Y))
    46.         End Function
    47.         Public Property Pixel(ByVal X As Integer, ByVal Y As Integer) As Color
    48.             Get
    49.                 Return GetPixel(X, Y)
    50.             End Get
    51.             Set(ByVal value As Color)
    52.                 SetPixel(X, Y, value)
    53.             End Set
    54.         End Property
    55.  
    56.         Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
    57.             If Me._disposed = False Then
    58.                 Select Case managedtype
    59.                     Case DCSource.Handle
    60.                         ReleaseDC(CType(Me.managedobject, IntPtr), Me.hdc)
    61.                     Case DCSource.Graphics
    62.                         CType(Me.managedobject, Graphics).ReleaseHdc(Me.hdc)
    63.                 End Select
    64.                 If managedgraphics IsNot Nothing Then managedgraphics.Dispose()
    65.                 Me.managedgraphics = Nothing
    66.                 Me.managedobject = Nothing
    67.                 Me.managedtype = Nothing
    68.                 Me.hdc = Nothing
    69.                 Me._disposed = True
    70.             End If
    71.         End Sub
    72.         Public Overloads Sub Dispose() Implements IDisposable.Dispose
    73.             Dispose(True)
    74.             GC.SuppressFinalize(Me)
    75.         End Sub
    76.     End Class

  7. #7
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Drawing on the screen with an overlay Window

    Quote Originally Posted by bergerkiller View Post
    That would cause flickering + lag, since the color is updated in a timer each 1/5 of a second. It would have to set/reset the transparency each time.
    I measured opacity switching between 1/255 and 0 for a form measuring 150 x 170 pixels and averaged 1.46 milliseconds per switch. Form Opacity is hardware accelerated (I have read) so I find this a bit disappointing, but it looks like it should be feasible. I see no visible flickering for opacity changes in the subvisible range. Ideally of course this should be checked on a range of different systems.

    This is the test code I used:
    Code:
    Dim sw As Stopwatch = Stopwatch.StartNew
    For i As Integer = 0 To 1000
    	Form2.Opacity = 1/ 255
    	Form2.Opacity = 0
    Next
    MessageBox.Show((sw.ElapsedTicks / Stopwatch.Frequency).ToString("N5") & "milliseconds per switch")
    The test seems to give consistent results. Switching between 0.99 and 0 also took about 1.5 ms but switching between 1 and 0 took about 10 ms.

    BB

    edit: the measured times are for two-way switching.

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    Well with lag I mean redrawing the screen. You can set the opacity to 0, get the pixel and set the opacity back to 1, but I doubt the screen has redrawn (invalidated and updated) the screen before the GetPixel command comes into view. I have seen a program (on screen drawing program) that does not change the color of the screen at all when ran. How did they do it?

  9. #9
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Drawing on the screen with an overlay Window

    Quote Originally Posted by bergerkiller View Post
    Well with lag I mean redrawing the screen. You can set the opacity to 0, get the pixel and set the opacity back to 1, but I doubt the screen has redrawn (invalidated and updated) the screen before the GetPixel command comes into view. I have seen a program (on screen drawing program) that does not change the color of the screen at all when ran. How did they do it?
    I don't see why you can't use the method I suggested with an "invisible" form. Switching between opacity 1 and opacity 0 does indeed take more time as I mentioned in my previous post, and I guess that is because the pixels have to be updated. But switching between anything less than 1 and 0 is far quicker. As I understand it, a partly transparent form behaves like a layered window. It occupies a separate hardware layer in the graphics subsystem and the pixels underneath it do not have to be updated because they are in a different layer.

    I'm sure I could learn a lot by studying your DC class, but if your purpose is to pick a colour from the screen I think I would do it in a much simpler way:

    Code:
    Public Function GetColorAtCursor() As Color
    	Dim bmp As New Bitmap(1, 1)
    	Using g As Graphics = Graphics.FromImage(bmp)
    		g.CopyFromScreen(MousePosition, Point.Empty, bmp.Size)
    	End Using
    	Return bmp.GetPixel(0, 0)
    End Function
    Since only 1 pixel is involved, both CopyFromScreen and GetPixel will be practically instantaneous. The drawback of Graphics.CopyFromScreen is that is doesn't do CaptureBlt so it can't see pixels with Alpha less than 255. If you don't need to capture from non-opaque windows then you can use the above code and you won't even need to switch the opacity of the invisible form. Otherwise, you could try my own version of CopyFromScreen:

    Code:
    Imports System
    Imports System.Runtime.InteropServices
    
    Public Class GrabPixels
    
    	Public Shared Function CopyFromScreen(ByVal upperLeftSource As Point, ByVal upperLeftDestination As Point, ByVal blockRegionSize As Size) As Bitmap
    		Dim hDesk As IntPtr = W32.GetDesktopWindow()
    		Dim hSrce As IntPtr = W32.GetWindowDC(hDesk)
    		Dim hDest As IntPtr = W32.CreateCompatibleDC(hSrce)
    		Dim hBmp As IntPtr = W32.CreateCompatibleBitmap(hSrce, blockRegionSize.Width, blockRegionSize.Height)
    		Dim hOldBmp As IntPtr = W32.SelectObject(hDest, hBmp)
    		W32.BitBlt(hDest, upperLeftDestination.X, upperLeftDestination.Y, blockRegionSize.Width, blockRegionSize.Height, hSrce, _
    					   upperLeftSource.X, upperLeftSource.Y, CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    		Dim bmp As Bitmap = Bitmap.FromHbitmap(hBmp)
    		W32.SelectObject(hDest, hOldBmp)
    		W32.DeleteObject(hBmp)
    		W32.DeleteDC(hDest)
    		W32.ReleaseDC(hDesk, hSrce)
    		Return bmp
    	End Function
    
    End Class
    Win32 is a module with Interop methods but I assume you can use your own. Using this method is even simpler than the Graphics version above:
    Code:
    Public Function GetColorAtCursor2() As Color
    	Dim bmp = New Bitmap(GrabPixels.CopyFromScreen(MousePosition, Point.Empty, New Size(1, 1)))
    	Return bmp.GetPixel(0, 0)
    End Function
    BB

  10. #10

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    CopyFromScreen uses BitBlt in the background, they are the same. CopyFromScreen performs a BitBlt operation between the desktop Hdc and the current Hdc (Graphics). I do not want to store it all in a new Bitmap and use GetPixel on that, since it would be the exact same as GetPixel with the source Hdc. Only difference is that the Hdc is then stored onto a new (temprary) surface.

    Full code of the DC class:
    vb Code:
    1. Public Class DC
    2.         Implements System.IDisposable
    3.  
    4.         Private Declare Function BitBlt Lib "gdi32" (ByVal hdc As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As CopyPixelOperation) As Boolean
    5.         Private Declare Function GetPixel Lib "gdi32" Alias "GetPixel" (ByVal hdc As IntPtr, ByVal X As Int32, ByVal Y As Int32) As Int32
    6.         Private Declare Function SetPixel Lib "gdi32" Alias "SetPixel" (ByVal hdc As IntPtr, ByVal X As Int32, ByVal Y As Int32, ByVal crColor As UInt32) As UInt32
    7.         Private Declare Function ReleaseDC Lib "user32" (ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Boolean
    8.         Private Declare Function GetClipBox Lib "gdi32" (ByVal hdc As IntPtr, ByRef lprc As WRECT) As Integer
    9.         Private Declare Function GetClipRgn Lib "gdi32" (ByVal hdc As IntPtr, ByRef hrgn As Region) As Integer
    10.         Private Declare Function GetRandomRgn Lib "gdi32" (ByVal hdc As IntPtr, ByRef hrgn As Region, ByVal inum As Integer) As Integer
    11.  
    12.         Private managedtype As DCSource
    13.         Private managedobject As Object
    14.         Private managedgraphics As Graphics
    15.         Private hdc As IntPtr
    16.         Private _disposed As Boolean
    17.         Public Enum DCSource
    18.             None
    19.             Handle
    20.             Graphics
    21.         End Enum
    22.         Sub New(ByVal g As Graphics)
    23.             Me.managedobject = g
    24.             Me.managedtype = DCSource.Graphics
    25.             Me.hdc = g.GetHdc
    26.         End Sub
    27.         Sub New(ByVal hwnd As IntPtr, ByVal hdc As IntPtr)
    28.             Me.managedobject = hwnd
    29.             Me.managedtype = DCSource.Handle
    30.             Me.hdc = hdc
    31.         End Sub
    32.         Sub New()
    33.             Me.managedobject = Nothing
    34.             Me.managedtype = DCSource.None
    35.         End Sub
    36.         Public ReadOnly Property Source() As DCSource
    37.             Get
    38.                 Return Me.managedtype
    39.             End Get
    40.         End Property
    41.         Public Sub SetPixel(ByVal X As Integer, ByVal Y As Integer, ByVal C As Color)
    42.             SetPixel(Me.hdc, X, Y, C.ToArgb)
    43.         End Sub
    44.         Public Function GetPixel(ByVal X As Integer, ByVal Y As Integer) As Color
    45.             Return ColorTranslator.FromOle(GetPixel(Me.hdc, X, Y))
    46.         End Function
    47.         Public Property Pixel(ByVal X As Integer, ByVal Y As Integer) As Color
    48.             Get
    49.                 Return GetPixel(X, Y)
    50.             End Get
    51.             Set(ByVal value As Color)
    52.                 SetPixel(X, Y, value)
    53.             End Set
    54.         End Property
    55.  
    56.         Public ReadOnly Property ClipBox() As Rectangle
    57.             Get
    58.                 Dim w As WRECT
    59.                 GetClipBox(Me.hdc, w)
    60.                 Return w.Value
    61.             End Get
    62.         End Property
    63.         Public ReadOnly Property ClipSize() As Size
    64.             Get
    65.                 Return Me.ClipBox.Size
    66.             End Get
    67.         End Property
    68.  
    69.         Public Property Handle() As IntPtr
    70.             Get
    71.                 Return Me.hdc
    72.             End Get
    73.             Set(ByVal value As IntPtr)
    74.                 Me.hdc = value
    75.             End Set
    76.         End Property
    77.  
    78.         Public ReadOnly Property Disposed() As Boolean
    79.             Get
    80.                 Return Me._disposed
    81.             End Get
    82.         End Property
    83.  
    84.         Public Sub Draw(ByVal source As Graphics, ByVal destrect As Rectangle, ByVal sourceoffset As Point, ByVal operation As CopyPixelOperation)
    85.             Dim hdc As IntPtr = source.GetHdc
    86.             Draw(hdc, destrect, sourceoffset, operation)
    87.             source.ReleaseHdc(hdc)
    88.         End Sub
    89.         Public Sub Draw(ByVal source As DC, ByVal destrect As Rectangle, ByVal sourceoffset As Point, ByVal operation As CopyPixelOperation)
    90.             Draw(source.hdc, destrect, sourceoffset, operation)
    91.         End Sub
    92.         Public Sub Draw(ByVal sourcehdc As IntPtr, ByVal destrect As Rectangle, ByVal sourceoffset As Point, ByVal operation As CopyPixelOperation)
    93.             BitBlt(Me.hdc, destrect.X, destrect.Y, destrect.Width, destrect.Height, sourcehdc, sourceoffset.X, sourceoffset.Y, operation)
    94.         End Sub
    95.  
    96.         Public Sub CopyTo(ByVal destination As Graphics, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    97.             CopyTo(destination, Me.ClipBox, operation)
    98.         End Sub
    99.         Public Sub CopyTo(ByVal destination As Graphics, ByVal destrect As Rectangle, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    100.             CopyTo(destination, destrect, New Point(0, 0), operation)
    101.         End Sub
    102.         Public Sub CopyTo(ByVal destination As Graphics, ByVal destrect As Rectangle, ByVal sourceoffset As Point, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    103.             Dim hdc As IntPtr = destination.GetHdc
    104.             CopyTo(hdc, destrect, sourceoffset, operation)
    105.             destination.ReleaseHdc(hdc)
    106.         End Sub
    107.         Public Sub CopyTo(ByVal destination As DC, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    108.             CopyTo(destination.hdc, Me.ClipBox, New Point(0, 0), operation)
    109.         End Sub
    110.         Public Sub CopyTo(ByVal destination As DC, ByVal destrect As Rectangle, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    111.             CopyTo(destination.hdc, destrect, New Point(0, 0), operation)
    112.         End Sub
    113.         Public Sub CopyTo(ByVal destination As DC, ByVal destrect As Rectangle, ByVal sourceoffset As Point, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    114.             CopyTo(destination.hdc, destrect, sourceoffset, operation)
    115.         End Sub
    116.         Public Sub CopyTo(ByVal desthdc As IntPtr, ByVal destrect As Rectangle, ByVal sourceoffset As Point, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt)
    117.             BitBlt(desthdc, destrect.X, destrect.Y, destrect.Width, destrect.Height, Me.hdc, sourceoffset.X, sourceoffset.Y, operation)
    118.         End Sub
    119.  
    120.         Public Function ToBitmap(Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) As Bitmap
    121.             Return ToBitmap(Me.ClipSize, operation)
    122.         End Function
    123.         Public Function ToBitmap(ByVal Resolution As Size, Optional ByVal operation As CopyPixelOperation = CopyPixelOperation.SourceCopy Or CopyPixelOperation.CaptureBlt) As Bitmap
    124.             ToBitmap = New Bitmap(Resolution.Width, Resolution.Height)
    125.             Dim g As Graphics = Graphics.FromImage(ToBitmap)
    126.             Dim ghdc As IntPtr = g.GetHdc
    127.             BitBlt(ghdc, 0, 0, Resolution.Width, Resolution.Height, Me.hdc, 0, 0, operation)
    128.             g.ReleaseHdc(ghdc)
    129.             g.Dispose()
    130.         End Function
    131.  
    132.         Public ReadOnly Property Graphics() As Graphics
    133.             Get
    134.                 If Me.managedgraphics Is Nothing Then Me.managedgraphics = Graphics.FromHdc(Me.hdc)
    135.                 Return Me.managedgraphics
    136.             End Get
    137.         End Property
    138.         Public Shared Function FromHandle(ByVal handle As IntPtr) As DC
    139.             FromHandle = New DC()
    140.             FromHandle.hdc = handle
    141.         End Function
    142.  
    143.         Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
    144.             If Me._disposed = False Then
    145.                 Select Case managedtype
    146.                     Case DCSource.Handle
    147.                         ReleaseDC(CType(Me.managedobject, IntPtr), Me.hdc)
    148.                     Case DCSource.Graphics
    149.                         CType(Me.managedobject, Graphics).ReleaseHdc(Me.hdc)
    150.                 End Select
    151.                 If managedgraphics IsNot Nothing Then managedgraphics.Dispose()
    152.                 Me.managedgraphics = Nothing
    153.                 Me.managedobject = Nothing
    154.                 Me.managedtype = Nothing
    155.                 Me.hdc = Nothing
    156.                 Me._disposed = True
    157.             End If
    158.         End Sub
    159.         Public Overloads Sub Dispose() Implements IDisposable.Dispose
    160.             Dispose(True)
    161.             GC.SuppressFinalize(Me)
    162.         End Sub
    163.     End Class

    The class is simply an extension to handle operations directly on Graphics or Hdc objects, since the Graphics class does not have GetPixel or BitBlt functions.

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    So there is no possible way to make a 100&#37; transparent canvas on top of the screen?

  12. #12
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Drawing on the screen with an overlay Window

    Quote Originally Posted by bergerkiller View Post
    So there is no possible way to make a 100% transparent canvas on top of the screen?
    Not if you want the transparent parts to raise mouse events.

    By the way, there is another easy way to solve the problem with your color selector without using an "invisible" form. Place the selector form off-centre relative to the mouse position so that the click hotspot is over an opaque part. When the user clicks it, pick the color located at the form's actual (transparent) centre.

    BB

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    I tried that before, but when you move the mouse fast enough it will leave the forms' opaque center and the form then just sits there. Just wondering...is it possible to "drag" the form around? Like, when the form starts, you make the form go into "drag mode", since then mouse events go to the main form any ways, as if you are moving a scrollbar. I could send a mouse down event on the opaque part, but I am not sure of how to catch the "after dragging". Plus I think sending a mouse down event is a bit "open for bugs".

    I'll try and see if I can make the form move by dragging it around.

    EDIT

    Aw yes! That works great. Only problem is I have to click and drag the form before it works. Anyone knows how to activate this dragging without sending a mouse down event?
    Code:
    Public Class ScreenColorSelect
        Private _c As Color = Color.White
        Private _dc As API.DC
    
        Private Sub ScreenColorSelect_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
            Dim p As New Pen(_c)
            p.Width = 20
            e.Graphics.DrawRectangle(p, p.Width / 2, p.Width / 2, 100 - p.Width, 100 - p.Width)
            e.Graphics.DrawRectangle(Pens.Black, p.Width, p.Width, 100 - p.Width * 2, 100 - p.Width * 2)
            e.Graphics.DrawRectangle(Pens.Black, 0, 0, 99, 99)
        End Sub
    
        Private Sub ScreenColorSelect_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
            If e.Button = Windows.Forms.MouseButtons.Left Then
                Me.Location = Point.Subtract(Cursor.Position, New Point(50, 50))
            End If
        End Sub
    
        Public ReadOnly Property SelectedColor() As Color
            Get
                Return _c
            End Get
        End Property
    
        Private Sub ScreenColorSelect_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            _dc = Window.GetDesktop.GetDC
            Timer1.Start()
        End Sub
        Private Sub ScreenColorSelect_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
            _dc.Dispose()
            Timer1.Stop()
        End Sub
    
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            _c = _dc.GetPixel(Cursor.Position)
            Me.Invalidate()
        End Sub
    
        Private Sub ScreenColorSelect_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp
            If e.Button = Windows.Forms.MouseButtons.Left Then
                Me.DialogResult = Windows.Forms.DialogResult.OK
                _c = _dc.GetPixel(Cursor.Position)
            Else
                Me.DialogResult = Windows.Forms.DialogResult.Cancel
            End If
            Me.Close()
        End Sub
    End Class

  14. #14
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Drawing on the screen with an overlay Window

    The jerky dragging is caused by updating the selector form's location from its own MouseMove event. Instead, use a timer to set the form's location relative to MousePosition. Of course you can drag instead; just check MouseButtons = MouseButtons.Left. You don't "send" a mouse down event; Windows sends it and you handle it. BB

    EDIT: now I see your own last edit. I'm always so darned slow with these thing I see you have sorted out the dragging using Cursor.Position instead of e.Location; very nice. If you don't want to drag (and have the form behave like a cursor) just don't test for the mouse button. Then the selector will behave like a custom cursor.

    BB

  15. #15

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    No I fixed that lag by setting DoubleBuffered to True; now I got one problem, though. I have to activate this dragging when the form is Shown. Right now you have to "Mouse down" on the opaque part and the form then follows the cursor nicely. The MouseUp handles the closing. The mouse could be up while the form is displayed, if the mouse state does not change it is no issue; you will just have to click (one time down and then up to close it).

    Instead of having to click in the control, I want this dragging to occur as soon you enter the form, as if the mouse clicked it. I used this (sending a mouse event) to do it, but it cause the cursor to change to a waitcursor and nothing happens:
    Code:
        Private Sub ScreenColorSelect_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
            Window.FromControl(Me).SendMouse(New Point(0, 0), Windows.Forms.MouseButtons.Left, Window.MouseEvent.Down)
        End Sub
    Uses:
    Code:
        Public Structure MouseCommand
            Sub New(ByVal X As UShort, ByVal Y As UShort, Optional ByVal Button As MouseButtons = MouseButtons.None, Optional ByVal EventType As MouseEvent = MouseEvent.Move)
                Me.EventType = EventType
                Me.Button = Button
                Me.Modifier = MK.NONE
                Me.x = X
                Me.y = Y
            End Sub
            Sub New(ByVal Location As Point, Optional ByVal Button As MouseButtons = MouseButtons.None, Optional ByVal EventType As MouseEvent = MouseEvent.Move)
                Me.EventType = EventType
                Me.Button = Button
                Me.Modifier = MK.NONE
                Me.x = Location.X
                Me.y = Location.Y
            End Sub
            Public EventType As MouseEvent
            Public Button As MouseButtons
            Public x As UShort
            Public y As UShort
            Public Modifier As MK
            Public Function Post(ByVal hwnd As IntPtr) As Boolean
                Dim msg1 As msg = 0
                Dim msg2 As msg = 0
                Dim add As Boolean = EventType >= 0 And EventType <= 2
                Select Case Button
                    Case MouseButtons.Left
                        msg1 = msg.LBUTTONDOWN
                    Case MouseButtons.Middle
                        msg1 = msg.MBUTTONDOWN
                    Case MouseButtons.Right
                        msg1 = msg.RBUTTONDOWN
                    Case Else
                        add = False
                        msg1 = msg.MOUSEMOVE
                End Select
                If EventType = MouseEvent.DoubleClick Then
                    msg2 = msg1 + MouseEvent.Up
                    msg1 = msg1 + MouseEvent.DoubleClick
                ElseIf EventType = MouseEvent.Click Then
                    msg2 = msg1 + MouseEvent.Up
                    msg1 = msg1 + MouseEvent.Down
                ElseIf add Then
                    msg1 += EventType
                End If
    
                Dim success As Boolean = True
                If msg1 <> 0 AndAlso Not API.PostMessage(hwnd, msg1, Modifier, New API.DWORD(Me.x, Me.y)) Then success = False
                If msg2 <> 0 AndAlso Not API.PostMessage(hwnd, msg2, Modifier, New API.DWORD(Me.x, Me.y)) Then success = False
                Return success
            End Function
            Public Enum MK As Integer
                'No keys are down
                NONE = &H0
                'The CTRL key is down.
                CONTROL = &H8
                'The left mouse button is down.
                LBUTTON = &H1
                'The middle mouse button is down.
                MBUTTON = &H10
                'The right mouse button is down.
                RBUTTON = &H2
                'The SHIFT key is down.
                SHIFT = &H4
                'The first X button is down.
                XBUTTON1 = &H20
                'The second X button is down.
                XBUTTON2 = &H40
            End Enum
    
            Private Enum msg As UInteger
                MOUSEACTIVATE = &H21
                MOUSEMOVE = &H200
                LBUTTONDOWN = 513
                LBUTTONUP = 514
                LBUTTONDBLCLK = 515
                RBUTTONDOWN = 516
                RBUTTONUP = 517
                RBUTTONDBLCLK = 518
                MBUTTONDOWN = 519
                MBUTTONUP = 520
                MBUTTONDBLCLK = 521
            End Enum
        End Structure
        Public Enum MouseEvent
            Down = 0
            Up = 1
            DoubleClick = 2
            Click = 3
            Move = 4
        End Enum
    EDIT

    SendInput did the job (GlobalInput is a class I made around SendInput and others to handle global key/mouse events):
    Code:
        Private Sub ScreenColorSelect_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
            GlobalInput.KeyPressed(Keys.LButton) = False
            Me.Location = Cursor.Position
            GlobalInput.KeyPressed(Keys.LButton) = True
            Me.Location = Point.Subtract(Cursor.Position, New Point(50, 50))
        End Sub
    I guess this is fixed, although I still think sending a mouse command is a bit of a hack. Any way to send some command to the control that does this dragging as well?

    And yes, it is "supposed" to act like a colored cursor.

  16. #16
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Drawing on the screen with an overlay Window

    See the edit to my previous post. It would be so much simpler to position the selector form off-centre relative to the actual mouse position and pick the pixel at its centre. BB

  17. #17

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    I already do that, right? The form has a size of 100x100 and it's position is set to be in the middle of the cursor, like the screenshot of my first post.

    If not, please explain what you mean with "off centre"

  18. #18
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Drawing on the screen with an overlay Window

    Since your selector appears to have a non-transparent border, you could just do Me.Position = Cursor.Position in the MouseMove event handler. Then pick the pixel color at point (50, 50) when the user clicks. Wait, I see the cross in the first image is an actual cursor or custom cursor. So just hide the real cursor with Cursor.Hide and draw the cross yourself.

    BB

    EDIT: when drawing your own cross in the middle of the form, make the middle pixel transparent with the transparency key, of course.

  19. #19

  20. #20

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    Ah you mean making the entire form like that. Well the problem with that is again getting the pixel. If I were to use something like that it would be impossible to get the pixel, since the drawn cross is in front of it. That is why I use the cursor as centre marking. There is no real problem now though, it all works nicely and the cursor controls the position of the form. The form is set to be 50/50 offset to the left/top of the cursor, so the cursor is in the middle of the form. Changing the "custom cursor form" to be not in the middle would make it harder than it has to be.

    Current code:
    Code:
    Public Class ScreenColorSelect
        Private _c As Color = Color.White
        Private _dc As API.DC
    
        Private Sub ScreenColorSelect_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
            Dim p As New Pen(_c)
            p.Width = 20
            e.Graphics.DrawRectangle(p, p.Width / 2, p.Width / 2, 100 - p.Width, 100 - p.Width)
            e.Graphics.DrawRectangle(Pens.Black, p.Width, p.Width, 100 - p.Width * 2, 100 - p.Width * 2)
            e.Graphics.DrawRectangle(Pens.Black, 0, 0, 99, 99)
        End Sub
    
        Private Sub ScreenColorSelect_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
            If e.Button = Windows.Forms.MouseButtons.Left Then
                Me.Location = Point.Subtract(Cursor.Position, New Point(50, 50))
            End If
        End Sub
    
        Public ReadOnly Property SelectedColor() As Color
            Get
                Return _c
            End Get
        End Property
    
        Private Sub ScreenColorSelect_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            _dc = Window.GetDesktop.GetDC
            Timer1.Start()
        End Sub
        Private Sub ScreenColorSelect_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing
            _dc.Dispose()
            Timer1.Stop()
        End Sub
    
        Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
            _c = _dc.GetPixel(Cursor.Position)
            Me.Invalidate()
        End Sub
    
        Private Sub ScreenColorSelect_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseUp
            If e.Button = Windows.Forms.MouseButtons.Left Then
                Me.DialogResult = Windows.Forms.DialogResult.OK
                _c = _dc.GetPixel(Cursor.Position)
            Else
                Me.DialogResult = Windows.Forms.DialogResult.Cancel
            End If
            Me.Close()
        End Sub
        Private Sub ScreenColorSelect_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
            GlobalInput.KeyPressed(Keys.LButton) = False
            Me.Location = Cursor.Position
            GlobalInput.KeyPressed(Keys.LButton) = True
            Me.Location = Point.Subtract(Cursor.Position, New Point(50, 50))
        End Sub
    End Class
    It does not matter if the dragged cursor is outside of the form, the MouseMove event is still passed to the control. Think of the ScrollBar, you can move it when dragging outside of the form with no problems. I only need a replacement for:
    Code:
            GlobalInput.KeyPressed(Keys.LButton) = False
            Me.Location = Cursor.Position
            GlobalInput.KeyPressed(Keys.LButton) = True
            Me.Location = Point.Subtract(Cursor.Position, New Point(50, 50))
    
    '//*under GlobalInput.KeyPressed()*//
    If key = Keys.LButton Then
       If value = True Then inputs(0) = New API.Input(0, 0, API.Input.MouseEvent.LeftDown)
       If value = False Then inputs(0) = New API.Input(0, 0, API.Input.MouseEvent.LeftUp)
    '//*Input structure*//
        <StructLayout(LayoutKind.Explicit)> Public Structure Input
            Sub New(ByVal dx As Integer, ByVal dy As Integer, ByVal flags As MouseEvent, Optional ByVal data As MouseData = 0)
                If (flags And MouseEvent.MoveScreen) = MouseEvent.MoveScreen Then
                    'convert to screen absolute
                    dx = dx / My.Computer.Screen.Bounds.Width * UShort.MaxValue
                    dy = dy / My.Computer.Screen.Bounds.Height * UShort.MaxValue
                    flags -= MouseEvent.MoveScreen
                    If Not (flags And MouseEvent.MoveAbsolute) = MouseEvent.MoveAbsolute Then
                        flags += MouseEvent.MoveAbsolute
                    End If
                End If
                Me.type = dwType.MOUSE
                With Me.mi
                    .dx = dx
                    .dy = dy
                    .time = 0
                    .dwExtraInfo = 0
                    .mouseData = data
                    .dwFlags = flags
                End With
            End Sub
            <FieldOffset(0)> Private type As dwType
            <FieldOffset(4)> Private mi As MOUSEINPUT
            <FieldOffset(4)> Private ki As KEYBDINPUT
            <FieldOffset(4)> Private hi As HARDWAREINPUT
    
            Private Structure MOUSEINPUT
                Public dx As Integer
                Public dy As Integer
                Public mouseData As Integer
                Public dwFlags As MOUSEEVENTF
                Public time As Integer
                Public dwExtraInfo As IntPtr
                Public Enum MOUSEEVENTF As Integer
                    MOVE = &H1
                    LEFTDOWN = &H2
                    LEFTUP = &H4
                    RIGHTDOWN = &H8
                    RIGHTUP = &H10
                    MIDDLEDOWN = &H20
                    MIDDLEUP = &H40
                    XDOWN = &H80
                    XUP = &H100
                    WHEEL = &H800
                    VIRTUALDESK = &H4000
                    ABSOLUTE = &H8000
                End Enum
            End Structure
            Private Structure KEYBDINPUT
                Public wVk As Short
                Public wScan As Short
                Public dwFlags As KEYEVENTF
                Public time As Integer
                Public dwExtraInfo As IntPtr
                Public Enum KEYEVENTF As Integer
                    KEYDOWN = 0
                    EXTENDEDKEY = 1
                    KEYUP = 2
                    UNICODE = 4
                    SCANCODE = 8
                End Enum
            End Structure
            Private Structure HARDWAREINPUT
                Public uMsg As Integer
                Public wParamL As Short
                Public wParamH As Short
            End Structure
            Private Enum dwType As Integer
                MOUSE = 0
                KEYBOARD = 1
                HARDWARE = 2
            End Enum
    
            Public Enum MouseEvent
                ''' <summary>
                ''' Moves the cursor with the offset dx and dy
                ''' </summary>
                Move = &H1
                ''' <summary>
                ''' Places the cursor at the screen coordinates dx and dy
                ''' </summary>
                MoveScreen = &H1000
                ''' <summary>
                ''' Places the cursor at the screen using dx and dy ranging from 0 (left/top) to 65535 (right/bottom)
                ''' </summary>
                MoveAbsolute = Move Or &H8000
                ''' <summary>
                ''' Places the cursor at the desktop using dx and dy ranging from 0 (left/top) to 65535 (right/bottom)
                ''' </summary>
                MoveVirtualDesktop = MoveAbsolute Or &H4000
                ''' <summary>
                ''' Press the left mouse button
                ''' </summary>
                LeftDown = &H2
                ''' <summary>
                ''' Release the left mouse button
                ''' </summary>
                LeftUp = &H4
                ''' <summary>
                ''' Press the right mouse button
                ''' </summary>
                RightDown = &H8
                ''' <summary>
                ''' Release the right mouse button
                ''' </summary>
                RightUp = &H10
                ''' <summary>
                ''' Press the middle mouse button
                ''' </summary>
                MiddleDown = &H30
                ''' <summary>
                ''' Release the middle mouse button
                ''' </summary>
                MiddleUp = &H40
                ''' <summary>
                ''' Press the XButton specified in the data member
                ''' </summary>
                XDown = &H80
                ''' <summary>
                ''' Release the XButton specified in the data member
                ''' </summary>
                XUp = &H100
                ''' <summary>
                ''' Scroll the vertical mousewheel with the delta count of the data member
                ''' </summary>
                MouseVWheel = &H800
                ''' <summary>
                ''' Scroll the horizontal mousewheel with the delta count of the data member
                ''' </summary>
                MouseHWheel = &H20E
            End Enum
            Public Enum MouseData As Integer
                XButton1 = 1
                XButton2 = 2
                Wheel_Delta_Backward = -120
                Wheel_Delta_Forward = 120
                Wheel_Delta_Left = -120
                Wheel_Delta_Right = 120
            End Enum
            Public Enum KeyEvent
                Down = 0
                Up = 2
            End Enum
    
            Private Declare Function SendInput Lib "user32.dll" (ByVal cInputs As Integer, ByVal pInputs() As Input, ByVal cbSize As Integer) As Integer
            Public Shared Function Send(ByVal ParamArray inputs() As Input) As Boolean
                Return SendInput(inputs.Count, inputs, Marshal.SizeOf(GetType(Input)))
            End Function
            Public Function Send() As Boolean
                Return Send(Me)
            End Function
        End Structure
    Which makes the cursor start dragging the form. I believe sending input is not the best method around. Let's say I try to move the bar on a scrollbar around.

  21. #21
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Drawing on the screen with an overlay Window

    Quote Originally Posted by bergerkiller View Post
    Ah you mean making the entire form like that. Well the problem with that is again getting the pixel. If I were to use something like that it would be impossible to get the pixel, since the drawn cross is in front of it. That is why I use the cursor as centre marking.
    Just leave the middle pixel of the cross transparent and draw the arms of the cross. It will look fine like that.

    On testing, it's better to make the cursor position a small distance (e.g. 30 pixels) inside the form. This prevents the real cursor from flickering during fast dragging.

    BB

  22. #22

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    Yeah, as a total replacement cursor I would have to do that yes, thanks.
    But, since the actual position of the form does not necessarily have to match the cursor position, I don't mind a minor delay when moving the cursor. Even then, the delay is rather small.

  23. #23

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Drawing on the screen with an overlay Window

    Time for a bump...

    I decided to go a different road, something unrelated to this, but the same idea.
    I have this external program and I want to make another topmost form above it.
    Any pressed keys or mouse events that this topmost screen obtains are redirected to the underlying program, thereby keeping track of what is going on.

    For this I need a 100% transparent form, 99% would either make the program underneath lighter or darker, or worse, coloured. On my OS (Windows 7 32 bit) I have no problems with this; I can simply click on the transparent window. But I fear that on other machines the OS will click through the form (and click on the program below). A colorkey could be used as well, but the same clickable rule must count there.

    I see I have to trick the OS into believing a form is present at the location, whilst drawing a completely transparent form. Anyone has any idea of how to accomplish this? I tried some regular commands like setting layered to true, they do not work out.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width