Form behaviour when called from toolbar button

E

Ed

Hello all,

Using Word 2003. I have a VBA userform which I would like to be
semi-transparent. The form contains the following sub (as well as
declarations and other stuff):

Private Sub UserForm_Initialize()
Dim hwnd As Long
Dim ret As Long
Const Transparency As Integer = 128

hwnd = FindWindow(vbNullString, Me.Caption)
ret = GetWindowLong(hwnd, GWL_EXSTYLE)
ret = ret Or WS_EX_LAYERED
SetWindowLong hwnd, GWL_EXSTYLE, ret
ret = SetLayeredWindowAttributes(hwnd, 0, Transparency, LWA_ALPHA)
End Sub

The relevant constants are declared in the form module as:

Private Const LWA_ALPHA = &H2
Private Const GWL_EXSTYLE = (-20)
Private Const WS_EX_LAYERED = &H80000

The form is instantiated by the following macro:

Sub EditFind()
Dim MyForm As frmFind

Set MyForm = New frmFind
MyForm.Show
Unload MyForm
Set MyForm = Nothing
End Sub

(Originally I tried just using frmFind.Show rather than using the MyForm
variable.)

When I run the macro in the VBA IDE it works, but when I add a toolbar
button in Word to call the macro, the form remains opaque. No errors are
reported.

Any ideas?

Thanks.

Ed
 
T

Tony Strazzeri

Hi Ed,

I tried to have a quick look at this but could not get your code to
run without errors. I am not really clear as to what you atre trying
to do. If no-one else can help it may be useful to post more of your
code.

Specifically,
What is frmFind? where is it defined. I get userdefined type not
defined.

Once I comment out the relevant bits and just do
Sub EditFind()
' Dim MyForm As Object ' frmFind

' Set MyForm = New frmFind
MyForm.Show
Unload MyForm
' Set MyForm = Nothing
End Sub

Then I can get to run the code in the Initialize event.
But then I get a problem with
hwnd = FindWindow(vbNullString, Me.Caption)

I get "Sub or function not defined" for FindWindow

I think this must have been declared elsewhere. I know it is a
Windows API.
Can you post the declaration?
The same goes for;
GetWindowLong, SetWindowLong, and SetLayeredWindowAttributes

Hope this helps.

Cheers
TonyS.
 
E

Ed

Hi Tony,

Thanks for your reply.

What I'm trying to do is intercept Word's EditFind command and display my
own VBA userform rather than Word's Find dialog. I want my form to be
semi-transparent so that it can remain onscreen but be unobtrusive.

The userform's name is "frmFind". In the EditFind macro that loads the form
I originally used the "normal" way of invoking the form - that is,
"frmFind.Show". However, when I experienced the problem that this posting
relates to I changed the way I invoke the form to see if that would cure it.
The method that I used was to declare an object variable, "MyForm" and use
that to create an instance of the "frmFind" class (Dim MyForm as frmFind ...
Set MyForm = New frmFind). As it happens, this change didn't make any
difference.

The problem that I'm getting is as follows:

If I invoke my form in the VBA IDE, the form displays as semi-transparent
(which is what I want). If I invoke the form outside the IDE by Ctrl+F, or by
Edit/Find, or by going into Tools/Macro/Macros and running the EditFind
macro, the form displays as semi-transparent (good). But if I invoke the form
by clicking a toolbar button (either Word's binoculars icon or a button on a
custom toolbar) the form displays as opaque, not semi-transparent.

The form has a textbox (txtFindText) and three command buttons (cmdFind,
cmdBuiltIn and cmdQuit).

The whole code for the form (which may have changed a little since yesterday
as it's work in progress) is here:

---------------------------------------------------------------------------------------
Option Explicit

Private Const LWA_COLORKEY = &H1
Private Const LWA_ALPHA = &H2
Private Const GWL_EXSTYLE = (-20)
Private Const WS_EX_LAYERED = &H80000

Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As
Long) As Long
Private Declare Function SetLayeredWindowAttributes Lib "user32" _
(ByVal hwnd As Long, ByVal crKey As Long, _
ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String)
As Long
Private Declare Function SetWindowPos Lib "user32" _
(ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
ByVal X As Long, ByVal Y As Long, ByVal cx As Long, _
ByVal cy As Long, ByVal wFlags As Long) As Long

Private Sub cmdBuiltIn_Click()
Dialogs(wdDialogEditFind).Show
End Sub

Private Sub cmdFind_Click()
Selection.Find.ClearFormatting

With Selection.Find
.Text = txtFindText.Text
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With

Selection.Find.Execute

txtFindText.SetFocus
End Sub

Private Sub cmdQuit_Click()
Unload Me
End Sub

