I would like to have a drop down menu in Winforms in C# with Text Label in between the menu items. It will be very similar to seperators. So basically I am looking at an option of grouping the menu items.
Any idea how we can achieve it ? Attached is the drop-down menu I wish to have.
Hope you are using VS2010
In the Menu Designer, right-click the location where you want a separator bar, and choose Convert To -> Separator.
MSDN Article on menu enhancements
You might want take a look at this also (Its about form separators, but version is VS2003!) -- Windows Forms Separator Control
May be below link can help you:
A Seperator Combo List Vox
I'm sure there are many complex ways to do this but i've found one that might satisfy your needs in 3 Steps:
1.You make your own ToolStripItem:
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.All)]
public sealed class CustomToolStripMenuItem : ToolStripMenuItem
{
public CustomToolStripMenuItem()
{
DisplayStyle = ToolStripItemDisplayStyle.Text;
BackColor = Color.LightSteelBlue;
ForeColor = Color.MidnightBlue;
Font = new Font(Font, FontStyle.Bold);
// Or other options to your liking
}
}
2.You make your own Renderer:
public class CustomeRenderer : ToolStripProfessionalRenderer
{
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
if(e.Item is CustomToolStripMenuItem)
{
e.Graphics.FillRectangle(Brushes.LightSteelBlue, e.Item.ContentRectangle);
}
else
{
base.OnRenderMenuItemBackground(e);
}
}
}
3.Use your items:
For your contextmenu you need to set up the renderer:
RenderMode = ToolStripRenderMode.Professional;
Renderer = new CustomeRenderer();
In your context menu you can now use your CustomToolStripMenuItem
Related
I started out C# very recently and sorry if this question sounds dumb.
How do I add a Listbox in a Form that pops out from a Button click?
Note: The Form isn't the one that's added from the Solution Explorer whereby I can just drag a Listbox from the Toolbox to my Form.
So what I want is to create a ListBox in my file drawer1Form where I can add additional items. Thanks for the help in advance!:)
private void drawer1button_Click(object sender, EventArgs e) // Drawer 1 Button
{
drawer1Form df1 = new drawer1Form();
df1.StartPosition = FormStartPosition.CenterScreen;
df1.Show();
}
public partial class drawer1Form : Form // Creates drawer1Form
{
public drawer1Form()
{
Text = "Drawer 1 ";
}
}
Pretty much the same way as you'd do with any other object.
In the class of your form add a
private ListBox myAwesomeListBox;
Then in the button event handler add something like this:
myAwesomeListBox = new ListBox();
myAwesomeListBox.SuspendLayout();
// set all the properties that you want
myAwesomeListBox.Name = "myAwesomeListBox";
myAwesomeListBox.Location = new Point(...); // place it somewhere
myAwesomeListBox.Size = new Size(...); // give it a size
// etc...
df1.Controls.Add(myAwesomeListBox);
myAwesomeListBox.ResumeLayout();
This should be it.
I highly advise you to do it through the designer first though, and then take a look at the generated code in the form's .Designer.cs file, you'll have a very good understanding after reading through that.
After searching for a long time for a simple way of changing the text color of a #region directive in Visual Studio, I've concluded there is no easy way of doing so.
I know how to change the #region statement color, and how to change the collapsed region color, but I want to change the color of the text with the region description. So:
#region Some text <--- all this text should be in a different color
public void Test()
{
}
#endregion <--- this too
It seems a lot of people are looking for something like this - see How to change the color of expanded regions' titles in VS2008?.
So I've been looking at writing a simple Visual Studio add-in to change the color.
However, it's more complicated than I thought it would be, with classes like Snapshot, Tagger, Classifier, WpfTextViewCreationListener, AdornmentLayer etc.
Simply put, I don't know where to start! I followed a couple of tutorials at the MSDN site, but they seem too complicated for what I'm trying to do.
Can someone point me to the most simple way of doing this? Ie. which classes/methods/events within the VS SDK I should use. I don't mind if the color is not customisable via the UI etc either. I'm using VS2010.
Edit: Just had the mztools website recommended to me; I'll take a look there too. Also noticed that StackOverflow's syntax highlighting of regions is pretty much exactly what I want!
I eventually came up with a solution, at least for VS2010.
Whilst I have used this for coloring '#region' and '#endregion' tags, a similar solution ought to be applicable for any text content in a Visual Studio window.
It seems that this sort of problem can be resolved by creating a IViewTaggerProvider which will 'tag' parts of the source code with a 'classification'.
Visual Studio will provide a style for text tagged with that classification which can then be changed by the user to the desired style via Tools > Options... > Environment > Fonts and Colors.
The Tagger provider looks like:
[Export(typeof(IViewTaggerProvider))]
[ContentType("any")]
[TagType(typeof(ClassificationTag))]
public sealed class RegionTaggerProvider : IViewTaggerProvider
{
[Import]
public IClassificationTypeRegistryService Registry;
[Import]
internal ITextSearchService TextSearchService { get; set; }
public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag
{
if (buffer != textView.TextBuffer)
return null;
var classType = Registry.GetClassificationType("region-foreground");
return new RegionTagger(textView, TextSearchService, classType) as ITagger<T>;
}
}
This creates an ITagger object, which, given a Visual Studio text view, will tag parts of the text with the given classification type. Note that this will work for all text views (i.e. source code editor, 'Find Results' windows etc.). It may be possible to change this by editing the ContentType attribute (to just C#?).
The classification type (in this case "region-foreground") is defined as:
public static class TypeExports
{
[Export(typeof(ClassificationTypeDefinition))]
[Name("region-foreground")]
public static ClassificationTypeDefinition OrdinaryClassificationType;
}
[Export(typeof(EditorFormatDefinition))]
[ClassificationType(ClassificationTypeNames = "region-foreground")]
[Name("region-foreground")]
[UserVisible(true)]
[Order(After = Priority.High)]
public sealed class RegionForeground : ClassificationFormatDefinition
{
public RegionForeground()
{
DisplayName = "Region Foreground";
ForegroundColor = Colors.Gray;
}
}
The Order attribute determines when the classification will be applied compared to other classifications which may also apply to a span of text.
The DisplayName will be used in the Tools > Options... dialog.
Once the classification is defined, an ITagger class can search a view's text and provide classifications for applicable sections of the text it finds.
Simply put, its job is to listen for the ViewLayoutChanged event of the text view, which is fired when the provided text view's content changes (e.g. because the the user has typed something).
It must then search the text for the area of text it is interested in (called a 'span'). Here, it returns spans of lines containing either #region or #endregion. I've kept this simple, but the TextSearchService used to find matches can also search using regular expressions.
Finally, a method is provided for Visual Studio to retrieve the tags of the text it has found, called GetTags(). For a given span collection, this will return text spans with classification tags, i.e. areas of those spans which should be classified in a certain way.
Its code is:
public sealed class RegionTagger : ITagger<ClassificationTag>
{
private readonly ITextView m_View;
private readonly ITextSearchService m_SearchService;
private readonly IClassificationType m_Type;
private NormalizedSnapshotSpanCollection m_CurrentSpans;
public event EventHandler<SnapshotSpanEventArgs> TagsChanged = delegate { };
public RegionTagger(ITextView view, ITextSearchService searchService, IClassificationType type)
{
m_View = view;
m_SearchService = searchService;
m_Type = type;
m_CurrentSpans = GetWordSpans(m_View.TextSnapshot);
m_View.GotAggregateFocus += SetupSelectionChangedListener;
}
private void SetupSelectionChangedListener(object sender, EventArgs e)
{
if (m_View != null)
{
m_View.LayoutChanged += ViewLayoutChanged;
m_View.GotAggregateFocus -= SetupSelectionChangedListener;
}
}
private void ViewLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
{
if (e.OldSnapshot != e.NewSnapshot)
{
m_CurrentSpans = GetWordSpans(e.NewSnapshot);
TagsChanged(this, new SnapshotSpanEventArgs(new SnapshotSpan(e.NewSnapshot, 0, e.NewSnapshot.Length)));
}
}
private NormalizedSnapshotSpanCollection GetWordSpans(ITextSnapshot snapshot)
{
var wordSpans = new List<SnapshotSpan>();
wordSpans.AddRange(FindAll(#"#region", snapshot).Select(regionLine => regionLine.Start.GetContainingLine().Extent));
wordSpans.AddRange(FindAll(#"#endregion", snapshot).Select(regionLine => regionLine.Start.GetContainingLine().Extent));
return new NormalizedSnapshotSpanCollection(wordSpans);
}
private IEnumerable<SnapshotSpan> FindAll(String searchPattern, ITextSnapshot textSnapshot)
{
if (textSnapshot == null)
return null;
return m_SearchService.FindAll(
new FindData(searchPattern, textSnapshot) {
FindOptions = FindOptions.WholeWord | FindOptions.MatchCase
});
}
public IEnumerable<ITagSpan<ClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans)
{
if (spans == null || spans.Count == 0 || m_CurrentSpans.Count == 0)
yield break;
ITextSnapshot snapshot = m_CurrentSpans[0].Snapshot;
spans = new NormalizedSnapshotSpanCollection(spans.Select(s => s.TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive)));
foreach (var span in NormalizedSnapshotSpanCollection.Intersection(m_CurrentSpans, spans))
{
yield return new TagSpan<ClassificationTag>(span, new ClassificationTag(m_Type));
}
}
}
For brevity I have omitted namespaces and the using statements, which are typically of the form Microsoft.VisualStudio.Text.*. For these to be available, the Visual Studio 2010 SDK must first be downloaded.
I've been using this solution for the past few months without issue.
One limitation I noticed is colours are not 'blended', so a color with less than 100% opacity will not 'fade out' the existing colours in a span - which might be useful to preserve syntax highlighting.
I also have little idea of its efficiency, as it looks like it will repeatedly search a document on each keypress. I have not done the research to see if Visual Studio optimises this somehow. I do notice a slowdown of Visual Studio on large files (> ~1000 lines), but I also use Resharper, so I cannot attribute this to this plugin alone.
As this was coded mostly using guesswork, I welcome any comments or code changes which could clarify or simplify things or improve upon the code's performance.
I guess you could start with Visual Studio Add-in project, it will used EnvDTE, which was considered as Visual Studio Object Model, and please find MSDN document here:
http://msdn.microsoft.com/en-us/vstudio/bb968855
You could control your visual studio behavior, like debugger, code editor and so on by EnvDTE.
In my application I am using a popup menu item when right clicking an object. I dynamically build up this menu using code like this:
ContextMenuStrip menu = new ContextMenuStrip();
menu.Items.Add(new ToolStripMenuItem("Item1", aNiceImage, someFunction));
menu.Items.Add(new ToolStripMenuItem("Item2", alsoNiceImage, someOtherFunction));
Now I want to set one of these menu items in bold (as it is recommended by the Windows User Experience Guidelines) to indicate which action corresponds with double clicking the object.
How do I do this?
use item.Font = new Font(item.Font, item.Font.Style | FontStyle.Bold) to make bold effect to the current font.
you can also auto select the default item as follows:
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
{
contextMenuStrip1.Items[3].Select();
}
Use the Font property to specify a font with the desired FontStyle:
myToolStripMenuItem.Font = new Font(
FontFamily.GenericSansSerif,
12.0F, FontStyle.Bold);
Obviously altering the inputs for the desired output, FontStyle.Bold being the important part here.
I created a FontDialog.cs Windows Form where my users can choose colors among other things for the text. I need to capture what the user has selected on the dialog:
Here's how I'm calling the dialog:
DialogsTestingGrounds.FontDialog dialog = new FontDialog();
dialog.ShowDialog();
How can I capture the selected values, I imagine I have to create properties for everything I want to transfer on the FontDialog.cs form end, right?
What you would want to do is expose properties on your FontDialog that make the values available. You could then use dialog.PropertyName to reference it by the name of the property.
It is not necessary, you can use, ie, dialog.Font to get the selected font,
dialog.Color for the color and so on...
Mitchel's answer will work but you might want to incorporate a couple other items along the same line.
Have a public property (per Mitchel's
answer).
Have a public constructor on your
form with the type of the property as
an argument so you can pass in the value
in question (this would allow you have the dialog prepopulated with old selection).
Surround your call to your dialog
with a check for dialogresult so you
only change the value when the user
wants to. (note the process for this is different in WPF)
Felice is also right in that you
don't really need to create a new
font dialog if the only thing you
care about is the font. There is a
built in font dialog in .Net
http://msdn.microsoft.com/en-us/library/system.windows.forms.fontdialog%28v=vs.71%29.aspx
So the internals of your dialog class may look like this psuedo code.
public Font SelectedFont { get; set; }
public FontDialog()
{
//set your defaults here
}
public FontDialog (Font font)
{
SelectedFont = font;
//dont forget to set the passed in font to your ui values here
}
private void acceptButton_Click(object sender, EventArgs e)
{
SelectedFont = //How ever you create your font object;
}
Then to call your function (assumes the the acceptButton above is the forms AcceptButton)
DialogsTestingGrounds.FontDialog dialog = new FontDialog();
if(dialog.ShowDialog() == DialogResult.OK)
//Do Something
We have a form which displays media items in tab pages of a tab control, and I'm implementing a feature which allows users to 'pop out' the tab pages into their own forms.
However, when I add the media player to a form rather than a TabPage, the background switches from the gradient fill of a tab page to the plain SystemColors.Control background of the parent form. I need to add the the media player to a control which has the same background as a TabControl, but which doesn't display a tab at the top. I tried adding the media player to the TabControl's control collection, but that just throws an exception.
How do I get a control which looks like a TabControl with no tabs? Should I keep trying to add the media player to a TabControl, or should I try to write a Panel with a custom-drawn background? If the latter, how do I make sure that works with all possible themes?
The questions seems to be about the UseVisbleBackgroundStyle. AFAIK only buttons and TabPages have this property.
The following is a very dirty hack, just to get you started:
1) derive a customControl from Panel and add "using System.Windows.Forms.VisualStyles;"
2) Add the following code
//warning: incomplete, add error checking etc
private readonly VisualStyleElement element = VisualStyleElement.Tab.Body.Normal;
public bool UseVisbleBackgroundStyle { get; set; }
protected override void OnPaint(PaintEventArgs pe)
{
if (UseVisbleBackgroundStyle)
{
var x = new VisualStyleRenderer(element);
x.DrawBackground(pe.Graphics, this.ClientRectangle);
}
else
{
base.OnPaint(pe);
}
}
Thanks to Henk - I eventually went with:
protected override void OnPaintBackground(PaintEventArgs e)
{
if (TabRenderer.IsSupported && Application.RenderWithVisualStyles)
{
TabRenderer.DrawTabPage(pe.Graphics, this.ClientRectangle);
}
else
{
base.OnPaintBackground(pe);
ControlPaint.DrawBorder3D(pe.Graphics, this.ClientRectangle, Border3DStyle.Raised);
}
}
Try creating your own customer UserControl
This answer is modified from another answer site. It does the trick rather cleanly.
In the load event for the window containing the tab control, try:
// TabControl is the name of the tab control in this window.
TabControl.Appearance = TabAppearance.FlatButtons;
TabControl.Multiline = false;
TabControl.SizeMode = TabSizeMode.Fixed;
TabControl.ItemSize = new Size(0,1);
// The tabs are now gone. Select the panel you want to display
TabControl.SelectTab("InProgressTab");