Что нового

Программа прилипалка для окон.

  • Автор темы VitAl2013
  • Дата начала
V

VitAl2013

Гость
Версия AutoIt: 3.
Любая подходящая

Описание:
Программа организует прилипание окон как в Линуксе, плюс может вытягивать их как в семёрке (по двойному клику в область растягивания)

Примечания:
Если не понятно написал (я уже заметил что меня мало кто понимает :smile: ), то примитивно: Тащим окно за шкирку, подтаскиваем к другому окну. Окно прилипает точно по грани. Окна стыкуются край в край. При попытке вытянуть окно по вертикали подводим мышку в область где курсор меняется на срелки верх-низ, даблкликаем ЛКМом. Окно вытягивается на полную высоту экрана (и вверх и вниз), не меняя своей ширины. Аналогичную опперацию для изменения ширины экрана.
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
VitAl2013
Здесь тоже можно использовать WinMove() плюс отловить событие "Изменение размеров окна" и "Перемещение окна"...

Извините, что предложил неготовое решение...
Не глянул на название раздела...
А идея, может, пригодится...
 
Автор
V

VitAl2013

Гость
Угу... это я её и делать пытаюсь. У гуру получилось бы быстрее и лучше. А может и есть уже такая. Кто заинтересован ждите или делайте сами :smile:
 

wanstein

Новичок
Сообщения
1
Репутация
0
VitAl2013 сказал(а):
Угу... это я её и делать пытаюсь. У гуру получилось бы быстрее и лучше. А может и есть уже такая. Кто заинтересован ждите или делайте сами :smile:
Есть такая програмка для XP, называется WindowSpace (тока Платная), идея реализовать такое проект на AutoIT поддерживаю :ok:
 

Redline

AutoIT Гуру
Сообщения
506
Репутация
369
Вот в архивах нашел скрипт от Creatora - работает только пристыковка к краям рабочего стола
Код:
#include <GUIConstants.au3>
#include <EditConstants.au3>

Global Const $WM_WINDOWPOSCHANGING = 0x0046

Global $nRange = 20

$hGUI = GUICreate("GUI Stickable!", 280, 150)

$Stickable_CB = GUICtrlCreateCheckbox("Stickable?", 20, 30)
GUICtrlSetState(-1, $GUI_CHECKED)

$Range_Input = GUICtrlCreateInput($nRange, 20, 60, 40, 20, $ES_READONLY)
$UpDown = GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 80, 5)

GUISetState()

GUICreate("Some extra window", 320, 180, 0, 0)
GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING")

GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $Stickable_CB
            If GUICtrlRead($Stickable_CB) = $GUI_CHECKED Then
                GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING")
            Else
                GUIRegisterMsg($WM_WINDOWPOSCHANGING, "")
            EndIf
        Case $UpDown
            $nRange = GUICtrlRead($Range_Input)
    EndSwitch
WEnd

