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.
Related
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
I'm working on a VB.NET 4.5 project in VS2013.
I have a richtextbox on a form and when a button is clicked I need to toggle the BOLD setting on all instances of a specific string found in the richtextbox.
I put together some code based on this question.
Private Sub ToggleBold()
rtxtOutputText.SelectionStart = rtxtOutputText.Find("##$%", RichTextBoxFinds.None)
rtxtOutputText.SelectionFont = New Font(rtxtOutputText.Font, FontStyle.Bold)
End Sub
However when the toggle bold button is clicked it only bolds the first instance of the string "##$%".
How can I set all instances of the string to bold? There can also be several of them strung together ("##$%##$%##$%"), so each of those would need to be bolded too.
(I know I mentioned toggling bold, but I'll set up the toggle portion later, right now I'm just trying to get the bold on all instances working right...)
Just add a loop to it and use the RichTextBox.Find(String, Int32, RichTextBoxFinds) overload to specify from where to start looking. Look from the current index + 1 so that it doesn't return the same again.
You also ought to actually select the word as well, so that you're sure the bold applies to the current instance only and not the text around it.
Private Sub ToggleBold()
'Stop the control from redrawing itself while we process it.
rtxtOutputText.SuspendLayout()
Dim LookFor As String = "##$%"
Dim PreviousPosition As Integer = rtxtOutputText.SelectionStart
Dim PreviousSelection As Integer = rtxtOutputText.SelectionLength
Dim SelectionIndex As Integer = -1
Using BoldFont As New Font(rtxtOutputText.Font, FontStyle.Bold)
While True
SelectionIndex = rtxtOutputText.Find(LookFor, SelectionIndex + 1, RichTextBoxFinds.None)
If SelectionIndex < 0 Then Exit While 'No more matches found.
rtxtOutputText.SelectionStart = SelectionIndex
rtxtOutputText.SelectionLength = LookFor.Length
rtxtOutputText.SelectionFont = BoldFont
End While
End Using
'Allow the control to redraw itself again.
rtxtOutputText.ResumeLayout()
'Restore the previous selection.
rtxtOutputText.SelectionStart = PreviousPosition
rtxtOutputText.SelectionLength = PreviousSelection
End Sub
Credit to Plutonix for telling me to dispose the font.
Call me crazy but for the life of me I cannot make this work. I have the following code:
Dim cControl As Control
For Each cControl In Me.Controls
If (TypeOf cControl Is Button) Then
cControl.ForeColor = Color.Black
cControl.Font = New Font(cControl.Font, FontStyle.Regular)
End If
Next cControl
Me.ActiveControl.ForeColor = Color.Blue
Me.ActiveControl.Font = New Font(Me.ActiveControl.Font, FontStyle.Bold)
I am trying to make the font black and regular for all of the buttons on the form (there are a lot) and the button just clicked, bolded and blue.
The second part of the code works (making the font bold and blue), it's the first that is not simply working.
What am I missing?
I've never tried it like that before, but I have used Linq to accomplish what you want.
Dim btn() As Button
btn = Me.Controls.OfType(Of Button)().Where(Function(c) c.Name.Contains("")).ToArray()
This will basically create an array of buttons from your form, then you can just loop through each one.
Dim i As Integer = 0
While i < btn.Count
btn(i).Enabled = True
btnText(i).BackColor = Color.DarkOliveGreen
btnText(i).ForeColor = Color.White
i += 1
End While
If you have a naming convention for your buttons and want to only change certain buttons where the empty quotes are you can have "btnTest".
Then you will have an index of any button that contains the text "btnTest" in it. So that would include "btnTest1", "btnTest2", "btnTestAnything1234" etc.
Hope this helps and you can use it!
Nevermind I found my problem. The buttons are in a group box so I had to reference the group box directly
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 imagine this is probably an easy to answer question but for some reason I can't get it to work
Sub New(ByVal Sess As AudioSessionControl2)
S_Session = Sess
'Create the panel and position it.
S_Panel.BackColor = Color.AliceBlue
S_Panel.Width = 200
S_Panel.Height = 40
Dim Position As New Point(6, 19)
If G_AppSessions.Count > 0 Then
Position = Point.Add(G_AppSessions.Item(G_AppSessions.Count - 1).SessionPanel.Location, New Point(0, 45))
End If
S_Panel.Location = Position
'Create a label which has the name of the process
Dim S_PName As New Label
S_PName.Text = "Test"
S_PName.Dock = DockStyle.Left
S_Panel.Controls.Add(S_PName)
'Create a button to change volume
Dim S_Save As New Button()
S_Save.Text = "Save"
AddHandler S_Save.Click, AddressOf Save_Click
S_Save.Parent = S_Panel
S_Panel.Controls.Add(S_Save)
S_Volume.Parent = S_Panel
S_PName.Parent = S_Panel
MainForm.Controls.Add(S_Panel)
S_Panel.Parent = MainForm.gb_Applications
End Sub
The problem is that, the label will show because its docked, but the button won't. It will only show if its docked as well, and thats just not what I want. This is part of a class for creating a dynamic UI, where I can create a number of this class to create a bunch of panels for various things.
I don't see anywhere where you are setting the label or button position. You probably have them both at 0,0 and the label is on top of the button, obscuring it. Did you try setting the position of both the controls, making sure they don't overlap?