Что нового

[Элементы GUI] Закрытие GUI по клику в любом месте окна

forc1k

Новичок
Сообщения
42
Репутация
1
Здравствуйте. Как реализовать закрытие GUI по щелчку(левой и/или правой кнопкой) в любом месте GUI?
upd: Напутал с разделом, извиняюсь.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Код:
#include <GUIConstantsEx.au3>

$hGUI = GUICreate("Test Script", 300, 200)
GUISetState(@SW_SHOW, $hGUI)

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE, $GUI_EVENT_PRIMARYUP, $GUI_EVENT_SECONDARYUP
			Exit
	EndSwitch
WEnd
 
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
CreatoR сказал(а):
Код:
#include <GUIConstantsEx.au3>

$hGUI = GUICreate("Test Script", 300, 200)
GUISetState(@SW_SHOW, $hGUI)

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE, $GUI_EVENT_PRIMARYUP, $GUI_EVENT_SECONDARYUP
			Exit
	EndSwitch
WEnd
Спасибо, но GUI закрывается не успев открыться. Я его создаю по вызову функции из основного GUI, т.е. нажатием ЛКМ. Можно реализовать чтобы вызванное GUI сначала создавалось, а уже в созданном окне клик приводил к закрытию?
 

Naisho

Знающий
Сообщения
86
Репутация
12
думаю лучше подойдёт функция
Код:
_WinAPI_WindowFromPoint($Struct)
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Код:
#include <GUIConstantsEx.au3>

$hParent = GUICreate("Parent")
GUISetState(@SW_SHOW, $hParent)

While 1
	$nMsg = GUIGetMsg()

	Switch $nMsg
		Case $GUI_EVENT_PRIMARYUP
			_GUI()
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd

Func _GUI()
	GUISetState(@SW_DISABLE, $hParent)
	
	Local $hGUI = GUICreate("Child", 300, 200, -1, -1, -1, -1, $hParent)
	GUISetState(@SW_SHOW, $hGUI)
	
	While 1
		$aMsg = GUIGetMsg(1)
		
		Switch $aMsg[0]
			Case $GUI_EVENT_CLOSE, $GUI_EVENT_PRIMARYUP, $GUI_EVENT_SECONDARYUP
				If $aMsg[1] = $hGUI Then
					ExitLoop
				EndIf
		EndSwitch
	WEnd
	
	GUISetState(@SW_ENABLE, $hParent)
	GUIDelete($hGUI)
EndFunc
 
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
CreatoR сказал(а):
Код:
#include <GUIConstantsEx.au3>

$hParent = GUICreate("Parent")
GUISetState(@SW_SHOW, $hParent)

While 1
	$nMsg = GUIGetMsg()

	Switch $nMsg
		Case $GUI_EVENT_PRIMARYUP
			_GUI()
		Case $GUI_EVENT_CLOSE
			Exit
	EndSwitch
WEnd

Func _GUI()
	GUISetState(@SW_DISABLE, $hParent)
	
	Local $hGUI = GUICreate("Child", 300, 200, -1, -1, -1, -1, $hParent)
	GUISetState(@SW_SHOW, $hGUI)
	
	While 1
		$aMsg = GUIGetMsg(1)
		
		Switch $aMsg[0]
			Case $GUI_EVENT_CLOSE, $GUI_EVENT_PRIMARYUP, $GUI_EVENT_SECONDARYUP
				If $aMsg[1] = $hGUI Then
					ExitLoop
				EndIf
		EndSwitch
	WEnd
	
	GUISetState(@SW_ENABLE, $hParent)
	GUIDelete($hGUI)
EndFunc
Отличный пример, спасибо.

Naisho сказал(а):
думаю лучше подойдёт функция
Код:
_WinAPI_WindowFromPoint($Struct)
Подошла, спасибо.

Проблема решена.


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

Еще вопрос связанный с этой темой. Gui отлично закрывается при клике на рабочем поле, а вот когда кликаешь на сам GUI, необходимо делать это дважды, с одного клика не срабатывает.
Например на Вашем примере так, CreatoR. И так же на всех других.
Это можно исправить?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Немного переделал пример:

Код:
#include <GUIConstantsEx.au3>

$hParent = GUICreate("Parent")
GUISetState(@SW_SHOW, $hParent)

$hChild = _ChildGUI($hParent)

While 1
	$aMsg = GUIGetMsg(1)
	
	Switch $aMsg[0]
		Case $GUI_EVENT_PRIMARYUP
			Switch $aMsg[1]
				Case $hParent
					GUISetState(@SW_SHOW, $hChild)
				Case $hChild
					GUISetState(@SW_HIDE, $hChild)
			EndSwitch
		Case $GUI_EVENT_CLOSE
			Switch $aMsg[1]
				Case $hParent
					Exit
				Case $hChild
					GUISetState(@SW_HIDE, $hChild)
			EndSwitch
	EndSwitch
WEnd

Func _ChildGUI($hParent)
	Local $hGUI = GUICreate("Child", 300, 200, -1, -1, -1, -1, $hParent)
	
	;...
	
	Return $hGUI
EndFunc


forc1k [?]
когда кликаешь на сам GUI, необходимо делать это дважды, с одного клика не срабатывает.
Речь про область заголовка?

По идее там вообще не должно срабатывать событие. Задержка происходит видимо из за приостановки выполнения скрипта, т.к клик или перетаскивание заголовка окна ставит в приоритет системные события.
Ещё вариант (правда тоже не решает проблему с двойным нажатием):

Код:
#include <GUIConstantsEx.au3>
#include <Misc.au3>
#include <WinAPI.au3>

$hParent = GUICreate("Parent")
GUISetState(@SW_SHOW, $hParent)

$hChild = _ChildGUI($hParent)

While 1
	$aMsg = GUIGetMsg(1)
	
	Switch $aMsg[0]
		Case $GUI_EVENT_CLOSE
			Switch $aMsg[1]
				Case $hParent
					Exit
				Case $hChild
					GUISetState(@SW_HIDE, $hChild)
			EndSwitch
	EndSwitch
	
	If _IsPressed(1) Then
		While _IsPressed(1)
			Sleep(10)
		WEnd
		
		$tPoint = _WinAPI_GetMousePos()
		$hWnd = _WinAPI_WindowFromPoint($tPoint)
		
		Switch $hWnd
			Case $hParent
				GUISetState(@SW_SHOW, $hChild)
			Case $hChild
				GUISetState(@SW_HIDE, $hChild)
		EndSwitch
	EndIf
WEnd

Func _ChildGUI($hParent)
	Local $hGUI = GUICreate("Child", 300, 200, -1, -1, -1, -1, $hParent)
	
	;...
	
	Return $hGUI
EndFunc
 
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
CreatoR сказал(а):
Немного переделал пример:

Код:
#include <GUIConstantsEx.au3>

$hParent = GUICreate("Parent")
GUISetState(@SW_SHOW, $hParent)

$hChild = _ChildGUI($hParent)

While 1
	$aMsg = GUIGetMsg(1)
	
	Switch $aMsg[0]
		Case $GUI_EVENT_PRIMARYUP
			Switch $aMsg[1]
				Case $hParent
					GUISetState(@SW_SHOW, $hChild)
				Case $hChild
					GUISetState(@SW_HIDE, $hChild)
			EndSwitch
		Case $GUI_EVENT_CLOSE
			Switch $aMsg[1]
				Case $hParent
					Exit
				Case $hChild
					GUISetState(@SW_HIDE, $hChild)
			EndSwitch
	EndSwitch
WEnd

Func _ChildGUI($hParent)
	Local $hGUI = GUICreate("Child", 300, 200, -1, -1, -1, -1, $hParent)
	
	;...
	
	Return $hGUI
EndFunc


forc1k [?]
когда кликаешь на сам GUI, необходимо делать это дважды, с одного клика не срабатывает.
Речь про область заголовка?

По идее там вообще не должно срабатывать событие. Задержка происходит видимо из за приостановки выполнения скрипта, т.к клик или перетаскивание заголовка окна ставит в приоритет системные события.
Ещё вариант (правда тоже не решает проблему с двойным нажатием):

Код:
#include <GUIConstantsEx.au3>
#include <Misc.au3>
#include <WinAPI.au3>

$hParent = GUICreate("Parent")
GUISetState(@SW_SHOW, $hParent)

$hChild = _ChildGUI($hParent)

While 1
	$aMsg = GUIGetMsg(1)
	
	Switch $aMsg[0]
		Case $GUI_EVENT_CLOSE
			Switch $aMsg[1]
				Case $hParent
					Exit
				Case $hChild
					GUISetState(@SW_HIDE, $hChild)
			EndSwitch
	EndSwitch
	
	If _IsPressed(1) Then
		While _IsPressed(1)
			Sleep(10)
		WEnd
		
		$tPoint = _WinAPI_GetMousePos()
		$hWnd = _WinAPI_WindowFromPoint($tPoint)
		
		Switch $hWnd
			Case $hParent
				GUISetState(@SW_SHOW, $hChild)
			Case $hChild
				GUISetState(@SW_HIDE, $hChild)
		EndSwitch
	EndIf
WEnd

Func _ChildGUI($hParent)
	Local $hGUI = GUICreate("Child", 300, 200, -1, -1, -1, -1, $hParent)
	
	;...
	
	Return $hGUI
EndFunc
Спасибо за примеры, жаль, что нельзя избавиться от двойного нажатия в области заголовка. Раз нельзя ничего сделать - тему закрываю.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
можно так. срабатывает при единичном клике на любой области или элементе окна
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

