--> Gospel Midi & Programming: 12/16/07 - 12/23/07

Wednesday, December 19, 2007

Creating an AIM Plugin in VB.NET Using the .NET Framework - Part 2

Welcome back.

The method m_session_BeforeImSend calls the transmogrify function. Since there isn't one there, we'll add it. The transmogrify function takes a string and shifts each letter 13 characters then returns the "transmogrified" string:


''' <summary>
''' All letters in a sent IM will be shifted 13 places.
''' </summary>
''' <param name="s"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function transmogrify(ByVal s As String) As String

Dim output As New StringBuilder

Dim chs As Char() = s.ToCharArray

For i As Integer = 0 To s.Length - 1

Select Case chs(1)

Case "a"c
output.Append("n")

Case Else
output.Append(chs(i).ToString)

End Select

Next i

Return output.ToString

End Function


I have no idea why the author uses a StringBuilder instead of a regular String. Maybe you can try it and tell me what the difference is. Just like the original author, I'm not going to implement all 52 cases either. I will say that there is definitely an easier way than actually defining 52 cases.

Think about it like this. If the letter is the 14th letter (N) of the alphabet (26 letters total), then shifting it 13 places would be (A). All characters have numeric values. For anything less than N, add 13. For anything N or later, start with the value 12 less than A's value, and then add 13. Two cases will handle the entire alphabet.

Or, for the sake of testing, you could have this function return something like "I love ______!" no matter what is typed. I have "Julia" in that blank.

If you didn't know (it was news to me when I found out), you can specify the text for your custom functions and parameters that Intellisense displays. Just type:


