2010-05-09 4 views
1

텍스트 편집기를 작성하고 txt 파일을 지정하려고합니다. 내 문제는 하나의 인스턴스를 실행하고 이미 실행중인 첫 번째 응용 프로그램에 파일 이름을 보내도록 새 파일을 열 때 ... (뮤텍스를 사용하여이 작업을 수행하려고합니다). 여기하나의 응용 프로그램에서 텍스트 파일 열기

조선 민주주의 인민 공화국이

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

그쪽 nks

+2

해당 뮤텍스 코드가 잘못되었습니다. 'OpenMutex'가 아닌'CreateMutex'를 항상 사용하십시오. 또한,'FindWindow' 루프는 무의미합니다. 이 함수는 응용 프로그램의 제목이 "TfrmMain"인 경우에만 현재 응용 프로그램의 창 핸들을 반환하지만 응용 프로그램의 이름을 지정하는 이유는 무엇입니까? 게다가'FindWindow' *가 응용 프로그램의 윈도우 핸들을 반환하면 반복 호출은 다른 응답을주지 않으므로 루프는 정확히 한 번 실행되거나 영원히 실행됩니다. –

답변

0

난 당신이 델파이 2009 델파이 2010 년 그 버전 사용 유니 코드 문자열을 사용하는 의심 때문에 Length 함수는 문자열에 문자의 개수를 알 수 있지만 수 바이트. wm_CopyData 메시지는 전송할 바이트 수를 알아야합니다. 문자 수에 2를 곱하시오. SizeOf(WideChar).

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

유니 코드가 아닌 버전에서 코드를 다시 사용하지 않는 한 작동합니다. 네가 그렇게한다면, 그것은 깨질 것이다. 'PChar'와'sizeof (char)'를 사용하고 컴파일러가 해석하도록하십시오. –

+0

이 경우에는 프로세스 간 통신을 다루기 때문에 명시 적으로 지정하는 것을 선호합니다. 양측은 탑재 물의 ​​크기와 형식에 관해 동의 할 필요가있다. 한 쪽이 유니 코드 모드로 컴파일되고 다른 쪽이 컴파일되지 않으면 내 코드가 컴파일되지 않아 뭔가 잘못되었다는 것을 암시하는 반면 PChar를 사용하는 코드는 양쪽 모두에서 컴파일을 컴파일하지만 런타임에 통신이 실패합니다. –

1

이것은 유니 코드 문제처럼 보입니다. 아마도 D2009 또는 D2010에있을 것입니다. Chaaracter가 아니라 크기를 바이트로 지정해야합니다. length 전화를 sizeof(char) 번으로 시도하면 제대로 작동합니다.

+0

+1 : 이것은 앞으로 수년 동안 델파이 개발자들의 가장 흔한 실수가 될 것입니다. "SizeOf (Char)"대신 "StringElementSize (StringVariable)"를 사용하는 것이 좋습니다. –

관련 문제