Category Archives: VB.Net

Capturing a still image from a Webcam in .net

Standard

image 

What if you want to capture a single image from a webcam?  It turns out that this is quite straight forward to do using a couple of Win32 api calls to the avicap32.dll library.

I encapsulated these api calls in a simple class.

To write a file called “snapshot.jpg” out to the desktop from a single webcam, simply declare the class and call a the TakePicture method.

Dim loSnap As New WebcamSnap
loSnap.TakePicture(0)

The devices collection shows a list of all webcam devices on your machine so you can populate a combo with them.

Note: This example has no decent error handling, which I suspect will be needed in the “real world” of multiple devices.

Here’s the WebcamSnap class:

Option Explicit On
Imports System.IO
Imports System.Runtime.InteropServices
''' <summary>
''' This class takes a snapshot from any or all attached webcams
''' </summary>
''' <remarks></remarks>
Public Class WebcamSnap
    Const WM_CAP As Short = &H400S

    Const WM_CAP_DRIVER_CONNECT As Integer = WM_CAP + 10
    Const WM_CAP_DRIVER_DISCONNECT As Integer = WM_CAP + 11
    Const WM_CAP_EDIT_COPY As Integer = WM_CAP + 30
    Const WS_CHILD As Integer = &H40000000
    Const WS_VISIBLE As Integer = &H10000000
    Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
        (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, _
        <MarshalAs(UnmanagedType.AsAny)> ByVal lParam As Object) As Integer

    Declare Function capCreateCaptureWindowA Lib "avicap32.dll" _
        (ByVal lpszWindowName As String, ByVal dwStyle As Integer, _
        ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, _
        ByVal nHeight As Short, ByVal hWndParent As Integer, _
        ByVal nID As Integer) As Integer

    Declare Function capGetDriverDescriptionA Lib "avicap32.dll" (ByVal wDriver As Short, _
        ByVal lpszName As String, ByVal cbName As Integer, ByVal lpszVer As String, _
        ByVal cbVer As Integer) As Boolean

    Public Devices As New List(Of String)
    Public Height As Integer = 480
    Public Width As Integer = 640
    Public OutputPath As String = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)
    Public FilenamePrefix As String = "snapshot"
    Public Sub New()
        mLoadDeviceList()
    End Sub
    Private Sub mLoadDeviceList()
        Dim lsName As String = Space(100)
        Dim lsVers As String = Space(100)
        Dim lbReturn As Boolean
        Dim x As Integer = 0

        Do
            '   Get Driver name and version
            lbReturn = capGetDriverDescriptionA(x, lsName, 100, lsVers, 100)

            ' If there was a device add device name to the list
            If lbReturn Then Devices.Add(lsName.Trim)
            x += 1
        Loop Until lbReturn = False
    End Sub
    Public Sub TakePicture()
        For i = 0 To Me.Devices.Count - 1
            Dim lsFilename As String = Path.Combine(OutputPath, Me.FilenamePrefix & i & ".jpg")
            TakePicture(i, lsFilename)
        Next
    End Sub
    Public Sub TakePicture(ByVal iDevice As Integer)
        Me.TakePicture(iDevice, Path.Combine(OutputPath, Me.FilenamePrefix & ".jpg"))
    End Sub
    Public Sub TakePicture(ByVal iDevice As Integer, ByVal filename As String)

        Dim lhHwnd As Integer ' Handle to preview window

        ' Create a form to play with
        Using loWindow As New System.Windows.Forms.Form

            ' Create capture window
            lhHwnd = capCreateCaptureWindowA(iDevice, WS_VISIBLE Or WS_CHILD, 0, 0, Me.Width, _
               Me.Height, loWindow.Handle.ToInt32, 0)

            ' Hook up the device
            SendMessage(lhHwnd, WM_CAP_DRIVER_CONNECT, iDevice, 0)
            ' Allow the webcam apeture to let enough light in
            For i = 1 To 10
                Application.DoEvents()
            Next

            ' Copy image to clipboard
            SendMessage(lhHwnd, WM_CAP_EDIT_COPY, 0, 0)

            ' Get image from clipboard and convert it to a bitmap
            Dim loData As IDataObject = Clipboard.GetDataObject()
            If loData.GetDataPresent(GetType(System.Drawing.Bitmap)) Then
                Using loBitmap As Image = CType(loData.GetData(GetType(System.Drawing.Bitmap)), Image)
                    loBitmap.Save(filename, Imaging.ImageFormat.Jpeg)
                End Using
            End If

            SendMessage(lhHwnd, WM_CAP_DRIVER_DISCONNECT, iDevice, 0)

        End Using

    End Sub

