A
Alex Cheng
I think it's working in Word. Let me try again and let you know.
Thanks,
Alex
Thanks,
Alex
Karl E. Peterson said:Alex said:FYI:
It won't work. It will ignore the dialog box and move on. I
guess
it is because it's not the same thread.
If you moved it into Word, yes, of course it's the same thread! That's
the whole point of doing it there. But you also need to set the
parameters for SetWindowsHookEx back to how they were when we started. I
need to you to *think* along with me here, okay? <g>
This (kinda) works:
Option Explicit
Private Declare Function SetWindowsHookEx Lib "user32" Alias
"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod
As Long, ByVal dwThreadId As Long) As Long
Private Declare Function GetCurrentThreadId Lib "kernel32" () As Long
Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook
As Long) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA"
(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal
lParam As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As
Any) As Long
Private Declare Function GetClassname Lib "user32" Alias "GetClassNameA"
(ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long)
As Long
Private Declare Function GetWindowText Lib "user32" Alias
"GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch
As Long) As Long
Private Const WH_CBT = 5
Private Const WM_CLOSE = &H10
Private Const HCBT_ACTIVATE = 5
Private m_hHook As Long
Public Sub AvoidCorruptDoc()
' Set the CBT hook. (Parameters set to be used in-process, within
VBA!)
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())
' Take step(s) here to Open document
CreateDocument
' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub
Private Function CloseCorrupt(ByVal nCode As Long, ByVal wParam As Long,
ByVal lParam As Long) As Long
' We only want to react to activations.
If nCode = HCBT_ACTIVATE Then
' Handle to be activated window is in wParam.
' IMPORTANT: Need to test for specific dialog!
Debug.Print Hex$(wParam), """"; Classname(wParam); """", """";
WindowText(wParam); """"
If IsFileSaveDialog(wParam) Then
' Press the [X] button!
Call SendMessage(wParam, WM_CLOSE, 0&, ByVal 0&)
' Hook no longer needed.
Call UnhookWindowsHookEx(m_hHook)
m_hHook = 0
End If
End If
End Function
Private Function IsFileSaveDialog(ByVal hWnd As Long) As Boolean
If Classname(hWnd) = "#32770" Then
If WindowText(hWnd) = "Microsoft Office Word" Then
' Pretty good odds this is the File-Save dialog.
' Could also test button text?
IsFileSaveDialog = True
End If
End If
End Function
Private Function Classname(ByVal hWnd As Long) As String
Dim nRet As Long
Dim Class As String
Const MaxLen As Long = 256
' Retrieve classname of passed window.
Class = String$(MaxLen, 0)
nRet = GetClassname(hWnd, Class, MaxLen)
If nRet Then Classname = Left$(Class, nRet)
End Function
Private Function WindowText(ByVal hWnd As Long) As String
Dim nRet As Long
Dim Buffer As String
Const MaxLen As Long = 256
' Retrieve caption of passed window.
Buffer = String$(MaxLen, 0)
nRet = GetWindowText(hWnd, Buffer, MaxLen)
If nRet > 0 Then
WindowText = Left$(Buffer, nRet)
End If
End Function
Public Sub CreateDocument()
Documents.Open "c:\temp\test.doc"
Selection.Text = "test"
Documents.Close
End Sub
I say "kinda" because (again!) I don't have a corrupt document to test
against, and my knowledge of the Word object model is severely
constrained. The Documents.Close call is failing when I send it the
WM_CLOSE message. Yes, *that* part is working just fine!
I think if you figure out the proper parameters for the dialog test,
you'll be in business. But as I said, I can't do all the thinking for ya
here. You gotta become a real participant in the process!