$Form1 = GUICreate("Form1", 561, 148, 484, 175)
$Input1 = GUICtrlCreateInput("Input1", 48, 24, 121, 21)
$Label1 = GUICtrlCreateLabel("Label1", 216, 24, 36, 17)
$Button1 = GUICtrlCreateButton("Button1", 64, 72, 75, 25)
$Checkbox1 = GUICtrlCreateCheckbox("Checkbox1", 200, 72, 97, 17)
$Radio1 = GUICtrlCreateRadio("Radio1", 320, 72, 113, 17)
GUISetState(@SW_SHOW)
GUIRegisterMsg($WM_SETCURSOR, "WM_SETCURSOR")

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit

	EndSwitch
WEnd

Func WM_SETCURSOR($hWnd, $Msg, $wParam, $lParam)
If _WinAPI_HiWord($lParam) = 513 Or _WinAPI_HiWord($lParam) = 517 Then Exit
    Return $GUI_RUNDEFMSG
EndFunc


если зарегистрировать функцию WM_SETCURSOR в таком виде
Код:
Func WM_SETCURSOR($hWnd, $Msg, $wParam, $lParam)
If _WinAPI_HiWord($lParam) = 512 Then Exit
    Return $GUI_RUNDEFMSG
EndFunc

то окно будет закрываться при движении мышки в пределах окна, без клика
 
Автор
F

forc1k

Новичок
Сообщения
42
Репутация
1
joiner сказал(а):
можно так. срабатывает при единичном клике на любой области или элементе окна
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

$Form1 = GUICreate("Form1", 561, 148, 484, 175)
$Input1 = GUICtrlCreateInput("Input1", 48, 24, 121, 21)
$Label1 = GUICtrlCreateLabel("Label1", 216, 24, 36, 17)
$Button1 = GUICtrlCreateButton("Button1", 64, 72, 75, 25)
$Checkbox1 = GUICtrlCreateCheckbox("Checkbox1", 200, 72, 97, 17)
$Radio1 = GUICtrlCreateRadio("Radio1", 320, 72, 113, 17)
GUISetState(@SW_SHOW)
GUIRegisterMsg($WM_SETCURSOR, "WM_SETCURSOR")

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit

	EndSwitch
WEnd

Func WM_SETCURSOR($hWnd, $Msg, $wParam, $lParam)
If _WinAPI_HiWord($lParam) = 513 Or _WinAPI_HiWord($lParam) = 517 Then Exit
    Return $GUI_RUNDEFMSG
EndFunc


если зарегистрировать функцию WM_SETCURSOR в таком виде
Код:
Func WM_SETCURSOR($hWnd, $Msg, $wParam, $lParam)
If _WinAPI_HiWord($lParam) = 512 Then Exit
    Return $GUI_RUNDEFMSG
EndFunc

то окно будет закрываться при движении мышки в пределах окна, без клика
Все отлично работает. Вот как это выглядит. За код Огромное Спасибо Joiner
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>
Global $exit = 0, $child
$hParent = GUICreate("Form1", 561, 148, -1, -1)
$Input1 = GUICtrlCreateInput("Input1", 48, 24, 121, 21)
$Label1 = GUICtrlCreateLabel("Label1", 216, 24, 36, 17)
$Button1 = GUICtrlCreateButton("Button1", 64, 72, 75, 25)
$Checkbox1 = GUICtrlCreateCheckbox("Checkbox1", 200, 72, 97, 17)
$Radio1 = GUICtrlCreateRadio("Radio1", 320, 72, 113, 17)
GUISetState(@SW_SHOW, $hParent)

While 1
    If $exit = 1 Then
        $exit = 0
        GUIRegisterMsg($WM_SETCURSOR, "")
        GUIDelete($child)
    EndIf
    $aMsg = GUIGetMsg(1)
    Switch $aMsg[0]
        Case $GUI_EVENT_CLOSE
            Switch $aMsg[1]
                Case $hParent
                    Exit
            EndSwitch
        Case $Button1
            _ChildGUI($hParent)
    EndSwitch
WEnd


Func _ChildGUI($hParent)
    $child = GUICreate("Инфо", 500, 100, -1, -1, -1, -1, $hParent)
    $Label = GUICtrlCreateLabel("Информационное окно" & @CRLF & 'Закрывается при клике мышкой по нему', 24, 16, 300, 90)
    GUISetState(@SW_SHOW, $child)
    GUIRegisterMsg($WM_SETCURSOR, "WM_SETCURSOR")
EndFunc   ;==>_ChildGUI

Func WM_SETCURSOR($hWnd, $Msg, $wParam, $lParam)
    If _WinAPI_HiWord($lParam) = 513 Or _WinAPI_HiWord($lParam) = 517 Then $exit = 1
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_SETCURSOR
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
forc1k,
Предупреждение За нарушение общих правил (пункт В.2):
Старайтесь избегать “Over quoting” (преувеличенное цитирование) - цитируйте только необходимую часть сообщения, которая наилучшим образом подчеркнёт суть цитируемого.


С уважением, ваш Глобальный модератор.
 
Верх