how to bypass dialog box

A

Alex Cheng

Hi there,

I've tried to open a corrupted Word File using the following
script. But a dialog box shows up and asked "The document 'myfile' caused a
serious error the last time it was opened. Would you like to continue
opening it?" Is there a way to bypas this dialog with selection of "No"
everytime? Here is the script:

Application.DisplayAlerts = wdAlertsAll
Documents.Open {myfile}, OpenAndRepair:=True,
NoEncodingDialog:=True, ConfirmConversions:=False


Thanks,

Alex
 
D

Doug Robbins - Word MVP on news.microsoft.com

Replace wdAlertsAll with wdAlertsNone


--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP, originally posted via msnews.microsoft.com
 
A

Alex Cheng

Sorry my mistake, I actually tried wdAlertsNone already but no
luck. Any other thought.

Thanks,

Alex
 
K

Karl E. Peterson

Alex said:
Hi there,

I've tried to open a corrupted Word File using the following
script. But a dialog box shows up and asked "The document 'myfile' caused a
serious error the last time it was opened. Would you like to continue
opening it?" Is there a way to bypas this dialog with selection of "No"
everytime? Here is the script:

Application.DisplayAlerts = wdAlertsAll
Documents.Open {myfile}, OpenAndRepair:=True,
NoEncodingDialog:=True, ConfirmConversions:=False

You could *potentially* set a CBT hook, watching for the dialog to pop, and then
sending the appropriate messages to dismiss it. I show how to do this with a MsgBox
with this sample -- http://vb.mvps.org/samples/MovedMsg -- which of course would
need to be seriously modified so that it A) recognized the proper window creation
event and B) sent the appropriate response to this event.

Looking at the dialog you posted, it's *possible* that sending it a WM_CLOSE message
would be the ticket, once you've identified the window. It appears the default
answer, which would be used in this case (same as pushing the [X] button), is "No"?
 
A

Alex Cheng

I've checked your sample but how do I add timeout for a Msgbox
that is not fired by my code? Maybe I don't understand your sample.

Thanks,

Alex


Karl E. Peterson said:
Alex said:
Hi there,

I've tried to open a corrupted Word File using the following
script. But a dialog box shows up and asked "The document 'myfile' caused
a
serious error the last time it was opened. Would you like to continue
opening it?" Is there a way to bypas this dialog with selection of "No"
everytime? Here is the script:

Application.DisplayAlerts = wdAlertsAll
Documents.Open {myfile}, OpenAndRepair:=True,
NoEncodingDialog:=True, ConfirmConversions:=False

You could *potentially* set a CBT hook, watching for the dialog to pop,
and then sending the appropriate messages to dismiss it. I show how to do
this with a MsgBox with this sample --
http://vb.mvps.org/samples/MovedMsg -- which of course would need to be
seriously modified so that it A) recognized the proper window creation
event and B) sent the appropriate response to this event.

Looking at the dialog you posted, it's *possible* that sending it a
WM_CLOSE message would be the ticket, once you've identified the window.
It appears the default answer, which would be used in this case (same as
pushing the [X] button), is "No"?
 
K

Karl E. Peterson

Alex said:
I've checked your sample but how do I add timeout for a Msgbox
that is not fired by my code? Maybe I don't understand your sample.

The sample is intended merely to show you one way to use SetWindowsHookEx. It's
impossible for me to test, of course, without a corrupt document to test against (or
some other way to dredge up that dialog). The idea is to set the CBT hook to watch
for creation/activation of any window in your process. Presumably, this dialog is
in the same process, correct? Here's some conceptual background:

http://msdn.microsoft.com/en-us/library/ms997537.aspx

Anyway, when you get the callback, you'd be looking for HCBT_ACTIVATE which passes
the hWnd in wParam. When you see that, call SendMessage(WM_CLOSE) on that hWnd. I
think it'll work. Assuming by "work" we mean it'll have the same effect as if you
pressed the [X] button on the dialog.
--
..NET: It's About Trust!
http://vfred.mvps.org


Karl E. Peterson said:
Alex said:
Hi there,

