gtk_message_dialog in a GtkCombo callback - c

I'm developing an app in C using Gtk. I have a GtkCombo with some restrictions that should launch an error message when user selects wrong entries in the list. The problem is that when callback launches the error message, pop-down string is still open, and if the user moves the mouse over it, the list acts as if all entries under the mouse pointer where clicked. This behavior stops if the user clicks on an empty window area or other GtkWidget. I've tried changing the focus to another widget, launching button_release signal...
Anyone knows how to prevent this bug?

Try connecting the signal with g_signal_connect_after() instead of g_signal_connect(). The callback should run after the combo popdown has finished all its reactions to the click.

Related

WPF menu and multitouch

I have a menu that is implemented in a way that when a menu item is pressed, a popup containing it's sub-items is open.
When running with touch screen, occasionally user touches 2 menu items at the same time with his fingers - and this leads to one of the menuitems have a touch capture which is not released until another window gets focus, making the app seem stuck.
How can I prevent such a case?
thanks
You could use a queue that contains delegates:
When triggering a command, add the delegate to the queue.
Then grab the first delegate of the queue and flush it afterwards.
Now you only have 1 "command".
I found the cause for the problem: the popup used to display submenu items had StaysOpen set to false.
This causes the Popup to capture input so it can know when to close itself once a click was made outside its boundaries.
Setting its StaysOpen property to True fixed the issue.

Can SetWindowHookEx(WH_CALLWNDPROC ) hang entire system?

I am stuck with this. I can't even see the debug output using OutputDebugString and debugview - the system just hangs.
One question is: if i call SendMessage() inside hook function, did this message comes to me back into my hook function or system just calls another handlers but not my?
Question two: I am using hook procedure to catch messages sent by the system when a user clicks the tray icons or moves the mouse over the icons.
Is this correct way using SetWindowHookEx(WH_CALLWNDPROC, myfunc, hDll, 0) or should I use the thread parameter and set it to the thread which recieves msgs as configured by Shell_NotifyIcon()?
You implemented the hook in a library!?
Regarding question 1: I would not call SendMessage inside the hook because this SendMessage again will let your hook being called. This might lead to a recursion.
Regarding question 2: You are using hooks to get notified when a tray icon was clicked? Do you want to now when ANY tray icon was clicked or when YOUR tray icon was clicked? For notifications about your tray icon you should use Shell_NotifyIcon and take a look at NOTIFYICONDATA::uCallbackMessage.

Show NotifyIcon Context Menu and Control Its Position?

I'm trying to show a context menu when I left-click a NotifyIcon. Just calling NotifyIcon.ContextMenuStrip.Show() doesn't work very well. A solution has been posted here before that calls a secret method using Reflection:
Dim mi As System.Reflection.MethodInfo = GetType(NotifyIcon).GetMethod("ShowContextMenu", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
mi.Invoke(Icon, Nothing)
This works great, except that I also need to control where the menu is shown. I want to wait for the SystemInformation.DoubleClickTime to elapse between receiving the NotifyIcon.MouseUp event and displaying the menu, so that I can handle single-clicks and double-clicks separately. But invoking the ShowContextMenu method displays the menu at the current mouse position when ShowContextMenu is called, not when the icon was actually clicked. Which means that if the mouse moved during the DoubleClickTime, the menu will be displayed in a different part of the screen. So if I can control where the menu is shown, I can just save the mouse coordinates when I receive the MouseUp event, and then I can ensure that the menu is displayed near the icon. Is there a way to do this?
Thanks in advance.
Well, I just discovered that there are existing programs that exhibit this same behavior. I just went through all the icons in my system tray and about half of them do it. If you left-click the icon and then move the mouse during the delay before the menu appears, the menu will appear at the last mouse location, wherever that is on the screen. Snagit is one application that does this. Outlook is the only program in my tray that always shows the menu where I clicked the icon. But Snagit looks like it's using a .NET ContextMenuStrip, while Outlook is probably using a native menu.
So either this is standard behavior, or it's a problem that no one else has been able to solve either. And as a user, I've never noticed this behavior until yesterday when I was testing my own application. So I guess it's not that big of a deal and I won't worry about it.

Silverlight click event registered a second time before first event completed

I have a button which launches a "modal dialog" - it just creates a transparent grid covering everything, with the "dialog" created on top of that.
However I have a strange issue - if I double/triple click the button really fast (or add some delay in the event code), the button click event is executed multiple times, creating multiple overlapping modal dialogs. If the first action in my event is to disable the button (IsEnabled=false) it seems to prevent this.
My guess is that Silverlight is being multithreaded with input - it is not only recording the second click in another thread (while the button's click event is running), but it is jumping the gun by evaluating which control should be the target before the previous event has finished executing. Even though that event alters what control is at those mouse coordinates, it doesn't matter.
Does anyone know anything about this behavoir, or a way around it? If I have something like a save window, where the user clicks a save button, a blocking grid ("Saving...") is placed up while it saves, and then the whole "window" is closed, I'd like to avoid the user being able to queue up multiple save event clicks (this could lead to unpredictable program behavoir).
If you've ever worked with WinForms or WPF, this is expected behavior. Your button is broadcasting its Click event until your modal dialog covers it up. Unfortunately, there is some amount of time between your first click and when the modal dialog covers the button which allows multiple clicks to the original button.
You have two solution choices:
Disable the button after the first click and then re-enable after the modal dialog returns. You've already mentioned that this works.
Write code in the Event Handler of the button to determine if a modal dialog is already being displayed. This way, you're putting the responsibility in one location rather than splitting it up (disabling and re-enabling the button). This would be my preferred solution.
I think what you're seeing is the behaviour of Silverlight's routed events.
You can set the Handled property of the event arguments to true to prevent the event from bubbling.

How can I make a 'Partially' modal dialog?

Is there a way to start off showing a dialog modally, but then instead of hiding it, to keep it visible while changing it to a non-modal dialog?
I want to show a dialog, blocking the method that shows the dialog. Then when the user clicks the 'Finish' button on the dialog I want:
The dialog to remain visible.
Control to return to the method that showed the dialog.
I've achieved this result by running the dialog on a separate STA thread, and using an event to block the main UI thread until 'Finish' is pressed, but there's a catch to this method: you can click on the close button of the 'main' window while the dialog is visible, and the main window closes when the dialog is hidden.
Update
Thanks for the responses so far. Sorry - it looks like I got the balance wrong between too much background and not enough.
The form is effectively a modal 'wizard' dialog - it appears, sits in front of the main app modally, and then is hidden. So as far as the user's concerned there's no non-standard weirdness going on. The only difference is that the dialog is driven from a series of callbacks from the UI thread, so I don't think making it truly modal (via a call to ShowDialog) for its lifetime would work. The first callback must show the dialog, and then block while the user sets their preferences via the dialog UI. After that, the dialog stays visible and displays a progress bar page while various other callbacks are made from the UI thread. Eventually the form is hidden. The user isn't interacting with the main window while the form is up. As far as they're concerned, it should appear to be 100% modal wrt the main UI thread.
(The form is a dialog for a Visual Studio wizard - these are driven from a series of callbacks on the UI thread). An alternative would be to show the dialog, hide it, immediately show a topmost 'progress' form instead and then hide that, but I think showing a single dialog is more seamless an experience for the user.
Again - sorry for the confusion!
Perhaps you want to rethink your interaction model? How are you going to explain this to your users? They have an internalized model of how computer programs work, and you better have a very good reason to break that. They know about modal dialogs, they know about non-modal dialogs, they know about inspectors. Choose one, and apply it.
Modal dialogs are made for short-time interaction. They should not block exiting the application. The user is in control of the interaction, the program only provides the minimum of restrictions needed.
[after the explanation, replaced]
What's wrong with showing the progress bar in the modal dialog? Start processing once ok
is clicked, disabling all buttons, only keeping the cancel button active? If it takes a long time, the user might want to abort the action. Only close the dialog when you're finished processing.
You could use a modeless dialog then have your main UI check if the user has clicked the Finished button. If the modeless dialog is open but Finished hasn't been clicked then don't respond to any users actions in the main form...
This is just a terrible idea - it's completely non-standard behavior and you're going to jump through all kinds of hoops to get something working that is just going to horribly confuse your users.
Like most of the other answers here stated, you're implement non-standard UI elements that will be confusing to most users.
If the dialog remains visible just to provide read-only access to the data, then why not have dialog window close normally and open a side-bar window in your application with the data from the dialog window?
If the dialog remains visible to allow the users to continue making updates in it, then perhaps, it shouldn't be modal to begin with.
Point is, there's a couple different ways you can accomplish your task without breaking standard UI metaphors.
I'd make it a flyout from the side or bottom of your app that shoves other things out of the way. If it's on top of other stuff that the user might need to see or interact with then it's just gonna annoy them.
I found that showing an an invisible modal dialog on the main UI thread during the blocking stage of the interaction works great.
Hidden modal dialog settings (so it's not visible): ShowInTaskBar=false, FormBorderStyle=None, size={0,0}, Opacity=0%, StartupPosition=CenterParent.
The hidden dialog is shown on the UI thread using ShowDialog. The visible dialog is shown on a separate STA thread. The thread is kicked off before calling hiddenDialog.ShowDialog on the main UI thread.
The visible dialog hides hiddenDialog when it wants the initial blocking state to complete. This stops the main UI thread from blocking.
The important bits of code:
void LaunchWizardForm(s)
{
// Show the wizard on its own thread.
ThreadStart t = () =>
{
_wizard = new WizardForm(s);
Application.Run(new ApplicationContext(_wizard));
};
var thread = new Thread(t);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
// Block this (main UI) thread
_hiddenForm.ShowDialog();
}
void EndModalEpisode()
{
_hiddenForm.Invoke((Action) (() => _hiddenForm.Hide()));
}

Resources