Что нового

[Окна, Диалоги] Как открыть приложение в окне скрипта и привязать к нему ?

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Требуется открыть стороннее приложение в окне GUI .
GUI имеет ряд кнопок сверху.
Требуется при перемещении и изменении размера GUI
обеспечение родительской связи окна приложения с GUI



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

Здесь смотрелhttp://autoit-script.ru/index.php/topic,2251.0.html
Там чистое GUI и заголовок приложения прячется в заголовке GUI


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

У меня есть решение,но не очень корректное :
Код:
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#Include <WinAPI.au3>

Opt('WinTitleMatchMode',2)

$hForm = GUICreate('Test',1400, 800,100,100,$WS_OVERLAPPEDWINDOW, $WS_EX_LAYERED)
GUISetBkColor(0x000001)

GUICtrlCreateLabel("", 0, 0,1400, 25)
GUICtrlSetBkColor(-1, 0xC0C0C0)
GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT)
GUICtrlSetState (-1, $GUI_DISABLE)
$ButTest=GUICtrlCreateButton('Test',10, 0, 40, 25)

_WinAPI_SetLayeredWindowAttributes($hForm , 0x000001)

$sFile=@ProgramFilesDir & "\AutoIt3\AutoIt3.chm" 
$hHelp=RunFile($sFile, "Справка", @SW_SHOW)

GUIRegisterMsg($WM_SIZE, "WM__SIZE")
GUIRegisterMsg($WM_MOVE, "WM__MOVE")
GUISetState(@SW_SHOW, $hForm)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			WinClose($hHelp)
			Exit
	EndSwitch
WEnd

Func RunFile($sRoot, $sTitle, $State=@SW_HIDE)
	ShellExecute($sRoot)
	WinWait ( $sTitle,'',1)
	$hRet=WinGetHandle ( $sTitle)
	$aPos=WinGetPos($hForm)
	WinMove($hRet, '',$aPos[0],$aPos[1]+25,$aPos[2],$aPos[3]-65 )
	Return $hRet
EndFunc

Func WM__SIZE($hWnd, $Msg, $wParam, $lParam)
	Switch $hWnd
		Case $hForm
			$aPos=WinGetPos($hForm)
			WinMove($hHelp, '',$aPos[0],$aPos[1]+25,$aPos[2],$aPos[3]-65 )
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc	;==>WM__SIZE

Func WM__MOVE($hWnd, $Msg, $wParam, $lParam)
	Switch $hWnd
		Case $hForm
			$aPos=WinGetPos($hForm)
			WinMove($hHelp, '',$aPos[0],$aPos[1]+25 )
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc	;==>WM__SIZE
Может кто посоветует что
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Посмотри этот пример с Блокнотом:
Код:
#include <WindowsConstants.au3>

Run('notepad', '', @SW_SHOW)

WinWait('[CLASS:Notepad]')
$hWnd = WinGetHandle("[CLASS:Notepad]")

$WP = WinGetPos($hWnd)
$GUI = GUICreate('Notepad', $wp[2], $wp[3] - 2, $wp[0] - 2, $wp[1] - 25)
GUISetState()

_WinSetStyle($hWnd,  $WS_POPUP, $WS_EX_TOPMOST)

Do
	$NP = WinGetPos($GUI)
	WinMove($hWnd, '', $NP[0] + 3, $NP[1] + 25)
	WinSetOnTop($hWnd, '', 1)
	If GUIGetMsg() = -3 Then ProcessClose('notepad.exe')
	If Not ProcessExists('notepad.exe') Then Exit
Until GUIGetMsg() = -3

