我现n个独立的.exe程序,主窗体为A.exe,有次窗体B.exe,C.exe……程序等,但是已经控制次窗体B.exe,C.exe……程序必须要A程序打开之后才能运行,当然允许B、C……程序重复打开;现在需要控制的是当B、C……程序打开后,不允许关闭主窗体A.exe!
我的自己的想法是:设主窗体A.exe一全局变量S,初始值为0,当次窗体B、C……程序每打开一个时,传递数值1到主窗体A.exe中,并使用主窗体A.exe中全局变量S累加;反之当次窗体B、C……程序每关闭一个时,,传递数值1到主窗体A.exe中,并使用主窗体A.exe中全局变量S递减。然后控制当S<>0时,即不能关闭!
请问能否实现这样的需求?(注:程序之间是相互独立开发的!)

解决方案 »

  1.   

    可以,B,C打开或关闭时,给A发消息,然后处理A中的标识
      

  2.   

    A在打开时可以通过命令行参数给B,C传递A的句柄,那样B,c就可以给A发消息了
      

  3.   

    ShellExecute(NULL,"open","B.EXE",PChar(IntToStr(A.Handle)),NULL,SW_SHOWNORMAL);下面就可以给Hanle发消息了
      

  4.   

    使用Windows系统提供的信号量(Semaphore)就可以实现了。
      

  5.   

    打开A程序时,不一定打开了B、C程序,所以A在打开时可以通过命令行参数给B时,是不是不可以哟?
      

  6.   

    奇了怪了,以下这段代码,我在简单程序里调试没有问题,可是一移到我自己完整那个程序里时,总会出错,说什么无效参数传递:
    //接收消息的窗口  public
      procedure Mymessage(var t:TWmCopyData); message WM_COPYDATA;
      { Public declarations }
      end;implementation{$R *.dfm}
    var
      Form2: TForm2;
      S:integer;procedure TForm2.FormCreate(Sender: TObject);
    begin
      S:=0;
    end;procedure TForm2.Mymessage(var t:TWmCopyData);
    var
      XiaoXi:string;
    begin
      XiaoXi:=copy(StrPas(t.CopyDataStruct^.lpData),1,8);
         if   XiaoXi='开启窗体' then
            begin
                Edit1.text:=inttostr(S+1);     //接受数据并显示。
                S:=strtoint(Edit1.Text);
            end
            else
            begin
                 if   XiaoXi='关闭窗体' then
                    begin
                        Edit1.text:=inttostr(S-1);     //接受数据并显示。
                        S:=strtoint(Edit1.Text);
                    end
                    else
                    Exit;
            end;
    end;//发送消息的窗口uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;procedure TForm1.FormCreate(Sender: TObject);
    var
      ds: TCopyDataStruct;
      hd: THandle;
    begin
      ds.cbData :=8;                                          //大小为下面'消息'几个汉字长度
      GetMem (ds.lpData, ds.cbData );                          //为传递的数据区分配内存
      StrCopy (ds.lpData, '开启窗体');
      Hd := FindWindow (nil, '程序主窗体');                   // 获得接受窗口的句柄(即窗体名称)
      if Hd <> 0 then
      SendMessage (Hd, WM_COPYDATA, Handle,Cardinal(@ds))      // 发送WM_COPYDATA消息
      else
      FreeMem (ds.lpData);                                  //释放资源
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    var
      ds: TCopyDataStruct;
      hd: THandle;
    begin
      ds.cbData :=8;                                          //大小为下面'消息'几个汉字长度
      GetMem (ds.lpData, ds.cbData );                          //为传递的数据区分配内存
      StrCopy (ds.lpData, '关闭窗体');
      Hd := FindWindow (nil, '程序主窗体');                   // 获得接受窗口的句柄(即窗体名称)
      if Hd <> 0 then
      SendMessage (Hd, WM_COPYDATA, Handle,Cardinal(@ds))      // 发送WM_COPYDATA消息
      else
      FreeMem (ds.lpData);                                     //释放资源
    end;
      

  7.   

    加上这句
    FillChar(ds,sizeof(ds),0);
      

  8.   

    你可以这样做:查看project --->view source
    程序在运行时先Application.Initialize;....
    你的一些特殊的初始化可以在这句之前进行,比如检测其他程序的运行:uses Tlhelp32;
    function form1.CanRun(ExefileName: string):Integer;
    const
      ContinueLoop:BOOL;
      FSnapshotHandle: THandle;
      FProcessEntry32: TProcessEntry32;
    begin
      Result := 0;
      FSnapshothandle := CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS,0);
      FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
      ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
      while Integer(ContinueLoop) <> 0 do
      begin
        if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) = 
            UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile =
            UpperCase(ExeFileName))) then
           Result := 1;
        ContinueLoop := Process32Next(FSnapShotHandle, FProcessEntry32);
      end;
      CloseHandle(FSnapshotHandle);
    end;
      end;
    end;
    这程序可以在你的主程序中比如叫:form1
    在Application.Initialize;
    Application.createForm(Tform1, from1);后面写:if form1.CanRun('form1.exe') = 0 then
    begin
      Application.MessageBox(PChar('XX未启动,程序退出!'), PChar('提示'),0);
      form1.Destroy;
      Application.Terminate;
    end;当然你的其他程序也要用,你可以把它做成一个单独的a.EXE,然后在程序中调a.exe,传递当前应用程序的名字作为参数,然后在a.exe中检测是否有这个进程。
    手都打累了
      

  9.   

    根据上面的指点又有一办法:
    检测是否有实例存在
    在form1中定义
    function Tform1.ExistsExe: Boolean;
    var
      hSysMutexHandle: THandle;
    begin
      Result := False;
      hSysMutexHandle  := createMutex(nil, False, pchar('MutexforOnlineForm2'));
      if hSysMutexHandle <> 0 then
      begin
        if GetLastError = ERROR_ALREADY_EXISTS then
        begin
          Result := True;      
        end;
      end;
      CloseHandle(hSysMutexHandle);
    end;form2为必须启动的那个程序。
    在Application.Initialize; 
    Application.createForm(Tform1, from1);后面写:
    if not form1.ExistsExe then
    begin
      Application.MessageBox(PChar('XX未启动,程序退出!'), PChar('提示'),0); 
      form1.Destroy; 
      Application.Terminate; 
    end;