End Class

Links

I found the original code sample here:

http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_22482234.html

(Although I’ve seen it all over the web in various guises)

Advertisements

Adding the User-Agent when calling a Web Service with WCF

Standard

 image

“Every computing problem can be solved with yet another layer of indirection”

One of the cool things about the original Visual Studio (Visual Studio.Net) was how easy it was to create and consume web services. 

Over time, this support has been replaced by the trendy WCF services and WCF Soapclient infrastructure.    These new “Service References” differ from the original “Web References” in that they completely abstract the communications layer.  So it isn’t really a web reference anymore is it?

Recently I had to create a client program that called a .net 1.1 asmx web service.  This web service accessed the HTTP-Header variable “User-Agent”.   The original web service client proxies (Web References) that were generated by Visual Studio used to supply a User-Agent.  This is no longer the case.

It appears that a bug has been logged on Microsoft Connect, but it seems unlikely this will be fixed.

Most remedies to the problem discuss using code like this:

Dim httpRequestMessage As New HttpRequestMessageProperty()
httpRequestMessage.Headers.Add(USER_AGENT_HTTP_HEADER, Me.m_userAgent) requestMessage.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage)

Sadly when you’re working with a generated Service Reference I could see no way of using this code.  I assume it’s intended for a lower layer than the one I was working with.

Fortunately Paul Morgado has posted some code that I manipulated to solve the problem.    This article shows how to create a “behaviour” which can be then added to the service reference instance.

Like this:

Dim loService As New MyServiceReferenceSoapClient()
loService.Endpoint.Behaviors.Add(New HttpUserAgentEndpointBehavior("SomeUserAgentString"))
loService.SomeWebMethod()

Here’s the code for the HttpUserAgentEndpointBehaviour:

Imports System.ServiceModel
Imports System.ServiceModel.Channels
Imports System.ServiceModel.Dispatcher
Imports System.ServiceModel.Description
Imports System.ComponentModel
Public Class HttpUserAgentMessageInspector

    Implements IClientMessageInspector
    Private Const USER_AGENT_HTTP_HEADER As String = "user-agent"

    Private m_userAgent As String

    Public Sub New(ByVal userAgent As String)
        Me.m_userAgent = userAgent
    End Sub

#Region "IClientMessageInspector Members"

    Public Sub AfterReceiveReply(ByRef reply As System.ServiceModel.Channels.Message, ByVal correlationState As Object) Implements IClientMessageInspector.AfterReceiveReply
    End Sub

    Public Function BeforeSendRequest(ByRef request As System.ServiceModel.Channels.Message, ByVal channel As System.ServiceModel.IClientChannel) As Object Implements IClientMessageInspector.BeforeSendRequest
        Dim httpRequestMessage As HttpRequestMessageProperty
        Dim httpRequestMessageObject As Object
        If request.Properties.TryGetValue(HttpRequestMessageProperty.Name, httpRequestMessageObject) Then
            httpRequestMessage = TryCast(httpRequestMessageObject, HttpRequestMessageProperty)
            If String.IsNullOrEmpty(httpRequestMessage.Headers(USER_AGENT_HTTP_HEADER)) Then
                httpRequestMessage.Headers(USER_AGENT_HTTP_HEADER) = Me.m_userAgent
            End If
        Else
            httpRequestMessage = New HttpRequestMessageProperty()
            httpRequestMessage.Headers.Add(USER_AGENT_HTTP_HEADER, Me.m_userAgent)
            request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage)
        End If
        Return Nothing
    End Function

#End Region
End Class
Public Class HttpUserAgentEndpointBehavior
    Implements IEndpointBehavior
    Private m_userAgent As String

    Public Sub New(ByVal userAgent As String)
        Me.m_userAgent = userAgent
    End Sub

#Region "IEndpointBehavior Members"

    Public Sub AddBindingParameters(ByVal endpoint As ServiceEndpoint, ByVal bindingParameters As System.ServiceModel.Channels.BindingParameterCollection) Implements IEndpointBehavior.AddBindingParameters
    End Sub

    Public Sub ApplyClientBehavior(ByVal endpoint As ServiceEndpoint, ByVal clientRuntime As System.ServiceModel.Dispatcher.ClientRuntime) Implements IEndpointBehavior.ApplyClientBehavior
        Dim inspector As New HttpUserAgentMessageInspector(Me.m_userAgent)
        clientRuntime.MessageInspectors.Add(inspector)
    End Sub

    Public Sub ApplyDispatchBehavior(ByVal endpoint As ServiceEndpoint, ByVal endpointDispatcher As System.ServiceModel.Dispatcher.EndpointDispatcher) Implements IEndpointBehavior.ApplyDispatchBehavior
    End Sub

    Public Sub Validate(ByVal endpoint As ServiceEndpoint) Implements IEndpointBehavior.Validate
    End Sub

