블로그 이미지
훅크선장

카테고리

분류 전체보기 (363)
사진이야기 (23)
펭귄컴퓨팅 (122)
컴퓨터보안 (84)
절름발이 프로그래머 (59)
하드웨어개조 (23)
멀알려줄까 (35)
잡다한것들 (15)
홈베이킹&홈쿠킹 (2)
Total
Today
Yesterday

달력

« » 2025.7
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

공지사항

태그목록

최근에 올라온 글

Delphi 를 만지다보니, 자연스레 동일한 비주얼 컴포넌트를 사용할 수 있는 C++ Builder에 관심을 가지게 되었다. (사실 나도 시작은 C/C++ 프로그래머였으니, 당연하지 않겠는가?)

그런데, C++ Builder 2007을 처음 사용해보면서, 아주 간단한 에디트와 버튼 컴포넌트를 가지고, 예제를 테스트해봤는데...

계속 에러가 생기는 것이었다. 예전에 보지 못한 에러라서, 혹시 새로이 설치한 컴포넌트들때문인지 의문이 생겼다. 아니 디폴트 설치하고나서, 처음 만드는 프로젝트인데, 단순한 컴포넌트 2개 쓴 프로젝트가 에러가 생기다니???
이전에는 문제없이 컴파일 되었던 것으로 기억했는데...

약 6시간에 가까운 온갖 방법의 동원과 디버깅을 해보았지만, 전혀 원인을 찾을 수 없었다.
컴포넌트를 제거하고, 라이브러리 경로를 추가하는 등 할 수 있는 것을 다 해보았다.

그리고, 출력되는 에러메시지도 전혀 정보를 주지 않았다.

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Borland.Cpp.Targets(1796,3): error : Fatal: Unable to open file ''

파일을 열수 없다는데, 파일명은 없는 이런 황당한 경우가...
지친 상태에서 야밤에 인터넷을 뒤적거리다보니, 참고될만한 내용이 있었다.



문제는 바로 프로젝트 경로명이었다.

내가 프로젝트를 만든 경로는 
C:\Documents and Settings\HooK\My Documents\RAD Studio\Projects_2007_C++Builder\ex1\
이었는데,
결정적으로 경로명에 "++"가 들어있는 것이 문제를 야기한 것이다.

해결되고보니, 너무 황당한 상황이었다.

C++ Builder 2009에서는 이런 문제가 없는 것 같았는데, 유난히 2007에서만 경로명에 "++" 문자열이 들어가면 안되는 것이었다.

너무 습관에 충실해서 생기는 문제라니... 경로명에는 아무튼 영문자와 _ 문자만 쓰는게 맞을 듯 싶다.
Posted by 훅크선장
, |
C언어에서는 당연하고 되는 것이지만,
델파이 즉, 오브젝티브 파스칼을 쓸 때는 한번쯤 생각해보게 되는 방법이다.

C언어에서는  타입 캐스팅으로 되는 것을
델파이에서는 다음과 같이 해야된다.

tmpbuffer: array[0..1023] of Byte;
ptr : ^aRecord;

    // 파일에서 데이터를 읽어온다.
    ZeroMemory(@tmpbuffer[0], sizeof(tmpbuffer));
    BlockRead(File, tmpbuffer, datasize, readbytes);
    ptr := @tmpbuffer; // 버퍼 내용을 레코드 형식으로 해석한다.

    ptr.a
이런 식으로 버퍼의 데이터를 레코드형식으로 받아서 사용할 수 있다.

Posted by 훅크선장
, |
http://delphi.about.com/od/windowsshellapi/a/executeprogram.htm
를 참고하였습니다.

델파이에서 별도의 프로그램, 즉 exe를 실행시키고 종료를 확인할 수 있습니다.
ShellExecuteEx 를 사용하는데, 
먼저 uses ShellApi; 를 포함합니다.

그리고,
procedure TForm1.Button2Click(Sender: TObject);
var
   SEInfo: TShellExecuteInfo;
   ExitCode: DWORD;
   ExecuteFile, ParamString, StartInString: string;
