Technical Journal

Programming, software technologies, operating systems, IT

Registry Capture Utility

I recently moved to Windows  7, but I still use Visual Studio 2005 Professional for my work. I have a rather complicated setup project, and when I built it the environment threw and error saying Microsoft Vsual Studio Registry Capture utility has stopped working.

After a little research on the web I have found it was a compatibility issue of regcap.exe. To fix the issue, the workaround is to browse to the regcap.exe location, which typically is under C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Deployment, right click it and under the Compatibility tab select Windows Vista(Service Pack2) mode.

I have re-run my setup project and I don’t get a crash anymore.

July 6, 2011 Posted by | Windows | Leave a Comment

Unit Testing

Software testing is a very important stage of software development; the better the software product is tested the higher the quality of your work gets.
This post is just opening a series of small entries in which I will try to get the best out of software testing techniques and make use of them in
further development processes.
I’ve started browsing the web and reading books. Up until now, I’ve found a nice book on unit testing (xUnit Test Patterns: Refactoring Test Code (Addison-Wesley Signature Series) ), which sheds some light on the topic. I plan on using NUnit to perform my unit testing, which is fairly easy to use and it’s free.
Of course, unit testing is not all there is to software testing, but this is where I’ll start. More on this to follow.

May 12, 2009 Posted by | Uncategorized | Leave a Comment

Enum to List

I’ve found this method useful lately so I thought I should add it here where everyone can see it.
It is meant to be used with the .NET Compact Framework. In the full framework this would have been much easier -
without reflection.
What the method does is that it adds the enum’s fields to a generic list of the same type T as the enum.

public static List EnumToList( )
{
Type enumType = typeof( T );

if( enumType.BaseType != typeof( Enum ) )
{
throw new ArgumentException( “Not an enum type!” );
}

List enumFieldList = new List( );

FieldInfo[ ] enumFields = typeof( T ).GetFields( );

foreach( FieldInfo fieldInfo in enumFields )
{
if( !fieldInfo.IsSpecialName )
{
enumFieldList.Add( (T) Enum.Parse( enumType, fieldInfo.Name, false ) );
}
}

return enumFieldList;
}

April 24, 2009 Posted by | Windows CE | , , , , | Leave a Comment

Zeitgeist

This movie contains some thinghs that I’ve already aknowledged during time and others I just found out. I think we should see all sides of our social existence and not just the one we are being served. I am not saying that everything here is the truth, but it certainly looks like the truth. The zeitgeist does not look like a heaven for the ordinary people.

http://video.google.com/videoplay?docid=-594683847743189197

April 12, 2009 Posted by | Uncategorized | | Leave a Comment

Windows CE Full Screen applications

