国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

使用互斥對象讓程序只運行一次

2019-11-18 18:32:19
字體:
來源:轉載
供稿:網友

使用互斥對象讓程序只運行一次

“怎么讓我的程序在運行時不能重復打開?”經常在論壇上看到有朋友問這方面的問題。本文將比較詳細的說明這一問題,并給出一個較為完善的解決方案。
盡管這已經不是一個新問題了,但這里還是簡要的說明一下這種技術:這的確是一個相當有用的技術,可能你經常會注意到相當多的程序在運行之后當你再次點擊運行時,它只是會回到原來的窗口,而不會運行兩個程序。就如同你在運行delphi時,在外部點開另一個工程文件時,delphi只是會簡單的將你的當前工程置換而不是運行兩個delphi。這樣的好處是顯而易見的:你不必擔心你的程序在某些情況下被別的軟件惡意運行多次而吃光內存造成當機。下面我們做進一部的說明:
熟悉win32編程的朋友(特別是多線程編程),相信對互斥對象已經相當熟悉了,它常被用做線程間同步的技術手段。這里我們使用它來防止程序重復運行。我們只是簡要的提一下互斥對象,并不做深入研究:互斥對象把第一次建立它的程序作為主程序,這樣我們只用檢測互斥對象是否已經有主程序就判斷程序是否已經運行過,這里需要涉及到一個api函數:WaitForSingleObject該函數的第一個參數為用以檢測的互斥對象,第2個參數的表示函數返回結果前的滯留時間,如果改函數返回wait_TimeOut就表明互斥對象已經有了一個主程序。修改了的工程文件代碼如下:(注意:以下的代碼都出現在工程文件中,而不是單元文件中,并且這里都在最簡單的delphi默認建立的工程基礎上修改)
var
 myMutex:HWND;
begin
  myMutex:=CreateMutex(nil,false,'hkOneCopy');// CreateMutex建立互斥對象,并且給互斥對象起一個唯一的名字。
  if WaitForSingleObject(myMutex,0)<>wait_TimeOut then//程序沒有被運行過
  begin
   application.Initialize;
   Application.CreateForm(TForm1, Form1);
   Application.Run;
  End;
End;
下面的工作是來完善這個程序,我們不僅希望程序可以不被重復運行,而且我們也希望當用戶再次點擊程序可執行文件時,已經運行的程序能夠做出一些響應。在這里我們希望它能夠變為最上層的活動窗口以提醒用戶程序已經被運行。為了達到這個目的,我們必須先獲得已經運行程序的窗口句柄,以便使用SetForeGroundWindow(handle)來使程序窗口最前并激活。為了得到這個句柄,我們必須使用windows枚舉函數EnumWindows來遍歷windows的窗口列表,該函數可以使用一個回調函數作為參數,并用這個回調函數來對每一個系統中的窗口進行調用直到最后一個窗口或回調函數返回false為止,這個回調函數規定有兩個參數(handle,Cardinal,只用注意第一個handle參數它表示由枚舉函數當前遍歷到的窗口句柄)。我們只要編寫這個函數并在其中不斷的比較當前遍歷到的窗口類名和我們的程序的主窗口類名,以及比較窗口可執行文件的名稱和我們程序的名稱直到找到相同的為止,將這時的窗口句柄保存下來就可以了,下面的代碼加上了適當的注釋:
function EnumWndPRoc(hwnd:Thandle;param:Cardinal):bool;stdcall;
//由于用于api回調函數,請使用windows傳統的參數傳遞方式stdcall
var
 ClassName,WinMoudleName:string;
 WinInstance:THandle;
begin
 result:=true;
 SetLength(ClassName,100);
 GetClassName(hwnd,pchar(ClassName),length(ClassName));//獲得當前遍歷窗口的類名
 ClassName:=pchar(ClassName);//在字符串后加結束符,確定字符串結束
 if ClassName=TForm1.ClassName then//比較
 begin
  WinInstance:=GetWindowLong(hwnd,GWL_HINSTANCE);//獲得當前遍歷窗口的實例
  setlength(WinMoudleName,100);
  GetModuleFileName(WinInstance,pchar(WinMoudleName),length(WinMoudleName));
  //獲得當前遍歷窗口的程序文件名
  WinMoudleName:=pchar(WinMoudleName);
  if WinMoudleName=MoudleName then//MoudleName為工程全局變量,自身程序的文件名
  begin
   FindHid:=hwnd;//FindHid為工程全局變量保存找到的句炳
   result:=false;//找到以后就結束遍歷
  end;
 end;
end;
下面是全部的工程文件:
var
 hMutex,FindHid:HWND;
 MoudleName:string;
begin
  hMutex:=CreateMutex(nil,false,'hkOneCopy');
  if WaitForSingleObject(hMutex,0)<>wait_TimeOut then
  begin
   ……//略去的代碼在前文
  end
  else
  begin
   SetLength(MoudleName,100);
   GetModuleFileName(HInstance,pchar(MoudleName),length(MoudleName));
   //獲得自己程序文件名
   MoudleName:=pchar(MoudleName);
   EnumWindows(@EnumWndProc,0);//調用枚舉函數
   if FindHid<>0 then
    SetForegroundWindow(FindHid);
  end;
end.

上一篇:TListView組件顯示文件夾中的文件

下一篇:使用內存映象實現進程間全局變量

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

主站蜘蛛池模板: 瑞安市| 汤阴县| 明光市| 延吉市| 定陶县| 万荣县| 蒲江县| 昭觉县| 阿克陶县| 甘德县| 东丰县| 四子王旗| 广西| 临沂市| 习水县| 堆龙德庆县| 龙山县| 当涂县| 延庆县| 临沂市| 凤台县| 镇江市| 扬中市| 游戏| 阳谷县| 汶上县| 晋中市| 迁西县| 临沧市| 石狮市| 华蓥市| 锡林浩特市| 富宁县| 天气| 神池县| 恩施市| 罗城| 林州市| 马山县| 旺苍县| 黎城县|