Displaying MessageBox when disabled menu item is clicked - c#

I want to display a message box when any person clicks on the menu item which is not enabled I have tried the following coding but it is not displaying the message box.
Coding:
private void updateFineDetailsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (updateFineDetailsToolStripMenuItem.Enabled == true)
{
frmUpdateFineDetails objUpdateFineDetails = new frmUpdateFineDetails();
objUpdateFineDetails.MdiParent = this;
objUpdateFineDetails.Show();
}
else if (updateFineDetailsToolStripMenuItem.Enabled == false)
{
MessageBox.Show("Unauthorized Person");
}
}
By default I have set the enabled status to false and when the form loads I am checking whether the user is administrator, if the user is admin then this menu item will be enabled for all other user who logs into the application the above menu item has to be disabled.
Please note that the above coding does not generate any error, but it does not even display the messagebox as unauthorized person.
Can anybody help me out in performing this task?
Thanks in advance!

The whole idea of disabling a menu item or a button is to prevent the user from interacting with it. Typically the control will also be rendered in a way so that this becomes clear to the user. If you want to prevent the user from taking certain actions, for instance based on whether the user is an administrator or not, you can use one of three approaches:
Keep the control enabled and inform unauthorized users that the function is not available if he or she invokes it
Disable the control
Hide the control
In the later two cases there is no interaction, since the user cannot invoke the command. I usually tend to prefer to hide the command, if the access to it is role based (meaning that if I don't have access to the command when I start the application, it will not happen at any point while running it), or disabling it if the availability of the command is related to data state.

As I understand, a disabled menu item does not raise Click events.

If you need to display the error message then enable the menu item.
If admin clicks then default action occurs and if other users click show a message box and prevent the default action.
From your code I think you can do this just by enabling the menu item.

Disabling a menu item isn't a cosmetic display issue, it does just what you'd expect from the term - it disables the menu item.
When disabled, the menu item is effectively inert - it will not raise the click event, and there's no (straightforward) way to make it do so.
I can guess at your motivations - to explain to your users why the particular menu item is unavailable to them - but you'll need to find a different approach, one that works with the system, not against it.
Some possible approaches ...
Leave the menu item disabled, allowing the user to select it - you can then make a role based choice on how to handle the event.
Disable the menu item and provide feedback elsewhere in your UI telling the user what level of access they have.
Display a tooltip with the reason for disabling the control
Leave the menu item enabled, but change it's display to look inactive (this is hard to achieve 100%); this will allow the events to fire and your handler to be invoked
Create a separate "Explain" menu item, perhaps on the "Help" menu; when invoked, all disabled menu items become enabled, and will explain to the user why the command is unavailable.
Some systems display a line of help text relevant to the highlighted menu item on the status bar - you could leverage this to explain availability: "Maintain customer details (requires Administrator role)"

a disabled control does not raise Click events. you should simulate that state! for example:
enable menu item
change menu item's forecolor to SystemColors.GrayText
save state of item in item's tag (enable or disable)
if click event raised, first check item's tag
change menu item's forecolor to normal fore color if enabled item.

Related

Preventing user selection but allowing selection programmatically

I have a listview control in my windows application, which is populated with some set of items. I will make the selection of an item programmatically by setting ListViewItem.Selected property to true. But I want to prevent the user from selecting an item in the listview. i.e., it should be always selected programmatically. I can prevent the user selection by disabling the control, but disabling the control will also disable the scroll bars which is not correct.
Even I have created a custom listview control and implemented a ItemSelectionChanging eventhandler using WndProc check link, using which i can cancel the event as shown below,
private void lstLiveTables_ItemSelectionChanging(object sender, ListViewExItemSelectionChangingEventArgs e)
{
e.Cancel = true;
}
But again, this will cancel the event, even for an item selected programmatically. My question, is there anyway to identify whether the selection is made manually (by user) or programmatically in SelectedIndexChanged or using WndProc Message.
Note: If it is required, I will upload the code of CustomListView control.
Update 1
Thanks emartel. It was a good thought. Even I tried to achieve the same thing by subscribing to the event only before selecting the item and removed it immediately after selecting. By this way, upon selection the event will be immediately triggered and it will continue. This is working fine.
this.lstTables.SelectedIndexChanged += new System.EventHandler(this.lstTables_SelectedIndexChanged);
item.Selected = true;
this.lstTables.SelectedIndexChanged -= new System.EventHandler(this.lstTables_SelectedIndexChanged);
But again I have a problem that, if the user selects an item manually, nothing will happen (no event will be triggered) but the item alone will be highlighted. Once an item is highlighted and if i try to select the same item programmatically nothing is happening i.e., the SelectedIndexChanged event is not getting triggered for that item as it is already highlighted.
Note: Same behavior even if I follow the Flag approach suggested by you.
Update 2
I can solve this issue by having my own method instead of handling through events as emartel's suggestion. But my question is, according to my update 1, is there anyway to trigger the SelectedIndexChanged event when the item is highlighted but not actually selected?
public FrmTest()
{
list.ItemSelectionChanged += list_ItemSelectionChanged;
}
private bool changing;
private void list_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
{
if (changing)
return;
if (e.Item == nonSelectableListItem)
{
changing = true;
nonSelectableListItem.Selected = false;
changing = false;
}
}
Sample:
Well, an easy solution would be to keep a flag saying that you are programmatically changing the selection and to allow the event to pass, and reset the flag when you're done
Edit: if you, and only you, can change the selection, and you do this programmatically, so you have control over where and when this happens, why do you even need the EventHandler? Why not call a method to do whatever processing you want to happen?
One dirty way to do that is to keep list of selected items and refresh selection every time it changes other way than from your code.
There is also an ItemSelectionChanged event which is raised separately for every item whose selection state have changed. You can probably flip the selection state back it this event.
You may also take a look on Better ListView Express control. It have a read-only mode, so that user cannot change the selection. Its setup is very simple:
listView.ReadOnly = true;
The full version also supports custom non-selectable items. Simply setting:
listView.Items[0].Selectable = false;
make the first non-selectable (by the user).
You can still select items from code, of course.
The following image shows non-selectable items in action (they are marked by gray color):

How to tell which control a contextmenustip is associated with?

I have two labels one lblEmail1 and two lblEmal2 each has the same context menu strip associated with it. The contextmenustip has one menu item which is "Send Email" when I right click on either label and you select "Send Email" it goes to the same function to process the request which would be to take the value lblEmail1.Text or lblEmail2.Text and start an email. The problem is I can't figure out how to tell which label initiated the request. Any help would be appreciated.
add an event handler for the menu's opened event
Sender will be which of the labels triggered it.
Store that somewhere, the email menuitem's tag property would be good, or a private variable on the form class.
Then in the Onclick of the menu item test and proceed accordingly.

How do I prevent a tab from rendering when selected?

I would like to be able to have a user be able run through the tabs, setting focus to each one, but only when they hit enter, the tabpage will render.
You would think that the paint event would be involved, but I don't know how to "cancel out" of it, if that would even do the job..
First, I should caution you that you're overriding the standard Windows behavior. In any property page dialog or anywhere else that uses tabs in the user interface, using the left and right arrow keys will flip through the tabs and cause them to display their contents in the tab control. You do not have to press Enter to get the selected tab page to display. Make sure that your users understand that your application is different (and that you understand the needs of your users) if you decide to go this route.
That said, you can override this behavior by handling the KeyDown event for the TabControl, detecting when one of the arrow keys has been pressed, and cancelling it. For example:
private void myTabControl_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
//Check to see if an arrow key was pressed
if ((e.KeyCode == Keys.Left) || (e.KeyCode == Keys.Right))
{
//Cancel the keypress by indicating it was handled
e.Handled = true;
}
}
However, once you do this, there will be no way for the user to set focus to a particular tab page's tab, because once the tab gets focus, the tab page is immediately brought into view. This is handled by the parent TabControl and is unrelated to the Paint event (which is responsible for how the control gets painted, not when or why).
Of course, you can always determine if the Enter key was pressed in the same KeyDown event and activate any tab page that you wish (such as by using a counter variable that is incremented/ decremented each time the corresponding arrow key is pressed), but there will be no visible indication to the user which tab will then be brought into view. The focus rectangle will not be drawn.
Also be aware that pressing Ctrl+Tab or Ctrl+Page Up/Page Down will switch between tab pages. If this is also undesirable, you'll need to watch for and cancel these key combinations as well.Any time you start trying to override default behaviors, you're in for a lot more trouble than if you just design your application around it. If there's a particular reason you want to require the Enter key to commit tab page switching, we might be able to help you come up with an easier and better solution.
I'm not sure I understand what you are trying to accomplish, but it sounds like you can do it using the Visible property.
You should be able to set the TabPage's visibility to false when the user switches to it, and then set it to true only when you want to.

