How to hide DropDownList in ComboBox?
I want use ComboBox only for displaying text.This control look nice, for me is better than TextBox plus Button. So control must be enabled, but without any items.
When user click arrow (or alt + down key) DropDownList should'n show, because ill select value from custom DataGridView in order to fill back text in ComboBox.
Edit. Alternative solution is set DropDownHeight to 1, with show only 1 pixel line after clicking control.
Edit. Real solution. Answer below
You can intercept the messages that cause the box to drop-down, in a subclass. The following snippet defines a control NoDropDownBox, that ignores the mouse clicks that result in a drop-down of the combo box:
public class NoDropDownBox : ComboBox
{
public override bool PreProcessMessage(ref Message msg)
{
int WM_SYSKEYDOWN = 0x104;
bool handled = false;
if (msg.Msg == WM_SYSKEYDOWN)
{
Keys keyCode = (Keys)msg.WParam & Keys.KeyCode;
switch (keyCode)
{
case Keys.Down:
handled = true;
break;
}
}
if(false==handled)
handled = base.PreProcessMessage(ref msg);
return handled;
}
protected override void WndProc(ref Message m)
{
switch(m.Msg)
{
case 0x201:
case 0x203:
break;
default:
base.WndProc(ref m);
break;
}
}
}
You will have less trouble and create a better end result by simply creating a usercontrol with a textbox and button that is styled in the way you want. If you figure out a way to remove the functionality of the combobox, all you're really doing is creating unneeded complexity.
Maybe it's better to create a custom control once and use it any time you do need this functionality.
If you are working with Windows Forms maybe the easiest way is to inherit class UserControl and create your component using the visual designer writing a little code. You can also descend ComboBox class and code your own drawing logic but it seems to be requiring more work.
[Updated]
OK, you can't set the Combo Box to Read Only, but you can set Enabled = false.
I've never tried this, but perhaps you could set the MaxDropDownItems to 0.
But, yo'd still set the Combo Box's Text to the value you want in code.
[Edit]
Another idea: Set DropDownHeight to 0 (...or 1 if it won't accept 0).
If the DropDownStyle is set to DropDown and the Text is set to "Something" then your ComboBox won't dropdown when user clicks the button.
At least, I'm getting that behaviour in WinForms (C# 4.0).
Is that what you are trying to achieve?
Related
No matter what the scenario may be I'm able to recreate this annoying problem 100% of the time.
Create a .Net project, C# or VB.Net. Add a ToolStrip control to the form. Create a few simple DropDownButton(s) that contain at least 2 menu items. Add any other controls you wish, a list box (populate it so it can receive focus correctly) and a ComboBox control. Either assign shortcut keys or enable TabStop on the ToolStrip so that it can receive focus by Keyboard.
Run the project (Debug/Release, which ever you fancy). Use your Keyboard to give the ToolStrip Focus (by tab or shortcut key). Arrow down into a sub item. Now select the escape key to collapse the Toolstrip sub menu. Tab to the ListBox or ComboBox that contains a few Items.
All looks great right? Now use your arrow keys to navigate in these controls... Surprise! your back on the ToolStrip and the control you thought had focus doesn't!
I've tried multiple things to force focus on the ListBox. One example is I'd add the event handler for OnEnter (ListBox.Enter+=...) and add some code like:
ListBox.Focus();
ListBox.Select();
Nothing was a success... It seems like once the menu expands on a toolstrip you will be forever stuck on this control using your Keyboard...
This is important for me to resolve due to the fact that i work with blind users whom use keyboard navigation only... Is this a bug? I cannot reproduce this in MFC...
Any suggestions?
Update
I was able to find a control that doesn't reproduce this strangeness...
System.Windows.Forms.MainMenu is the only "Tool Bar object" that doesn't behave like the others...
I'd still like some feedback on the above though (Help for others and myself)...
Update 2
The underlying issue is within [ToolStripObject].TabFocus property... if set to false all seems to work ok... giving focus back to the control that "looks" like it's focused. But having that capability to allow a blind user to navigate throughout all UI controls via tab is a handy thing to implement... it's too bad this property doesn't work like it should....
I got it to work by overriding the ToolStripMenuItem:
public class ToolStripMenuItemEx : ToolStripMenuItem {
protected override bool ProcessCmdKey(ref Message m, Keys keyData) {
if (keyData == Keys.Escape) {
ToolStripDropDownButton tb = this.OwnerItem as ToolStripDropDownButton;
if (tb != null) {
tb.HideDropDown();
return false;
}
}
return base.ProcessCmdKey(ref m, keyData);
}
}
I am developing a Windows Form Application with several pages. I am using a TabControl to implement this. Instead of using the header to switch between tabs, I want my application to control this e.g. the next tab should open after the user has filled in a text box and clicked the next button.
Add a new class to your project and paste the code shown below. Compile. Drop the new control from the top of the toolbox onto your form. It shows the tabs at design time so you can easily switch between them while designing. They are hidden at runtime, use the SelectedTab or SelectedIndex property in your code to switch the page.
using System;
using System.Windows.Forms;
public class TablessControl : TabControl {
protected override void WndProc(ref Message m) {
// Hide tabs by trapping the TCM_ADJUSTRECT message
if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
else base.WndProc(ref m);
}
}
tabControl1.Appearance = TabAppearance.FlatButtons;
tabControl1.ItemSize = new Size(0, 1);
tabControl1.SizeMode = TabSizeMode.Fixed;
Create new UserControl, name it for example TabControlWithoutHeader and change inherited UserControl to TabControl and add some code. Result code should look like:
public partial class TabControlWithoutHeader: TabControl
{
public TabControlWithoutHeader()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x1328 && !DesignMode)
m.Result = (IntPtr)1;
else
base.WndProc(ref m);
}
}
After compile you will have TabControlWithoutHeader control in ToolBox. Drop it on form, in designer you will see headers, but at runtime they'll be hidden. If you want to hide them in designer too, then remove && !DesignMode.
Hope that helps.
http://social.msdn.microsoft.com/Forums/windows/en-US/c290832f-3b84-4200-aa4a-7a5dc4b8b5bb/tabs-in-winform?forum=winforms
You can replace tabcontrol with a hand made panel that mimic like you want:
class MultiPagePanel : Panel
{
private int _currentPageIndex;
public int CurrentPageIndex
{
get { return _currentPageIndex; }
set
{
if (value >= 0 && value < Controls.Count)
{
Controls[value].BringToFront();
_currentPageIndex = value;
}
}
}
public void AddPage(Control page)
{
Controls.Add(page);
page.Dock = DockStyle.Fill;
}
}
And then add pages and set current visible page:
MultiPagePanel p;
// MyTabPage is a Control derived class that represents one page on your form.
MyTabPage page = new MyTabPage();
p.AddPage(page);
p.CurrentPageIndex = 0;
I was needing this code but in VB.net so I converted it. If someone needs this code in VB.Net there it is
Imports System
Imports System.Windows.Forms
Public Class TablessControl
Inherits System.Windows.Forms.TabControl
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
' Hide tabs by trapping the TCM_ADJUSTRECT message
If (m.Msg = Convert.ToInt32("0x1328", 16) And Not DesignMode) Then
m.Result = CType(1, IntPtr)
Else
MyBase.WndProc(m)
End If
End Sub
End Class
and thanks to #Hans Passant for the answer in C#
To complement Hans Passant's existing answer, I've found four ways to hide the arrows from the user when the numbers of tabs exceeds the width of the TablessControl. No single solution is necessarily perfect for everyone, but may be for you (or at least a combination of them).
Solution 1:
Simply enable Multiline. This will prevent the arrows from appearing in the first place. However, bear in mind, you may lose WYSIWYG in the designer because the vertical space will be adjusted downwards vertically, and controls within the TablessControl may even be 'chopped off' at the bottom (again, only in developer mode though).
Solution 2:
A more advanced solution which solves the WYSIWYG problem above is to only enable Multiline once the program gets running. Simply add this constructor to the TablessControl class:
public TablessControl()
{
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
if (!designMode) Multiline = true;
}
To the developer, they will still appear as a single line of tabs.
Solution 3:
Decrease the font size of the TablessControl. Each tab should shrink accordingly. Since the user never gets to see the tabs, it shouldn't matter much if you set the font sizes to even 4pt.
However be careful, because the TablessControl's contents may also be resized. If this happens, re-edit the font size for each widget inside, and at that point, they'll thankfully stay at that size even if you then decide to re-change the main TablessControl's font size again.
This approach also has the advantage of more closely showing the true WYSIWYG vertical real-estate to the developer (which can look fine for the user, but may be cut off slightly at the bottom in the designer due to the height of the tabs).
This solution can be combined with Solution 1 and 2 for accumulated advantages.
Solution 4:
This solution isn't necessarily so great if any of the tabs have text which are long. Thanks to Hans for suggesting it.
First set the TablessControl's SizeMode to 'Fixed', and then reduce the TablessControl's ItemSize Width property to a smaller number to reduce each tab's width. Feel free also to adjust the ItemSize Height property to help address the aforementioned WYSIWYG issue, though Solution 3 may be more helpful for that problem.
This solution can be combined with the above solutions to further accumulate advantages.
If you really want to do this, yo can do something like this
tcActionControls.Region = new Region(new RectangleF(
tbPageToShow.Left,
tbPageToShow.Top,
tbPageToShow.Width,
tbPageToShow.Height)
);
Where tcActionControls is your TabControl and tbPageToShow is a TabPage to show in this precise moment.
Should work for you.
Regards.
This solution appears to work well -
How to hide tabs in the tab control?
Insert Tabcontrol into a form, the default name being tabcontrol1.
Ensure that tabcontrol1 is selected in the Properties pane in visual studio and change the following properties:
a. Set Appearance to Buttons
b. Set ItemSize 0 for Width and 1 for Height
c. Set Multiline to True
d. Set SizeMode to Fixed
This is best done after your have finished your design time tasks as it hides them in the designer as well - making it difficult to navigate!
You can try removing the TabPage from the TabPageCollection :
TabControl.TabPageCollection tabCol = tabControl1.TabPages;
foreach (TabPage tp in tabCol)
{
if(condition)
{
tabCol.Remove(tp);
}
}
In my WinForms app, I was able to work around this by positioning the TabControl's y-coordinate outside the visible range of the form, so the tabs were effectively hidden. This example only works if the tabControl is near the top of the form, but you get the idea.
private void frmOptions_Load(object sender, EventArgs e)
{
tabControl1.Top = -23; //Only tabPage contents visible
}
Iam working on a touch screen windows form that has many checkboxes, textboxes, listboxes, date dropdown pickers etc. Depending on user action a status message is displayed at the bottom. For eg., Your profile saved successfully, From and to date cannot be same, Please select a valid ... etc
What is an elegant way to clear the status message on ANY touch.
if (statusLabel.text != string.empty )
statusLabel.text = string.empty)
Meaning if any checkbox is checked, any text is input in a textbox, any listbox or combo is selected...then I want to clear the status label. This way the last status message does not "stick" to confuse the user. I am poking around to see if I can override some event at the form level in one place that will do this.
thanks
thx Saravanan and Pedery for your suggestions. They do not solve my problem. I just discovered Reactive extensions and posting a related question which may help me. Left mouse button click detect on winform using Reactive extensions IObservable on events
Try to find an event in the statusbar itself like text changed or content changed etc. Override it to clear the content of itself.
You may write code to clear the status bar content on the change event of the control's container.
Its your choice.
You can put the message in the controls' Tag property and use a single common event to add them all up.
If you wanna be more orderly, you can subclass the checkbox with a custom property the same way.
This was the solution to my problem
protected override void WndProc(ref Message msg)
{
switch(msg.Msg)
{
case WM_LBUTTONDOWN:
//Do something here
break;
//add other cases if needed
}
// call the base class WndProc for default message handling
base.WndProc(ref msg);
}
How do I make a tab manager that doesn't show the tab headers?
This is a winforms application, and the purpose of using a tab manager is so the display content can only be changed through code. It's good for menus where various menu options change the screen contents.
Hiding the tabs on a standard TabControl is pretty simple, once you know the trick. The tab control is sent a TCM_ADJUSTRECT message when it needs to adjust the tab size, so we just need to trap that message. (I'm sure this has been answered before, but posting the code is easier than searching for it.)
Add the following code to a new class in your project, recompile, and use the CustomTabControl class instead of the built-in control:
class CustomTabControl : TabControl
{
private const int TCM_ADJUSTRECT = 0x1328;
protected override void WndProc(ref Message m)
{
// Hide the tab headers at run-time
if (m.Msg == TCM_ADJUSTRECT && !DesignMode)
{
m.Result = (IntPtr)1;
return;
}
// call the base class implementation
base.WndProc(ref m);
}
}
(Code sample originally taken from Dot Net Thoughts.)
Note that this will not work properly for tab headers positioned on the sides or the bottom. But not only does that just look weird, you won't be able to see the tabs at run-time anyway. Just put them on the top where they belong.
Right, if it's web application, you can build your own DIV with the same placement and hide/show as per your needs.
Along with everybody else, I find your question a bit confusing. I've used this method found here before. Using this way you have a single property you can change as to whether you want to show the tab headers or not.
After the edit and comments made the question more clear, I think the normal way to handle this is to use multiple panels rather than tabs.
I guess, that using panels is the simplest solution. In addition, I suggest using my (free, opensource) VisualStateManager to simplify switching and eliminate lots of .Enabled = true horrors.
Package is available on Nuget.
Just write this code:
// Contains and propagates information about current page
private SwitchCondition<int> settingPageCondition;
// Controls state of specific controls basing on given SwitchCondition
private VisualStateSwitchController<int> settingPageController;
// (...)
private void InitializeActions()
{
// Initialize with possible options
settingPageCondition = new SwitchCondition<int>(0, 1);
settingPageController = new VisualStateSwitchController<int>(
null, // Enabled is not controlled
null, // Checked is not controlled
settingPageCondition, // Visible is controller by settingPageCondition
new SwitchControlSet<int>(0, pGeneral), // State 0 controls pGeneral
new SwitchControlSet<int>(1, pParsing)); // State 1 controls pParsing
}
// (...)
public void MainForm()
{
InitializeComponent();
InitializeActions();
}
// (...)
// Wat to set specific page
settingPageCondition.Current = 0;
I want to create a Windows form in C# with textbox whose text cannot be altered or selected by the user.
I managed to make it unalterable (ReadOnly = true), but I am still able to select and highlight the text.
How can I change this?
Thanks!
-R
This is the expected behavior and is by design. You can see this for yourself if you right-click on an item in Windows Explorer and open its Properties window. All of the dynamic text fields on the "General" tab are selectable, though not modifiable. If this is not the behavior you desire, you should strongly consider using a Label control instead. This is the exact situation for which it was intended—static text that is not selectable by the user.
In case, for whatever reason, you're not sold on why you should use a Label control instead, I'll proceed onward in answering the question you asked. The major problem with trying to override this behavior (like overriding the default behavior of any control) is that there are a lot of ways for the user to accomplish it: clicking and dragging with the mouse, double-clicking the mouse button, using the arrow keys on the keyboard in combination with the Shift key, tabbing into the textbox,right-clicking and choosing "Select All" from the context menu, etc...
Your first instinct might be to override the potentially relevant events exposed by the .NET Framework (such as OnMouseDown, OnKeyDown, etc.) and reset the selected length to 0 so that the text is immediately unselected after it is automatically selected. However, this causes a little bit of a flicker effect in the process, which may or may not be acceptable to you.
Alternatively, you could do the same thing by overriding the control's WndProc method, watching for the relevant window messages, and preventing the messages from being passed on to the control's base class altogether. This will prevent the flicker effect because the base TextBox control never actually receives a message causing it to automatically select its text, but it does have the obvious side effect of preventing the control from taking any action as a result of these common events. It seems like that probably doesn't matter to you in this case, but realize that this is still a pretty drastic hack. I definitely cannot recommend it as being good practice.
That being said, if you're still interested, you could use the following custom UnselectableTextBox class. It prevents the processing of every window message that I could think of which would possibly allow the user to select text. It does indeed work, but fair warning: there may be yet others I haven't thought of.
public class UnselectableTextBox : TextBox
{
public UnselectableTextBox() : base()
{
//Set it to read only by default
this.ReadOnly = true;
}
protected override void OnGotFocus(System.EventArgs e)
{
base.OnGotFocus(e);
//Prevent contents from being selected initally on focus
this.DeselectAll();
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
const int WM_KEYDOWN = 0x100;
const int WM_LBUTTONDOWN = 0x201;
const int WM_LBUTTONDBLCLK = 0x203;
const int WM_RBUTTONDOWN = 0x204;
if ((m.Msg == WM_KEYDOWN) || (m.Msg == WM_LBUTTONDOWN) ||
(m.Msg == WM_LBUTTONDBLCLK) || (m.Msg == WM_RBUTTONDOWN))
{
this.DeselectAll();
return;
}
base.WndProc(ref m);
}
}
Use label inplace of textbox. I think you only want to show information but not to select, not to copy, using label will be better option...
Is disabling it an option? (Enabled = false)