Showing posts with label WPF. Show all posts
Showing posts with label WPF. Show all posts

Friday, May 28, 2010

WPF program crashes when started from within a 16-bit DOS program

Scenario: I am programming a Windows application in VB.NET using Windows Presentation Foundation. My program is going to be started from within another old-style 16-bit program, hence this starter program runs in NTVDM (NT Virtual Dos Machine - the way Windows creates backwards compatibility with Windows 3.x/MS-DOS programs). Yes, they are actually still being used out there - the app I am programming is a helper app for the medical journal system WinMed.

Problem: Starting my app by double-clicking its EXE file is no problem, neither is starting it from a command prompt - from a cmd.exe command prompt, that is. But starting the program from within the 16-bit WinMed (it has a customizable menu for starting external programs) or from a command.com (=16-bit) command prompt, immediately results in a crash simply stating: "A problem caused the program to stop working correctly. Please close the program". Why it stopped working is kept a secret.

Cause: I had a strong hunch that NTVDM has something to do with it, since starting my app from both command.com and from within the WinMed program fails. Then I found this post: The environment variable WINDIR is missing from the NTVDM environment. This can be easily checked by running a command.com window and type the set command - all environment variables are then listed. I found that no WINDIR setting was present in this list of environment variables.

Solution: To run the program from the command.com command prompt, I had to first run the following command:
set windir=c:\windows
Now I was able to start the program from within command.com. To ensure that the environment variable was always set when running NTVDM programs, I edited the c:\windows\system32\autoexec.nt file by adding the above command to the end of it - making sure I had no spaces before or after the equal sign. Now my app starts even from within WinMed!


Tuesday, April 7, 2009

WPF DatePicker: Replace/remove the "Show Calendar" string

Scenario: I am programming in VB.NET using WPF (Windows Presentation Foundation) as the visual platform. The program will among other things also ask the user to select a date. I found and installed the WPF Toolkit from the Microsoft CodePlex website, which includes the DatePicker tool in question.

Problem: This post will probably be obsolete in a few months, but for those of us who needs to use the WPF Toolbox DatePicker tool in its current (April 2009) state in their applications, there's no straightforward way to remove the "Show Calendar" text that shows up on the DatePicker text field when no date is selected. I needed to start out with a blank date - selecting one would be optional for the user.

Solution: On the CodePlex website, they will tell you how to modify the xaml template to achieve just that, but I came up with an (imho) ingenious - or should we say quick and dirty - solution to avoid fiddling with all that. Basically this method consists of two steps:
  1. Put a blank Textbox on top of the DatePicker control so that only the date icon shows
  2. Add a a couple of code lines to control the transfer of the date between the text box and the date picker.
To acheive no. 1, I had a grid control on my xaml where both the DatePicker and the TextBox are aligned in the same position, e.g. Margins 0 of the grid cell in question.

I found 85 to be just the right length to cover the DatePicker's text field, without hiding its icon. I removed tabstop from the DatePicker to avoid ever landing at the DatePicker's text field that is hidden behind the TextBox, when using the keyboard to navigate in the app. The xaml looks like this:

<my:datepicker height="24" verticalalignment="Top" istabstop="False" textbox="" row="0" column="1" margin="0" name="DatePicker1" horizontalalignment="Left" width="85">

<TextBox Grid.Row="0" Grid.Column="1" Margin="0" Name="TextBox1" HorizontalAlignment="Left" Width="85" />

Now, the only thing needed is a couple of event handlers to transfer the dates back and forth:


Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.TextChangedEventArgs) Handles TextBox1.TextChanged
DatePicker1.Text = NormalizeDateString(TextBox1.Text)
End Sub

Private Sub TextBox1_LostFocus(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles TextBox1.LostFocus
TextBox1.Text = DatePicker1.Text
End Sub

Private Sub DatePicker1_SelectedDateChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Handles DatePicker1.SelectedDateChanged
TextBox1.Focus()
End Sub

Oh, and finally, the NormalizeDateString function referenced above:

Protected Function NormalizeDateString(ByVal DateIn As String) As String
Dim ReturnDato As String
Try
If DateIn.Substring(DateIn.Length - 1) = "." Then DateIn = DateIn.Substring(0, DateIn.Length - 1)
Dim ConvertedDato As DateTime = Convert.ToDateTime(DateIn)
ReturnDato = ConvertedDato.ToShortDateString
Catch ex As Exception
Return ""
End Try

Return ReturnDato
End Function

And voilla! You have a WPF DatePicker that does not display any text if the date is left blank, and that at any time will hold the date the user selected, regardless if he types the date (in the overlaying TextBox) or he selects the date by clicking the DatePicker calendar icon visible to the right of the textbox.