通用过程
procedure TFormMain.OpenOneDev(iDevId: Integer);
var
  Hr: Integer;
begin
  if m_DoFlag[iDevId] then
  begin
    MessageBox(0, PChar('相机 '+IntToStr(iDevId)+' 已经打开!'), PChar('提示'), MB_ICONWARNING or MB_OK);
    Exit;
  end;
  //打开设备
  Hr:= HV_OpenDevice(iDevId);
  if (Hr <> HV_SUCCESS) then
  begin
    MessageBox(0, PChar('HV_OpenDevice 失败!'), PChar('提示'), MB_ICONWARNING or MB_OK);
    Exit;
  end;
  //初始化设备
  Hr:= HV_DevCapInit(iDevId);
  if (Hr <> HV_SUCCESS) then
  begin
    MessageBox(0, PChar('HV_DevCapInit 失败!'), PChar('提示'), MB_ICONWARNING or MB_OK);
    Exit;
  end;
  Hr:= HV_SetExposureValue(3000,iDevId);
  if (Hr <> HV_SUCCESS) then
  begin
    MessageBox(0, PChar('HV_SetExposureValue 失败!'), PChar('提示'), MB_ICONWARNING or MB_OK);
    Exit;
  end;
  //设置去抖动的时间,该时间越短,触发采集输出就越快
  Hr:= HV_SetSnapDebounceTime(20,iDevId);
  if (Hr <> HV_SUCCESS) then
  begin
    MessageBox(0, PChar('HV_SetSnapDebounceTime 失败!'), PChar('提示'), MB_ICONWARNING or MB_OK);
    Exit;
  end;
  //设置触发模式下的参数,第一个参数为相机输出的帧率,不能高于该相机固有帧率。
  //第二个参数为一次触发获取几幅图像,该参数设为0时,则表示以第一个参数为帧率连续触发输出。
  //第三个参数表示相机的对应网卡的ID号
  HV_SetSnapTrigFreqImgCount(14,1,iDevId);
  //设置回调函数
  case iDevId of
    0:HV_SetCallBack(@MyCallBackProc0,iDevId);
    1:HV_SetCallBack(@MyCallBackProc1,iDevId);
    2:HV_SetCallBack(@MyCallBackProc2,iDevId);
    3:HV_SetCallBack(@MyCallBackProc3,iDevId);
  end;
  //设置采集模式,第一个参数:1:连续采集模式,0:触发模式
  HV_SetPreviewSnapMode(0,1,iDevId);  HV_SetImageMirror(2,iDevId);
  //设置SDK进入采集状态
  HV_StartCapture(iDevId);  m_DoFlag[iDevId]:= True;
  Label2.Caption:= '相机:'+IntToStr(iDevId);
end;分三个按键执行,一个一个点,可以依次打开三个相机
procedure TFormMain.SpeedButton1Click(Sender: TObject);
begin
  OpenOneDev(0);
//  SpeedButton2.Click;  //直接调用打开设备2的事件,还是会跳出来
end;procedure TFormMain.SpeedButton2Click(Sender: TObject);
begin
  OpenOneDev(1);     //单个打开,就可以
end;procedure TFormMain.SpeedButton3Click(Sender: TObject);
begin
  OpenOneDev(2);
end;
放到循环里,程序在执行到i=1的时候就会跳出来
procedure TFormMain.OpenDeviceBtnClick(Sender: TObject);
var
  i: Integer;
begin
  for i:=0 to 2 do
    OpenOneDev(i);
end;
而且有时候还发现,for循环执行完i=0后,第二次进入的i不是1,而是一个很大的数值。请帮忙分析分析什么原因啊
delphi循环分按键执行