The first task I had to do when I started developing my first Windows CE application was to make my main program window appear in full screen mode. After some research I came across a small article posted on Code Project. It describes a method of showing a window in full screen mode using standard window management calls which is what I was looking for. I completed the source with proper definitions of system calls and structures. I provide this source code along with a basic test application.

            The usual method of doing this would have been to use SHFullScreen, but I was not able to use this function as my OS Design was not to contain aygshell.dll, the library from which this function was part of.

            I am developing under .NET Compact Framework 2.0.

            First, I had to define some useful enums containing constants of the Windows API. Here are some of them, for the rest please see the attached project as this post would grow unreasonably if I pasted them here.

      [Flags( )]

      internal enum FullScreenFlags : int

      {

            SwHide = 0,

            ShowTaskbar = 0×1,

            HideTaskbar = 0×2,

            ShowSipButton = 0×4,

            HideSipButton = 0×8,

            SwRestore = 9,

            ShowStartIcon = 0×10,

            HideStartIcon = 0×20

 

      }

 

      internal enum Hwnd : int

      {

            HWND_TOP = 0,

            HWND_BOTTOM = 1,

            HWND_TOPMOST = -1,

            HWND_NOTOPMOST = -2

      }

 

            A very useful thing to do is to check www.pinvoke.net and retrieve the values of certain constants that you would make use of in various situations.

            Next, I had to implement a static class that imports my needed functions from coredll.dll. This dll is very useful to get acustomed with because in it you will find system calls that you are very likely to need in your development process under .NET CF. So, here is what you need:

 

      public static class Coredll

      {

            /// <summary>

            /// The function retrieves the handle to the top-level

            /// window whose class name and window name match

            /// the specified strings. This function does not search child windows.

            /// </summary>

            /// <param name=”lpClass”></param>

            /// <param name=”lpWindow”></param>

            /// <returns></returns>

            [DllImport( "coredll.dll", SetLastError = true )]

            public static extern IntPtr FindWindowW( string lpClass, string lpWindow );

 

            [DllImport( "coredll.dll", SetLastError = true )]

            public static extern bool ShowWindow( IntPtr hwnd, int state );

 

            [DllImport( "coredll.dll", SetLastError = true )]

            public static extern bool SetWindowPos( IntPtr hwnd, IntPtr hwndAfter,

                                                                              int xPos, int yPos, int cX, int cY, int wFlage );

 

            [DllImport( "coredll.dll" )]

            public static extern int GetSystemMetrics( int smIndex );

 

            [DllImport( "coredll.dll", SetLastError = true )]

            [return: MarshalAs( UnmanagedType.Bool )]

            public static extern bool SystemParametersInfo( Spi uiAction, uint uiParam, IntPtr pvParam, Spif fWinIni );

 

            [DllImport( "coredll.dll", SetLastError = true )]

            [return: MarshalAs( UnmanagedType.Bool )]

            public static extern bool SystemParametersInfo( Spi uiAction, uint uiParam, String pvParam, Spif fWinIni );

 

            [DllImport( "coredll.dll", SetLastError = true )]

            [return: MarshalAs( UnmanagedType.Bool )]

            public static extern bool SystemParametersInfo( Spi uiAction, uint uiParam, ref AnimationInfo pvParam, Spif fWinIni );

 

            [DllImport( "coredll.dll", EntryPoint = "SystemParametersInfo", SetLastError = true )]

            public static extern bool SystemParametersInfoGet( uint action, uint param, ref uint vparam, uint init );

 

            [DllImport( "coredll.dll", EntryPoint = "SystemParametersInfo", SetLastError = true )]

            public static extern bool SystemParametersInfoSet( uint action, uint param, uint vparam, uint init );

 

            /// <summary>

            /// to find whether you are running on a Smartphone or a Pocket PC

            /// </summary>

            /// <param name=”uiAction”></param>

            /// <param name=”uiParam”></param>

            /// <param name=”pvParam”></param>

            /// <param name=”fWinIni”></param>

            /// <returns></returns>

            [DllImport( "Coredll.dll", EntryPoint = "SystemParametersInfoW", CharSet = CharSet.Unicode )]

            public static extern int SystemParametersInfo4Strings( uint uiAction, uint uiParam, System.Text.StringBuilder pvParam, uint fWinIni );

      }

           

            Now, to put things toghether here are the two methods needed to enter full screen mode and end it:

 

            public static void StartFullScreen( Control control )

            {

                  IntPtr hWndInputPanel = Coredll.FindWindowW( “SipWndClass” , null );

                  IntPtr hWndSipButton = Coredll.FindWindowW( “MS_SIPBUTTON”, null );

                  if( hWndInputPanel != null ) Coredll.ShowWindow( hWndInputPanel, SW_HIDE );

                  IntPtr hWndTaskBar = Coredll.FindWindowW( “HHTaskBar”, null );

 

                  IntPtr hWnd = control.Handle;

 

                  if( hWndTaskBar != null ) Coredll.ShowWindow( hWndTaskBar, (int) Sw.SW_HIDE );

                  if( hWndInputPanel != null ) Coredll.ShowWindow( hWndInputPanel, (int) Sw.SW_HIDE );

                  if( hWndSipButton != null ) Coredll.ShowWindow( hWndSipButton, (int) Sw.SW_HIDE );

 

                  Coredll.SetWindowPos(

                        hWnd, (IntPtr) ( (int)Hwnd.HWND_TOPMOST ), 0, 0,

                        Coredll.GetSystemMetrics( (int) SystemMetric.SM_CXSCREEN ),

                        Coredll.GetSystemMetrics( (int) SystemMetric.SM_CYSCREEN ),

                        (int) Swp.SWP_SHOWWINDOW );

            }

 

            public static void StopFullScreen( Control control )

            {

                  //IntPtr hWndInputPanel = Coredll.FindWindowW( “SipWndClass” , null );

                  IntPtr hWndSipButton = Coredll.FindWindowW( “MS_SIPBUTTON”, null );

                  IntPtr hWndTaskBar = Coredll.FindWindowW( “HHTaskBar”, null );

 

                  IntPtr hWnd = control.Handle;

 

                  Rect rtDesktop = new Rect( );

 

                  if( hWndTaskBar != null )

                  {

                        Coredll.ShowWindow( hWndTaskBar, (int) Sw.SW_SHOW );

                  }

                  //Never forcibly show the input panel

                  //if( hWndSipButton != null )

                  //{

                  //    Coredll.ShowWindow( hWndSipButton, Sw.SW_SHOW );

                  //}

 

                  IntPtr rectPtr = Marshal.AllocHGlobal( Marshal.SizeOf( rtDesktop ) );

 

                  if( Coredll.SystemParametersInfo( Spi.SPI_GETWORKAREA, 0, rectPtr, Spif.None ) ) )

                  {

                        Rect rect = (Rect) Marshal.PtrToStructure( rectPtr, typeof( Rect ) );

 

                        Coredll.SetWindowPos( hWnd, (IntPtr) ( (int) Hwnd.HWND_TOPMOST ), 0, 0, rect.right – rect.left, rect.bottom – rect.top, (int) Swp.SWP_SHOWWINDOW );

                  }

                  Marshal.FreeHGlobal( rectPtr );

            }

 

            The first method, StartFullScreen, hides the SIP( Standard Input Panel ), the SIP button bar and the task bar leaving the entire screen to be filled by the application window. The application window’s size is set to the size of the entire screen in SetWindowPos. It’s that simple!

            When you want to exit full screen mode, you need to show the task bar, get the size of the client work area, specified with Spi.SPI_GETWORKAREA and then calculated the new size of the window( it would appear as a maximized window on your screen ).

