≈※爖※≈ 发表于 2010-4-23 12:03:22

如何限制窗口界面移出屏幕边缘?

比如说屏幕上有个窗口在屏幕上移动位置时,如何限制它不可移出屏幕的边缘?

lxz 发表于 2010-4-23 12:51:36

我也想知道......

zjimmy 发表于 2010-4-23 16:02:51

思路:循环判断窗口的位置,一旦发现超过屏幕,就马上移动回来。

zjimmy 发表于 2010-4-23 17:54:52

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

$Form = GUICreate("My GUI") ; will create a dialog box that when displayed is centered
GUISetState(@SW_SHOW) ; will display an empty dialog box

While 1
        _GUILock($Form)
        $msg = GUIGetMsg()
        If $msg = $GUI_EVENT_CLOSE Then ExitLoop
WEnd

GUIDelete()

Func _GUILock($hGUI)
        Local $aPos = WinGetPos($hGUI), _
                        $iX = $aPos, $iY = $aPos, $iWidth = $aPos, $iHeight = $aPos
        If $iX < 0 Then
                $iX = 0
        ElseIf $iX + $iWidth > @DesktopWidth Then
                $iX = @DesktopWidth - $iWidth
        EndIf
        If $iY < 0 Then
                $iY = 0
        ElseIf $iY + $iHeight > @DesktopHeight Then
                $iY = @DesktopHeight - $iHeight
        EndIf
        WinMove($hGUI, '', $iX, $iY, $iWidth, $iHeight)
EndFunc   ;==>_GUILock

pusofalse 发表于 2010-4-23 18:43:52

#include <StructureConstants.au3>
#include <WindowsConstants.au3>


Local $iWidth = 400, $iHeight = 300
Local $iStyle = BitOR($WS_MINIMIZEBOX, $WS_MAXIMIZEBOX, $WS_SIZEBOX)
$hGUI = GUICreate("Test", $iWidth, $iHeight, -1, -1, $iStyle)
GUISetState()

GUIRegisterMsg(0x216, "WM_MOVING")
GUIRegisterMsg($WM_SIZE, "WM_SIZE")

While GUIGetMsg() <> -3
WEnd

Func WM_SIZE($hWnd, $iMsg, $iwParam, $ilParam)
        $iWidth = BitAnd($ilParam, 0xFFFF)
        $iHeight = BitShift($ilParam, 0x10)
EndFunc        ;==>WM_SIZE

Func WM_MOVING($hWnd, $iMsg, $iwParam, $ilParam)
        Local $tBuffer, $iLeft, $iTop

        $tBuffer = DllStructCreate($tagRECT, $ilParam)
        $iLeft = DllStructGetData($tBuffer, "Left")
        $iTop = DllStructGetData($tBuffer, "Top")
        $iRight = DllStructGetData($tBuffer, "Right")
        $iBottom = DllStructGetData($tBuffer, "Bottom")

        If ($iLeft < 0) Then
                DllStructSetData($tBuffer, "Left", 0)
        ElseIf ($iRight > @DesktopWidth) Then
                DllStructSetData($tBuffer, "Left", @DesktopWidth - $iWidth)
                DllStructSetData($tBuffer, "Right", @DesktopWidth)
        EndIf
        If ($iTop < 0) Then
                DllStructSetData($tBuffer, "Top", 0)
        ElseIf ($iBottom > @DesktopHeight) Then
                DllStructSetData($tBuffer, "Top", @DesktopHeight - $iHeight)
                DllStructSetData($tBuffer, "Bottom", @DesktopHeight)
        EndIf
        $tBuffer = 0
EndFunc        ;==>WM_MOVING

≈※爖※≈ 发表于 2010-4-23 18:52:59

谢谢,就是想这样的效果!!!

zjimmy 发表于 2010-4-23 20:10:36

超版就是超版~~境界不同!

pusofalse 发表于 2010-4-23 20:23:07

回复 7# zjimmy


    - -||| 谢谢赞同,5#的代码只适用于AutoIt自身进程的窗口,对于其他进程,就无能为力了,这是5#的代码缺陷所在。对于外部进程,就不得不使用zjimmy兄的方法了。或者,可以把那个外部程序破解,把自己控制窗口边界的代码嵌入进去,但这个实在太高深,要用到反汇编了,不懂~

myloveqmx 发表于 2010-4-23 20:55:23

