2010-05-09 88 views
1

我想寫一個文本編輯器並將txt文件分配給它。我的問題是,我想只有一個實例在運行,並且打開一個新文件以將文件名發送到已經運行的第一個應用程序...(我想使用互斥鎖來執行此操作)。這裏是一個小測試在一個應用程序中打開文本文件

DPR看起來像這樣

uses 
    Windows, Messages, SysUtils, 
    Forms, 
    wndMain in 'wndMain.pas' {frmMain}; 

{$R *.res} 

var 
    PrevWindow : HWND; 
    S : string; 
    CData : TCopyDataStruct; 
begin 
    PrevWindow := 0; 
    if OpenMutex(MUTEX_ALL_ACCESS, False, 'MyMutex') <> 0 then 
    begin 
    repeat 
    PrevWindow:=FindWindow('TfrmMain', nil); 
    until PrevWindow<>Application.Handle; 

    if IsWindow(PrevWindow) then 
    begin 
     SendMessage(PrevWindow, WM_SYSCOMMAND, SC_RESTORE, 0); 
     BringWindowToTop(PrevWindow); 
     SetForegroundWindow(PrevWindow); 

     if FileExists(ParamStr(1)) then 
     begin 
      S:=ParamStr(1); 
      CData.dwData:=0; 
      CData.lpData:=PChar(S); 
      CData.cbData:=1+Length(S); 

      SendMessage(PrevWindow, WM_COPYDATA, 0, DWORD(@CData)); 
      end; 
     end; 
    end 
    else 
     CreateMutex(nil, False, 'MyMutex'); 

    Application.Initialize; 
    Application.CreateForm(TfrmMain, frmMain); 
    Application.Run; 
end. 

PAS:

type TfrmMain = class(TForm) 
    memo: TMemo; 
    private 
     procedure WMCopyData (var msg : TWMCopyData) ; message WM_COPYDATA; 
    public 
    procedure OpenFile(f : String); 
end; 

var 
    frmMain: TfrmMain; 

implementation 

{$R *.dfm} 

procedure TfrmMain.WMCopyData (var msg : TWMCopyData) ; 
var 
    f : String; 
begin 
    f:=PChar(msg.CopyDataStruct.lpData); 
    //ShowMessage(f); 
    OpenFile(f); 
end; 

procedure TfrmMain.OpenFile(f : String); 
begin 
    memo.Clear; 
    memo.Lines.LoadFromFile(f); 
    Caption:=f; 
end; 

這段代碼應該沒問題,但如果我想打開一個文本文件(從第二個應用程序)中,第一應用程序接收到一個消息是這樣的:

alt text http://img218.imageshack.us/img218/2175/errorjd.jpg

THA nks

+2

該互斥碼錯誤。始終使用'CreateMutex',而不是'OpenMutex'。而且,'FindWindow'循環沒有意義。如果你的應用程序的標題是「TfrmMain」,那麼這個函數只會返回當前應用程序的窗口句柄,但你爲什麼要爲你的應用程序命名呢?另外,如果'FindWindow' * *會返回你的應用程序的窗口句柄,那麼重複的調用就不會給出不同的答案,因此循環將運行一次,否則它將永遠運行。 – 2010-05-09 20:40:02

回答

0

我懷疑你使用德爾福2009年或2010年德爾福版本的那些使用Unicode字符串,所以Length功能講述了一個字符串的字符數量,而不是數量字節。消息wm_CopyData需要知道要發送的字節數。將字符數乘以2,或者SizeOf(WideChar)

CData.lpData := PWideChar(S); 
CData.cbData := (1+Length(S)) * SizeOf(WideChar); 
+0

只要您不嘗試重複使用非Unicode版本的代碼,就會工作。如果你這樣做,它會打破。最好使用'PChar'和'sizeof(char)',讓編譯器負責解釋。 – 2010-05-10 01:08:28

+0

在這種情況下,我更願意明確說明,因爲我們正在處理進程間通信。雙方需要就有效載荷的大小和格式達成一致。如果一方以Unicode模式編譯,另一方不是編譯,我的代碼將無法編譯,暗示出現問題,而使用PChar的代碼將編譯雙方的查找,但通信在運行時將失敗。 – 2010-05-10 01:50:03

1

這看起來像一個Unicode問題。你可能在D2009或D2010。您需要以字節爲單位給出大小,而不是以字符爲單位。嘗試乘你length呼叫sizeof(char),它應該工作。

+0

+1:這可能會成爲德爾福開發人員未來幾年最常見的錯誤。而不是「SizeOf(Char)」,我建議使用「StringElementSize(StringVariable)」。 – 2010-05-10 12:58:58

相關問題