2010-05-09 91 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

相关问题