Jump to content
Sign in to follow this  
az2000

Detect tab focus change?

Recommended Posts

az2000

How can I detect that the user went to a different tab? (I am interested in the tab they departed from.).

I searched the forum and found an example of detecting focus change for input fields:

$wProcNew = DllCallbackRegister("_FocusWindowProc", "ptr", "hwnd;uint;long;ptr")
$wProcOld = _WinAPI_SetWindowLong(GUICtrlGetHandle($cInput), $GWL_WNDPROC, DllCallbackGetPtr($wProcNew))

But, that uses GUICtrlGetHandle. It doesn't seem like tab *items* have a handle.

Could someone point me in the right direction?

Thanks

Share this post


Link to post
Share on other sites
nguyenbason

GuiCtrlRead($Tab) will return index of selected tab (0,1,2,....)


UnderWorldVN- Just play the way you like it

Share this post


Link to post
Share on other sites
az2000

GuiCtrlRead($Tab) will return index of selected tab (0,1,2,....)

Thanks. But, I want to be notified when the tab focus changes (the user left the tab).

I think I know how to do that using the dll example. But, it requires a control handle which doesn't seem to be available for tab items.(?)

Share this post


Link to post
Share on other sites
az2000

; Get handle to Tab control
$hTab = ControlGetHandle($hWnd, "", "SysTabControl321")
If @error Then _Exitonerror("Failed to get handle to TAB control.")
Tab "items" are what I can't get a handle to. I believe your example only returns the handle to the Tab control (not the Tab items within it).

I have something partially working with GUIRegisterMsg using system message 0x0008 (kill focus). It calls my registered function when I change tabs after changing data in any control on the tab item.

But, I don't know how to determine which tab item it is losing focus from. I'll post an example shortly.

Mark

Share this post


Link to post
Share on other sites
nguyenbason

Why don't you write a variable that store current selected index tab, then when new tab is selected you did something with it and change value to new tab index?


UnderWorldVN- Just play the way you like it

Share this post


Link to post
Share on other sites
DCCD

While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    If $msg = $tab Then
        ; display the clicked tab
        If GUICtrlRead($tab) = 0 Then WinSetTitle("My GUI Tab", "", "My GUI Tab0")
        If GUICtrlRead($tab) = 1 Then WinSetTitle("My GUI Tab", "", "My GUI Tab1")
        If GUICtrlRead($tab) = 2 Then WinSetTitle("My GUI Tab", "", "My GUI Tab2")
    EndIf
WEnd

Share this post


Link to post
Share on other sites
az2000

While 1
    $msg = GUIGetMsg()

    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    If $msg = $tab Then
        ; display the clicked tab
        If GUICtrlRead($tab) = 0 Then WinSetTitle("My GUI Tab", "", "My GUI Tab0")
        If GUICtrlRead($tab) = 1 Then WinSetTitle("My GUI Tab", "", "My GUI Tab1")
        If GUICtrlRead($tab) = 2 Then WinSetTitle("My GUI Tab", "", "My GUI Tab2")
    EndIf
WEnd

I need to know when the user *LEAVES* a tab item. I don't need to know when they arrived on a tab item.

Also, I'm using "onEvent" mode. I can't poll the GUI trying to track the user's movements.

The following works somewhat. The "WM_KILLFOCUS" message works perfectly. I'm notified when the user left a *control* (with changed data) on the tab item. But, I can't figure out how to determine which control triggered the message.

The "WM_MESSAGE" message tells me which control triggered the message. But, it triggers for a lot of other stuff too. I just want WM_KILLFOCUS.

This gives me an idea that maybe I could go back to the DLL example I found and setup events for all the controls on each tab item. Maybe that would tell me the same thing as WM_KILLFOCUS. But, I'd know which control caused it.

#include <GuiConstants.au3>

Opt('GUIOnEventMode', 1); Event mode, not message mode.

; This reports only killfocus events, but I don't know how to determine
; the control that caused the event.
;Global Const $WM_KILLFOCUS = 0x0008; killfocus event

; Or, use this. It seems to report more events. The $nID bits indicate 
; if it was a set focus or kill focus.
Global Const $WM_COMMAND = 0x0111; wmcommand events?
Global Const $EN_SETFOCUS = 0x100
Global Const $EN_KILLFOCUS = 0x200


_Main()

;*********************************************************************
;*********************************************************************
Func _Main()

Global $hWnd, $tab, $tab0, $tab0OK, $tab0input
Local $tab1, $tab1combo, $tab1OK
Local $tab2, $tab2OK, $msg

$hWnd = GUICreate("My GUI Tab") 