I've tried to open a corrupted Word File using the following
script. But a dialog box shows up and asked "The document 'myfile' caused
a
serious error the last time it was opened. Would you like to continue
opening it?" Is there a way to bypas this dialog with selection of "No"
everytime? Here is the script:

Application.DisplayAlerts = wdAlertsAll
Documents.Open {myfile}, OpenAndRepair:=True,
NoEncodingDialog:=True, ConfirmConversions:=False

You could *potentially* set a CBT hook, watching for the dialog to pop,
and then sending the appropriate messages to dismiss it. I show how to do
this with a MsgBox with this sample --
http://vb.mvps.org/samples/MovedMsg -- which of course would need to be
seriously modified so that it A) recognized the proper window creation
event and B) sent the appropriate response to this event.

Looking at the dialog you posted, it's *possible* that sending it a
WM_CLOSE message would be the ticket, once you've identified the window.
It appears the default answer, which would be used in this case (same as
pushing the [X] button), is "No"?
 
K

Karl E. Peterson

Alex said:
I've checked your sample but how do I add timeout for a Msgbox
that is not fired by my code? Maybe I don't understand your sample.

This is the general idea:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Documents.Open ...

' 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!
If IsErrorDialog(wParam) Then
' Press the [X] button!
Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' Hook no longer needed.
Call UnhookWindowsHookEx(m_hHook)
m_hHook = 0
End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
End Function

You'll still need to write a highly robust IsErrorDialog procedure! I'd suggest, at
the least, checking the window caption and classname there.
 
A

Alex Cheng

Will try and let you know.

Thanks,

Alex

Karl E. Peterson said:
Alex said:
I've checked your sample but how do I add timeout for a
Msgbox
that is not fired by my code? Maybe I don't understand your sample.

The sample is intended merely to show you one way to use SetWindowsHookEx.
It's impossible for me to test, of course, without a corrupt document to
test against (or some other way to dredge up that dialog). The idea is to
set the CBT hook to watch for creation/activation of any window in your
process. Presumably, this dialog is in the same process, correct? Here's
some conceptual background:

http://msdn.microsoft.com/en-us/library/ms997537.aspx

Anyway, when you get the callback, you'd be looking for HCBT_ACTIVATE
which passes the hWnd in wParam. When you see that, call
SendMessage(WM_CLOSE) on that hWnd. I think it'll work. Assuming by
"work" we mean it'll have the same effect as if you pressed the [X] button
on the dialog.
--
.NET: It's About Trust!
http://vfred.mvps.org


Karl E. Peterson said:
Alex Cheng wrote:
Hi there,

I've tried to open a corrupted Word File using the following
script. But a dialog box shows up and asked "The document 'myfile'
caused
a
serious error the last time it was opened. Would you like to continue
opening it?" Is there a way to bypas this dialog with selection of "No"
everytime? Here is the script:

Application.DisplayAlerts = wdAlertsAll
Documents.Open {myfile}, OpenAndRepair:=True,
NoEncodingDialog:=True, ConfirmConversions:=False

You could *potentially* set a CBT hook, watching for the dialog to pop,
and then sending the appropriate messages to dismiss it. I show how to
do
this with a MsgBox with this sample --
http://vb.mvps.org/samples/MovedMsg -- which of course would need to be
seriously modified so that it A) recognized the proper window creation
event and B) sent the appropriate response to this event.

Looking at the dialog you posted, it's *possible* that sending it a
WM_CLOSE message would be the ticket, once you've identified the window.
It appears the default answer, which would be used in this case (same as
pushing the [X] button), is "No"?
 
A

Alex Cheng

Thanks Karl. I will try and let you know.

alex

Karl E. Peterson said:
Alex said:
I've checked your sample but how do I add timeout for a
Msgbox
that is not fired by my code? Maybe I don't understand your sample.

This is the general idea:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Documents.Open ...

' 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!
If IsErrorDialog(wParam) Then
' Press the [X] button!
Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' Hook no longer needed.
Call UnhookWindowsHookEx(m_hHook)
m_hHook = 0
End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
End Function

You'll still need to write a highly robust IsErrorDialog procedure! I'd
suggest, at the least, checking the window caption and classname there.
 
A

Alex Cheng

I've tried your code. It works in sample 1 where it will bypass
the Msgbox "Testing". But it won't work in sample 2 when it tries to open a
bad document. The dialog box is still showing. Do I miss something?

