Friday, September 30, 2005

Creating a Domino Navigation System - Part 2

Last time we got the views, forms, framesets etc up and running. This time we're going to look at execution.

Create a VB Script Library called NAVScripts

The first thing we need to do is add the RunShellExecute API to our Project.

In the Declarations section of your application, add the following;

Declare Function GetDesktopWindow Lib "user32" () As Long

Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (Byval hwnd As Long, Byval lpOperation As String, Byval lpFile As String, Byval lpParameters As String, Byval lpDirectory As String, Byval nShowCmd As Long) As Long

Note that the there are only two lines here (The second group has a few word-wraps in it).

Next, add the following code, which makes it a little easier to use the shellexecute function. It also allows us to pass multiple things to it separated by double hashes ## (this is useful if you want to specify a specific action, as specified in the comments at the beginning of the routine).

Sub RunShellExecute(sTopic As String, sFile As Variant, sParams As Variant, sDirectory As Variant, nShowCmd As Long)

'EXAMPLE: Play wav file with associated app RunShellExecute "Play", "c:\windows\media\Notify.wav", 0&, 0&, SW_SHOWNORMAL

'EXAMPLE: Play avi file with associated app RunShellExecute "Play", "E:\VB Graphics\avi\Cogs.avi", 0&, 0&, SW_SHOWNORMAL

'EXAMPLE: Open txt file with associated app RunShellExecute "Open", "c:\My Documents\rundll.txt", 0&, 0&, SW_SHOWNORMAL

'EXAMPLE: Open txt file with notepad RunShellExecute "Play", "C:\windows\notepad.exe", "c:\My Documents\rundll.txt", 0&, SW_SHOWNORMAL

Dim hWndDesk As Long
Dim success As Long

Const vbTextCompare = 1

Dim HashPos As Integer

HashPos = Instr(1, sFile, "##" , vbTextCompare)

If HashPos > 0 Then
sTopic = Left(sFile, HashPos -1 )
sFile = Right(sFile, (Len(sFile) - (HashPos+1)))
End If

'The desktop will be the default for error messages
hWndDesk = GetDesktopWindow()

Print "RunShellExecute: " + "Topic=[" + sTopic + "]" + " File=[" + sFile + "]"

'Execute the passed operation

success = ShellExecute(hWndDesk, sTopic, sFile, sParams, sDirectory, nShowCmd)

End Sub

I've also got a couple of other useful subs which we should include (or the code wont work).

The first of these subs allows us to replace specific parts of variables, very similar to the replace function in Visual BASIC. (Actually, this was what we used before there was a replace function). Using this allows you to interpret command lines on the fly (eg: Substitute %USERNAME% with the current user name).

Function ReplaceSubstring(BigString As String, ReplaceString As String, WithString As String, CaseSensitive As Boolean) As String
Dim CaseSelector As Integer
Dim ReplaceLength As Integer, Position As Integer
Dim LeftString As String, RightString As String

If CaseSensitive = True Then CaseSelector = 0 Else CaseSelector = 1
Position = Instr(1,BigString,ReplaceString, CaseSelector)

If Position <> 0 Then
ReplaceLength = Len(ReplaceString)
LeftString = Left$(Bigstring,Position-1)
RightString = Mid$(BigString,Position+ReplaceLength)
ReplaceSubstring = LeftString + WithString + RightString
ReplaceSubstring = BigString
End If
End Function

Now that we have actual "execution" routines, we need to create a function to read the values from the form and execute them.

Sub QueryODCentral(Source As Notesuiview, Continue As Variant)
Dim session As New NotesSession
Dim db As NotesDatabase
Dim docs As NotesDocumentCollection
Dim doc As NotesDocument

Set db = session.CurrentDatabase
Set docs = Source.Documents
Set doc = docs.GetFirstDocument()

Dim CommandLine As String
Dim LinkType As String
Dim LinkData As String
Dim DocInfo As String
Dim ReminderTitle As String
Dim DatabaseURL As String

DatabaseURL = db.NotesURL
DocInfo = doc.TXTTitle(0)
ReminderTitle = doc.Subject(0)
LinkType = doc.KeyLinkType(0)
LinkData = doc.TXTLinkData(0)

If DocInfo = "" Then DocInfo = ReminderTitle

Select Case Ucase$(Trim$(LinkType))

If LinkData <> "" Then
If Instr(1, Ucase$(LinkData), "%NOTESSERVER%",1) > 0 Then
LinkData = ReplaceSubstring(LinkData, "%NOTESSERVER%", NotesServer, 0)
End If

If Instr(1, Ucase$(LinkData), "%CURRENTYEAR%",1) > 0 Then
LinkData = ReplaceSubstring(LinkData, "%CURRENTYEAR%", Trim$(Format$(Now, "YYYY")), 0)

End If

RunShellExecute "Open", LinkData, 0&, 0&, 1
Print "LAUNCH: " + DocInfo
Print "LAUNCH ERROR: There was no document specified"
End If

Msgbox LinkData,64,DocInfo
Print "MESSAGE: " + LinkData

Case Else
Msgbox "Unknown Link Type - Unable to Launch",48,"Error"
End Select

Continue = False
End Sub

You will notice that in this code, there are two possible linktypes: Message and Launch. We can easily add more, though as yet, I havent found the need... Eventually though, I may add an opendocument type - I'll explain the use of Notes URLs a bit later, so you can see that this wont necessarily be required.

Finally, we need to make some modifications to the views... Remember to leave at least one view "untouched" (and call this view Edit Mode - or something similar).

In the Options for the View, include the phrase

Use "NAVScripts"

In the QueryOpenDocument part of the view, include the following;

Sub Queryopendocument(Source As Notesuiview, Continue As Variant)
QueryODCentral Source , Continue
End Sub

That's it... now you can start to create some Navigator Entries.

Ideally when you double-click them, they will launch.

The theory is that you could create an entry with a sensible display title (TXTTitle), set the link type (KEYLinkType) to LAUNCH, and then Set the Link Data (TXTLinkData) to almost anything;



The other terribly exciting thing that this navigator has over my old Navigator is that because these things are documents in views, I can full text search for anything I can't find.

Final Thoughts...
The full version of my navigator also includes...
  • Keywords for Department Names (so that certain things only appear for certain departments)
  • Keywords for Importance Levels etc... to assist in the sorting of items in views.
  • A calendar entry form which is similar to the navigator entry, which causes specific items to appear on specific days only. (and they're still launchable).

I apologise for getting so technical early on on this blog... I'll try to vary the technical levels of my entries. If anyone has any questions, let me know and I'll provide you with a template.


No comments: