[RESOLVED] Maximize borderless form with transparent groupbox
Hi,
I've set Groupbox Dock.Fill on form, and placed some controls in It. Then I've set Groupbox to transparent and with a little work I got nice rounded window. However, when I maximize window I have empty space on top - that is transparent space of Groupbox which doesn't fully dock to parent as some other controls do. Is there any simple way to eliminate this empty space - like crop It in Paint or just set maximized window with a little more height?
What I've done so far is this:
Code:
Dim ScrennRect As System.Drawing.Rectangle =
Screen.PrimaryScreen.WorkingArea
Me.Size = New System.Drawing.Size(ScreenRect.Width,
ScreenRect.Height + 6)
Me.Location = New System.Drawing.Point(0, -6)
This places my window with correct size and location as It should be when maximized, but then I have to place a lot more code in different events to disable other things (moving, resizing, cursors etc.), so I don't like It.
Screenshot of current situation is attached. Any help appreciated.
Last edited by LuckyLuke82; Feb 9th, 2017 at 04:21 PM.
Re: Maximize borderless form with transparent groupbox
Originally Posted by LuckyLuke82
that is transparent space of Groupbox which doesn't fully dock to parent as some other controls do.
But the GroupBox DOES "fully dock" to it's parent, just like other controls. The fact of the matter is that the group border that the control draws is not at the top of the control. If what you actually want is a control with a rounded border where that border is at the edge of the control then it sounds like you should just be using a Panel with a custom-drawn border.
Re: Maximize borderless form with transparent groupbox
The fact of the matter is that the group border that the control draws is not at the top of the control.
Yes, I only couldn't express myself correctly.
If what you actually want is a control with a rounded border where that border is at the edge of the control then it sounds like you should just be using a Panel with a custom-drawn border.
Well, I have tried with custom rounded forms & rounded panel, but I don't know much about graphics and then I had much problems with resizing and moving, and haven't found any short or simple solution for this. For example, I tried this code which nicely draws rounded corner Panel (https://www.experts-exchange.com/que...thin-form.html) an this are results of resizing and maximizing It:
Groupbox as I created has no problems with resizing & moving & draws nice rounded & transparent border. Do you have maybe any suggestions for custom drawn border of Panel which can maximized and resized simply ?
Last edited by LuckyLuke82; Feb 10th, 2017 at 01:34 AM.
Re: Maximize borderless form with transparent groupbox
I agree, use a panel. Your problem is that the control isn't automatically redrawn when the form is resized, so you have to take action to trigger repainting. The first (and simplest) thing to try is to put Me.ResizeRedraw = True in the form's Load sub.
Another widely used way of triggering repainting is to Invalidate the form or control concerned, for example Me.Invalidate.
Explanation: The basic idea of graphics for Forms projects (aka. GDI+ graphics) is:
1. Use the Paint event to specify HOW to draw something. But this doesn't itself trigger repainting of the screen.
2. Invalidate the form or other control WHEN you need to redraw. ResizeRedraw does that automatically. The effect is to trigger repainting of the screen as described in the Paint event handler. Typically you call Me.Invalidate from an event handler like MouseMove or SizeChanged, depending on what you are doing.
Re: Maximize borderless form with transparent groupbox
Explanation: The basic idea of graphics for Forms projects (aka. GDI+ graphics) is:
1. Use the Paint event to specify HOW to draw something. But this doesn't itself trigger repainting of the screen.
2. Invalidate the form or other control WHEN you need to redraw. ResizeRedraw does that automatically. The effect is to trigger repainting of the screen as described in the Paint event handler. Typically you call Me.Invalidate from an event handler like MouseMove or SizeChanged, depending on what you are doing.
Thanks for the explanation, I needed this, I'm still learning a lot about graphics. I'm testing bunch of things now (including panels), and what I've camed across is this:
Code:
<DllImport("Gdi32.dll", EntryPoint:="CreateRoundRectRgn")>
Private Shared Function CreateRoundRectRgn(nLeftRect As Integer, nTopRect As Integer, nRightRect As Integer, nBottomRect As Integer, nWidthEllipse As Integer, nHeightEllipse As Integer) As IntPtr
' width of ellipse
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.ResizeRedraw = True
End Sub
Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles Me.Resize
Region = System.Drawing.Region.FromHrgn(CreateRoundRectRgn(0, 0, Width, Height, 2, 2))
End Sub
It's a function which draws corner to form. As you can see this is very short code, so I like It a lot. Only problem with this code is that when you dock some control in form (like Split Container) re-drawing borders of form don't work anymore. Is there a way I could draw boders too ? - that migh solve all my problems.
Re: Maximize borderless form with transparent groupbox
The trouble with Gdi32.dll functions like CreateRoundRectRgn is that they do a highly specific job but are inflexible. In this case it doesn't provide a way to vary the shape, or to draw a border line.
As an alternative to what you have been doing, I'd like to suggest using a GraphicsPath to create the rounded rectangle instead of either a GroupBox or a Panel. Among the advantages of a GraphicsPath are that you could in theory make it almost any shape you want, including text; and you can use it to draw an outline as well as to fill a shape.
Using the Region property to crop the shape of a form or other control is a useful method to know about. It does basically the same job as TransparencyKey, but with a predefined shape instead of a colour. However, the border then has to go exactly inside the region, and it's hard to get it to line up exactly inside the edge. So I suggest you continue using TransparencyKey for the while.
Here's a ready-to-run code example using a GraphicsPath function. For testing purposes, click the form to alternate between maximized and normal size. You should test this (and any other method) against a dark background as well as a light one, to make sure there are no messy pixels around the edge. Set the CornerRadius property to whatever value you prefer.
Code:
Public Class Form1
Public Property CornerRadius As Integer = 10
Private Function RoundedRectanglePath(ByVal rect As Rectangle, ByVal radius As Integer) As Drawing2D.GraphicsPath
Dim gp As New Drawing2D.GraphicsPath
gp.AddArc(rect.Left, rect.Top, radius * 2, radius * 2, 180, 90) 'top left corner
gp.AddArc(rect.Right - radius * 2, rect.Top, radius * 2, radius * 2, 270, 90) 'top right corner
gp.AddArc(rect.Right - radius * 2, rect.Bottom - radius * 2, radius * 2, radius * 2, 0, 90) 'bottom right corner
gp.AddArc(rect.Left, rect.Bottom - radius * 2, radius * 2, radius * 2, 90, 90) 'bottom left corner
gp.CloseFigure() 'join up the corners with straight lines.
Return gp
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.None
Me.BackColor = Color.Lime
Me.TransparencyKey = Color.Lime
Me.ResizeRedraw = True
End Sub
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
Dim rect As Rectangle = New Rectangle(0, 0, Me.Width - 1, Me.Height - 1)
Dim borderPath = RoundedRectanglePath(rect, CornerRadius)
e.Graphics.FillPath(Brushes.Aqua, borderPath)
e.Graphics.DrawPath(Pens.Black, borderPath)
End Sub
'For testing purposes only:
Private Sub Form1_Click(sender As Object, e As EventArgs) Handles Me.Click
Static maximize As Boolean = False
maximize = Not maximize
If maximize Then Me.WindowState = FormWindowState.Maximized Else Me.WindowState = FormWindowState.Normal
End Sub
End Class
By the way, I'm not suggesting that this approach is ideal. There is almost nothing you can do about having either aliasing (roughness) at the rounded corners or showing false-coloured pixels against certain backgrounds (even worse). It's a limitation of the GDI+ drawing technology used in Windows Forms. If you have time, you may like to try out the Shaped Form link in my sig. below, which illustrates the much better drawing quality obtainable in WPF.
BB
Last edited by boops boops; Feb 10th, 2017 at 08:29 PM.
Re: Maximize borderless form with transparent groupbox
The trouble with Gdi32.dll functions like CreateRoundRectRgn is that they do a highly specific job but are inflexible. In this case it doesn't provide a way to vary the shape, or to draw a border line.
Well there is actually a trick I tried and It works, It got me to desired output result. What you need to do is only to adjust form Padding to shrink Parent control a bit (docked Split container in my case). Then you can still draw border to form.
Currently I'm testing everything I find online and I see there are many different varieties you can do. As noted by others, WPF is the best when It comes to create whatever you wish, but I've never done anything in WPF so far (but will probably try something in future).
Thanks for all your help, you opened my mind a lot. I'll probably attach an example of form's I'm dealing with next time, some of them really turned up nice (but that just my taste ).
Re: [RESOLVED] Maximize borderless form with transparent groupbox
Here, some examples of custom forms (I had more but deleted most of them because codes were just too long). What I like mostly is "Round form", but I want It with same glowing effect as Form1 has. I tried allready but when "Round form" loses focus It loses glowing effect too. If someone knows how I could fix this, please let me know.
Last edited by Shaggy Hiker; Feb 11th, 2017 at 06:34 PM.
Reason: Removed attachment.
Re: [RESOLVED] Maximize borderless form with transparent groupbox
I had to remove the attachment because it contained compiled code, which this forum does not accept. This can be remedied by deleting the bin and obj folders and creating re-uploading. Those folders aren't useful anyways, since they will be recreated automatically by VS when you build the project.
Re: [RESOLVED] Maximize borderless form with transparent groupbox
Originally Posted by Shaggy Hiker
I had to remove the attachment because it contained compiled code, which this forum does not accept. This can be remedied by deleting the bin and obj folders and creating re-uploading. Those folders aren't useful anyways, since they will be recreated automatically by VS when you build the project.
O.K., I didn't know that, It's my 1st post of project on this forum. Is It good now ?
P.S.: About attachments I've allready uploaded in past - can I delete them from "Manage attachments" ?
Imports System.Runtime.InteropServices
Public Class Form1
'Variables for shadow effect
Public aeroEnabled As Boolean
#Region "Buttons and Labels"
Private Sub Label2_Click(sender As Object, e As EventArgs) Handles Label2.Click
Me.Close()
End Sub
Private Sub Label3_Click(sender As Object, e As EventArgs) Handles Label3.Click
If Me.WindowState = FormWindowState.Maximized Then
Me.WindowState = FormWindowState.Normal
Else
Me.WindowState = FormWindowState.Maximized
End If
End Sub
Private Sub Label4_Click(sender As Object, e As EventArgs) Handles Label4.Click
Me.WindowState = FormWindowState.Minimized
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Round_Form.Show()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Round_Panel.Show()
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Groupbox_Form.Show()
End Sub
#End Region
#Region "Shadow effect"
Private Sub CheckAeroEnabled()
If Environment.OSVersion.Version.Major >= 6 Then
Dim enabled As Integer = 0
Dim response As Integer = NativeMethods1.DwmIsCompositionEnabled(enabled)
aeroEnabled = (enabled = 1)
Else
aeroEnabled = False
End If
End Sub
Protected Overrides ReadOnly Property CreateParams() As CreateParams
Get
CheckAeroEnabled()
Dim cp As CreateParams = MyBase.CreateParams
If Not aeroEnabled Then
cp.ClassStyle = cp.ClassStyle Or NativeConstants.CS_DROPSHADOW
Return cp
Else
Return cp
End If
End Get
End Property
Protected Overrides Sub WndProc(ByRef m As Message)
Select Case m.Msg
'Shadowing
Case NativeConstants.WM_NCPAINT
Dim val = 2
If aeroEnabled Then
NativeMethods1.DwmSetWindowAttribute(Handle, 2, val, 4)
Dim bla As New NativeStructs.MARGINS()
With bla
.bottomHeight = 1
.leftWidth = 1
.rightWidth = 1
.topHeight = 1
End With
NativeMethods1.DwmExtendFrameIntoClientArea(Handle, bla)
End If
Case Else
MyBase.WndProc(m)
End Select
End Sub
#End Region
#Region "Resize / Move Borderless Form"
'Based on code by NickThissen, http://www.vbforums.com/showthread.php?568015
'Width of the 'resizable border', the area where you can resize.
Private Const BorderWidth As Integer = 6
Private _resizeDir As ResizeDirection = ResizeDirection.None
Private Const WM_NCLBUTTONDOWN As Integer = &HA1
Private Const HTBORDER As Integer = 18
Private Const HTBOTTOM As Integer = 15
Private Const HTBOTTOMLEFT As Integer = 16
Private Const HTBOTTOMRIGHT As Integer = 17
Private Const HTCAPTION As Integer = 2
Private Const HTLEFT As Integer = 10
Private Const HTRIGHT As Integer = 11
Private Const HTTOP As Integer = 12
Private Const HTTOPLEFT As Integer = 13
Private Const HTTOPRIGHT As Integer = 14
<DllImport("user32.dll")>
Private Shared Function ReleaseCapture() As Boolean
End Function
<DllImport("user32.dll")>
Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function
Private Enum ResizeDirection
None = 0
Left = 1
TopLeft = 2
Top = 3
TopRight = 4
Right = 5
BottomRight = 6
Bottom = 7
BottomLeft = 8
End Enum
Private Property resizeDir() As ResizeDirection
Get
Return _resizeDir
End Get
Set(ByVal value As ResizeDirection)
_resizeDir = value
Select Case value 'Change cursor
Case ResizeDirection.Left
Me.Cursor = Cursors.SizeWE
Case ResizeDirection.Right
Me.Cursor = Cursors.SizeWE
Case ResizeDirection.Top
Me.Cursor = Cursors.SizeNS
Case ResizeDirection.Bottom
Me.Cursor = Cursors.SizeNS
Case ResizeDirection.BottomLeft
Me.Cursor = Cursors.SizeNESW
Case ResizeDirection.TopRight
Me.Cursor = Cursors.SizeNESW
Case ResizeDirection.BottomRight
Me.Cursor = Cursors.SizeNWSE
Case ResizeDirection.TopLeft
Me.Cursor = Cursors.SizeNWSE
Case Else
Me.Cursor = Cursors.Default
End Select
End Set
End Property
Private Sub ResizeForm(ByVal direction As ResizeDirection)
Dim dir As Integer = -1
Select Case direction
Case ResizeDirection.Left
dir = HTLEFT
Case ResizeDirection.TopLeft
dir = HTTOPLEFT
Case ResizeDirection.Top
dir = HTTOP
Case ResizeDirection.TopRight
dir = HTTOPRIGHT
Case ResizeDirection.Right
dir = HTRIGHT
Case ResizeDirection.BottomRight
dir = HTBOTTOMRIGHT
Case ResizeDirection.Bottom
dir = HTBOTTOM
Case ResizeDirection.BottomLeft
dir = HTBOTTOMLEFT
End Select
If dir <> -1 Then
' Resize form
ReleaseCapture()
SendMessage(Me.Handle, WM_NCLBUTTONDOWN, dir, 0)
Else
' Move Form
ReleaseCapture()
SendMessage(Me.Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0)
End If
End Sub
Private Sub Form1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseDown
If e.Button = MouseButtons.Left AndAlso Me.WindowState <> FormWindowState.Maximized Then
ResizeForm(resizeDir) 'allow form resize and moving.
End If
End Sub
Private Sub Form1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles MyBase.MouseMove
If Me.WindowState = FormWindowState.Maximized Then Return
'Calculate which direction to resize based on mouse position
If e.Location.X < BorderWidth And e.Location.Y < BorderWidth Then
resizeDir = ResizeDirection.TopLeft
ElseIf e.Location.X < BorderWidth And e.Location.Y > Me.Height - BorderWidth Then
resizeDir = ResizeDirection.BottomLeft
ElseIf e.Location.X > Me.Width - BorderWidth And e.Location.Y > Me.Height - BorderWidth Then
resizeDir = ResizeDirection.BottomRight
ElseIf e.Location.X > Me.Width - BorderWidth And e.Location.Y < BorderWidth Then
resizeDir = ResizeDirection.TopRight
ElseIf e.Location.X < BorderWidth Then
resizeDir = ResizeDirection.Left
ElseIf e.Location.X > Me.Width - BorderWidth Then
resizeDir = ResizeDirection.Right
ElseIf e.Location.Y < BorderWidth Then
resizeDir = ResizeDirection.Top
ElseIf e.Location.Y > Me.Height - BorderWidth Then
resizeDir = ResizeDirection.Bottom
Else
resizeDir = ResizeDirection.None
End If
End Sub
#End Region
End Class
Last edited by Edgemeal; Feb 12th, 2017 at 10:09 AM.
Re: [RESOLVED] Maximize borderless form with transparent groupbox
Originally Posted by LuckyLuke82
P.S.: About attachments I've allready uploaded in past - can I delete them from "Manage attachments" ?
Yes, looks good.
As for editing/deleting attachments, I believe you can, but I'm not certain. Some features are only acquired after you reach a certain number of posts. One of those thresholds is 5, and you're well past that. Another is 2048, and you've got a ways to go to get there. I'm pretty sure that you should be able to edit attachments at almost any point, because it's something that people would likely want to do. However, I just don't know.
Re: [RESOLVED] Maximize borderless form with transparent groupbox
Originally Posted by Edgemeal
Looks pretty good! FWIW If you want to resize a borderless form maybe look at this thread, http://www.vbforums.com/showthread.php?568015
I mod your form1 code using that idea.
[/CODE]
Thanks Edgemeal, but I allready have this code, I just didn't include It in this project because I focused only on drawing borders and shadows ... However I found many other examples with shorter codes for resizing form. But I need to resize controls too, so I also use this code - much better than dealing with all x's and y's manually
Last edited by LuckyLuke82; Feb 12th, 2017 at 02:33 PM.
Re: [RESOLVED] Maximize borderless form with transparent groupbox
Originally Posted by Shaggy Hiker
As for editing/deleting attachments, I believe you can, but I'm not certain. Some features are only acquired after you reach a certain number of posts. One of those thresholds is 5, and you're well past that. Another is 2048, and you've got a ways to go to get there. I'm pretty sure that you should be able to edit attachments at almost any point, because it's something that people would likely want to do. However, I just don't know.
Thanks, I asked that only because I still see some attachments which were replaced in threads (added by mistake or not correctly) and looks like they are uploaded somewhere, for no reason.