Func _WinSetStyle($hWnd, $nStyle = -1, $nExStyle = 0)
    Local Const $GWL_STYLE = -16, $GWL_EXSTYLE = -20
    Local Const $SWP_NOMOVE = 0x2, $SWP_NOSIZE = 0x1, $SWP_SHOWWINDOW = 0x40, $SWP_NOZORDER = 0x4
    Local $iFlags = BitOR($SWP_SHOWWINDOW, $SWP_NOSIZE, $SWP_NOZORDER)

    If $nStyle = -1 Then
        $nStyle = BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU)
    EndIf
    $Pos = WinGetpos($hWnd)
    $x = $Pos[0]
    $y = $Pos[1]

    DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE, "int", $nStyle)
    DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_EXSTYLE, "int", $nExStyle)
    DllCall("User32.dll", "int", "SetWindowPos", "hwnd", $hWnd, "hwnd", 0, "int", $x + 1, "int", $y + 1 , "int", 0, "int", 0, "int", $iFlags)
EndFunc

Func _WinGetStyle($hWnd, $iIndex = 0)
    Local Const $GWL_STYLE = -16, $GWL_EXSTYLE = -20

    Local $iGWL_Index = $GWL_STYLE

    If $iIndex > 0 Then
        $iGWL_Index = $GWL_EXSTYLE
    EndIf

    Local $aStyles = DllCall('User32.dll', 'long', 'GetWindowLong', 'hwnd', $hWnd, 'int', $iGWL_Index)
    Return $aStyles[0]
EndFunc
 
Автор
G

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Zaramot [?]
Посмотри этот пример с Блокнотом:

Я его тоже смотрел,но так и не смог пришить корректно.



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

Вот пример со стилем $WS_POPUP :
Код:
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#Include <WinAPI.au3>

Opt('WinTitleMatchMode',2)

$hForm = GUICreate('Test',1400, 800,100,100,$WS_OVERLAPPEDWINDOW,$WS_EX_CLIENTEDGE)


GUICtrlCreateLabel("", 0, 0,1400, 25)
GUICtrlSetBkColor(-1, 0xC0C0C0)
GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT)
GUICtrlSetState (-1, $GUI_DISABLE)
$ButTest=GUICtrlCreateButton('Test',10, 0, 40, 25)

GUISetState(@SW_SHOW, $hForm)
$sFile=@ProgramFilesDir & "\AutoIt3\AutoIt3.chm" 
$hHelp=RunFile($sFile, "Справка", @SW_SHOW)
_WinSetStyle($hHelp,  $WS_POPUP, $WS_EX_TOPMOST)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			WinClose($hHelp)
			Exit
	EndSwitch
WEnd

Func RunFile($sRoot, $sTitle, $State=@SW_HIDE)
	ShellExecute($sRoot)
	WinWait ( $sTitle,'',1)
	$hRet=WinGetHandle ( $sTitle)
	$aPos=WinGetPos($hForm)
	WinMove($hRet, '',$aPos[0],$aPos[1]+55,$aPos[2],$aPos[3]-65 )
	Return $hRet
EndFunc

Func _WinSetStyle($hWnd, $nStyle = -1, $nExStyle = 0)
    Local Const $GWL_STYLE = -16, $GWL_EXSTYLE = -20
    Local Const $SWP_NOMOVE = 0x2, $SWP_NOSIZE = 0x1, $SWP_SHOWWINDOW = 0x40, $SWP_NOZORDER = 0x4
    Local $iFlags = BitOR($SWP_SHOWWINDOW, $SWP_NOSIZE, $SWP_NOZORDER)

    If $nStyle = -1 Then
        $nStyle = BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU)
    EndIf
    $Pos = WinGetpos($hWnd)
    $x = $Pos[0]
    $y = $Pos[1]

    DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE, "int", $nStyle)
    DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_EXSTYLE, "int", $nExStyle)
    DllCall("User32.dll", "int", "SetWindowPos", "hwnd", $hWnd, "hwnd", 0, "int", $x + 1, "int", $y + 1 , "int", 0, "int", 0, "int", $iFlags)
EndFunc


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

В принципе сам стиль вполне встраивается, но тогда
при попытках привязки окон возникает чехарда
Пробовал выполнить привязку так:
Код:
DllCall("User32.dll", "hwnd", "SetParent", "hwnd", $hHelp, "hwnd", $hForm)
DllCall("User32.dll", "int", "InvalidateRect", "hwnd", $hForm, "int", 0, "int", 0)

