none
'Cookie Cutter' through a form RRS feed

  • Question

  • Hi

    I have looked around but wasn't able to find anything. I have a form that I am filling the screen with. The form is set to 30% Opacity. On the form I have added a rectangle that I can resize. What I need to achieve is for the area INSIDE the rectangle to look through the form to the main screen contents behind very much like a cookie cutter or a hole in the form so to speak.

    Is this possible? I'm needing to take a screenshot of the contents behind using the rectangle as a frame

    Cheers

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Sunday, November 5, 2017 7:31 AM

Answers

  • Hi again

    It seems to be working ok with a small exception. In the earlier version, the rectangle was resized by selecting any of the grips. In this version, its very hard to select grip to resize it. My mousemove event is picking up when the mouse is over the grip and the rectangle but its a hit and miss as to whether the rectangle moves. it takes about 3 or 4 attempts to select the rectangle.

    Also

    Is there a way to dispose of the rectangle when moving? In your earlier version, the rectangle disappeared in the mousemove event then reappeared when the moving stopped. I cant see how that worked in the code version you provided. The result im getting is the orange rectangle and grips appearing in the snapshot image... I was hoping for a visible method but there isnt one...

    Other than that, its working sweet :)

    Cheers


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Nacho,

    "I had to add the Method CaptureFormRect() from a previous sample as when i tried to get the bmp from the rectangle, all i could get was the background image."

    Notice in my Example 2 that has the CaptureFormRect sub there is a variable Capturing = true and then Refresh. In the Paint event when Capturing a Lime hole is drawn on the form and the background image is not. So that gives the transparent hole only when caputuring and then Capturing = False at the end of CaptureFormRect and next time we paint the captured image is drawn in the hole.

    Are you doing that?

    "Last thing i need to do now is turn off the border & grips while taking the capture as they are captured in the image."

    Yes that is why when capturing only the transparency is used on the form and when moving the mouse the entire form background is drawn on the form so there is no transparency.

    Realize in Example 2 only the fence rect was being used.

    "Is there a way to dispose of the rectangle when moving? In your earlier version, the rectangle disappeared in the mousemove event then reappeared when the moving stopped. "

    Yes dont draw them as I explained. Thats what the capturing flag is for. It is set because the mouse move event in example 2 called the captureFormRect sub which sets it.

    If you look at example 3, I dont capture the background in paint event. Only in form location changed and resize. So as I mentioned, in Example 3 the background is just captured when the form loads or moves. And in example 3 I used creategraphics in the capture sub and draw the transparent color on the form before capture, then later, in the paint event, the entire background of the form client area was captured and now drawn on the form in the paint event. Since the form is not the transparent color rather its the bitmap colors, there is no transparency.

    There is just the captured background bitmap and its not changing. So all we have to do is show the bitmap and draw on it and get mouse events on it and then capture the rect we want from it. Just like putting the background image in a paint program and cropping the rect we want.

    So Example 3 is a better way to do it. If your background is not changing that is.

    Anyway I am sure that is confusing.

    It sounds like you are not making the form transparent by drawing it lime color just before the capture.

    And then when the mouse event is sluggish or not responding you must be mixing events. Thats why I was careful, in example 2 the capturing flag tells us dont draw the rect and grips and etc in paint. In example 3 paint is not used for the capture instead only form resize. So the code is not capturing in the mouse move event.

    And finally we have a problem with many examples being mixed up and not knowing exactly what you are doing now. I named my code examples 1, 1a, 2 and 3 above please ref those. Also you should make it clear which post you are responding to I was not sure if you were referring to me or Razerz etc.

    So you will have to post a working example with your problem or we cant really help much more as we are guessing what is happening.

    :)




    • Edited by tommytwotrain Wednesday, November 8, 2017 2:05 PM
    • Marked as answer by NachoShaw Thursday, November 9, 2017 8:41 AM
    Wednesday, November 8, 2017 2:03 PM

