Jump to content
Xtreme .Net Talk
    • Cags
      Foreward
      I recently ran into a very annoying problem whilst developing for the Pocket PC. How to create an application that was full screen? The simple answer to this is you create a Form with it's WindowState property set to Maximised and set the Menu property to null. I wasn't happy with this however as although I didn't want the TaskBar and the SIP Icon, I still wanted to allow a menu.
       
      Solution 1
      Many places I looked suggested that the way to get around this was to use the SHFullScreen API. The way this works is by moving the items passed into dwState below the object with the windows handle passed into hwndRequester. I'm not going to go into too much detail, but sufficed to say I could not get this method to work to a satisfactory standard. The problem is that many things can cause the Z Order to be changed back to it's initial state which causes the SIP Icon to suddenly re-appear. One annoying thing that used to trigger this was selecting a top level MenuItem, then not selecting a child MenuItem, but instead clicking back on the form.
      NB. SHFullScreen is generally in aygshell.dll however it's in coredll.dll on the Pocket PC

      Declare Function SHFullScreen Lib "aygshell" (ByVal hwndRequester As Long, ByVal dwState As Long) As Boolean

      [DllImport("aygshell.dll")] private extern static bool SHFullScreen(IntPtr hWnd, long dwState);
      Solution 2
      Still determined to come up with the effect I wanted I continued on experimenting/researching. Eventually I came across some articles which used a differen't method. Namely moving the items off screen so that the form can be resize in thier place. The solution I came up with uses the following three API Calls...

      [DllImport("coredll.dll")] public static extern int FindWindow(string LPClassName, string LPWindowName); [DllImport("coredll.dll")] public static extern int GetWindowRect(int hwnd, ref RECT rc); [DllImport("coredll.dll")] public static extern int MoveWindow(int hWnd, int X, int Y, int cx, int cy);
      The basic theory is as follows. The constructor of the class gathers the required info for each item. This information is the Handle and its Location. This information is then stored for later use. A reference to the form is stored as it's possible its handle will change.

      public ScreenHelper(System.Windows.Forms.Form mainForm) { _parent = mainForm; hiddenItems = new ScreenItem(); GetWindowRect(FindWindow(null, _parent.Text), ref rtFormDefault); hWndSipButton = FindWindow("MS_SIPBUTTON", null); GetWindowRect(hWndSipButton, ref rtSipButton); hWndTaskBar = FindWindow("HHTaskBar", null); GetWindowRect(hWndTaskBar, ref rtTaskBar); hWndSip = FindWindow("SipWndClass", null); GetWindowRect(hWndSip, ref rtSip); }
      There are two other public methods, they are ChangeItemVisibility and ResetScreen.
       
      I won't cover the code too much here as its in the file, but essentially ChangeItemVisibility accepts a flagged enum, which allows you to alter whether an item is displayed on screen or not. The ResetScreen method is very important as it replaces all the items in their correct positions. It is very important that this message is called before the application is closed otherwise the user may have to reset their device in order to get the items back.
       
      To use the class successfully in an application you will need to call ChangeItemVisibilty each time the application gets control and call ResetScreen when your application looses control. To-do this I override the OnActivated and OnDeactivated events. It's also worth noting that OnDeactivated is not called when you call Application.Exit(), so be sure to add an extra call to ResetScreen() before calling it.
       
      Afterword
      Well I'm no Guru, but I thought that since this problem caused me a lot of headaches, I'd share the solution I came up with. Attached is a sample project which contains my ScreenHelper class. Feel free to use it or any parts at your descretion, no guarantee implied etc, etc. Comments, suggestions, bug reports all welcome.
       
      References
      The following is a list of the main articles that helped me create my ScreenHelper class.
      pocketpcdn.com
      http://support.microsoft.com/kb/q266244/
      http://www.codeproject.com/netcf/netfullscreen.asp

    • PlausiblyDamp
      Quick Guide to Parametrising SQL
       
      Jump to the bit on using parameters
       
      Often when interacting databases we need to provide information to the database that can only be obtained at runtime (this could be from user input, other programmatic means or similar).
       
      Two potential approaches to this problem involve either parametrising the database code or relying on string concatenation. In this post I hope to show why concatenation is bad and parameters are good.
       
      To keep things simple I am using the simplest code I can and deliberately ignoring non-essential error handling, for similar reasons I am also choosing not to use stored procedures. I am choosing Northwind as the database as this is available to anyone with SQL or MS access but the ideas will convert to other database platforms. Another point to bear in mind is these problems will occur with any form of string concatenation be they String.Format, StringBuilder or some other means.
       
      Why not parametrising is bad
      A typical example of how to perform a query based on user input could look like the following (the example has a simple form with a button, textbox and datagrid - should work in either a web or windows environment)
       
      For sql server

      Dim conn As New SqlConnection("Data Source=.;Initial Catalog=Northwind;Integrated Security=true") Dim sql As String = "SELECT ProductID, ProductName FROM Products WHERE ProductName Like '" & TextBox1.Text & "%'" Dim cmd As New SqlCommand(sql, conn) Dim ds As New DataSet Dim da As New SqlDataAdapter(cmd) debug.WriteLine(sql) 'Lets us see the sql just before it is executed! da.Fill(ds) DataGridView1.DataSource = ds.Tables(0) 'DataBind 'Uncomment this line if a web application
      or for access

      Dim conn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Nwind.mdb;Persist Security Info=True") Dim sql As String = "SELECT ProductID, ProductName FROM Products WHERE ProductName Like '" & TextBox1.Text & "%'" Dim cmd As New OleDbCommand(sql, conn) Dim ds As New DataSet Dim da As New OleDbDataAdapter(cmd) Debug.WriteLine(sql) da.Fill(ds) DataGridView1.DataSource = ds.Tables(0) 'DataBind 'Uncomment this line if a web application
       
      To see the application work try entering a value of

      chef
      into the textbox and see the resulting values. Notice this works and is simple, the initial reaction is therefore to use this method.
       
      notice the line

      Dim sql As String = "SELECT ProductID, ProductName FROM Products WHERE ProductName Like '" & TextBox1.Text & "%'"
      is the one that builds the query by concatenating the contents of a textbox with a sql string, it is this concatenation that causes our potential problems.
       
      Problem 1
      Maybe not a big problem but consider how complex the string building will get if the query is a multiple table join, with multiple textboxes that get concatenated into the sql query. How about if my code needs to use the " character? All of these situations can result in a piece of code spanning multiple lines, maintenance is not it's strong point ;) If this runs but the results are wrong how do we pinpoint the problem - is the SQL correct but the code we are using to build it wrong; is the SQL wrong but at least we are building it correctly; both bits of code are wrong and we really have our work cut out.
       
      Problem 2
      To get a little more adventurous try searching for the string

      Chef Anton's
      and suddenly our system isn't running as smoothly...
       
      If you look at the resultant SQL (as displayed in the output window by the Debug.WriteLine(sql)) it looks like

      SELECT ProductID, ProductName FROM Products WHERE ProductName Like 'Chef Anton's%'
      Notice the end of the statement
      'Chef Anton's%' contains invalid sql due to the single ' character contained within our textbox. If we need to search / insert etc. data that may contain this character we now have a major problem to contend with.
       
      Problem 3
      change the sql assignment to

      'sql server users use Dim sql As String = "SELECT FirstName,LastName FROM Employees WHERE HireDate ='" & TextBox1.Text & "'" 'oledb people use Dim sql As String = "SELECT FirstName,LastName FROM Employees WHERE HireDate =#" & TextBox1.Text & "#"
      and now try querying the value
      17/10/1993 and see the results, also try
      10/17/1993 and compare. I would like to tell you the results but there are no guarantees here. On my pc either value worked on the oledb version, while 17/10/1993 throws an exception and 10/17/1993 works against sql server. This is a result of us passing strings to the database that the database then needs to interpret correctly. Differences in client / server locale settings and user input formats can all cause problems here.
       
      Problem 4
      Firstly if you are using Access then inherent limitations of it's SQL engine prevent this problem occurring, for most other databases however this is a valid and very dangerous problem.
       
      Let's revert back to the original sql string

      Dim sql As String = "SELECT ProductID, ProductName FROM Products WHERE ProductName Like '" & TextBox1.Text & "%'"
      and we will try something a little more fun. We already know that putting a single ' into the text box causes an error because the code then adds an additional ' to the end. Therefore if we search for a very simple - but invalid string like
      x' we will see the same error as before with the resultant sql being

      SELECT ProductID, ProductName FROM Products WHERE ProductName Like 'x'%'
      Notice if we change the textbox contents to
      x' -- then the resultant sql looks like

      SELECT ProductID, ProductName FROM Products WHERE ProductName Like 'x' --%'
      although this doesn't return any data neither is it crashing! By commenting out the extra ' character we now have well formed sql code again.
       
      Now enter the following into the text box and see what happens

      x' INSERT Employees (FirstName,LastName) VALUES('get here?','How did this') --
      this gives us a resulting sql string of

      SELECT ProductID, ProductName FROM Products WHERE ProductName Like 'x' INSERT Employees (FirstName,LastName) VALUES('get here?','How did this') --%'
      What would you expect to happen if you ran this against your server? If you have been following along you have just ran this against your server - go have a look in the Employees table and check the last entry ;)
       
      If the above points haven't convinced you that string concatenation is bad then I'm probably fighting a losing battle and you might as well ignore the rest of this post. If you have encountered any of the above you may have also come across means of preventing them (detecting invalid characters, regular expressions, encoding and decoding characters etc.) these may work but can often involve more effort than simply doing things correctly in the first place.

    • snarfblam

      Interpolated Picture Box

      By snarfblam, in Code Samples,

      Ever wish the picture box could scale images without using bilinear filtering (for example, when viewing/editing video game graphics)? In the past I had written controls from scratch that emulate the PictureBox but used my desired interpolation. Then I was hit with a stroke of common sense. I've extended the PictureBox class to enhance it with the ability to use various interpolation modes, including the video game creator's best friend, nearest neighbor.

      using System.Windows.Forms; using System.Drawing.Drawing2D; using System.ComponentModel; using System; namespace iLab { /// /// A PictureBox control extended to allow a variety of interpolations. /// class InterpolatedBox:pictureBox { #region Interpolation Property /// Backing Field private InterpolationMode interpolation = InterpolationMode.Default; /// /// The interpolation used to render the image. /// [DefaultValue(typeof(InterpolationMode), "Default"), Description("The interpolation used to render the image.")] public InterpolationMode Interpolation { get { return interpolation; } set { if(value == InterpolationMode.Invalid) throw new ArgumentException("\"Invalid\" is not a valid value."); // (Duh!) interpolation = value; Invalidate(); // Image should be redrawn when a different interpolation is selected } } #endregion /// /// Overridden to modify rendering behavior. /// /// Painting event args. protected override void OnPaint(PaintEventArgs pe) { // Before the PictureBox renders the image, we modify the // graphics object to change the interpolation. // Set the selected interpolation. pe.Graphics.InterpolationMode = interpolation; // Certain interpolation modes (such as nearest neighbor) need // to be offset by half a pixel to render correctly. pe.Graphics.PixelOffsetMode = PixelOffsetMode.Half; // Allow the PictureBox to draw. base.OnPaint(pe); } } }
      Since I'm such a swell guy, I translated it to VB too.

      Imports System.Drawing.Drawing2D Imports System.ComponentModel ''' A PictureBox control extended to allow a variety of interpolations. Public Class InterpolatedBox Inherits PictureBox ''' The backing field for the Interpolation property Dim _interpolation As InterpolationMode = InterpolationMode.Default ''' ''' The interpolation used to render the image. ''' Description("The interpolation used to render the image.")> _ Public Property Interpolation() As InterpolationMode Get Return _interpolation End Get Set(ByVal value As InterpolationMode) If value = InterpolationMode.Invalid Then _ Throw New ArgumentException("""Invalid"" is not a valid value.") '(duh.) _interpolation = value Invalidate() 'Image should be redrawn when a different interpolation is selected End Set End Property ''' ''' Overridden to modify rendering behavior. ''' ''' Painting event args. Protected Overrides Sub OnPaint(ByVal pe As System.Windows.Forms.PaintEventArgs) ' Before the PictureBox renders the image, we modify the ' graphics object to change the interpolation. ' Set the selected interpolation. pe.Graphics.InterpolationMode = _interpolation ' Certain interpolation modes (such as nearest neighbor) need ' to be offset by half a pixel to render correctly. pe.Graphics.PixelOffsetMode = PixelOffsetMode.Half ' Allow the PictureBox to draw. MyBase.OnPaint(pe) End Sub End Class

    • JumpyNET
      A simplified version of the MSDN StreamSocket sample (tested and working).
       
      TCP Client (Windows Phone 8 App)

      Imports Windows.Networking Imports Windows.Networking.Sockets Imports Windows.Storage.Streams Partial Public Class MainPage : Inherits PhoneApplicationPage Dim Socket As StreamSocket Private Async Sub ButtonConnect_Click(sender As Object, e As RoutedEventArgs) Handles ButtonConnect.Click Socket = New StreamSocket Await Socket.ConnectAsync(New HostName("192.168.1.7"), "1234") StartListening() End Sub Private Async Sub StartListening() Dim reader As New DataReader(Socket.InputStream) Do ' Read first 4 bytes (length of the subsequent string). Dim sizeFieldCount As UInteger = Await reader.LoadAsync(CUInt(Runtime.InteropServices.Marshal.SizeOf(New UInteger))) If sizeFieldCount <> Runtime.InteropServices.Marshal.SizeOf(New UInteger) Then ' The underlying socket was closed before we were able to read the whole data. Return End If ' Read the string. Dim stringLength As UInteger = reader.ReadUInt32() Dim actualStringLength As UInteger = Await reader.LoadAsync(stringLength) If stringLength <> actualStringLength Then ' The underlying socket was closed before we were able to read the whole data. Return End If ' Display the string. Dim MsgReceived As String = reader.ReadString(actualStringLength) System.Diagnostics.Debug.WriteLine(MsgReceived) Loop End Sub Private Async Sub ButtonSend_Click(sender As Object, e As RoutedEventArgs) Handles ButtonSend.Click Dim stringToSend As String = "Some Text To Send" Dim writer As New DataWriter(Socket.OutputStream) writer.WriteUInt32(writer.MeasureString(stringToSend)) writer.WriteString(stringToSend) Await writer.StoreAsync() writer.DetachStream() writer.Dispose() End Sub End Class
       
      TCP Server (Windows 8 Store App)

      Imports Windows.Networking Imports Windows.Networking.Sockets Imports Windows.Storage.Streams Public NotInheritable Class MainPage : Inherits Page Dim WithEvents ListenerSocket As StreamSocketListener Private Async Sub ButtonListen_Click(sender As Object, e As RoutedEventArgs) Handles ButtonListen.Click ListenerSocket = New StreamSocketListener ' Don't limit traffic to an address or an adapter. Await ListenerSocket.BindServiceNameAsync("1234") End Sub Dim Socket As StreamSocket Private Async Sub listener_ConnectionReceived(sender As StreamSocketListener, args As StreamSocketListenerConnectionReceivedEventArgs) Handles ListenerSocket.ConnectionReceived ' Invoked once a connection is established. Debug.WriteLine("Connection Established") Socket = args.Socket Dim reader As New DataReader(args.Socket.InputStream) Do ' Read first 4 bytes (length of the subsequent string). Dim sizeFieldCount As UInteger = Await reader.LoadAsync(CUInt(Runtime.InteropServices.Marshal.SizeOf(New UInteger))) If sizeFieldCount <> Runtime.InteropServices.Marshal.SizeOf(New UInteger) Then Return ' The underlying socket was closed before we were able to read the whole data. End If ' Read the string. Dim stringLength As UInteger = reader.ReadUInt32() Dim actualStringLength As UInteger = Await reader.LoadAsync(stringLength) If stringLength <> actualStringLength Then Return ' The underlying socket was closed before we were able to read the whole data. End If ' Display the string. Dim MsgReceived As String = reader.ReadString(actualStringLength) Debug.WriteLine(MsgReceived) Loop End Sub Private Async Sub ButtonSend_Click(sender As Object, e As RoutedEventArgs) Handles ButtonSend.Click Dim stringToSend As String = "Some Text Back" Dim writer As New DataWriter(Socket.OutputStream) writer.WriteUInt32(writer.MeasureString(stringToSend)) writer.WriteString(stringToSend) Await writer.StoreAsync() writer.DetachStream() writer.Dispose() End Sub End Class
       
      PS: Requesting to be moved to code library, please.

    • AWS

      Download Visual Studio Code

      By AWS, in Code Samples,

      Visual Studio Code is a lightweight but powerful source code editor which runs on your desktop and is available for Windows, macOS and Linux. It comes with built-in support for JavaScript, TypeScript and Node.js and has a rich ecosystem of extensions for other languages and runtimes (such as C++, C#, Java, Python, PHP, Go, .NET). Begin your journey with VS Code with these introductory videos.
       
      You can download with the links below. Be sure to download the correct version for your system.
       
      Windows: https://code.visualstudio.com/sha/download?build=stable&os=win32-x64-user
      MacOS: https://code.visualstudio.com/sha/download?build=stable&os=darwin-universal
      Linux: https://code.visualstudio.com/sha/download?build=stable&os=linux-x64

×
×
  • Create New...