Hey Ken I responded to someone before about the cursor position but I never
tried it myself. What's wrong with sending the EM_SETSEL message to the
RichEdit control? Should be fairly straightforward.
(One hour later...) Okay please excuse my horredous VBA/Win32. It's been so
long since I've done this. The code below will set the cursor position of
the body control or text box of any standard Outlook item. This started out
as a 10 minute thing but then I realized that guy wanted to set the position
in the subject so I had to change some things around.
-------------------------------------------
Option Explicit
Private Declare Function SendMessage Lib "User32.dll" Alias "SendMessageA"
(ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam
As Long) As Long
Private Declare Function GetForegroundWindow Lib "User32.dll" () As Long
Private Declare Function FindWindowEx Lib "User32.dll" Alias "FindWindowExA"
(ByVal hwndParent As Long, ByVal hwndChildAfter As Long, ByVal lpszClass As
String, ByVal lpszWindow As String) As Long
Private Declare Function EnumChildWindows Lib "User32.dll" (ByVal hwndParent
As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Boolean
Private Declare Function GetClassName Lib "User32.dll" Alias "GetClassNameA"
(ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long)
As Long
Private Declare Function SetFocusAPI Lib "User32.dll" Alias "SetFocus"
(ByVal hwnd As Long) As Long
Private Declare Function GetWindowTextAPI Lib "User32.dll" Alias
"GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As
Long) As Long
Private Declare Function GetWindowTextLength Lib "User32.dll" Alias
"GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Private Const CLASS_SUBJECT = "RichEdit20WPT"
Private Const CLASS_BODY = "RichEdit20W"
Private Const CLASS_WINDOW = "rctrl_renwnd32"
Private Const DEFAULT_SUBJECT = "To whom it may concern"
Private Const DEFAULT_BODY = "When in the course of human events..."
Private Const EM_SETSEL = &HB1
Private Const FINDMODE_BYCLASS = 0
Private Const FINDMODE_BYTEXT = 1
Private hwndRichEdit As Long
' Used internally
Private expectedText As String
Private currentFindMode As Long
''' <summary>
''' Demo entry method
''' </summary>
Public Sub CreateTestItem()
Dim app As AppointmentItem
Set app = Application.CreateItem(olAppointmentItem)
app.Subject = DEFAULT_SUBJECT
app.Body = DEFAULT_BODY
app.Display
DoEvents
'SetBodyCursorPos 5
SetTextBoxCursorPos DEFAULT_SUBJECT, 5
End Sub
''' <summary>
''' Sets the cursor position in a given text box by finding the text box
that has the specied
''' text and sets the focus to it.
''' </summary>
Public Sub SetTextBoxCursorPos(ByVal subjectText As String, ByVal pos As
Long)
SetPositionInternal subjectText, FINDMODE_BYTEXT, pos
End Sub
''' <summary>
''' Sets the cursor position in the body by finding the body (no text is
needed because only one
''' body control is on the form) and sets focus to it.
''' </summary>
Public Sub SetBodyCursorPos(ByVal pos As Long)
SetPositionInternal "", FINDMODE_BYCLASS, pos
End Sub
''' <summary>
''' Sets the cursor position of a text box or the body field. Called
internally by the two
''' public methods SetBodyCursorPos and SetTextBoxCursorPos.
'' </summary>
Private Sub SetPositionInternal(ByVal text As String, ByVal findMode As
Long, ByVal pos As Long)
' Get the foreground window which should be appointmentitem
Dim hwnd As Long
hwnd = GetForegroundWindow()
' Make sure it's the appointment window
Dim hwnd2 As Long
hwnd2 = FindWindowEx(0, 0, CLASS_WINDOW, vbNullString)
If hwnd = hwnd2 Then
' Store the text that they're searching for in a private variable
expectedText = text
' Likewise store the find mode. Would have passed this to
enumchildwindows
' but since i'm storing expectedText, I'll do this too. I hate VB
currentFindMode = findMode
' Find the rich edit box on the page
EnumChildWindows hwnd, AddressOf EnumWindowProc, 0
If hwndRichEdit <> 0 Then
SetFocusAPI hwndRichEdit
SendMessage hwndRichEdit, EM_SETSEL, pos, pos
End If
End If
End Sub
''' <summary>
''' Callback function invoked by Windows for every child window enumerated.
''' </summary>
Private Function EnumWindowProc(ByVal hwnd As Long, ByVal lParam As Long) As
Boolean
Dim returnValue As Boolean
returnValue = True
Dim className As String
Dim length As Long
className = Space(100)
length = GetClassName(hwnd, className, Len(className) - 1)
If length > 0 Then
' FINDMODE_BYTEXT means they are looking for a single-line textbox
that
' has the specified text. Because there are multiple single-line
text box class
' instances on the form, we need the expected text to match it to
get the right hwnd
If currentFindMode = FINDMODE_BYTEXT Then
If Left(className, length) = CLASS_SUBJECT And
GetWindowText(hwnd) = DEFAULT_SUBJECT Then
hwndRichEdit = hwnd
returnValue = False
End If
' FINDMODE_BYCLASS means they are looking for the body control.
Since there's
' only one instance of that class on the form we don't care about
the text
ElseIf currentFindMode = FINDMODE_BYCLASS Then
If Left(className, length) = CLASS_BODY Then
hwndRichEdit = hwnd
returnValue = False
End If
End If
End If
EnumWindowProc = returnValue
End Function
''' <summary>
''' Helper function to get the window text of the HWND in one call.
''' </summary>
Private Function GetWindowText(ByVal hwnd As Long) As String
Dim buff As String
buff = Space(GetWindowTextLength(hwnd) + 1)
GetWindowTextAPI hwnd, buff, Len(buff)
GetWindowText = Left(buff, Len(buff) - 1)
End Function
--
Josh Einstein
Einstein Technologies
Microsoft Tablet PC MVP
Tablet Enhancements for Outlook 2.0 - Try it free for 14 days
www.tabletoutlook.com