Что нового

Запрет фокуса на элементах gui

DanSaratov

Новичок
Сообщения
112
Репутация
1
Есть GUI, там несколько чекбоксов и 2 кнопки, нужно сделать так, что бы фокус мог быть установлен только на одной из них. Т.е при нажатии стрелочек на клавиатуре мы переключались между этими двумя кнопками.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
Код:
GUICtrlSetState($Button1, $GUI_FOCUS)
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
DanSaratov,
Попробуйте сделать примерно так.
Код:
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <WindowsConstants.au3>

Global $hGui, $iChb_1, $iChb_2, $iBtn_1, $iBtn_2

$hGui = GUICreate('Test', 200, 100)
$iChb_1 = GUICtrlCreateCheckbox('Checkbox 1', 10, 20, 80, 20, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_NOTIFY))
$iChb_2 = GUICtrlCreateCheckbox('Checkbox 2', 110, 20, 80, 20, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_NOTIFY))
$iBtn_1 = GUICtrlCreateButton('Btn 1', 10, 60, 80, 30)
$iBtn_2 = GUICtrlCreateButton('Btn 2', 110, 60, 80, 30)
GUISetState()
GUIRegisterMsg($WM_COMMAND, '_WM_COMMAND')

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd

Func _WM_COMMAND($h_Wnd, $i_Msg, $i_wParam, $i_lParam)
	Switch $h_Wnd
		Case $hGui
			Switch BitShift($i_wParam, 16);code
				Case $BN_SETFOCUS
					Switch BitAND($i_wParam, 0xFFFF);ID
						Case $iChb_1
							GUICtrlSetState($iBtn_1, $GUI_FOCUS)
						Case $iChb_2
							GUICtrlSetState($iBtn_2, $GUI_FOCUS)
					EndSwitch
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_COMMAND


Добавлено:
Сообщение автоматически объединено:

Не самый удачный вариант получился - Checkbox'ы не работают. :(
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Переключение фокуса подразумевает нажатие Tab. Убрать элемент из этой цепочки можно удалением у него стиля WS_TABSTOP.

Код:
#Include <APIConstants.au3>
#Include <GUIConstants.au3>
#Include <WinAPI.au3>

GUICreate('MyGUI', 400, 400)
For $i = 0 to 4
	GUICtrlCreateCheckbox('Checkbox ' & $i, 20, 20 + $i * 24, 100, 21)
	_SetStyle(-1, $WS_TABSTOP, 0)
Next
For $i = 0 To 2
	GUICtrlCreateButton('Button ' & $i, 140, 20 + $i * 30, 80, 23)
Next
GUICtrlSetState(-1, $GUI_FOCUS)
GUISetState()

Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func _SetStyle($hWnd, $iStyle, $fSet, $fExStyle = False, $fUpdate = False)

	Local $Flag, $Style

	If Not IsHWnd($hWnd) Then
		$hWnd = GUICtrlGetHandle($hWnd)
		If Not $hWnd Then
			Return 0
		EndIf
	EndIf
	If $fExStyle Then
		$Flag = $GWL_EXSTYLE
	Else
		$Flag = $GWL_STYLE
	EndIf
	$Style = _WinAPI_GetWindowLong($hWnd, $Flag)
	If $fSet Then
		If BitAND($Style, $iStyle) <> $iStyle Then
			_WinAPI_SetWindowLong($hWnd, $Flag, BitOR($Style, $iStyle))
		EndIf
	Else
		If BitAND($Style, $iStyle) Then
			_WinAPI_SetWindowLong($hWnd, $Flag, BitAND($Style, BitNOT($iStyle)))
		EndIf
	EndIf
	If $fUpdate Then
		_WinAPI_InvalidateRect($hWnd)
	EndIf
	Return 1
EndFunc   ;==>_SetStyle
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Так Checkbox'ы работают, но при нажатии на Tab или на стрелки, их состояние меняется. Побороть этот косяк у меня не получается.
Код:
#include <GUIConstantsEx.au3>
#include <ButtonConstants.au3>
#include <WindowsConstants.au3>

Global $hGui, $iChb_1, $iChb_2, $iBtn_1, $iBtn_2

$hGui = GUICreate('Test', 200, 100)
$iChb_1 = GUICtrlCreateCheckbox('Checkbox 1', 10, 20, 80, 20, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_NOTIFY))
$iChb_2 = GUICtrlCreateCheckbox('Checkbox 2', 110, 20, 80, 20, BitOR($GUI_SS_DEFAULT_CHECKBOX, $BS_NOTIFY))
$iBtn_1 = GUICtrlCreateButton('Btn 1', 10, 60, 80, 30)
$iBtn_2 = GUICtrlCreateButton('Btn 2', 110, 60, 80, 30)
GUICtrlSetState(-1, $GUI_FOCUS)
GUISetState()
GUIRegisterMsg($WM_COMMAND, '_WM_COMMAND')

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $iBtn_1
			MsgBox(64, 'Info', '$iBtn_1 clicked', 0, $hGui)
		Case $iBtn_2
			MsgBox(64, 'Info', '$iBtn_2 clicked', 0, $hGui)
	EndSwitch
WEnd

Func _WM_COMMAND($h_Wnd, $i_Msg, $i_wParam, $i_lParam)
	Switch $h_Wnd
		Case $hGui
			Switch BitShift($i_wParam, 16);code
				Case $BN_SETFOCUS
					Switch BitAND($i_wParam, 0xFFFF);ID
						Case $iChb_1
							GUICtrlSendMsg($iChb_1, $BM_SETCHECK, Not GUICtrlSendMsg($iChb_1, $BM_GETCHECK, 0, 0), 0)
							GUICtrlSetState($iBtn_1, $GUI_FOCUS)
						Case $iChb_2
							GUICtrlSendMsg($iChb_2, $BM_SETCHECK, Not GUICtrlSendMsg($iChb_2, $BM_GETCHECK, 0, 0), 0)
							GUICtrlSetState($iBtn_2, $GUI_FOCUS)
					EndSwitch
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_COMMAND


Добавлено:
Сообщение автоматически объединено:

Yashied [?]
Переключение фокуса подразумевает нажатие Tab. Убрать элемент из этой цепочки можно удалением у него стиля WS_TABSTOP.
А если нажимать на стрелки, то переход на Checkbox'ы все равно происходит.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
madmasles сказал(а):
А если нажимать на стрелки, то переход на Checkbox'ы все равно происходит.

Да это уже грабли. Для выбора фокуса используется Tab, вот ее и нужно нажимать для переключения между элементами GUI. Можно, конечно, написать проверку на стрелки и т.д., но оно нужно?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
У ТС неправильный подход. Если уж очень хочется, то можно разместить все "нежелательные" элементы GUI в дочернем окне без стиля WS_TABSTOP.


Добавлено:
Сообщение автоматически объединено:

Оптимизировать не хочется.

Код:
#Include <APIConstants.au3>
#Include <GUIConstants.au3>
#Include <WinAPI.au3>

GUICreate('MyGUI', 400, 400)
For $i = 0 to 4
    GUICtrlCreateCheckbox('Checkbox ' & $i, 20, 20 + $i * 24, 100, 21)
    _SetStyle(-1, $WS_TABSTOP, 0)
Next
For $i = 0 To 2
    GUICtrlCreateButton('Button ' & $i, 140, 20 + $i * 30, 80, 23)
Next
GUICtrlSetState(-1, $GUI_FOCUS)
$hPrev = GUICtrlGetHandle(-1)
GUISetState()

Do
    $hFocus = _WinAPI_GetFocus()
    If $hFocus <> $hPrev Then
        If Not BitAND(_WinAPI_GetWindowLong($hFocus, $GWL_STYLE), $WS_TABSTOP) Then
            If _Keys() Then
                GUICtrlSetState(_WinAPI_GetDlgCtrlID($hPrev), $GUI_FOCUS)
            EndIf
        Else
            $hPrev = $hFocus
        EndIf
    EndIf
Until GUIGetMsg() = $GUI_EVENT_CLOSE

Func _Keys()
    For $i = 0x25 To 0x28
        If BitAND(_WinAPI_GetAsyncKeyState($i), 0x8000) Then
            Return 1
        EndIf
    Next
    Return 0
EndFunc   ;==>_Keys

Func _SetStyle($hWnd, $iStyle, $fSet, $fExStyle = False, $fUpdate = False)

    Local $Flag, $Style

    If Not IsHWnd($hWnd) Then
        $hWnd = GUICtrlGetHandle($hWnd)
        If Not $hWnd Then
            Return 0
        EndIf
    EndIf
    If $fExStyle Then
        $Flag = $GWL_EXSTYLE
    Else
        $Flag = $GWL_STYLE
    EndIf
    $Style = _WinAPI_GetWindowLong($hWnd, $Flag)
    If $fSet Then
        If BitAND($Style, $iStyle) <> $iStyle Then
            _WinAPI_SetWindowLong($hWnd, $Flag, BitOR($Style, $iStyle))
        EndIf
    Else
        If BitAND($Style, $iStyle) Then
            _WinAPI_SetWindowLong($hWnd, $Flag, BitAND($Style, BitNOT($iStyle)))
        EndIf
    EndIf
    If $fUpdate Then
        _WinAPI_InvalidateRect($hWnd)
    EndIf
    Return 1
EndFunc   ;==>_SetStyle
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied,
Вместо
Код:
GUICtrlSetState(_WinAPI_GetDlgCtrlID($hPrev), $GUI_FOCUS)
ИМХО, лучше использовать
Код:
_WinAPI_SetFocus($hPrev)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
madmasles сказал(а):
Yashied,
Вместо
Код:
GUICtrlSetState(_WinAPI_GetDlgCtrlID($hPrev), $GUI_FOCUS)
ИМХО, лучше использовать
Код:
_WinAPI_SetFocus($hPrev)

Если бы не особенности AutoIt, я бы ее и использовал.
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
DanSaratov [?]
при нажатии стрелочек на клавиатуре мы переключались между этими двумя кнопками
Если элементы объединять в группы, то "стрелочки" будут работать только внутри группы. В то же время Tab'ом можно переходить в соседние группы
Код:
GUICreate('MyGUI', 400, 400)

For $i = 0 to 4
    GUICtrlCreateCheckbox('Checkbox ' & $i, 20, 20 + $i * 24, 100, 21)
Next

GUICtrlCreateGroup("", 0, 0, 1, 1)
For $i = 0 To 2
    GUICtrlCreateButton('Button ' & $i, 140, 20 + $i * 30, 80, 23)
Next
GUICtrlSetState(-1, 256) ; $GUI_FOCUS
GUICtrlCreateGroup("", -99, -99, 1, 1)

GUISetState()

Do
Until GUIGetMsg() = -3
 
Верх