ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Impossible to select Twain-Device
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

Xylit

13 Posts

Posted - Apr 20 2012 :  03:08:14  Show Profile  Reply
Hi,

I have two Twain-Devices: "Scanner ABC" and "Scanner" (In that order; The second name is the prefix of the first name). In this constellation it is not possible to select the second Twain-Device. Both functions
TImageEnIO.SelectAcquireSource(ieaTWain)
or
TwainParams.SelectSourceByName('Scanner')
result in the first Twain-Device selected. (Checked with TImageEnIO.TWainParams.SourceName[TestIO.TWainParams.SelectedSource]).

Is this bug fixed in the actual version?

I am using ImageEn 3.0.5 components for Delphi.

fab

1310 Posts

Posted - Apr 20 2012 :  05:00:44  Show Profile  Reply
Hi,
this is not a known bug (and I cannot replicate in my tests). Please could you clear this: "The second name is the prefix of the first name"? Are both devices connected?
Go to Top of Page

Xylit

13 Posts

Posted - Apr 20 2012 :  05:11:14  Show Profile  Reply
I don't think it changes something, but the real TWAIN names are "Optic Pro S28 Pro" and "Optic Pro S28". Both drivers are installed but only the second device was ever connected to the pc. The first device is installed, but was never connected to the pc.
Go to Top of Page

fab

1310 Posts

Posted - Apr 20 2012 :  07:21:41  Show Profile  Reply
Yes, it is important for me in order to find the bug!!
Do you have source code, so I can propose a fix?
Go to Top of Page

Xylit

13 Posts

Posted - Apr 20 2012 :  07:29:48  Show Profile  Reply
function ShowSelectAcquirSource: AnsiString;
var
  TestIO: TImageEnIO;
begin
  result:='';
  TestIO:=TImageEnIO.Create(NIL);

  Application.BringToFront;
  if TestIO.SelectAcquireSource(ieaTWain) then
  begin
    result:=TestIO.TWainParams.SourceName[TestIO.TWainParams.SelectedSource];
  end;

  TestIO.Free;
end;
Go to Top of Page

fab

1310 Posts

Posted - Apr 20 2012 :  07:34:23  Show Profile  Reply
I meant ImageEn source code.
Go to Top of Page

Xylit

13 Posts

Posted - Apr 20 2012 :  07:47:57  Show Profile  Reply
Are you kidding? You don't have the 3.0.5 source code?

Well the fix is quite easy: Remove the "IECopy" or fix the length parameter.
function TIETWainParams.SelectSourceByName(const sn: AnsiString): boolean;
var
  q, ll: integer;
begin
  {$ifdef IEPROFILE} try IEProfileBegin('TIETWainParams.SelectSourceByName'); {$endif}
  result := false;
  FillSourceListData;
  ll := length(sn);
  for q := 0 to fSourceListData.Count - 1 do
    if IEUpperCase(IECopy(pTW_IDENTITY(fSourceListData[q])^.ProductName, 1, ll)) = IEUpperCase(sn) then
    begin
      if fSelectedSource <> q then
        SetSelectedSource(q);
      result := true;
      break;
    end;
  {$ifdef IEPROFILE} finally IEProfileEnd; end; {$endif}
end;
Go to Top of Page

fab

1310 Posts

Posted - Apr 20 2012 :  08:19:25  Show Profile  Reply
quote:
Are you kidding?


No, why?

quote:
You don't have the 3.0.5 source code?


My question was: "Do YOU have source code, ...".

I just wanted to propose a fix in "ImageEn" source code (in TIETWainParams.SelectSourceByName, of course...).
Go to Top of Page

Xylit

13 Posts

Posted - Apr 20 2012 :  08:32:56  Show Profile  Reply
Okay, now I get it.

Yes, I have the source code. What do you propose?
Go to Top of Page

fab

1310 Posts

Posted - Apr 20 2012 :  08:55:05  Show Profile  Reply
Previous code allowed to execute partial matches (this is the reason you will always select "Optic Pro S28 Pro", that partially matches with "Optic Pro S28").
To avoid to break old code, I think it is better to execute an exact match first, then a partial patch.
This is the changed code (for 4.x version):

function TIETwainParams.SelectSourceByName(const sn: AnsiString): boolean;
var
  q: integer;
  bestMatch: integer;
  bestMatchLen: integer;
  toFind, current: AnsiString;
  minLen: integer;
begin
  result := false;
  FillSourceListData;

  bestMatch := -1;
  toFind := IEUpperCase(sn);

  // search for exact match
  for q := 0 to fSourceListData.Count - 1 do
    if (IEUpperCase(IETrim(AnsiString(pTW_IDENTITY(fSourceListData[q])^.ProductName))) = toFind) then
    begin
      bestMatch := q;
      break;
    end;

  if bestMatch = -1 then
  begin
    // partial match
    bestMatchLen := 0;
    for q := 0 to fSourceListData.Count - 1 do
    begin
      current := IETrim(AnsiString(pTW_IDENTITY(fSourceListData[q])^.ProductName));
      minLen := imin(length(current), length(toFind));
      if (IEUpperCase(IECopy(current, 1, minLen)) = IECopy(toFind, 1, minLen)) and (minLen > bestMatchLen) then
      begin
        bestMatch := q;
        bestMatchLen := minLen;
      end;
    end;
  end;
  if bestMatch <> -1 then
  begin
    if fSelectedSource <> bestMatch then
      SetSelectedSource(bestMatch);
    result := true;
  end;

  // Make Twain the API for subsequent calls to Acquire
  {$IFDEF IEINCLUDEMULTIVIEW}
  If Result and (fOwner is TImageEnMIO) then
    (fOwner as TImageEnMIO).AcquireParams.fSelectedSourceAPI := ieaTwain
  else
  {$ENDIF}
  If Result and (fOwner is TImageEnIO) then
    (fOwner as TImageEnIO).AcquireParams.fSelectedSourceAPI := ieaTwain;
end;


This is for 3.x versions (not tested!):

function TIETwainParams.SelectSourceByName(const sn: AnsiString): boolean;
var
  q: integer;
  bestMatch: integer;
  bestMatchLen: integer;
  toFind, current: AnsiString;
  minLen: integer;
begin
  result := false;
  FillSourceListData;

  bestMatch := -1;
  toFind := IEUpperCase(sn);

  // search for exact match
  for q := 0 to fSourceListData.Count - 1 do
    if (IEUpperCase(IETrim(AnsiString(pTW_IDENTITY(fSourceListData[q])^.ProductName))) = toFind) then
    begin
      bestMatch := q;
      break;
    end;

  if bestMatch = -1 then
  begin
    // partial match
    bestMatchLen := 0;
    for q := 0 to fSourceListData.Count - 1 do
    begin
      current := IETrim(AnsiString(pTW_IDENTITY(fSourceListData[q])^.ProductName));
      minLen := imin(length(current), length(toFind));
      if (IEUpperCase(IECopy(current, 1, minLen)) = IECopy(toFind, 1, minLen)) and (minLen > bestMatchLen) then
      begin
        bestMatch := q;
        bestMatchLen := minLen;
      end;
    end;
  end;
  if bestMatch <> -1 then
  begin
    if fSelectedSource <> bestMatch then
      SetSelectedSource(bestMatch);
    result := true;
  end;
end;


Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: