TCollection, TCollectionItem 에서 파생시켜 리스트를 만들고
TCollectionItem 에 이벤트 속성을 넣고 개발시에 이벤트를 생성하려고 하면 오류가 난다.
기존 작성된 메소드 연결은 되는데 생성시만 "Cannot create a method for an unnamed
component" 메세지와 함께 오류가 난다.

원인은 TCollection 에서 GetNamePath 를 호출 할 때 부모 클래스 이름이 없기 때문이다.
GetOwner 라는 메소드에서 Owner 객체가 반환 되어야 하는데,
기본적으로 TPersistent 의 메소드에서 nil(NULL) 을 반환한다.

해결 방법은 Owner 를 기억하고 있다가 GetOwner 메소드로 반환시키면 된다.
이를 구현해 놓은 클래스가 있는데 TOwnedCollection 이다.
TCollection 부분을 TOwnedCollection 으로 고치면 잘 동작할 것이다.

참고: http://delphi.newswhat.com/geoxml/forumhistorythread?groupname=borland.public.delphi.vcl.components.writing.general&messageid=40825226@newsgroups.borland.com

Design-time Package 란 말 그대로 디자인 시에 필요한 것들이다.
Component editor, Property editor 들이 이에 해당한다.
뭔가 어려운 작업 같지만... 그럴게 없다.

Runtime package 에는 컴포넌트 코드를 넣는다. (Register 함수 제거하고~)
Design-time package 에는 Editor 코드와 Register 함수를 모은 유닛을 넣는다.
그리고 프로젝트 옵션에서 해당 Package 타입을 변경한다.

컴포넌트 배포시에는 Runtime package 는 bpl 만 Design-time package 는 obj, h, bpk 같은 부분만 배포하면 되고,
컴포넌트를 이용한 실행 파일 배포에는 Runtime package 의 bpl 만 배포하면 된다.







080425 - 문자 삭제에 따른 이전 '-' 위치 값 변경 수정
             ExtractFloat 추가

숫자에 사용되는 문자('-', '.') 에 대한 처리가 되어있다.

일반적인 변환에 관해서는 StrToInt 가 더 빠르게 동작하므로,
예외 상황이 가끔 발생하는 경우 TryStrToint 를 이용한 뒤 변환되지 않은 경우 적용하면 된다.






TPersistent 에서 상속된 클래스만 가능한 방법이다.

DefineProperties 메소드를 구현해주면 된다.
TFiler 를 매개변수로 받고 DefineProperty 메소드를 이용해서
Load, Write, CanDo 메소드를 인자 값으로 넣어준다.

Load 메소드의 인자 값은 TReader 형태
Write 메소드의 인자 값은 TWriter 형태
CanDo 메소드의 인자 값은 TFiler 형태로 받고

CanDo 에서는 Filer->Ancestor 와 비교해서 가능 여부를 반환하고
나머지는 각 인자 값으로 넘어온 객체를 이용해 Load/Write 하면 된다.
-------------------------------------------------------------------

복합적인 Property 의 경우 Binary 로 저장이 가능하다.
Binary 저장은 다음과 같다.

        Filer->DefineBinaryProperty("Cells", ReadCells, WriteCells, DoCells(Filer));

배열로 잡혀진 객체를 저장하는데 이 코드를 썼는데, 객체에 Read/Write 메소드를 구현하여,
ReadCells, WriteCells 에서는 이를 호출만 하게 해주면된다.

객체의 Read/Write 메소드 구현은 파일 저장과 같다.
TStream 을 받아서 저장을 하게 되는데
TTreeView 의 경우는 자료 저장용 구조체를 따로 만들어 값을 넣고 Read/Write 를 한다.

이 때, 주의할 점은 문자열 처리다.
문자열은 가변길이이기 때문에 구조체의 맨 마지막에 와야한다.
Delphi 의 string 과 C++Builder 의 AnsiString 은 다른 형태라 같은 루틴을 사용할 수 없다.
Delphi 의 코드를 보면 255 크기의 string 변수를 생성하고 값을 대입하고 크기를 구해서 크기와 값을 저장하고 읽어온다.
C++Builder 에서는 클래스를 바로 저장할 수 없기에 (포인터 값이 저장되어 난리난다.)
char [255] 배열을 생성해서 비슷한 구현을 하면된다.
다만 Write 시에는 strncpy 로 값을 복사해 줘야 하지만, Read 시에는 그냥 대입하면 자동 String 변환이 된다.

DbugIntf.pas 유닛을 추가한다.

StartDebugWin(): Debug window 시작

SendDebugClear(): 메세지 초기화
SendSeparator(): 구분자 표시
SendDebugPause(void): 메세지 받기 정지
SendDebugResume(void): 메세지 받기 재시작

SendDebugEx(const AnsiString Msg, Dialogs::TMsgDlgType MType): 실제 메세지 전송 메소드. 메세지와 TMsgDlgType 을 인자로 받는다.

SendDebugFmtEx(const AnsiString Msg, const System::TVarRec * Args, const int Args_Size, Dialogs::TMsgDlgType MType): 특정 포맷의 특정 메세지 출력. SendDebugEx(Format(Msg, Args), MType);
SendDebugFmt(const AnsiString Msg, const System::TVarRec * Args, const int Args_Size): 특정 포맷의 알림 메세지 출력. SendDebugEx(Format(Msg, Args), mtInformation);

SendDebug("메세지"): 알림 메세지 출력. SendDebugEx(Msg, mtWarning);
SendDebugError("메세지"): 에러 메세지 출력. SendDebugEx(Msg, mtError);
SendDebugWarning("메세지"): 경고 메세지 출력. SendDebugEx(Msg, mtInformation);