Sample 1:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
MsgBox "Testing"
' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Sample 2:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Dim o As Word.Application
Set o = New Word.Application
o.DisplayAlerts = wdAlertsNone
o.Documents.Open "c:\temp\b.doc", OpenAndRepair:=True,
NoEncodingDialog:=True
o.Quit
Set o = Nothing

' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Thanks,

Alex


Karl E. Peterson said:
Alex said:
I've checked your sample but how do I add timeout for a
Msgbox
that is not fired by my code? Maybe I don't understand your sample.

This is the general idea:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Documents.Open ...

' 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!
If IsErrorDialog(wParam) Then
' Press the [X] button!
Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' Hook no longer needed.
Call UnhookWindowsHookEx(m_hHook)
m_hHook = 0
End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
End Function

You'll still need to write a highly robust IsErrorDialog procedure! I'd
suggest, at the least, checking the window caption and classname there.
 
K

Karl E. Peterson

Alex said:
I've tried your code. It works in sample 1 where it will bypass
the Msgbox "Testing". But it won't work in sample 2 when it tries to open a
bad document. The dialog box is still showing. Do I miss something?

Hmmmm, I guess because we were in the VBA group, I had assumed you were writing VBA
code. That's kinda critical here, as that would mean your code is running
*in-process* with Word, and hence the dialog you're seeking to be alerted to. Where
does this code exist? This just got near-infinitely more complex. At the least,
you'll need to monitor windows in the other process, not your own.
--
..NET: It's About Trust!
http://vfred.mvps.org


Sample 1:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
MsgBox "Testing"
' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Sample 2:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Dim o As Word.Application
Set o = New Word.Application
o.DisplayAlerts = wdAlertsNone
o.Documents.Open "c:\temp\b.doc", OpenAndRepair:=True,
NoEncodingDialog:=True
o.Quit
Set o = Nothing

' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Thanks,

Alex


Karl E. Peterson said:
Alex said:
I've checked your sample but how do I add timeout for a
Msgbox
that is not fired by my code? Maybe I don't understand your sample.

This is the general idea:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Documents.Open ...

' 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!
If IsErrorDialog(wParam) Then
' Press the [X] button!
Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' Hook no longer needed.
Call UnhookWindowsHookEx(m_hHook)
m_hHook = 0
End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
End Function

You'll still need to write a highly robust IsErrorDialog procedure! I'd
suggest, at the least, checking the window caption and classname there.
 
A

Alex Cheng

I put it in VB 6. Should I handle it different way?

Thanks,

Alex

Karl E. Peterson said:
Alex said:
I've tried your code. It works in sample 1 where it will
bypass
the Msgbox "Testing". But it won't work in sample 2 when it tries to open
a
bad document. The dialog box is still showing. Do I miss something?

Hmmmm, I guess because we were in the VBA group, I had assumed you were
writing VBA code. That's kinda critical here, as that would mean your
code is running *in-process* with Word, and hence the dialog you're
seeking to be alerted to. Where does this code exist? This just got
near-infinitely more complex. At the least, you'll need to monitor
windows in the other process, not your own.
--
.NET: It's About Trust!
http://vfred.mvps.org


Sample 1:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
MsgBox "Testing"
' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Sample 2:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Dim o As Word.Application
Set o = New Word.Application
o.DisplayAlerts = wdAlertsNone
o.Documents.Open "c:\temp\b.doc", OpenAndRepair:=True,
NoEncodingDialog:=True
o.Quit
Set o = Nothing

' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Thanks,

Alex


Karl E. Peterson said:
Alex Cheng wrote:
I've checked your sample but how do I add timeout for a
Msgbox
that is not fired by my code? Maybe I don't understand your sample.

This is the general idea:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Documents.Open ...

' 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!
If IsErrorDialog(wParam) Then
' Press the [X] button!
Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' Hook no longer needed.
Call UnhookWindowsHookEx(m_hHook)
m_hHook = 0
End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
End Function

You'll still need to write a highly robust IsErrorDialog procedure! I'd
suggest, at the least, checking the window caption and classname there.
 
K

Karl E. Peterson

