Allowing Enter or Return in controls such as TextBox when using Windows Forms .NET 2.0
Posted by jimblackler on Mar 6, 2008
Many applications feature text input boxes that used to accept input for immediate use by the program. For instance, a program might provide a dialog allowing user to search for text in a document. This would feature a text box to enter the text, and a button next to it labelled ‘search’ that would immediately act on the supplied text.
However many users will not want to click the ‘search’ button, but simply press Return or Enter after entering the text.
How can this be done in a C# .NET 2.0 Windows Forms application? One way is to set the Accept property in the parent form to refer to the ‘search’ button. This will make Enter / Return automatically press the button, when pressed in any child control on the form.
This doesn’t always offer the level of control the application developer wants. Any control could activate the press, not just the relevant text box. It requires a button, which might not always be desirable. Also it is not trivial to allow multiple textboxes on a single form that all accept Enter / Return in that way.
The best way that I have found is to add a KeyDown event to the textbox and compare the pressed key with Keys.Enter. Then, act on that key and set SuppressKeyPress in the event arguments so that the system does not try to do anything further with the keypress. (Typically what happens otherwise is that an ‘error’ beep is played).
- private void textBox1_KeyDown(object sender, KeyEventArgs e)
- {
- if (e.KeyCode == Keys.Enter && e.Modifiers == Keys.None)
- {
- // do something with textBox1.Text
- e.SuppressKeyPress = true;
- }
- }
However if you implement that code and run the application, you’ll find nothing happens when you press Enter. The reason is that the Enter key press never reaches the KeyDown event. This happens because certain key presses are reserved for system use. The solution is to supply a PreviewKeyDown event in the textbox. This gives the opportunity to override the system override as it were, and allow the key to reach the KeyDown even in the textbox.
- private void textBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
- {
- if (e.KeyCode == Keys.Enter && e.Modifiers == Keys.None)
- {
- e.IsInputKey = true;
- }
- }
I’ve provided source for an example application as a zip file. Requires Visual Studio 2005 or later, C# express will also work.
Running Java applications on OSX (Mac), that were developed with NetBeans on Windows
Posted by jimblackler on Jan 1, 2008
Mac and Java 1.6 (or the lack thereof)
Java SE provides a great opportunity to create applications that will run on Windows, Linux and Mac from the same single .jar executable file. All the end user needs is Java installed, and this is installed as standard for many OSes.
Unfortunately at the time of writing, Jan 2008, there is a problem with targeting Macs. Even the latest version of the Mac operating system OSX 10.5 (Leapard) does not include the latest version of Java, 1.6, that has been the default in Windows-based Java IDEs for a year at least.
A beta can be downloaded but this requires registration on the developer sites, cannot run on OSX 1.4 (Tiger), requires an Intel 64 bit processor, and has other restrictions. Right now it’s far from ideal for a mainstream application, and it’s hard to imagine that even when released officially 1.6 will reach a critical mass of deployment until 2009 at least.
The Windows NetBeans to Mac problem
Unfortunately GUI applications developed with the latest Windows NetBeans 5.5 (the free Java API from Sun) require some configuration to allow applications to be developed that run on out-of-the-box Macs. This is not just because of the OSX Java 1.6 problem, but also some glitches with the “backport” targeting in NetBeans. This affects GUI applications developed with NetBeans GUI editor which uses Swing, a cross-platform GUI layer for Java.
It is not enough to set the source level to 1.5 in the project properties, but to continue to use the 1.6 JDK. This will not run on OSX with 1.5 JRE. The error in the Console will be:
java.lang.NoClassDefFoundError: javax/swing/GroupLayout$Group
The problem is that when using NetBeans’ Swing editor with the 1.6 JDK will create code that won’t run on machines that have Java 1.5. This is because it inserts references to javax.swing.GroupLayout, which only exists in 1.6 onwards. Misleadingly, it does this even if ‘source level’ is set to 1.5.
The solution
This can be fixed by downloading the 1.5 JDK (aka the Java Development Kit 5.0 Update 14) and set your NetBeans project to use it. When new Swing GUI elements are created with this JDK set, the IDE uses the org.jdesktop.layout.GroupLayout class instead. This is not built into the JRE but the additional files can be bundled in your .jar. More about this in a second.
The file you require is jdk-1_5_0_14-windows-i586-p.exe and can be downloaded from Sun. Once installed, in NetBeans select Tools->Java Platform Manager. Click Add Platform and choose C:\Program Files\Java\jdk1.5.0_14.
In your applications, in the properties panel, select Libraries, then set the Java Platform to Java Hotspot(TM) Client VM 1.5.0 14-b03 which should now be available. It is important that you do this before you add any Frames as the act of doing this generates the code that must use the correct version of GroupLayout.
The last step is to ensure that the files that 1.5 users (i.e. Mac users) will require are bundled into your .jar, follow the instructions here.
In conclusion
Following these instructions will results in a .jar file that can run on any out-of-the-box installation of OSX, Windows (with latest Java), or Linux.
A great benefit of cross-platform Java SE with Swing is that you can create applications that use all the standard “native” GUI controls for the platforms on which they run. The end-user will have little idea that Java was used, they’ll just see it as an application that looks like it was developed for their choice of OS. To make your Swing applications use native look and feel, follow the instructions under “Programatically Setting the Look and Feel” here
Modular JavaScript enabled user controls in ASP.NET 2.0
Posted by jimblackler on Dec 23, 2007
ASP.NET is great at separating design and code elements on the server side. This extends to a powerful yet simple way of adding your own custom controls to your ASP.NET websites.
It provides a great method to connect HTML elements in an .ascx and back end server code in a .cs file. This approach is quick to get going and has long term scalability too. However, on the web today, developers will want to have the option of client side dynamic code too, in the form of JavaScript elements to add to the control.
Microsoft’s suggestions are useful but only suitable for simple applications such as mouseover effects. This is because they tell you how to add isolated fragments of JavaScript to DOM elements. I wanted a single JavaScript class that had permanent links to DOM elements.
Lately they also provide Ajax tools for ASP.NET, and a framework of Ajax controls. There are some nice controls with these tools. However even with everything installed, what you don’t get is an way of adding your own JavaScript enabled custom controls which is as easy as adding a Web User Control from the Add New Item wizard. I was expecting to see a pattern that simply provided a client side .js file to complement the server side .cs and .ascx files. The AJAX tools seem rather over-complex compared to vanilla ASP.NET 2.0, and worse still, this approach requires .dlls to be installed on the server side. I had to telephone my host to ask them to add the components.
I’ll explain the simpler system I have developed. My aims were:
- To neatly include all the JavaScript in a .js file, containing a parallel JavaScript class for the control.
- To give the JavaScript part access to DOM elements set up in the .ascx (server side) part of the control (either runat=”client” elements type or elements created with runat=”server” controls).
- To give the JavaScript part access to the attributes set on the server side of the control.
- To allow unique HTML IDs, so that there can be more than one control of that type per page, with each control operating independently.
My method enables links not only between server and client sides of a user control, but between controls and their parent elements on the client side (just as could be done on the server side). Think of it as “client-side code behind”.
How it works
- An ASP.NET control is set up in the usual way with code behind which adds the .ascx and .ascx.cs files to the project.
- The developer adds a .ascx.js file to the project for the client-side components, with a matching name.
- function TrackBar(clientID, minimum, maximum, smallChange, barPixelWidth)
- {
- //....
- }
- The developer adds two pieces of JavaScript to the .ascx. Firstly, a client-side include to the .ascx.js script:
- <script type="text/javascript" src="TrackBar.ascx.js"></script>
Below that, a script to create a new instance of the JavaScript object with the expected parameters detailed in the previous step.
- <script type="text/javascript">
- <%=ID%>= new TrackBar('<%=ClientID%>', <%=Minimum%>, <%=Maximum%>, <%=SmallChange%>, <%=BarPixelWidth%>);
- </script>
The “<%=ID%> =” before the ‘new’ creates JavaScript code that sets a variable that contains the JavaScript object associated with the control that is named the same as the server side ID for the control. This could allow JavaScript in the parent page to interact with the control object of the child control.
This contains a single class wrapped with a single function of the same name, and taking as parameters the client ID of the the control, and any properties that the JavaScript object requires to receive from the server-side part. e.g:
The ClientID allows the JavaScript to have access to the DOM relating to its specific instance using the getElementById() function. This is because is possible to predict client IDs of child DOM elements by using the control’s own parent ID. For instance a div declared with <div runat=”server” id=”content”> in a control with client ID “myControl1” will have the client ID “myControl1_content”. In code this could be obtained with getElementByID(clientID + “_content”);
The use of runat=”server” is necessary because although a static client ID could be provided, this would not have a name unique to the page, and would therefore not allow more than one control of that type per form or parent control.
Example
An example with an online demo and full source is presented here. I’ve developed a TrackBar control for ASP.NET similar to the control in Windows Forms. This control is for number entry by a user viewing a web page. It presents a number as a text box, but if the user has JavaScript enabled it also shows a visual slider that can be manipulated with the mouse. The effect on the value can be seen in real time.
The control changes the text in the TextBox which gives a return path of data to the server side. An example of this can be seen in the code in the Default.aspx.cs file.
In addition, a callback can be added to an instance of a TrackBar control on the client (JavaScript) side. An example of this can be seen in the code in Default.ascx.js, where the position and content of a text fragment is changed in real time as the slider is altered.
Breathing exercise timer for Windows, with .NET 3.5, WPF and Visual Studio C# Express 2008
Posted by jimblackler on Dec 2, 2007
A family member requested I write them a simple windows program to help them with some medically-prescribed breathing exercises. For the exercise (which is designed to lower blood pressure) you have to breath in for six seconds, and out again for six seconds. In the absence of a commercial timer available to do this, a dedicated timer program on PC is the next best thing. The program simply displays a bar-chart type graphic with the bars appearing and disappearing to indicate the six second intervals.
A tiny project like this was the perfect opportunity to take the newly-released VS C# Express 2008 for a spin. Initial impressions are good, just like Express 2005 almost everything is there for professional development. It offers both Windows Forms and WPF as options on the New Project wizard, but it seems only to offer 3.5. In other words there seems no easy way of targeting 2.0 or other .NET versions from the wizard. I can confirm that 2.0 projects do load though (after running the conversion wizard) so it must be possible.
I like the WPF designer and the massive flexibility that WPF gives the developer in UI development. For this application, it was possible to add geometric shapes to the interface, which would have been hard in the Windows Forms designer. Also it meant that the window can be set to scale when resized. Being able to switch between a massive timer display and a tiny one could be very useful for users of a program like that.
For reference, the way to have WPF content automatically scale is to wrap the content in a
Installer for One to Six program
Grid rotate puzzle (Flash CS /ActionScript 3.0 for Flash Player 9)
Posted by jimblackler on Nov 13, 2007
I’ve written a simple puzzle game based on an idea I’ve been knocking around. The idea is inspired by slide puzzles and the Rubik’s Cube. Also a lesser-known puzzle called the Rubik’s Clock that I loved as a child.
The objective is to return a grid of numbers to its original form by rotating individual 2 x 2 square bocks by 90 degrees. Hard to explain but give it a go, you’ll work it out quickly I’m sure
The grid starts out straight. You can scramble it yourself or hit the ‘Spin’ button and have it done for you (hit it again to stop the scrambling). You can also experiment with using the slider to create grids of different sizes.
It is worth pointing out something though. When I came up with the idea I thought that it would be about as difficult to complete as a standard slide puzzle. Wrong. It seems very, very difficult. People tend to get very stuck on the last row. In fact, based on a day’s play testing, nobody has yet even completed a 3 x 3 grid.
So give it a try, you could be the first.
Qindar for Windows 3.0 released
Posted by jimblackler on Oct 24, 2007
I received another request by email to update one of my wordgame programs to use the latest CSW dictionary. This time the program was Qindar for Windows (as opposed to my AJAX website Qindar.net).
As it happened I’d been sitting on an updated of Qindar for Windows for a while. Not only had I modernised the dictionaries I’d also added an analyse mode where the valid games for each turn can be viewed after a game. (They can even be viewed during the game if you turn the option on in the settings).
Not only that you can perform a basic “simulation” on moves to estimate the relative strategic value of each alternative.
Other improvements include a challenge mode other than ‘void’, plus the bots from Qindar.net. As all my wordgame programs use the game logic engine it’s easy to port over the benefits.
I’d not put this version out because I’d put a few bugs in somewhere along the line so I wanted to polish it a bit first. I’ve done that now, so I present to you Qindar 3.0. (click) Please do email me or comment here if you find any bugs with it.
Standard whitespace, Visual Studio style
Posted by jimblackler on Oct 15, 2007
Stressing about standard code appearance in a large team project is fairly low on my list of priorities, but it is on the list.
I’m happy to change my style to fit in, but as every project has a different ‘standard’, it’s annoying to have to keep changing.
“The wonderful thing about standards is that there are so many of them to choose from.” Grace Hopper
Visual Studio has, from VS 2002, offered a facility to ‘format’ some code files. This format actually means convert the whitespace to a standard form. This form is apparently of Microsoft’s own design.
I was delighted to see this feature, however, as it meant that there was an easy way that a common format for whitespace could be set in a large team. Yes there are formatting utilities out there, and VS is just one of the many IDEs available. VS is however a very popular IDE in the world of commercial development.
The actual keypresses and modes vary by language, VS version, and configuration. In some modes it is automatic, in others you can press CTRL-E-D. You can format C++, C#, Visual Basic or XML. The .NET languages have controllable options and seem to format more effectively.
Over the last couple of years I’ve got so familiar with the VS format that I apply the style manually when working with non-VS languages like Javascript, Actionscript and PHP.
I have reversed engineered the default VS style so that you can do the same if you like! These are the basics. The general rule is that all tabs and spaces are stripped with the exception of:
Indentation
Braces appear on a line of their own (controversial!) at the same indentation level as the parent. Block content appears indented.
- class MyClass
- {
- int Method()
- {
- return 3;
- }
- }
Case labels and content are each indented.
- switch (name)
- {
- case "John":
- break;
- }
Comments appear in the first column without indentation.
Indentation is not changed for the second and further lines for any instruction that spills over multiple lines. The default however is that it is indented from the first line.
- {
- bool receiveMessage( Stream & stream,
- int & header, int & size );
- }
Spaces after keywords
Spaces are placed between keywords (if, switch, for, return, etc.) and the content that follows, unless it is ;. So you have
- return (x);
.. which contrasts with no space in a function call such as ..
- SomeFunc(x);
Spaces between mathematical operators
Brackets are not followed by spaces, but a single space appears between other mathematical operators.
- int y = (3 + 4 / 2 - 6 + (4 + 2 * array[4]));
Spaces after commas and semicolon separators
- SomeFunc(4, x, 5);
- for(int count = 0; count != 9; count++)
- {
- }
That’s pretty much it. It’s a simple summary, no doubt a more accurate, formal one could be prepared. But that’ll give you the basics
Other aspects of code standardisation such as standard naming conventions are not currently supported by VS. It would be interesting to see an optional scheme where violations of some convention could be flagged as errors.
Safely adding events to DOM elements in Javascript for IE, Firefox, Opera and Safari
Posted by jimblackler on Sep 29, 2007
Recently I looked into some reported problems with my word game site Qindar.net and the Safari browser. This was a bit easier for me since Apple released a Windows version of Safari (which, albeit arguably surplus to requirements, is actually a very nice, usable browser on Windows).I discovered that the technique I was using to work out which method of event attachment to use was flawed and was failing for Safari. So I refined it slightly to fix the problem.
The problem is that Javascript on Firefox, Opera and Safari support the “W3C DOM Level 2 event binding mechanism”, which uses a function on DOM elements called addEventListener. Internet Explorer however uses a technique that was apparently from before that particular standard was drawn up, employing a function called attachEvent. In addition, the names of the events are different. For instance, IE uses events such as “onmousemove”, “onmouseup”, but the other browsers omit the “on” and name these events “mousemove” and “mouseup”.
Curiously, Opera is the only browser to support both styles.
The simplest and safest way of working out which one to use is simply to test for the existence of a function called addEventListener. I quite like this method because it works on the latest version of the big four browsers, and IE 6, without having to do any browser version probing.
For instance, here is how to add focus and focus lost events to a page in a way that will work on all modern browsers:
[Javascript]
if (window.addEventListener != null)
{ // Method for browsers that support addEventListener, e.g. Firefox, Opera, Safari
window.addEventListener(“focus”, FocusFunction, true);
window.addEventListener(“blur”, FocusLostFunction, true);
}
else
{ // e.g. Internet Explorer (also would work on Opera)
window.attachEvent(“onfocus”, FocusFunction);
document.attachEvent(“onfocusout”, FocusLostFunction); //focusout only works on document in IE
}
[/Javascript]
This is how to add mouse events:
[Javascript]
if (document.addEventListener != null)
{ // e.g. Firefox, Opera, Safari
document.addEventListener(“mousemove”, MouseMoveFunction, true);
document.addEventListener(“mouseup”, MouseUpFunction, true);
}
else
{ // e.g. Internet Explorer (also would work on Opera)
document.attachEvent(“onmousemove”, MouseMoveFunction);
document.attachEvent(“onmouseup”, MouseUpFunction);
}
[/Javascript]
To remove the mouse events, I recommend…
[Javascript]
if (document.removeEventListener != null)
{ //e.g. Firefox, Opera, Safari
document.removeEventListener(“mousemove”, MouseMoveFunction, true);
document.removeEventListener(“mouseup”, MouseUpFunction, true);
}
else
{ //e.g. Internet Explorer (also would work on Opera)
document.detachEvent(“onmousemove”, MouseMoveFunction);
document.detachEvent(“onmouseup”, MouseUpFunction);
}
[/Javascript]
I personally pray there comes a time when these kinds of workarounds are not required. In the mean time, this will have to do.
Scraping text from Wikipedia using PHP
Posted by jimblackler on Sep 25, 2007
Wikipedia has grown from one of many interesting websites to being one of the most famous sites on the Internet. Millions of volunteer years have been invested over the years, and the pay off is what we have today – a wealth of factual data in one place.
When Wikis were a new concept, many predicted they would descend into chaos as they grew. In the case of Wikipedia the reverse is true. It seems to become increasingly well organised as the site develops. Rather than becoming more jumbled, the natural development of article conventions and the more planned use of standardised templates has created an increasingly neat and consistent structure.
This careful organisation of the prose leads to the interesting possibility of extracting more structured data from Wikipedia for alternative purposes, while staying true to the letter and spirit of the GFDL under which the material is licensed.
There’s the potential for a kind of semantic reverse engineering of article content. HTML pages could be scraped, and pages scoured for hints as to the meaning of each text fragment.
Applications could include loading articles about a variety of subjects into structured databases. Subjects for this treatment could include countries, people, chemical elements, diseases, you name it. These databases could then be searched by a variety of applications.
I’ve knocked up a simple page that gives a kind of quasi-dictionary definition when a word is entered. It looks at the first sentence of the Wikipedia article, which typically describes the article topic concisely.
I’ll show here how the basic page scrape works, which is actually very easy with PHP, its HTML reading abilities and the power of xpath.
- $html = @file_get_contents(“http://en.wikipedia.org/wiki/France”); will pull down the HTML content of the Wikipedia article on France.
- $dom = @DOMDocument::loadHTML($html); will read the HTML into a DOM for querying.
- $xpath = new domXPath($dom); will make a new xpath query.
- $results = $xpath->query(‘//div[@id=”bodyContent”]/p’); will find the first paragraph that is a direct child of the div with the id “bodyContent”. This is where the article always starts in a Wikipedia article page.
I then perform some more processing on the results including contingencies for if any of the steps fail. For instance to make the definitions snappier reading I strip any text in brackets, either round or square. There’s also some additional logic to pick the first topic in the list if the page lists multiple subjects (a “disambiguation” page). Predicting the Wikipedia URL for a given topic also involves a small amount of processing.Anyway, when you ask the page “what is France”, it will reply..
France, officially the French Republic, is a country whose metropolitan territory is located in Western Europe and that also comprises various overseas islands and territories located in other continents.
Can’t argue with that!
Edit, 1st March: By request, here is the source of the WhatIs application. It will work in any LAMP environment but the .sln file is for VS.PHP under Visual Studio 2005.
Overriding the backspace key using JavaScript, in Firefox, IE, Opera and Safari
Posted by jimblackler on Sep 21, 2007
In my web wordgame Qindar.net I wanted to allow the players to use the keyboard to place words on the game board. This included use of the arrow keys to navigate, and the backspace key to ‘delete’ wrongly placed letters.
The problem is that even when this is handled in JavaScript, most browsers still catch the backspace key and interpret it as a user request to go back to the previous page. Boom! There goes your game page, and one annoyed user.
I did find a way of masking the backspace key that works in all the browsers I have tested it against. The trick for most browsers is to override the onkeydown event, check for event number “8” and return ‘false’ from that event. This signals to the browser not to process that key.
As often happens one particular browser is troublesome, in this case it was Opera, that needed “onkeypress” overriding rather than “onkeydown”.
Yesterday I had an email query recently asking how this was done so I’ve detailed it here.
There’s a demo here. Select ‘View Source’ in your browser to see how it’s done.
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml" >
- <head>
- <title>Backspace Browser Trap Demo</title>
- </head>
- <body>
- <p>Try pressing backspace on this page.</p>
- <p>Note you can still go 'back' with Alt + Left</p>
- <p id="keypressed"></p>
- <script type="text/javascript" language="javascript">
- // function to possibly override keypress
- trapfunction = function(event)
- {
- var keynum;
- if (window.event) // eg. IE
- {
- keynum = window.event.keyCode;
- }
- else if (event.which) // eg. Firefox
- {
- keynum = event.which;
- }
- if (keynum == 8) // backspace has code 8
- {
- document.getElementById("keypressed").innerHTML = "Backspace pressed";
- // display a message
- return false;
- // nullifies the backspace
- }
- return true;
- }
- document.onkeyup = function(event)
- {
- document.getElementById("keypressed").innerHTML = ""; // clear the message
- return true;
- }
- document.onkeydown = trapfunction; // IE, Firefox, Safari
- document.onkeypress = trapfunction; // only Opera needs the backspace nullifying in onkeypress
- </script>
- </body>
- </html>