Func WM_WINDOWPOSCHANGING($hWnd, $Msg, $wParam, $lParam)
    Local $IsSideWinStick  = True ;Set to True for sticking to all visible windows :) - but it's hangs up CPU :(

    Local $stWinPos        = DllStructCreate("uint;uint;int;int;int;int;uint", $lParam)
    Local $nLeft            = DllStructGetData($stWinPos, 3)
    Local $nTop            = DllStructGetData($stWinPos, 4)

    Local $aCurWinPos      = WinGetPos($hWnd)
    Local $aWorkArea        = _GetWorkingArea()

    ;Left
    If Abs($aWorkArea[0] - $nLeft) <= $nRange Then DllStructSetData($stWinPos, 3, $aWorkArea[0])
    ;Right
    If Abs($nLeft + $aCurWinPos[2] - $aWorkArea[2]) <= $nRange Then DllStructSetData($stWinPos, 3, $aWorkArea[2] - $aCurWinPos[2])
    ;Top
    If Abs($aWorkArea[1] - $nTop) <= $nRange Then DllStructSetData($stWinPos, 4, $aWorkArea[1])
    ;Bottom
    If Abs($nTop + $aCurWinPos[3] - $aWorkArea[3]) <= $nRange Then DllStructSetData($stWinPos, 4, $aWorkArea[3] - $aCurWinPos[3])

    If Not $IsSideWinStick Then Return 0

    Local $ahWnd = WinList()

    For $i = 1 To UBound($ahWnd) - 1
        If $ahWnd[$i][1] = $hWnd Or Not BitAND(WinGetState($ahWnd[$i][1]), 2) Or _
            BitAND(WinGetState($ahWnd[$i][1]), 32) Or BitAND(WinGetState($ahWnd[$i][1]), 16) Then ContinueLoop

        $aSideWinPos = WinGetPos($ahWnd[$i][1])

        If $aCurWinPos[1] + $aCurWinPos[3] >= $aSideWinPos[1] And $aCurWinPos[1] <= $aSideWinPos[1] + $aSideWinPos[3] Then
            ;Left
            If Abs(($aSideWinPos[0] + $aSideWinPos[2]) - $nLeft) <= $nRange Then _
                DllStructSetData($stWinPos, 3, $aSideWinPos[0] + $aSideWinPos[2])

            ;Right
            If Abs($nLeft + $aCurWinPos[2] - $aSideWinPos[0]) <= $nRange Then _
                DllStructSetData($stWinPos, 3, $aSideWinPos[0] - $aCurWinPos[2])
        EndIf

        If $aCurWinPos[0] + $aCurWinPos[2] >= $aSideWinPos[0] And $aCurWinPos[0] <= $aSideWinPos[0] + $aSideWinPos[2] Then
            ;Top
            If Abs(($aSideWinPos[1] + $aSideWinPos[3]) - $nTop) <= $nRange Then _
                DllStructSetData($stWinPos, 4, $aSideWinPos[1] + $aSideWinPos[3])

            ;Bottom
            If Abs($nTop + $aCurWinPos[3] - $aSideWinPos[1]) <= $nRange Then _
                DllStructSetData($stWinPos, 4, $aSideWinPos[1] - $aCurWinPos[3])
        EndIf
    Next

    Return 0
EndFunc

;===============================================================================
;
; Function Name:    _GetWorkingArea()
; Description:      Returns the coordinates of desktop working area rectangle
; Parameter(s):    None
; Return Value(s):  On Success - Array containing coordinates:
;                        $a[0] = left
;                        $a[1] = top
;                        $a[2] = right
;                        $a[3] = bottom
;                  On Failure - 0
;
;BOOL WINAPI SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni);
;uiAction SPI_GETWORKAREA = 48
;===============================================================================
Func _GetWorkingArea()
    Local Const $SPI_GETWORKAREA = 48
    Local $stRECT = DllStructCreate("long; long; long; long")
    Local $SPIRet = DllCall("User32.dll", "int", "SystemParametersInfo", _
                        "uint", $SPI_GETWORKAREA, "uint", 0, "ptr", DllStructGetPtr($stRECT), "uint", 0)
    If @error Then Return 0
    If $SPIRet[0] = 0 Then Return 0

    Local $sLeftArea = DllStructGetData($stRECT, 1)
    Local $sTopArea = DllStructGetData($stRECT, 2)
    Local $sRightArea = DllStructGetData($stRECT, 3)
    Local $sBottomArea = DllStructGetData($stRECT, 4)

    Local $aRet[4] = [$sLeftArea, $sTopArea, $sRightArea, $sBottomArea]
    Return $aRet
EndFunc
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 473
Репутация
2 403
Тот же пример но со значительными улучшениями (например, не прикрепляется к фоновом окнам, только к тем что на видимом фронте :smile: ), я кажется в сети это ещё не выкладывал:

Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
;

Global Const $WM_EXITSIZEMOVE 				= 0x0232
Global Const $SC_MOVE 						= 0xF010
Global Const $SC_SIZE 						= 0xF000

