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;

WM_QUIT 는 종료 메세지이다.
라는 말을 믿고 VCL 에서 윈도우 핸들을 얻어
WM_QUIT 메세지를 보냈는데 종료되지 않는다.

아 이런...
WndProc 메소드를 override 해서
WM_QUIT 시에 PostQuitMessage(Message.WParam) 을 넣어주니 잘 동작하는데...
그렇다면 이 메세지 처리가 안되있다는 말인가.

TApplication.ProcessMessage 에서 WM_QUIT 이 오면
FTerminated := False; 가 되있는데 왜 동작하지 않지...

일단, WM_SYSCOMMAND 메세지를 WParam = SC_CLOSE 로 해서 종료시키기는 했다.

procedure WaitForWindowDestroy(lpClassName, lpWindowName: PChar);
var
  H: HWND;
  Value: DWORD;
begin
  H := FindWindow(lpClassName, lpWindowName);
  if H = 0 then raise Exception.Create('FindWindow failed');

  GetWindowThreadProcessId(H, @Value);
  H := OpenProcess(PROCESS_ALL_ACCESS, False, Value);
  if H = 0 then raise Exception.Create('OpenProcess failed');

  try
    GetExitCodeProcess(H, Value);
    while Value = STILL_ACTIVE do
      GetExitCodeProcess(H, Value);
  finally
    CloseHandle(H);
  end;
end;

'Windows > RAD Studio' 카테고리의 다른 글

[SOCK] 소켓 에러 목록  (0) 2008.04.16
[RAD] TListBox - Horizontal Scroll Bar  (0) 2008.04.08
[RAD] TCanvas 의 글자 폭, 높이 구하기  (0) 2008.03.17
[CB] Excel binary 저장  (0) 2008.03.13
TComponentState type  (0) 2008.03.05
TCanvas 에는 TextWidth, TextHeight 가 있어 폭과 높이를 구할 수 있다.
TListBox, TListView, TStringGrid 등에서 CustomDraw 를 할 경우 텍스트 위치를 잡아주기 위해 필요한 정보다.
그 함수를 들여다 보면 둘 모두 TextExtent 를 호출하여 가로, 세로 폭을 얻은 뒤 한 쪽 정보만을 넘겨준다.
한 쪽 정보만 필요하다면 어차피 같겠지만 가로, 세로 모두 필요한 경우 저 두 함수를 호출 하면 크기 정보를 두번 가져오게 된다.
그냥 TextExtent 를 직접 호출 하여 TSize 형태의 정보로 가져온 뒤 값을 참조 한다면 쓸데없는 호출은 줄일 수 있다.

'Windows > RAD Studio' 카테고리의 다른 글

[RAD] TListBox - Horizontal Scroll Bar  (0) 2008.04.08
[DEL] 외부 프로세스 종료 대기하기  (0) 2008.03.17
[CB] Excel binary 저장  (0) 2008.03.13
TComponentState type  (0) 2008.03.05
[RAD] SendMessage 의 Param 자료형  (0) 2008.02.29
Excel 파일 생성을 Ole 가 아닌 Binary 모드에서 하는 것이다.
포맷이 공개되지 않은 상태에서의 코드이기에 한 셀 당 단일 자료 저장만 되는 코드다.

자세한 내용은 코드 참조

TComponentState 는 현재 컴포넌트의 상태를 묘사하는 표시문자 집합이다.

유닛
Classes

델파이 문법:
type TComponentState = set of (csLoading, csReading, csWriting, csDestroying, csDesigning, csAncestor, csUpdating, csFixups, csFreeNotification, csInline, csDesignInstance);

C++ 문법:
enum Classes__34 { csLoading, csReading, csWriting, csDestroying, csDesigning, csAncestor, csUpdating, csFixups, csFreeNotification, csInline, csDesignInstance };

typedef Set<Classes__34, csLoading, csDesignInstance>  TComponentState;

설명
TComponentState 는 TComponent 인스턴스의 ComponentState 속성의 가능한 상태 집합을 정의한다. 아래 표는 TComponentState 유형과 각 표시 문자에 대응하는 의미의 목록을 보여준다.

표시 문자: 컴포넌트 상태
csAncestor: 컴포넌트가 조상 폼에 삽입되었다.csDesigning 이 설정된 상태에서 설정된다.
csDesigning: 컴포넌트가 폼 위에 있고 폼 디자이너에 의해 조정됨.
csDestroying: 컴포넌트가 소멸 될 때.
csFixups: 컴포넌트가 로드되지 않은 다른 폼의 컴포넌트와 연결되었음. 이 표시는 모든 연결이 해결되었을 때 지워진다.
csFreeNotification: 하나 이상의 컴포넌트들이 이 컴포넌트가 파괴될 때 알려달라고 요청하였다. 이 표시 문자는 다른 컴포넌트가 이 컴포넌트의 FreeNorification 메소드를 호출할 때 설정된다.
csInline: 컴포넌트가 최상위 컴포넌트로 디자인 시에 수정할 수 있고 또한 폼에 넣을 수 있다. 이 표시문자는 읽거나 쓰는 중에 포함된 프레임을 식별하기 위해 사용된다.
csLoading: filer 객체가 현재 컴포넌트를 로드하고 있다. 이 표시 문자는 컴포넌트가 처음 생성되고 컴포넌트와 이에 포함된 자식 컴포넌트들이 초기화 되지 않았을 때 까지 설정된다. (Loaded 메소드가 호출되었을 때).
csReading: 스트림에서 속성 값을 읽고 있는 상태. 참고로 csReading 이 설정되었을 때 csReading 이 항상 설정된다. 다시 말하면, csReading 은 컴포넌트가 불러오는 중 속성 값을 덮어 쓰는 시간의 부분 구간에서 설정한다.
csUpdating: 컴포넌트가 조상 폼의 변화를 반영하기 위해 갱신된다. csAncestor 가 설정된 상태에서 설정된다.
csWriting: 속성 값을 스트림에 쓰고 있는 상태.
csDesignInstance: 컴포넌트가 디자이너에서 뿌리 객체다. 예를 들어, it is set for a frame when you are designing it, but not on a frame that acts like a component. 이 표시 문자는 csDesigning 과 함께 나타난다.

'Windows > RAD Studio' 카테고리의 다른 글

[RAD] TCanvas 의 글자 폭, 높이 구하기  (0) 2008.03.17
[CB] Excel binary 저장  (0) 2008.03.13
[RAD] SendMessage 의 Param 자료형  (0) 2008.02.29
[DEL] Parameter 에서 const, var 키워드  (0) 2008.02.27
[RAD] default 키워드  (0) 2008.02.27

오늘 SendMessage 의 Param 의 형태가 C++, Delphi 언어마다 다르다는 소리에 발끈해 뒤졌다. 도대체 API 함수인데 어떻게 다를 수가 있고, Delphi 는 포팅해서 쓴다는 소리는 뭐냐고, Windows 유닛에 뻔히 있는데 다른데 있다니...

글 아래의 자료는 거슬러 올라가며 관련 선언을 다 모아 놓은 것이니 참고하시길...
결론은 SendMessage 의 Param 은 둘다 32-bit unsigned integer 다.

무슨 에러가 났네 어쩌내 해대서 더 찾아봤더니...
VCL 의 메세지 처리 프로시저의 매개변수인 TMessage 의 Param 들은 32-bit signed integer 형이다.

-2147483648..2147483647 signed 32-bit
0..4294967295 unsigned 32-bit

2147483647 이상의 값은 TMessage 로 받아보면 음수가 되는 것이다.
그 상황은 아마 signed 와 unsigned 를 비교해 놓고 안되네 어쩌네 한 것이겠지...
답답하다.