GUISetBkColor(0x00E0FFFF)
GUISetFont(9, 300)

$tab = GUICtrlCreateTab(10, 10, 200, 100)

$tab0 = GUICtrlCreateTabItem("tab0")
GUICtrlCreateLabel("label0", 30, 80, 50, 20)
$tab0OK = GUICtrlCreateButton("OK0", 20, 50, 50, 20)
$tab0input = GUICtrlCreateInput("default", 80, 50, 70, 20)

$tab1 = GUICtrlCreateTabItem("tab----1")
GUICtrlCreateLabel("label1", 30, 80, 50, 20)
$tab1combo = GUICtrlCreateCombo("", 20, 50, 60, 120)
GUICtrlSetData(-1, "Trids|CyberSlug|Larry|Jon|Tylo", "Jon"); default Jon
$tab1OK = GUICtrlCreateButton("OK1", 80, 50, 50, 20)

$tab2 = GUICtrlCreateTabItem("tab2")
GUICtrlSetState(-1, $GUI_SHOW) ; will be display first
GUICtrlCreateLabel("label2", 30, 80, 50, 20)
$tab2OK = GUICtrlCreateButton("OK2", 140, 50, 50)

GUICtrlCreateTabItem("") ; end tabitem definition

GUISetState()
;GUIRegisterMsg($WM_KILLFOCUS, "MY_KILLFOCUS")
GUIRegisterMsg($WM_COMMAND, "MY_WMCOMMAND")


While 1
    Sleep(5000); or, change the eventMode, comment out this line, and decomment the following.
;   Switch GUIGetMsg()
;       Case $ExitButton, $GUI_EVENT_CLOSE; You'll need to add an exit button to the form.
;       ExitLoop
;   EndSwitch
    WEnd
EndFunc  ;==>_Main


;*********************************************************************
;*********************************************************************
Func MY_KILLFOCUS($hWnd, $msg, $wParam, $lParam)
    
Local $nNotifyCode = BitShift($wParam, 16); high word
Local $nID = BitAND($wParam, 0xFFFF); low word
Local $hCtrl = $lParam

MsgBox(64, "In MY_KILLFOCUS", '$nID=' & $nID)


; Proceed the default Autoit3 internal message commands.
; You also can complete let the line out.
; !!! But only 'Return' (without any value) will not proceed
; the default Autoit3-message in the future !!!
Return $GUI_RUNDEFMSG

EndFunc  ;==>MY_WM_COMMAND



;*********************************************************************
;*********************************************************************
Func MY_WMCOMMAND($hWnd, $msg, $wParam, $lParam)
    
Local $nNotifyCode = BitShift($wParam, 16); high word
Local $nID = BitAND($wParam, 0xFFFF); low word
Local $hCtrl = $lParam

If $nNotifyCode = $EN_KILLFOCUS Then

    MsgBox(64, "In MY_WMCOMMAND with killfocus message", '$nID=' & $nID)

EndIF


; Proceed the default Autoit3 internal message commands.
; You also can complete let the line out.
; !!! But only 'Return' (without any value) will not proceed
; the default Autoit3-message in the future !!!
Return $GUI_RUNDEFMSG

EndFunc  ;==>MY_WM_COMMAND

Mark

Share this post


Link to post
Share on other sites
az2000

Also, browsing the TabConstants.au3 I see a section called "Notifications" containing the following:

Global Const $TCN_FOCUSCHANGE = ($TCN_FIRST - 4)

That sounds like what I want. But, I don't know where I would use it.

Mark

Share this post


Link to post
Share on other sites
az2000

This gives me an idea that maybe I could go back to the DLL example I found and setup events for all the controls on each tab item. Maybe that would tell me the same thing as WM_KILLFOCUS. But, I'd know which control caused it.

Just a follow up. What I described is working well. I register the controls on each tab using the DLL shown in my first post. In the registered function, I can

1) tell that it was called because the control lost focus,

2) which control caused it,

3) I know which tab that control is on

4) I can determine if the focus loss was due to the user clicking on a different control on the same tabItem, or going to a different tabItem. If the user clicked a different tabItem, GUICtrlRead($tab) will return that tabItem number (or controlID). I can compare this with what I know from #3.

I like this better than WM_FOCUSKILL or WM_MESSAGE (with the registerMsg function). That called my registered function for every control on the GUI. The DLL lets me specify which controls I want to receive messages for. This is useful if I'm only concerned that a user would lose changes to a text control by going to a different tab before "applying" the change. I can keep them on the tab and prompt them to confirm abandoning changes.

I'll update this thread with an example later.

Edited by az2000

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.