博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Calling DLL routines from LotusScript. Part I: Windows API
阅读量:5935 次
发布时间:2019-06-19

本文共 11665 字,大约阅读时间需要 38 分钟。

Domino/Notes Version: 4.x and higher

Platform: Windows 95, 98, NT 4

Like me, you probably find LotusScript just cannot do everything you want at times. After seeing the article titled "Changing Drivers on the Road" in the February 1998 a whole new world became obvious to me. The article described how to call the Windows API functions from within LotusScript. I have found countless uses for this including:

· Modifying the default printer (as described in the above mentioned article)

· Getting a list of Windows printers to present to the user before modifying the default printer
· Using the Windows Common Dialogs
· Accessing the Windows clipboard
· Getting Windows configuration settings (temp directory, computer name, etc.)
· and quite a few others...

A natural and quite possibly even more interesting extension to this is using the same method to call the Notes API. Again, I must given credit where credit is due. An article in sparked this idea. It appeared in the July/August 1998 issue and was called "Manipulating Rich Text Fields with LotusScript and the HiTest C API - Without C Programming". When I have done this I have chosen to use the C API over the HiTest C API and I will tell you why later. Part I of this document will describe writing declares and using the Windows API DLLs. Part II will cover using the Lotus Notes C API.

Part I: The Windows API

My intent here is not to cover programming the Windows API as there are many good books on the subject but to cover integrating it into your Lotus Notes/Domino applications. I have included several good references on more information that I found useful as I was getting started doing this and I also have a couple of examples to show you what can be done through the API.

Declaring the DLL Functions

Often, the trickiest part of using the WIndows API is writing the counterpart of the API routine in Notes; the declare statement for the function in the DLL. It takes some practice to get things right. Without the right declare statement get prepared for lots of memory exceptions and crashes within the Notes client. VB programmers do this all of the time so there are a few good references that you will find handy:

First and foremost if you have Visual Basic, it contains a Text API Viewer which allows you to browse the Windows API functions and their associated declares. You can copy them to the clipboard and paste then into your (Declarations). The declares are also stored in a plain text file, WIN32API.TXT, that you can open with any text editor. Personally, I find this more effective for finding what I want.

If you don’t have VB then there is another alternative. First, find the Windows DLL (e.g. kernel32.dll) you would like to investigate functions for in the Windows System directory using Windows Explorer. Right click it and select Quick View. This will bring up, among other things, an Export Table that will list the names of all of the functions in the DLL. Knowing what function you want to call, you just need the syntax for each function. The comes in handy here. On it, you’ll want to go to the MSDN Library Online but first you will have to register and tell MS about yourself. I think it is well worth it. Once on the site, a search on WIN32API.TXT turns up several good articles some of which are listed below. (The URLs are included here but I imagine they might change and that is why I told you how I found the documents.)

This article introduces you Declaring DLL routines for Word Basic but it applies equally to VB and LotusScript. Most importantly, it also covers how to convert C Language declarations to Word Basic/LotusScript equivalents.

An introduction to calling DLL procedures from VB. Listed here are important Windows DLL files and what types of routines they contain.

I have provided a couple of examples here to discuss the main points in writing these solutions. The examples cover using the Windows Common Dialogs and using the Windows clipboard.

Example 1 - Windows Common Dialogs

The Lotus macro language has @Prompt([LocalBrowse]) but LotusScript programmers aren’t so lucky. In trying to solve this problem I could not help but think about using the Windows Common Dialogs. Here I’ll show you how to use the Open File dialog and this method can be extended to other common dialogs as well.

To demonstrate this I wrote an Agent that had the settings "Manually from the Actions menu" and "Run Once (@Commands may be used)"


(Declarations)

Type OPENFILENAME