SendMessage 는 32비트의 자료를 안전하게 전송해 줬는데 자료 이용을 잘 못하고...
이 글을 보는 이들은 이런 실수 하지마시길...

피해가려면 VCL 의 메세지 맵을 쓰지 말고 CALLBACK 프로시저를 하나 만들어서 Sub-Classing 하세요. 직접 unsigned 형으로 받으면... 그래도 실수할 수 없겠지. ㅋ


'Windows > RAD Studio' 카테고리의 다른 글

[CB] Excel binary 저장  (0) 2008.03.13
TComponentState type  (0) 2008.03.05
[DEL] Parameter 에서 const, var 키워드  (0) 2008.02.27
[RAD] default 키워드  (0) 2008.02.27
[DEL] TMessage.Msg 문자열 변환  (0) 2008.02.26

procedure Test(var AParam);
begin
  ShowMessage(PChar(AParam));
  String(AParam) := '호이' ;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  S: String;
begin
  S := '하이';
  Test(S);
  ShowMessage(S);
end;

위 코드가 수행되면 Button1 클릭 시
'하이' 메세지창 -> '호이' 메세지창 이 뜬다.

Test 함수의 인자 값에 변수 형을 명시하지 않으면, Pointer 또는 다른 어떤 타입이 와도 되는 것 같다.

var -> const 로 변환을 할 경우도 유사하다.
어느 타입도 받으면서 값 변경은 방지한다.

마치 C++ 의 Template 과 같은 느낌이다.

Delphi 만 쓴다면 꽤 괜찮아 보이지만, C++ 변환시 혼동이 올 가능성이 있으므로 사용은 피하자.

'Windows > RAD Studio' 카테고리의 다른 글

TComponentState type  (0) 2008.03.05
[RAD] SendMessage 의 Param 자료형  (0) 2008.02.29
[RAD] default 키워드  (0) 2008.02.27
[DEL] TMessage.Msg 문자열 변환  (0) 2008.02.26
[CB] MMTimer 를 이용한 수행시간 확인  (0) 2008.02.26
property 에 default 설정은 기본 값 설정으로 알고 있었다.
C++Builder 를 먼저 했으니 당연히 저렇게만 알고 있었는데...
Delphi 에는 조금 다른 이용이 가능하다.

  TStrings = class(TPersistent)
  public
    property Strings[Index: Integer]: string read Get write Put; default;
  end;

값 설정 없는 default 다.
저 경우
Str := TString.Create;
Str[0] := 'asdf';
와 같은 이용이 가능한 것이다.

C++ 에는 위의 방법이 안된다.
그런데... VCL 코드의 변환된 헤더를 살펴보니 연산자 중첩으로 해결해 놓은 것이다.

class DELPHICLASS TStrings;
class PASCALIMPLEMENTATION TStrings : public TPersistent
{
public:
    AnsiString operator[](int Index) { return Strings[Index]; }
    __property AnsiString Strings[int Index] = {read=Get, write=Put/*, default*/};
};

/*, default*/ 라는 눈속임의 주석...
어쨌든 코드의 동작은 똑같다.

TMessge 의 Msg 값은 Cardinal(숫자) 형이라 알아보기 불편해 변환 함수 작성했다.
힘들었다. -ㅅ-;

uses
  MsgStrUtils;

MsgToStr(ComboBox1, Message.Msg);


수정내역

080705 C++Builder 6.0 에서 없는 메세지에 대한 선언 처리
          TScrollBar 처리 버그 수정




'Windows > RAD Studio' 카테고리의 다른 글

[DEL] Parameter 에서 const, var 키워드  (0) 2008.02.27
[RAD] default 키워드  (0) 2008.02.27
[CB] MMTimer 를 이용한 수행시간 확인  (0) 2008.02.26
[DEL, CB] Proxies  (0) 2008.02.13
[DEL] Splash 없이 실행  (0) 2008.02.13

+ Recent posts