以前没注意这个,学习了

lainline 发表于 2010-4-23 21:01:05

本帖最后由 lainline 于 2010-4-23 21:07 编辑

详情参考http://www.autoitx.com/thread-14446-1-1.html;#include <ACC_Const.au3>
$EVENT_SYSTEM_MOVESIZEEND = 0x000B;窗口移动结束事件
Global $hWinEventProc = DllCallbackRegister("WinEventProc", "none", "hwnd;int;hwnd;long;long;int;int");注册回调函数
_Acc_SetWinEventHook($hWinEventProc,$EVENT_SYSTEM_MOVESIZEEND,$EVENT_SYSTEM_MOVESIZEEND);设置“最小化事件”钩子

OnAutoItExitRegister("_Exit");注册退出函数
While 1
        Sleep(200)
WEnd

Func _Exit();退出程序
        _Acc_UnhookWinEvent($hWinEventProc);释放钩子
        Exit
EndFunc

;回调函数
Func WinEventProc($hHook, $iEvent, $hWnd, $idObject, $idChild, $iEventThread, $iEventTime);钩子,事件,句柄,对象,子ID,事件追逐,事件事件
        If $iEvent = $EVENT_SYSTEM_MOVESIZEEND Then
       MsgBox (0,"","窗口移动完成事件")
        EndIf
EndFunc   ;==>WinEventProc

Func _Acc_SetWinEventHook($hWinEvent,$event_start,$event_end,$mode=2);设置事件钩子
    Local $aRet,$modeget
    Local Const $WINEVENT_OUTOFCONTEXT = 0x0
        Local Const $WINEVENT_SKIPOWNTHREAD = 0x1
        Local Const $WINEVENT_SKIPOWNPROCESS = 0x2
        Local Const $WINEVENT_INCONTEXT = 0x4
        Select
                Case $mode=1
                        $modeget=$WINEVENT_OUTOFCONTEXT;0
                Case $mode=2
                        $modeget=$WINEVENT_SKIPOWNTHREAD;1
                Case $mode=3
                        $modeget=$WINEVENT_SKIPOWNPROCESS;2
                Case $mode=4
                        $modeget=$WINEVENT_INCONTEXT;4
                Case $mode=5
                        $modeget=BitOR($WINEVENT_INCONTEXT , $WINEVENT_SKIPOWNTHREAD);5
                Case $mode=6
                        $modeget=BitOR($WINEVENT_INCONTEXT , $WINEVENT_SKIPOWNPROCESS);6
                Case Else
                        $modeget=2
        EndSelect
    $aRet = DllCall("User32.dll", "hwnd", "SetWinEventHook","uint",$event_start, _
                                        "uint", $event_end, "hwnd", 0, "ptr", DllCallbackGetPtr($hWinEvent), _
                                        "int", 0, "int", 0, "uint", $modeget)
        If @error Or $aRet=0 Then Return SetError(1,0,0)
    Return $aRet
EndFunc

Func _Acc_UnhookWinEvent($hHook);解除事件钩子
        DllCall("User32.dll", "int", "UnhookWinEvent", "hwnd", $hHook)
EndFunc

Func _Acc_CoInitializeEx();初始化
        $aRet = DllCall("Ole32.dll", "long", "CoInitializeEx", "ptr", 0, "dword", 2)
EndFunc

pusofalse 发表于 2010-4-23 21:28:22

回复 10# lainline


    请教一下,我下载了lainline兄发表的【Accessible 技术实例集】中的附件,发现其中的API调用中有idispatch*这样一个写法,请教这是什么意思?谢谢~

lainline 发表于 2010-4-23 21:38:49

不清楚呢
例子没吃透
好像是新语法
另外有时RtlMoveMemory 要改成RtlCopyMemory
要不然程序内存会不断增加

lainline 发表于 2010-4-23 21:41:16

看了下帮助
* 传递一个其它类型(添加一个*到末尾.) 例如 "int*" 传递一个指针到 "int" 类型.

pusofalse 发表于 2010-4-23 22:06:09

API调用中,星号*的作用我知道,多数情况下是用于不超过8字节的输出型参数,只是不明白idispatch是什么类型。

lainline 发表于 2010-4-23 22:20:10

搜下帮助里面 com参考里面有大片的英文 没有仔细看应该是com 接口
页: [1] 2
查看完整版本: 如何限制窗口界面移出屏幕边缘?