Delphi Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
델파이 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
FreePascal/Lazarus
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
델마당
볼랜드포럼 광고 모집

델파이 Q&A
Delphi Programming Q&A
[9860] 퀵레포트4.03에 대해 문의 합니다.
박진수 [jeensoo] 1112 읽음    2004-09-16 09:23
퀵레포트4.03에 대해 문의 합니다.

퀵레포트 4에서는 새롭게 추가된 사항이
preview 에서 text search 기능이 추가 되었습니다.

그런데 문제는 한글 search가 되지 않더군요.

그래서 관련 소스인 qrprev.pas, qrextra.pas qrprntr.pas를 보니

결국 퀵레포트도 메타파일을 받아서 다시 이 메타파일에서
메타레코드를 추출해  이것의 type을 분석해 문자열을 추출한후

이 추출한 문자열을 가지고 찾을 문자열과 비교하고 있다는 것을 알게 되었습니다.

그래서 해당소스를 보니 EnumEnhMetafile 이라는 win32 api와 이것의 콜백함수를 가지고
처리를 하고 있던 터라 이 콜백함수부분에서 문자열 추출이 완료되는 시점에서
문자열추출이 완료된 직후 break 나 showmessage를 걸어 해당 값을 화면으로 보면
한글은 모두 깨져서 출력이 됩니다.

그래서 델파이 6버전 부터 UTF8과 관련한 CHARATER SET CONVERT 처리 함수가 추가되어 있어서
제가 찾고자 하는 문자열을 직접 UTF8로 바꾸어 화면으로 본 결과 콜백함수부분에서 문자열 추출이
완료되는 시점에서 문자열추출이 완료된 직후의 값과 틀린 값이 나왔습니다.

메타파일에서 문자열이 어떠한 규칙으로 처리되는 지 아시는 분이 있으신지요..
아래는 QUICK REPORT 4.03에서 SEARTCH 부분을 처리하는 부분들을 추출한 자료입니다.

---------------------------------


qrprev unit에서

procedure TQRStandardPreview.FindButtonClick(Sender: TObject);
var
  FindStr : string;
  MatchCase : boolean;
  I : integer;
  APage : TMetafile;
  Dummy : TList;
begin
  if GetTextSearch(MatchCase, FindStr) then
  begin
    SearchResultBox.Enabled := true;
    SearchTextLabel.Caption := FindStr;
    SearchResultBox.Items.Clear;
    for I := 1 to QRPrinter.PageCount do
    begin                                     
       APage := QRPrinter.GetPage(I);
       try
         if StrInMetafile(FindStr, APage, MatchCase) then
            SearchResultBox.Items.Add('Page ' + IntToStr(I));
       finally
         APage.Free;
       end;
    end;
    if SearchResultBox.Items.Count = 0 then
    begin
      SearchResultBox.Items.Add('일치하는 결과가 없습니다.');
      SearchResultBox.Enabled := false;
    end;
  end;
end;


-----------------------------------------------------

qrextra unit에서


type
  MFBar = array of Char;
var
  MFSearchStr : string;
  MFFound : boolean;
  MFMatchCase : boolean;
  MFSearchBusy : boolean;



function MetaEnum(DC : THandle; HandleTable : pointer; MetaRec : Pointer; Count : word; dummy : pointer) : shortint stdcall;
var
  aStr : string;
  Ofs : integer;
  Len : integer;
  I : integer;
begin
  aStr := '';
  with tagENHMETARECORD(MetaRec^) do
  begin
    case iType of
      EMR_EXTTEXTOUTW,
      EMR_EXTTEXTOUTA : begin
                          aStr := '';
                          Ofs := (tagEMREXTTEXTOUTA(Metarec^).EMRText.offString);
                          Len := (tagEMREXTTEXTOUTA(Metarec^).EMRText.nChars);
                          SetLength(aStr, Len);
                          for I := 0 to len - 1 do
                        //    aStr[I+1] := char(MFBar(MetaRec^)[ofs + (I*2)]);
                            aStr[I+1] := MFBar(MetaRec)[ofs + (I*2)];
                          Showmessage(aStr);
                        end;
    end;
  end;
  if not MFMatchCase then aStr := AnsiUppercase(AStr);
  if Pos(MFSearchStr, aStr) > 0 then
  begin
    Result := 0;
    MFFound := true;
  end else
    Result := 1;
end;

function StrInMetafile(AString : string; AMetafile : TMetafile; MatchCase : boolean) : boolean;
begin
  while MFSearchBusy do Application.ProcessMessages;
  MFSearchBusy := true;
  if MatchCase then
    MFSearchStr := AString
  else
    MFSearchStr := AnsiUppercase(AString);
  MFFound := false;
  MFMatchCase := MatchCase;
  EnumEnhMetafile(0, AMetafile.handle, @MetaEnum, nil, rect(0,0,0,0));
  Result := MFFound;
  MFSearchBusy := false;
end;


----------------------------------------------


qrprntr unit에서


type
  bar = array of Char;
var
  MFSearchStr : string;
  MFFound : boolean;
  MFMatchCase : boolean;           

function MetaEnum(DC : THandle; HandleTable : pointer; MetaRec : Pointer; Count : word; dummy : pointer) : shortint stdcall;
var
  aStr : string;
  Ofs : integer;
  Len : integer;
  I : integer;
begin
  with tagENHMETARECORD(MetaRec^) do
  begin
    case iType of
      EMR_EXTTEXTOUTW,
      EMR_EXTTEXTOUTA : begin
                          aStr := '';
                          Ofs := (tagEMREXTTEXTOUTA(Metarec^).EMRText.offString);
                          Len := (tagEMREXTTEXTOUTA(Metarec^).EMRText.nChars);
                          SetLength(aStr, Len);
                          for I := 0 to len - 1 do
                            aStr[I+1] := char(bar(MetaRec^)[ofs + (I*2)]);
                        end;
    end;
  end;
  if not MFMatchCase then aStr := AnsiUppercase(AStr);
  if Pos(MFSearchStr, aStr) > 0 then
  begin
    Result := 0;
    MFFound := true;
  end else
    Result := 1;
end;

function StrInMetafile(AString : string; AMetafile : TMetafile; MatchCase : boolean) : boolean;
begin
  if MatchCase then
    MFSearchStr := AString
  else
    MFSearchStr := AnsiUppercase(AString);
  MFFound := false;
  MFMatchCase := MatchCase;
  EnumEnhMetafile(0, AMetafile.handle, @MetaEnum, nil, rect(0,0,0,0));
  Result := MFFound;
end;


-----------------------------------------------------------------------


기타 windows 유닛에서

  PEnhMetaRecord = ^TEnhMetaRecord;
  {$EXTERNALSYM tagENHMETARECORD}
  tagENHMETARECORD = packed record
    iType: DWORD; { Record type EMR_XXX}
    nSize: DWORD; { Record size in bytes}
    dParm: array[0..0] of DWORD; { Parameters}
  end;
  TEnhMetaRecord = tagENHMETARECORD;
  {$EXTERNALSYM ENHMETARECORD}
  ENHMETARECORD = tagENHMETARECORD;




  {$EXTERNALSYM EMR_EXTTEXTOUTA}
  EMR_EXTTEXTOUTA = 83;
  {$EXTERNALSYM EMR_EXTTEXTOUTW}
  EMR_EXTTEXTOUTW = 84;




  {$EXTERNALSYM tagEMREXTTEXTOUTA}
  tagEMREXTTEXTOUTA = packed record
    emr: TEMR;
    rclBounds: TRect;     { Inclusive-inclusive bounds in device units}
    iGraphicsMode: DWORD; { Current graphics mode}
    exScale: Single;       { X and Y scales from Page units to .01mm units}
    eyScale: Single;       {   if graphics mode is GM_COMPATIBLE.}
    emrtext: TEMRText;    { This is followed by the string and spacing array}
  end;
  TEMRExtTextOut = tagEMREXTTEXTOUTA;
  {$EXTERNALSYM EMREXTTEXTOUTA}
  EMREXTTEXTOUTA = tagEMREXTTEXTOUTA;





  { Base text record type for the enhanced metafile.}
  PEMRText = ^TEMRText;
  {$EXTERNALSYM tagEMRTEXT}
  tagEMRTEXT = packed record
    ptlReference: TPoint;
    nChars: DWORD;
    offString: DWORD; { Offset to the string}
    fOptions: DWORD;
    rcl: TRect;
    offDx: DWORD;     { Offset to the inter-character spacing array.}
                      { This is always given.}
  end;
  TEMRText = tagEMRTEXT;
  {$EXTERNALSYM EMRTEXT}
  EMRTEXT = tagEMRTEXT;





  {$EXTERNALSYM tagEMR}
  tagEMR = packed record
    iType: DWORD; { Enhanced metafile record type}
    nSize: DWORD; { Length of the record in bytes.}
                  { This must be a multiple of 4.}
  end;
  TEMR = tagEMR;
  {$EXTERNALSYM EMR}
  EMR = tagEMR;

+ -

관련 글 리스트
9860 퀵레포트4.03에 대해 문의 합니다. 박진수 1112 2004/09/16
9864     Re: 자답 입니다. 박진수 1242 2004/09/21
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.