編程時在同一程序中使用全局變量給我們帶來了很多方便,大多數程序幾乎都離不開全局變量。那麼不同的程序之間呢?我們怎樣在不同的程序(進程)之間共享數據呢?事實上,你可能已經注意到在不同的進程間使用全局變量在有些場合還是很有必要,這是一項相當有用的技術,基於某中特殊情況我們的確需要在我們開發的不同的程序間共享數據。比如有些軟件你會發現安裝後不止一個可執行文件,而且在運行時任務欄也不止出現一個進程,但在使用中你發現不同的進程竟向一個單獨運行程序一樣,效果很好。接下來我們仔細研究一下該技術:
要在不同進程間共享全局變量,應該首先想到我們可以通過不同的進程在內存中的同一塊存儲區域讀取數據,那裡就象一個公共場合一樣,我們把這樣的區域叫做內存映象文件。通過Windows api我們可以很容易的在內存中創建這麼一個區域並輕易的讀取它。這裡需要用到兩個關鍵的api函數:CreateFileMapping和MapVIEwOfFile,前者在內存中創建一個內存映象區,它需要一些參數包括這塊區域的讀寫權限,唯一區域名稱以及數據大小(這些參數將在下面代碼的注釋中給予說明,更多的參數說明請參看win sdk的幫助文件或查看msdn);後者返回一個指向這塊區域的指針以便在程序中調用。下面我們將通過一個簡單的例子來說明,這個例子由兩個工程組成,一個通過一個按紐負責向內存映象區寫入一個長度為11個字符的字符串(‘how are you‘,通過一個edit讀入,如果edit中的字符數大於了11個程序將可能出錯),另一個則通過一個按紐讀出這個字符串,寫入一個edit中。下面是部分的代碼(為了節省篇幅,加上程序很簡單,有些不會影想你閱讀的代碼沒有貼出):
我們首先在第一個工程(窗口取名為SetValue)的單元的接口部分聲明一個指向即將創建的內存區域的句柄和一個用來向這個區域寫數據的指針變量:
var
……
hFileMapping:HWND;//指向內存區域的句柄
SetString:pchar;//這裡應該使用標准的Windows字符串而非Delphi特有的string類型
這樣我們可以在按紐的單擊事件中編寫相應的代碼:
procedure TForm1.Button1Click(Sender: TObject);
begin
hFileMapping:=CreateFileMapping($FFFFFFFF,nil,Page_ReadWrite,0,11,'MapString');
//$FFFFFFFF表示使用虛擬文件,注意兩個工程中應該使用同一個唯一的名稱MapString
if hFileMapping=0 then
raise Exception.Create('Error creating map file!');
SetString:=MapVIEwOfFile(hFileMapping,File_Map_Write,0,0,11);
strcopy(SetString,pchar(Edit1.Text));
//注意這裡應該使用拷貝函數而不是直接賦值 SetString:=pchar(Edit1.Text)
end;
當然,我們還可以在這個主工程中編寫一個釋放內存映象的過程:
procedure TForm1.Button2Click(Sender: TObject);
begin
UnMapVIEwOfFile(SetString);
if hFileMapping<>0 then
closehandle(hFileMapping);
end;
接下來是第2個工程的按紐單擊事件,它和第一個工程幾乎沒有什麼不同,只是我們修改了內存映象的讀取權限為只讀而以:
var
……
GetString:pchar;
hMapFileMaping:HWND;
procedure TForm1.Button1Click(Sender: TObject);
begin
hMapFileMaping:=CreateFileMapping($FFFFFFFF,nil,Page_ReadOnly,0,11,'MapString');
//再次注意一定要使用唯一的名稱(MapString)和第一個工程保持一致
if hMapFileMaping=0 then
raise Exception.Create('Error');
GetString:=MapVIEwOfFile(hMapFileMaping,File_Map_Read,0,0,11);
Edit1.Text:=String(GetString);
end;
現在我們便可以測試了,通過下圖你可以看到測試情況:
當然,上面的程序只是一個例子,沒有任何使用意義,只是為了介紹這種技術,起到拋磚引玉的作用,再實際編程中你可以更嚴格的控制共享變量。你還可以使用這種技術實現一些奇特的效果。關於一些api函數,它們大多都非常復雜,自己也還沒有完全掌握。建議大家在編程中多查看Delphi中的win sdk幫助,裡面相當詳細,一定能幫助大家學到更多的東西。