You can download a sample project form 4shared: Source code here.

April 12, 2009 Posted by | Windows CE | , , , , , , | 7 Comments

C++ UNREFERENCED_PARAMETER

I am currently developing a driver for one of our custom made devices under Windows CE and I came across this macro -

UNREFERENCED_PARAMETER in one of the driver examples I took as reference for developing my own. The definition itself does not say much:

#define  UNREFERENCED_PARAMETER(P) (P)

All it does is to layout the parameter or expression it has been passed. After some browsing on the internet I’ve found this post by Paul DiLascia:

http://msdn.microsoft.com/en-us/magazine/cc163805.aspx which I think greatly explains what is meant by compiling with Warning Level 4 – it made me a believer anyway.

Indeed, an unreferenced parameter would cause an error when compiling using level 4 and this is where UNREFERENCED_PARAMETER comes in handy.

For instance you have a function like this:

void foo( int arg1, float arg2 )

{

     UNREFERENCED_PARAMETER( arg1 );

}

Since you won’t be using arg1 and also you will compile with level 4, you just fool the compiler by passing arg1 as parameter to a macro that just adds the line:

arg1;

to your code. And since it is not used the compiler does not generate code for it and no efficiency or space is lost.

I will not repeat here stuff written in that post, just thought I’d mention it as a great post on C++ I’ve found.

April 7, 2009 Posted by | Programming | , | Leave a Comment

Install an application for all users

In this article I present techniques based on Visual Studio 2005 Deployment, C#, Windows Registry. 

I have recently encountered one of those errors you should expect but you don’t. I have an application for which I have created an installer project, under Visual Studio 2005. The application works fine after installation for the administrative role user that installed it, but when switching to a less priviledge user on the same computer the install/ repair program starts for that user prompting for the installation kit path. As an aditional detail, the setup kit creates the application registry keys it requires under HKEY_CURRENT_USER key. And this is the flaw…