begin
   ExecuteFile:='C:\Windows\Notepad.exe'; // 실행하려는 프로그램의 경로 및 파일명 지정
   ParamString := 'C:\autoexec.bat'; // 프로그램 실행시 인자값을 문자열로 지정

   FillChar(SEInfo, SizeOf(SEInfo), 0) ;
   SEInfo.cbSize := SizeOf(TShellExecuteInfo) ;
   with SEInfo do begin
     fMask := SEE_MASK_NOCLOSEPROCESS;
     Wnd := Application.Handle;
     lpFile := PChar(ExecuteFile) ;
     lpParameters := PChar(ParamString) ;
 // lpDirectory := PChar(StartInString) ; // StartInString 문자열에 실행되고자 하는 디렉토리를 지정할 수 있음. 지정하지 않으면 현재 프로그램 실행 디렉토리가 디폴트로 사용됨
     nShow := SW_SHOWNORMAL; // 프로그램이 실행되는 윈도우 형태를 지정할 수 있습니다. ACTIVE, 최대화, 최소화 등등...
   end;
   if ShellExecuteEx(@SEInfo) then begin
     repeat
       Application.ProcessMessages;
       GetExitCodeProcess(SEInfo.hProcess, ExitCode) ;
     until (ExitCode <> STILL_ACTIVE) or
Application.Terminated;
     ShowMessage('프로그램이 종료되었습니다.') ;
   end
   else ShowMessage('프로그램을 실행하지 못했습니다.') ;
end;
같이 코드를 작성하면 됩니다.
Posted by 훅크선장
, |
ipAddresses 라는 TStringList에 IP 주소 문자열이 있다고 가정할 때,
동일한 IP주소가 몇 개나 있는지 찾고, 그 결과를 출력하는 예제입니다.
꼭 IP 주소가 아닌, 일반 문자열이나 단어등에도 적용해 볼 수 있습니다.

AddObject로 문자열의 개수를 추가하는 방식이라서, 간단하게 결과를 볼 수 있습니다.
아래 펌글에 좀 더 빠른 방법이 제안되어 있습니다만, 대용량이 아니라면 이것만 가지고도 충분히 빠른 결과를 볼 수 있습니다.

procedure TForm1.Button1Click(Sender: TObject);
var
  ls : TStringList;
  ip : string;
  ipAddresses : TStringList;
  n : integer;
  I: Integer;
begin
  memo1.Lines.Clear;
  memo2.Lines.Clear;

  ipAddresses := TStringList.Create;
  ipAddresses.Add('192.168.10.1');
  ipAddresses.Add('192.168.1.10');
  ipAddresses.Add('192.168.1.1');
  ipAddresses.Add('192.168.10.1');
  ipAddresses.Add('192.168.1.1');
  ipAddresses.Add('192.168.1.10');
  ipAddresses.Add('192.168.1.1');
  ipAddresses.Add('192.168.1.10');

  ls := TStringList.Create;
  ls.Sorted := true;
  for ip in ipAddresses do begin
    n := ls.IndexOf(ip);
    if n = -1 then
      ls.AddObject(ip, TObject(1))
    else
      ls.Objects[n] := TObject(Integer(ls.Objects[n]) + 1);
  end;

  memo1.Lines := ls;
  for I := 0 to ls.Count - 1 do
  begin
    memo2.Lines.Add(IntToStr(Integer(ls.Objects[I])));
  end;

end;
Posted by 훅크선장
, |
http://www.matsgefvert.se/blog/archives/651
에서 가져온 글입니다.

StringList상에 있는 동일한 문자열 개수 세기 샘플 코드와
StringList의 검색속도를 증가시키는 방법이 나와있습니다.
----------------------------------------------------------------------------------

Speeding Up Delphi’s TStringList.IndexOf
1 June 2009, 15:33 ? Music, Software Development
Delphi’s TStringList is one of the objects I love the most. If it’s sorted (StringList.Sorted := true) then you can use it to parse huge chunks of data quickly.

For instance, looping through an enormous amount of IP addresses and keeping count of how many times they appeared, is easily done using the following code (not compiled or checked for syntax errors):

ls := TStringList.Create;
ls.Sorted := true;
for ip in ipAddresses do begin
  n := ls.IndexOf(ip);
  if n = -1 then
    ls.AddObject(ip, TObject(1))
  else
    ls.Objects[n] := TObject(Integer(ls.Objects[n]) + 1);
end;
It’s very efficient. Since TStringList.IndexOf always does a binary search, it operates in log2(n) time, and using Objects as integers allows us to keep track of count without messing with the string data.

But there are things we can do to speed it up. For instance, TStringList.IndexOf relies on TStringList.Find, which itself uses AnsiCompareStr, which is a slow Windows call, taking locale and its mother into consideration. Overriding this with our own method should be worthwhile. (The code below is adapted straight from the Classes unit.)

type
  TStringListEx = class(TStringList)
  public
    function Find(const S: string; var Index: Integer): Boolean; override;
  end;

function TStringListEx.Find(const S: string; var Index: Integer): Boolean;
var
  L, H, I, C: Integer;