I laid out your options. Out of process is gonna be a *heckuva* lot more involved.
I have no way to test anything specific to your problem, as I said, because I don't
know how to force that dialog. If I had a corrupt document, I might be able to try
a few things, and see where that went.
--
..NET: It's About Trust!
http://vfred.mvps.org


Alex said:
I put it in VB 6. Should I handle it different way?

Thanks,

Alex

Karl E. Peterson said:
Alex said:
I've tried your code. It works in sample 1 where it will
bypass
the Msgbox "Testing". But it won't work in sample 2 when it tries to open
a
bad document. The dialog box is still showing. Do I miss something?

Hmmmm, I guess because we were in the VBA group, I had assumed you were
writing VBA code. That's kinda critical here, as that would mean your
code is running *in-process* with Word, and hence the dialog you're
seeking to be alerted to. Where does this code exist? This just got
near-infinitely more complex. At the least, you'll need to monitor
windows in the other process, not your own.
--
.NET: It's About Trust!
http://vfred.mvps.org


Sample 1:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
MsgBox "Testing"
' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Sample 2:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Dim o As Word.Application
Set o = New Word.Application
o.DisplayAlerts = wdAlertsNone
o.Documents.Open "c:\temp\b.doc", OpenAndRepair:=True,
NoEncodingDialog:=True
o.Quit
Set o = Nothing

' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Thanks,

Alex


Alex Cheng wrote:
I've checked your sample but how do I add timeout for a
Msgbox
that is not fired by my code? Maybe I don't understand your sample.

This is the general idea:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Documents.Open ...

' 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!
If IsErrorDialog(wParam) Then
' Press the [X] button!
Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' Hook no longer needed.
Call UnhookWindowsHookEx(m_hHook)
m_hHook = 0
End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
End Function

You'll still need to write a highly robust IsErrorDialog procedure! I'd
suggest, at the least, checking the window caption and classname there.
 
A

Alex Cheng

Can you try the following?

1. open a document (that is read-only file)
2. edit the document
3. do a save

It should prompt you dialog box? And see if you can bypass that.
Does it make sense?

Thanks,

Alex

Karl E. Peterson said:
I laid out your options. Out of process is gonna be a *heckuva* lot more
involved. I have no way to test anything specific to your problem, as I
said, because I don't know how to force that dialog. If I had a corrupt
document, I might be able to try a few things, and see where that went.
--
.NET: It's About Trust!
http://vfred.mvps.org


Alex said:
I put it in VB 6. Should I handle it different way?

Thanks,

Alex

Karl E. Peterson said:
Alex Cheng wrote:
I've tried your code. It works in sample 1 where it will
bypass
the Msgbox "Testing". But it won't work in sample 2 when it tries to
open
a
bad document. The dialog box is still showing. Do I miss something?

Hmmmm, I guess because we were in the VBA group, I had assumed you were
writing VBA code. That's kinda critical here, as that would mean your
code is running *in-process* with Word, and hence the dialog you're
seeking to be alerted to. Where does this code exist? This just got
near-infinitely more complex. At the least, you'll need to monitor
windows in the other process, not your own.
--
.NET: It's About Trust!
http://vfred.mvps.org



Sample 1:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
MsgBox "Testing"
' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Sample 2:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Dim o As Word.Application
Set o = New Word.Application
o.DisplayAlerts = wdAlertsNone
o.Documents.Open "c:\temp\b.doc", OpenAndRepair:=True,
NoEncodingDialog:=True
o.Quit
Set o = Nothing

' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Thanks,

Alex


Alex Cheng wrote:
I've checked your sample but how do I add timeout for a
Msgbox
that is not fired by my code? Maybe I don't understand your sample.

This is the general idea:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Documents.Open ...

' 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!
If IsErrorDialog(wParam) Then
' Press the [X] button!
Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' Hook no longer needed.
Call UnhookWindowsHookEx(m_hHook)
m_hHook = 0
End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
End Function

You'll still need to write a highly robust IsErrorDialog procedure!
I'd
suggest, at the least, checking the window caption and classname
there.
 
K

Karl E. Peterson

Alex said:
Can you try the following?

1. open a document (that is read-only file)
2. edit the document
3. do a save

