找回密码
 加入
搜索
查看: 8088|回复: 15

[AU3基础] 如何从自定义函数1的代码执行后退出自定义函数2[已解决]

 火.. [复制链接]
发表于 2011-2-28 08:22:40 | 显示全部楼层 |阅读模式
本帖最后由 m765555 于 2011-3-6 11:33 编辑

请教高手,如何从自定义函数1的代码while 1死循环中执行后退出自定义函数2的while 1死循环?
本工具抛开一些不能被置顶的程序外,目前大概还有两个bug;
1.工具本身无法置顶
2.当置顶某个程序后,然后再关闭被置顶的程序,再点击本工具的置顶按钮,无响应了.(正常情况下有检测提示)
举个例子说下更具体:
   比如用本工具在输入框中输入“qqplayer.exe”,也就是QQ影音播放器,然后点置顶,这样QQ影音就置顶了,问题来了,这时又手动关闭QQ影音,再在输入框中输入“qqplayer.exe”,这时无任何响应了,检测功能失效,经仔细观察:进入“置顶函数”死循环后无法再退出继续操作了。

第一个BUG也是和这个死循环有关系,无法退出造成的。请高手指点一下,谢谢。
#NoTrayIcon
#Include <WinAPI.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#cs
因为无聊,有时候看电影时,又想看下网页,影响看电影,所以写了此工具!本人QQ:76555051 
此工具纯属个人使用,无任何商业用途,用于源码学习,高手莫笑!
#ce
;被置顶的窗口最小最大化使用的开关变量
$my_true_false=True
;隐藏开关变量
$yc=True
$mytitle = "test"
If WinExists($mytitle) Then Exit
AutoItWinSetTitle($mytitle)
;快捷键提示
MsgBox(262144+0,"程序快捷键信息","友情提示:"&@CRLF&@CRLF&"程序自身退出快捷键是:Shift+Alt+d"&@CRLF&@CRLF&"程序自身隐藏显示快捷键是:Alt+q"& @CRLF&@CRLF&"被置顶窗口程序的最小和还原快捷键是:Alt+w")

HotKeySet("+!d", "myexit")  ;Shift-Alt-d  程序退出快捷键
HotKeySet("!q", "yc")   ;Alt-q  程序隐藏显示快捷键
HotKeySet("!w", "jh")   ;Alt-w 程序激活显示快捷键


#Region ### START Koda GUI section ### Form=C:\Documents and Settings\Administrator\桌面\Form1.kxf
$Form1 = GUICreate("程序置顶小工具   by 明兵", 371, 164, 344, 258)
GUISetIcon("F:\au3程序源码(201102月前)\mycom.ico", -1)
$Label1 = GUICtrlCreateLabel("请你输入要置顶的程序的进程名称", 56, 32, 244, 24)
GUICtrlSetFont(-1, 12, 400, 0, "MS Sans Serif")
$Input1 = GUICtrlCreateInput("qqplayer.exe", 64, 80, 137, 21)
GUICtrlSetBkColor(-1, 0xFFFFFF)
$Button1 = GUICtrlCreateButton("置顶程序", 232, 80, 65, 25,0x0001)
$Label2 = GUICtrlCreateLabel("QQ:76555051", 232, 136, 71, 17)
$Label3 = GUICtrlCreateLabel("退出", 328, 136, 28, 17)
GUICtrlSetBkColor(-1, 0x9DB9EB)
GUISetState(@SW_HIDE )
#EndRegion ### END Koda GUI section ###


Global $myjc,$ProcessID,$Process,$mb

GUISetState(@SW_SHOW )
While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit
                Case $Button1
                        jc()
                        
                Case $Label3
                        Exit

        EndSwitch
WEnd


;通过进程的PID获取进程窗口句柄函数
Func _pid_jb($pid)
        Dim $jb = ""
        While $jb = ""
                $win_list = WinList("[REGEXPTITLE:.+]")
                For $i = 1 To $win_list[0][0]
                        If BitAND(WinGetState($win_list[$i][0]), 2) And WinGetProcess($win_list[$i][1], "") = $pid Then $jb = $win_list[$i][1]
                Next
        WEnd
        Return $jb
EndFunc   ;==>pid_jb

;进程检测函数
Func jc()
    If GUICtrlRead($Input1)="" Then
                GUISetState(@SW_HIDE )
        MsgBox(262144+0,"提示","进程不能为空,请重填,谢谢合作!",5)
            GUISetState(@SW_SHOW )
        ElseIf Not ProcessExists(GUICtrlRead($Input1)) Then
        GUISetState(@SW_HIDE )
        
        MsgBox(262144+0,"提示","进程不存在,请打开有关程序后再运行本工具,谢谢合作!",5)
        
        GUICtrlSetData($input1,"")
        GUISetState(@SW_SHOW )
Else
        $Process=GUICtrlRead($Input1)
    $ProcessID = ProcessExists($Process)
    $mb=_pid_jb($ProcessID)
        ;调用置顶函数
    mb()
    EndIf