begin
  Result := False;
  L := 0;
  H := Count - 1;
  while L <= H do
  begin
    I := (L + H) shr 1;
    C := CompareStr(Get(I), S);
    if C < 0 then L := I + 1 else
    begin
      H := I - 1;
      if C = 0 then
      begin
        Result := True;
        if Duplicates <> dupAccept then L := I;
      end;
    end;
  end;
  Index := L;
end;
We’ve replaced AnsiCompareStr with Delphi’s own CompareStr, which is a highly optimized FastCode routine. There are some drawbacks ? things will always be sorted in byte order and no case-sensitivity is done. But we don’t care about this ? it can always be done afterwards; right now, speed is the main importance.

And it turns out that using the above code, in pure examples, can slash execution time with up to about 80%. Dramatic savings, indeed. In my own example, where I analyze ftp log data, I managed to cut execution time on 122 MB of data down from 7 seconds down to 3.1 seconds.

Best of all, since TStringList.Find is declared virtual, we don’t need to change any types anywhere, just do a TStringListEx.Create instead of a TStringList.Create and you’re good to go.




Posted by 훅크선장
, |
http://www.delmadang.com/
델마당의 “강좌, 팁, 정보” 게시판에서 가져온 글입니다.

대웅
(klol)
2009-01-12 오후 11:39:47

이 쓰신 글입니다.
----------------------------------------------------------------------------------

DBGrid자료를 엑셀로 보내는 함수입니다.

uses
      dbgrids, ComObj, Excel2000, Clipbrd;
.....

procedure ToExcle(vDBGrid: TDBGrid);
var
  XL: Variant;
  i,k: integer;
  sData: string;
begin
  try
    XL := CreateOLEObject('Excel.Application');
  except on E: Exception do
  begin
    ShowMessage('Excel OLE object를 오픈할 수 없습니다.'+E.Message);
    Exit;
  end; end;
  try
    XL.WorkBooks.Add; //새로운 페이지 생성
    XL.Visible := False;
    XL.Workbooks[XL.Workbooks.Count].WorkSheets[1].Name := 'Sheet1';
    sData := '';
    for i := 0 to vDBGrid.Columns.Count - 1 do
    begin
      sData := sData+vDBGrid.Columns[i].Title.Caption+#9;
      if vDBGrid.Columns[i].Field.DataType in [ftString,ftMemo,ftWideString] then
      begin
        XL.Workbooks[XL.Workbooks.Count].WorkSheets['Sheet1'].Columns[i+1].Select;
        XL.Selection.NumberFormatLocal := '@';
      end;
    end;
    sData := sData+#$D#$A;

    with vDBGrid do
    begin
      k := 0;
      DataSource.DataSet.First;
      while not DataSource.DataSet.Eof do
      begin
        inc(k);
        for i := 0 to Columns.Count - 1 do
          sData := sData+Columns[i].Field.AsString+#9;
        sData := sData+#$D#$A;
        DataSource.DataSet.Next;
      end;
    end;

    Clipboard.SetTextBuf(PChar(sData));
    XL.Cells[1,1].Pastespecial;
    XL.Range['A1', Chr(64+vDBGrid.Columns.Count)+IntToStr(k)].select;
    XL.Selection.Columns.AutoFit;
    XL.Range['A1', 'A1'].select;
    XL.Visible := True;
  except on E: Exception do
  begin
    ShowMessage('Excel로 자료를 보내는 중 오류가 발생했습니다.'+E.Message);
    XL.Visible := True;
    Exit;
  end; end;
end;

테스트결과 아주 잘 되는군요.

Posted by 훅크선장
, |
http://topopen.egloos.com/3211897 에서 가져왔습니다.

StringGrid를 아직 안 써봤지만, 앞으로 쓸 일이 있을 것 같습니다.

[Delphi] 델파이 excel export 소스

아래는 델마당 소스 발췌한 내용입니다.
---------------------------------------------------------------------
스트링그리드이 내용을 excel로 저장하는 델파이 소스입니다..

그런데, 제가 델은 잘 몰라서....변환을 할 수가 없군요..

소스는 한델에서 얻었구요... 빌더로 변환해 주세요..^^

소스는 아래와 같습니다..

1. StringGrid 예제
Uses절 ComObj 포함..

procedure TshGridX.run_excel;
var
  XL, XArr: Variant;
  i, j: Integer;