解决方案 »

  1.   

    对了,有人说,把Delphi的环境修改一下
    Project->Options->Complier->Optimization的钩,去掉 就好了。
    可是我去掉后还是老样子……
      

  2.   

    OpenOneDev的问题把OpenOneDev里的代码分段注释, 调试几次就查出来了
      

  3.   

    这些 Hr:= HV_XXXXXXXXX 都是相机SDK里DLL的函数,你是说他们的DLL有问题吧?我去试试
      

  4.   

    可能是OpenOneDev里面的API调用的接口函数有改变i的值,修改为这样:procedure TFormMain.OpenDeviceBtnClick(Sender: TObject);
    var
      i, n: Integer;
    begin
      for i:=0 to 2 do
      begin
        n := i;
        OpenOneDev(n);
      end;
    end;
      

  5.   

    我把主要的代码取出来了procedure TFormMain.OpenDeviceBtnClick(Sender: TObject);
    var
      i: Integer;
    begin
      for i:=0 to 2 do
    //    OpenOneDev(i);
      begin
        if m_DoFlag[i] then
        begin
          MessageBox(0, PChar('相机 '+IntToStr(i)+' 已经打开!'), PChar('提示'), MB_ICONWARNING or MB_OK);
          Exit;
        end;
        HV_OpenDevice(i);
    //问题1    HV_DevCapInit(i);   
        HV_SetExposureValue(3000,i);
        HV_SetSnapDebounceTime(20,i);
    //问题2    HV_SetSnapTrigFreqImgCount(14,1,i);
        if (i=0) then
          HV_SetCallBack(@MyCallBackProc0,0);
        if (i=1) then
          HV_SetCallBack(@MyCallBackProc1,1);
        if (i=2) then
          HV_SetCallBack(@MyCallBackProc2,2);
        if (i=3) then
          HV_SetCallBack(@MyCallBackProc3,3);
        HV_SetPreviewSnapMode(0,1,i);
        HV_SetImageMirror(2,i);
        HV_StartCapture(i);
        m_DoFlag[i]:= True;
        label2.Caption:= 'OK';
      end; 
    end;上边注释掉的两句,第一句在运行跳出CPU窗口第二句用F7单步运行可以通过,连续运行就跳出程序了。
      

  6.   

    1  丢进线程里面去试试2  使用   application.ProcessMessages;   试试3  把i 弄成全局或者静态试试? 
      

  7.   

    对了,他们的DLL看来是VC写的。上边的Delphi程序,改成VC的,就可以顺利运行(XP+VC2008)
      

  8.   


    procedure TFormMain.OpenDeviceBtnClick(Sender: TObject);
    var
      i: Integer;
    begin
      for i:=0 to 2 do
      begin
        if m_DoFlag[i] then
        begin
          MessageBox(0, PChar('相机 '+IntToStr(i)+' 已经打开!'), PChar('提示'), MB_ICONWARNING or MB_OK);
          Exit;
        end;
        HV_OpenDevice(i);
    //    HV_DevCapInit(i);
        HV_SetExposureValue(3000,i);
        HV_SetSnapDebounceTime(20,i);
        HV_SetSnapTrigFreqImgCount(14,1,i);
        if (i=0) then
          HV_SetCallBack(@MyCallBackProc0,0);
        if (i=1) then
          HV_SetCallBack(@MyCallBackProc1,1);
        if (i=2) then
          HV_SetCallBack(@MyCallBackProc2,2);
        if (i=3) then
          HV_SetCallBack(@MyCallBackProc3,3);
        HV_SetPreviewSnapMode(0,1,i);
        HV_SetImageMirror(2,i);
        HV_StartCapture(i);
        m_DoFlag[i]:= True;
        label2.Caption:= 'OK';
        Sleep(3000);
      end; 
    end;
    涛声依旧
      

  9.   

    void CIndCamDemoDlg::OnOpenCam0() 
    {
    int i;
    for(i=0;i<3;i++)  
    //这是我们准备用循环的方式把8个相机顺序打开,我们这里用三个相机做实验  {
      // TODO: Add your control notification handler code here
      if (bCamStatus[i])
        {
    MessageBox(_T("Device is already opened!"));
    return ;
    }
    HRESULT hr;
        hr = HV_OpenDevice(i); //打开设备
    if(hr!=HV_SUCCESS)
    {
    MessageBox(_T("Open Device fail!"));
    return ;
    }
    // 初始化设备
    hr = HV_DevCapInit(i); //初始化设备
    if(hr!=HV_SUCCESS)
    {
    MessageBox(_T("Device initial fail!"));
    return ;
    } HV_SetExposureValue(200,i); //设置曝光行数,一行为30微秒左右 HV_SetSnapDebounceTime(20,i); //设置去抖动的时间,该时间越短,触发采集输出就越快 HV_SetSnapTrigFreqImgCount(14,1,i); //设置触发模式下的参数,第一个参数为相机输出的帧率,不能高于该相机固有帧率。
    //第二个参数为一次触发获取几幅图像,该参数设为0时,则表示以第一个参数为帧率连续触发输出。
    //第三个参数表示相机的对应网卡的ID号
    //设置回调函数
    if (i==0)
    HV_SetCallBack(CIndCamDemoDlg::MyCallBackProc0,i);
    if (i==1)
    HV_SetCallBack(CIndCamDemoDlg::MyCallBackProc1,i);
    if (i==2)
    HV_SetCallBack(CIndCamDemoDlg::MyCallBackProc2,i);

    //设置采集模式,第一个参数:1:连续采集模式,0:触发模式
    HV_SetPreviewSnapMode(0,0,i);  //设置SDK进入采集状态
    HV_StartCapture(i);

      bCamStatus[i] = TRUE;
    //  m_nIndex = -1;
    //MessageBox(_T("打开成功!"));
    //下边的OpenCam1是为了测试两个相机打开的时候会不会跳出来,把相机1打开的消息事件放到这里来执行。   //OnOpenCam1();
    }
    return ;
    }
    在VC里边这样就没问题
      

  10.   

    每步加上i的重新复制,单步调试看下是哪步修改了i的值:procedure TFormMain.OpenDeviceBtnClick(Sender: TObject);
    var
      i, j: Integer;
    begin
      for j := 0 to 2 do
      begin
        i := j;
        if m_DoFlag[i] then
        begin
          MessageBox(0, PChar('相机 '+IntToStr(i)+' 已经打开!'), PChar('提示'), MB_ICONWARNING or MB_OK);
          Exit;
        end;
        HV_OpenDevice(i);
        i := j;
        HV_DevCapInit(i);
        i := j;
        HV_SetExposureValue(3000,i);
        i := j;
        HV_SetSnapDebounceTime(20,i);
        i := j;
        HV_SetSnapTrigFreqImgCount(14,1,i);
        i := j;
        if (i=0) then
          HV_SetCallBack(@MyCallBackProc0,0);
        if (i=1) then
          HV_SetCallBack(@MyCallBackProc1,1);
        if (i=2) then
          HV_SetCallBack(@MyCallBackProc2,2);
        if (i=3) then
          HV_SetCallBack(@MyCallBackProc3,3);
        i := j;
        HV_SetPreviewSnapMode(0,1,i);
        i := j;
        HV_SetImageMirror(2,i);
        i := j;
        HV_StartCapture(i);
        i := j;
        m_DoFlag[j]:= True;
        label2.Caption:= 'OK';
      end; 
    end;
      

  11.   

    我单步执行查过了,第一个循环一直都是0,到了第一个循环执行完,i值就变了也用CnDebug输出i的每一步值看了。
    procedure TFormMain.OpenDeviceBtnClick(Sender: TObject);
    var
      i: Integer;
    begin
      for i:=0 to 2 do
      begin
      CnDebugger.LogMsg('01  '+IntToStr(i));
        OpenOneDev(i);
      CnDebugger.LogMsg('14  '+IntToStr(i));  //到这就是一个很大的随机数了
      end;
    end;procedure TFormMain.OpenOneDev(iShs: Integer);
    var
      Hr: Integer;
    begin
      CnDebugger.LogMsg('02  '+IntToStr(iShs));
      if m_DoFlag[iShs] then
      begin
        MessageBox(0, PChar('相机 '+IntToStr(iShs)+' 已经打开!'), PChar('提示'), MB_ICONWARNING or MB_OK);
        Exit;
      end;
      //打开设备
      CnDebugger.LogMsg('03  '+IntToStr(iShs));
      Hr:= HV_OpenDevice(iShs);
      if (Hr <> HV_SUCCESS) then
      begin
        MessageBox(0, PChar('HV_OpenDevice 失败!'), PChar('提示'), MB_ICONWARNING or MB_OK);
        Exit;
      end;
      CnDebugger.LogMsg('04  '+IntToStr(iShs));
      //初始化设备
      Hr:= HV_DevCapInit(iShs);
      if (Hr <> HV_SUCCESS) then
      begin
        MessageBox(0, PChar('HV_DevCapInit 失败!'), PChar('提示'), MB_ICONWARNING or MB_OK);
        Exit;
      end;
      CnDebugger.LogMsg('05  '+IntToStr(iShs));
      Hr:= HV_SetExposureValue(3000,iShs);
      if (Hr <> HV_SUCCESS) then
      begin
        MessageBox(0, PChar('HV_SetExposureValue 失败!'), PChar('提示'), MB_ICONWARNING or MB_OK);
        Exit;
      end;
      CnDebugger.LogMsg('06  '+IntToStr(iShs));
      //设置去抖动的时间,该时间越短,触发采集输出就越快
      Hr:= HV_SetSnapDebounceTime(20,iShs);
      if (Hr <> HV_SUCCESS) then
      begin
        MessageBox(0, PChar('HV_SetSnapDebounceTime 失败!'), PChar('提示'), MB_ICONWARNING or MB_OK);
        Exit;
      end;
      CnDebugger.LogMsg('07  '+IntToStr(iShs));
      //设置触发模式下的参数,第一个参数为相机输出的帧率,不能高于该相机固有帧率。
      //第二个参数为一次触发获取几幅图像,该参数设为0时,则表示以第一个参数为帧率连续触发输出。
      //第三个参数表示相机的对应网卡的ID号
      HV_SetSnapTrigFreqImgCount(14,1,iShs);
      CnDebugger.LogMsg('08  '+IntToStr(iShs));
      //设置回调函数
      case iShs of
        0:HV_SetCallBack(@MyCallBackProc0,iShs);
        1:HV_SetCallBack(@MyCallBackProc1,iShs);
        2:HV_SetCallBack(@MyCallBackProc2,iShs);
        3:HV_SetCallBack(@MyCallBackProc3,iShs);
      end;
      CnDebugger.LogMsg('09  '+IntToStr(iShs));
      //设置采集模式,第一个参数:1:连续采集模式,0:触发模式
      HV_SetPreviewSnapMode(0,1,iShs);
      CnDebugger.LogMsg('10  '+IntToStr(iShs));  HV_SetImageMirror(2,iShs);
      CnDebugger.LogMsg('11  '+IntToStr(iShs));
      //设置SDK进入采集状态
      HV_StartCapture(iShs);
      CnDebugger.LogMsg('12  '+IntToStr(iShs));  m_DoFlag[iShs]:= True;
      CnDebugger.LogMsg('13  '+IntToStr(iShs));  //到这都还是0
      Label2.Caption:= '相机:'+IntToStr(iShs);
    end;
      

  12.   

    这样调试下:procedure TFormMain.OpenDeviceBtnClick(Sender: TObject);
    var
      i, j: Integer;
    begin
      for i:=0 to 2 do
      begin
      CnDebugger.LogMsg('01  '+IntToStr(i));
      CnDebugger.LogMsg('01  '+IntToStr(j));
        j := i;
        OpenOneDev(j);
      CnDebugger.LogMsg('14  '+IntToStr(i));
      CnDebugger.LogMsg('14  '+IntToStr(j));
      end;
    end;
      

  13.   

    如果上面还是不行,再试下这样会不会有问题:procedure TFormMain.OpenDeviceBtnClick(Sender: TObject);
    var
      i: Integer;
      j: array[0..2] of Integer;
    begin
      for i:=0 to 2 do
      begin
      CnDebugger.LogMsg('01  '+IntToStr(i));
      CnDebugger.LogMsg('01  '+IntToStr(j[i]));
        j[i] := i;
        OpenOneDev(j[i]);
      CnDebugger.LogMsg('14  '+IntToStr(i));
      CnDebugger.LogMsg('14  '+IntToStr(j[i]));
      end;
    end;
      

  14.   

    但是我这样执行就没问题
    procedure TFormMain.OpenDeviceBtnClick(Sender: TObject);
    var
      i: Integer;
    begin
      for i:=0 to 2 do
      begin
      CnDebugger.LogMsg('H01  '+IntToStr(i));
        if m_DoFlag[i] then
        begin
          MessageBox(0, PChar('相机 '+IntToStr(i)+' 已经打开!'), PChar('提示'), MB_ICONWARNING or MB_OK);
          Exit;
        end;
      CnDebugger.LogMsg('H02  '+IntToStr(i));
        HV_OpenDevice(i);
      CnDebugger.LogMsg('H03  '+IntToStr(i));
        HV_DevCapInit(i);
      CnDebugger.LogMsg('H04  '+IntToStr(i));
        HV_SetExposureValue(3000,i);
      CnDebugger.LogMsg('H05  '+IntToStr(i));
        HV_SetSnapDebounceTime(20,i);
      CnDebugger.LogMsg('H06  '+IntToStr(i));
        HV_SetSnapTrigFreqImgCount(14,1,i);
      CnDebugger.LogMsg('H07  '+IntToStr(i));
        if (i=0) then
          HV_SetCallBack(@MyCallBackProc0,0);
        if (i=1) then
          HV_SetCallBack(@MyCallBackProc1,1);
        if (i=2) then
          HV_SetCallBack(@MyCallBackProc2,2);
        if (i=3) then
          HV_SetCallBack(@MyCallBackProc3,3);
      CnDebugger.LogMsg('H08  '+IntToStr(i));
        HV_SetPreviewSnapMode(0,1,i);
      CnDebugger.LogMsg('H09  '+IntToStr(i));
        HV_SetImageMirror(2,i);
      CnDebugger.LogMsg('H10  '+IntToStr(i));
        HV_StartCapture(i);
      CnDebugger.LogMsg('H11  '+IntToStr(i));
        m_DoFlag[i]:= True;
      CnDebugger.LogMsg('H12  '+IntToStr(i));
        label2.Caption:= 'OK';
      end;
    end;不过就是还是执行到i为1的时候,到HV_DevCapInit(i);就跳出,直接杀掉进程……
      

  15.   

    m_DoFlag[i]的定义是 m_DoFlag: array[0..2] of Boolean;吗???再试下下面
    procedure TFormMain.OpenDeviceBtnClick(Sender: TObject);
    var
      i, k: Integer;
      j: array[0..2] of Integer;
    begin
      k := 0;
      j[k] := 0;
      for i:=0 to 2 do
      begin
      CnDebugger.LogMsg('01  '+IntToStr(i));
      CnDebugger.LogMsg('01  '+IntToStr(k));
      CnDebugger.LogMsg('01  '+IntToStr(j[i]));
        inc(k);
        j[k-1] := k-1;
        OpenOneDev(j[k-1]);
      CnDebugger.LogMsg('14  '+IntToStr(i));
      CnDebugger.LogMsg('14  '+IntToStr(k));
      CnDebugger.LogMsg('14  '+IntToStr(j[i]));
      end;
    end
      

  16.   

    m_DoFlag: array[0..7] of Boolean;              //操作状态标识
      

  17.   

    执行到i为1的时候,到HV_DevCapInit(i);就跳出,直接杀掉进程的问题找到了:
    他们的DLL开发文档过期了/******************************************************************************
    * Function: HV_DevCapInit
    * Description: 设备捕捉初始化
    * Format:
    *     HRESULT HV_DevCapInit(int nDevId, LPCSTR lpFileName = NULL) ;
    * Params:
    *     int nDevId
    *   LPCSTR lpFileName: 配置文件保存路径,当为空时,默认为当前目录;
    * Return: 
    *     HV_SUCCESS: 成功
    ******************************************************************************/
    HVGIGE_WP_API HRESULT __stdcall HV_DevCapInit(int nDevId, LPCSTR lpFileName = NULL);
    后边多了一个参数。就剩下这个循环i改变很大值的问题了
      

  18.   

    是啊灰常郁闷……现在的情况下,我用
    procedure TFormMain.SpeedButton1Click(Sender: TObject);
    begin
      OpenOneDev(0);
      OpenOneDev(1);
      OpenOneDev(2);
    end;执行到OpenOneDev(1);还是不行~~~~神啊,救救我吧
      

  19.   


      OpenOneDev(0);
      sleep(1000);
      OpenOneDev(1);
      sleep(1000);
      OpenOneDev(2);试试能不能通过,理论上能通过。应该是抢占硬件资源导致的。
      

  20.   


    我将你c++的代码翻译过来了,你直接复制过去执行试下有没有问题。
    procedure TFormMain.OpenOneDev;
    var
      Hr: Integer;
      iDevId: Integer;
    begin
      for iDevId := 0 to 2 do
      begin
        if m_DoFlag[iDevId] then
        begin
          MessageBox(0, PChar('Device is already opened!'), PChar('Error'), MB_ICONWARNING or MB_OK);
          Exit;
        end;    Hr:= HV_OpenDevice(iDevId);
        if (Hr <> HV_SUCCESS) then
        begin
          MessageBox(0, PChar('Open Device fail!'), PChar('Error'), MB_ICONWARNING or MB_OK);
          Exit;
        end;    Hr:= HV_DevCapInit(iDevId);
        if (Hr <> HV_SUCCESS) then
        begin
          MessageBox(0, PChar('Device initial fail!'), PChar('Error'), MB_ICONWARNING or MB_OK);
          Exit;
        end;    HV_SetExposureValue(200,iDevId);
        HV_SetSnapDebounceTime(20,iDevId);
        HV_SetSnapTrigFreqImgCount(14,1,iDevId);    case iDevId of
          0:HV_SetCallBack(@MyCallBackProc0,iDevId);
          1:HV_SetCallBack(@MyCallBackProc1,iDevId);
          2:HV_SetCallBack(@MyCallBackProc2,iDevId);
        end;    HV_SetPreviewSnapMode(0,0,iDevId);
        //HV_SetImageMirror(2,iDevId);
        HV_StartCapture(iDevId);
        m_DoFlag[iDevId]:= True;
      end;
    end;procedure TFormMain.Button1Click(Sender: TObject);
    begin
      OpenOneDev;
    end;
      

  21.   

    执行了,问题依旧……但是我找到解决办法了,就是不知道为什么……还是前边说的,把Delphi的环境修改一下
    Project->Options->Complier->Optimization的钩,去掉 就好了。这个不是优化代码选项吗?为什么会在这里出幺蛾子呢?
      

  22.   


    只找到这个,再等高人解释。
    Optimization (-$O+)* 
    Controls code optimization. When enabled (equivalent to {$O+}), the compiler performs a number of code optimizations, such as placing variables in CPU registers, eliminating common subexpressions, and generating induction variables. When disabled, (equivalent to {$O-}), all such optimizations are disabled. Other than for certain debugging situations, you should never need to turn optimizations off. All optimizations performed by the Delphi compiler are guaranteed not to alter the meaning of a program. In other words, the compiler performs no "unsafe" optimizations that require special awareness by the programmer. 
    This option can only turn optimization on or off for an entire procedure or function. You can’t turn optimization on or off for a single line or group of lines within a routine.
    Default = true 
      

  23.   

    you should never need to turn optimizations off问题是关掉就可以正常运行,不关就