I am a fairly experienced WinForms developer. I have an MdiApplication that used to work well. However, recently the main shell of the application, for which we use ComponentOne RibbonForm, has been updated in a big way. This update did affect some of our other 3rd party components, which we established was due to ComponentOne's use of DoEvents() in their event code. I thought I had cleaned up all of the code causing problems but I now have found another...
When I have multiple MdiChildren open and select one of these in code from an button click event on the ribbon form via
document.Activate();
document.EditorControl.Select();
document.EditorControl.Focus();
the other open MdiChildren documents still have focus, that it the forms are highlighted and input is not set on the document I set in code. Two questions:
How can I ensure that the Form I want to make active is the only one that is active?
Linking to the above; setting one form as active using form.Activate() should deactivate the others MdiChildren, but it is not - how can I deactivate the other windows in code?
Thanks for your time.
[Too long for a comment]
I am sick to the hind teeth with fighting C1. Esp. the Ribbon. I have confirmed with their support that they do use DoEvents() which they use to yield on their Gui threads. I am now going to switch to DevExpress which should be straight forward for my MVC application...
C1's use of DoEvents() messes up the normal flow of your application. DoEvents() is asynchronous which means it terminates before the application has actually processed any outstanding events, so if you're using it in a procedure with many sequential statements, calling DoEvents() causes a huge disturbance whenever it's called. This is what I think we are seeing when we perform our MDI operations, but we can never be sure without the C1 source code.
I hope this helps.
Related
I have an application that contains multiple MemoEdit controls containing DevExpress spell checkers. When a user updates the Options (through a MemoEdit's context menu), we are saving those options to our db. Is there any built-in way to broadcast those new options to all spell checkers in the application? It's probably worth noting that some of the MemoEdits are used in Interop controls in the VB6 "part" of our application.
Right now I'm using events, but things aren't working out as well as I'd hoped and before I get too deeply into rolling my own fix I figured I'd ask the SO folks.
Thanks in advance for any tips.
My tech lead and I just acquired dev express subscription for a win forms application we are building and we are using the spellchecker and saving the options to our sql server ce table. We have multiple forms with one spellchecker each tied to one memo edit control per form.
I programmed a single reusable function named “GetSpellCheckerOptions” which returns type “DevExpress.ExtraSpellChecker.OptionsSpelling” that loads the six options from the spell check options dialog form from our sql server ce table. This function is invoked in a form’s constructor where the form has the spellchecker component associated to it and this can be any form in our application. It is built around an “on-demand” basis as opposed to loading it in memory and keeping it around for the lifetime of the application because the notes or comments being written by our users are on forms that load, fill it out and close.
You can use the event called OptionsChanged which is a member of the type “DevExpress.ExtraSpellChecker.OptionsSpelling”. You will have hook up the event in runtime using a subroutine you write like this for example:
jobsSpellChecker.OptionsSpelling.OptionChanged += new EventHandler(this.jobsSpellChecker_OptionChanged);
When a user changes an option on the spell check options dialog this event will fire, however there are some gotchas to be aware of. When the event fires you will not know which option fired the event because the Event Argument does not provide that information. So I save as a whole save regardless of which options were changed. The save occurs after the OK button is clicked as opposed per option being changed. The biggest gotcha is that this event fires three times. Two of those three times is from something totally unrelated to changing an option. So to control the two unneed event fires you need an if statement evaluating the options form dialog result, like this for example,
if(jobsSpellChecker.FormsManager.OptionsForm.DialogResult == System.Windows.Forms.DialogResult.OK)
This will protect your save code from being executed needlessly. In addition without the “if” statement the control has a nasty way of remembering previous state of what the options were before you changed them and during those unneeded two of three event fires, it changes your options setting from the new desired settings back to previous state or settings. Very annoying and it has taken the whole day to get past these obstacles and more experimenting with these controls. Hopefully this information can offer you or someone else a value that will save time, avoid potential frustration and endless browsing product support pages.
I am trying to detect the Idle time in a Windows Mobile application and show a Screen lock after this inactive period. This link http://blog.opennetcf.com/ctacke/2009/05/19/DetectingApplicationIdle.aspx gives a hint but I found that this works only for a single form.
How can this same code be used across an application with multiple forms. I tried implementing this code after the InitializeComponent() for each form and used the Reset() function in the form Activate and GotFocus event so that the timer is reset after the user closes the screen lock by entering a PIN number. But this does not seem to work for multiple forms and the timer is not reset but it keeps firing every minute. Even if I am working on the application the event fires up every 1 minute (as per the sample code) and this is not correct.
Can anyone suggest how to use this functionality across the entire application.
Thanks in advance for any solution.
We need to see your code to know what's wrong, but the method proposed in that blog entry uses an IMessageFilter implementation. That hooks into the Windows message pump, which is application-wide not a single-Form system. I use the exact same technique for application-wide idle detection in a couple of solutions and it works well.
My guess is that you have a scope issue with the IMessageFilter instance you're using. If you create it as a Form-level variable (like the sample in that blog does), when close the Form that the filter is disposed of and will no longer work. If you have multiple Forms, you need to put it somewhere else in the Model so it survives as long as the app is up.
What about utilizing GetIdleTime ? Seems like this, paired with a timer that wakes peroidically to check it, could detect system idle and allow you to show the screen lock.
I am developing an extension for existing application via COM.
Current interface of the application to extend allows to create custom property windows and use them inside that application.
Now, I am using .NET for that purpose and have strange problems:
extensionForm = new Form();
extensionForm.SetBounds(0, 0, 100, 100);
extensionForm.Controls.Add(new Button());
ExApplAPI.AddCustomPropertyWindow(extensionForm.Handle.ToInt32(), "Ololo");
As you can see below, the property sheets actually get extended, but after that something strange starts to happen.
Basically, if I switch to Ololo tab, then back to any of other 3 tabs (Attributes, Drawing or Services), the application freezes. I also know that the freeze happens inside of some unmanaged code block.
Another interesting fact here is that if I don't write the extensionForm.Controls.Add(new Button()) (with or without the Suspend / Resume Layout calls), everything works fine. So, if the recently constructed form has no controls (buttons or any other) on it, it doesn't freeze.
Here is a Spy++ log on the Ololo window right before the freeze (last message is the WM_CTLCOLORBTN, right after that the application became frozen):
Combining everything together:
Freezing happens only if I switch from Ololo to some other tab and then switch to the Ololo tab again.
Freezing only happens if the integrated form has at least one control on it, forms without controls don't freeze.
Application is not running any managed code at the moment and is not spending any CPU time.
So - any ideas / similiar problems solved / etc to help me in this case?
The Win32 HWND handles for the Forms in .NET are lazy initialized.
And I think this may be a problem here.
You may argue that the handle is created in your line ExApplAPI.AddCustomPropertyWindow(extensionForm.Handle.ToInt32(), "Ololo"); due to accessing Handle property.
It is true and what documentation acknowledges.
However, it creates the handle for the Form itself, but handles for child controls (Button in this case) are not created. This can be forced by calling CreateControl method. See more documentation.
I don't know if not having a handle for button may be a cause of your problem, but this is definitely something I would investigate.
To summarize, I suggest changing your code to:
extensionForm = new Form();
extensionForm.SetBounds(0, 0, 100, 100);
extensionForm.Controls.Add(new Button());
extensionForm.CreateControl();
ExApplAPI.AddCustomPropertyWindow(extensionForm.Handle.ToInt32(), "Ololo");
Are there any exception thrown?
We had an similar behavior when using WPF and COM, it solved by calling reset double calculation by using
[DllImport("msvcr70.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int _fpreset();
It is possible that the resource handle is not right. As you mentioned this happens only when the integrated form has atleast one control in it, Ololo tab is not able to find it's resources when active again. Please try storing resource handle the first time and then restoring it everytime the tab is active.
To understand why the application hangs, there are 2 things that may help:
Can you post a stack trace of the UI thread while the application is hung?
Which thread calls your code and actually creates the windows?
I am writing an application in c# to lock or freeze all programs untill user enters a value in the app's textbox and clicks ok.
The purpose of the app would be to get people to enter their time.
As far as I know you can set it to top most but they can end the app with task manager so am stuck here..
formName.TopMost = true;
Any help would be appreciated
Yes, that's correct. The Windows operating system allows multiple programs to run at one time. What you're experiencing is entirely by design.
If I remember correctly, the TopMost property applies only to windows in your process, and as you mention, it's all quite irrelevant: the user can still kill your application using the Task Manager.
There's no legitimate way of getting around that. It's not a "limitation", it's a feature. Any app that prevents itself from being closed by the Task Manager is treading dangerously closely on the category of software that we call malware. Nothing good can come out of pursuits like this.
Relevant reading: The arms race between programs and users
Perhaps a good compromise solution is to make your window/form actually top-most and disable the Close button so that the user knows they shouldn't try and close it. This is almost always enough to stop a user that is not determined to end your application by any means necessary, and that's about all you should ever be concerned with.
See the sample code here for how to make your window/form always appear on top of other running applications by setting the WS_EX_TOPMOST flag or toggling HWND_TOPMOST.
I've also already written a detailed answer here about disabling the Close button the correct way by setting the CS_NOCLOSE class style.
We have a C# .NET 3.5 UI client application that runs in a multiple monitor desktop environment (typically 4 screens) on Windows 7. Every so often, after running several of these applications, the screen stops redrawing.
Controls continue to be reactive to clicks or keypress and values can be updated programmatically, but the entire form is not redrawn to reflect any changes. For example buttons that are enabled/disabled based on state may be remain grayed out, but be reactive to clicks or vice versa. Buttons do not animate when clicked.
Workaround: minimizing and restoring the window appears to clear the problem. After this, the application begins to draw correctly.
The must frustrating aspect of this problem is that programmatically, everything appears to be running normally. No exceptions are caught in our logs. Nothing was visible in the system event logs. We have not found a way to detect this condition is happening yet.
Other miscellaneous aspects: logging uses log4net, server communication layer uses ZMQ
Update:
Calling form Invalidate() and Update() does not fix the problem.
When dragging the window between screens, it shows different values on each screen.
Minimize/restore still resolves the issue.
I can't be sure of anything without seeing the app and the code, but my best guess is someone calls .SuspendLayout() before a complicated update, and an exception (probably swallowed) prevents the code from ever reaching the corresponding .ResumeLayout(). To test this, try adding a button that calls .ResumeLayout() for the form.
It seems the solution is there:
1) http://blogs.msdn.com/b/alejacma/archive/2009/08/11/controls-won-t-get-resized-once-the-nesting-hierarchy-of-windows-exceeds-a-certain-depth-x64.aspx
2) http://support.microsoft.com/kb/2664641/en-us