begin
  //데이타 처리변수
  XArr := VarArrayCreate([1, StringGrid1.ColCount], VarVariant);

  try
  //엑셀을 실행
    XL := CreateOLEObject('Excel.Application');
  except
    MessageDlg('Excel이 설치되어 있지 않습니다.', MtWarning, [mbok], 0);
    Exit;
  end;

  XL.WorkBooks.Add; //새로운 페이지 생성
  XL.Visible := True;
  
  for i := 0 to StringGrid1.RowCount - 1 do begin
    for j := 0 to StringGrid1.ColCount - 1 do begin
      XArr[j+1] := StringGrid1.Cells[j,i];
    end;
    //엑셀에 값을 넣는다.
    XL.Range['A' + IntToStr(i+1), CHR(64 + StringGrid1.ColCount) + IntToStr(i+1)].Value := XArr;
  end;

  //셀 크기 조정
  XL.Range['A1', CHR(64 + StringGrid1.ColCount) + IntToStr(i+1)].Select;
  XL.Selection.Columns.AutoFit;
  XL.Range['A1', 'A1'].Select;
end;
Posted by 훅크선장
, |
정상적인 윈도우즈 운영체제에서 Excel 이 깔려있다면,
대부분의 그리드 형태나 리스트뷰 내용을 Excel로 바로 띄워 볼 수 있다.
바로 Excel이 지원하는 형태로 저장할 수 있다는 의미이다.

일단  uses ComObj;  를 추가하여야 엑셀 컴포넌트 기능을 사용할 수 있다.

다음과 같이 한다.

procedure TForm1.BtnExcelViewClick(Sender: TObject);
var
  XL, XArr: Variant;
  i, j: Integer;
begin
  //데이타 처리변수
  XArr := VarArrayCreate([1, ListView1.Columns.Count], VarVariant);

  try
    //엑셀을 실행
    XL := CreateOLEObject('Excel.Application');
  except
    MessageDlg('Excel이 설치되어 있지 않습니다.', MtWarning, [mbok], 0);
    Exit;
  end;

  XL.WorkBooks.Add; //새로운 페이지 생성
  XL.Visible := True;

  // 제목 행 생성
  XArr[1] := '첫번째열';
  XArr[2] := '두번째열';
  XArr[3] := '세번째열';
  XArr[4] := '네번째열';
  XArr[5] := '다섯번째열';
  XL.Range['A1', CHR(64 + ListView1.Columns.Count) +  IntToStr(1)].Value := XArr;

  for i := 0 to ListView1.Items.Count - 1 do begin
    for j := 0 to ListView1.Columns.Count - 1 do begin
      if j = 0 then XArr[j+1] := ListView1.Items.Item[i].Caption
      else XArr[j+1] := ListView1.Items.Item[i].SubItems[j-1];
    end;
    //엑셀에 값을 넣는다.
    XL.Range['A' + IntToStr(i+2), CHR(64 + ListView1.Columns.Count) +  IntToStr(i+2)].Value := XArr;
  end;

  //셀 크기 조정
  XL.Range['A1', CHR(64 + ListView1.Columns.Count) + IntToStr(i+1)].Select;
  XL.Selection.Columns.AutoFit;
  XL.Range['A1', 'A1'].Select;
end;


Posted by 훅크선장
, |
http://tolyn.net/24

Delphi2007(CodeGear RAD Stduio 2007) 을 설치하면 기본적으로 Indy10이 설치된다.
9와 10 중 원하는것을 설치할 수 있던것과는 대조적인데..
Indy10보다는 9쪽을 애용하는 분들이 훨신 많은게 현실이다.
그래서 여기에 Indy9를 사용 하는 방법을 소개한다


 

1. 일단 Component 메뉴에서 Install Packages 를 선택한다

 

그중 붉은 사각형에 있는 Indy10 관련 컴포넌트의 체크를 제거한다.

그 후 ADD버튼을 누르면 아래와 같은 창이 나올텐데

 
dclindy100.bpl 을 골라 설치한다.
이 파일은 RADStudio 설치폴더 \ bin 에 존재한다. 
(기본경로는 C:\Program Files\CodeGear\RAD Studio\5.0\bin)


그 뒤에 옵션창을 열고 

붉은 사각형 안에 있는 Indy10 으로 된 패스를 전부 Indy9로 고쳐주면 된다.


자 이제 우리는 Indy9를 사용 할 수 있다.
맘껏 네트워크 프로그램을 짜 보자 


ps. RAD Studio 2007 에는 현재(07년 4월 23일) Indy9의 최신버젼이 들어있는 것으로 확인되었다
Posted by 훅크선장
, |
http://support.codegear.com/article/39426
의 내용을 번역해보았습니다.

