This article just tells the problem encountered when I was implementing a custom dropdown for a custom UITypeEditor control.
When user opens a dropdown form by clicking on dropdown button on UITypeEditor. And provides input to form by mouse click/enter key/esc key input is read from form. This has been implemented using the .Net UITypeEditors concept. Please refer MSDN for more information.
Coming to the actual details, when dropdown button is clicked IWindowsFormEditorService.DropDownControl method is called to show the dropdown form. IWindowsFormEditorService interface is implemented by EditorService class. When dropdown is shown and if we provide input the dropdown use to closed and input is not returned to the control.
This happens because the mouse clicks/enter/esc events are reached to actual form rather than the dropdown form. And for this solution is, using same old DoEvents method. By calling DoEvents method of the System.Windows.Forms.Application class causes processing of all the Windows messages in the current thread's message queue. This method is called in a loop until dropdown is closed.
Code: public class UITypeEditorContainer { public void DisplayDropDown() { // Display the form. Show(); //wait until form is deactivated while (m_IsFormDeactivated == false) { Application.DoEvents(); } } }
This solved my one issue and raised another issue of 100% CPU utilization. When form is dropdown task manager shows 100 present CPU utilization (which doesn’t consume 100% cpu time). This is caused because the DoEvents are called in a loop and thread reentry occurred.
To solve this I have looked the dot net PropertyGrid implementation using Reflector. It has a similar implementation. There I found that it was calling MsgWaitForMultipleObjects after DoEvents call. It is a standard Win32 API function. The purpose of the function is to suspend the calling thread until one or all of the object handles become signaled. For more information you can look in MSDN.
Code: public class UITypeEditorContainer { public void DisplayDropDown() { // Display the form. Show(); //wait until form is deactivated while (m_IsFormDeactivated == false) { Application.DoEvents(); Win32.MsgWaitForMultipleObjects(1, 0, 1, 250, 255); } } }
Unfortunately Microsoft has not documented calling of this function this way. Once used this function my 100% CPU utilization problem disappeared.
|
| Author: Prafulla S Shimpi 15 Sep 2008 | Member Level: Gold Points : 1 |
Hi Shiva,
Very nice article/ solution.
In fact we should use Do Events to clear up the events when any task gets completed.
I didnt check for CPU utilization earlier. but now i will definitely try.
Thanks once again.
|