EndFunc

;将指定程序的窗口置顶函数
Func mb()
While 1
                $hw=_WinAPI_GetForegroundWindow()
                If $hw<>$mb Then
                        _WinAPI_SetWindowPos($hw, -2, 0, 0, 0, 0, 3)

                EndIf
                _WinAPI_SetWindowPos($mb, -1, 0, 0, 0, 0, 3)
                $nMsg = GUIGetMsg()
        Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit
                Case $Label3
                        Exit
        EndSwitch
WEnd
EndFunc

;退出本程序函数
Func myexit()
        Exit
EndFunc

;隐藏与显示本程序函数
Func yc()
        If $yc=True Then
                GUISetState(@SW_HIDE)
                $yc=False
        Else
                GUISetState(@SW_SHOW)
                $yc=True
        EndIf        

EndFunc

;被置顶的程序最小最大化函数
Func jh()
        ;$mm=WinGetHandle("新建 文本文档.txt - 记事本","")

If $my_true_false=True Then
_WinAPI_ShowWindow($mb,@SW_RESTORE)
   $my_true_false=False
ElseIf $my_true_false=False Then
_WinAPI_ShowWindow($mb,@SW_SHOWMINIMIZED)
   $my_true_false=True
EndIf
EndFunc

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×

评分

参与人数 1金钱 +10 收起 理由
afan + 10 感谢主动将修改帖子分类为[已解决],请继续 ...

查看全部评分

发表于 2011-2-28 13:01:41 | 显示全部楼层
回复 1# m765555

有点不懂你的意思,能写个例子吗?

不是这个意思吧?
a()
Func a()
        While 1
                MsgBox(0,0,'第一个循环')
                b()
        WEnd
EndFunc

Func b()
        $i = 1
        While 1
                If $i > 10 Then ExitLoop
                MsgBox(0,0,'第二个循环')
                $i += 1
        WEnd
EndFunc
发表于 2011-2-28 16:18:05 | 显示全部楼层
可以通过设置一个全局变量来传递成么?例如:
Global  $QQ=1
a()

Func a()
        While 1

                MsgBox(0,0,'第一个循环')
                b()
               $QQ=2

        WEnd
EndFunc


Func b()
        $i = 1
        While 1
                If $i > 10 Then ExitLoop
                MsgBox(0,0,'第二个循环')
                $i += 1
               IF  $QQ=2 then ......................
        WEnd
EndFunc
 楼主| 发表于 2011-3-1 08:42:57 | 显示全部楼层
不是的,把源码传给各位兄弟看看就明白了
 楼主| 发表于 2011-3-1 08:53:59 | 显示全部楼层
问题已更新,请各位兄弟看楼顶
发表于 2011-3-1 09:54:51 | 显示全部楼层
结构不好.

mb() 中exit 改成 exitloop 吗?
 楼主| 发表于 2011-3-1 11:41:44 | 显示全部楼层
mb() 中exit 改成 exitloop也没有什么用处呀,一样的效果
发表于 2011-3-1 11:44:22 | 显示全部楼层
回复 5# m765555

Func mb()里面的Switch $nMsg
Switch $nMsg
                        Case $GUI_EVENT_CLOSE
                                Exit
                        Case $Label3
                                Exit
EndSwitch

改成这样就可以了.
Switch $nMsg
                        Case $GUI_EVENT_CLOSE
                                Exit
                        Case $Button1
                                jc()
                        Case $Label3
                                Exit
EndSwitch

评分

参与人数 1金钱 +10 收起 理由
afan + 10

查看全部评分

 楼主| 发表于 2011-3-1 11:49:42 | 显示全部楼层
关键是mb()函数中的窗口置顶必须while 1死循环才能置顶,脚本自身窗口置顶的话就要退出mb()函数中的死循环才行,而且要不影响置顶其它窗口的功能失效。如何解决呢,兄弟们,请教!!!
 楼主| 发表于 2011-3-1 11:55:38 | 显示全部楼层
lixiaolong 兄,加入代码后解决了检测的问题,但alt+w好像没有作用了?
发表于 2011-3-1 14:39:15 | 显示全部楼层
本帖最后由 lixiaolong 于 2011-3-1 14:42 编辑

回复 10# m765555

把Func  mb()改成这样不行吗?
Func mb()
        $hw = _WinAPI_GetForegroundWindow()
        If $hw <> $mb Then
                _WinAPI_SetWindowPos($hw, -2, 0, 0, 0, 0, 3)
        EndIf
        _WinAPI_SetWindowPos($mb, -1, 0, 0, 0, 0, 3)
EndFunc   ;==>mb
我从看了一遍代码以下的代码好像没什么作用,循环好像也不用.
$nMsg = GUIGetMsg()
                Switch $nMsg
                        Case $GUI_EVENT_CLOSE
                                Exit
                        Case $Button1
                                jc()
                        Case $Label3
                                Exit
                EndSwitch
        WEnd