Global $nRange 								= 20
Global $IsSideWinStick 						= False ;True for sticking to all visible windows ( it's hangs up CPU).

$hGUI = GUICreate("GUI Stickable!", 280, 150)
GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")
GUIRegisterMsg($WM_EXITSIZEMOVE, "WM_EXITSIZEMOVE")
GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING")

$Stickable_CB = GUICtrlCreateCheckbox("Stickable (to the screen edges)", 20, 20)
GUICtrlSetState(-1, $GUI_CHECKED)

$StickableToAll_CB = GUICtrlCreateCheckbox("Stickable to all windows (High CPU usage !!!)", 20, 40)

GUICtrlCreateLabel("Stick Range:", 20, 93)
$Range_Input = GUICtrlCreateInput($nRange, 90, 90, 40, 20, $ES_READONLY)
$UpDown = GUICtrlCreateUpdown(-1)
GUICtrlSetLimit(-1, 80, 5)

GUISetState()

GUICreate("Some extra window", 320, 180, 0, 0)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			ExitLoop
		Case $Stickable_CB
			If GUICtrlRead($Stickable_CB) = $GUI_CHECKED Then
				GUIRegisterMsg($WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING")
				GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")
				GUIRegisterMsg($WM_EXITSIZEMOVE, "WM_EXITSIZEMOVE")
			Else
				GUIRegisterMsg($WM_WINDOWPOSCHANGING, "")
				GUIRegisterMsg($WM_SYSCOMMAND, "")
				GUIRegisterMsg($WM_EXITSIZEMOVE, "")
			EndIf
		Case $StickableToAll_CB
			If GUICtrlRead($StickableToAll_CB) = $GUI_CHECKED Then
				$IsSideWinStick = True
			Else
				$IsSideWinStick = False
			EndIf
		Case $UpDown
			$nRange = GUICtrlRead($Range_Input)
	EndSwitch
WEnd

Func WM_WINDOWPOSCHANGING($hWnd, $Msg, $wParam, $lParam)
	Local $stWinPos 		= DllStructCreate("uint;uint;int;int;int;int;uint", $lParam)
	Local $nLeft   			= DllStructGetData($stWinPos, 3)
	Local $nTop    			= DllStructGetData($stWinPos, 4)
	
	Local $aCurWinPos 		= WinGetPos($hWnd)
	Local $aWorkArea 		= _GetWorkingArea()
	
	;Left
	If Abs($aWorkArea[0] - $nLeft) <= $nRange Then DllStructSetData($stWinPos, 3, $aWorkArea[0])
	;Right
	If Abs($nLeft + $aCurWinPos[2] - $aWorkArea[2]) <= $nRange Then DllStructSetData($stWinPos, 3, $aWorkArea[2] - $aCurWinPos[2])
	;Top
	If Abs($aWorkArea[1] - $nTop) <= $nRange Then DllStructSetData($stWinPos, 4, $aWorkArea[1])
	;Bottom
	If Abs($nTop + $aCurWinPos[3] - $aWorkArea[3]) <= $nRange Then DllStructSetData($stWinPos, 4, $aWorkArea[3] - $aCurWinPos[3])
	
	If Not $IsSideWinStick Then Return 0
	
	Local $ahWnd = WinList()
	Local $aStickWinPos, $XPoint, $YPoint
	
	For $i = 1 To UBound($ahWnd) - 1
		If $ahWnd[$i][1] = $hWnd Or Not BitAND(WinGetState($ahWnd[$i][1]), 2) Then ContinueLoop
		
		$aStickWinPos = WinGetPos($ahWnd[$i][1])
		If UBound($aStickWinPos) < 3 Then ContinueLoop
		
		$XPoint = $aStickWinPos[0]+15
		$YPoint = $aStickWinPos[1]+15
		
		If $XPoint < 0 Then $XPoint = 5
		If $YPoint < 0 Then $YPoint = 5
		
		If $aCurWinPos[1] + $aCurWinPos[3] >= $aStickWinPos[1] And $aCurWinPos[1] <= $aStickWinPos[1] + $aStickWinPos[3] Then
			;Left
			If Abs(($aStickWinPos[0] + $aStickWinPos[2]) - $nLeft) <= $nRange And _
				_GetWindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
					DllStructSetData($stWinPos, 3, $aStickWinPos[0] + $aStickWinPos[2])
			
			;Right
			If Abs($nLeft + $aCurWinPos[2] - $aStickWinPos[0]) <= $nRange And _
				_GetWindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
					DllStructSetData($stWinPos, 3, $aStickWinPos[0] - $aCurWinPos[2])
		EndIf
		
		If $aCurWinPos[0] + $aCurWinPos[2] >= $aStickWinPos[0] And $aCurWinPos[0] <= $aStickWinPos[0] + $aStickWinPos[2] Then
			;Top
			If Abs(($aStickWinPos[1] + $aStickWinPos[3]) - $nTop) <= $nRange And _
				_GetWindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
					DllStructSetData($stWinPos, 4, $aStickWinPos[1] + $aStickWinPos[3])
			
			;Bottom
			If Abs($nTop + $aCurWinPos[3] - $aStickWinPos[1]) <= $nRange And _
				_GetWindowFromPoint($XPoint, $YPoint) = $ahWnd[$i][1] Then _
					DllStructSetData($stWinPos, 4, $aStickWinPos[1] - $aCurWinPos[3])
		EndIf
	Next
	
	Return 0
EndFunc

Func WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
	Switch BitAND($wParam, 0xFFF0)
		Case $SC_SIZE, $SC_MOVE
			DllCall("user32.dll", "int", "SystemParametersInfo", "int", 37, "int", 1, "ptr", 0, "int", 2)
	EndSwitch
EndFunc

Func WM_EXITSIZEMOVE($hWnd, $Msg, $wParam, $lParam)
	Local $Old_Show_Content_Param = RegRead("HKEY_CURRENT_USER\Control Panel\Desktop", "DragFullWindows")
	DllCall("user32.dll", "int", "SystemParametersInfo", "int", 37, "int", $Old_Show_Content_Param, "ptr", 0, "int", 2)
EndFunc

Func _GetWindowFromPoint($XPoint, $YPoint)
	Local $aResult = DllCall("User32.dll", "hwnd", "WindowFromPoint", "int", $XPoint, "int", $YPoint)
	Return $aResult[0]
EndFunc

;===============================================================================
;
; Function Name:    _GetWorkingArea()
; Description:      Returns the coordinates of desktop working area rectangle
; Parameter(s):     None
; Return Value(s):  On Success - Array containing coordinates:
;                        $a[0] = left
;                        $a[1] = top
;                        $a[2] = right
;                        $a[3] = bottom
;                   On Failure - 0
;
;BOOL WINAPI SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni);
;uiAction SPI_GETWORKAREA = 48
;===============================================================================
Func _GetWorkingArea()
	Local Const $SPI_GETWORKAREA = 48
	Local $stRECT = DllStructCreate("long; long; long; long")
	
	Local $SPIRet = DllCall("User32.dll", "int", "SystemParametersInfo", _
		"uint", $SPI_GETWORKAREA, "uint", 0, "ptr", DllStructGetPtr($stRECT), "uint", 0)
	If @error Then Return 0
	If $SPIRet[0] = 0 Then Return 0
	
	Local $sLeftArea = DllStructGetData($stRECT, 1)
	Local $sTopArea = DllStructGetData($stRECT, 2)
	Local $sRightArea = DllStructGetData($stRECT, 3)
	Local $sBottomArea = DllStructGetData($stRECT, 4)
	
	Local $aRet[4] = [$sLeftArea, $sTopArea, $sRightArea, $sBottomArea]
    Return $aRet
EndFunc
 
Автор
V

VitAl2013

Гость
Почти то что надо, когда ко всем окнам! Осталось доработать напильником. Не хватает чтоб прилипание было у любого активного окна. И ещё прилипала к продлённым (мысленно) краям (как опцию). Это когда надо выставить 2 и более программы разной высоты в строку, так чтобы их заголовоки (или низ, или бока) были на одном уровне (окна разумеется висят "в воздухе" а не пристыкованы к краю монитоора)

Я не знаю как это организованно у Creator'а (пока не смотрел), но сам поразмыслив над алгоритмом получил примерно следующее:
1. Вычислить края всех видимых окон кроме активного.
2. Сделать из них сетку с позициями... в виде наверно двухмерного массива.
3. Сканировать позицию таскаемого окна.
4. При приближении (значение R) края окна к значениям одного из членов двумерного массива приравнивать их к ближайшим занчениям из него.
5. При протаскивании мышки дальше чем на R после момента прилипания при нажатой ЛКМ отлиплять окно и повторять с начала (с 1).
 
Верх