2022年程序只运行一次并激活原来的程序 .pdf
《2022年程序只运行一次并激活原来的程序 .pdf》由会员分享,可在线阅读,更多相关《2022年程序只运行一次并激活原来的程序 .pdf(16页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、程序只运行一次并激活原来的程序我们的程序有时候只允许运行一次,并且最好的情况是,如果程序第二次运行,就激活原来的程序。网上有很多的方法实现程序只运行一次,但对于激活原来的窗口却都不怎么好。关键就在于激活原来的程序,一般的做法是在工程开始时,打开互斥量对象,如果打不开表示程序还没有运行,创建一个互斥量对象;如果打得开表示程序已经运行了,查找程序中一个特定的窗口,一般是主窗口,然后发送一个自定义消息,主窗口在这个消息处理中激活自己。我原来就是这么做的,却发现有很多问题。主窗口在消息处理函数中激活不了自己,众所周知激活一个窗口最有效的方法当然就是SetForegroundWindow,但在主窗口中调
2、用这个函数激活自己的效果却是只在标题栏闪了一闪,如果在其他进程调用该函数则不会有问题;另外,如果程序是最小化的,它连闪都不闪了。对于这些问题,我想了下面的办法,在知道原程序已经运行后,用FindWindow找原程序主窗口的句柄,找到了,就发送一个自定义消息过去,而在原程序主窗口的消息处理函数中,只是调用Application.Restore方法,这样如果原程序是最小化的就会还原过来。在发送消息之后,紧接着我调用SetForegroundWindow并传入原程序主窗口的句柄,由于上面的处理,原程序肯定不是最小化了,且调用SetForegroundWindow的地方已经不是原程序了(是第二次运行的
3、程序,也可以说是另一个进程),所以原程序可以很好的被激活。看来一切都很好,当然不是,不然就不会有下面的代码了,我又发现了一些问题,首先当主窗体不是活动窗口时,比如主窗体被隐藏了,而目前活动的窗体是其他窗体,则上面的代码无效。另一个,如果主窗体前面有一个ShowModal的窗体,则上面的代码后,主窗体跑到ShowModal窗体的前面了。只有继续探索了,看来问题出在SetForegroundWindow上,激活那个窗体都不好,因为那个窗体都有可能不在,有没有办法激活工程呢,我在Application中找方法,我找到 Application.BringToFront,也许这个有点用,于是新建一个工程
4、,加一个 Timer控件,然后每隔 3 秒调用一次Application.BringToFront,运行看结果。可惜窗体仍然只是闪一下,并没有激活,这和我上面说的在自己进程中激活自己的结果名师资料总结-精品资料欢迎下载-名师精心整理-第 1 页,共 16 页 -一样,可能BringToFront方法里面也调用了SetForegroundWindow了吧,但它激活哪个窗口呢,这让我好奇,打开源码来看,看到了如下有代码:procedure TApplication.BringToFront;var TopWindow:HWnd;beginif Handle 0thenbegin TopWindow
5、:=GetLastActivePopup(Handle);if(TopWindow 0)and (TopWindow Handle)and IsWindowVisible(TopWindow)and IsWindowEnabled(TopWindow)then SetForegroundWindow(TopWindow);end;end;原来是用 GetLastActivePopup这个 API 找到程序拥有的窗体中最近激活的窗体,然后再激活它。哈,我有了一个技术方案,首先我要在第二次运行的程序中找到第一次运行的程序的Application的 Handle,然后调用 SendMessage(A
6、PPHandle,WM_SYSCOMMAND,SC_RESTORE,0),Application类有处理这个消息的,最终它会调用Application.Restore方法,让自己变为显示的状态,即最大化或正常。接着,就执行上面方法中的代码,让第一次运行的程序激活。现在关键是怎么找到第一次运行的Application的 Handle,自然而然就想到了共享内存的技术,程序第一次运行时,先打开一个内存映射文件,如果打不开,则表示程序第一次运行,建一个内存映射文件对象,开辟一块共享的内存,这块内存保存Application的 Handle。程序第二次运行,打开内存映射文件,可以打开了,得到一块共享内存
7、,并取得了第一次运行程序的Application的 Handle,然后,用我上面说的方法,即可大功告成。花了一个小时的试验,最终有了下面的代码,结果非常成功:unit wdRunOnce;名师资料总结-精品资料欢迎下载-名师精心整理-第 2 页,共 16 页 -*brief:让程序只运行一次*autor:linzhenqun*date:2005-12-28*email:*blog:http:/ AppHasRun(AppHandle:THandle):Boolean;implementationuses Windows,Messages;const MapFileName=CAF49BBB-A
8、F40-4FDE-8757-51D5AEB5BBBF;type/共享内存 PShareMem=TShareMem;TShareMem=record AppHandle:THandle;/保存程序的句柄end;var hMapFile:THandle;名师资料总结-精品资料欢迎下载-名师精心整理-第 3 页,共 16 页 -PSMem:PShareMem;procedure CreateMapFile;begin hMapFile:=OpenFileMapping(FILE_MAP_ALL_ACCESS,False,PChar(MapFileName);if hMapFile=0 thenbeg
9、in hMapFile:=CreateFileMapping($FFFFFFFF,nil,PAGE_READWRITE,0,SizeOf(TShareMem),MapFileName);PSMem:=MapViewOfFile(hMapFile,FILE_MAP_WRITE or FILE_MAP_READ,0,0,0);if PSMem=nilthenbegin CloseHandle(hMapFile);Exit;end;PSMem.AppHandle:=0;endelsebegin PSMem:=MapViewOfFile(hMapFile,FILE_MAP_WRITE or FILE_
10、MAP_READ,0,0,0);if PSMem=nilthenbegin CloseHandle(hMapFile);endend;end;名师资料总结-精品资料欢迎下载-名师精心整理-第 4 页,共 16 页 -procedure FreeMapFile;begin UnMapViewOfFile(PSMem);CloseHandle(hMapFile);end;function AppHasRun(AppHandle:THandle):Boolean;var TopWindow:HWnd;begin Result:=False;if PSMem nilthenbeginif PSMem.
11、AppHandle 0 thenbegin SendMessage(PSMem.AppHandle,WM_SYSCOMMAND,SC_RESTORE,0);TopWindow:=GetLastActivePopup(PSMem.AppHandle);if(TopWindow 0)and (TopWindow PSMem.AppHandle)and IsWindowVisible(TopWindow)and IsWindowEnabled(TopWindow)then SetForegroundWindow(TopWindow);Result:=True;endelse PSMem.AppHan
12、dle:=AppHandle;end;end;名师资料总结-精品资料欢迎下载-名师精心整理-第 5 页,共 16 页 -initialization CreateMapFile;finalization FreeMapFile;end.你所要做的,就是将这个单元加进你的程序中,然后在你的工程文件中调用AppHasRun,并传入 Application的 Handle,你的程序就可以只运行一次了,工程大概如下:program Project1;uses Forms,Unit1 inUnit1.pasForm1 wdRunOnce inwdRunOnce.pas,Unit2 inUnit2.pas
13、Form2$R*.resbegin Application.Initialize;ifnot AppHasRun(Application.Handle)then Application.CreateForm(TForm1,Form1);Application.Run;end.多新建一些窗口测试一下吧,不过要注意新建的窗口得不能是自动创建的。名师资料总结-精品资料欢迎下载-名师精心整理-第 6 页,共 16 页 -目前还没有发现什么问题,如果你发现了什么问题,可以在留言中说明,如果你要完整的 Demo 程序,当然可以,Email给我就行了,别告诉我你不知道我的Email,到我的 Blog的首页去
14、找吧。操作系统:Windows 9x 编程工具:delphi4 问题:有些程序可以多个窗口同时运行,如ACCESST 等,请问如果只限定一个窗口运行如何能做到?如何知道程序是否在运行?回答:下面是一个简单的例子,每次程序启动时都判断是否已经有一个实例运行了,如果有就退出。The code for OneInstance.dpr program OneInstance;uses Windows,Forms,Unit1 in Unit1.pas Form1;$R*.RES begin Attempt to create a named mutex CreateMutex(nil,false,MyA
15、pp);if it failed then there is another instance if GetLastError=ERROR_ALREADY_EXISTS then begin Send all windows our custom message-only our other 名师资料总结-精品资料欢迎下载-名师精心整理-第 7 页,共 16 页 -instance will recognise it,and restore itself SendMessage(HWND_BROADCAST,RegisterWindowMessage(MyApp),0,0);Lets quit
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年程序只运行一次并激活原来的程序 2022 程序 运行 一次 激活 原来
限制150内