내용은 Tip'N Tricks 란에 올려 놓았습니다.
박진수 님이 쓰신 글 :
: 퀵레포트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;
|