SendMethodEnter("메소드 시작"): 알림 메세지 출력 + Indent 증가.
SendMethodExit("메소드 종료"): 알림 메세지 출력 + Indent 감소
SendBoolean("Enabled", Enabled): Boolean 출력
SendInteger("Tag", Tag): Integer 출력
SendDateTime("DataTimePicker1->Time", DataTimePicker1->Time): TDateTime 출력


사용법
1. 직접 대입 방법
    TDiv A;
    A.Value = 6;
    int Div16 = IntToStr(A.Div16);
    int Mod16 = IntToStr(A.Mod16 & 0x0F);

2. int 변수를 형변환 방법
    int A = 6;
    int Div16 = IntToStr(((TDiv*)&A)->Div16);
    int Mod16 = IntToStr(((TDiv*)&A)->Mod16 & 0x0F);

주의사항
  나머지는 꼭 해당비트 값만 참고할 수 있게 & 연산을 해주어야 한다는 것.

문자열(S)의 중간 위치(Offset)부터 특정 문자열(SubStr) 찾기

int __fastcall PosEx(const String &SubStr, const String &S, int Offset = 1)
{
    if (Offset <= 1) return S.Pos(SubStr);

    int i = Offset;
    int LenSubStr = SubStr.Length();
    int Len = S.Length() - LenSubStr + 1;

    while (i <= Len)
    {
        if (S[i] == SubStr[1])
        {
            int x = 1;
            while (x < LenSubStr && S[i + x] == SubStr[x + 1]) x++;
            if (x == LenSubStr) return i;
        }
        i++;
    }
    return 0;
}

WSAEINTR           (10004): 'Interrupted system call';
WSAEBADF           (10009): 'Bad file number';
WSAEACCES          (10013): 'Permission denied';
WSAEFAULT          (10014): 'Bad address';
WSAEINVAL          (10022): 'Invalid argument';
WSAEMFILE          (10024): 'Too many open files';
WSAEWOULDBLOCK     (10035): 'Operation would block';
WSAEINPROGRESS     (10036): 'Operation now in progress';
WSAEALREADY        (10037): 'Operation already in progress';
WSAENOTSOCK        (10038): 'Socket operation on non-socket';
WSAEDESTADDRREQ    (10039): 'Destination address required';
WSAEMSGSIZE        (10040): 'Message too long';
WSAEPROTOTYPE      (10041): 'Protocol wrong type for socket';
WSAENOPROTOOPT     (10042): 'Protocol not available';
WSAEPROTONOSUPPORT (10043): 'Protocol not supported';
WSAESOCKTNOSUPPORT (10044): 'Socket type not supported';
WSAEOPNOTSUPP      (10045): 'Operation not supported on socket';
WSAEPFNOSUPPORT    (10046): 'Protocol family not supported';
WSAEAFNOSUPPORT    (10047): 'Address family not supported by protocol family';
WSAEADDRINUSE      (10048): 'Address already in use';
WSAEADDRNOTAVAIL   (10049): 'Address not available';
WSAENETDOWN        (10050): 'Network is down';
WSAENETUNREACH     (10051): 'Network is unreachable';
WSAENETRESET       (10052): 'Network dropped connection on reset';
WSAECONNABORTED    (10053): 'Connection aborted';
WSAECONNRESET      (10054): 'Connection reset by peer';
WSAENOBUFS         (10055): 'No buffer space available';
WSAEISCONN         (10056): 'Socket is already connected';
WSAENOTCONN        (10057): 'Socket is not connected';
WSAESHUTDOWN       (10058): 'Can''t send after socket shutdown';
WSAETOOMANYREFS    (10059): 'Too many references (can''t splice';
WSAETIMEDOUT       (10060): 'Connection timed out';
WSAECONNREFUSED    (10061): 'Connection refused';
WSAELOOP           (10062): 'Too many levels of symbolic links';
WSAENAMETOOLONG    (10063): 'File name too long';
WSAEHOSTDOWN       (10064): 'Host is down';
WSAEHOSTUNREACH    (10065): 'No route to host';
WSAENOTEMPTY       (10066): 'Directory not empty';
WSAEPROCLIM        (10067): 'Too many processes';
WSAEUSERS          (10068): 'Too many users';
WSAEDQUOT          (10069): 'Disc quota exceeded';
WSAESTALE          (10070): 'Stale NFS file handle';
WSAEREMOTE         (10071): 'Too many levels of remote in path';
WSAEDISCON         (10101): 'Disconnected';
WSASYSNOTREADY     (10091): 'Network sub-system is unusable';
WSAVERNOTSUPPORTED (10092): 'WinSock DLL cannot support this application';
WSANOTINITIALISED  (10093): 'WinSock not initialized';
WSAHOST_NOT_FOUND  (11001): 'Host not found';
WSATRY_AGAIN       (11002): 'Non-authoritative host not found';
WSANO_RECOVERY     (11003): 'Non-recoverable error';
WSANO_DATA         (11004): 'No Data';

void __fastcall ShowListBoxHScroll(TListBox *LB)
{
    int MaxWidth = 0;
    for (int i = LB->Items->Count; i--; )
        MaxWidth = Max(MaxWidth, LB->Canvas->TextWidth(LB->Items[I]));
    ::SendMessage(LB->Handle, LB_SETHORIZONTALEXTENT, MaxWidth + 6, 0);
}

procedure ShowListBoxHScroll(LB: TListBox);
var
  I: Integer;
  MaxWidth: integer;
begin
  MaxWidth := 0;
  for I := 0 to LB.Items.Count - 1 do
    MaxWidth := Max(MaxWidth, LB.Canvas.TextWidth(LB.Items[I]));
  SendMessage(LB.Handle, LB_SETHORIZONTALEXTENT, MaxWidth + 6, 0);
end;

+ Recent posts