An Original Idea

because all great software begins with an original idea

Archive for the ‘VB.Net’ Category

Hosting Winforms in Firefox

Posted by anoriginalidea on November 16, 2009

 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

Posted in .net Framework, VB.Net, Windows Forms, Windows Presentation Foundation | Tagged: , , | 2 Comments »

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

Posted by anoriginalidea on August 10, 2009

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 :

Posted in .net Framework, VB.Net | Leave a Comment »

Flick Scrolling in Winforms

Posted by anoriginalidea on August 10, 2009

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 :

Posted in VB.Net, Windows Forms | Tagged: , , | 3 Comments »

Why my brain hurts – Objective C vs VB.Net

Posted by anoriginalidea on March 11, 2009

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

Posted in Objective C, VB.Net | 3 Comments »

A Simple Scroll Controller for Winforms

Posted by anoriginalidea on February 20, 2009

 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

Posted in .net Framework, Code, Software Development, VB.Net | 2 Comments »

Twittering using the Compact Framework

Posted by anoriginalidea on May 19, 2008

 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 :

Posted in .net Framework, Pocket PC Development, VB.Net | Tagged: , , , , | 4 Comments »

Easy InkCanvas in Winforms for capturing signatures

Posted by anoriginalidea on April 18, 2008

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 :

Posted in .net Framework, VB.Net, Windows Forms | Tagged: , , | 5 Comments »

Give the "Gift of Text" by sending an SMS with VB.NET and Skype

Posted by anoriginalidea on February 26, 2008

image

Never underestimate the value (to some) of sending someone a note.  In my case, a note to my beloved is an excellent way of ensuring a happier homecoming.

Each note has to have an appropriately original sentiment, and be sent in a timely fashion.  Sometimes circumstances do not permit time for the creative effort required.   (Although I’ve heard that Generation Y can shoot of a text message faster than I just wrote the word faster…)

So why not queue up some appropriate messages and let my computer send one a day at the appropriate time?  Yes I’m sure you can think of plenty, but this is just an intro to a code sample….

So to send an SMS, all you need to do is install Skype and get a reference to the COM type library:

image

 

After this, the following code sample should be enough to get you in trouble:

 

Public Sub SendSMS(ByVal strNumber As String, ByVal strBody As String)
    Dim loSkype As New SKYPE4COMLib.Skype
    Dim loSmsMessage As SKYPE4COMLib.SmsMessage

    loSmsMessage = loSkype.CreateSms(SKYPE4COMLib.TSmsMessageType.smsMessageTypeOutgoing, strNumber)
    loSmsMessage.Body = strBody
    loSmsMessage.Send()
    Trace.WriteLine(loSmsMessage.Status.ToString)

    loSmsMessage = Nothing
    loSkype = Nothing

End Sub

 

Have fun!

Links

Original VBA post by Conrad Sharry


Share this post :

Posted in .net Framework, VB.Net | Tagged: , , , , | Leave a Comment »

Getting the SMTP Email Address of an Exchange Sender of a MailItem from Outlook in VB.NET VSTO

Posted by anoriginalidea on January 11, 2008

 image

Sometimes the easiest things in software development are the hardest things.  Particularly when it comes to VSTO development.

The Problem

You’d think that programmatically retrieving the sender’s SMTP email address from an email item in Outlook would be easy wouldn’t you?  It isn’t.

The “Address” property of the MailItem object is supposed to return the email address.   And it does if your email comes from an internet sender, such as a friendly Nigerian businessman.  If the email sender a user of Microsoft Exchange, you get a wierd X400 formatted email address.  Not very handy if you want the SMTP email address.

If you search for this information you’ll find solutions that usually involve obsolete components (CDO 1.21 – Unsupported by Microsoft) or 3rd party dlls (such as the excellent “Outlook Redemption”).   See the links section at the bottom of this article for a list of the good articles that discuss these techniques.

If you want your application to “remain pure” .NET however, there is no “cut and dried” solution.

The Solution

After much experimentation and agony my colleague Puji Arsana and myself have devised a solution that uses pure VSTO and VB.Net, without any 3rd party dependencies.

It seems to me that many people have already created this solution (and published parts of this), but so far noone has published a complete solution before.

So without further ado, here’s the VB.NET code to allow you to extract the SMTP email address, regardless of whether it’s an exchange or internet email.

Private Function GetSMTPEmailAddress(mailItem As MailItem) As String

    If mailItem.SenderAddressType = "EX" Then
         Return GetEmailAddressForExchangeServer(loItem.Name)
    Else
         Return mailItem.Address
    End If

End Function