It should prompt you dialog box? And see if you can bypass that.
Does it make sense?

I don't automate Word, generally speaking, so you'd save me bunches of time if you
gave me the six lines of code it'd take to do the above.

Thanks...


Karl E. Peterson said:
I laid out your options. Out of process is gonna be a *heckuva* lot more
involved. I have no way to test anything specific to your problem, as I
said, because I don't know how to force that dialog. If I had a corrupt
document, I might be able to try a few things, and see where that went.
--
.NET: It's About Trust!
http://vfred.mvps.org


Alex said:
I put it in VB 6. Should I handle it different way?

Thanks,

Alex

Alex Cheng wrote:
I've tried your code. It works in sample 1 where it will
bypass
the Msgbox "Testing". But it won't work in sample 2 when it tries to
open
a
bad document. The dialog box is still showing. Do I miss something?

Hmmmm, I guess because we were in the VBA group, I had assumed you were
writing VBA code. That's kinda critical here, as that would mean your
code is running *in-process* with Word, and hence the dialog you're
seeking to be alerted to. Where does this code exist? This just got
near-infinitely more complex. At the least, you'll need to monitor
windows in the other process, not your own.
--
.NET: It's About Trust!
http://vfred.mvps.org



Sample 1:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
MsgBox "Testing"
' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Sample 2:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Dim o As Word.Application
Set o = New Word.Application
o.DisplayAlerts = wdAlertsNone
o.Documents.Open "c:\temp\b.doc", OpenAndRepair:=True,
NoEncodingDialog:=True
o.Quit
Set o = Nothing

' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Thanks,

Alex


Alex Cheng wrote:
I've checked your sample but how do I add timeout for a
Msgbox
that is not fired by my code? Maybe I don't understand your sample.

This is the general idea:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Documents.Open ...

' 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!
If IsErrorDialog(wParam) Then
' Press the [X] button!
Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' Hook no longer needed.
Call UnhookWindowsHookEx(m_hHook)
m_hHook = 0
End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
End Function

You'll still need to write a highly robust IsErrorDialog procedure!
I'd
suggest, at the least, checking the window caption and classname
there.
 
A

Alex Cheng

Here is the VBA code

'you can create a empty word document in whatever path you want
Documents.Open "c:\temp\test.doc"
Selection.Text = "test"
Application.Quit

Here is the VB code
Dim o As Word.Application
Set o = New Word.Application
o.Visible = True
o.Documents.Open "c:\temp\test.doc"
Selection.Text = "test"
o.Quit
Set o = Nothing

Thanks,

Alex


Karl E. Peterson said:
Alex said:
Can you try the following?

1. open a document (that is read-only file)
2. edit the document
3. do a save

It should prompt you dialog box? And see if you can bypass
that.
Does it make sense?

I don't automate Word, generally speaking, so you'd save me bunches of
time if you gave me the six lines of code it'd take to do the above.

Thanks...


Karl E. Peterson said:
I laid out your options. Out of process is gonna be a *heckuva* lot more
involved. I have no way to test anything specific to your problem, as I
said, because I don't know how to force that dialog. If I had a corrupt
document, I might be able to try a few things, and see where that went.
--
.NET: It's About Trust!
http://vfred.mvps.org


Alex Cheng wrote:
I put it in VB 6. Should I handle it different way?

Thanks,

Alex

Alex Cheng wrote:
I've tried your code. It works in sample 1 where it will
bypass
the Msgbox "Testing". But it won't work in sample 2 when it tries to
open
a
bad document. The dialog box is still showing. Do I miss something?

Hmmmm, I guess because we were in the VBA group, I had assumed you
were
writing VBA code. That's kinda critical here, as that would mean your
code is running *in-process* with Word, and hence the dialog you're
seeking to be alerted to. Where does this code exist? This just got
near-infinitely more complex. At the least, you'll need to monitor
windows in the other process, not your own.
--
.NET: It's About Trust!
http://vfred.mvps.org



Sample 1:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
MsgBox "Testing"
' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Sample 2:
Public Sub AvoidCorruptDoc()
' Set the CBT hook.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Dim o As Word.Application
Set o = New Word.Application
o.DisplayAlerts = wdAlertsNone
o.Documents.Open "c:\temp\b.doc", OpenAndRepair:=True,
NoEncodingDialog:=True
o.Quit
Set o = Nothing

