I have a mdi container form that when it opens a child inside I get this double title bar with another set of close/minimize/maximize buttons and the form icon. How can I get rid of it? I've tried setting Control to false but it does not work. FormBorderStyle to none also does not work and it deforms the child form.
Also, I have a toolstrip that contains some buttons and it has this annoying border looking line at the bottom (check out the blue arrow I drew). How can I disable that aswell?
First Part
For the first part of your question, the workaround posted here by Mr. #RezaAghaei could be the answer. Here's the VB.NET version:
Public Class YourParentForm
'Or drop one in the designer...
Private ReadOnly ContainerPanel As Panel
Sub New()
InitializeComponent()
IsMdiContainer = False
ContainerPanel = New Panel With {.Dock = DockStyle.Fill}
Controls.Add(ContainerPanel)
End Sub
End Class
And where you create the child Form:
Dim f As New ChildForm With
{
.FormBorderStyle = FormBorderStyle.None,
.TopLevel = False,
.ControlBox = False,
.Dock = DockStyle.Fill,
}
ContainerPanel.Controls.Add(f)
f.Show()
Since the last inserted control into the collection is docked first, you need to explicitly set the order of the controls to avoid any possible dock overlapping. So as you noticed and mentioned in your comment, the Dock.Fill Form is overlapping the Dock.Top Label. To fix that:
Dim f As New ChildForm With
{
.FormBorderStyle = FormBorderStyle.None,
.TopLevel = False,
.ControlBox = False,
.Dock = DockStyle.Fill
}
ContainerPanel.Controls.Add(f)
Controls.SetChildIndex(ContainerPanel, 0)
Controls.SetChildIndex(Label1, 1)
f.Show()
In fact you can omit Controls.SetChildIndex(Label1, 1), just added to clear up the idea.
If you'r using the designer to add the ContainerPanel, select it and right click, you will see in the context menu Bring to Front and Send to Back which are used to do the same thing. Also, you can use the Document Outline window (Ctrl + T to show it) to change the order of the controls using the up/down arrows and the left/right arrows to move controls to different containers.
Second Part
As for the second part, you need to create a new class that inherits the ProfessionalColorTable and override the ToolStripBorder property to prevent it from returning the default color when rendering the ToolStrip:
Public Class CustomColorTable
Inherits ProfessionalColorTable
Public Overrides ReadOnly Property ToolStripBorder As Color
Get
Return Color.Empty
End Get
End Property
End Class
Then, pass the custom color table to a new instance of the ToolStripProfessionalRenderer class and assign it to the ToolStrip.Renderer or the ToolStripManager.Renderer properties.
Revisiting the constructor of the parent Form:
Sub New()
InitializeComponent()
ContainerPanel = New Panel With {.Dock = DockStyle.Fill}
Controls.Add(ContainerPanel)
ToolStrip1.Renderer = New ToolStripProfessionalRenderer(New CustomColorTable) With {
.RoundedEdges = False
}
'Or
'ToolStripManager.Renderer = New ToolStripProfessionalRenderer(New CustomColorTable) With {
' .RoundedEdges = False
'}
End Sub
Related
Could someone please tell me how to select a control programmatically in design mode.
I tried to create a custom user control in VB.net that consists of two panels.
I want the whole user control to be easily selectable in design mode.
I have included the following sample and tried.
I was able to identify the selected control but can't SELECT it.
I am using visual studio 2015 / windows 10 Pro.
1.Make Project
New Project -> Windows Forms application
-> name : sample -> [OK]
2.Add User Control
Add -> New Item -> User Control -> Name : usrPanel.vb -> [Add]
usrPanel.BorderStyle : FixedSingle
3.Add 2 Panel controls on usrPanel
Add Panel control on usrPanel
name : pnlTitle
pnlTitle.Dock : Top
pnlTitle.BackColor : Maroon
Add one more Panel
name : pnlMain
pnlMain.Dock : Full
4.Modify usrPanel.vb like this
Imports System.ComponentModel
Imports System.Windows.Forms.Design
Imports System.Windows.Forms.Design.Behavior
<Designer(GetType(usrPanelDesigner))>
Public Class usrPanel
End Class
Public Class usrPanelDesigner
Inherits ParentControlDesigner
Private myAdorner As Adorner
Public Overrides Sub Initialize(component As IComponent)
MyBase.Initialize(component)
If (TypeOf MyBase.Control Is usrPanel) Then
MyBase.EnableDesignMode(DirectCast(MyBase.Control, usrPanel).pnlTitle, "Title")
MyBase.EnableDesignMode(DirectCast(MyBase.Control, usrPanel).pnlMain, "Main")
End If
myAdorner = New Adorner()
BehaviorService.Adorners.Add(myAdorner)
myAdorner.Glyphs.Add(New MyGlyph(BehaviorService, Control))
End Sub
End Class
5.Paste this entire sample below.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.design.behavior.behavior?redirectedfrom=MSDN&view=netcore-3.1
Class MyGlyph
Inherits Glyph
Private control As Control
Private behaviorSvc As _
System.Windows.Forms.Design.Behavior.BehaviorService
Public Sub New(ByVal behaviorSvc As _
System.Windows.Forms.Design.Behavior.BehaviorService, _
ByVal control As Control)
MyBase.New(New MyBehavior())
Me.behaviorSvc = behaviorSvc
Me.control = control
End Sub
Public Overrides ReadOnly Property Bounds() As Rectangle
Get
' Create a glyph that is 10x10 and sitting
' in the middle of the control. Glyph coordinates
' are in adorner window coordinates, so we must map
' using the behavior service.
Dim edge As Point = behaviorSvc.ControlToAdornerWindow(control)
Dim size As Size = control.Size
Dim center As New Point(edge.X + size.Width / 2, edge.Y + _
size.Height / 2)
Dim bounds1 As New Rectangle(center.X - 5, center.Y - 5, 10, 10)
Return bounds1
End Get
End Property
Public Overrides Function GetHitTest(ByVal p As Point) As Cursor
' GetHitTest is called to see if the point is
' within this glyph. This gives us a chance to decide
' what cursor to show. Returning null from here means
' the mouse pointer is not currently inside of the glyph.
' Returning a valid cursor here indicates the pointer is
' inside the glyph,and also enables our Behavior property
' as the active behavior.
If Bounds.Contains(p) Then
Return Cursors.Hand
End If
Return Nothing
End Function
Public Overrides Sub Paint(ByVal pe As PaintEventArgs)
' Draw our glyph. It is simply a blue ellipse.
pe.Graphics.FillEllipse(Brushes.Blue, Bounds)
End Sub
' By providing our own behavior we can do something interesting
' when the user clicks or manipulates our glyph.
Class MyBehavior
Inherits System.Windows.Forms.Design.Behavior.Behavior
Public Overrides Function OnMouseUp(ByVal g As Glyph, _
ByVal button As MouseButtons) As Boolean
MessageBox.Show("Hey, you clicked the mouse here")
Return True
' indicating we processed this event.
End Function 'OnMouseUp
End Class
End Class
6.After Mouse Clidk I want to select the specified panel
in Design Mode
MessageBox.Show("Hey, you clicked the mouse here")
Change
'MessageBox.Show("Hey, you clicked the mouse here")
Dim myg As MyGlyph = CType(g, MyGlyph)
Dim c As Control = myg.control
c.Select()
c.Focus()
7.Build All
8.Add usrPanel control on Form1
usrPanel was displayed
click header of usrPanel -> header SELECTED
click blue point -> nothing happens
click the right edge of the usrPanel -> The entire panel is SELECTED
How do I get the usrPanel to be SELECTED when the blue point is clicked?
WinForm Designer code is all about using designer services. In this case you need to acquire an instance of the selection service that is manifested through an object that implements the ISelectionService Interface.
You acquire a service instance through an object that implements the IServiceProvider Interface. The Control.Site Property implements the ISite Interface that in turn implements IServiceProvider.
Use the IServiceProvider.GetService(Type) Method to acquire the service and then use the ISelectionService.SetSelectedComponents Method to select the desired component(s).
Public Overrides Function OnMouseUp(g As Glyph, button As MouseButtons) As Boolean
Dim myg As MyGlyph = CType(g, MyGlyph)
Dim c As Control = myg.control
Dim selService As ISelectionService = CType(c.Site.GetService(GetType(ISelectionService)), ISelectionService)
selService?.SetSelectedComponents({c})
Return True
End Function
I have one form and I want it to be fullscreen, but taskbar should be still visible. And I want it to have one Panel on it, whose borders are 10px away from form borders
I tried hundreds of combinations, and I simply can't achieve this.
here's my code
Public Class Form1
Sub New()
InitializeComponent()
WindowState = FormWindowState.Maximized
Size = New Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height)
Dim p1 As New Panel()
p1.Location = New Point(10, 10)
p1.Size = New Size(ClientSize.Width - 20, ClientSize.Height - 20)
p1.BackColor = Color.Blue
Controls.Add(p1)
End Sub
End Class
what I want: http://i.imgur.com/4BxoBeh.png
what I get: http://i.imgur.com/QynIdaU.png
I would take an entirely different approach where there is no need to calculate anything:
WindowState = FormWindowState.Maximized
Size = New Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height)
Padding = New Padding(10)
Dim p1 As New Panel()
p1.Location = New Point(0, 0)
p1.Dock = DockStyle.Fill
p1.BackColor = Color.Blue
Controls.Add(p1)
Your calculation is correct for a form that takes entire screen but is not maximized, which you can see by unmaximizing it as soon as it appears. The reason is that you are observing the form sizes from the constructor which is a bit too early (namely, even though you are setting WindowState = FormWindowState.Maximized before everything else, ClientSize still has values corresponding to non-maximized window because the window has not yet been created and shown). If you move your original code to e.g. a Form.Load handler it will give the opposite result - looking correct when the form is maximized and incorrect if not.
The padding approach works as expected in all cases.
I am trying to create a document writer in vb.net
So I decided to add a tab control, so I can create a new tab when I press a button. I would like to save the text in the tab that is open. I created a function the returns the text depending on what tab is open, but that only works for the two default tabs. I don't know how I would save if I've created a new tab.
The function to get the text is this:
Public Function getText() As String
If tabPage1.Visible = True Then
Return mainText.Text
ElseIf tabPage2.Visible = True Then
Return textBox1.Text
End If
End Function
I've done some research online, I've even looked at SharpDevelop's source code and I couldn't find anything.
Thanks in advance!
EDIT :
Public Sub setText(Byval value As String)
If tabPage1.Visible = True Then
mainText.Text = value
ElseIf tabPage2.Visible = True Then
textBox1.Text = value
End If
End Sub
Does anyone know how I would do an open feature determined on what tab is open (as before.)
If I understand you correctly, you are trying to have a textbox in each of your tabPages generated dynamically. If this is the case you could generalize your GetText function with this code
Function GetText() As String
If tabControl1.SelectedTab IsNot Nothing Then
Return tabControl1.SelectedTab.Controls.OfType(Of TextBox)().First().Text
End If
End Function
This requires that you have at least one textbox in each page (and your TabControl is named tabControl1). The SelectedTab property (if not nothing) is the current tabPage displayed by your tabControl
I have many buttons in my app, and some of them are disabled in various circumstances. The problem is, buttons "look wrong" when .Enabled = False
What follows is an example of a list of properties which may be similarly applied to all buttons.
.BackColor = Color.Goldenrod
.Flatstyle = FlatStyle.Flat
.FlatAppearance.MouseOverBackColor = Color.White
.FlatAppearance.BorderSize = 0
.BackgroundImageLayout = ImageLayout.Stretch
.BackGroundImage = My.Resources.Resources.ButtonFade 'This image is translucent, giving the rounded 3D look as shown below.
.ForeColor = Color.Black
.Image = My.Resources.Resources.refresh 'May be other images.
.Text = "RELOAD"
The .BackColor property may be all kinds of colors, as set by the user via a "theme".
To illustrate my concern, below is a screenshot of three buttons. "NEW" is enabled. "SAVE" is disabled. Although "NEW" AND "SAVE" look similar, "SAVE" is washed out with low contrast colors for the text and image.
I'd like all disabled buttons to look more like "RELOAD". That is, I would like the text and image to remain solid black, for better legibility, but I can set BackgroundImage = Nothing so it won't look 3D. (To the user, the model is "If it isn't 3D, it's not clickable.") I will probably also modify the background color of disabled buttons, but that part is easy. I just need the system to stop "greying out" the text and image when I set Enabled = False.
To get this screenshot, "RELOAD" is actually enabled, but I've removed its background image. Problem is, it can still be clicked.
How can I get the look I'm looking for?
You cannot achieve what you want by using the Enabled property, the Button class implements the Windows GUI style guide that disabled controls should look disabled by graying out their appearance. A further restriction is that the button renderers cannot be tinkered with, they are not overridable.
You need to achieve your goal by making the control act disabled. Add a new class to your project and paste the code shown below. Compile. Drag the new control from the top of the toolbox to your form, replacing the existing button controls. Set the Disabled property to True in your code when you want to disable the button. You probably want to tinker with the code that changes the appearance.
Imports System.ComponentModel
Public Class MyButton
Inherits Button
<DefaultValue(False)> _
Public Property Disabled As Boolean
Get
Return IsDisabled
End Get
Set(value As Boolean)
If Value = IsDisabled Then Return
IsDisabled = Value
MyBase.SetStyle(ControlStyles.Selectable, Not IsDisabled)
If IsDisabled And Me.Focused Then Me.Parent.SelectNextControl(Me, True, True, True, True)
'' Change appearance...
If IsDisabled Then
Me.FlatStyle = Windows.Forms.FlatStyle.Flat
Else
Me.FlatStyle = Windows.Forms.FlatStyle.Standard
End If
End Set
End Property
Protected Overrides Sub OnMouseEnter(e As EventArgs)
If Not IsDisabled Then MyBase.OnMouseEnter(e)
End Sub
Protected Overrides Sub OnMouseDown(mevent As MouseEventArgs)
If Not IsDisabled Then MyBase.OnMouseDown(mevent)
End Sub
Protected Overrides Sub OnKeyDown(kevent As KeyEventArgs)
If Not IsDisabled Then MyBase.OnKeyDown(kevent)
End Sub
Private IsDisabled As Boolean
End Class
The way i do it in c (is way more powerfull for extreme gui stuff. This example is trivial!) to override the disabled state and draw my image (in c):
NMHDR *nmr;
NMCUSTOMDRAW *nmcd;
case WM_NOTIFY:
nmr = (NMHDR *)lParam;
nmcd = (NMCUSTOMDRAW *)lParam;
if(nmr->idFrom == IDC_BUTTON && nmr->code == NM_CUSTOMDRAW){
if(nmcd->dwDrawStage == CDDS_PREERASE){
if(nmcd->uItemState & 0x1) {StretchBlt(nmcd->hdc,...);} //Down
else if(nmcd->uItemState & 0x40){StretchBlt(nmcd->hdc,...);} //Enter
else if(nmcd->uItemState & 0x4) {StretchBlt(nmcd->hdc,...);} //Disable
else {StretchBlt(nmcd->hdc,...);} //Leave
return CDRF_SKIPDEFAULT;
}
}
break;
The WM_NOTIFY is sent to your main form so you can catch it. The nmcd->hdc
is your button hdc, and you draw on it your image depending on the state (Down, Enter,
Disable or Leave). I know it is difficult to write vb from c but you have a start point if you are patient enough.
Valter
I am looking for a way to design things differently in my project. Instead of using TabControls I wish to use Buttons (Instead of pressing the tabs on the top I would like to press the Buttons on the left-side). These buttons when pressed they have their own Panel where each has their own respective content.
Select Case tabAdmin.SelectedIndex
Case 0
If txtCode_Patient.Text = "" Then
txtCode_Patient.Focus()
Else
cmdAdminister.Focus()
End If
Case 1
If txtD_Patient.Text = "" Then
txtD_Patient.Focus()
Else
cmdRefresh.Focus()
End If
Case 2
If txtI_Patient.Text = "" Then
txtI_Patient.Focus()
Else
cmdI_CUser.Focus()
End If
Case 3
If txtStat_CS.Text = "" Then
txtStat_CS.Focus()
Else
cmdStat_Refresh.Focus()
End If
End Select
The code above is similar to what my project acts and it works with TabControls. I want to do a similar thing but this time, like I said before, pressing Buttons on the left-side. How can I do a similar thing ?
UPDATE:
I found a way for this one but now my concern is how do I make it look like one of its default button 3D look-alike?
Public Class Tab
Inherits TabControl
Private Property DoubledBuffered As Boolean
Sub New()
SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint, True)
DoubledBuffered = True
SizeMode = TabSizeMode.Fixed
ItemSize = New Size(30, 110)
End Sub
Protected Overrides Sub CreateHandle()
MyBase.CreateHandle()
Alignment = TabAlignment.Left
End Sub
Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
Dim B As New Bitmap(Width, Height)
Dim G As Graphics = Graphics.FromImage(B)
G.Clear(Color.AliceBlue)
For i = 0 To TabCount - 1
Dim TabRectangle As Rectangle = GetTabRect(i)
If i = SelectedIndex Then
'//Selected
G.FillRectangle(Brushes.DarkSlateGray, TabRectangle)
Else
'//Not Selected
G.FillRectangle(Brushes.AntiqueWhite, TabRectangle)
End If
G.DrawString(TabPages(i).Text, Font, Brushes.Black, TabRectangle, New StringFormat With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center})
Next
e.Graphics.DrawImage(B.Clone, 0, 0)
G.Dispose() : B.Dispose()
MyBase.OnPaint(e)
End Sub
End Class
Use the CheckBox control instead of Button, but set Appearance = Button, that way it looks exactly like a button can remains in the "pressed" state when clicked.
To shift between content, put each of your sub-forms into their own UserControl instances, then host them within a Panel control, then switch the .Visibility property of each sub-form according to which CheckBox was clicked.
There is an Outlook-style side bar available on Code Project. It has a VB version as well as C# and although it's knocking on a bit now, you could always adapt this to look a bit nicer. I have used it in the past and it worked pretty well as I recall.
You can set the selected tab via tabAdmin.SelectedIndex = 0 (or 1, 2, etc, but remember it is 0 based)
You may also set the tab by the tab's name via tabAdmin.SelectedTab = TabName
Use a common click event handler for the buttons. Store the relevant tabindex in the Tag property of the buttons. Then tabAdmin.SelectedIndex equals the tag of the clicked button cast as integer.