When creating registry entries for an application that might be used by more than one user, each of which having different access rights on the computer, we should place the registry key under the “user/ machine hive” node in the Registry view of the deployment project. This way we ensure that the keys get into the right place when the application is first installed. According to Microsoft’s definition, the keys placed under user/ machine hive will be placed either under HKEY_CURRENT_USER when the application is insalled only for one user and under HKEY_LOCAL_MACHINE when the application is intalled for all users. Here is a screenshot :

 Visual Studio Registry View

The problem with keys under HKEY_LOCAL_MACHINE is that they are read only for restricted users, for example user belonging only to the “Users” group. It is though required to assign special permissions for those keys a user not only to read but also modify. The reason I needed this was to save some user settings in the registry, so when a less privileged user saves the settings, he/ she must also have proper permisions.

To solve my problem I’ve created a custom installer class implemented an event handler for the Commited event. In this handler, write access permissions are given to users belonging to the “Users” group.

I give bellow the implementation of my event handler.

// Event handler for ‘Committed’ event.

private void CustomInstaller_Committed( object sender, InstallEventArgs e ){

RegistryKey hkCustom = null;RegistryKey hkTester = null;

// depending on the installation options, we will search for the application’s registry keys :

// 1. – if installation is performed just for the current user, the keys will be under HKEY_CURRENT_USER

// 2. – else if the installation is performed for all users, the keys will be under HKEY_LOCAL_MACHINE

hkCustom = Registry.CurrentUser.OpenSubKey( “Software” ).OpenSubKey( “CustomInstallerTester” );if( hkCustom != null ){

hkTester = hkCustom.OpenSubKey( “Tester99″, RegistryKeyPermissionCheck.ReadWriteSubTree /*required*/ );}

if( hkTester == null ){

hkCustom = Registry.LocalMachine.OpenSubKey( “Software” ).OpenSubKey( “CustomInstallerTester” );

}

if( hkCustom != null ){

if( hkTester == null ){

hkTester = hkCustom.OpenSubKey( “Tester99″, RegistryKeyPermissionCheck.ReadWriteSubTree /*required*/ );}}

 

if( hkTester != null ){

System.Security.AccessControl.RegistrySecurity regSec = new System.Security.AccessControl.RegistrySecurity( );// grant write permissions to the users group :

regSec.AddAccessRule( new RegistryAccessRule( “users”,

RegistryRights.ReadKey | RegistryRights.WriteKey | RegistryRights.Delete,

InheritanceFlags.ContainerInherit,PropagationFlags.None,

AccessControlType.Allow) );hkTester.SetAccessControl( regSec );}

 

if( hkTester != null ) { hkTester.Close( ); }

if( hkCustom != null ) { hkCustom.Close( ); }

 

}

 

 

February 19, 2008 Posted by | Programming, Windows | 5 Comments

Vista usb driver installation issues

Recently, I’ve made a fresh install of Windows Vista on my Dell laptop. My troubles started when I tried to plug in a usb device that I needed to program.

Vista found my device, displayed it’s name in the Device Manager and started to install the driver for it. The installation seemed to go fine when it suddenly finished with an error message :

“Windows encounterd a problem installing the driver software for your device” … “Could not find the file specified.”.

I was astonished… I tried reinstalling the driver several times by manually specifying the path to my driver. I KNEW it was there.

The solution came by inspecting the log file : C:\Windows\inf\setupapi.dev.log. In the last entry I’ve found that Vista was not searching for the driver in the proper location, meaning C:\Windows\system32\drivers, but in a new location that I suspect, comes from a bug in the driver path formation. Vista was expecting the driver files ( .sys ) in C:\Windows\inf\system32\drivers.

So, what was left to do was to copy my .sys file in the folder Vista expects it to be and it all turned out fine. Now my device is installed and ready to use :) . I need to point out that the expected folder did not exist, so I had to create it myself. As Microsoft so obsessively suggests, “make sure you have administrator privileges for this action”.