Private Function GetEmailAddressForExchangeServer(ByVal emailName As String) As String
        Dim loDummyMsg As MailItem = moMailItem.Application.CreateItem(OlItemType.olMailItem)
        Dim loAddress As Recipient = loDummyMsg.Recipients.Add(emailName)

        loAddress.Resolve()
        Dim lsSmtpAddress As String = GetMAPIProperty(loAddress.AddressEntry.MAPIOBJECT, PR_SMTP_ADDRESS)
        Return lsSmtpAddress

End Function

#Region "MAPI Interface ID'S"
    ' The Interface ID's are used to retrieve the specific MAPI Interfaces from the IUnknown Object
    Private Const IID_IMAPISession As String = "00020300-0000-0000-C000-000000000046"
    Private Const IID_IMAPIProp As String = "00020303-0000-0000-C000-000000000046"
    Private Const IID_IMAPITable As String = "00020301-0000-0000-C000-000000000046"
    Private Const IID_IMAPIMsgStore As String = "00020306-0000-0000-C000-000000000046"
    Private Const IID_IMAPIFolder As String = "0002030C-0000-0000-C000-000000000046"
    Private Const IID_IMAPISpoolerService As String = "0002031E-0000-0000-C000-000000000046"
    Private Const IID_IMAPIStatus As String = "0002031E-0000-0000-C000-000000000046"
    Private Const IID_IMessage As String = "00020307-0000-0000-C000-000000000046"
    Private Const IID_IAddrBook As String = "00020309-0000-0000-C000-000000000046"
    Private Const IID_IProfSect As String = "00020304-0000-0000-C000-000000000046"
    Private Const IID_IMAPIContainer As String = "0002030B-0000-0000-C000-000000000046"
    Private Const IID_IABContainer As String = "0002030D-0000-0000-C000-000000000046"
    Private Const IID_IMsgServiceAdmin As String = "0002031D-0000-0000-C000-000000000046"
    Private Const IID_IProfAdmin As String = "0002031C-0000-0000-C000-000000000046"
    Private Const IID_IMailUser As String = "0002030A-0000-0000-C000-000000000046"
    Private Const IID_IDistList As String = "0002030E-0000-0000-C000-000000000046"
    Private Const IID_IAttachment As String = "00020308-0000-0000-C000-000000000046"
    Private Const IID_IMAPIControl As String = "0002031B-0000-0000-C000-000000000046"
    Private Const IID_IMAPILogonRemote As String = "00020346-0000-0000-C000-000000000046"
    Private Const IID_IMAPIForm As String = "00020327-0000-0000-C000-000000000046"
#End Region

#Region "MAPI Properties"

    ' MAPI Properties
    Public Const PR_TRANSPORT_MESSAGE_HEADERS As UInteger = 8192030
    Public Const PR_BODY As UInteger = 268435486
    Public Const PR_BODY_HTML As UInteger = 269680670
    Public Const PR_HTML As UInteger = 269680898
    Public Const PR_DISPLAY_NAME As UInteger = 805371934
    Public Const PR_SUBJECT As UInteger = 3604510
    Public Const PR_EMAIL_ADDRESS As UInteger = 805503006
    'public const uint PR_NEG_EMAIL_ADDRESS = -2146496482;
    Public Const PR_SMTP_ADDRESS As UInteger = 972947486
    Public Const PR_ADDRTYPE As UInteger = 805437470
#End Region

#Region "structure and variables "
    Private Structure SPropValue
        Public ulPropTag As UInteger
        Public dwAlignPad As UInteger
        Public Value As Long
    End Structure

    ' return codes
    Private Const S_OK As Integer = 0
#End Region

