For Programmers: Free Programming Magazines  


Home > Archive > Visual Basic > April 2005 > SendKeys is affected by clicking on Close button









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author SendKeys is affected by clicking on Close button
Howard Kaikow

2005-04-22, 8:55 pm

What's the best way to prevent SendKeys from being affected by clicking on
Close button?

I hide the Form just before the SendKeys, but to code timing, other Forms
appear to get displayed before the SendKeys are finished.

The code is of the following structure:

Me.Hide
ctrl.Execute ' Displays the dialog to which the SendKeys are
to be applied
SendKeys "^{TAB}": Sleep 50: DoEvents
SendKeys "%v": Sleep 50: DoEvents
SendKeys "{TAB}": Sleep 50: DoEvents
SendKeys strStuff: Sleep 50: DoEvents
SendKeys "~": Sleep 50: DoEvents
Set ctrl = Nothing

However, a bit later in the code stream, other Forms get displayed, and
idepending on the timing of the clicks on the respective Close buttons, the
SendKeys gets messed up.

Is there a way to avoid this problem?
Can I detect when the SendKeys have actually completed execution?



--
http://www.standards.com/; See Howard Kaikow's web site.


MikeD

2005-04-23, 3:55 am


"Howard Kaikow" <kaikow@standards.com> wrote in message
news:%23LAxTn4RFHA.3928@TK2MSFTNGP09.phx.gbl...
> What's the best way to prevent SendKeys from being affected by clicking on
> Close button?


Don't use SendKeys? Seriously. I'm not joking. SendKeys is notorious for
being....shall we say....unpredictable (not to mention very
problematic)....and that's being kind regarding SendKeys.

>
> I hide the Form just before the SendKeys, but to code timing, other Forms
> appear to get displayed before the SendKeys are finished.
>
> The code is of the following structure:
>
> Me.Hide
> ctrl.Execute ' Displays the dialog to which the SendKeys

are
> to be applied
> SendKeys "^{TAB}": Sleep 50: DoEvents
> SendKeys "%v": Sleep 50: DoEvents
> SendKeys "{TAB}": Sleep 50: DoEvents
> SendKeys strStuff: Sleep 50: DoEvents
> SendKeys "~": Sleep 50: DoEvents
> Set ctrl = Nothing
>
> However, a bit later in the code stream, other Forms get displayed, and
> idepending on the timing of the clicks on the respective Close buttons,

the
> SendKeys gets messed up.
>
> Is there a way to avoid this problem?
> Can I detect when the SendKeys have actually completed execution?


What exactly are you trying to accomplish by means of all those SendKeys?
It looks as if you're changing focus, copying something, tabbing to some
other control, do whatever, and I have no idea what "~" means to SendKeys.
I can't believer there's not SOMETHING better than SendKeys to do whatever
it is that you're wanting. But you need to tell us what that is.

--
Mike
Microsoft MVP Visual Basic





Trammel

2005-04-23, 3:55 am

"Howard Kaikow" <kaikow@standards.com> wrote in message
news:%23LAxTn4RFHA.3928@TK2MSFTNGP09.phx.gbl...
> What's the best way to prevent SendKeys from being affected by clicking on
> Close button?
>
> I hide the Form just before the SendKeys, but to code timing, other Forms
> appear to get displayed before the SendKeys are finished.
>
> The code is of the following structure:
>
> Me.Hide
> ctrl.Execute ' Displays the dialog to which the SendKeys

are
> to be applied
> SendKeys "^{TAB}": Sleep 50: DoEvents
> SendKeys "%v": Sleep 50: DoEvents
> SendKeys "{TAB}": Sleep 50: DoEvents
> SendKeys strStuff: Sleep 50: DoEvents
> SendKeys "~": Sleep 50: DoEvents
> Set ctrl = Nothing
>
> However, a bit later in the code stream, other Forms get displayed, and
> idepending on the timing of the clicks on the respective Close buttons,

the
> SendKeys gets messed up.
>
> Is there a way to avoid this problem?
> Can I detect when the SendKeys have actually completed execution?
>
>
>
> --
> http://www.standards.com/; See Howard Kaikow's web site.
>
>


Try this:
http://www.programmershelp.co.uk/vbactivewindow.php


Howard Kaikow

2005-04-23, 3:55 am

My goal is to not use SendKeys.

I am trying to programmatically set the Password in the VBA Project
Properties window. Right now, the only method that works is to use SendKeys.

I was able to enumerate the windows and I found a handle to what I thought
corresponded to each item in the Project Properties dialog, both for th
eGeneral and Protection tabs.

A few minutes ago, I discovered the following.

Turns out that the handles returned in the code are the handles for the
labels on the textboxes.

For example, the handle for &Password is the handle for the "Password" label
itself, not for the adjacent box provided for the password.

So that may explain why using WM_COPYDATA with SendMessage returns an
invalid
password error.

Using WM_SETTEXT with SendMessage causes the "Password" label itself to be
changed to whatever text I send.

Need to find out how to get the handle of the actual input boxes.


--
http://www.standards.com/; See Howard Kaikow's web site.
"MikeD" <nobody@nowhere.edu> wrote in message
news:uwxAUQ5RFHA.356@TK2MSFTNGP14.phx.gbl...
>
> "Howard Kaikow" <kaikow@standards.com> wrote in message
> news:%23LAxTn4RFHA.3928@TK2MSFTNGP09.phx.gbl...
on[color=darkred]
>
> Don't use SendKeys? Seriously. I'm not joking. SendKeys is notorious for
> being....shall we say....unpredictable (not to mention very
> problematic)....and that's being kind regarding SendKeys.
>
Forms[color=darkred]
> are
> the
>
> What exactly are you trying to accomplish by means of all those SendKeys?
> It looks as if you're changing focus, copying something, tabbing to some
> other control, do whatever, and I have no idea what "~" means to SendKeys.
> I can't believer there's not SOMETHING better than SendKeys to do whatever
> it is that you're wanting. But you need to tell us what that is.
>
> --
> Mike
> Microsoft MVP Visual Basic
>
>
>
>
>



Howard Kaikow

2005-04-23, 3:55 am

Thanx.

As I just tried to explain in another response in this thread, I'm trying to
get the handles of the actual controls in the VBA Project Properties dialog
for the Protection tab.

I have not found a way to get those handles.

Once I cause the Protection tab to be known, EnumChildWindows appeared to
ennumate all windows, but I just found out a few minutes ago that it is not
ennumerating the password and confirm password boxes and likely not the
locked check box.

