Category Archives: Software Development

Backing up your files without file locks on Windows

Standard

Make perfect copies every time with Volume Shadow Copy

Do you have some files you want backed up but can’t afford the downtime?

As part of the eidy we have a shared game world for the team to experiment with running windows server.  Windows has a feature called “Volume Shadow Copy” that allows you to copy files while they are in use.

Shadow Copy is used in taking manual or automatic backup copies or snapshots of computer files or volumes, even when they are in use. It is implemented as a Windows service called the Volume Shadow Copy service. A software VSS provider service is also included as part of Windows to be used by Windows applications. Shadow Copy technology requires the file system to be NTFS to be able to create and store shadow copies. Shadow Copies can be created on local and external (removable or network) volumes by any Windows component that uses this technology, such as when creating a scheduled Windows Backup or automatic System Restore point. (From: https://en.wikipedia.org/wiki/Shadow_Copy)

I didn’t particularly want to use backup.  I just wanted to do a simple file copy.

The way this works is that you mount the folder you want to copy as a special drive letter, which you then copy the files from.  Weird eh?

I did this using a cool little program called “ShadowSpawn” that allows you to execute a command using a volume shadow copy mount.

Using Windows Scheduler I execute the following command:

shadowspawn C:\eidy Q: robocopy Q:\ D:\eidybackup /s

(The volume “Q:\” is a temporary driver letter, “D:\” is a cloud synced volume)

It’s easy to setup, and may help with your simplistic copying needs.

Advertisements

Optimising Winforms Dropdown list combos for touch

Standard

image

The optimisation of the iPhone and the iPad for touch has contributed to it’s success. 

One example of this kind of optimisation is “drop down combos”.  Rather than sticking with the traditional touch UI of a big combo with a fat scrollbar (that would mess up web pages), they do something completely different.  As shown above a neat “roller” control is shown which makes combos a pleasure to use.

On the iPad the experience is more like a traditional combo, but it is not the same.

In the creation of Windows 7 Tablet user interfaces I am sure our users would prefer this kind of experience.

In Winforms it turns out that it’s possible to improve the touch experience markedly using the “OwnerDrawVariable” style on comboboxes.

As you can see, when the combo box looks relatively normal, not taking up much screen real estate….

image

Yet when it’s clicked, the control becomes bigger, so the normal flick scrolling features of Windows 7 tablet can work better.

image

The following code sample is a class called TouchCombo that can be used to cause combos to take on the new style.  Here’s the code for the sample form:

Public Class Form1
    Private Sub mPopulate(ByVal combo As ComboBox)
        combo.Items.Add("Alpha")
        combo.Items.Add("Beta")
        combo.Items.Add("Gamma")
        combo.Items.Add("Delta")
        combo.Items.Add("Epsilon")
        combo.SelectedIndex = 0

    End Sub

    Private moTouchCombo As New TouchCombo
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        mPopulate(ComboBox1)
        mPopulate(ComboBox2)
        moTouchCombo.Connect(ComboBox2)
    End Sub
End Class

 

Here’s the code for the TouchCombo class:

 

Public Class TouchCombo

    Public Sub Connect(ByVal combo As ComboBox)
        combo.DrawMode = DrawMode.OwnerDrawVariable
        combo.DropDownHeight = 200
        combo.DropDownWidth = combo.Width * 1.5
        AddHandler combo.MeasureItem, AddressOf mMeasureItem
        AddHandler combo.DrawItem, AddressOf mDrawItem
        AddHandler combo.DropDown, AddressOf mDropDown
        AddHandler combo.DropDownClosed, AddressOf mDropDownClosed
        AddHandler combo.Disposed, AddressOf mDisposed
    End Sub

    Private Sub mDrawItem(ByVal sender As Object, ByVal e As System.Windows.Forms.DrawItemEventArgs)

        Dim loCombo As ComboBox = sender

        Using loBrush = New System.Drawing.SolidBrush(e.ForeColor)

            ' Draw the normal Background
            e.DrawBackground()

            ' If it's not dropped down, make it look normal
            If Not loCombo.DroppedDown OrElse e.State = DrawItemState.ComboBoxEdit OrElse e.State = DrawItemState.Default Then
                e.Graphics.DrawString(loCombo.Items(e.Index), loCombo.Font, loBrush, e.Bounds.X, e.Bounds.Y)
            Else
                ' Otherwise draw it big
                Using loFont As New System.Drawing.Font("Arial", 15, FontStyle.Bold)
                    e.Graphics.DrawString(loCombo.Items(e.Index), loFont, loBrush, e.Bounds.X, e.Bounds.Y)
                End Using
            End If

            e.DrawFocusRectangle()

        End Using

    End Sub
    Private Sub mMeasureItem(ByVal sender As Object, ByVal e As System.Windows.Forms.MeasureItemEventArgs)
        e.ItemHeight = 35
    End Sub
    Private Sub mDropDown(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim loCombo As ComboBox = sender
        loCombo.ItemHeight = 35
    End Sub

    Private Sub mDropDownClosed(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim loCombo As ComboBox = sender
        loCombo.ItemHeight = 15
    End Sub

    Private Sub mDisposed(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim loCombo As ComboBox = sender
        RemoveHandler loCombo.MeasureItem, AddressOf mMeasureItem
        RemoveHandler loCombo.DrawItem, AddressOf mDrawItem
        RemoveHandler loCombo.DropDown, AddressOf mDropDown
        RemoveHandler loCombo.DropDownClosed, AddressOf mDropDownClosed
        RemoveHandler loCombo.Disposed, AddressOf mDisposed
    End Sub
End Class

 

Download the project.

PowerPoint Inception Deck template for the Agile Samurai

Standard

 

image

Recently I read the “Agile Samurai” a great introduction to Agile software development.

The first part of the book talks about an artefact called the “Inception Deck”, a number of cards or powerpoint presentation that is used to help understand and scope a software project.

The inception deck elaborates on:

  1. Why are we here?
  2. Create an elevator pitch
  3. Product Box
  4. Create a NOT list
  5. Meet your neighbours
  6. Show the solution
  7. What keeps us up at night
  8. Size it up
  9. Be clear on what’s going to give
  10. Show what it’s going to take

I couldn’t find a powerpoint template to start me off, so I created one for anyone who is interested.  It’s pretty basic, but it’s nice to start somewhere.

Download here.

Links

Learn more from the Agile Warrior himself here:

http://agilewarrior.wordpress.com/2010/11/06/the-agile-inception-deck/

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)

In hell with SSL and WCF

Standard

 image

A long time ago I decided that WCF was one of those things I wouldn’t try and learn about in preference to learning other things, such as Silverlight, MVC and how to cook cookies properly.  Now that decision has come back to haunt me.

It seemed simple.  A client server prototype using wsHttpBindings and WCF.  My initial Project’s configuration files worked well on my local development machine (http).

The time came to put this on the server using SSL (https).

Much of the documentation on the web says that the simplest way of doing this is to configure IIS (IIS6 in my case) to work with SSL, then copy it over.  Words cannot express how wrong this proved to be.

For future reference, rest assured you will need very different versions of these files for local development as opposed to a production server.

I’ve also learnt that WCF gives as good as it gets in the ongoing competition between software development technologies in providing weird and useless error messages that are no hope at all in solving problems.  (Although handy for doing google searches to find others as miserable as you are)

Before

image

My original (Visual Studio generated) client app.config file looked like this:

<system.serviceModel>
  <bindings>
    <wsHttpBinding>
      <binding name="WSHttpBinding_IClientConnect" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
          maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
          messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
          allowCookies="false">
        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
        <reliableSession ordered="true" inactivityTimeout="00:10:00"
            enabled="false" />
        <security mode="Message">
          <transport clientCredentialType="Windows" proxyCredentialType="None"
              realm="" />
          <message clientCredentialType="Windows" negotiateServiceCredential="true"
              algorithmSuite="Default" />
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <client>
    <endpoint address="http://localhost:10916/SecureClientDemoServer/ClientConnect.svc"
        binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IClientConnect"
        contract="ClientService.IClientConnect" name="WSHttpBinding_IClientConnect">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
  </client>
</system.serviceModel>

My server web.config file looked like this:

    <system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
        <services>
   <service behaviorConfiguration="ServiceBehavior" name="ClientConnect">
    <endpoint address="" binding="wsHttpBinding" contract="IClientConnect">
     <identity>
      <dns value="localhost" />
     </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
   </service>
  </services>
        <behaviors>
            <serviceBehaviors>
                <behavior name="ServiceBehavior">
                    <!– To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>
                    <serviceMetadata httpGetEnabled="true"/>
                    <!– To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information –>
                    <serviceDebug includeExceptionDetailInFaults="false"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>

 

After

 image

app.config

<system.serviceModel>
   <bindings>
    <wsHttpBinding>
      <binding name="WSHttpBinding_IClientConnect" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
        <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
        <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/>
        <security mode="Transport">
          <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
          <message clientCredentialType="None"  algorithmSuite="Default" negotiateServiceCredential="false" establishSecurityContext="false" /> 
        </security>
      </binding>
    </wsHttpBinding>
  </bindings>
  <client>
    <endpoint address=https://remoteserver/SecureClientDemo/ClientConnect.svc binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IClientConnect" contract="ClientService.IClientConnect" name="WSHttpBinding_IClientConnect">
    </endpoint>
  </client>
</system.serviceModel>

 

web.config

    <system.serviceModel>
        <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
        <services>
            <service behaviorConfiguration="ServiceBehavior" name="ClientConnect">
                     <endpoint address=https://remoteserver/SecureClientDemo/ClientConnect.svc bindingConfiguration="HttpsBinding" binding="wsHttpBinding" contract="IClientConnect">
                </endpoint>
                <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"
                                 name="MexHttpsBindingEndpoint" 
                                 />
            </service>
        </services>
        <behaviors>
            <serviceBehaviors>
                <behavior name="ServiceBehavior">
                    <!– To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment –>
                    <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true"/>
                    <!– To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information –>
                    <serviceDebug includeExceptionDetailInFaults="false"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
           <bindings>
         <wsHttpBinding>
          <binding name="HttpsBinding">
            <security mode="Transport">
              <transport clientCredentialType="None"/>
            </security>
          </binding>
        </wsHttpBinding>
            </bindings>
    </system.serviceModel>

 

 

Conclusion

This article is intended to show on the web a working set of configuration parameters, so for the time being I don’t have time to go into and explanation I only half understand.  I hope people find this helpful.

 

Links

http://msdn.microsoft.com/en-us/library/ms729700.aspx

http://stackoverflow.com/questions/1521117/wcf-over-ssl-404-error

http://stackoverflow.com/questions/2435823/the-provided-uri-scheme-https-is-invalid-expected-http-parameter-name-via

http://msdn.microsoft.com/en-us/library/ff648840.aspx

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

When User Experience doesn’t matter

Standard

image

I spend a great deal of time preaching the merits of user experience.  Software design is about the end user, not about my preferences as a user of software.

I particularly subscribe to the ideas in Alan Cooper’s work “Face 3” and the book the “Inmates are Running the Asylum”.  This involves researching one’s target market, creating personas typical of that market, then having those personas participate in realistic scenarios, which may or may not involve your software.

I think I’ve learnt the hard way, however, that sometimes designing the ideal user experience can be, frankly, a waste of time.

In a recent presentation, designer Joel Flom relates how designers sometimes create great designs which are gratefully received by the customer, who then proceed to take the design, consider it completely unworkable then place it in a box, never to be looked at again.   So all time spent in design, documentation and analysis is of no benefit to anyone.

Although creating a “world” (via personas and scenarios) that accurately model a user experience, we need to be careful that we do not lose sight of two highly influential factors. 

The first is ensuring that the personas we create truly do reflect the attitudes of our target market.  It’s tempting to create a persona that is a user advocate, that loves our company and wants to form a relationship with it.  This makes me feel warm inside but i don’t think it reflects every persons expectations.  Most people want to do something quickly and easily.  They’re not interested in taking us out to dinner.   Creating an elaborate “UX” for these people can be a waste of time.

The second involves the other stakeholders in the software project.  I’m talking about the analysts, developers, other designers, consultants and marketing that are expected to implement your ideas.  They have opinions too and need to be heard.  If they aren’t then they will either consciously or subconsciously sabotage or modify your grand plans beyond recognition.   

Joel provides 3 thoughts that may help.  Firstly, get a complete picture of the customer experience, not just an idealised one.  Become a student of the business, not just your customer’s business, but your own.  Understand what all the stakeholders want, particularly those responsible for implementing your solution.  Give the customer what they really need, not just what’s “cool”.  Having a more complete understanding of the problem will result in a truly effective solution.

 

 

Links

Enabling callto (Skype) in your application

Standard

image image

You may have noticed that Skype seems to embed itself into Internet Explorer, Firefox and Chrome.  It recognises contacts and phone numbers in the page and provides the ability to call them.

I believe people will expect this kind of functionality in conventional windows applications also.  To assist with this I created a little class that will not only allow calls, but allows a check for the existence of a skype and give the ability to extract the calling applications icon.

Sample Project

The sample winforms project includes the CallTo class and a simple Winforms test form:

image

The form has a textbox and button.   One load, the call button is enabled and give an image.  The button makes the call.

 

Public Class Form1

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim loCallTo As New CallTo
        cmdCall.Image = loCallTo.Image
        cmdCall.Enabled = loCallTo.Enabled
    End Sub
    Private Sub cmdCall_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdCall.Click
        Dim loCallTo As New CallTo
        loCallTo.DoCall(txtPhoneNumber.Text)
    End Sub

End Class

 

 

Heres the source of CallTo.vb:

 

Imports Microsoft.Win32
Imports System.Runtime
Imports System.Runtime.InteropServices

''' <summary>
''' This class allows for making callto calls
''' </summary>
Public Class CallTo

    ''' <summary>
    ''' Gets the image.
    ''' </summary>
    ''' <value>The image.</value>
    Public ReadOnly Property Image() As Image
        Get
            If Not Enabled Then Return Nothing

            Dim lsValue As String
            With Registry.ClassesRoot.OpenSubKey("callto\DefaultIcon")
                lsValue = .GetValue("")
            End With

            If lsValue.Contains(",") Then
                Dim lsBits() As String = lsValue.Split(","c)
                Dim lsFilename As String = lsBits(0).Trim(New Char() {""""c})
                Dim liPosition As Integer = Val(lsBits(1))
                Return moGetIconFromExeOrDll(lsFilename, liPosition)
            Else
                Return Nothing
            End If

        End Get
    End Property
    Private Declare Auto Function ExtractIcon Lib "shell32" ( _
ByVal hInstance As IntPtr, ByVal lpszExeFileName As String, _
ByVal nIconIndex As Integer) As IntPtr
    Private Function moGetIconFromExeOrDll(ByVal filename As String, ByVal position As Integer) As Image
        Dim hInstance As IntPtr = Marshal.GetHINSTANCE( _
           System.Reflection.Assembly.GetExecutingAssembly.GetModules()(0))
        Dim hIcon As IntPtr = ExtractIcon(hInstance, filename, position)
        Dim loBitmap As Bitmap = Bitmap.FromHicon(hIcon)
        Dim loReturn As Image = loBitmap.GetThumbnailImage(16, 16, Nothing, Nothing)

        loBitmap.Dispose()
        Return loReturn

    End Function

    ''' <summary>
    ''' Gets a value indicating whether this CallTo is enabled.
    ''' </summar
    ''' <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
    Public ReadOnly Property Enabled() As Boolean
        Get
            Try
                Dim loReg As RegistryKey = Registry.ClassesRoot.OpenSubKey("callto", False)
                loReg.Close()
            Catch
                Return False
            End Try
            Return True
        End Get
    End Property
    ''' <summary>
    ''' Does the call.
    ''' </summary>
    ''' <param name="destination">The destination.</param>
    Public Sub DoCall(ByVal destination As String)

        If Not Enabled Then Throw New ApplicationException("Callto is not enabled")
        Process.Start("callto://" & destination)

    End Sub

End Class

 

Download Sample

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

Alright, I admit it, Now I have an iPhone!

Standard

 

Dear Windows Mobile,

 

By the time you read this blog post, I’ll be gone.  I’m sorry for doing this but you left me no other choice.  I know comes as a bit of a shock to you – especially because things have been going so well.  But I’m sorry – I cant stand watching all those iPhone users giggling in the corridors anymore.  I think you’re swell, but I don’t think we’re right for each other.  First of all, we’re not compatible.  You’re a a bit too clunky and I’ve lost patience.   Secondly, I’m tired of waiting for Windows Mobile 7.  It’s too late isn’t it?

Anyway, I want to try another smart phone.  But you know what?  I still want to be friends.  We had some good times, developing software on the brilliant compact framework.  I’m very sad it has to be this way.  But please, don’t cold boot like last time.  Maybe I could still answer questions on the Compact Framework from time to time.  I still code in .net!  Look I wont even make issue of the fact that I had to buy you a replacement battery.

So, take care of yourself and all the best.

Sincerely

Me