다음은 Delphi 2009, C++Builder 2009을 언인스톨하기 위한 일반적인 수순입니다.:

Windows XP가 설치된 컴퓨터에서의 기본적인 수순입니다.

“시작”메뉴에서 [CodeGear RAD Studio 2009 | Modify, Repair, Uninstall]을 선택하여, 언인스톨을 시작합니다.
CodeGear RAD Studio를 설치했던 (디폴트 경로는 C:\Program Files\CodeGear\RAD Studio\6.0) 디렉토리를 삭제합니다.
C:\Documents and settings\All Users\Documents\Rad Studio\6.0 디렉토리를 삭제합니다.
C:\Documents and Settings\All Users\Application Data\Codegear\Rad Studio\6.0 디렉토리를 삭제합니다.

레지스트리의 HKEY_LOCAL_MACHINE\SOFTWARE\CodeGear\BDS\6.0 을 삭제합니다.
레지스트리의 HKEY_CURRENT_USER\SOFTWARE\CodeGear\BDS\6.0 을 삭제합니다.
레지스트리의 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{A2B58B18-5D04-4006-9713-B6945880746E} 을 삭제합니다.
레지스트리의 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CodeGear RAD Studio 2009 을 삭제합니다.

C:\Documents and Settings\All Users\Application Data\ 디렉토리 밑에 GUID값으로 만들어진 디렉토리를 삭제합니다.
*** 레지스트리 HKEY_LOCAL_MACHINE\Software\MimarSinan\InstallAware\Ident.Cache\ 의 서브키를 보면 디렉토리명으로 사용된 GUID를 알 수 있다. ***

C:\Windows\System32 디렉토리 밑에 다음과 같은 파일들이 남아있다면 삭제합니다.
모든 *120.bpl (*는 임의의 문자열을 지칭) 파일들
모든 *120.jdbg (*는 임의의 문자열을 지칭) 파일들
모든 *120.xml (*는 임의의 문자열을 지칭) 파일들
모든 bdeadmin.* (*는 임의의 문자열을 지칭) 파일들
모든 cc32*.dll (*는 임의의 문자열을 지칭) 파일들
모든 midas.* (*는 임의의 문자열을 지칭) 파일들
모든 xerces*.dll (*는 임의의 문자열을 지칭) 파일들
모든 Tee*120*.bpl (*는 임의의 문자열을 지칭) 파일들

Windows Vista가 설치된 컴퓨터에서의 기본적인 수순입니다.

“시작”메뉴에서 [CodeGear RAD Studio 2009 | Modify, Repair, Uninstall]을 선택하여, 언인스톨을 시작합니다.
CodeGear RAD Studio를 설치했던 (디폴트 경로는 C:\Program Files\CodeGear\RAD Studio\6.0) 디렉토리를 삭제합니다.
C:\Users\Public\Public Documents\Rad Studio 디렉토리를 삭제합니다.
C:\ProgramData\CodeGear\Rad Studio\6.0 디렉토리를 삭제합니다.

레지스트리의 HKEY_LOCAL_MACHINE\SOFTWARE\CodeGear\BDS\6.0 을 삭제합니다.
레지스트리의 HKEY_CURRENT_USER\SOFTWARE\CodeGear\BDS\6.0 을 삭제합니다.
레지스트리의 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{A2B58B18-5D04-4006-9713-B6945880746E} 을 삭제합니다.
레지스트리의 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CodeGear RAD Studio 2009 을 삭제합니다.

C:\Documents and Settings\All Users\Application Data\ 디렉토리 밑에 GUID값으로 만들어진 디렉토리를 삭제합니다.
*** 레지스트리 HKEY_LOCAL_MACHINE\Software\MimarSinan\InstallAware\Ident.Cache\ 의 서브키를 보면 디렉토리명으로 사용된 GUID를 알 수 있다. ***

C:\Windows\System32 디렉토리 밑에 다음과 같은 파일들이 남아있다면 삭제합니다.
모든 *120.bpl (*는 임의의 문자열을 지칭) 파일들
모든 *120.jdbg (*는 임의의 문자열을 지칭) 파일들
모든 *120.xml (*는 임의의 문자열을 지칭) 파일들
모든 bdeadmin.* (*는 임의의 문자열을 지칭) 파일들
모든 cc32*.dll (*는 임의의 문자열을 지칭) 파일들
모든 midas.* (*는 임의의 문자열을 지칭) 파일들
모든 xerces*.dll (*는 임의의 문자열을 지칭) 파일들
모든 Tee*120*.bpl (*는 임의의 문자열을 지칭) 파일들
Posted by 훅크선장
, |