--
http://www.standards.com/; See Howard Kaikow's web site.
"Trammel" <Me@Server.com> wrote in message
news:cigae.21620$Pc.12529@fe1.news.blueyonder.co.uk...
> "Howard Kaikow" <kaikow@standards.com> wrote in message
> news:%23LAxTn4RFHA.3928@TK2MSFTNGP09.phx.gbl...
on[color=darkred]
Forms[color=darkred]
> are
> the
>
> Try this:
> http://www.programmershelp.co.uk/vbactivewindow.php
>
>



J French

2005-04-23, 8:55 am

On Fri, 22 Apr 2005 23:23:26 -0400, "Howard Kaikow"
<kaikow@standards.com> wrote:

<snip>

>For example, the handle for &Password is the handle for the "Password" label
>itself, not for the adjacent box provided for the password.
>
>So that may explain why using WM_COPYDATA with SendMessage returns an
>invalid
>password error.


Check out what WM_COPYDATA is meant to do
- it is a fairly complex beast

>Using WM_SETTEXT with SendMessage causes the "Password" label itself to be
>changed to whatever text I send.


That figures
- but you should be able to locate the Handle of the Edit box
- if it really is an edit box

>Need to find out how to get the handle of the actual input boxes.


Write a little WindowFromPoint snooper
Howard Kaikow

2005-04-23, 8:55 pm



--
http://www.standards.com/; See Howard Kaikow's web site.
"J French" <erewhon@nowhere.uk> wrote in message
news:426a2e94.5869236@news.btclick.com...
> On Fri, 22 Apr 2005 23:23:26 -0400, "Howard Kaikow"
> <kaikow@standards.com> wrote:
>
> <snip>
>
label[color=darkred]
>
> Check out what WM_COPYDATA is meant to do
> - it is a fairly complex beast
>
be[color=darkred]
>
> That figures
> - but you should be able to locate the Handle of the Edit box
> - if it really is an edit box
>
>
> Write a little WindowFromPoint snooper



Howard Kaikow

2005-04-23, 8:55 pm

> That figures
> - but you should be able to locate the Handle of the Edit box
> - if it really is an edit box


I already enumerated the windows, no handle is returne for the box.

>
> Write a little WindowFromPoint snooper


I can only position the pointer into the box using SendKeys.
I guess I can follow that with a Window fromPoint to see what gets returned.


Howard Kaikow

2005-04-23, 8:55 pm

I tried using WindowFromPoint, see code below.

Just before calling this sub, I used SendKeys to fill the password field,
but that does not seem to make it the active cursor position.

Right after using SendKeys to fill the password field, I run:

strPassword = "Boo"
SendString strPassword
strPassword = "my"

I had hoped that the SendString would change the password box, but it did
not.
If it had, I would have received an error that the password in the confirm
box does not match.

When I run in design mode, I can see that SendString is sometimes changing
the caption for the button in the VB 6 Form, not that VBA dialog. Oter
times, I do not see where it changes anything. Of course, the code is too
fat to watch. Cannot step thru the code because then th Debug winow gets the
focus.

Running from a .exe, the code is too fast to see anything.

I do list the relevant items in a list box.

Private Sub SendString(strToSend As String)
Dim buffer() As Byte
Dim k As Long
Dim hWnd As Long
Dim strCaption As String

Dim Pt As POINTAPI

hWnd = GetActiveWindow()
strCaption = Space$(GetWindowTextLength(hWnd) + 1)
GetWindowText hWnd, strCaption, Len(strCaption)
strCaption = Left$(strCaption, Len(strCaption) - 1)

lstOutput.AddItem "GetActiveWindow in SendString: " & strCaption & " = "
& hWnd

GetCursorPos Pt
hWnd = WindowFromPoint(Pt.X, Pt.Y)
strCaption = Space$(GetWindowTextLength(hWnd) + 1)
GetWindowText hWnd, strCaption, Len(strCaption)
strCaption = Left$(strCaption, Len(strCaption) - 1)

lstOutput.AddItem "GetCursorPos in SendString: " & strCaption & " = " &
hWnd

k = Len(strToSend)
ReDim buffer(k)
Call CopyMemory(buffer(0), ByVal strToSend, Len(strToSend))
SendMessage hWnd, WM_SETTEXT, 0, buffer(0)
End Sub


Randy Birch

2005-04-24, 3:55 am

Run the spyxx tool and inspect the dialog with that. You should get, for the
password box of interest, a control ID number. That never changes between
runs, but the hwnd will. Armed with the control ID, you can now do your
thing to get the hwnd of the property dialog, then use the GetDlgItem() API
to return the hwnd to the control you specify with the control ID you
discovered earlier. Now that you have that hwnd, try using SendMessage with
WM_SETTEXT as the message, and byval sPassword as lparam. wParam will be
passed as 0&. For an example of using GetDlgItem, see
http://vbnet.mvps.org/code/hooks/ch...orcustomize.htm

--

Randy Birch
MS MVP Visual Basic
http://vbnet.mvps.org/
----------------------------------------------------------------------------
Read. Decide. Sign the petition to Microsoft.
http://classicvb.org/petition/
----------------------------------------------------------------------------



"Howard Kaikow" <kaikow@standards.com> wrote in message
news:OFiLYWFSFHA.1392@TK2MSFTNGP10.phx.gbl...
:I tried using WindowFromPoint, see code below.
:
: Just before calling this sub, I used SendKeys to fill the password field,
: but that does not seem to make it the active cursor position.
:
: Right after using SendKeys to fill the password field, I run:
:
: strPassword = "Boo"
: SendString strPassword
: strPassword = "my"
:
: I had hoped that the SendString would change the password box, but it did
: not.
: If it had, I would have received an error that the password in the confirm
: box does not match.
:
: When I run in design mode, I can see that SendString is sometimes changing
: the caption for the button in the VB 6 Form, not that VBA dialog. Oter
: times, I do not see where it changes anything. Of course, the code is too
: fat to watch. Cannot step thru the code because then th Debug winow gets
the
: focus.
:
: Running from a .exe, the code is too fast to see anything.
:
: I do list the relevant items in a list box.
:
: Private Sub SendString(strToSend As String)
: Dim buffer() As Byte
: Dim k As Long
: Dim hWnd As Long
: Dim strCaption As String
:
: Dim Pt As POINTAPI
:
: hWnd = GetActiveWindow()
: strCaption = Space$(GetWindowTextLength(hWnd) + 1)
: GetWindowText hWnd, strCaption, Len(strCaption)
: strCaption = Left$(strCaption, Len(strCaption) - 1)
:
: lstOutput.AddItem "GetActiveWindow in SendString: " & strCaption & " =
"
: & hWnd
:
: GetCursorPos Pt
: hWnd = WindowFromPoint(Pt.X, Pt.Y)
: strCaption = Space$(GetWindowTextLength(hWnd) + 1)
: GetWindowText hWnd, strCaption, Len(strCaption)
: strCaption = Left$(strCaption, Len(strCaption) - 1)
:
: lstOutput.AddItem "GetCursorPos in SendString: " & strCaption & " = " &
: hWnd
:
: k = Len(strToSend)
: ReDim buffer(k)
: Call CopyMemory(buffer(0), ByVal strToSend, Len(strToSend))
: SendMessage hWnd, WM_SETTEXT, 0, buffer(0)
: End Sub
:
:

Howard Kaikow

2005-04-24, 3:55 am

"Randy Birch" <rgb_removethis@mvps.org> wrote in message
news:O$KBdqHSFHA.3928@TK2MSFTNGP09.phx.gbl...
> Run the spyxx tool and inspect the dialog with that. You should get, for

the
> password box of interest, a control ID number. That never changes between
> runs, but the hwnd will. Armed with the control ID, you can now do your
> thing to get the hwnd of the property dialog, then use the GetDlgItem()

API
> to return the hwnd to the control you specify with the control ID you
> discovered earlier. Now that you have that hwnd, try using SendMessage

with
> WM_SETTEXT as the message, and byval sPassword as lparam. wParam will be
> passed as 0&. For an example of using GetDlgItem, see
> http://vbnet.mvps.org/code/hooks/ch...orcustomize.htm


Thanx.

I have spyxx, but, alas, on my mail system, the installation of VB .NET
seems to have uninstalled the old Visual Studio version.

I guess I could write a quickee VB .NET program to use .NET's spyxx.
Alternative is to reboot to a system that does not have VS.NET.
I guess I'll flip a coin, with my luck it will likely land on its edge.

I've managed to use keybd_event to get rid of most of the SendKeys, but I
need to add code for keyboard_event to use Alt, Shift and Ctrl keys.

However, it does appear that keybd_event might be susceptiple to the user's
mouse clicks when the code is running, so it may be better to continue
trying to use WM_SETTEXT, i.e., if I can ever get the handles I need.
keybd_event runs much faster than SendKeys.

The last thing I will try to do, tho I'm not sure it is possible, is to try
to set the fields of the Project Properties dialog without the dialog
needing to be visible. I do not think this is possible, unless the IDs that
I can get with GetDlgItem exist when the dialog is not visible. The handles
do not exist without the dialog being visible, indeed, they do not exist
unless the Protection tab is displayed, and CTRL TAB is needed to get to the
Protection tab.

Getting rid of SendKeys, in this case, eliminates the need for DoEvents and
Sleep with each SendKey.


Howard Kaikow

2005-04-24, 3:55 am

I see that spyxx is independent of vb 6, so I was able to use the .net spyxx
to find that there are 2 Edit controls and a Systabcontrol32 that might be
relevant.

I'll try using GetDlgItem to get the handles.

I'm hoping that systancontrol32 will allow me to use GetFocus to go to the
Protection tab.
--
http://www.standards.com/; See Howard Kaikow's web site.
"Howard Kaikow" <kaikow@standards.com> wrote in message
news:%23u5G3LISFHA.3560@TK2MSFTNGP14.phx.gbl...
> "Randy Birch" <rgb_removethis@mvps.org> wrote in message
> news:O$KBdqHSFHA.3928@TK2MSFTNGP09.phx.gbl...
> the
between[color=darkred]
> API
> with
>
> Thanx.
>
> I have spyxx, but, alas, on my mail system, the installation of VB .NET
> seems to have uninstalled the old Visual Studio version.
>
> I guess I could write a quickee VB .NET program to use .NET's spyxx.
> Alternative is to reboot to a system that does not have VS.NET.
> I guess I'll flip a coin, with my luck it will likely land on its edge.
>
> I've managed to use keybd_event to get rid of most of the SendKeys, but I
> need to add code for keyboard_event to use Alt, Shift and Ctrl keys.
>
> However, it does appear that keybd_event might be susceptiple to the

user's
> mouse clicks when the code is running, so it may be better to continue
> trying to use WM_SETTEXT, i.e., if I can ever get the handles I need.
> keybd_event runs much faster than SendKeys.
>
> The last thing I will try to do, tho I'm not sure it is possible, is to

try
> to set the fields of the Project Properties dialog without the dialog
> needing to be visible. I do not think this is possible, unless the IDs

that
> I can get with GetDlgItem exist when the dialog is not visible. The

handles
> do not exist without the dialog being visible, indeed, they do not exist
> unless the Protection tab is displayed, and CTRL TAB is needed to get to

the
> Protection tab.
>
> Getting rid of SendKeys, in this case, eliminates the need for DoEvents

and
> Sleep with each SendKey.
>
>



Howard Kaikow

2005-04-24, 3:55 pm

Using spyxx, I was able to find all the needed comtrol ids, but there is
still an issue.

My original code and the current new code are given below.
I retained the Sleep and DoEvents in the new code until I get the critter
working.

I can see the boxes being checked/filled-in and the dialog closes, but the
values are not retained with the new code.

'''''''''''''''''''''OLD
CODE''''''''''''''''''''''''''''''''''''
'''''''''''''''''''
' Lock project for &viewing
SendKeys "%v": Sleep 50: DoEvents

' &Password
SendKeys "{TAB}": Sleep 50: DoEvents
SendKeys strPassword: Sleep 50: DoEvents

' &Confirm Password
SendKeys "{TAB}": Sleep 50: DoEvents
SendKeys strPassword: Sleep 50: DoEvents

'Enter key
SendKeys "~": Sleep 50: DoEvents

'''''''''''''''''''''New
CODE''''''''''''''''''''''''''''''''''''
'''''''''''''''''''
' ' Lock project for &viewing
' SendKeys "%v": Sleep lngSleep: DoEvents 'Keep for debugging

' ' &Password
' SendWM_SETTEXT strPassword, lngPassword
' Sleep lngSleep: DoEvents

' ' &Confirm password
' SendWM_SETTEXT strPassword, lngConfirmPassword
' Sleep lngSleep: DoEvents

' 'Enter key on OK
' SetFocusAPI lngOK
' Sleep lngSleep: DoEvents
' SendKeys "~": Sleep lngSleep: DoEvents 'Keep for debugging

The new code uses:


Private Sub SendWM_SETTEXT(strToSend As String, hWnd As Long)
' strToSend: String to send
' hWnd: hWnd of the target window
Dim k As Long
Dim buffer() As Byte
k = Len(strToSend)
ReDim buffer(k)
Call CopyMemory(buffer(0), ByVal strToSend, k)
SendMessage hWnd, WM_SETTEXT, 0, buffer(0)
End Sub


Randy Birch

2005-04-24, 3:55 pm

OK ... instead of wm_settext, try a combination of em_setsel to select the
text, and em_replacesel to replace any text there. Using em_setsel, wparam
is the first char, and byval lparam is the last char to select (if the
control contains any text already, of course). em_setsel is not required
when the control is empty. It's sister api is em_replacesel which assigns
the text to the control; wparam is either 1 or 0, where 1 means the
operation can be undone, and 0 means it can't. lParam is Byval <your
string>. (any reason you're using byte arrays instead of sending the string
directly?)

It is possible that the control uses the keypress to capture the text
entered, and merely uses the gui to reflect the entered text.

There is also a message called em_setmodify, which when called sets (or
clears) the modification flag for an edit control. The modification flag
indicates whether the text within the edit control has been modified. This
message is sent using sendmessage, with wparam set to 1 if the text has been
modified, and a false to indicates it has not been modified. lparam is not
used so should be passed as ByVal 0&.

--

Randy Birch
MS MVP Visual Basic
http://vbnet.mvps.org/
----------------------------------------------------------------------------
Read. Decide. Sign the petition to Microsoft.
http://classicvb.org/petition/
----------------------------------------------------------------------------



"Howard Kaikow" <kaikow@standards.com> wrote in message
news:%23Y84RbMSFHA.2788@TK2MSFTNGP09.phx.gbl...
: Using spyxx, I was able to find all the needed comtrol ids, but there is
: still an issue.
:
: My original code and the current new code are given below.
: I retained the Sleep and DoEvents in the new code until I get the critter
: working.
:
: I can see the boxes being checked/filled-in and the dialog closes, but the
: values are not retained with the new code.
:
: '''''''''''''''''''''OLD
: CODE''''''''''''''''''''''''''''''''''''
'''''''''''''''''''
: ' Lock project for &viewing
: SendKeys "%v": Sleep 50: DoEvents
:
: ' &Password
: SendKeys "{TAB}": Sleep 50: DoEvents
: SendKeys strPassword: Sleep 50: DoEvents
:
: ' &Confirm Password
: SendKeys "{TAB}": Sleep 50: DoEvents
: SendKeys strPassword: Sleep 50: DoEvents
:
: 'Enter key
: SendKeys "~": Sleep 50: DoEvents
:
: '''''''''''''''''''''New
: CODE''''''''''''''''''''''''''''''''''''
'''''''''''''''''''
: ' ' Lock project for &viewing
: ' SendKeys "%v": Sleep lngSleep: DoEvents 'Keep for debugging
:
: ' ' &Password
: ' SendWM_SETTEXT strPassword, lngPassword
: ' Sleep lngSleep: DoEvents
:
: ' ' &Confirm password
: ' SendWM_SETTEXT strPassword, lngConfirmPassword
: ' Sleep lngSleep: DoEvents
:
: ' 'Enter key on OK
: ' SetFocusAPI lngOK
: ' Sleep lngSleep: DoEvents
: ' SendKeys "~": Sleep lngSleep: DoEvents 'Keep for debugging
:
: The new code uses:
:
:
: Private Sub SendWM_SETTEXT(strToSend As String, hWnd As Long)
: ' strToSend: String to send
: ' hWnd: hWnd of the target window
: Dim k As Long
: Dim buffer() As Byte
: k = Len(strToSend)
: ReDim buffer(k)
: Call CopyMemory(buffer(0), ByVal strToSend, k)
: SendMessage hWnd, WM_SETTEXT, 0, buffer(0)
: End Sub
:
:

Howard Kaikow

2005-04-24, 8:55 pm

"Randy Birch" <rgb_removethis@mvps.org> wrote in message
news:uJNHHUOSFHA.688@TK2MSFTNGP10.phx.gbl...
> OK ... instead of wm_settext, try a combination of em_setsel to select the
> text, and em_replacesel to replace any text there. Using em_setsel,

wparam
> is the first char, and byval lparam is the last char to select (if the
> control contains any text already, of course). em_setsel is not required
> when the control is empty. It's sister api is em_replacesel which assigns
> the text to the control; wparam is either 1 or 0, where 1 means the
> operation can be undone, and 0 means it can't. lParam is Byval <your
> string>. (any reason you're using byte arrays instead of sending the

string
> directly?)
>
> It is possible that the control uses the keypress to capture the text
> entered, and merely uses the gui to reflect the entered text.
>
> There is also a message called em_setmodify, which when called sets (or
> clears) the modification flag for an edit control. The modification flag
> indicates whether the text within the edit control has been modified.

This
> message is sent using sendmessage, with wparam set to 1 if the text has

been
> modified, and a false to indicates it has not been modified. lparam is not
> used so should be passed as ByVal 0&.


Thanx, I'll try your suggestions after I visit Wysteria Lane tonight.

But, your reply prompted me to print some of the pages on edit controls in
the October 2001 MSDN library.

Sure 'nuff WM_SETTEXT is not listed as one of the messages to be used with
edit controls.
WM_COPY is listed, but that requires knowing what value to use for dwData in
COPYDATASTRUCT.

Guess I got some reading to do.


Randy Birch

2005-04-25, 3:55 am

: Sure 'nuff WM_SETTEXT is not listed as one of the messages to be
: used with edit controls.

Actually somewhere in the MSDN it does say that for edit controls the
correct message is WM_SETTEXT. Under Remarks there, it states:

The DefWindowProc function sets and displays the window text. For an edit
control, the text is the contents of the edit control. For a combo box, the
text is the contents of the edit-control portion of the combo box. For a
button, the text is the button name. For other windows, the text is the
window title.


--

Randy Birch
MS MVP Visual Basic
http://vbnet.mvps.org/
----------------------------------------------------------------------------
Read. Decide. Sign the petition to Microsoft.
http://classicvb.org/petition/
----------------------------------------------------------------------------



Tom Esh

2005-04-25, 3:55 am

On Sun, 24 Apr 2005 18:01:51 -0400, "Howard Kaikow"
<kaikow@standards.com> wrote:
>But, your reply prompted me to print some of the pages on edit controls in
>the October 2001 MSDN library.
>
>Sure 'nuff WM_SETTEXT is not listed as one of the messages to be used with
>edit controls.
>WM_COPY is listed, but that requires knowing what value to use for dwData in
>COPYDATASTRUCT.
>
>Guess I got some reading to do.


One helpful thing to look for with controls in MSDN is a sub-topic
titled "controlname Default Message Processing". It's a summary of
sorts - brief descriptions of the control's default handling of
applicable WM_ messages along with control-specific messages.


-Tom
MVP - Visual Basic
(please post replies to the newsgroup)
Howard Kaikow

2005-04-25, 8:55 am

Eureka!

I'm one step closer to eliminating SendKeys in this app.

I was not able to use EM_REPLACESEL successfully, i.e., the password did not
get entered as I intended or there was an error in matching the Password and
Confirm Pasword fields.

The problem had to be with the way I was passing lParam since SendMessage
had that typed as Any.

The fix was simple and obvious, I just declared a SendMessageAsString that
had lParam as String.

So there is now but one SendKeys left, but it is key to everything else.

' Get to the Protection tab
SendKeys "^{TAB}": Sleep lngSleep: DoEvents

I can set focus to the SysTabControl32 control using:
SetFocusAPI lngSysTabControl32

Is there a message that can be used to switch the tab?

In the process of doing all this, I found something that, to me, is strange.

Initially, I get the handle for the Project Properties window by creating a
string that has the known window caption and passing that caption to
FindWindow.

With that handle, I can use GetDlgItem to get the handles for OK and
SysTabControl32.
I have to CTRL TAB to the Protection tab before I can use GetDlgItem to get
the Lock project, Password and Confirm Password handles.

Nothing wrong with that, but I was surprised to find that the original
handle for the Project Properties window could not be used to get the Lock
Project, Password and Confirm Password handles.

Since the old handle was no longer valid, I could not use GetDlgItem to get
those handles.

The solution was to use EnumChildWindows to get the new handle, which seemed
strange as EnumChildWindows had to start with the old handle.

So the question is, if I can enum the windows using the old handle, why
cannot I get the other handles using the old handle?

There's likely an explanation of this somewhere, and it likely makes sense.


Howard Kaikow

2005-04-25, 8:55 pm

Bingo!

In this app, SendKeys is no more!

'''''''''''''''''''''OLD
CODE''''''''''''''''''''''''''''''''''''
'''''''''''''''''''
'Protection tab
' SendKeys "^{TAB}": Sleep 50: DoEvents

' ' Lock project for &viewing
' SendKeys "%v": Sleep 50: DoEvents
'
' ' &Password
' SendKeys "{TAB}": Sleep 50: DoEvents
' SendKeys strPassword: Sleep 50: DoEvents
'
' ' &Confirm Password
' SendKeys "{TAB}": Sleep 50: DoEvents
' SendKeys strPassword: Sleep 50: DoEvents
'
' 'Enter key
' SendKeys "~": Sleep 50: DoEvents

'''''''''''''''''''''New
CODE''''''''''''''''''''''''''''''''''''
'''''''''''''''''''
'Protection tab
KeyBoardSendStringCtrl vbTab ' Uses keybd_event
' SetFocusAPI lngSysTabControl32 ' I'd like to use this instead.

' Lock project for &viewing
SendMessage lngLockProject, BM_SETCHECK, BST_CHECKED, 0

' &Password
SendMessageAsString lngPassword, EM_REPLACESEL, vbTrue,
strPassword

' &Confirm password
SendMessageAsString lngConfirmPassword, EM_REPLACESEL, vbTrue,
strPassword

'Enter key on OK
SetFocusAPI ByVal lngOK
KeyBoardSendString vbCr ' Uses keybd_event, I'd like to use
somethibg other than keybd_event here


Randy Birch

2005-04-26, 3:55 am

FWIW, it's not necessary to create an aliased SendMessage declare ... just
leave it as lparam as any and pass the string using Byval strPassword.

--

Randy Birch
MS MVP Visual Basic
http://vbnet.mvps.org/
----------------------------------------------------------------------------
Read. Decide. Sign the petition to Microsoft.
http://classicvb.org/petition/
----------------------------------------------------------------------------



"Howard Kaikow" <kaikow@standards.com> wrote in message
news:%23AM2AsXSFHA.2356@TK2MSFTNGP14.phx.gbl...
: Eureka!
:
: I'm one step closer to eliminating SendKeys in this app.
:
: I was not able to use EM_REPLACESEL successfully, i.e., the password did
not
: get entered as I intended or there was an error in matching the Password
and
: Confirm Pasword fields.
:
: The problem had to be with the way I was passing lParam since SendMessage
: had that typed as Any.
:
: The fix was simple and obvious, I just declared a SendMessageAsString that
: had lParam as String.
:
: So there is now but one SendKeys left, but it is key to everything else.
:
: ' Get to the Protection tab
: SendKeys "^{TAB}": Sleep lngSleep: DoEvents
:
: I can set focus to the SysTabControl32 control using:
: SetFocusAPI lngSysTabControl32
:
: Is there a message that can be used to switch the tab?
:
: In the process of doing all this, I found something that, to me, is
strange.
:
: Initially, I get the handle for the Project Properties window by creating
a
: string that has the known window caption and passing that caption to
: FindWindow.
:
: With that handle, I can use GetDlgItem to get the handles for OK and
: SysTabControl32.
: I have to CTRL TAB to the Protection tab before I can use GetDlgItem to
get
: the Lock project, Password and Confirm Password handles.
:
: Nothing wrong with that, but I was surprised to find that the original
: handle for the Project Properties window could not be used to get the Lock
: Project, Password and Confirm Password handles.
:
: Since the old handle was no longer valid, I could not use GetDlgItem to
get
: those handles.
:
: The solution was to use EnumChildWindows to get the new handle, which
seemed
: strange as EnumChildWindows had to start with the old handle.
:
: So the question is, if I can enum the windows using the old handle, why
: cannot I get the other handles using the old handle?
:
: There's likely an explanation of this somewhere, and it likely makes
sense.
:
:

Howard Kaikow

2005-04-26, 3:55 am

"Randy Birch" <rgb_removethis@mvps.org> wrote in message
news:u3YcZ6eSFHA.3496@TK2MSFTNGP12.phx.gbl...
> FWIW, it's not necessary to create an aliased SendMessage declare ... just
> leave it as lparam as any and pass the string using Byval strPassword.



I did, but that was not working.
Of course, in my daze, I may have screwed up, I'll have to go back and
check, ...

OK, got rid of the alias, now its working with Byval. Don't know it didn't
work before.


Howard Kaikow

2005-04-26, 3:55 am

OK. now that I've gotten rid of SendKeys and minimined the window, next step
is to try to get rid of keybd_event.

In the following code, I'd like to avoid sending CTRL TAB.
I can use SetFocusAPI to set the focus on the SysTabControl32..
How does one change tabs for SysTabControl32?

'Protection tab
KeyBoardSendStringCtrl vbTab
' SetFocusAPI hWndSysTabControl32

The other case is the following code. I can set the focus on the OK button
and then use keybd_event to send a vbTab.

I'd rather find a way to click on the button. BM_SETCHECK does not effect
command buttons.

'OK button
SetFocusAPI ByVal hWndOK
KeyBoardSendString vbCr


Tom Esh

2005-04-26, 3:56 am

On Mon, 25 Apr 2005 22:07:58 -0400, "Howard Kaikow"
<kaikow@standards.com> wrote:

>In the following code, I'd like to avoid sending CTRL TAB.
>I can use SetFocusAPI to set the focus on the SysTabControl32..
>How does one change tabs for SysTabControl32?


To change tabs, you can send TCM_SETCURSEL with the ~0-based~ index of
the tab. (Depending on the app you may find it necessary to follow
TCM_SETCURSEL with a TCN_SELCHANGE notification (WM_NOTIFY) to the
parent.)

>The other case is the following code. I can set the focus on the OK button
>and then use keybd_event to send a vbTab.
>
>I'd rather find a way to click on the button. BM_SETCHECK does not effect
>command buttons.


For the button, try sending it a BM_CLICK message.


-Tom
MVP - Visual Basic
(please post replies to the newsgroup)
Howard Kaikow

2005-04-26, 3:56 am

"Tom Esh" <tjeshGibberish@suscom.net> wrote in message
news:6sbr61dks4b0g2nl1u69e5mbbkg6vistg7@
4ax.com...
> On Mon, 25 Apr 2005 22:07:58 -0400, "Howard Kaikow"
> <kaikow@standards.com> wrote:
>
>
> To change tabs, you can send TCM_SETCURSEL with the ~0-based~ index of
> the tab. (Depending on the app you may find it necessary to follow
> TCM_SETCURSEL with a TCN_SELCHANGE notification (WM_NOTIFY) to the
> parent.)
>
button[color=darkred]
>
> For the button, try sending it a BM_CLICK message.


Thanx.

Did not know about the TCM stuff.
BM_Click is not liste din Dan Appleman's book, so I missed that.


Tom Esh

2005-04-26, 3:56 am

On Tue, 26 Apr 2005 00:04:50 -0400, "Howard Kaikow"
<kaikow@standards.com> wrote:
>
>Did not know about the TCM stuff.
>BM_Click is not liste din Dan Appleman's book, so I missed that.