评分

参与人数 1金钱 +15 收起 理由
afan + 15

查看全部评分

 楼主| 发表于 2011-3-1 17:43:17 | 显示全部楼层
呵呵,多谢,解决了,还差一个脚本自身置顶的问题了,慢慢玩
发表于 2011-3-6 15:55:00 | 显示全部楼层
程序逻辑有问题。
你应该按照这样的逻辑来做
1.程序采用事件驱动模式 不要采用消息循环模式。事件驱动中一般只有一个While主循环,不会出现子循环卡住程序流程的情况。
2.程序启动 检测自身设置是否置顶,若置顶,则在While循环中执行置顶操作。
3.点击置顶按钮后,检测输入框中有无信息,无提示错误。有,再次检测输入的程序是否存在,不存在,提示出错。 存在,获取窗体信息,并设置标志位和标志窗体。
4.主循环中检测标志位,如果为置顶标志,还要检测标志窗体是否存在。如果不存在,什么都不做。如果存在则将标志窗体置顶。如果不为置顶标志,什么都不做。
5.将标志窗体置顶之后,再次根据各人习惯设置本程序是否置顶。

评分

参与人数 1贡献 +2 收起 理由
afan + 2

查看全部评分

发表于 2011-3-6 16:51:31 | 显示全部楼层
浪费了点时间给你写个代码, 你瞧瞧吧。

#include <ButtonConstants.au3>
#include <ComboConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1)
;      进程PID  标志窗体标题   标志是否要置顶   窗体列表
Global $Pid="" ,$FlgTitle="",$FlgOnTop=False,$WindowList=""
;      进程列表        列表框数据
Global $ProcessList="",$TempDate=""
        
#Region ### START Koda GUI section ### Form=
$Form = GUICreate("窗口置顶", 162, 102, 192, 144, $WS_SYSMENU)
GUISetOnEvent($GUI_EVENT_CLOSE, "FormClose")
$Combox = GUICtrlCreateCombo("选择进程", 8, 8, 145, 25, BitOR($CBS_DROPDOWNLIST,$CBS_AUTOHSCROLL,$WS_VSCROLL))
GUICtrlSetOnEvent($Combox, "ComboChange")
$ButtonOnTop = GUICtrlCreateButton("置顶", 8, 40, 70, 25)
GUICtrlSetOnEvent(-1, "ButtonOnTopClick")
$ButtonRef = GUICtrlCreateButton("刷新", 78, 40, 70, 25)
GUICtrlSetOnEvent(-1, "ButtonOnRefClick")
ButtonOnRefClick()  ;启动时侯刷新进程列表
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

While 1
        If WinExists($FlgTitle) Then  ;如果目标窗体存在
                If $FlgOnTop=True Then  ;如果置顶标志位为真,
                        WinActivate($FlgTitle)
                        WinSetOnTop($FlgTitle,"",1)
                ElseIf $FlgTitle<>"" Then  ;如果为假,且目标窗体名不为空,则将目标窗体取消置顶并最小化
                        WinSetState($FlgTitle,"",@SW_MINIMIZE)
                        WinSetOnTop($FlgTitle,"",0)
                EndIf
        EndIf
        Sleep(200)
WEnd

Func ButtonOnTopClick()
        $Pid=ProcessExists(GUICtrlRead($Combox))  ;获取列表中的选中进程
        $WindowList=WinList("[REGEXPTITLE:.+]")   ;获取当前窗体列表
        For $i=1 To $WindowList[0][0]   ;遍历当前窗口列表,查找进程的窗口名
                If BitAND(WinGetState($WindowList[$i][0]),2) And $Pid=WinGetProcess($WindowList[$i][0]) Then
                        $FlgTitle=$WindowList[$i][0]  ;设置标志窗口名
                        $FlgOnTop=True                ;设置窗口置顶标志
                        ExitLoop  ;找到后退出循环
                EndIf        
        Next
EndFunc

Func ButtonOnRefClick()  ;刷新按钮
        $ProcessList=ProcessList()  ;重新获取当前进程列表
        For $i=1 To $ProcessList[0][0]   ;将进程列表组成字符串
                $TempDate&=$ProcessList[$i][0]&"|"
        Next
        GUICtrlSetData($Combox,$TempDate)  ;显示到combox框
EndFunc

Func ComboChange()
        $FlgOnTop=False  ;这句的作用是把上次设置的窗口清除置顶
EndFunc

Func FormClose()
        WinSetOnTop($FlgTitle,"",0) ;退出时清除置顶效果
        Exit
EndFunc


评分

参与人数 1金钱 +20 收起 理由
afan + 20

查看全部评分

发表于 2012-3-20 16:24:01 | 显示全部楼层
学习到了 谢谢
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-9-30 17:34 , Processed in 0.131030 second(s), 32 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表