#End Region
End Class

Getting the parent process in VB.Net

Standard

 

image

The .net framework’s Process object lacks a means of determining which process invoked it. 

There are 3 techniques I have seen for determining this:

  • Api Calls
  • Iterating through the process table
  • Using wmi

This code sample uses the 3rd technique.  

Usage:

The code exposes a new “Parent” process function on the standard System.Diagnostics.Process class.

MessageBox.Show(System.Diagnostics.Process.GetCurrentProcess.Parent.Id)

Source:

Imports System.Management
Public Module ProcessExtensions
    <System.Runtime.CompilerServices.Extension()> _
    Public Function Parent(ByVal process As Process) As Process
        Return process.GetProcessById(miGetParentProcessId(process.Id))
    End Function
    Private Function miGetParentProcessId(ByVal processId As Integer) As Integer

        Dim loQuery As SelectQuery = New SelectQuery(String.Format("select * from Win32_Process where ProcessId = {0}", processId))
        Dim loSearcher As ManagementObjectSearcher = New ManagementObjectSearcher(loQuery)
        Dim loProcesses As ManagementObjectCollection = loSearcher.Get()

        If loProcesses.Count > 0 Then
            Return loProcesses(0)("ParentProcessId")
        End If
        Return 0
    End Function
End Module

 

 

References

Kill a specific process – System.Management forum post

Retrieving the Parent Process of a Child when Multiple Instances Exist – Robert Villahermosa

System Management Select Query

Hosting Winforms in Firefox

Standard

 image

I have a strange fascination with hybrids.  Combining old and new technologies in bizarre and interesting ways.   Why must developers make “the choice” between a web or native technology? It would be great to build applications that would increase or decrease in features depending on the platform they were run on.

 

clip_image002

Do you have a Winforms application that you’d like to host in a web browser?  There’s an interesting technique you can use to do this enabled by .net Framework 3.5.

The .net framework provides the ability to create WPF web applications (commonly called XBAP).  WPF has the ability, in turn, to host Winforms. 

Security

It appears that in order to do this effectively, it’s necessary to deploy your XBAP application as a “Full Trust” application.

image

The code

To use this, create an XBAP project, then a page a “WinformHost” control on it.   The XAML could look like this:

<Page x:Class="Page1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Page1">
    <DockPanel LastChildFill="True">
        <Button Name="Button1"  DockPanel.Dock="Bottom"  >This is a WPF Button</Button>
        <WindowsFormsHost Name="WinformHost"   />
    </DockPanel>
</Page>

Then, create some code to instantiate your winform and show it on the Winform host:

Class Page1

    Private Sub Page1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded

        Dim loForm As New HelloWorldWinform

        WinformHost.Child = WinformToUserControl.GetWrapper(loForm)
        loForm.Show()

    End Sub
End Class

Here’s the subroutine:

Public NotInheritable Class WinformToUserControl

    Public Shared Function GetWrapper(ByVal form As System.Windows.Forms.Form) As System.Windows.Forms.Control
        Dim loPanel As New System.Windows.Forms.Panel
        loPanel.Dock = Forms.DockStyle.Fill
        ShowFormInControl(loPanel, form)
        Return loPanel
    End Function

    Private Shared Sub ShowFormInControl(ByVal ctl As System.Windows.Forms.Control, ByVal frm As System.Windows.Forms.Form)

        frm.TopLevel = False
        frm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None
        frm.AutoScaleMode = Forms.AutoScaleMode.Dpi
        ctl.Controls.Add(frm)

        frm.Dock = Forms.DockStyle.Fill

    End Sub
End Class

   

Interesting bits and pieces

We found that in order for the items inside the control to scale properly, the AutoScaleMode property on the Winform must be set to Dpi instead of the default, which is Font.  I have a feeling this is because Dpi is the mode preferred for WPF, but I am uncertain.

In the sample WinformToUserControl class I found it better to contain the Winform inside a panel rather than exposing the Winform directly.  It seemed to make it more stable.  Feel free to experiment with taking it off.

Gotchas