Private Sub UserForm_Initialize()
Dim hwnd As Long
Dim ret As Long
Const Transparency As Integer = 128

hwnd = FindWindow(vbNullString, Me.Caption)
ret = GetWindowLong(hwnd, GWL_EXSTYLE)
ret = ret Or WS_EX_LAYERED
SetWindowLong hwnd, GWL_EXSTYLE, ret
ret = SetLayeredWindowAttributes(hwnd, 0, Transparency, LWA_ALPHA)
End Su
---------------------------------------------------------------------------------------

The code of the EditFind macro (which has also changed a little) is:

---------------------------------------------------------------------------------------
Sub EditFind()
Dim MyForm As frmFind
Const FormTop As Integer = 20
Const FormLeft As Integer = 600

Set MyForm = New frmFind
MyForm.Top = FormTop
MyForm.Left = FormLeft
MyForm.Show vbModeless
MyForm.txtFindText.SetFocus
Set MyForm = Nothing
End Sub
---------------------------------------------------------------------------------------

It's not massively important but it would be nice to know what's happening.

Regards.

Ed
 
T

Tony Strazzeri

Hi Ed,

Try the code below. I have made the following changes:
1. You don't need to create a new form object when dispolaying
userforms. I have simplified the display of the form as shown.
Sub EditFind()
frmFind.Show vbModeless
End Sub
2. The initial positioning of the form can't be done withing the
Initialize event unluss you want the predefined positions accessible
through the PictureAlignment property of the form. I have moved that
code to the Activate event which gets processed after the Initialize.




This is the code for the Form module (I haven't changed the Declares
so have not pasted those.

I have tried this from the keyboard shortcut, the Edit|Find Menu, and
the IDE.

I also created a toolbar and added a button to launch the macro and
that worked for me as well.

Let me know how this goes for you.

Cheers
TonyS.
------------------------------------


Private Sub cmdBuiltIn_Click()
Dialogs(wdDialogEditFind).Show
End Sub

Private Sub cmdFind_Click()
Selection.Find.ClearFormatting

With Selection.Find
.Text = txtFindText.Text
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With

Selection.Find.Execute

txtFindText.SetFocus
End Sub

Private Sub cmdQuit_Click()
Unload Me
End Sub

Private Sub UserForm_Activate()
Const FormTop As Integer = 20
Const FormLeft As Integer = 600

With Me
.Top = FormTop
.Left = FormLeft
End With
End Sub

Private Sub UserForm_Initialize()
txtFindText.SetFocus

Dim hwnd As Long
Dim ret As Long
Const Transparency As Integer = 128

hwnd = FindWindow(vbNullString, Me.Caption)
ret = GetWindowLong(hwnd, GWL_EXSTYLE)
ret = ret Or WS_EX_LAYERED
SetWindowLong hwnd, GWL_EXSTYLE, ret
ret = SetLayeredWindowAttributes(hwnd, 0, Transparency, LWA_ALPHA)
End Sub
 
E

Ed

Hi Tony,

Thanks for your time.

I think the issue may be Word version-related. I generally use Word 2003 at
the moment and that's what I was testing my form with.

Both the original code and your amended code turn the form transparent (even
when invoked by a toolbar button) in Word 97 but not in Word 2003 (at least
not in my copy of Word).

In Word 2003, what happens with the amended code is that if I run it by any
means other than a toolbar button the form is transparent, but as soon as I
run it by a button the form is opaque. And once it's been invoked by a
button, it opens as opaque if I invoke it by Ctrl+F or by Tools/Macro/Macros.
To get it to open as transparent again I have to run it from the IDE.

Strange :)

Luckily, in reality I pretty much always invoke it by Ctrl+F so there's no
problem really, I was just curious.

Thanks again.

Regards.

Ed
 
T

Tony Strazzeri

Hi Ed,

FYI, I am using Windows XP Pro 2002 with SP2.
Word 2003 (11.8134.8132) SP2.

Cheers
TonyS.
 
E

Ed

Hi Tony,

Thanks for the information.

Looks like it's not a simple Word version issue then as I'm using the same
build of Word as you (and Win XP Pro SP2). I do have Word 97 and 2007 on the
same machine so that might have something to do with it, although it works as
intended in these versions.

I can live with it as it is :)

Thanks again.

Regards.

Ed
 
R

Russ

Ed,
Is the form suppose to start off semi-transparent and stay that way or
become opaque when selected for use?
 
E

Ed

Hi Russ (& Tony),

It's intended to be semi- transparent all of the time.

I've never particularly liked Word's built-in Find dialog - the way it
obscures much of the screen and jumps around, so I banged together my
mini-Find. When it's onscreen, I keep it semi-transparent so that it doesn't
distract from the content of the document I'm searching.

Regards.

Ed
 

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