2010-05-09 7 views
1

Je veux écrire un éditeur de texte et lui assigner les fichiers txt. Mon problème est que je veux avoir une seule instance en cours d'exécution et quand un nouveau fichier est ouvert pour envoyer le nom de fichier à la première application qui est déjà en cours d'exécution ... (Je veux le faire en utilisant mutex). Voici un petit testouvrir des fichiers texte dans une application

République populaire démocratique ressemble à ce

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; 

ce code devrait être ok, mais si je veux ouvrir un fichier texte (à partir de la seconde application) , la première application reçoit un message comme celui-ci:

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

tha nks

+2

Ce code mutex est incorrect. Utilisez toujours 'CreateMutex', pas' OpenMutex'. En outre, cette boucle 'FindWindow' est inutile. Cette fonction renvoie uniquement le handle de fenêtre de l'application en cours si le titre de votre application était "TfrmMain", mais pourquoi nommez-vous votre application? De plus, si 'FindWindow' * renvoie * le handle de fenêtre de votre application, les appels répétés ne donneront pas une réponse différente, donc cette boucle sera exécutée exactement une fois, ou elle fonctionnera pour toujours. –

Répondre

0

je soupçonne que vous utilisez Delphi 2009 ou Delphi 2010. Ces utilisation version chaînes Unicode, donc la fonction Length indique le nombre de caractères dans une chaîne, mais pas le nombre octets. Le message wm_CopyData doit connaître le nombre d'octets à envoyer. Multipliez le nombre de caractères par deux ou SizeOf(WideChar).

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

Cela fonctionnera tant que vous n'essayez pas de réutiliser le code dans une version non-unicode. Si vous faites cela, ça va casser. Mieux vaut utiliser 'PChar' et' sizeof (char) 'et laisser le compilateur s'occuper de l'interprétation. –

+0

Je préférerais le rendre explicite dans ce cas parce que nous traitons de la communication interprocessus. Les deux parties doivent se mettre d'accord sur la taille et le format de la charge utile. Si un côté est compilé en mode Unicode et l'autre non, mon code échouera à compiler, suggérant que quelque chose ne va pas, alors que le code qui utilise PChar compilera find des deux côtés, mais la communication échouera au moment de l'exécution. –

1

Cela ressemble à un problème Unicode. Vous êtes probablement en D2009 ou D2010. Vous devez donner la taille en octets, pas en caractères. Essayez de multiplier votre appel length par sizeof(char) et cela devrait fonctionner.

+0

+1: Cela va probablement être l'erreur la plus commune des développeurs Delphi pour les années à venir. Au lieu de "SizeOf (Char)", je suggère d'utiliser "StringElementSize (StringVariable)". –