As of time of writing, Firefox on my Windows 7 64 bit machine steadfastly refuses to run xbap.  It appears the “Windows Presentation Foundation” addin has not been automatically installed.  I have no idea how to install it.  There’ appears to be no information about how to do so.  So if you have it, good for you.  If you don’t….try re-installing the .net framework 3.51 (which didn’t work for me…)

I do know there was some controversy about this addin being temporarily blacklisted by Mozilla due to security concerns last month, but that’s all over now isn’t it?  

 

Download

You can download a sample project here.

image

Links

Serialize and Deserialize objects as Xml using generic types in VB.Net

Standard

image

In his blog post Serialize and deserialize objects as xml using generic types in C# 2.0 , Paul Whitaker creates some ubiquitous functions for doing Xml Serialization with generics.

 

To serialize:

Dim lsXml As String = GenericXmlSerializer.SerializeObject(of MyObjectType)(myObject)

 

To deserialize:

Dim myObject As MyObjectType = GenericXmlSerializer.DeserializeObject(of MyObjectType)(lsXml)

 

Here’s the code

Imports System.Collections.Generic
Imports System.Text
Imports System.Xml
Imports System.IO
Imports System.Xml.Serialization

Class GenericXmlSerializer
    ''' <summary>
    ''' To convert a Byte Array of Unicode values (UTF-8 encoded) to a complete String.
    ''' </summary>
    ''' <param name="characters">Unicode Byte Array to be converted to String</param>
    ''' <returns>String converted from Unicode Byte Array</returns>
    Public Shared Function UTF8ByteArrayToString(ByVal characters As Byte()) As String

        Dim encoding As New UTF8Encoding
        Dim constructedString As String = encoding.GetString(characters)
        Return constructedString

    End Function

    ''' <summary>
    ''' Converts the String to UTF8 Byte array and is used in De serialization
    ''' </summary>
    ''' <param name="pXmlString"></param>
    ''' <returns></returns>
    Public Shared Function StringToUTF8ByteArray(ByVal pXmlString As String) As Byte()

        Dim encoding As New UTF8Encoding()
        Dim byteArray As Byte() = encoding.GetBytes(pXmlString)
        Return byteArray
    End Function

    ''' <summary>
    ''' Serialize an object into an XML string
    ''' </summary>
    ''' <typeparam name="T"></typeparam>
    ''' <param name="obj"></param>
    ''' <returns></returns>
    Public Shared Function SerializeObject(Of T)(ByVal obj As T) As String

        Try
            Dim xmlString As String = Nothing

            Dim memoryStream As New MemoryStream()
            Dim xs As New XmlSerializer(GetType(T))
            Dim xmlTextWriter As New XmlTextWriter(memoryStream, Encoding.UTF8)
            xs.Serialize(xmlTextWriter, obj)
            memoryStream = CType(xmlTextWriter.BaseStream, MemoryStream)
            xmlString = UTF8ByteArrayToString(memoryStream.ToArray())
            memoryStream.Dispose()

            Return xmlString
        Catch

            Return String.Empty
        End Try
    End Function

    ''' <summary>
    ''' Reconstruct an object from an XML string
    ''' </summary>
    ''' <param name="xml"></param>
    ''' <returns></returns>
    Public Shared Function DeserializeObject(Of T)(ByVal xml As String) As T

        Dim xs As New XmlSerializer(GetType(T))
        Dim memoryStream As New MemoryStream(StringToUTF8ByteArray(xml))
        Dim xmlTextWriter As New XmlTextWriter(memoryStream, Encoding.UTF8)

        Dim theObject As T = CType(xs.Deserialize(memoryStream), T)
        memoryStream.Dispose()
        Return theObject

    End Function

End Class

 

Rather than be original, I converted most of his code verbatim and have found the functions useful. 

I offer them to you warranty free, unadorned and hopefully useful.

 

 

Share this post :

Flick Scrolling in Winforms

Standard

image

 

In the article A Simple Scroll Controller for Winforms I mentioned that I was working on a FlickScrolling framework for Winforms.

I finished a version of this code a couple of months ago and it seems to work well.  

The code never went into production because I think that Windows 7 will provide this functionality automatically for winforms applications. 

Nevertheless, some people have showed an interest in what I came up with, so I’m posting it here for your edification.  I hope someone finds it useful.

Usage

To use, simply instantiate the “ApplicationFlickScrolling” class, passing in the datatypes of the container controls you wish to scroll.

For example:

Private Shared moApplicationFlick As New ApplicationFlickScrolling(GetType(Panel))

To switch it on and off, used the “Enabled” property:

moApplicationFlick.Enabled = True

That’s it!

 

The Implementation

image

The code consists of 3 classes:

  • ApplicationFlickScrolling to act as the master controller class
  • ApplicationMouseEvents class for detecting mouse events
  • FlickDetector for detecting simple gestures
  • ScrollController for performing elastic-style easing of scrolling

Improvements

If I’d have continued developing this I would have modified ScrollController to use “proper” easing functions. 

 

 
Note: The usual disclaimers apply for this code, which has been given freely to help others learn and is not intended for usage in your business application or for running a nuclear facility.
Share this post :

Why my brain hurts – Objective C vs VB.Net

Standard

It has been said that software developers can expand their skills by learning a new computer language a year.  The similarity of languages I have encountered up to this point led me to doubt whether this was so.  I was wrong.

In my quest to create the ultimate iPhone application, I’ve had to learn not only a new platform but a whole new computer language, “Objective C”.  My “native” computer language is C, so imagine my consternation when found how different Objective C appears from C Sharp and C++.

So far there doesn’t seem to be any direct comparison between .net languages and Objective C, so I thought I’d post a small article on the subject.  I have decided to use VB.Net as the basis of comparison, but I’m sure C Sharp developers can understand the concepts.   This article is based on the fine Wikipedia introduction to Objective C.  I encourage you to take a look at this.

 

 

Method Invocation and Method Passing

To invoke a method on an Objective C object, we “pass a message”.  This differs from VB.Net in that a method must exist in order to invoke it.

Declaration of classes, by convention are done in two seperate files, a “.h” header file containing an interface declaration and a “.m” (method implementation) containing the actual class code.

HelloWorld.h

@interface HelloWorld : object 

– (id) hello;

@end

 

HelloWorld.m

 

#import “HelloWorld.h”

 

@implementation HelloWorld

– (id) hello

{

   printf(“Hello World”);

}

 

To use this class:

HelloWorld * myhello = [[HelloWorld alloc] init];

[myhello hello];

 

A rough VB.Net equivalent might be:

 

Public Class HelloWorld

   Public Sub Hello

        Console.WriteLn(“Hello World”)

   End Sub

End Class

 

Invoked by:

 

Dim myhello As New HelloWorld

myhello.hello

 

 

A big difference between these examples, is that in the Objective C case, the hello method does NOT have to be implemented at all.  It’s only responding to a “message” that the class may or may not have an implementation for.

 

Admittedly this does produce a compiler warning “warning:’HelloWorld’ may not respond to ‘-hello'”, but it still compiles.

 

A better VB.Net equivalent may be the use of reflection to check for the existence of a method prior to invocation:

 

Dim myhello As New HelloWorld

If myHello.GetType.GetPropInfo(“Hello”) IsNot Nothing Then myHello.hello

 

Another way would be to treat the object as an “object”.  For example:

Dim myhello As New HelloWorld

Ctype(myhello,object).Hello

 

That’s probably missing the point however, because it effectively causes an error at runtime, whereas ObjectiveC does not produce an error.

 

Another possible VB.Net equivalent could be using Events.  Are these equivalent to messages?

 

Public Class HelloWorld

   Private WithEvents moHelloWorldEventSource As HelloWorldEvents 

   Public Sub New(eventSource As HelloWorldEvents)

        moHelloWorldEventSource = eventSource

   End Sub

 

   Private Sub Hello Handles moHelloWorldEventSource.Hello

        Console.WriteLn(“Hello World”)

   End Sub

End Class

Public Class HelloWorldEventSource

      Public Event Hello

      Public Sub Hello

           RaiseEvent Hello

      End Sub

End Class

 

To invoke this masterpiece:

 

Dim helloEvents As New HelloWorldEventSource

Dim myhello As New HelloWorld(helloEvents)

helloEvents.Hello

 

 

Another capability of Objective C is to pass an unhandled method invocation to another object.  VB.Net does not seem to have an equivalent of this.

 

Protocols (Interfaces)

 

Protocols introduce the multiple inheritance of specification, but not implementation through the introduction of “protocols”.

 

Our Objective C hello world class could implement a prototcol:

 

@protocol DescribeDialect

– (void)DescribeYourLanguage;

@end

 

 Like this:

 

@interface HelloWorld : Object <DescribeDialect>

….

@end

 

I get the impression that although HelloWorld declares it implements the DescribeDialect protocol, I’m not sure if it really has to implement each of the methods.  I’m guessing it should.

 

The vb.net equivalent is quite direct:

Public Interface DescribeDialect

    Sub DescribeYourLanguage

End Interface

 

Public Class HelloWorld

     Implements HelloWorld

….

End Class

 

The only element of confusion here is the use of the word “interface” between the languages.  I suppose knowing “protocol” exists helps with this.

 

Dynamic Typing

A programming language is said to be dynamically typed when the majority of it’s type checking is performed at runtime as opposed to compile time.

 

The previously described “optional” implementation of a passed message allows for increased flexibility.  See “Forwarding” for more information.

 

Static typing information may also be added to variables.  The information is then checked at compile time.

 

For example:

 

– setMyValue:(id) foo;

– setMyValue:(id <aProtocol>) foo;

– setMyValue:(NSNumber*)foo;

 

The vb equivalent appears to be declarations with multiple signatures, like this:

 

Public Sub setMyValue(foo As object)

End Sub

Public Sub setMyValue(foo As DescribeDialect)

End Sub

Public Sub setMyValue(foo As String)

End Sub

 

Post Java 1.5 and the .net languages also support “generics”.  I am unsure at this stage if Objective C supports this or not.

 

Forwarding (Delegation)

Since Objective-C permits the sending of a message to an object which might not respond to it, the object has a number of things it can do with the message. One of these things could be to forward the message on to an object which can respond to it. Forwarding can be used to implement certain design patterns, such as the Observer pattern or the Proxy pattern very simply.

There is no direct VB.Net equivalent of this behaviour.  See the wikipedia article for more information.

Categories

In VB.Net 9, a new feature called “Extension Methods” allowed the creation of extra methods on sealed classes.  Objective C’s “categories” are a similar way of creating groupings of methods in separate files that  allow the extension of a base class at runtime.

If we wanted to extend the HelloWorld class above to have an extra Goodbye method, in Objective C we could write:

 

HelloWorldGoodbyes.h

 

#import “HelloWorld.h”

 

@interface HelloWorldDisplay  (HelloWorld) 

– (id) goodbye;

@end

 

HelloWorldGoodbyes.m

 

#import “HelloWorld.h”

 

@implementation HelloWorld

– (id) goodbye

{

   printf(“Bye”);

}

 

The VB.Net equivalent using extension methods could be:

 

Imports System.Runtime.CompilerServices

Module HelloWorldDisplay

 

      <Extension()>Public Sub goodbye(Byval targetHelloWorld As HelloWorld)

               Console.WriteLn(“Bye”)

      End Sub

 

End Module

 

 

A similar VB.Net feature is “partial” classes, although these are compile time constructs.

 

Partial Public Class HelloWorld

   Public Sub Hello

        Console.WriteLn(“Hello World”)

   End Sub

End Class

 

Partial Public Class HelloWorld

   Public Sub Goodbye

        Console.WriteLn(“Bye”)

   End Sub

End Class

 

I don’t believe either of these equivalents support Objective C’s ability to override the base implementation.

 

Posing

Class Posing is an Objective C feature that allows messages sent to the target class to be wholy replaced by calls to a substitute class with the same implementation.

A class may only pose as one of its direct or indirect superclasses

  • The posing class must not define any new instance variables which are absent from the target class (though it may define or override methods).
  • The target class may not have received any messages prior to the posing.

Posing, similarly to categories, allows globally augmenting existing classes. Posing permits two features absent from categories:

  • A posing class can call overridden methods through super, thus incorporating the implementation of the target class.
  • A posing class can override methods defined in categories.

 

Here’s an example:

 

@interface CustomNSApplication : NSApplication

@end

 

@implementation CustomNSApplication

– (void) setMainMenu: (NSMenu*) menu

{

     // do something with menu

}

@end

 

class_poseAs ([CustomNSApplication class], [NSApplication class]);

 

There is no direct VB.Net equivalent of this functionality.  Similar constructs may be created by implementing a singleton pattern combined with an interface.

 

It appears that this feature has been “depreciated” in MacOS 10.5 and onward, so I wont dedicate discuss it any further.

 

#import

 

The #import directive is similar to the #include directive in C, except it only includes a nested file once.   In VB.Net files in the same “project” are automatically included together in this way.

 

If the developer decides to structure their code with namespaces, the VB.Net “Imports” keyword allows inclusion of namespaced classes without having to prefix the namespace path.

And so ends our brief comparison of the two languages.  If you’re after a comparative critique, I am sorry to disappoint you.  Each language has it’s strengths and weaknesses.  At the moment I’m not qualified to comment either way.

If you found this useful, feel free to leave a comment.

 

Links

A Simple Scroll Controller for Winforms

Standard

 image

I am currently researching “flick” scrolling for Windows XP and over.  As part of this I need the ability to scroll controls in code.

To do this I have created a wrapper around the scrolling apis to assist with this.

Here’s how to use it for an autoscrolling panel:

 

Dim loScrollIt As New ScrollController(Panel1)

loScrollIt.VerticalScroll(20)

 

Here’s the code:

Imports System.Runtime.InteropServices
Public Class ScrollController

    ' Scrollbar direction
    '
    Const SBS_HORZ = 0
    Const SBS_VERT = 1

    ' Windows Messages
    '
    Const WM_VSCROLL = &H115
    Const WM_HSCROLL = &H114
    Const SB_THUMBPOSITION = 4

    Private Declare Function GetScrollPos Lib "user32.dll" ( _
        ByVal hWnd As IntPtr, _
        ByVal nBar As Integer) As Integer

    'Example: position = GetScrollPos(textbox1.handle, SBS_HORZ)
    Private Declare Function SetScrollPos Lib "user32.dll" ( _
        ByVal hWnd As IntPtr, _
        ByVal nBar As Integer, _
        ByVal nPos As Integer, _
        ByVal bRedraw As Boolean) As Integer

    'Example: SetScrollPos(hWnd, SBS_HORZ, position, True

    Private Declare Function PostMessageA Lib "user32.dll" ( _
        ByVal hwnd As IntPtr, _
        ByVal wMsg As Integer, _
        ByVal wParam As Integer, _
        ByVal lParam As Integer) As Boolean

    'Example: PostMessageA(hWnd, WM_HSCROLL, SB_THUMBPOSITION _
    '                         + &H10000 * position, Nothing)

    Private moControl As Control

    Public Sub New(ByVal controlToScroll As Control)

        moControl = controlToScroll
    End Sub
    Public Sub VerticalScroll(ByVal amount As Integer)
        Dim liHwnd As IntPtr = moControl.Handle
        Dim Position = GetScrollPos(liHwnd, SBS_VERT) + amount

        If (SetScrollPos(liHwnd, SBS_VERT, Position, True) <> -1) Then

            PostMessageA(liHwnd, WM_VSCROLL, SB_THUMBPOSITION + _
                                       &H10000 * Position, Nothing)
        End If

    End Sub

End Class

Twittering using the Compact Framework

Standard

 image

My twitter updates are done using a variety of code.  At the moment I use the Curl command line  in conjunction with SlickRun.  In the past I did this with Outlook (see the article Twittering from Outlook Using VBA).  In the past I’ve found this pretty easy to do using the Twitter Api.

 

I also like to do updates from my Pocket PC, but am not keen on SMS charges.  The solution of course is to create my own client, which I’ll be posting about shortly.

For my client program I intend to use TwitterLib library.  Sadly this does not work for the compact framework unaltered.  I am currently working on porting it to the compact framework.

 

In the interim I want to share with you a simple code sample for submitting tweets to Twitter. 

The example is simple enough to be used by people who want to do HTTP posts to similar services.

 

    Dim lsParams As String = "status=" & Uri.EscapeDataString(tweetText)

    Dim loRequest As HttpWebRequest = CType(HttpWebRequest.Create("http://twitter.com/statuses/update.xml"), HttpWebRequest)
           With loRequest
               .Proxy = System.Net.GlobalProxySelection.GetEmptyWebProxy()

               .Timeout = 10000
               .AllowAutoRedirect = True
               .AllowWriteStreamBuffering = True

               .Method = "POST"

               .ContentType = "application/x-www-form-urlencoded"
               .ContentLength = Len(lsParams)

               Dim loCred As New System.Net.NetworkCredential("someusername", "somepassword")
               .Credentials = loCred

               ' Write the request paramater
               Dim stOut As New StreamWriter(.GetRequestStream(), System.Text.Encoding.ASCII)
               stOut.Write(lsParams)
               stOut.Flush()
               stOut.Close()

               Dim loResp = .GetResponse
               With loResp

                   .Close()
               End With

           End With

 

The most important difference with the full .net framework is the “GetEmptyWebProxy” and “AllowWriteStreamBuffering” lines.  It won’t work without it.

Share this post :

Easy InkCanvas in Winforms for capturing signatures

Standard

image

In WPF there’s an interesting control called “InkCanvas” that can be used to capture signatures and the like in Tablet PC applications.

Recently I created a prototype for a windows forms application.  I did consider using WPF, but the overhead seemed unnecessary considering the simplicity of the requirement.

I am aware there’s a specific SDK for Tablet PC that provides winforms controls for the requirement, but I thought it might be fun to create my own.  As it turns out, it was pretty easy.

The requirement was to have a signature panel which could be used to collect a bitmap that would be attached to an entity to act as an authorisation.

Signature Panel

In the prototype I decided to create the signature panel as a standalone usercontrol called it, strangely enough “SignaturePanel”.

It uses Mousedown and MouseUp events to determine stylus pressure and mousemove for drawing.  Like the WPF control it keeps a collection of strokes internally.

Unlike the wpf control, I just decided to expose a “SignatureImage” property to allow a developer to retrieve a bitmap.  This is rendered from the strokes in realtime.

I assume it works for the Tablet PC, but I don’t know for sure.

Write your signature here

An additional feature of this control is a label which tells the user the last time the signature was last updated.  I thought the user may find this helpful.

If the user hasn’t written anything then it just reads “Write your signature here”.

The user control consists of a picturebox called “inkPanel” and a button for resetting the content:

 

What the control looks like in design time

Here’s the code:

 

Public Class SignaturePanel

    Private moCurrentWriting As New List(Of Point)
    Private moRememberInk As New List(Of List(Of Point))
    Private mbPenDown As Boolean = False
    Private Sub inkPanel_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles inkPanel.MouseDown
        mbPenDown = True
    End Sub

    Private Sub inkPanel_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles inkPanel.MouseMove
        If mbPenDown Then
            moCurrentWriting.Add(e.Location)
            mdLastSignatureUpdate = Now
            Me.Refresh()
        End If
    End Sub

    Private Sub inkPanel_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles inkPanel.MouseUp
        If moCurrentWriting.Count > 2 Then
            moRememberInk.Add(moCurrentWriting)
        End If

        moCurrentWriting = New List(Of Point)
        mbPenDown = False
    End Sub

    Private Sub inkPanel_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles inkPanel.Paint

        mRenderSignature(e.Graphics)

        Dim lsText As String = ""
        If Not Me.DesignMode Then
            If mdLastSignatureUpdate.HasValue Then
                lsText = "Signature last updated " & Me.LastSignatureUpdate.ToLongTimeString
            End If
            e.Graphics.DrawString(lsText, Me.Font, Brushes.Black, 5, inkPanel.Height - 20)
        Else
            lsText = "... Write your signature here ..."

            e.Graphics.DrawString(lsText, Me.Font, Brushes.Black, (inkPanel.Width / 2) - (e.Graphics.MeasureString(lsText, Me.Font).Width / 2), (inkPanel.Height / 2) - (e.Graphics.MeasureString(lsText, Me.Font).Height / 2))
        End If
    End Sub
    Private Sub mRenderSignature(ByVal g As Graphics)
        Using loPen As New Pen(Color.Black)
            loPen.Width = 2
            For Each loLines As List(Of Point) In moRememberInk
                g.DrawLines(loPen, loLines.ToArray)
            Next
            If moCurrentWriting.Count > 1 Then
                g.DrawLines(loPen, moCurrentWriting.ToArray)
            End If
        End Using
    End Sub
    Private Sub cmdClearInk_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdClearInk.Click
        moRememberInk.Clear()
        inkPanel.Refresh()
    End Sub
    Private mdLastSignatureUpdate As Nullable(Of Date) = Nothing
    <System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)> _
    Public Property LastSignatureUpdate() As Date
        Get
            Return mdLastSignatureUpdate
        End Get
        Set(ByVal value As Date)
            mdLastSignatureUpdate = value
        End Set
    End Property

    <System.ComponentModel.DesignerSerializationVisibility(System.ComponentModel.DesignerSerializationVisibility.Hidden)> _
    Public ReadOnly Property SignatureImage() As Image
        Get
            Dim loBitmap As New Bitmap(Me.Width, Me.Height)
            Using loGfx As Graphics = Graphics.FromImage(loBitmap)
                mRenderSignature(loGfx)
            End Using

            Return loBitmap
        End Get
    End Property

End Class

 

If anyone’s interested in a standalone sample project, post the request to this blog and I’ll see what I can do.

Possible Uses

It may be interesting to use this code as:

  • Signature recognition
  • “Mud map” style sketching for business applications
  • A basis for a drawing program 😉

Of course, if you’re using WPF, use InkPanel.  But if you don’t want the overhead, maybe this will be the foundation of a lightweight solution.

 

Share this post :