' Hook no longer needed.
If m_hHook Then Call UnhookWindowsHookEx(m_hHook)
End Sub

Thanks,

Alex


Alex Cheng wrote:
I've checked your sample but how do I add timeout for a
Msgbox
that is not fired by my code? Maybe I don't understand your sample.

This is the general idea:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, 0&,
GetCurrentThreadId())

' Take step(s) here to Open document
Documents.Open ...

' 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!
If IsErrorDialog(wParam) Then
' Press the [X] button!
Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' Hook no longer needed.
Call UnhookWindowsHookEx(m_hHook)
m_hHook = 0
End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
End Function

You'll still need to write a highly robust IsErrorDialog procedure!
I'd
suggest, at the least, checking the window caption and classname
there.
 
K

Karl E. Peterson

Well, as I was afraid, this gets real ugly real fast. Here's something you can play
with. Be sure you don't have anything you value unsaved at the time:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt, App.hInstance, 0&)

' 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 IsErrorDialog(wParam) Then
' ' Press the [X] button!
' Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' ' Hook no longer needed.
' Call UnhookWindowsHookEx(m_hHook)
' m_hHook = 0
' End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
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

Private Sub CreateDocument()
Dim o As Word.Application
Set o = New Word.Application
o.Visible = True
o.Documents.Open "c:\temp\test.doc"
Selection.Text = "test"
o.Quit
Set o = Nothing
End Sub

That's the general idea. I'd *strongly* recommend you consider whether you can
automate this entire process from either directly within Word, or at least from a
DLL that you execute from Word. Keeping this in process is going tomake all the
difference in the world. Otherwise, spend some time googling "global vb cbt hook".
It's not purty.
 
A

Alex Cheng

Thanks Karl. I'm really appreicated your help. I will let you how's that
go.

alex

Karl E. Peterson said:
Well, as I was afraid, this gets real ugly real fast. Here's something
you can play with. Be sure you don't have anything you value unsaved at
the time:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt,
App.hInstance, 0&)

' 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 IsErrorDialog(wParam) Then
' ' Press the [X] button!
' Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' ' Hook no longer needed.
' Call UnhookWindowsHookEx(m_hHook)
' m_hHook = 0
' End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
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

Private Sub CreateDocument()
Dim o As Word.Application
Set o = New Word.Application
o.Visible = True
o.Documents.Open "c:\temp\test.doc"
Selection.Text = "test"
o.Quit
Set o = Nothing
End Sub

That's the general idea. I'd *strongly* recommend you consider whether
you can automate this entire process from either directly within Word, or
at least from a DLL that you execute from Word. Keeping this in process
is going tomake all the difference in the world. Otherwise, spend some
time googling "global vb cbt hook". It's not purty.
 
A

Alex Cheng

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. Anyway thanks for you help.

Thanks,

Alex

Karl E. Peterson said:
Well, as I was afraid, this gets real ugly real fast. Here's something
you can play with. Be sure you don't have anything you value unsaved at
the time:

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 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.
m_hHook = SetWindowsHookEx(WH_CBT, AddressOf CloseCorrupt,
App.hInstance, 0&)

' 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 IsErrorDialog(wParam) Then
' ' Press the [X] button!
' Call PostMessage(wParam, WM_CLOSE, 0&, 0&)
' ' Hook no longer needed.
' Call UnhookWindowsHookEx(m_hHook)
' m_hHook = 0
' End If
End If
End Function

Private Function IsErrorDialog() As Boolean
' TBD
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

Private Sub CreateDocument()
Dim o As Word.Application
Set o = New Word.Application
o.Visible = True
o.Documents.Open "c:\temp\test.doc"
Selection.Text = "test"
o.Quit
Set o = Nothing
End Sub

That's the general idea. I'd *strongly* recommend you consider whether
you can automate this entire process from either directly within Word, or
at least from a DLL that you execute from Word. Keeping this in process
is going tomake all the difference in the world. Otherwise, spend some
time googling "global vb cbt hook". It's not purty.
 
K

Karl E. Peterson

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!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top