lStructSize As Long
hwndOwner As Long
hInstance As Long
lpstrFilter As String
lpstrCustomFilter As String
nMaxCustFilter As Long
nFilterIndex As Long
lpstrFile As String
nMaxFile As Long
lpstrFileTitle As String
nMaxFileTitle As Long
lpstrInitialDir As String
lpstrTitle As String
flags As Long
nFileOffset As Integer
nFileExtension As Integer
lpstrDefExt As String
lCustData As Long
lpfnHook As Long
lpTemplateName As String
End Type

Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long

 


Sub Initialize

Dim OpenFile As OPENFILENAME
Dim Returnl As Long
Dim Filterstr As String

OpenFile.lStructSize = Len(OpenFile)

Filterstr = "Word Documents (*.doc)" & Chr(0) & "*.doc" & Chr(0) & "All Files (*.*)" & Chr(0) & "*.*" & Chr(0)
OpenFile.lpstrFilter = Filterstr
OpenFile.nFilterIndex = 1
OpenFile.lpstrFile = String(257, 0)
OpenFile.nMaxFile = Len(OpenFile.lpstrFile) - 1
OpenFile.lpstrFileTitle = OpenFile.lpstrFile
OpenFile.nMaxFileTitle = OpenFile.nMaxFile
OpenFile.lpstrInitialDir = "C:\My Documents"
OpenFile.lpstrTitle = "Open File"
OpenFile.flags = 0
Returnl = GetOpenFileName(OpenFile)

If Returnl = 0 Then

Msgbox "The user pressed the Cancel Button"
Else
Msgbox "The user chose " & Trim(OpenFile.lpstrFile)
End If
End Sub


This example demonstrates several important things about declaring and calling DLL routines.

Often structures are used to pass data to and from these routines. Not only do you need to declare the routine but you must also define the structures to LotusScript. I have done that here with the OPENFILENAME structure in the (Declarations) section of my Agent. I just copied the declarations straight from the WIN32API.TXT file. In my call to the routine I have chosen to default the folder to "My Documents" and to display only Word (.doc) documents by default and also giving the user the option to change the Files of Type selection to "All Files (*.*)". For more information on the syntax of the options for GetOpenFileName see the developer's network and search of GetOpenFileName. My program simply calls the dialog box and returns, via a message box, the path and filename that the user has selected. This information can then be used for a file operation such as a NotesEmbeddedObject.ExtractFile

Example 2 - Accessing the Windows clipboard

I originally wrote this when I was using OLE Automation from LotusScript to work in another application (MS Word) and needed to bring back text from the other application into a Notes backend document. This routine accomplishes that although it just brings back plain text. I am sure there are lots of other uses for and extensions of it.


(Declarations)

'Clipboard Manager Functions

Declare Function GetClipboardData Lib "User32" (Byval wFormat As Long) As Long 'Note: GetClipboardDataA as aliased in Win32api.txt did not work!
Declare Function OpenClipboard Lib "User32" Alias "OpenClipboard" (Byval hwnd As Long) As Long
Declare Function CloseClipboard Lib "User32" Alias "CloseClipboard" () As Long

'Predefined Clipboard Formats

Public Const CF_TEXT = 1

'Memory management functions

Declare Function GlobalLock Lib "kernel32" Alias "GlobalLock" (Byval hMem As Long) As Long
Declare Function GlobalUnlock Lib "kernel32" Alias "GlobalUnlock" (Byval hMem As Long) As Long

'String Copy function for each of its various parameter configurations lstrcpy(to_string, from_string)

Declare Function lstrcpyLP2Str Lib "kernel32" Alias "lstrcpyA" (Byval lpString1 As String, Byval lpString2 As Long) As Long
Declare Function lstrcpyStr2Str Lib "kernel32" Alias "lstrcpyA" (Byval lpString1 As String, Byval lpString2 As String) As Long
Declare Function lstrcpyStr2LP Lib "kernel32" Alias "lstrcpyA" (Byval lpString1 As Long, Byval lpString2 As String) As Long

'String Length function for each of its various parameter configurations

Declare Function lstrlenLP Lib "kernel32" Alias "lstrlenA" (Byval lpString As Long) As Long
Declare Function lstrlenStr Lib "kernel32" Alias "lstrlenA" (Byval lpString As String) As Long

