[How To] Implement Tabstop for ActiveX > Shell.Explorer

Helpful script writing tricks and HowTo's
User avatar
SKAN
Posts: 311
Joined: 29 Sep 2013, 16:58

[How To] Implement Tabstop for ActiveX > Shell.Explorer

04 Dec 2013, 18:17

Greetings :)

When we create a GUI with Edit, Button and ActiveX Shell.Explorer control, the TAB navigation is restricted to Edit & Button controls. We have to manually mouse click the WebControl before we can perform any key strokes on it

The following is ClassNN list for a above like GUI:

Code: [Select all] [Download] (Script1.ahk)GeSHi © Codebox Plus

Edit1  ( WS_TABSTOP )
Button1 ( WS_TABSTOP )
AtlAxWin1
Shell Embedding1 ( WS_TABSTOP )


The "Shell Embedding" is styled WS_TABSTOP, but being child of "AtlAxWin", it is unable to participate in overall GUI TAB navigation.
Any attempt to style AtlAxWin with WS_TABSTOP will result in appcrash.

The correct way of enabling "Shell Embedding" to participate in TAB navigation is to style its parent AtlAxWin with WS_EX_CONTROLPARENT

WS_EX_CONTROLPARENT 0x00010000L ( E0x10000 ) MSDN: goo.gl/8TsQaK
The window itself contains child windows that should take part in dialog box navigation.
If this style is specified, the dialog manager recurses into children of this window when
performing navigation operations such as handling the TAB key, an arrow key, or a keyboard
mnemonic.

Once an URL is loaded into Shell.Explorer object, additional child controls are created and ClassNN list will be:

Code: [Select all] [Download] (Script2.ahk)GeSHi © Codebox Plus

Edit1  ( WS_TABSTOP )
Button1 ( WS_TABSTOP )
AtlAxWin1
Shell Embedding1
Shell DocObject View1 ( WS_TABSTOP )
Internet Explorer_Server1


From above we see that Tabstop now belongs to "Shell DocObject View".
Attempts to transfer Tabstop to "Internet Explorer_Server1" does not enable it to receive focus.
Also, I checked IE 10. the above lying "Internet Explorer_Server1" is not styled WS_TABSTOP

The workaround I am suggesting/using is to detect when "Shell DocObject View" receives the focus, and transfer it immediately ( with ControlFocus ) to it child "Internet Explorer_Server"

We already have to handle WM_KEYDOWN & WM_KEYUP message for calling IOleInPlaceActiveObject::TranslateAccelerator method.
Placing the following code along, inside the OnMessage handler should be sufficient.

Code: [Select all] [Download] (Script.ahk)GeSHi © Codebox Plus

  If ( ClassName = "Shell DocObject View" && wParam = 0x09 ) {
WinGet, hIES, ControlListHwnd, ahk_id %hWnd% ; List children of 'Shell DocObject View'
ControlFocus,, ahk_id %hIES%
Return 0
}


The above snippet detects if "Shell DocObject View" receives TAB key and sets the focus to its only child, which will be "Internet Explorer_Server"

That should be it, and should serve most of the needs... but,
If you open a webpage like http://ip.ahk4.me/ in any browser, you can immediately use Ctrl+A to select all text.
But the suggested implementation is not enough. The control will have focus but not any elements to focus on. Depending on needs one could use ControlClick instead of ControlFocus, but it will clear any selection already been made in the web content.

The correct way to handle these, would be to handle it in DocumentComplete() event. I do know more on the subject but it will be like testing all frames and whether it has elements (enabled & visible) and set focus accordingly. If it does not have any, as the case with http://ip.ahk4.me/, one may use WB.Document.Body.Focus() to ready the document for Select All (Ctrl+A).

Example code ( adapted from Doc and rest of forum ):

Code: [Select all] [Expand] [Download] (Script.ahk)GeSHi © Codebox Plus