Координаты начинают смещаться непонятно как.
Да и от режима "Поверх всех окон" надо избавляться как-то.
 
Автор
G

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Вроде получился более менее приемлемый рез-тат:
Код:
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#Include <WinAPI.au3>

Opt('WinTitleMatchMode',2)

$hForm = GUICreate('Test',1400, 800,100,100,$WS_OVERLAPPEDWINDOW,$WS_EX_CLIENTEDGE)

GUICtrlCreateLabel("", 0, 0,1400, 25)
GUICtrlSetBkColor(-1, 0xC0C0C0)
GUICtrlSetResizing(-1, $GUI_DOCKLEFT+$GUI_DOCKRIGHT+$GUI_DOCKTOP+$GUI_DOCKHEIGHT)
GUICtrlSetState (-1, $GUI_DISABLE)
$ButTest=GUICtrlCreateButton('Test',10, 0, 40, 25)

GUISetState(@SW_SHOW, $hForm)
$sFile=@ProgramFilesDir & "\AutoIt3\AutoIt3.chm" 
$hHelp=RunFile($sFile, "Справка", @SW_SHOW)
$h_Active=$hHelp
_WinSetStyle($h_Active,  $WS_POPUP, $WS_EX_TOPMOST)
WinSetOnTop ($h_Active,'',1)
GUIRegisterMsg($WM_SIZE, "WM__SIZE")
GUIRegisterMsg($WM_MOVE, "WM__MOVE")

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			WinClose($h_Active)
			Exit
	EndSwitch
WEnd

Func RunFile($sRoot, $sTitle, $State=@SW_HIDE)
	ShellExecute($sRoot)
	WinWait ( $sTitle,'',1)
	$hRet=WinGetHandle ( $sTitle)
	$aPos=WinGetPos($hForm)
	WinMove($hRet, '',$aPos[0]+5,$aPos[1]+55,$aPos[2]-15,$aPos[3]-65 )
	Return $hRet
EndFunc

Func _WinSetStyle($hWnd, $nStyle = -1, $nExStyle = 0)
    Local Const $GWL_STYLE = -16, $GWL_EXSTYLE = -20
    Local Const $SWP_NOMOVE = 0x2, $SWP_NOSIZE = 0x1, $SWP_SHOWWINDOW = 0x40, $SWP_NOZORDER = 0x4
    Local $iFlags = BitOR($SWP_SHOWWINDOW, $SWP_NOSIZE, $SWP_NOZORDER)

    If $nStyle = -1 Then
        $nStyle = BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU)
    EndIf
    $Pos = WinGetpos($hWnd)
    $x = $Pos[0]
    $y = $Pos[1]

    DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE, "int", $nStyle)
    DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_EXSTYLE, "int", $nExStyle)
    DllCall("User32.dll", "int", "SetWindowPos", "hwnd", $hWnd, "hwnd", 0, "int", $x + 1, "int", $y + 1 , "int", 0, "int", 0, "int", $iFlags)
EndFunc

Func WM__SIZE($hWnd, $Msg, $wParam, $lParam)
	Switch $hWnd
		Case $hForm
			$aPos=WinGetPos($hForm)
			WinMove($h_Active, '',$aPos[0]+5,$aPos[1]+55,$aPos[2]-15,$aPos[3]-65 )
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc	;==>WM__SIZE

Func WM__MOVE($hWnd, $Msg, $wParam, $lParam)
	Switch $hWnd
		Case $hForm
			$aPos=WinGetPos($hForm)
			WinMove($h_Active, '',$aPos[0]+5,$aPos[1]+55 )
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc	;==>WM__SIZE

Проблема все таки с режимом : WinSetOnTop осталась.
При клике рядом с окном Окно GUI уходит , а окно справки остается.
Если же установить и для GUI $WS_EX_TOPMOST. то
при изменении размера и перемещении оно закрывает окно справки
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Пробовал выполнить привязку так:Код: AutoIt [Выделить]
DllCall("User32.dll", "hwnd", "SetParent", "hwnd", $hHelp, "hwnd", $hForm)
DllCall("User32.dll", "int", "InvalidateRect", "hwnd", $hForm, "int", 0, "int", 0)