All replies

  • Use SetWindowRgn() to create a hole (many codes on Google...)
    Sunday, November 5, 2017 7:52 AM
  • Hi

    Thanks. Easy when you know what to look for. I had found samples of that but couldnt find any in vb.net. They all seem to be in C++


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Sunday, November 5, 2017 8:18 AM
  • A very long time on our website

    http://www.vb-tips.com/ShapedForm.aspx


    Success
    Cor

    Sunday, November 5, 2017 9:27 AM
  •  This can be done by simply setting the TransparencyKey color.  Then you can either place a Panel on the form that is the same color as the TransparencyKey color,  or you can draw a filled rectangle on the form with the same color.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.Opacity = 0.3
            Me.BackColor = Color.Black
            Me.TransparencyKey = Color.Lime
        End Sub
    
        Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
            e.Graphics.FillRectangle(Brushes.Lime, 40, 60, Me.ClientSize.Width - 80, Me.ClientSize.Height - 120)
        End Sub
    End Class
    
     

     Here you can see it has a transparent rectangle where i draw the rectangle with the Lime color.

     


    If you say it can`t be done then i`ll try it

    Sunday, November 5, 2017 10:57 AM

  • This one captures the desktop image and puts it in the Panel so all that is left is copy the captured image from the panel backgroundimage.

    PS I don't know how you move your panel but it may need adapting with a transparent form. You don't need a panel as Razerz said you can just draw a rectangle on the form as Razerz (and this) showed. I don't know how your form is setup which will be easiest/best.

    'example 1

    Imports System.Drawing.Imaging Public Class Form6 Private WithEvents Panel1 As New Panel With {.Parent = Me, .Size = New Size(160, 120), .Location = New Point(30, 40), .BackgroundImageLayout = ImageLayout.None, .BorderStyle = BorderStyle.None} Private mdPt, mdOffsetPt As PointF Private Sub Form11_Load(sender As Object, e As EventArgs) Handles MyBase.Load BackColor = Color.Lime TransparencyKey = BackColor Opacity = 0.6 End Sub Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint e.Graphics.Clear(Color.Lime) Using bmp1 As New Bitmap(Panel1.ClientSize.Width, Panel1.ClientSize.Height), bgBmp As New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height), g1 As Graphics = Graphics.FromImage(bmp1), g3 As Graphics = Graphics.FromImage(bgBmp) 'get the screen background Dim pt0 As New Point(0, 0) Dim pt As Point = PointToScreen(pt0) g3.CopyFromScreen(pt, pt0, bgBmp.Size) 'copy the background to the panel Dim destRect As New Rectangle(0, 0, Panel1.ClientSize.Width, Panel1.ClientSize.Height) g1.DrawImage(bgBmp, destRect, Panel1.Bounds, GraphicsUnit.Pixel) Dim img As Image img = Panel1.BackgroundImage Panel1.BackgroundImage = CType(bmp1.Clone, Image) If img IsNot Nothing Then img.Dispose() End Using End Sub Private Sub Form6_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint e.Graphics.Clear(Color.FromArgb(30, Color.Red)) e.Graphics.FillRectangle(Brushes.Lime, Panel1.Bounds) End Sub End Class






    Sunday, November 5, 2017 12:03 PM
  •  Here is an example of a resizable panel class that you can add to a new Form project for testing.  You will then need to Build or Run the application.  After that you will find the 'CapturePanel' control at the top of the Toolbox.  Add one to the Form the same way you would with any other controls.

    Public Class Form1

    End Class

    Public Class CapturePanel Inherits Panel Private Const WM_NCHITTEST As Integer = &H84 Private Const HTLEFT As Integer = &HA Private Const HTRIGHT As Integer = &HB Private Const HTTOP As Integer = &HC Private Const HTTOPLEFT As Integer = &HD Private Const HTTOPRIGHT As Integer = &HE Private Const HTBOTTOM As Integer = &HF Private Const HTBOTTOMLEFT As Integer = &H10 Private Const HTBOTTOMRIGHT As Integer = &H11 Public Function GetCapture() As Bitmap Dim bm As New Bitmap(Me.Width - 12, Me.Height - 12) Using g As Graphics = Graphics.FromImage(bm) g.CopyFromScreen(Me.Left + 6, Me.Top + 6, 0, 0, New Size(Me.Width - 12, Me.Height - 12), CopyPixelOperation.SourceCopy) End Using Return bm End Function Public Sub New() Me.ResizeRedraw = True Me.DoubleBuffered = True Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True) End Sub Protected Overrides Sub OnPaint(e As PaintEventArgs) e.Graphics.FillRectangle(Brushes.Lime, 6, 6, Me.Width - 12, Me.Height - 12) MyBase.OnPaint(e) End Sub Protected Overrides Sub WndProc(ByRef m As Message) If m.Msg = WM_NCHITTEST Then Dim loc As Point = Me.PointToClient(MousePosition) Dim bTop As Boolean = (loc.Y <= 6) Dim bLeft As Boolean = (loc.X <= 6) Dim bRight As Boolean = (loc.X >= Me.Width - 6) Dim bBottom As Boolean = (loc.Y >= Me.Height - 6) If bTop AndAlso bLeft Then m.Result = CType(HTTOPLEFT, IntPtr) Return ElseIf bTop AndAlso bRight Then m.Result = CType(HTTOPRIGHT, IntPtr) Return ElseIf bBottom AndAlso bLeft Then m.Result = CType(HTBOTTOMLEFT, IntPtr) Return ElseIf bBottom AndAlso bRight Then m.Result = CType(HTBOTTOMRIGHT, IntPtr) Return ElseIf bLeft Then m.Result = CType(HTLEFT, IntPtr) Return ElseIf bTop Then m.Result = CType(HTTOP, IntPtr) Return ElseIf bRight Then m.Result = CType(HTRIGHT, IntPtr) Return ElseIf bBottom Then m.Result = CType(HTBOTTOM, IntPtr) Return End If End If MyBase.WndProc(m) End Sub End Class

     

     After doing the above,  add a Button to the form too.  Then try the below code in the Form.  In this example i show how to get the screen image using the GetCapture method of the CapturePanel.  I save it to a file but,  you can do whatever you want with the captured image.

     You may also want to use a Button to close the form too. Otherwise you can press (Alt+F4) to close it.

    Public Class Form1
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.FormBorderStyle = FormBorderStyle.None
            Me.WindowState = FormWindowState.Maximized
            Me.Opacity = 0.3
            Me.BackColor = Color.Black
            Me.TransparencyKey = Color.Lime
            CapturePanel1.BackColor = Me.BackColor
        End Sub
    
        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Using img As Bitmap = CapturePanel1.GetCapture
                img.Save("C:\testfolder\captured.png", Imaging.ImageFormat.Png)
            End Using
        End Sub
    End Class
    


    If you say it can`t be done then i`ll try it

    Sunday, November 5, 2017 12:50 PM
  • This one does not use a panel.

    :)

    'example 2

    Public Class Form8 Private MouseDownStage As Integer Private MouseDownPt, MouseMovePt, MouseDownOffsetPt As PointF Private FenceRect As RectangleF Private Capturing As Boolean Private CaptureBmp As Bitmap Private Sub Form8_Load(sender As Object, e As EventArgs) Handles MyBase.Load DoubleBuffered = True BackColor = Color.Lime TransparencyKey = BackColor End Sub Private Sub Form8_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown MouseDownStage = GetMouseOverType(e.X, e.Y) Select Case MouseDownStage Case 1 'nothing under mouse down begin drawing tracer MouseDownPt = e.Location MouseMovePt = e.Location Case 2, 3 'mouse down on rectangle or handle begine moving MouseDownPt = FenceRect.Location MouseDownOffsetPt.X = e.X - FenceRect.X MouseDownOffsetPt.Y = e.Y - FenceRect.Y End Select End Sub Private Sub Form8_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove MouseMovePt = e.Location If MouseDownStage > 0 Then Dim dx, dy As Single Select Case MouseDownStage Case 1 'drawing rectangle FenceRect = GetFenceRect(MouseDownPt, New SizeF(MouseMovePt.X - MouseDownPt.X, MouseMovePt.Y - MouseDownPt.Y)) Case 2 'moving fence dx = e.X - MouseDownPt.X dy = e.Y - MouseDownPt.Y FenceRect.X = MouseDownPt.X + dx - MouseDownOffsetPt.X FenceRect.Y = MouseDownPt.Y + dy - MouseDownOffsetPt.Y Case 3 'moving handle FenceRect.Width = Math.Abs(FenceRect.X - e.X) FenceRect.Height = Math.Abs(FenceRect.Y - e.Y) End Select CaptureFormRect() Invalidate() Else Select Case GetMouseOverType(e.X, e.Y) Case 2 'fence Cursor = Cursors.Hand Case 3 'handle Cursor = Cursors.SizeNESW Case Else Cursor = Cursors.Default End Select End If End Sub Private Sub Form8_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp Select Case MouseDownStage Case 1 'save the rectangle FenceRect = GetFenceRect(MouseDownPt, New SizeF(MouseMovePt.X - MouseDownPt.X, MouseMovePt.Y - MouseDownPt.Y)) CaptureFormRect() End Select MouseDownStage = 0 Invalidate() End Sub Private Sub Form8_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint With e.Graphics .Clear(Color.Black) Using p As New Pen(Color.White, 1), br As New SolidBrush(BackColor) 'draw the rectangle If FenceRect.Width > 0 Then If Capturing Then 'make transparent hole for capture .FillRectangle(br, Rectangle.Round(FenceRect)) Else 'draw captured image in rect If CaptureBmp IsNot Nothing Then .DrawImage(CaptureBmp, Rectangle.Round(FenceRect)) End If 'rectangle outline dashed white p.DashStyle = Drawing2D.DashStyle.Dash .DrawRectangle(p, Rectangle.Round(FenceRect)) 'draw the handle Dim h As Integer = 5 Dim rect2 As New Rectangle(CInt(FenceRect.X + FenceRect.Width - h), CInt(FenceRect.Y + FenceRect.Height - h), 2 * h, 2 * h) p.Width = 2 p.Color = Color.Red p.DashStyle = Drawing2D.DashStyle.Solid .DrawRectangle(p, rect2) End If End If End Using End With End Sub Private Sub Form8_LocationChanged(sender As Object, e As EventArgs) Handles _ Me.LocationChanged, Me.Resize CaptureFormRect() Invalidate() End Sub Private Function GetMouseOverType(x As Integer, y As Integer) As Integer 'determine if the mouse pointer is over the handle or fence Dim h As Integer = 5 Dim handleRect As New Rectangle(CInt(FenceRect.X + FenceRect.Width - h), CInt(FenceRect.Y + FenceRect.Height - h), 2 * h, 2 * h) If handleRect.Contains(x, y) Then GetMouseOverType = 3 'mouse over handle ElseIf FenceRect.Contains(x, y) Then GetMouseOverType = 2 'mouse over fence FenceRect Else GetMouseOverType = 1 'mouse not over anything End If End Function Private Function GetFenceRect(locPt As PointF, sz As SizeF) As RectangleF 'creates proper FenceRect from any direction for point and size Dim X As Single = locPt.X Dim X1 As Single = sz.Width If X1 < 0 Then X1 = Math.Abs(X1) X -= X1 End If Dim Y As Single = locPt.Y Dim Y1 As Single = sz.Height If Y1 < 0 Then Y1 = Math.Abs(Y1) Y -= Y1 End If GetFenceRect = New RectangleF(X, Y, X1, Y1) End Function Private Sub CaptureFormRect() If FenceRect.Width > 0 AndAlso FenceRect.Height > 0 Then Capturing = True Refresh() If CaptureBmp IsNot Nothing Then Dim img As Image img = CaptureBmp CaptureBmp = Nothing img.Dispose() End If Using bmp1 As New Bitmap(CInt(FenceRect.Width), CInt(FenceRect.Height)), bgBmp As New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height), g1 As Graphics = Graphics.FromImage(bmp1), g3 As Graphics = Graphics.FromImage(bgBmp) 'get the screen background Dim pt0 As New Point(0, 0) Dim pt As Point = PointToScreen(pt0) g3.CopyFromScreen(pt, pt0, bgBmp.Size) 'copy the background to the capture bmp Dim destRect As New Rectangle(0, 0, bmp1.Width, bmp1.Height) g1.DrawImage(bgBmp, destRect, FenceRect, GraphicsUnit.Pixel) CaptureBmp = CType(bmp1.Clone, Bitmap) End Using Capturing = False End If End Sub End Class




    Sunday, November 5, 2017 2:03 PM
  • Hi

    This is all pretty cool and i appreciate the help. I managed to make this last night.

    There are a couple of tweaks i would to try and achieve

    • I need to stop the flickering when the box is resized
    • i'd like to try and maintain the mouse movement on the form. currently because there is a hole, i lose focus and the window behind the hoe becomes active.
    • maintain the button controls NOT to have opacity while the form has 30%. So basically, semi transparent form, solid buttons.

    i quite like the image approach sample, that could work and i can combine it with my code to give me the grips for resizing.

    for reference, i wasnt completely clear in my description. I have a panel to maintain a specific area on my form. I create a rectangle within the panel so that the rectangle movement can be controlled visually at design time :)

    Thanks for the help and samples, much appreciated :)

    Nacho



    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Sunday, November 5, 2017 9:13 PM
  • Hi

    This is all pretty cool and i appreciate the help. I managed to make this last night.

    There are a couple of tweaks i would to try and achieve

    • I need to stop the flickering when the box is resized
    • i'd like to try and maintain the mouse movement on the form. currently because there is a hole, i lose focus and the window behind the hoe becomes active.
    • maintain the button controls NOT to have opacity while the form has 30%. So basically, semi transparent form, solid buttons.

    i quite like the image approach sample, that could work and i can combine it with my code to give me the grips for resizing.

    for reference, i wasnt completely clear in my description. I have a panel to maintain a specific area on my form. I create a rectangle within the panel so that the rectangle movement can be controlled visually at design time :)

    Thanks for the help and samples, much appreciated :)

    Nacho



    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Looks good Nacho,

    Its still not clear to me exactly the panel doings that you want.

    To stop flickering try adding doublebuffer = true to the form load to set double buffered for the form. If that does not stop it then for your panels you will need to make a class of your own and set the doublebuffer for the panel. If you use a picturebox instead of a panel it has doublebuffer on by default.

    Yes well that is the trick as I mentioned. When you make a transparent hole then you click through the form. So either set things up where you don't need to click the hole or don't really have a hole. In my examples that's why I put the image over the hole so there it something to click on, as long as it is not the transparent color you can click it.

    I think that's how the buttons and other controls will behave? As long as they are not the transparent color they will be opaque.

    Monday, November 6, 2017 1:16 AM
  • Hi

    Thanks for the reply. I will convert my project from a Panel to a Picturebox tonight as i like the placement of the image into the box to prevent an 'open window'.

    My code method is different to yours so i will be looking at the conversion of your method into my project. I would like to retain the 9 grips around the rectangle as thats more in keeping with the overall format of the application (CAD based).

    Regarding other controls, is there a method keeping them completely solid while making the form background slightly opaque? I actually need to make the form more opaque and currently, i can see through my controls too which isnt great...

    Cheers

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Monday, November 6, 2017 11:09 PM
  • Hi TommyTwoTrain

    Im struggling a little with the conversion. I have used what i can but i cant the correct behavior i need.

    as you can see, i can now move the rectangle but when the image copies, it seems to be offset. I think its because i am using a picturebox control as the container on the form. The code for this is currently in a class, not in the form. I can manually set the offset in this line to 8,31

    'copy the background to the capture bmp
                        Dim destRect As New Rectangle(8, 31, bmp1.Width, bmp1.Height)
                        g1.DrawImage(bgBmp, destRect, rect, GraphicsUnit.Pixel)

     As the class i have is now placing a picturebox on my form as a container, the issue must be between the form & the picturebox sizes. i have docked the picturebox into the form but that didnt change anything. What i cant seem to do is create the rectangle on the form itself using the class.....

    I then tried to get your sample (using form8) to act like mine. i copied across the method to create the 9 handles which works ok but i cant seem to get your version to function like mine. For example, i need it to function like:

    Form loads, rectangle is automatically created and positioned in the center of the form

    rectangle can be resized with any grip

    Here is my class code. PLEASE NOTE: There are currently extra methods that i have yet to remove as i have copied some samples over but not deleted unused yet, i will do that at the end.

    Imports System.Collections.Generic
    Imports System.Text
    Imports System.Drawing
    Imports System.Drawing.Drawing2D
    Imports System.Windows.Forms
    
    Namespace UserRectDemo
        Public Class UserRect
            Inherits PictureBox
            Private mPictureBox As System.Windows.Forms.PictureBox
            'Friend mPictureBox As Form
            Public rect As Rectangle
            Private grip As Rectangle
            Public allowDeformingDuringMovement As Boolean = False
            Private mIsClick As Boolean = False
            Private mMove As Boolean = False
            Private oldX As Integer
            Private oldY As Integer
            Private sizeNodeRect As Integer = 8
            Private mBmp As Bitmap = Nothing
            Private nodeSelected As PosSizableRect = PosSizableRect.None
            Private angle As Integer = 30
            Private pColor As System.Drawing.Color = Color.Orange
            Private HoleBrush As New SolidBrush(Color.Green)
            Private GripBrush As New SolidBrush(Color.Orange)
            Private edgeOffset As Integer = 0
            Friend CaptureBmp As Bitmap
            Private Capturing As Boolean
    
            'new
            Private MouseDownStage As Integer
            Private MouseDownPt, MouseMovePt, MouseDownOffsetPt As Point
    
            Private Enum PosSizableRect
                UpMiddle
                LeftMiddle
                LeftBottom
                LeftUp
                RightUp
                RightMiddle
                RightBottom
                BottomMiddle
                None
            End Enum
    
            Public Sub New(r As Rectangle)
                rect = r
                mIsClick = False
            End Sub
    
            Public Sub Draw(g As Graphics)
                Dim p As New Pen(pColor, 2)
                p.DashStyle = Drawing2D.DashStyle.Dash
                g.DrawRectangle(p, rect)
    
                g.FillRectangle(HoleBrush, rect)
    
                For Each pos As PosSizableRect In [Enum].GetValues(GetType(PosSizableRect))
                    g.DrawRectangle(New Pen(Color.Orange, 3), GetRect(pos))
                    g.FillRectangle(GripBrush, GetRect(pos))
                Next
            End Sub
    
            Public Sub SetBitmapFile(filename As String)
                Me.mBmp = New Bitmap(filename)
            End Sub
    
            Public Sub SetBitmap(bmp As Bitmap)
                Me.mBmp = bmp
            End Sub
    
            Public Sub SetPictureBox(p As PictureBox)
                Me.mPictureBox = p
    
                AddHandler mPictureBox.MouseDown, New MouseEventHandler(AddressOf mPictureBox_MouseDown)
                AddHandler mPictureBox.MouseUp, New MouseEventHandler(AddressOf mPictureBox_MouseUp)
                AddHandler mPictureBox.MouseMove, New MouseEventHandler(AddressOf mPictureBox_MouseMove)
                AddHandler mPictureBox.Paint, New PaintEventHandler(AddressOf mPictureBox_Paint)
    
            End Sub
    
            Private Sub mPictureBox_Paint(sender As Object, e As PaintEventArgs)
    
                Try
                    Draw(e.Graphics)
                    'new
                    With e.Graphics
                        If rect.Width > 0 Then
                            If Capturing Then
                                ''make transparent hole for capture
                            Else
                                'draw captured image in rect
                                If CaptureBmp IsNot Nothing Then
                                    .DrawImage(CaptureBmp, Rectangle.Round(rect))
                                End If
                            End If
                        End If
                    End With
    
                Catch exp As Exception
                    System.Console.WriteLine(exp.Message)
                End Try
    
            End Sub
    
            Private Sub mPictureBox_MouseDown(sender As Object, e As MouseEventArgs)
                mIsClick = True
    
                nodeSelected = PosSizableRect.None
                nodeSelected = GetNodeSelectable(e.Location)
    
                If rect.Contains(New Point(e.X, e.Y)) Then
                    mMove = True
                    MouseDownStage = GetMouseOverType(e.X, e.Y)
                End If
                oldX = e.X
                oldY = e.Y
            End Sub
    
            Private Sub mPictureBox_MouseUp(sender As Object, e As MouseEventArgs)
                mIsClick = False
                mMove = False
    
                'new
                Select Case MouseDownStage
                    Case 1      'save the rectangle
                        rect = GetFenceRect(MouseDownPt, New Size(MouseMovePt.X - MouseDownPt.X,
                                                                            MouseMovePt.Y - MouseDownPt.Y))
                        CaptureFormRect()
                End Select
                MouseDownStage = 0
                Invalidate()
            End Sub
    
            Private Sub mPictureBox_MouseMove(sender As Object, e As MouseEventArgs)
                ChangeCursor(e.Location)
                If mIsClick = False Then
                    Return
                End If
    
    
    
                Dim backupRect As Rectangle = rect
    
                Select Case nodeSelected
                    Case PosSizableRect.LeftUp
                        rect.X += e.X - oldX
                        rect.Width -= e.X - oldX
                        rect.Y += e.Y - oldY
                        rect.Height -= e.Y - oldY
                        Exit Select
                    Case PosSizableRect.LeftMiddle
                        rect.X += e.X - oldX
                        rect.Width -= e.X - oldX
                        Exit Select
                    Case PosSizableRect.LeftBottom
                        rect.Width -= e.X - oldX
                        rect.X += e.X - oldX
                        rect.Height += e.Y - oldY
                        Exit Select
                    Case PosSizableRect.BottomMiddle
                        rect.Height += e.Y - oldY
                        Exit Select
                    Case PosSizableRect.RightUp
                        rect.Width += e.X - oldX
                        rect.Y += e.Y - oldY
                        rect.Height -= e.Y - oldY
                        Exit Select
                    Case PosSizableRect.RightBottom
                        rect.Width += e.X - oldX
                        rect.Height += e.Y - oldY
                        Exit Select
                    Case PosSizableRect.RightMiddle
                        rect.Width += e.X - oldX
                        Exit Select
    
                    Case PosSizableRect.UpMiddle
                        rect.Y += e.Y - oldY
                        rect.Height -= e.Y - oldY
                        Exit Select
                    Case Else
    
                        If mMove Then
                            rect.X = rect.X + e.X - oldX
                            rect.Y = rect.Y + e.Y - oldY
                        End If
                        Exit Select
                End Select
                oldX = e.X
                oldY = e.Y
    
                If rect.Width < 5 OrElse rect.Height < 5 Then
                    rect = backupRect
                End If
    
                TestIfRectInsideArea()
                CaptureFormRect()
                mPictureBox.Invalidate()
    
            End Sub
    
            Private Sub TestIfRectInsideArea()
                ' Test if rectangle still inside the area.
                If rect.X < 0 Then
                    rect.X = 0
                End If
                If rect.Y < 0 Then
                    rect.Y = 0
                End If
                If rect.Width <= 0 Then
                    rect.Width = 1
                End If
                If rect.Height <= 0 Then
                    rect.Height = 1
                End If
    
                If rect.X + rect.Width > mPictureBox.Width Then
                    rect.Width = mPictureBox.Width - rect.X - 1
                    ' -1 to be still show 
                    If allowDeformingDuringMovement = False Then
                        mIsClick = False
                    End If
                End If
                If rect.Y + rect.Height > mPictureBox.Height Then
                    rect.Height = mPictureBox.Height - rect.Y - 1
                    ' -1 to be still show 
                    If allowDeformingDuringMovement = False Then
                        mIsClick = False
                    End If
                End If
            End Sub
    
            Private Function CreateRectSizableNode(x As Integer, y As Integer) As Rectangle
                Return New Rectangle(x - sizeNodeRect / 2, y - sizeNodeRect / 2, sizeNodeRect, sizeNodeRect)
            End Function
    
            Private Function GetRect(p As PosSizableRect) As Rectangle
                Select Case p
                    Case PosSizableRect.LeftUp
                        Return CreateRectSizableNode(rect.X, rect.Y)
    
                    Case PosSizableRect.LeftMiddle
                        Return CreateRectSizableNode(rect.X, rect.Y + +rect.Height / 2)
    
                    Case PosSizableRect.LeftBottom
                        Return CreateRectSizableNode(rect.X, rect.Y + rect.Height)
    
                    Case PosSizableRect.BottomMiddle
                        Return CreateRectSizableNode(rect.X + rect.Width / 2, rect.Y + rect.Height)
    
                    Case PosSizableRect.RightUp
                        Return CreateRectSizableNode(rect.X + rect.Width, rect.Y)
    
                    Case PosSizableRect.RightBottom
                        Return CreateRectSizableNode(rect.X + rect.Width, rect.Y + rect.Height)
    
                    Case PosSizableRect.RightMiddle
                        Return CreateRectSizableNode(rect.X + rect.Width, rect.Y + rect.Height / 2)
    
                    Case PosSizableRect.UpMiddle
                        Return CreateRectSizableNode(rect.X + rect.Width / 2, rect.Y)
                    Case Else
                        Return New Rectangle()
                End Select
            End Function
    
            Private Function GetNodeSelectable(p As Point) As PosSizableRect
                For Each r As PosSizableRect In [Enum].GetValues(GetType(PosSizableRect))
                    If GetRect(r).Contains(p) Then
                        Return r
                    End If
                Next
                Return PosSizableRect.None
            End Function
    
            Private Sub ChangeCursor(p As Point)
                mPictureBox.Cursor = GetCursor(GetNodeSelectable(p), p)
            End Sub
    
            ''' <summary>
            ''' Get cursor for the handle
            ''' </summary>
            ''' <param name="p"></param>
            ''' <returns></returns>
            Private Function GetCursor(p As PosSizableRect, pnt As Point) As Cursor
                Select Case p
                    Case PosSizableRect.LeftUp
                        Return Cursors.SizeNWSE
    
                    Case PosSizableRect.LeftMiddle
                        Return Cursors.SizeWE
    
                    Case PosSizableRect.LeftBottom
                        Return Cursors.SizeNESW
    
                    Case PosSizableRect.BottomMiddle
                        Return Cursors.SizeNS
    
                    Case PosSizableRect.RightUp
                        Return Cursors.SizeNESW
    
                    Case PosSizableRect.RightBottom
                        Return Cursors.SizeNWSE
    
                    Case PosSizableRect.RightMiddle
                        Return Cursors.SizeWE
    
                    Case PosSizableRect.UpMiddle
                        Return Cursors.SizeNS
                    Case Else
                        If rect.Contains(pnt) Then
                            Return Cursors.SizeAll
                        Else Return Cursors.Cross
                        End If
                End Select
            End Function
    
            'new
            Private Function GetMouseOverType(x As Integer, y As Integer) As Integer
                'determine if the mouse pointer is over the handle or fence
                Dim h As Integer = 5
                Dim handleRect As New Rectangle(CInt(rect.X + rect.Width - h), CInt(rect.Y + rect.Height - h), 2 * h, 2 * h)
    
                If rect.Contains(x, y) Then
                    GetMouseOverType = 2              'mouse over fence FenceRect
                Else
                    GetMouseOverType = 1              'mouse not over anything
                End If
            End Function
    
            Private Function GetFenceRect(locPt As Point, sz As Size) As Rectangle
                'creates proper FenceRect from any direction for point and size 
                Dim X As Single = locPt.X
                Dim X1 As Single = sz.Width
    
                If X1 < 0 Then
                    X1 = Math.Abs(X1)
                    X -= X1
                End If
    
                Dim Y As Single = locPt.Y
                Dim Y1 As Single = sz.Height
    
                If Y1 < 0 Then
                    Y1 = Math.Abs(Y1)
                    Y -= Y1
                End If
    
                GetFenceRect = New Rectangle(X, Y, X1, Y1)
    
            End Function
    
            Friend Sub CaptureFormRect()
                If rect.Width > 0 AndAlso rect.Height > 0 Then
                    Capturing = True
                    Form2.PictureBox1.Refresh()
    
                    If CaptureBmp IsNot Nothing Then
                        Dim img As Image
                        img = CaptureBmp
                        CaptureBmp = Nothing
                        img.Dispose()
                    End If
    
                    Using bmp1 As New Bitmap(CInt(rect.Width), CInt(rect.Height)),
                       bgBmp As New Bitmap(Form2.ClientSize.Width, Form2.ClientSize.Height),
                        g1 As Graphics = Graphics.FromImage(bmp1),
                            g3 As Graphics = Graphics.FromImage(bgBmp)
    
                        'get the screen background
                        Dim pt0 As New Point(0, 0)
                        Dim pt As Point = PointToScreen(pt0)
                        g3.CopyFromScreen(pt, pt0, bgBmp.Size)
    
                        'copy the background to the capture bmp
                        Dim destRect As New Rectangle(8, 31, bmp1.Width, bmp1.Height)
                        g1.DrawImage(bgBmp, destRect, rect, GraphicsUnit.Pixel)
    
                        CaptureBmp = CType(bmp1.Clone, Bitmap)
                    End Using
    
                    Capturing = False
                End If
            End Sub
    
        End Class
    End Namespace


    This is how i am currently loading it

     PictureBox1.Left = Me.Left
            PictureBox1.Top = Me.Top
            PictureBox1.Width = Me.ClientSize.Width
    
            Me.WindowState = FormWindowState.Maximized
            rect = New UserRectDemo.UserRect(New Rectangle(PictureBox1.Width - 100, PictureBox1.Height - 100, 200, 200))
    
    
            Panel2.Left = (Me.Width / 2) - (Me.Panel2.Width / 2)
    
            rect.SetPictureBox(Me.PictureBox1)

    I also noticed that on your sample, the border & handles disappeared when moving the rectangle. how did you do that? i cant seem to see it

    Cheers

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!


    • Edited by NachoShaw Tuesday, November 7, 2017 8:01 AM
    Tuesday, November 7, 2017 7:59 AM
  • Nacho,

    Well it sounds like 8, 31 is the difference between the outside of the form and the client area of the form. It is the form border width and the form titlebar height+border.

    I started writing explanation but I guess an example is easier. Here is my first example redone so you can click the panel. It seems to work properly as you move the form. You will have to modify it to capture in the panel mouse move event as we were doing with my second example instead of the form location changed as in this example.

    Finally you do see I capture the entire form background from the screen and then cut out the hole image that we want below the panel?

    'example 1B

    Imports System.Drawing.Imaging Public Class Form6 Private WithEvents Panel1 As New Panel With {.Parent = Me, .Size = New Size(160, 120), .Location = New Point(30, 40), .BackgroundImageLayout = ImageLayout.None, .BorderStyle = BorderStyle.None} Private mdPt, mdOffsetPt As PointF Private Sub Form11_Load(sender As Object, e As EventArgs) Handles MyBase.Load BackColor = Color.Lime TransparencyKey = BackColor Opacity = 0.6 End Sub Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint 'draw border e.Graphics.DrawRectangle(Pens.White, New Rectangle(0, 0, Panel1.ClientRectangle.Width - 1, Panel1.ClientRectangle.Height - 1)) End Sub Private Sub Form6_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint 'draw opacity and clear hole below panel e.Graphics.Clear(Color.FromArgb(30, Color.Red)) e.Graphics.FillRectangle(Brushes.Lime, Panel1.Bounds) End Sub Private Sub Form6_LocationChanged(sender As Object, e As EventArgs) Handles Me.LocationChanged Using bmp1 As New Bitmap(Panel1.ClientSize.Width - 0, Panel1.ClientSize.Height - 0), bgBmp As New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height), g1 As Graphics = Graphics.FromImage(bmp1), g3 As Graphics = Graphics.FromImage(bgBmp) Panel1.Visible = False 'get the screen background Dim pt0 As New Point(0, 0) Dim pt As Point = PointToScreen(pt0) g3.CopyFromScreen(pt, pt0, bgBmp.Size) 'copy the background to the panel Dim destRect As New Rectangle(0, 0, bmp1.Width, bmp1.Height) g1.DrawImage(bgBmp, destRect, Panel1.Bounds, GraphicsUnit.Pixel) Dim img As Image img = Panel1.BackgroundImage Panel1.BackgroundImage = CType(bmp1.Clone, Image) If img IsNot Nothing Then img.Dispose() Panel1.Visible = True End Using End Sub End Class



    Tuesday, November 7, 2017 2:13 PM
  • PS this shows the coordinates. I am just assuming your form border and title are 8 and 31 its possible that is not where those values come from.

    This shows you need to be sure you are using the same coord system, screen, form client area, panel client area.

    Maybe you know already. Try to break the problem down into one little area. Its too hard when you have many things that could be wrong or not understood. Make a new example. Don't use your big project until you have all the details clear and understood in your mind.

    PS In my example I capture the screen of the Form Client Area first. Then I cut out the panel image from that. So the captured form image upper left is (0,0) in the client area of the form. The cutout for the panel is the panel location in form client coordinates. That is the same as the fence rectangle or is the panel outside bounds rectangle.




    • Edited by tommytwotrain Tuesday, November 7, 2017 3:15 PM improve image
    Tuesday, November 7, 2017 3:01 PM
  • Nacho,

    Are you starting to see the advantage of just drawing on the form? Doing away with the panel (picturebox)? You have not convinced me you need the control. You may think it is easier but in the long run it is not and has problems when you try to combine all the different view ports screen, form, panel.

    Also, you can capture and draw the entire form image of the background using opacity, and not use opacity for the form. Then your controls wont be semi opaque. So instead of just the panel image, we would do the entire form client area image plus the panel or fence image (you can do this with or without the control).

    Comprende?

    :)


    PS I will post a new example of what I mean later today.
    Tuesday, November 7, 2017 3:41 PM
  • Hi

    Thanks for the help. I did try to alter my method to allow me to draw the rectangle directly to the form as it does seem a lot easier but in my attempt, i couldnt see my rectangle. I think it would be my preference now to have it direct in the form and i can manage the restrictions in the mousemove event (to keep away from edges etc).

    the 8, 31 is directly related to the form border top & border left. It worked ok until i set my form to have these not showing (as i need to fill the screen). Thats when the offset occurred. Again, if i was now to have the rectangle directly in theform instead, i think this issue would go away :)

    Thanks agin

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Tuesday, November 7, 2017 4:56 PM
  • Also, you can capture and draw the entire form image of the background using opacity, and not use opacity for the form. Then your controls wont be semi opaque. So instead of just the panel image, we would do the entire form client area image plus the panel or fence image (you can do this with or without the control).

    Hi

    This sounds interesting. I sort of understand. You are saying that:

    The whole screen area behind the form is captured and placed on the form to 'look' like it is opaque and then the rectangle using the transparency key will be the cut out hole?

    that would make sense. My form is full screen so i wouldnt need to handle the form loctation

    Appreciate the advice :)

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Tuesday, November 7, 2017 5:03 PM
  • Hi

    Just to remove any doubt, im not using the panel as the rectangle, i was using it as a perimeter for the rectangle to move so that i could control the area that the rectangle could move in. I can however control this in the mousemove


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Tuesday, November 7, 2017 5:21 PM
  • Hi

    Just to remove any doubt, im not using the panel as the rectangle, i was using it as a perimeter for the rectangle to move so that i could control the area that the rectangle could move in. I can however control this in the mousemove


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    I see. Well I would draw that then and have no panels. I suppose you can get it to work though. You just have another control offset to deal with.

    Here is an example that does not use form opacity. So your controls will look normal I think. I had to give the button a color or it was still transparent.

    So the beauty here is there is there is just the background image and a rectangle.

    You can also draw all your handles etc both inside and outside the capture rect its all just the form. And everything is clickable on the form.

    'Example 3

    Public Class Form9 Private WithEvents Button1 As New Button With {.Parent = Me, .Location = New Point(0, 0), .BackColor = Color.Red, .ForeColor = Color.AntiqueWhite, .Text = "Button"} Private CaptureBmp As Bitmap Private CaptureRect As New Rectangle(100, 100, 100, 100) Private mdPt, mdOffsetPt, mmPt As Point Private mdStage As Integer Private Sub Form11_Load(sender As Object, e As EventArgs) Handles MyBase.Load DoubleBuffered = True 'stops blinking TransparencyKey = Color.Lime BackColor = TransparencyKey End Sub Private Sub Form9_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint If CaptureBmp IsNot Nothing Then With e.Graphics 'draw captured background image on the form .DrawImage(CaptureBmp, ClientRectangle) 'draw semiopaque over form background image .FillRectangle(New SolidBrush(Color.FromArgb(80, Color.DimGray)), ClientRectangle) 'draw the capture fence window image opaque .DrawImage(CaptureBmp, CaptureRect, CaptureRect, GraphicsUnit.Pixel) .DrawRectangle(Pens.Gold, CaptureRect) End With End If End Sub Private Sub Form9_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown mdPt = e.Location If CaptureRect.Contains(mdPt) Then mdOffsetPt = CaptureRect.Location mdStage = 1 End If End Sub Private Sub Form9_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove Select Case mdStage Case 1 'moving rect Dim dx As Integer = e.X - mdPt.X Dim dy As Integer = e.Y - mdPt.Y CaptureRect.X = mdOffsetPt.X + dx CaptureRect.Y = mdOffsetPt.Y + dy Invalidate() End Select End Sub Private Sub Form9_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp mdStage = 0 End Sub Private Sub Form9_Resize(sender As Object, e As EventArgs) Handles _ Me.Resize, Me.LocationChanged CaptureFormBg() Invalidate() End Sub Private Sub CaptureFormBg() Using g As Graphics = Me.CreateGraphics, bmp As New Bitmap(ClientSize.Width, ClientSize.Height), g1 As Graphics = Graphics.FromImage(bmp) g.Clear(TransparencyKey) 'get the screem background below the form client area Dim pt0 As New Point(0, 0) 'convert from form client area (0, 0) point Dim pt As Point = PointToScreen(pt0) 'to screen coordinates g1.CopyFromScreen(pt, pt0, ClientSize) 'capture the screen desktop area below the form to the bbBmp Dim img As Image img = CaptureBmp CaptureBmp = CType(bmp.Clone, Bitmap) If img IsNot Nothing Then img.Dispose() End Using End Sub End Class



    Tuesday, November 7, 2017 6:06 PM
  • PS

    So what example 3 does is just grab the screen and then select the area you want from that bitmap. You can to that a number of ways. It does not have to be in a transparent form. You can edit it in a paint program and crop out the area you want. But we use vb. Could be another form, another picturebox etc. Could even resize it so a full screen is say half size on the form. And On and on...

    Example 3 has one problem in that it does not update the screen after the form moves. So if you are capturing a changing desktop it has to be a bit more.

    Tuesday, November 7, 2017 6:31 PM
  • Regarding other controls, is there a method keeping them completely solid while making the form background slightly opaque?

    Cheers

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

     You can use a second borderless form that uses the TransparencyKey to make it transparent.  Then use the Shown event of your Opaque form with the Panel/PictureBox on it,  to create and show the second form.  You would need to make sure you set the opaque form as the owner of the second for to make sure it stays in font of the opaque form.

     Add your controls to the second form and they will appear as though they are on the opaque form and will not be opaque.

     For a simple example which is only to show you what i am talking about.  Try it in a new form project just to see.

     Form1 code which has a PictureBox added to it.

    Public Class Form1
    
        Public Sub New()
            InitializeComponent()
            Me.FormBorderStyle = FormBorderStyle.None
            Me.WindowState = FormWindowState.Maximized
            Me.Opacity = 0.5
            Me.BackColor = Color.Black
            Me.TransparencyKey = Color.Lime
        End Sub
    
        Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
            Dim ctrlForm As New ControlForm(Me) 'use the custom contructor we added to the ControlForm to pass an instance of this form to it
            ctrlForm.Show(Me) 'set this form as the owner of the secondary ControlForm
        End Sub
    
        Public Function CaptureImage() As Bitmap
            Return If(PictureBox1.Image IsNot Nothing, CType(PictureBox1.Image, Bitmap), Nothing)
        End Function
    End Class
    
     

     Here is the 'ControlForm'  which has 2 buttons on it...

    Public Class ControlForm
        Private OwnerForm As Form1 = Nothing
    
        Public Sub New(owner As Form1) 'a custom constructor for this form which you use to pass the instance of Form1 through when Form1 creates this ControlForm
            InitializeComponent()
            Me.FormBorderStyle = FormBorderStyle.None
            Me.TransparencyKey = Color.Lime
            Me.BackColor = Color.Lime
            Me.ShowInTaskbar = False
            Me.StartPosition = FormStartPosition.Manual
            Me.Location = New Point(0, 0)
            OwnerForm = owner
        End Sub
    
        Private Sub Button_CaptureImage_Click(sender As Object, e As EventArgs) Handles Button_CaptureImage.Click
            Using bm As Bitmap = OwnerForm.CaptureImage
                Dim DeskTopFile As String = IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Captured Image.png")
                bm.Save(DeskTopFile, Imaging.ImageFormat.Png)
            End Using
        End Sub
    
        Private Sub Button_Close_Click(sender As Object, e As EventArgs) Handles Button_Close.Click
            Application.Exit()
        End Sub
    End Class
    
    
     

     Here is what it looks like...


    If you say it can`t be done then i`ll try it

    Tuesday, November 7, 2017 11:45 PM
  • Hi

    Really appreciate the time and effort in supplying some samples. I have now made a new project and my form is working ok. I had to add the Method CaptureFormRect() from a previous sample as when i tried to get the bmp from the rectangle, all i could get was the background image. Adding the Method fixed the problem.

    I added in my code to draw the additional grips and allow resizing from any of the grips along with changing the cursor depending on its position.

    What i do now is capture the rectangle image as a byte so it can be stored in a database. I can then stream it back to my picturebox using MemoryStream

    Last thing i need to do now is turn off the border & grips while taking the capture as they are captured in the image. :)

    BTW, the background form was a great idea. All of my other controls are all in a solid state while my form background 'appears' to be semi transparent.

    Cheers

    Nacho



    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, November 8, 2017 3:33 AM
  • Hi again

    It seems to be working ok with a small exception. In the earlier version, the rectangle was resized by selecting any of the grips. In this version, its very hard to select grip to resize it. My mousemove event is picking up when the mouse is over the grip and the rectangle but its a hit and miss as to whether the rectangle moves. it takes about 3 or 4 attempts to select the rectangle.

    Also

    Is there a way to dispose of the rectangle when moving? In your earlier version, the rectangle disappeared in the mousemove event then reappeared when the moving stopped. I cant see how that worked in the code version you provided. The result im getting is the orange rectangle and grips appearing in the snapshot image... I was hoping for a visible method but there isnt one...

    Other than that, its working sweet :)

    Cheers


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, November 8, 2017 9:05 AM
  • Hi again

    It seems to be working ok with a small exception. In the earlier version, the rectangle was resized by selecting any of the grips. In this version, its very hard to select grip to resize it. My mousemove event is picking up when the mouse is over the grip and the rectangle but its a hit and miss as to whether the rectangle moves. it takes about 3 or 4 attempts to select the rectangle.

    Also

    Is there a way to dispose of the rectangle when moving? In your earlier version, the rectangle disappeared in the mousemove event then reappeared when the moving stopped. I cant see how that worked in the code version you provided. The result im getting is the orange rectangle and grips appearing in the snapshot image... I was hoping for a visible method but there isnt one...

    Other than that, its working sweet :)

    Cheers


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Nacho,

    "I had to add the Method CaptureFormRect() from a previous sample as when i tried to get the bmp from the rectangle, all i could get was the background image."

    Notice in my Example 2 that has the CaptureFormRect sub there is a variable Capturing = true and then Refresh. In the Paint event when Capturing a Lime hole is drawn on the form and the background image is not. So that gives the transparent hole only when caputuring and then Capturing = False at the end of CaptureFormRect and next time we paint the captured image is drawn in the hole.

    Are you doing that?

    "Last thing i need to do now is turn off the border & grips while taking the capture as they are captured in the image."

    Yes that is why when capturing only the transparency is used on the form and when moving the mouse the entire form background is drawn on the form so there is no transparency.

    Realize in Example 2 only the fence rect was being used.

    "Is there a way to dispose of the rectangle when moving? In your earlier version, the rectangle disappeared in the mousemove event then reappeared when the moving stopped. "

    Yes dont draw them as I explained. Thats what the capturing flag is for. It is set because the mouse move event in example 2 called the captureFormRect sub which sets it.

    If you look at example 3, I dont capture the background in paint event. Only in form location changed and resize. So as I mentioned, in Example 3 the background is just captured when the form loads or moves. And in example 3 I used creategraphics in the capture sub and draw the transparent color on the form before capture, then later, in the paint event, the entire background of the form client area was captured and now drawn on the form in the paint event. Since the form is not the transparent color rather its the bitmap colors, there is no transparency.

    There is just the captured background bitmap and its not changing. So all we have to do is show the bitmap and draw on it and get mouse events on it and then capture the rect we want from it. Just like putting the background image in a paint program and cropping the rect we want.

    So Example 3 is a better way to do it. If your background is not changing that is.

    Anyway I am sure that is confusing.

    It sounds like you are not making the form transparent by drawing it lime color just before the capture.

    And then when the mouse event is sluggish or not responding you must be mixing events. Thats why I was careful, in example 2 the capturing flag tells us dont draw the rect and grips and etc in paint. In example 3 paint is not used for the capture instead only form resize. So the code is not capturing in the mouse move event.

    And finally we have a problem with many examples being mixed up and not knowing exactly what you are doing now. I named my code examples 1, 1a, 2 and 3 above please ref those. Also you should make it clear which post you are responding to I was not sure if you were referring to me or Razerz etc.

    So you will have to post a working example with your problem or we cant really help much more as we are guessing what is happening.

    :)




    • Edited by tommytwotrain Wednesday, November 8, 2017 2:05 PM
    • Marked as answer by NachoShaw Thursday, November 9, 2017 8:41 AM
    Wednesday, November 8, 2017 2:03 PM
  • Hi

    I have looked around but wasn't able to find anything. I have a form that I am filling the screen with. The form is set to 30% Opacity. On the form I have added a rectangle that I can resize. What I need to achieve is for the area INSIDE the rectangle to look through the form to the main screen contents behind very much like a cookie cutter or a hole in the form so to speak.

    Is this possible? I'm needing to take a screenshot of the contents behind using the rectangle as a frame

    Cheers

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Well that depends.

    I believe drawing a rectangle to whatever color the Forms transparency key is set to will allow the user to actively use the mouse on anything beneath the Form on the desktop when the Form is at the top of the z order.

    Therefore the requirements other than transparent area on Form are unclear.

    And transparency key issues occur depending on transparency colors used so review this thread Why couldn't the Transparencykey property work on some Win7 x32 systems?.

    Perhaps this thread Opaque Form Region w/o WPF, not specifically what you ask for, can help in some fashion.


    La vida loca

    Wednesday, November 8, 2017 5:45 PM
  • I believe drawing a rectangle to whatever color the Forms transparency key is set to will allow the user to actively use the mouse on anything beneath the Form on the desktop when the Form is at the top of the z order.

    Hi

    Well there is a nice little trick here. The area inside the capture panel is  taken as an image through the cutout and then placed into the rectangle on the mouseup event. This prevents the mouse clicking 'through' the hole onto the desktop beneath.

    Im taking another look tonight. :)

    Thanks for all of your help & TommyTwoTrain for being very informative and patient :)

    Nacho


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Wednesday, November 8, 2017 11:23 PM
  • Hi again

    Something that I cant quite figure out. When I run my form and maximize it using code, it seems to be correct and works as expected however, if I set the form to Maximize and turn off the code, I get a black screen instead of a transparent screen....

    The form is to run in full screen at all times when used but as I am maximising it by code, I get a little flash of the smaller form before it is resized which I would like to remove. I have tried everything from opening it invisible, hidden, maximised with all giving some sort of minor visual issue..

    Cheers


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Saturday, December 30, 2017 12:56 AM
  • Hi again

    Something that I cant quite figure out. When I run my form and maximize it using code, it seems to be correct and works as expected however, if I set the form to Maximize and turn off the code, I get a black screen instead of a transparent screen....

    The form is to run in full screen at all times when used but as I am maximising it by code, I get a little flash of the smaller form before it is resized which I would like to remove. I have tried everything from opening it invisible, hidden, maximised with all giving some sort of minor visual issue..

    Cheers


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Nacho,

    Well I don't know what version of code you have now. In fact it seems some of the examples, ie the last one are missing from this thread??

    I think in my last example, the only time the form was transparent was when captureing. And this was done by painting the form background black in the paint event. In the capture event the form background was set to lime the transparency key color for the form.

    So it sounds like you need to make a flag that tells you when you want full maximized screen transparency or when you want the clipping hole to be visible. When you want the full transparency, don't use the e.graphics.clear(color.black) in the paint event and set form.backgroundcolor to the transparency key color. If you don't draw the black in the pain event then you have a full lime color background and its transparent.

    If that is not making sense you need to show the code you are working with.


    Saturday, December 30, 2017 10:38 AM
  • Hi

    I'm not sure where the code went, I haven't removed it. in fact, I'm not even sure I can move it.

    i'll look at what you have suggested later tonight :)

    Thanks


    Nacho is the derivative of Nigel - True fact! I am self taught in VB.Net. 50% of the time, I am right 100% of the time!

    Saturday, December 30, 2017 11:16 PM