Персональные инструменты
 

Frontpage:Как установить макросом положение курсора

Материал из CustisWiki

Перейти к: навигация, поиск

Задача и решение

При написании различных расширений, вспомогательных макросов для Frontpage, часто возникает задача установить (из макроса), положение (строку и столбец) курсора в окне редактирования. Например, если вызывать различные внешние валидаторы, то при ошибке, нужно точно позиционировать пользователя на ее предполагаемое место. К сожалению, открытое API не позволяет этого сделать. Однако есть несколько обходной, хакерский путь.

Суть его состоит в том, чтобы «найти» правильный идентификатор самого глубокого вложенного окна редактирования Frontpage (эвристическая процедура GetFrontpage2002Hwnd, как следует из ее названия работает с «Frontpage 2002» и для других версий, возможно потребует адаптации), и, посылая ему клавиатурные сообщения, отпозиционироваться сначала в начало первой строки, а затем, «клавишами» вниз и вправо, переползти на нужную колонку нужной строки.

Код

Option Explicit
'****************************************************************
'some Windows API -based hacks and heuristics for Frontpage 2002
'----------------------------------------------------------------
'(c) 2003 Stas Fomin
'****************************************************************
 
'Not all declared API functions are used here...
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Private Declare Function PostThreadMessage Lib "user32.dll" Alias "PostThreadMessageA" (ByVal idThread As Long, ByVal msg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal msg As Long, ByVal wp As Long, ByVal lp As Long) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal msg As Long, ByVal wp As Long, ByVal lp As Long) As Long
 
Private Declare Function PostThreadMessageA Lib "user32.dll" (ByVal idThread As Long, ByVal msg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function PostThreadMessageW Lib "user32.dll" (ByVal idThread As Long, ByVal msg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Private Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long
 
 
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
 
'to get hwnd handle from callback functions
Public g_hwnd As Long
 
 
'Keys and messages
Const WM_SETFOCUS As Long = &H7
Const WM_KEYDOWN As Long = &H100
Const WM_KEYUP As Long = &H101
Const VK_CONTROL As Long = &H11
Const VK_HOME As Long = &H24
Const VK_RIGHT As Long = &H27
Const VK_DOWN As Long = &H28
Const WS_VISIBLE = &H10000000
Const GWL_STYLE = (-16)
 
 
'Heuristic for determine Frontpage 2002 Hwnd handle
'It did not tested for others versions of FP,
' but I think can be easy adapted for them.
Public Function GetFrontpage2002Hwnd() As Long
Dim hwnd As Long
Dim ls_caption As String
GetFrontpage2002Hwnd = 0
 
ls_caption = Application.ActiveWebWindow.Caption
hwnd = FindWindow("FrontPageExplorerWindow40", ls_caption)
If hwnd = 0 Then Exit Function
 
hwnd = FindWindowEx(hwnd, 0, "AfxMDIFrame42", "")
If hwnd = 0 Then Exit Function
 
hwnd = FindWindowEx(hwnd, 0, "AfxWnd42", "")
If hwnd = 0 Then Exit Function
 
hwnd = FindWindowEx(hwnd, 0, "AfxMDIFrame42", "")
If hwnd = 0 Then Exit Function
 
hwnd = FindWindowEx(hwnd, 0, "AfxFrameOrView42", "")
If hwnd = 0 Then Exit Function
 
hwnd = FindWindowEx(hwnd, 0, "AfxFrameOrView42", "")
If hwnd = 0 Then Exit Function
 
 
'hATLWnd = FindWindowEx(hWnd, 0, "ATL:33957BC0", "")
Call EnumChildWindows(hwnd, AddressOf FindVisibleWindow, &H0)
hwnd = g_hwnd
If hwnd = 0 Then Exit Function
 
hwnd = FindWindowEx(hwnd, 0, "FrontPageEditorDocumentFrame", "")
If hwnd = 0 Then Exit Function
 
Dim hWndChild As Long
 
hWndChild = FindWindowEx(hwnd, 0, "AfxFrameOrView42", "")
If hWndChild = 0 Then Exit Function
 
While (hWndChild <> 0) And ((GetWindowLong(hWndChild, GWL_STYLE) And WS_VISIBLE) <> WS_VISIBLE)
    hWndChild = FindWindowEx(hwnd, hWndChild, "AfxFrameOrView42", "")
Wend
hwnd = hWndChild
If hwnd = 0 Then Exit Function
 
hwnd = FindWindowEx(hwnd, 0, "RichEdit20W", "")
If hwnd = 0 Then Exit Function
 
GetFrontpage2002Hwnd = hwnd
End Function
 
 
'Heuristic for setting line and column in HTML-view
' of FP. (HTML-view must be active).
Public Sub SetFrontpageLineAndCol(li_line As Long, li_col As Long)
   If li_line < 0 Then Exit Sub
   If li_col < 0 Then li_col = 0
 
   Dim hwnd As Long
   hwnd = GetFrontpage2002Hwnd()
   If hwnd = 0 Then Exit Sub
 
   Dim l_lparam As Long
   Dim l_wparam As Long
   Dim l_res As Long
 
   l_lparam = &H24
   l_wparam = &H1470001
   l_res = PostMessage(hwnd, WM_KEYDOWN, l_lparam, l_wparam)
 
'Sending a burst of  PageUp's for parking in line 1, col 1
'I failed to use Ctrl-Home for this purpose
   l_lparam = &H21
   l_wparam = &H1490001
 
   Dim i As Long
   For i = 1 To 10
       l_res = PostMessage(hwnd, WM_KEYDOWN, l_lparam, l_wparam)
   Next
 
'Sending some DOWN_ARROW for positioning the line
   If li_line > 1 Then
       l_lparam = &H28
       l_wparam = &H1500001
       For i = 1 To li_line - 1
           l_res = PostMessage(hwnd, WM_KEYDOWN, l_lparam, l_wparam)
       Next
   End If
 
'Sending some RIGHT_ARROW for positioning the column
   If li_col > 1 Then
        l_lparam = &H27
        l_wparam = &H14D0001
        For i = 1 To li_col - 1
           l_res = PostMessage(hwnd, WM_KEYDOWN, l_lparam, l_wparam)
        Next
   End If
End Sub
 
 
'Callback function, for selecting first child visible window
Private Function FindVisibleWindow(ByVal hwnd As Long, ByVal lParam As Long) As Long
   FindVisibleWindow = 1
   g_hwnd = 0
   If IsWindowVisible(hwnd) Then
        g_hwnd = hwnd
        FindVisibleWindow = 0
   End If
End Function
 

Внимание! Эта статья была создана путем автоматического реплицирования из внутренней базы знаний компании Заказные Информ Системы. Любые правки этой статьи могут быть перезаписаны при следующем сеансе репликации. Если у вас есть серьезное замечание по тексту статьи, запишите его в раздел «discussion».