'''


before any class, subroutine, function, property, or structure declaration, and you will be able to describe in more detail what this piece of code does. Excellent if you have to share code.

Additionally, what I just learned today, a single quoted letter or character followed by c will give you the Char value. Priceless.

This is the end of Part 2 of this post. Come back for part 3.

Labels: , , ,

Creating an AIM Plugin in VB.NET Using the .NET Framework - Part 1

This post is based upon this web site:

http://dev.aol.com/creating-aim-plugin-in-csharp#comment-208

I love VB.NET; am I going to say it's better than C#? No. I don't have time for petty squabbling. Both are languages for the same framework, but it does seem that C# allows for better control in particular areas. That is a fact.

*NOTE: This tutorial uses Visual Studio 2005, which requires .NET 2.0.

With that aside:

Getting Started...
1) Open Visual Studio 2005. Go to File --> New Project (Ctrl + N).
2) Under "Project Types", go to Visual Basic --> Windows --> and select "Class Library" on the right-hand side. In the text box beside "Name," type:

Rotate

(Personally, I typed "Rotate - VB.NET", but that doesn't matter).

3) If you haven't already, download the latest version of the Open AIM SDK (I'm using version 1.5) from http://developer.aim.com/plugin. Log in by clicking "Manage your keys" under the yellow "Get Started" button. Although the page claims 1.1.2 is the latest version, if you login, 1.5 is available for download. Download accsdk_win32_1_5.zip to your desktop.

4) In Visual Studio 2005, go to Project --> Rotate Properties. Click "Compile" on the left-hand side. Look at the bottom and check "Register for COM interop."

5) Press Ctrl + Shift + S to save all files in your solution. You will be presented with a dialog box asking you where to save your files. For location, I used My Documents\Visual Studio 2005\Projects.

6) After you have created the folder for our "Rotate" solution, unzip the accsdk_win32_1_5.zip file in a folder called accsdk_win32_1_5 within the folder created for your solution so we can locate it easier. We will need this in the near future.

Creating a Reference to the SDK Library

1) Go to Project --> Add Reference.
2) Click "Browse" and browse to the accsdk_win32_1_5 folder where you unzipped the Open AIM SDK. Go to the:

Dist --> Release

folder to add a reference to "acccore.dll" to your project by double-clicking the file.

*NOTE: The reason I didn't use the COM tab is that because on the first time, it has to scan the entire computer for usable DLLs. I don't like to wait.

3) Go to Project --> Add Reference --> .NET and hold Ctrl and click the following two .NET libraries:

System.Drawing
System.Windows.Forms

Click OK to add references to these libraries.

Creating a Rotate Class
I didn't want to use "Class1.vb", so I went in the Solution Explorer and deleted it. I added a new class called "Rotate.vb" by going to Project --> Add Class. Select "Class" as the template and type "Rotate.vb" in the textbox beside "Name." Click OK.

Importing the Necessary Libraries
In order to use our referenced libraries, we need to import them. Add the following code before "Public Class Rotate":

Imports System.drawing
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.windows.forms

Imports Microsoft.Win32
Imports AccCoreLib

If any of these lines are underlined in green, it means that the required references have not been added to the solution. Go to Project --> Add References to add any missing references.

Adding Self-Registering
Self-registering allows your application to add information to the registry so that your plugin is known to AIM. Add the following code to your class:


#Region "Plugin Registration"
<ComRegisterFunctionAttribute()> _
Public Shared Sub RegisterFunction(ByVal t As Type)
Dim key As RegistryKey = Registry.LocalMachine.CreateSubKey(PluginKeyName(t))
key.SetValue("Name", t.Name)
End Sub
<ComUnregisterFunctionAttribute()> _
Public Shared Sub UnregisterFunction(ByVal t As Type)
Registry.LocalMachine.DeleteSubKey(PluginKeyName(t))
End Sub
Private Shared Function PluginKeyName(ByVal t As Type) As String
Return "Software\America Online\AIM\Plugins\" + "{"C + t.GUID.ToString() + "}"C
End Function
#End Region


If you know about the "My" namespace, you can use this instead to handle the registry. For the sake of creating a VB.NET version of the article, that will not be covered here.


Implementing the Interfaces
Now we are going to change our class declaration to include a reference to our developer key (replace DEVELOPER_KEY in the following code with the key value) and the two interfaces we use from the SDK. Change your class declaration from:

Public Class Rotate

to


<GuidAttribute("DEVELOPER_KEY")> _
Public Class Rotate
Implements IAccPlugin, IAccCommandTarget


NOTE: Replace the text DEVELOPER_KEY with your own key. You must use a Dev (Development) key for compiling your plugin. This may seem elementary to some, but since the Deploy key seemed to have less restrictions, I thought it was ideal. Wrong.

According to an e-mail I received from gregsblog@aol.com Development keys require a fingerprint otherwise known as a hash of your dll. Anytime you compile the code with a modification, the hash will change, thus making AIM not load the plugin.

Thanks, Greg.

If you copy and paste this code and IAccPlugin and IAccCommandTarget are underlined in blue, indicating that they have not been implemented by this class, then move your cursor to the end of IAccCommandTarget and press Enter. This will automatically add the necessary functions and subroutines (methods) for implementing these two classes. The added code is:


Public Sub Exec(ByVal command As Integer, ByVal users As Object) Implements AccCoreLib.IAccCommandTarget.Exec

End Sub

Public Function QueryStatus(ByVal command As Integer, ByVal users As Object) As Boolean Implements AccCoreLib.IAccCommandTarget.QueryStatus

End Function

Public Sub Init(ByVal session As AccCoreLib.AccSession, ByVal pluginInfo As AccCoreLib.IAccPluginInfo) Implements AccCoreLib.IAccPlugin.Init

End Sub

Public Sub Shutdown() Implements AccCoreLib.IAccPlugin.Shutdown

End Sub


Before we implement these methods, we need to create some variables; otherwise, we will get errors as we implement the methods. At the top of the class, just below the class declaration, add the following variables:


Const kCommandID As Integer = 0
Private WithEvents m_session As AccSession
Private xlate As Boolean = False


The first declaration creates a constant value that represents a command. The second m_session is a session object we use to keep track of user preferences. For VB.NET, we need WithEvents because we need to access the events that happen during the current AIM session. The last is a Boolean that tells our plugin whether to translate the text message.

Find the Init method in the IAccPlugin region and add the following code:


Me.m_session = session
Dim command As IAccCommand = pluginInfo.AddCommand(kCommandID)
Dim command2 As IAccCommand = pluginInfo.AddCommand(AccCommandId.AccCommandId_Preferences)
command.Property(AccCommandProp.AccCommandProp_Text) = "Command #1..."
command2.Property(AccCommandProp.AccCommandProp_Text) = "Command #2..."
AddHandler Me.m_session.BeforeImSend, AddressOf m_session_BeforeImSend


Why are there two different commands added instead of 1 like in the example? I'll explain at the end

In the last line of the Init method, the BeforeIMSend event of the m_session object is handled by the m_session_BeforeImSend. We have to create this method with the correct signature:


Private Sub m_session_BeforeImSend(ByVal session As AccSession, ByVal imSession As IAccImSession, _
ByVal recipient As IAccParticipant, ByVal im As IAccIm) Handles m_session.BeforeImSend

End Sub


Before our IM is sent, we want to "transmogrify" our text if the plugin is enabled. Add this code to the m_session_BeforeImSend method:


If Me.xlate Then im.Text = Me.transmogrify(im.Text)


When our plugin is shutdown, we need to release the resources used to keep our preferences for the current session. Add this line to the Shutdown method:


Me.m_session = Nothing


Stay tuned for Part 2 of this tutorial.

Labels: , , ,