Yeah, Appleman's book is a great place to start but is by no means
complete. (You'd need a hand truck to carry it if it were.) Here's the
declares if you need them:

Public Const TCM_FIRST = &H1300&
Public Const TCM_SETCURSEL = (TCM_FIRST + 12)
Public Const TCN_FIRST = (-550&)
Public Const TCN_SELCHANGE = (TCN_FIRST - 1)


-Tom
MVP - Visual Basic
(please post replies to the newsgroup)
Howard Kaikow

2005-04-26, 8:56 am

"Tom Esh" <tjeshGibberish@suscom.net> wrote in message
news:dokr615phvdkfrbg8bnokdfkac68tn2hmq@
4ax.com...
> On Tue, 26 Apr 2005 00:04:50 -0400, "Howard Kaikow"
> <kaikow@standards.com> wrote:
>
> Yeah, Appleman's book is a great place to start but is by no means
> complete. (You'd need a hand truck to carry it if it were.) Here's the
> declares if you need them:
>
> Public Const TCM_FIRST = &H1300&

Should not that be &H2CC& as the value in C was, as I recall, in octal?

> Public Const TCM_SETCURSEL = (TCM_FIRST + 12)
> Public Const TCN_FIRST = (-550&)
> Public Const TCN_SELCHANGE = (TCN_FIRST - 1)


Thanx.

I found those in commctrl.h, but i was also looking for the declare for
TabCtrl_SetCurSel.
My (misreading) of commctrl.h led me to use

Private Declare Function TabCtrl_SetCurSel Lib "comctl32" (ByVal hwnd As
Long, ByVal iTem As Integer) As Long

But comctl32 is not the right library. Nor was user32.

In either case, I likely will have follow up with the TCN_SELCHANGE
notification via WM_NOTIFY.
I have to look into how to do that.

Do I really need to download the 266 MB SDK to get the latest poop?


Howard Kaikow

2005-04-26, 3:56 pm

Is the following correct use of TCM_SETCURSEL and TCN_SELCHANGE?

I must be screwing up somewhere.

Private Type NMHDR
hwndFrom As Long
idfrom As Long
code As Long
End Type

Private Const TCM_SETCURSEL as Long= &H2CC&
Private Const TCN_FIRST As Long = -500
Private Const TCN_SELCHANGE As Long = (TCN_FIRST - 1)
Private Const WM_NOTIFY As Long = &H4E&

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
----------------------------------
With msgNotify
.hwndFrom = hWndSysTabControl32
.idfrom = ControlIDSysTabControl32
.code = TCN_SELCHANGE
End With

'Protection tab
' SetFocusAPI hWndSysTabControl32 ' this works
' KeyBoardSendStringCtrl vbTab ' this works

SendMessage hWndSysTabControl32, TCM_SETCURSEL, 1, 0
SendMessage hWndSysTabControl32, WM_NOTIFY,
ControlIDSysTabControl32, ByVal msgNotify

where hWndSysTabControl32 is the handle for the tab control in the Project
properties dialog, and
ControlIDSysTabControl32 is the ID for the tab control


Tom Esh

2005-04-26, 3:56 pm

On Tue, 26 Apr 2005 02:51:13 -0400, "Howard Kaikow"
<kaikow@standards.com> wrote:
>Should not that be &H2CC& as the value in C was, as I recall, in octal?


No idea where you got &H2CC, but it's not octal anything.
&H1300 (hex) is correct.

>...
>I found those in commctrl.h, but i was also looking for the declare for
>TabCtrl_SetCurSel.
>My (misreading) of commctrl.h led me to use


TabCtrl_SetCurSel is a C ~macro~, not an Api function.
I probably would not use a proceedure wrapper for something this
simple, but a VB equivalent would be:

Public Sub TabCtrl_SetCurSel( _
ByVal hwndTabCtl, _
ByVal nTab As Long)

SendMessage hwndTabCtl, TCM_SETCURSEL, nTab, ByVal 0&
End Sub

>In either case, I likely will have follow up with the TCN_SELCHANGE
>notification via WM_NOTIFY.
>I have to look into how to do that.
>
>Do I really need to download the 266 MB SDK to get the latest poop?


Yeah, I know. It's mostly stuff VB'ers don't need. I think there's a
declare file for comctl somewhere at vbaccelerator:
http://vbaccelerator.com/home/index.asp



-Tom
MVP - Visual Basic
(please post replies to the newsgroup)
Tom Esh

2005-04-26, 3:56 pm

On Tue, 26 Apr 2005 07:45:35 -0400, "Howard Kaikow"
<kaikow@standards.com> wrote:

>Is the following correct use of TCM_SETCURSEL and TCN_SELCHANGE?
>
>I must be screwing up somewhere.
>
> Private Type NMHDR
> hwndFrom As Long
> idfrom As Long
> code As Long
> End Type
>
> Private Const TCM_SETCURSEL as Long= &H2CC&
> Private Const TCN_FIRST As Long = -500
> Private Const TCN_SELCHANGE As Long = (TCN_FIRST - 1)
> Private Const WM_NOTIFY As Long = &H4E&
>
> 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
>----------------------------------
> With msgNotify
> .hwndFrom = hWndSysTabControl32
> .idfrom = ControlIDSysTabControl32
> .code = TCN_SELCHANGE
> End With
>
> 'Protection tab
>' SetFocusAPI hWndSysTabControl32 ' this works
>' KeyBoardSendStringCtrl vbTab ' this works
>
> SendMessage hWndSysTabControl32, TCM_SETCURSEL, 1, 0
> SendMessage hWndSysTabControl32, WM_NOTIFY,
>ControlIDSysTabControl32, ByVal msgNotify
>
>where hWndSysTabControl32 is the handle for the tab control in the Project
>properties dialog, and
>ControlIDSysTabControl32 is the ID for the tab control
>


Ok, except for some minor points.

Somehow you got the wrong declares. Use these.

Public Const TCM_FIRST = &H1300&
Public Const TCM_SETCURSEL = (TCM_FIRST + 12)
Public Const TCN_FIRST = (-550&)
Public Const TCN_SELCHANGE = (TCN_FIRST - 1)

WM_NOTIFY with TCN_SELCHANGE goes to the control's ~parent~, not the
control itself. (Think of WM_NOTIFY as an ~event~ mechanism.) You can
use GetParent in-line to fetch the parent hwnd.

'note lParam passed ByVal...
SendMessage hWndSysTabControl32, TCM_SETCURSEL, 1, ByVal 0&

'note lParam passed ByRef...
SendMessage GetParent(hWndSysTabControl32), WM_NOTIFY, _
ControlIDSysTabControl32, msgNotify


-Tom
MVP - Visual Basic
(please post replies to the newsgroup)
Howard Kaikow

2005-04-26, 8:55 pm

"Tom Esh" <tjeshGibberish@suscom.net> wrote in message
news:aets615u0afagjdf47mm9nccdsrtn3ju3n@
4ax.com...
> On Tue, 26 Apr 2005 02:51:13 -0400, "Howard Kaikow"
> <kaikow@standards.com> wrote:
octal?[color=darkred]
>
> No idea where you got &H2CC, but it's not octal anything.
> &H1300 (hex) is correct.


I found the following in commctrl.h

#define TCM_FIRST 0x1300 // Tab control messages

I forgot that 0x means hexadecimal, not octal.

> TabCtrl_SetCurSel is a C ~macro~, not an Api function.
> I probably would not use a proceedure wrapper for something this
> simple, but a VB equivalent would be:
>
> Public Sub TabCtrl_SetCurSel( _
> ByVal hwndTabCtl, _
> ByVal nTab As Long)
>
> SendMessage hwndTabCtl, TCM_SETCURSEL, nTab, ByVal 0&
> End Sub


I agree that a wrapper is unnecessary here.
I had the right SendMessage, but the wrong hex code

>
> Yeah, I know. It's mostly stuff VB'ers don't need. I think there's a
> declare file for comctl somewhere at vbaccelerator:
> http://vbaccelerator.com/home/index.asp


Ayup, Norm Cook pointed it to me in another thread

http://www.vbaccelerator.com/home/V..._c
tl.asp



Howard Kaikow

2005-04-26, 8:55 pm

"Tom Esh" <tjeshGibberish@suscom.net> wrote in message
news:nius61h85lakc3g1bao4eg64seq4j22t23@
4ax.com...
> Ok, except for some minor points.
>
> Somehow you got the wrong declares. Use these.
>
> Public Const TCM_FIRST = &H1300&
> Public Const TCM_SETCURSEL = (TCM_FIRST + 12)
> Public Const TCN_FIRST = (-550&)
> Public Const TCN_SELCHANGE = (TCN_FIRST - 1)
>
> WM_NOTIFY with TCN_SELCHANGE goes to the control's ~parent~, not the
> control itself. (Think of WM_NOTIFY as an ~event~ mechanism.) You can
> use GetParent in-line to fetch the parent hwnd.
>
> 'note lParam passed ByVal...
> SendMessage hWndSysTabControl32, TCM_SETCURSEL, 1, ByVal 0&
>
> 'note lParam passed ByRef...
> SendMessage GetParent(hWndSysTabControl32), WM_NOTIFY, _
> ControlIDSysTabControl32, msgNotify


Thanx.

I see that having the dialog minimized is causing a problem.

I'll try stepping thru the code to see what's not getting set.


Howard Kaikow

2005-04-27, 3:55 am

Eureka, I guess that's what Archimedes is reputed to have said!

I see what is the problem.

After using TCM_SETCURSEL and TCN_SELCHANGE, the tab control itelf does
change to identify
the desired tab, but the controls themselves on the tab do not change to
those of the desired tab.

As a result, the subsequent SendMessages to the hWndLockProcect,
hWndPassword and hWndPassword controls do not take effect.

The solution may be to instead use TCM_SETCURFOCUS, seems to work

Private Const TCM_SETCURFOCUS As Long = (TCM_FIRST + 48)


Tom Esh

2005-04-27, 3:55 am

On Tue, 26 Apr 2005 19:52:57 -0400, "Howard Kaikow"
<kaikow@standards.com> wrote:

>Eureka, I guess that's what Archimedes is reputed to have said!
>
>I see what is the problem.
>
>After using TCM_SETCURSEL and TCN_SELCHANGE, the tab control itelf does
>change to identify
>the desired tab, but the controls themselves on the tab do not change to
>those of the desired tab.
>
>As a result, the subsequent SendMessages to the hWndLockProcect,
>hWndPassword and hWndPassword controls do not take effect.
>
>The solution may be to instead use TCM_SETCURFOCUS, seems to work
>
> Private Const TCM_SETCURFOCUS As Long = (TCM_FIRST + 48)


Hmmm... I'm surprised that's necessary, but whatever works :-)


-Tom
MVP - Visual Basic
(please post replies to the newsgroup)
Howard Kaikow

2005-04-27, 3:55 am

THe following is the code I ended up with.
I've run the code using Word 97, Word 2000, Word 2002 and Word 2003.

I used a VB 6 Form. Code might work in a Word VBA Userform, but I have no
interest in running such code from within Word.

Thanx to all who helped.
-----------------------------
3 References are required:

Office object Library
Word object Library
VBA for EXtensibity 5.3 (or equivalent in Word 97)

I expect to post versions of this code for at least Excel and Word at my web
site

Put the following in a code module:

Option Explicit
Public hWndProjectProperties As Long

Public Function EnumChildProc(ByVal hWnd As Long, ByVal lParam As Long) As
Long
hWndProjectProperties = hWnd
' Do not recurse
EnumChildProc = 0
End Function

Put the following in a VB 6 Form with 2 command buttons, as indicated in the
code:

Option Explicit
' Constants for SendMessage messages
Private Const BM_CLICK As Long = &HF5&
Private Const BM_SETCHECK As Long = &HF1&
Private Const BST_CHECKED As Long = &H1&
Private Const EM_REPLACESEL As Long = &HC2&
Private Const KEYEVENTF_EXTENDEDKEY As Long = &H1&
Private Const KEYEVENTF_KEYUP As Long = &H2&
' Needed if dialog is to be minimized in code below
'Private Const SW_SHOWMINIMIZED As Long = 2
Private Const TCM_SETCURFOCUS As Long = &H1330&

' API functions and subs
Private Declare Function EnumChildWindows Lib "user32" _
(ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam 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 GetDlgItem Lib "user32.dll" _
(ByVal hDlg As Long, ByVal nIDDlgItem As Long) As Long

Private Declare Sub keybd_event Lib "user32.dll" _
(ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long,
ByVal dwExtraInfo 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 SetFocusAPI Lib "user32" Alias "SetFocus" _
(ByVal hWnd As Long) As Long

' Needed if dialog is to be minimized
'Private Declare Function ShowWindow Lib "user32" _
' (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long

Private Declare Function VkKeyScan Lib "user32" Alias "VkKeyScanA" _
(ByVal cChar As Byte) As Integer

Private Sub btnByeBye_Click()
Unload Me
End Sub

Private Sub GetPassword(strPassword As String)
' Set password
strPassword = "my"
End Sub

Private Sub KeyBoardSendString(strToSend As String)
' This sub may not handle all character codes correctly
Dim i As Long
Dim VirtualKey As Integer

For i = 1 To Len(strToSend)
VirtualKey = VkKeyScan(Asc(Mid$(strToSend, i, 1))) And &HFF
keybd_event VirtualKey, 0, KEYEVENTF_EXTENDEDKEY, 0 ' key down
keybd_event VirtualKey, 0, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP,
0 ' key up
Next i
End Sub

Private Sub btnCreateTemplate_Click()
' spy++ was used to get Control IDs in Project Properties dialog
Const ControlIDConfirmPassword As Long = &H1556&
Const ControlIDLockProject As Long = &H1557&
Const ControlIDOK As Long = &H1&
Const ControlIDPassword As Long = &H1555&
Const ControlIDSysTabControl32 As Long = &H3020&
Const strProject As String = "HKNewTemplate"

Dim ctrl As Office.CommandBarControl
Dim appWord As Word.Application
Dim docWord As Word.Document
Dim hWndLockProject As Long
Dim hWndPassword As Long
Dim hWndConfirmPassword As Long
Dim hWndOK As Long
Dim hWndSysTabControl32 As Long
Dim strCaption As String
Dim strNewTemplate As String
Dim strPassword As String
Dim strPath As String

Set appWord = New Word.Application
With appWord
.Visible = False
.ScreenUpdating = False
.WindowState = wdWindowStateMinimize

strPath = .Options.DefaultFilePath(wdUserTemplatesPath) &
..PathSeparator
strNewTemplate = strPath & strProject & ".dot"
Set docWord = .Documents.Add(NewTemplate:=True)
With docWord
With .VBProject
' Rename template project
.Name = "HowardKaikowTest"
With .VBE
' Find Project Properties dialog
Set ctrl = .CommandBars.FindControl(ID:=2578)
' Displat Project Properties dialog
ctrl.Execute
Set ctrl = Nothing
End With
strCaption = .Name & " - Project Properties"
End With

' Get hWnd for Project Properties dialog
hWndProjectProperties = FindWindow(vbNullString, strCaption)
If hWndProjectProperties = 0 Then
Exit Sub
End If

GetPassword strPassword
' Get hWnd for OK button in Project Properties dialog
hWndOK = GetDlgItem(hWndProjectProperties, ControlIDOK)
' Get hWnd for Tab Control in Project Properties dialog
hWndSysTabControl32 = GetDlgItem(hWndProjectProperties,
ControlIDSysTabControl32)

'Move to Protection tab
SendMessage hWndSysTabControl32, TCM_SETCURFOCUS, 1, ByVal 0&

' Must reset hWndProjectProperties probably because tab changed.
EnumChildWindows ByVal hWndProjectProperties, AddressOf
EnumChildProc, ByVal 0

' Get hWnd for Password Edit control in Project Properties
dialog
hWndPassword = GetDlgItem(hWndProjectProperties,
ControlIDPassword)
' Get hWnd for Confirm Password Edit control in Project
Properties dialog
hWndConfirmPassword = GetDlgItem(hWndProjectProperties,
ControlIDConfirmPassword)
' Get hWnd for Lock Project checkbox control in Project
Properties dialog
hWndLockProject = GetDlgItem(hWndProjectProperties,
ControlIDLockProject)

' Minimize Project Properties dialog
' May cause problems if done before showing Protection tab
' Anyway, causes problem in Word 97, Word 2000
' Needed if dialog is to be minimized
'ShowWindow hWndProjectProperties, SW_SHOWMINIMIZED

' Lock project for &viewing
SendMessage hWndLockProject, BM_SETCHECK, BST_CHECKED, 0

' &Password
SendMessage hWndPassword, EM_REPLACESEL, vbTrue, ByVal
strPassword

' &Confirm password
SendMessage hWndConfirmPassword, EM_REPLACESEL, vbTrue, ByVal
strPassword

'OK button
SetFocusAPI hWndOK
SendMessage hWndOK, BM_CLICK, 0, 0

On Error Resume Next
Kill strNewTemplate
On Error GoTo 0
.SaveAs strNewTemplate, addtorecentfiles:=False
.Close
End With
.ScreenUpdating = True
.Quit
End With

Set appWord = Nothing
Set docWord = Nothing
btnCreateTemplate.Visible = False
End Sub


Howard Kaikow

2005-04-27, 3:55 am

I forgot to state.

The code will create a template in Word's default template directory.
The password is "my".


Howard Kaikow

2005-04-28, 3:56 am

Although I have not yet found a way to restore the minimized and flashing
icon, I found a way to prevent te Project Properties dialog from being
minimized in the first place.

In the original Word version of the code, Word itself was minimized. Even
so, Word did not minimize the Project Properties dialog.

In the Excel version, apparently Excel does minimize the Project Properties
dialog if Excel is minimized.

Turns out, at this point, it is not necessary to minimize either Word or
Excel, so after pulling the WindowState setting, Excel does not minimize the
dialog.

However, I'd still like to know how to restore such a minimized dialog.
I'll play with that separately later.
--
http://www.standards.com/; See Howard Kaikow's web site


Howard Kaikow

2005-04-30, 3:55 pm

Here's what I ended up with.
It was a difficult birth.

http://www.standards.com/index.html...ProjectPassword


Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com