You may find another strange location Vista wants your driver to be, so I think a good point to start is by first analysing the setupapi.dev.log file I just mentioned.

November 13, 2007 Posted by | Windows | 3 Comments

Choosing the default playback device in Xp

The theme of this post is one I have been fascinated for the last few days. The situation arises when you have more than one audio device attached to your computer. One might be the default audio device for your system while the other might be a USB audio device( like another audio usb board or a usb headset ). In the application I am working on, the user is required to record an audio note through an iMic usb system and in order to listen to that note, the default system playback device must be used. ( I will not waste the time explaining why, it is not relevant ). This configuration applies in other circumstances as well and I thought it would be usefull to post an entry about it.

As you are probably aware, when inserting a new usb audio device into your computer’s usb port, the default playback and recording device is set to the new usb device. You can do something about that too, but only if you write a custom driver for the usb devices such that they are not set as defaults upon insertion.

There is no clean way to change the playback and recording devices programatically. And there seems to be NO way in Vista. You must set the default playback and recording devices manually from Control Panel/ Sounds and Audio Devices. And this is a “feature” of the operating system, not a bug.

Oh, well… I’ve found a solution for this problem in XP. The basic idea is that you must modify a registry key and then restart explorer.exe. My implementation is in C#, but this is not language dependent.

The Registry :

I assume you are familiar with the Audio setting control panel, and I will jump to presenting the registry entries you must change.

First, you must open the registry editor and browse to the following key :

HKEY_CURRENT_USER\Software\Microsoft\Multimedia\Sound Mapper\

sound mapper keys

This is how the registry keys under Sound Mapper look like in my case. As you can see, the UserPlayback and UserRecord keys are filled with the system’s default audio device. The Playback and Record keys represent the current playback and recording devices.

Implementation :

Bellow, I give the two methods I use to get and set the audio playback devices:

public string GetDefaultDevice( )
{

RegistryKey soundMapper = null;

soundMapper = Registry.CurrentUser.OpenSubKey(“Software”).OpenSubKey(“Microsoft” ).OpenSubKey( “Multimedia” ).OpenSubKey( “Sound Mapper”, true );

if ( soundMapper != null )

{

string userPlayback= Convert.ToString(soundMapper.GetValue(“UserPlayback”, string.Empty));

return userPlayback;

}

return string.Empty;

}

/// <summary>
/// Sets the audio device with the provided description as the default playback device.
/// USE WITH CARE. THE DEVICE YOU MAY BE TRYING TO SET AS DEFAULT

///MAY NOT EXIST IN YOUR HARDAWARE CONFIGURATION

///</summary>
/// <param name=”deviceDescription”>Audio device description to be written to registry.</param>

public void SetDefaultDevice( string deviceDescription )
{

RegistryKey soundMapper = null;

soundMapper = Registry.CurrentUser.OpenSubKey(“Software”).OpenSubKey(“Microsoft” ).OpenSubKey( “Multimedia” ).OpenSubKey( “Sound Mapper”, true );

if ( soundMapper != null )

{

string playbackDev = Convert.ToString( soundMapper.GetValue( “Playback”, string.Empty ) );

if ( playbackDev != string.Empty )

{

if ( playbackDev != deviceDescription )

{

soundMapper.SetValue( “Playback”, deviceDescription, RegistryValueKind.String );

soundMapper.Flush();

soundMapper.Close( );

// restart explorer.exe :

// 1. kill explorer

foreach(Process p in Process.GetProcessesByName(“explorer”))

{

try
{

p.Kill( );

}

catch ( Exception ex )
{
System.Diagnostics.Debug.WriteLine( ex.Message + “\n” + ex.StackTrace );
}

}

// 2. the OS restarts explorer automatically

return;

}

}

soundMapper.Close( );

}

}

Note that these two can be used together, when you want to set the playback device as the default device :

string defaultDevice = GetDefaultDevice( );

SetDefaultDevice( defaultDevice );