#Region "MAPI Functions"

    <DllImport("MAPI32.DLL", CharSet:=CharSet.Ansi, EntryPoint:="HrGetOneProp@12")> _
    Private Shared Sub HrGetOneProp(ByVal pmp As IntPtr, ByVal ulPropTag As UInteger, ByRef ppProp As IntPtr)
    End Sub

    <DllImport("MAPI32.DLL", CharSet:=CharSet.Ansi, EntryPoint:="HrSetOneProp@8")> _
    Private Shared Sub HrSetOneProp(ByVal pmp As IntPtr, ByVal pprop As IntPtr)
    End Sub

    <DllImport("MAPI32.DLL", CharSet:=CharSet.Ansi, EntryPoint:="MAPIFreeBuffer@4")> _
    Private Shared Sub MAPIFreeBuffer(ByVal lpBuffer As IntPtr)
    End Sub

    <DllImport("MAPI32.DLL", CharSet:=CharSet.Ansi)> _
    Private Shared Function MAPIInitialize(ByVal lpMapiInit As IntPtr) As Integer
    End Function

    <DllImport("MAPI32.DLL", CharSet:=CharSet.Ansi)> _
    Private Shared Sub MAPIUninitialize()
    End Sub

    ''' <summary>
    ''' Get a property from a passed MAPI object
    ''' </summary>
    ''' <param name="oMAPIObject"></param>
    ''' <param name="uiPropertyTag"></param>
    ''' <returns></returns>
    Private Shared Function GetMAPIProperty(ByVal oMAPIObject As Object, ByVal uiPropertyTag As UInteger) As String

        If oMAPIObject.Equals(Nothing) Then
            'No MAPI Object
            Return ""
        End If

        Dim sProperty As String = ""
        Dim pPropValue As IntPtr = IntPtr.Zero

        Dim IUnknown As IntPtr = IntPtr.Zero
        Dim IMAPIProperty As IntPtr = IntPtr.Zero

        Try

            ' initialize MAPI
            MAPIInitialize(IntPtr.Zero)

            ' get the unknown object.
            IUnknown = Marshal.GetIUnknownForObject(oMAPIObject)

            'get the property
            Dim guidIMAPIProp As New Guid(IID_IMAPIProp)
            If Marshal.QueryInterface(IUnknown, guidIMAPIProp, IMAPIProperty) <> S_OK Then
                'Failed to get IMAPIProperty
                Return ""
            End If

            Try

                ' get the field from the MAPI Property
                HrGetOneProp(IMAPIProperty, uiPropertyTag, pPropValue)
                ' Is the property actually there?
                If pPropValue = IntPtr.Zero Then
                    Return ""
                End If
                ' Get the value back
                Dim propValue As SPropValue = DirectCast(Marshal.PtrToStructure(pPropValue, GetType(SPropValue)), SPropValue)
                ' convert to string

                sProperty = Marshal.PtrToStringAnsi(New IntPtr(propValue.Value))
            Catch ex As System.Exception
                Throw ex
            End Try
        Finally
            ' CLEAN UP
            If pPropValue <> IntPtr.Zero Then
                MAPIFreeBuffer(pPropValue)
            End If

            If IMAPIProperty <> IntPtr.Zero Then
                Marshal.Release(IMAPIProperty)
            End If
            If IUnknown <> IntPtr.Zero Then
                Marshal.Release(IUnknown)
            End If

            MAPIUninitialize()
        End Try

        Return sProperty
    End Function
#End Region

How it Works

If the email is from exchange it translates the  email address into a “Recipient” object. 

Recipient objects expose “AddressEntry” objects, which in turn can be utilised by “ExtendedMAPI”.

The code then uses ExtendedMAPI which can “see” the property where the normal Outlook API cant.

Links

See http://www.outlookcode.com/d/code/getsenderaddy.htm#redemption and http://www.cdolive.com/cdo5.htm#EMailAddressOfSender for Redemption and CDO examples and http://groups.google.com/group/microsoft.public.outlook.program_vba/browse_frm/thread/4d4d5fece24a2a7/ad2fcbb691d5bf18 for a discussion of the property to use with Cached Exchange Mode in Outlook 2003 or later.


Share this post :

Posted in .net Framework, Outlook, VB.Net, VSTO | Tagged: , , , , | 27 Comments »

Getting a Screenshot with VB.NET on the Compact Framework 2.0

Posted by anoriginalidea on January 3, 2008

 

image

I believe that “thumbnail” images of data in applications is a powerful way of giving an overview to a user.

One sort of application that uses this technique is the “Flip 3D” functionality of Vista.

The code sample below provides a routine that “grabs” a rectangle of the currently displayed screen.  Just like it’s desktop equivalent, it can only take screenshots of the visible screen, not graphics that are off-screen. (Anyone know how to do that? Please let me know!)

Here’s the code:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    picScreenshot.Image = GetControlBitmap(Me.CreateGraphics, Me.SomeControl.Bounds)
End Sub
Const SRCCOPY As Integer = &HCC0020
Public Declare Function BitBlt Lib "coredll.dll" (ByVal hdc As IntPtr, ByVal nXDest As Integer, ByVal nYDest As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hdcSrc As IntPtr, ByVal nXSrc As Integer, ByVal nYSrc As Integer, ByVal dwRop As Integer) As Boolean

Private Function GetControlBitmap(ByVal gx As Graphics, ByVal rect As Rectangle) As Bitmap

    ' Create the bitmap to output
    Dim loBitmap As Bitmap = New Bitmap(rect.Width, rect.Height)

    ' Create compatible graphics
    Dim loCompGraphics As Graphics = Graphics.FromImage(loBitmap)

    ' Blit the image data
    BitBlt(loCompGraphics.GetHdc(), 0, 0, rect.Width, rect.Height, gx.GetHdc(), rect.Left, rect.Top, SRCCOPY)

    ' Cleanup
    loCompGraphics.Dispose()
    Return loBitmap
End Function

The function “GetControlBitmap” will get a bitmap of a control or any rectangle passed into it.

Links


Share this post :

Posted in .net Framework, Pocket PC Development, VB.Net | Tagged: , , , , | 2 Comments »