Координаты начинают смещаться непонятно как.
Да и от режима "Поверх всех окон" надо избавляться как-то.

Я не стал использовать DLL'ки и взял функцию _WinAPI_SetParent(). Вроде все отлично работает :smile:
Код:
#include <WindowsConstants.au3>
#include <WinAPIEx.au3>

Run('notepad')
WinWait('[CLASS:Notepad]')
$hWnd = WinGetHandle("[CLASS:Notepad]")

$WP = WinGetPos($hWnd)
$GUI = GUICreate('Notepad', $wp[2], $wp[3], $wp[0], $wp[1], $WS_TILEDWINDOW, $WS_EX_LAYERED)
GUISetBkColor(0x000001)
GUISetState()

_WinAPI_SetLayeredWindowAttributes($GUI , 0x000001)
_WinSetStyle($hWnd,  $WS_POPUP, $WS_EX_TOPMOST)
_WinAPI_SetParent($hWnd, $GUI)

Do
	$GUIPos = WinGetPos($GUI)
    WinMove($hWnd, '', 0, 0, $GUIPos[2] - 5, $GUIPos[3] - 30)
    If GUIGetMsg() = -3 Then ProcessClose('notepad.exe')
    If Not ProcessExists('notepad.exe') Then Exit
Until GUIGetMsg() = -3

Func _WinSetStyle($hWnd, $nStyle = -1, $nExStyle = 0)
    Local Const $GWL_STYLE = -16, $GWL_EXSTYLE = -20
    Local Const $SWP_NOMOVE = 0x2, $SWP_NOSIZE = 0x1, $SWP_SHOWWINDOW = 0x40, $SWP_NOZORDER = 0x4
    Local $iFlags = BitOR($SWP_SHOWWINDOW, $SWP_NOSIZE, $SWP_NOZORDER)

    If $nStyle = -1 Then
        $nStyle = BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU)
    EndIf
    $Pos = WinGetpos($hWnd)
    $x = $Pos[0]
    $y = $Pos[1]

    DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE, "int", $nStyle)
    DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_EXSTYLE, "int", $nExStyle)
    DllCall("User32.dll", "int", "SetWindowPos", "hwnd", $hWnd, "hwnd", 0, "int", $x + 1, "int", $y + 1 , "int", 0, "int", 0, "int", $iFlags)
EndFunc

Func _WinGetStyle($hWnd, $iIndex = 0)
    Local Const $GWL_STYLE = -16, $GWL_EXSTYLE = -20

    Local $iGWL_Index = $GWL_STYLE

    If $iIndex > 0 Then
        $iGWL_Index = $GWL_EXSTYLE
    EndIf

    Local $aStyles = DllCall('User32.dll', 'long', 'GetWindowLong', 'hwnd', $hWnd, 'int', $iGWL_Index)
    Return $aStyles[0]
EndFunc
 
Автор
G

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Zaramot [?]
Я не стал использовать DLL'ки и взял функцию _WinAPI_SetParent(). Вроде все отлично работает

Не совсем.
Использование _WinAPI_SetParent() избавило от проблем с режимом "Поверх всех окон"
Это уже хорошо. Спасибо.
Но проблемы возникают при максимизазции окна.
Тем более ты же пробуешь без панельки с доп.кнопкой
Придется использовать $WM_SIZE.

P.S. И еще : То,что работает на Notepad , не корректно работает на других приложениях.
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Но проблемы возникают при максимизазции окна.
Попробуй добавить стиль $WS_EX_COMPOSITED, вроде помогает:
Код:
_WinSetStyle($hWnd,  $WS_POPUP, $WS_EX_TOPMOST + $WS_EX_COMPOSITED)
 
Автор
G

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Zaramot [?]
Попробуй добавить стиль $WS_EX_COMPOSITED, вроде помогает:

Пробовал.
Да при изменении размеров помогает,но возникают проблемы уже при наведении мыши в окнах приложения.
Пришлось отказаться.

Надо Выяснить Почему происходит скачок в координатах приложения, когда происходит присвоение родительской связи.
Хотя почему это-то понятно. Происходит изменение начальных координат.
Вот почему эти скачки иногда проявляются, а иногда нет.?
Если бы были скачки постоянные, от них можно было бы избавиться


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

Извини, но похоже действительно помогает.
Я то ставил этот стиль на GUI окно , а не на окно приложения

Надо потестить .
 
Автор
G

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Вроде бы получилось так :
Код:
#include <WindowsConstants.au3>
#include <GuiConstantsEx.au3>
#include <WinAPIEx.au3>

Opt('WinTitleMatchMode',2)

$hForm = GUICreate('Test',1400, 800,100,100,$WS_OVERLAPPEDWINDOW ,$WS_EX_CLIENTEDGE)
GUISetBkColor(0xc0c0c0)

$ButTest1=GUICtrlCreateButton('Test1',10, 0, 40, 25)

GUISetState(@SW_SHOW, $hForm)

$sFile=@ProgramFilesDir & "\AutoIt3\AutoIt3.chm" 
$h_Help=RunFile($sFile, "Справка",  @SW_SHOW)
$h_Active=$h_Help
GUIRegisterMsg($WM_SIZE, "WM__SIZE")

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			WinClose($h_Active)
			Exit
		Case $ButTest1
	EndSwitch
WEnd

Func RunFile($sRoot, $sTitle, $State=@SW_HIDE)
	ShellExecute($sRoot)
	WinWait ( $sTitle,'',1)
	$hRet=WinGetHandle ( $sTitle)
	_WinSetStyle($hRet,  $WS_POPUP, $WS_EX_TOPMOST+ $WS_EX_COMPOSITED)
	_WinAPI_SetParent($hRet, $hForm)		
	$aPos=WinGetPos($hForm)
	WinMove($hRet, '',0,30,$aPos[2]-10,$aPos[3]-65 )
	If $State=@SW_HIDE Then 
		WinSetState($hRet, '', $State )
	ElseIf  $State=@SW_SHOW Then 
		$h_Active=$hRet
		ConsoleWrite ("$h_Active = " & $h_Active & @LF)
	EndIf
	Return $hRet
EndFunc

Func _WinSetStyle($hWnd, $nStyle = -1, $nExStyle = 0)
    Local Const $GWL_STYLE = -16, $GWL_EXSTYLE = -20
    Local Const $SWP_NOMOVE = 0x2, $SWP_NOSIZE = 0x1, $SWP_SHOWWINDOW = 0x40, $SWP_NOZORDER = 0x4
    Local $iFlags = BitOR($SWP_SHOWWINDOW, $SWP_NOSIZE, $SWP_NOZORDER)

    If $nStyle = -1 Then
        $nStyle = BitOR($WS_MINIMIZEBOX, $WS_CAPTION, $WS_POPUP, $WS_SYSMENU)
    EndIf
    $Pos = WinGetpos($hWnd)
    $x = $Pos[0]
    $y = $Pos[1]

    DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_STYLE, "int", $nStyle)
    DllCall("User32.dll", "int", "SetWindowLong", "hwnd", $hWnd, "int", $GWL_EXSTYLE, "int", $nExStyle)
    DllCall("User32.dll", "int", "SetWindowPos", "hwnd", $hWnd, "hwnd", 0, "int", $x + 1, "int", $y + 1 , "int", 0, "int", 0, "int", $iFlags)
EndFunc

Func WM__SIZE($hWnd, $Msg, $wParam, $lParam)
	Local $iW = BitAND($lParam, 0xFFFF) 
	Local $iH = BitShift($lParam, 16) 
	Switch $hWnd
		Case $hForm
			WinMove($h_Active, '',0,30,$iW,$iH-30)
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc	;==>WM__SIZE
 
Верх