RadTabStrip On Click Show Prompt

When the user clicks on a tab, I want to fire the radconfirm window to ask them if they want to proceed. Now, I cancel the event, fire radconfirm, and in the callback, if successful, I'm trying to explicitly postback to show the new tab. I tried doing:
//In tabSelecting event on client
e.get_tab().select(); //to select the new tab because I canceled the selection earlier on
sender._postback(e.get_tab()); //to perform the postback
The RadMultiPage gets updated to the new tab's content, but the RadTabStrip does not show me the new tab selected. I see the old tab selected with the new tab's content.
Any ideas?
Thanks.
If you get your hands on the client object of the clicked tab, you can set is as selected using the set_selected method from the client API (see here).
Because I was attaching to tabSelecting, I need to add a boolean in the component to prevent the cancelling of the event the second time, because setting the selected tab was also firing tabSelecting event. That was the fix.

Show/Hide ContextMenuStrip outside the form

I'm creating a simple clipboard manager application. It monitors the content of a clipboard. When a change occurs (throu the win api message loop) it fires up a method to capture current content of clipboard and creates new object called clipboarditem. Next its building a ContextMeuStrip which consits of several clipboarditems created previously. The items menu is accessed by a hotkey. It shows up this menu on certain position of the screen itemsMenu.Show(caretPosition);, with .Focus(), I want it to make it disappear after it loses the focus (eg. clicking somehwere else on the screen or switch applications by alt-tab). Found an event OnLoseFocus but I dont think its working properly because the menu wont even show up.
How to make ContextMenuStrip disappear after loosing focus and how to prevent from showing ContextMenuStrip in taskabr ?
Sorry for my language skills :)
From a very quick look at the events that ContextMenuStrip contains, have you tried the "MouseCaptureChanged" event? It may help you with the losing focus issue.
For the showing in the taskbar issue, have you set "ShowInTaskbar" to false on the form you have your ContextMenuStrip (if you have it on a form)?

Categories