However, you can use the SetDefaultDevice method to set the Playback device to any device you want, as long as it exists. You must know the device description string in order to do that. This string is the one presented in the Audio settings control panel and should be an exact match in your code.

You can list the audio devices yourself, from inside your code, if you are willing to use the DirectX library.

Note that in SetDefaultDevice, I have killed all explorer processes in the system. Windows will restart explorer automatically, so you don’t have to worry about that.

If you are using forms, do not make the registry chages inside the Load event handler but in the constructor. Otherwise, the changes will not be seen until the next time you restart your application.

So, I hope this will be of any help to you. And if you find another solution to this issue, I will be glad to hear about it. Thanks.

August 21, 2007 Posted by | Windows | 4 Comments

.NET NumericUpDown crash workaround

I encountered the following problem when trying to handle a NumericUpDown_ValueChanged event :

In the event handler, the code was very similar to this template :

if( someVal > numericUpDown.Minimum && someVal < numericUpDown.Maximum )

{

// do something here

}

else

{

MessageBox.Show( “Some message” );

}

When the user holds the mouse pressed on one of the control arrows and the MessageBox is to be shown, I get an exception that is more than unexpected.

Here is the complete stack trace :

System.Transactions Critical: 0 : <TraceRecord xmlns=”http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord”
Severity=”Critical”>
<TraceIdentifier>http://msdn.microsoft.com/TraceCodes/System/ActivityTracing/2004/07/Reliability/Exception/Unhandled</TraceIdentifier>
<Description>Unhandled exception</Description>
<AppDomain>YOUR_PROJECT_NAME.vshost.exe</AppDomain><Exception>
<ExceptionType>System.NullReferenceException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>Object reference not set to an instance of an object.</Message>
<StackTrace> at System.Windows.Forms.UpDownBase.UpDownButtons.TimerHandler(Object source, EventArgs args)

at System.Windows.Forms.Timer.OnTick(EventArgs e)
at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at

… your line of code …

at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()</StackTrace><ExceptionString>System.NullReferenceException: Object reference not set to an instance of an object.
at System.Windows.Forms.UpDownBase.UpDownButtons.TimerHandler(Object source, EventArgs args)
at System.Windows.Forms.Timer.OnTick(EventArgs e)
at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at

… your line of code …

at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()</ExceptionString></Exception></TraceRecord>
A first chance exception of type ‘System.Threading.ThreadAbortException’ occurred in mscorlib.dll

As I was to find out digging some Microsoft forums, this is a known, documented issue of the
Microsoft .NET framework. ( https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=251486&wa=wsignin1.0 ).

The workaround is available on this forum and it was of real help to me :

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1554539&SiteID=1.

Basically, “the control does not expect to get a message while it is executing an event handler. The workaround delays your response and lets the control finish its event handling. “

This is a sample( skeleton ) of my code, that uses a delegate instead of the MethodInvoker on the Microsoft forum example :

private delegate void CallMethodParam2( double x, bool y );

private void NumericUpDown_ValueChanged(object sender, EventArgs e)
{

if ( (someVal >= numericUpDown.Minimum ) && ( someVal <= numericUpDown.Maximum ) )
{

// some code

}
else
{

// Cancel changes
this.ShowError( someVal );

}

}

private void ShowError( double someVal )
{

bool bLess = true;

double val = 0;

if ( someVal<= numericUpDown.Minimum )
{

bLess = true;

val = numericUpDown.Minimum ;

}
else if ( someVal >= numericUpDown.Maximum)
{

bLess = false;

val = numericUpDown.Maximum;

}
this.BeginInvoke( new CallMethodParam2( this.ShowError ), new object[ ] { val, bLess } );

}
private void ShowError( double dist, bool bLess )
{

string text = “Distance “+ ( ( bLess ) ? “less” : “greater” ) + ” than ” + dist.ToString( ) +” not allowed!”;

MessageBox.Show( text, “Error”, MessageBoxButtons.OK, MessageBoxIcon.Error );

}

July 30, 2007 Posted by | Windows | 1 Comment

Follow

Get every new post delivered to your Inbox.