'Keyboard input functions

Declare Function GetFocus Lib "User32" Alias "GetFocus" () As Long

 


Function GetClipboardContents() As String

Dim ClipboardHandlel As Long

Dim LpStrl As Long
Dim HWndl As Long
Dim Resultl As Long
Dim Clipboardstr As String

'Get a handle for the current window that has keyboard focus

HWndl = GetFocus()

'Open the clipboard, specify this window as the owner so no one else modifies it while we use it

If (OpenClipboard(HWndl) <> 0) Then

'Get the data off of the clipboard in text format

ClipboardHandlel = GetClipboardData(CF_TEXT)

'Get the text out of Windows memory into a string we can work with here

If (ClipboardHandlel <> 0) Then
'Lock the memory we will work on and get a handle to it
LpStrl = GlobalLock(ClipboardHandlel)
'Pre-allocate some space for our String
Clipboardstr = Space$(lstrlenLP(LpStrl))
'Copy it in
Resultl = lstrcpyLP2Str(Clipboardstr, LpStrl)
'Release the lock
GlobalUnlock(ClipboardHandlel)
Else
Clipboardstr = "NULL"
End If
'Close the clipboard so other applications may use it
Resultl = CloseClipboard
Else
Print "Could not open Clipboard"
End If

GetClipboardContents = Clipboardstr

End Function


There are some important points about this code worth mentioning. There are sometimes more that one way to alias a DLL routine depending on the types of parameters that will be passed to it. In Example 2 I have done this for the lstrlenA routine which computes the length of a string.

Often the result of a call to a DLL routine will be a pointer to a block of memory that contains a result; in our case a string. This is a little different from a block of memory that has been allocated via LotusScript for a string variable. When using lstrlenA providing it pointers to each of these blocks of memory is done differently. In the first case, the pointer is passed as a Long. Is the second case the pointer is passed for the String. Each of these two difference interactions with the single routine require a different declaration in LotusScript as I have done for lstrlenA. I have named them so it is easy to tell them apart when using them. For the version that is used when the pointer is a long pointer obtained from another routine I have appended "LP" to its name and declared the parameter as ByVal Long. For the version that is used when a LotusScript string variable is used I have appended "Str" to its name and declared the parameter as ByVal String..

Conclusion

I think it goes without saying that careful planning must be done when using these types of solutions since you are tying your application to not only the Lotus Notes platform but the Operating System version. These types of calls would not result in cross platform solutions that would work on other Operating Systems. But, if you work primarily in the Windows enviroment as many people do the power here is very appealing. And, although Windows versions are usually backward compatible it is not always the case that things behave exactly the same from one version to another.

Hopefully this document arms you with enough information and inspiration to incorporate this type of functionality into your solutions.

转载地址:http://nwjtx.baihongyu.com/

你可能感兴趣的文章
Go 语言环境搭建
查看>>
sql常用语句
查看>>
PixelFormat 枚举
查看>>
多媒体之录音
查看>>
jQuery ajax - ajax() 方法详解
查看>>
什么是“对用户友好”
查看>>
android 获取网络类型名称2G 3G 4G wifi
查看>>
MySQL thread pool【转】
查看>>
开源数据汇集工具
查看>>
几本自然语言处理入门书
查看>>
java根据本地Ip获取mac地址
查看>>
cocos2d-x路~使得第一个字游戏(一个)
查看>>
SQLServer:什么是主键(PK)和外键(FK)?
查看>>
Android开发之获取设备的屏幕信息和px dp之间的转换
查看>>
.NET中的动态编译
查看>>
Android开发UI之Action Bar
查看>>
在Oracle中使用Guid
查看>>
iOS 在不添加库的情况下 通过抽象类来获取自己想要的方法
查看>>
罗将公布手机锤,我感到深深的内疚
查看>>
spark(1.1) mllib 源代码分析
查看>>