Experts may please edit this topic as they seem fit.
User avatar
tank
Posts: 2334
Joined: 28 Sep 2013, 22:15
Facebook: charlie.simmons.7334
Google: ttnnkkrr
GitHub: ttnnkkrr
Location: Louisville KY
Contact:

Re: [How To] Implement Tabstop for ActiveX > Shell.Explorer

04 Dec 2013, 18:40

Love the tut and I learned from it. But I love the ascii art
We are troubled on every side‚ yet not distressed; we are perplexed‚
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
https://www.facebook.com/ahkscript.org
If you have forum suggestions please submit a pull request
User avatar
SKAN
Posts: 311
Joined: 29 Sep 2013, 16:58

Re: [How To] Implement Tabstop for ActiveX > Shell.Explorer

04 Dec 2013, 19:11

tank wrote:I love the ascii art

Me too.. and looks even better when displayed non-italicized

Code: [Select all] [Download] (Script.ahk)GeSHi © Codebox Plus

Thanks to tank for
__ __ __ __ __ __ __ _ __
/ /_ / /_/ /_____ _ / // /____ _/ /_ / /________________(_)___ / /_ ____ _______
/ __ \/ __/ __/ __ \(_) // // __ '/ __ \/ //_/ ___/ ___/ __/ / __ \/ __// __ \/ __/ _ \
/ / / / /_/ /_/ /_/ / / // // /_/ / / / / ,< (__ ) /__/ / / / /_/ / /__/ /_/ / / / // /
/_/ /_/\__/\__/ .___(_) // / \__,_/_/ /_/_/|_/____/\___/_/ /_/ .___/\__(_)____/_/ \__ /
/_/ /_//_/ /_/ (___/

"the freedom site"


:)
tmplinshi
Posts: 1242
Joined: 01 Oct 2013, 14:57

Re: [How To] Implement Tabstop for ActiveX > Shell.Explorer

03 Jan 2014, 12:46

Thank you, very helpful.
User avatar
jethrow
Posts: 183
Joined: 30 Sep 2013, 19:52
Location: Iowa

Re: [How To] Implement Tabstop for ActiveX > Shell.Explorer

25 Feb 2014, 02:14

Please confirm - the following is all that would need updated to make this 32bit/64bit compatible:

Code: [Select all] [Download] (Script.ahk)GeSHi © Codebox Plus

;~ Original:
TranslateAccelerator := NumGet( NumGet( pipa+0 ) + 20 )

;~ Updated:
TranslateAccelerator := NumGet( NumGet( pipa+0 ) + 5*A_PtrSize )

Code: [Select all] [Download] (Script.ahk)GeSHi © Codebox Plus

;~ Original
VarSetCapacity( MSG, 28, 0 ) ; MSG STructure http://goo.gl/4bHD9Z
Loop, Parse, Vars, |, %A_Space%
NumPut( %A_LoopField%, MSG, ( A_Index-1 ) * 4 )

;~ Updated:
VarSetCapacity( MSG, 48, 0 ) ; MSG STructure http://goo.gl/4bHD9Z
Loop, Parse, Vars, |, %A_Space%
NumPut( %A_LoopField%, MSG, ( A_Index-1 ) * A_PtrSize )
jballi
Posts: 492
Joined: 29 Sep 2013, 17:34

Re: [How To] Implement Tabstop for ActiveX > Shell.Explorer

24 Oct 2015, 00:14

Old thread but this is as good of a place as any to post this.

Based upon the research posted in this and other threads, I created a stand-alone method of giving input focus to a web browser control. Results appear to be consistent after the web browser control has been rendered, i.e. the parent window is showing, and after the web browser control is loaded, i.e. the ReadyState method returns a READYSTATE_LOADED value. Before that... not so much.

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus


I haven't done much testing but it's working so far. If you find any problems or if you have any improvements, post it!

Return to “Tutorials”

Who is online

Users browsing this forum: FatCatsUnite and 2 guests