如何恢复一个最小化的视窗?(100分)

  • 主题发起人 主题发起人 peng_qs
  • 开始时间 开始时间
P

peng_qs

Unregistered / Unconfirmed
GUEST, unregistred user!
我想在一个程序第二次运行时,并不执行第二份,而是将先前已经执行的弹出到最前面.<br>如果已经最小化就恢复正常状态.请问哪位高手有此经验?
 
等着我马上给你写个完整的程序
 
算了太多我还是全文贴吧<br><br>------------------------------<br>防止程序被重复执行(第一法)<br><br>Windows95的程序一般都可以重复执行,例如你按下WIN+E组合键即启动资 <br>源管理器,如果再按WIN+E组合键又会出现一个资源管理器,这两个程序互不干 <br>扰。有时候你可以需要制作这样一个程序:当该程序已经执行时,若用户企图 <br>再次执行该程序则只会激活那个已执行的程序,而不是又出现一个副本。 <br>  完成这个目的的核心就是要在程序启动时查找该程序是否已经运行,我曾 <br>试过很多种方法,包括向“全局元素表”(Global ATOM Table)写特定字符串等 <br>等,但最简单的方法还是下面这个: <br><br>在程序启动时将Application的Title特性字段的值暂时改变。 <br>利用Windows API函数FindWindows()查找窗口 <br>恢复Application的Title值 <br><br>  上述步骤一般在主Form的OnCreate事件中实现,示例如下: <br><br>procedure TForm1.FormCreate(Sender: TObject); <br>var <br>ZAppName: array[0..127] of char; <br>Hold: String; <br>Found: HWND; <br>Found: HWND; <br>begin <br>Hold := Application.Title; <br>Application.Title := 'OnlyOne' <br>+ IntToStr(HInstance); // 暂时修改窗口标题 <br>StrPCopy(ZAppName, Hold); // 原窗口标题 <br>Found := FindWindow(nil, ZAppName); // 查找窗口 <br>Application.Title := Hold; // 恢复窗口标题 <br>if Found&lt;&gt;0 then begin <br>// 若找到则激活已运行的程序并结束自身 <br>ShowWindow(Found, SW_RESTORE); <br>Application.Terminate; <br>end; <br>end; <br><br>----------------------------------------<br>防止程序重复执行<br><br><br><br>相关文章:防止程序被重复执行(另一种方法)<br><br><br>  实现单实例运行的关键是判断前一实例是否存在,Win3.x中运行的程序能获知前 <br>一实例的句柄,从而可以方便地进行判断,但 Windows 95 是抢先式多任务系统,其 <br>程序的前一实例句柄恒为零,所以只有另寻其他办法。目前最有效的办法是通过查看 <br>是否有相同窗口类名的例程存在来进行判断。下面介绍在Delphi中实现的方法。 <br><br>1、对主窗口程序的改动: <br><br>在主窗口(即程序创建的第一个窗口)中interface节加入 <br>const <br>CM_RESTORE = WM_USER + $1000; {自定义的“恢复”消息} <br>MYAPPNAME = "My Delphi Program"; <br>并在Form的定义的public节中加入 <br>procedure CreateParams(var Params: TCreateParams); override; <br>Procedure RestoreRequest(var message: TMessage); message CM_RESTORE; <br>在implementation节中加入 <br>{指定窗口名称} <br>procedure TForm1.CreateParams(var Params: TCreateParams); <br>begin <br>inherited CreateParams(Params); <br>Params.WinClassName := MYAPPNAME; <br>end; <br><br>{处理“恢复”消息} <br>procedure TForm1.RestoreRequest(var message: TMessage); <br>procedure TForm1.RestoreRequest(var message: TMessage); <br>begin <br>if IsIconic(Application.Handle) = TRUE then <br>Application.Restore <br>else <br>Application.BringToFront; <br>end; <br><br>经过以上修改,程序的主窗口的类名已经被指定了,这是进行判断的基础。一般在程 <br>序刚开始运行的时候进行判断,所以还要对DPR文件进行修改。 <br><br>2、对DPR文件的改动 <br><br>在 uses 节中添加 windows、messages这两个单元加入下列语句,注意两个文件中常 <br>量CM_RESTORE和MYAPPNAME的定义必须一致 <br>const <br>CM_RESTORE = WM_USER + $1000; {自定义的“恢复”消息} <br>MYAPPNAME = "My Delphi Program"; <br>var <br>RvHandle : hWnd; <br><br>将下列语句插到程序最前部(在Application.Initialize之前) <br><br>RvHandle := FindWindow(MYAPPNAME, NIL); <br>if RvHandle &gt; 0 then <br>begin <br>PostMessage(RvHandle, CM_RESTORE, 0, 0); <br>Exit; <br>end; <br>这段程序的意思是如果找到一个类名相同的窗口,则向该窗口发送一个消息,并退 <br>出,而本例中原窗口收到该消息后会自动激活或从图标还原,从而达到了避免二次运 <br>行且能自动调出前一例程的目的。 <br><br><br><br><br><br><br>
 
程序没有图标化时,仅仅Application.BringToFront; 是不会让窗口跳到最前面的,<br>那样只是flash几下而已<br>应该用下面的函数<br>procedure SetRoreground(hwnd:integer);<br>var<br>&nbsp; ForegroundWin,ForegroundTHreadID:integer;<br>begin<br>&nbsp; ForegroundWin:=GetForegroundWindow;<br>&nbsp; ForegroundTHreadID:=GetWindowThreadProcessID(ForegroundWin,nil);<br>&nbsp; if AttachThreadInput(GetcurrentThreadID,ForegroundTHreadID,True) then<br>&nbsp; begin<br>&nbsp; &nbsp; SetFocus(hwnd);<br>&nbsp; &nbsp; AttachThreadInput(GetCurrentTHreadID,ForegroundTHreadID,False);<br>&nbsp; end<br>end;<br>用SetRoreground(handle);代替上面的Application.BringToFront;
 
多人接受答案了。
 
两位大侠, 为什么我单独做试验用的时候没问题,但是加到我的程序里时执行到<br>&nbsp; ForegroundTHreadID:=GetWindowThreadProcessID(ForegroundWin,nil);<br>&nbsp; 就会报告一个什么"超出范围"的异常.
 
奇怪,在我这里是没问题的,环境:D5,WIN2K
 
我用的也是D5,以前我在做另外一个项目时也考虑过这种切换输入控制权的方法,后来也是因为有时候会发生<br>死机现象而放弃,不知道这种方法是不是不够稳定? 其它很多软件解决这个问题也是用这种方法吗?<br>非常感谢你们的帮助和支持.
 
这个我是在《版主答疑——Delphi高级编程技巧》里看到的,在我的机上试验成功,<br>我就COPY上来了,不知道够不够稳定,呵呵
 
后退
顶部