2014. 2. 13. 10:23

Q&A 정리

Tform
[Q1] Delphi는 Code나 Form을 어떻게 저장하나요 ?
[A1] Form은 .DFM 화일로, Code는 .PAS로 저장합니다. .DFM 화일은 이진화일이므로 IDE 상태에서 열면 Form 형태로 화면에 나타납니다.

[Q2] Form을 화면에 보이지 않도록 하려면 ?
[A2] 가장 쉬운 방법은 Form의 Left, Top 위치를 -1000 정도의 값(화면에보이지 않을 위치)으로 지정하는 것입니다.

[Q3] 스크린의 resolution에 상관없이 항상 일정한 크기로 폼을 띄우는 방법은 무엇입니까 ?
[A3] 다음과 같이 Form의 height와 width를 실행시에 조정하도록 합니다.

implementation
const
ScreenWidth: LongInt = 800; {800x600 모드에서 설계한 경우}
ScreenHeight: LongInt = 600;

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
scaled := true;
if (screen.width <> ScreenWidth) then

begin
height := longint(height) * longint(screen.height) DIV ScreenHeight;
width := longint(width) * longint(screen.width) DIV ScreenWidth;
scaleBy(screen.width, ScreenWidth);
end;
end;

[Q4] 화면크기에 따라 component의 위치와 크기를 조정하려면 ?
[A4] 다음과 같이 프로그램한 후 테스트로 Form의 크기를 조절해 봅니다.

var oldwidth, oldheight : integer ;

procedure TForm1.FormCreate(Sender: TObject);
begin
oldheight := height ;
oldwidth := width ;
end;

procedure TForm1.FormResize(Sender: TObject);
var i : integer ;
px, py, t : real ;
begin
for i:= 0 to ComponentCount -1 do
if (Components[i] is TControl) then
begin
px := oldwidth / width ;
py := oldheight / height ;
t := (Components[i] as TControl).Top ;
(Components[i] as TControl).Top := trunc(t/py) ;

t := (Components[i] as TControl).Left ;
(Components[i] as TControl).Left := trunc(t/px) ;

t := (Components[i] as TControl).height ;
(Components[i] as TControl).height := trunc(t/py) ;

t := (Components[i] as TControl).width ;
(Components[i] as TControl).width := trunc(t/px) ;
end ;
oldheight := height ;
oldwidth := width ;
end;

[Q5] 사용자가 Form의 크기를 바꾸지 못하게 하려면 ?
[A5] WM_NCHITTEST message를 받아 처리합니다.

TForm1 = class(TForm)
private
{ Private declarations }
procedure WMNCHitTest(var Message : TWMNChitTest) ; message WM_NCHITTEST;
public
{ Public declarations }
end;

procedure WMNCHitTest(var Message:TWMNChitTest) ; message WM_NCHITTEST;
begin
if Message.Result = HTBOTTOM then Message.Result := HTCLIENT ;
end ;

[Q6] 폼이 화면의 중앙에 위치하도록 만들려면 ?
[A6] 프로그램이 처음 시작될 때 중앙에 위치시키려면 폼의 Position Property를PoScreenCenter로 설정하시면 됩니다.
또는 사용자가 폼의 크기를 바꾼 후에 위치를 조정하려면 다음과 같이 합니다.

{Pascal에서는 '/' 기호 대신에 'DIV'를 사용합니다}
Form1.Left := (Screen.Width - Form1.Width) div 2;
Form1.Top := (Screen.height - Form1.height) div 2;

[Q7] Form이 생성되거나, 보여질때 실행되는 Event Handler는 무엇이고 그 순서는 ?
[A7] Form이 생성될 때 OnCreate, OnShow, OnPaint, OnActivate, OnResize,다시 OnPaint Event Handler가 실행됩니다.

[Q8] Run-time시에 프로그램에서 Form을 생성시키려면 ?
[A8] 1. Options/Project에서 Auto-create forms 리스트에 있는 form을Available forms 리스트로 옮긴다.
2. 다음과 같이 프로그램 합니다.

implemetaton
uses unit2 ; {TForm2가 정의되어 있는 unit을 use 시킨다.}

procedure TForm1.Button1Click(Sender : TObject) ;
var f : TForm2 ;
begin
try
f := TFrom2.Create(Self) ;
f.ShowModal ;
finally
f.Free ;
end ;
end ;


Create Method는 새로운 폼을 생성하지만, 이미 생성된 폼은 절대 삭제되지않습니다. 그러므로 폼은 Free Method를 사용하여 자신의 Resource를 Free 시켜야합니다. 그렇지 않으면 위의 Event Handler가 실행될 때 마다 Windows Resource가감소될 것입니 다.

[Q9] Form을 Maximize하려면 ?
[A9] Resize event에서 폼의 크기를 조절하면 됩니다.
만약 이렇게 했을 때 뻔쩍거리는 현상이 나타난다면 다음과 같이 해 보십시오.

Form의 private section에 다음을 추가합니다.
procedure mymax(var m: TWMGETMINMAXINFO); message wm_getminmaxinfo;

다음 procedure를 implemetatoin section에 추가합니다.
procedure yourForm.mymax(var m : TWMGETMINMAXINFO);
begin
m.minmaxinfo^.ptmaxsize.x := screen.width;
m.minmaxinfo^.ptmaxsize.y := screen.height;
m.minmaxinfo^.ptmaxposition.x := 0;
m.minmaxinfo^.ptmaxposition.y := 0;
end;

[Q10] Form의 title bar를 없애려면 ?
[A10] 다음 procedure를 사용해 보십시오.

Procedure TYourFormName.HideTitlebar;
Var
Save : LongInt;
Begin
If BorderStyle=bsNone then Exit;
Save:=GetWindowLong(Handle,gwl_Style);
If (Save and ws_Caption)=ws_Caption then Begin
Case BorderStyle of
bsSingle, bsSizeable :
SetWindowLong(Handle,gwl_Style,Save and (Not(ws_Caption)) or ws_border);
bsDialog :
SetWindowLong(Handle,gwl_Style,Save and (Not(ws_Caption)) or ws_modalframeor ws_dlgframe);
End;
Height:=Height-getSystemMetrics(sm_cyCaption);
Refresh;
End;
end;


Procedure TYourFormName.ShowTitlebar;
Var
Save : LongInt;
begin
If BorderStyle=bsNone then Exit;
Save:=GetWindowLong(Handle,gwl_Style);
If (Save and ws_Caption)<>ws_Caption then Begin
Case BorderStyle of
bsSingle, bsSizeable :
SetWindowLong(Handle,gwl_Style,Save or ws_Caption or ws_border);
bsDialog :
SetWindowLong(Handle,gwl_Style,Save or ws_Caption or ds_modalframe or ws_dlgframe);
End;
Height:=Height+getSystemMetrics(sm_cyCaption);
Refresh;
End;
end;


[Q11] form event(onCreate, onPaint, 등)들이 실행되기 전에 form이 보이도록 하려면 ?
[A11] onCreate event에 "Visible := True"를 추가합니다.

[Q12] 크기 조정이 가능한 multi-split window를 어떻게 만듭니까 ?
[A12] 다음과 같이 합니다.

1) Memo 를 폼에 놓고 그것의 Align 프로퍼티를 alTop 으로 지정합니다.
2) Panel 을 폼에 놓고 Align 프로퍼티를 alTop 으로 지정합니다.
3) Panel의 Height 프로퍼티를 6이나 7쯤으로 둡니다.
4) Panel의 DragMode 프로퍼티를 dmAutomatic으로 둡니다.
5) Panel의 DragCursor 프로퍼티를 crVSplit으로 둡니다.
6) Panel의 Cursor 프로퍼티를 crVSplit으로 둡니다.
7) 또 다른 Memo를 폼에 놓고 Align 프로퍼티를 alClient로 둡니다.
8) Memo 와 Panel을 한꺼번에 선택하고, 다음의 OnDragOver핸들러를 연결합니다.

procedure TForm1.Memo1DragOver(Sender, Source : TObject;
X, Y : Integer; State: TDragState; var Accept: Boolean);
begin
Accept := False;
if Source = Panel1 then begin
Accept := True;
Memo1.Height := Y + (Sender as TControl).Top;
end;
end;

[Q13] Dialog box는 어떻게 사용합니까 ?
[A13] 다음과 같이 사용합니다.

FontDialog1.Font.Assign(Edit1.Font) ;
if FontDialog1.Execute then Edit1.Font.Assign(FontDialog1.Font) ;

[Q14] OnActivate Event에서 Form의 FormStyle 특성을 변경하려면 'CannotChange Visible in OnShow or OnHide' Error가 발 생합니다. 그 이유는 ?
[A14] FormStyle는 Window가 생성될때 결정되며, OnCreate Event에서 일반적인설정이 이루어 집니다. 그러므로 OnShow나 OnHid e, OnActivate event에서 사용될수 없습니다.

[Q15] 윈도우에서 폼이나 Image component를 Byte-Align하는 방법은 ?
[A15] CreateParams Method를 사용합니다.

Procedure TMyForm.CreateParams(Var Params : CreateParams);
Begin
inherited CreateParams(Params);
Style := Style or CS_BYTEALIGNWINDOWS;
End;

모든 고해상의 Video 모드들은 항상 Byte-Align이므로 위의 Code는 Monochrome,EGA, 16Color VGA 모드에서 의미가 있습니다.

[Q16] OnCloseQuery Event는 언제 사용합니까 ?
[A16] 일반적으로 onClose와 onCloseQuery는 해당 form이 close될 때 발생합니다.차이점은 onClose는 해당폼이 close할때 만 발생하지만 OnCloseQuery는 Parentform이 close될때도 발생됩니다.

TMemo
[Q17] TMemo에서 cursor가 있는 line 번호를 알수 있습니까 ?
[A17] EM_LINEFROMCHAR, EM_LINEINDEX 라는 Windows 메세지를 사용하여알 수 있습니다.

procedure GetMemoLine(Memo : TCustomMemo; var MemoLine, MemoCol : integer) ;
var
LineNum : Longint;
CharsBeforeLine : Longint;
begin
LineNum := SendMessage(Memo.Handle, EM_LINEFROMCHAR, Memo.SelStart, 0);
CharsBeforeLine := SendMessage(Memo.Handle, EM_LINEINDEX, LineNum, 0);
MemoLine := LineNum + 1;
MemoCol := Memo.SelStart - CharsBeforeLine + 1;
end;

procedure SetMemoLine(Memo : TCustomMemo; MemoLine, MemoCol : integer );
begin
Memo.SelStart := SendMessage(Memo.Handle,EM_LINEINDEX,MemoLine-1,0)+MemoCol-1;
end ;

[Q18] TMemoField와 TMemo간에 데이타를 주고 받으려면 ?
[A18] TMemo의 내용을 TMemoField로 보내려면 다음과 같이 합니다.

Table.Edit ;
TMemoField.Assign( TMemo.Lines );

반대로 TMemoField의 내용을 TMemo로 보내려면 다음과 같이 합니다.
VAR aBlobStream : TBlobStream;

aBlobStream := TBlobStream.Create(TMemoField, bmRead);
TMemo.Lines.LoadFromStream( aBlobStream );
aBlobStream.Free;

[Q19] TMemo에서 Tab Stop을 설정할 수 있습니까?
[A19] 다중열을 편집할 때 Tab키를 사용하기 위해 Tab Stop을 지정하는정수값 갯수와 Tab Stop 값을 가지고 있는 array po inter를 parameter로 EM_SetTabStops메세지를 TMemo component로 보냅니다.
또한 TMemo의 WantTabs property를 True로 설정하셔야 합니다.

Procedure TForm1.FormCreate(Sender:TObject);
const
TabInc:LongInt = 10;
Begin
SendMessage(Meno1.Handle,EM_SetTabStops,1,Longint(@TabInc));
End;

[Q20] Delphi에서 Memo 필드의 크기는 무엇입니까?
[A20] Delphi의 TEdit와 TMemo component는 MS Windows상의 응용프로그램이사용하는 일반 Edit Control 입니다.
그러므로 Windows가 제공하는 Edit Control은 공통적으로 32KB의 한계를 가지고있습니다.

[Q21] 한번에 TMemo나 TListBox에 여러줄의 데이타를 한번에 채울 수 있는 방법이 있습니까?
[A21] TMemo나 TListbox Component의 SetText Method를 사용할 수 있습니다.
각각을 행을 구분하기 위해 Carriage Return 문자인 #13을 사용합니다.
예를 들어, 다음과 같이 사용합니다.

Memo1.Lines.SetText('aaaaa'#13'bbbbb'#13'ccccc')

그러나 Memo나 Listbox를 채우기 위해서는 Lines나 Items의 method를 사용하여추가하는 것이 무난합니다.

TListBox, TComboBox, TCheckBox
[Q22] 여러개의 CheckBox가 동일한 event handler를 사용할 때 각각의 checkbox에 대해 별개의 작업을 하도록 하려면 ?
[A22] TGroupBox내에 여러개의 checkbox를 위치시킵니다. 설계 또는 실행시에checkbox의 Click event handler를 동일하게 지정한 후에 그 event handler에서는다음과 같이 프로그램하면 됩니다.

for i := 0 to GroupBox1.ControlCount -1 do
if (GroupBox1.Controls[i] as TCheckBox).checked then
begin
if (GroupBox1.Controls[i] as TComponent).name = 'CheckBox1' then
{do something}
else if (GroupBox1.Controls[i] as TComponent).name = 'CheckBox2' then
{do something}
end ;

[Q23] 실행시에 ComboBox 컴포넌트가 초기값을 갖도록 하려면 ?
[A23] ComboBox의 Items에 여러 항목을 추가한 후에 실행중에 ComboBox1.ItemIndex를원하는 index 번호로 지정하면 됩니다 .

[Q24] Add Method를 사용하여 ListBox에 새로운 아이템을 추가할 때, Item이화면에 보이는 것보다 더 많이 있다면 추가된 아이템은 보이지 않습니다. Add와동시에 추가된 항목을 보려면 ?
[A24] 다음과 같이 설정하시면 됩니다.

ListBoxName.Items.ADD('XXX')
ListBoxName.ItemIndex := ListBoxName.Items.Count - 1

[Q25] ListBox에서 오른쪽으로 문자를 정렬하려면 ?
[A25] property로 제공되는 것은 없습니다. 스트링의 앞쪽으로 공백을 채우는형태로 사용할 수 있습니다.

[Q26] Multi-Column Listbox를 만드는 방법은 무엇입니까 ?
[A26] 일반적으로 Listbox에는 하나의 column에 대한 data를 나타낼 수있습니다. 그러나 Listbox의 canvas property와 onD rawItem event를 이용하여여러 column으로 data를 보이게 할 수 있습니다. column구별과 제목 표시를위하여 Header component 를 이용합니다. onDrawItem event procedure에 구현된대로data가 display되도록 하기 위해서는 Listbox의 Style property를 lbO wnerDrawFixed나lbOwnerDrawVariable로 설정해야 합니다.

Listbox의 각 column의 기본 너비를 결정하기 위해 header component의
각 SectionWidth 값을 form의 onCreate event에 정의합니다.

procedure TForm1.FormCreate(Sender: TObject);
begin
Header1.SectionWidth[0] := 80;
Header1.SectionWidth[1] := 100;
Header1.SectionWidth[2] := 100;
end;

다음과 같은 방법으로 Listbox에 data를 입력합니다. column은 3개이며 각 column의구별자는 #9(VK_TAB)를 이용합니다.

ListBox1.Items.Add('1000'+#9+'홍길동'+#9+'연구소');

Listbox의 onDrawItem event에서는 주어진 Header component의 SectionWidth만큼 rect를 구하여서 #9 구분자를 이용하여 data 를 parsing한다음, ListboxCanvas에 해당 data를 display 합니다.

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;Rect: TRect; State: TOwnerDrawState);
var r1, r2, r3 : TRect;
tmp : string;
ind : byte;
begin
r1 := Rect;
r1.Right := Header1.SectionWidth[0];
r2 := Rect;
r2.left := r1.right + 1;
r2.right := r2.left + Header1.SectionWidth[1];
r3 := Rect;
r3.left := r2.right + 1;
tmp := TListBox(Control).Items[Index];
with TListBox(Control).Canvas do begin
FillRect(Rect);
ind := Pos(#9, tmp);
TextRect(r1, r1.left, r1.top, copy(tmp, 1, ind-1));
tmp := Copy(tmp, ind+1, Length(tmp)-ind+1);
ind := Pos(#9, tmp);
TextRect(r2, r2.left, r2.top, copy(tmp, 1, ind-1));
tmp := Copy(tmp, ind+1, Length(tmp)-ind+1);
TextRect(r3, r3.left, r3.top, tmp);
end;
end;

Listbox의 각 column이 resizing 될 수 있도록 header component를 resize했을경우에는 Listbox를 다시 그릴 수 있도록 합니다 .

procedure TForm1.Header1Sized(Sender: TObject; ASection, AWidth: Integer);
begin
Listbox1.Invalidate;
end;


[Q27] Listbox에 Bitmap(또는 Icon)을 display하는 방법은 무엇입니까 ?
[A27] 이것 역시 Listbox의 canvas property와 onDrawItem event를 이용합니다.
style property도 역시 lbOwnerDrawFixed나 lbOwnerDrawVariable로 설정해야합니다.

Listbox에 bitmap 또는 icon data를 추가하는 방법은 AddObject method를 이용합니다.

ListBox1.Items.AddObject('Bitmap', Image1.Picture.Bitmap);
ListBox2.Items.AddObject('Icon', Image2.Picture);

procedure TForm1.ListBox1DrawItem(Control:TWinControl; Index:Integer; Rect:TRect;State: TOwnerDrawState);
var Bitmap : TBitmap;
begin
with Listbox1.Canvas do begin
FillRect(Rect);
Bitmap := TBitmap(Listbox1.Items.Objects[index]);
BrushCopy(Bounds(Rect.Left + 2, Rect.Top, Bitmap.Width, Bitmap.Height),Bitmap, Bounds(0, 0, Bitmap.Width, Bi tmap.Height), clRed);
TextOut(Rect.Left+50, Rect.Top, Listbox1.Items[Index]);
end;
end;

procedure TForm1.ListBox2DrawItem(Control:TWinControl; Index:Integer; Rect:TRect;State: TOwnerDrawState);
var Pic : TPicture;
begin
with Listbox2.Canvas do begin
FillRect(Rect);
Pic := TPicture(Listbox2.Items.Objects[index]);
Draw(Rect.Left, Rect.Top, Pic.Graphic);
TextOut(Rect.Left+50, Rect.Top, Listbox2.Items[Index]);
end;
end;


[Q28] Listbox에서 특정 index의 font/background color를 어떻게 바꿀 수 있습니까 ?
[A28] canvas property와 onDrawItem event를 이용합니다.

procedure TForm1.ListBox1DrawItem(Control:TWinControl; Index:Integer; Rect:TRect;State: TOwnerDrawState);
begin
with TListBox(Control).Canvas do begin
if Index = 2 then begin
Brush.Color := clYellow;
Font.Color := clBule;
end;
FillRect(Rect);
TextRect(Rect, Rect.left, Rect.top, Listbox1.Items[Inex]);
end;
end;

[Q29] ListBox에서 수평 스크롤바를 표시하기 위해 어떻게 합니까?
[A29] ListBox의 윈도우를 조작하기 위해 LB_SetHorizontalExtent 메세지를보냅니다. 예를 들어 폼의 OnCreate에서 메세지 를 보낼 수 있습니다.

Procedure TForm1.FormCreate(Sender:TObject);
Begin
SendMessage(Listbox1.Handle,LB_SetHorizontalExtent, 1000,Longint(0));
End;

StringGrid
[Q30] StringGrid에서 Options property의 goEditing을 TRUE로 한 후 StringGrid에서직접 편집을 하려고 한다. 그런데 cursor 가 보이지 않습니다. cursor를 보이게 하려면 ?
[A30] DefaultRowHeight property를 조절해 보십시오. 화면의 해상도와글꼴의 크기에 따라 다르긴 하지만 18 또는 22 이상 으로 조정해 보십시오.

[Q31] StringGrid의 Color를 부분적으로 바꾸려면 ?
[A31] DrawCell event handler를 다음과 같이 작성합니다.

procedure TForm1.StringGrid1DrawCell(Sender:TObject; Col,Row:Longint; Rect:TRect;State: TGridDrawState);
begin

{if gdFocused in State then}
if (Col >= StringGrid1.FixedCols) and (Row >= StringGrid1.FixedRows)then
with (Sender as TStringGrid).Canvas do
begin
if (Row = 1) and (Col = 1)then
Brush.Color := clRed
else Brush.Color := clBlue ;
FillRect(Rect) ;
TextOut(Rect.Left, Rect.Top, StringGrid1.Cells[Col,Row]) ;
end ;
end;

[Q32] StringGrid에서 입력된 데이타의 종류에 따라 정렬하는 방법은 무엇입니까?
[A32] StringGrid의 DrawCell event를 이용합니다.

procedure TForm1.StringGrid1DrawCell(Sender:TObject; Col,Row:Longint; Rect:TRect;State: TGridDrawState);
var
Left,code, V : integer;
ConvertString : String;
DataInCell : string;
begin
DataInCell := StringGrid1.Cells[col,row];
if DataInCell = '' then exit;
with StringGrid1.Canvas do begin
FillRect(Rect);
if (row = 0) or (col = 0) then
Left := Rect.Left + ((Rect.Right-Rect.Left) - TextWidth(DataInCell)) div2
else begin
val(DataInCell, V, code);
if (code = 0) and (col <> 0) then begin
DataInCell := FormatFloat('\#,##0', StrToInt(DataInCell));
Left := Rect.Right - TextWidth(DataInCell) - 3;
end
else Left := Rect.Left + 3;
end;
TextRect(Rect, Left, Rect.Top, DataInCell);
end;
end;

 

[Q33] StringGrid의 값을 오른쪽으로 정렬하려면 ?
[A33] DrawDell event handler를 다음과 같이 작성합니다.

procedure TForm1.StringGrid1DrawCell(Sender:TObject; Col,Row:Longint, Rect:TRect;State: TGridDrawState);
var oldalign : word;
begin
if (row=0) or (col<2) then {set the headings in bold}
StringGrid1.canvas.font.style := StringGrid1.canvas.font.style + [fsbold];

if col<>1 then
begin
oldalign:=settextalign(StringGrid1.canvas.handle,ta_right);
StringGrid1.canvas.textrect(rect,rect.right-2,rect.top+2,
StringGrid1.cells[col,row]);
settextalign(StringGrid1.canvas.handle,oldalign);
end
else
StringGrid1.canvas.textrect(rect,rect.left+2,rect.top+2,
StringGrid1.cells[col,row]);

StringGrid1.canvas.font.style:=StringGrid1.canvas.font.style-[fsbold];
end;


[Q34] TStringGrid에서 wrap을 지원하려면 ?
[A34] 다음과 같이 TStringGrid로 부터 새로운 component를 만듭니다.

TWrapGrid = class(TStringGrid)
private
{ Private declarations }
protected
{ Protected declarations }
{ This DrawCell procedure wraps text in the grid cell }
procedure DrawCell(ACol, ARow : Longint; ARect : TRect; AState : TGridDrawState);override;
public
{ Public declarations }
{ The Create procedure is overriden to use the DrawCell procedure by
default }
constructor Create(AOwner : TComponent); override;
published
{ Published declarations }
end;


constructor TWrapGrid.Create(AOwner : TComponent);
begin
{ Create a TStringGrid }
inherited Create(AOwner);

{ Make the drawing use our DrawCell procedure by default }
DefaultDrawing := FALSE;
end;


{ This DrawCell procedure wraps text in the grid cell }
procedure TWrapGrid.DrawCell(ACol, ARow : Longint; ARect : TRect;
AState : TGridDrawState);
var
Sentence, { What is left in the cell to output }
CurWord : String; { The word we are currently outputting }
SpacePos, { The position of the first space }
CurX, { The x position of the 'cursor' }
CurY : Integer; { The y position of the 'cursor' }
EndOfSentence : Boolean; { Whether or not we are done outputting the cell}
begin
{ Initialize the font to be the control's font }
Canvas.Font := Font;

with Canvas do begin
{ If this is a fixed cell, then use the fixed color }
if gdFixed in AState then begin
Pen.Color := FixedColor;
Brush.Color := FixedColor;
end
else begin { else, use the normal color }
Pen.Color := Color;
Brush.Color := Color;
end;

{ Prepaint cell in cell color }
Rectangle(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
end;

{ Start the drawing in the upper left corner of the cell }
CurX := ARect.Left;
CurY := ARect.Top;

Sentence := Cells[ACol, ARow]; { Here we get the contents of the cell }

{ for each word in the cell }
EndOfSentence := FALSE;
while (not EndOfSentence) do begin
{ to get the next word, we search for a space }
SpacePos := Pos(' ', Sentence);
if SpacePos > 0 then begin
{ get the current word plus the space }
CurWord := Copy(Sentence, 0, SpacePos);

{ get the rest of the sentence }
Sentence := Copy(Sentence, SpacePos + 1, Length(Sentence) - SpacePos);
end
else begin
{ this is the last word in the sentence }
EndOfSentence := TRUE;
CurWord := Sentence;
end;

with Canvas do begin
{ if the text goes outside the boundary of the cell }
if (TextWidth(CurWord) + CurX) > ARect.Right then begin
{ wrap to the next line }
CurY := CurY + TextHeight(CurWord);
CurX := ARect.Left;
end;

{ write out the word }
TextOut(CurX, CurY, CurWord);
{ increment the x position of the cursor }
CurX := CurX + TextWidth(CurWord);
end;
end;
end;


메뉴
[Q35] Help 메뉴를 메뉴바 우측 가장자리로 정렬시키려면 ?
[A35] 설계시에는 할 수 없습니다. MenuItem의 Name property를 Help 라고할 때 실행시에 폼의 'OnCreate handler'에 다음 과 같이 추가합니다.

Help.Caption := #8 + Help.Caption;

단, 윈도우 95에서는 실행되지 않을 수 있습니다.

[Q36] Copy, Cut, Paste와 Undo에 대한 CTRL-C, CTRL-X, CTRL-Y, CTRL-Z키는 그냥 사용할 수 있습니다. 그러나 이들을 메뉴바에서 선택하게 하려면?
[A36] 예를 들면 다음과 같이 합니다.

procedure TForm1.Menu1Click(Sender: TObject);
begin
if ((ActiveControl) is TCustomEdit) then TEdit(ActiveControl).CutToClipBoard;
end;

procedure TForm1.Menu2Click(Sender: TObject);
begin
if ((ActiveControl) is TCustomEdit) then TEdit(ActiveControl).ClearSelection;
end;

[Q37] 어떤 component가 Popup 메뉴를 동작시켰는지 아는 방법은 ?
[A37] 다음과 같이 PopupComponent property를 사용합니다.

Procedure TForm1.PopupItem1Click(Sender: TObject);
begin
Label1.Caption := PopupMenu1.PopupComponent.ClassName;
End;

1.5 DDE
[Q38] DDE 기능을 사용하여 다른 응용프로그램으로 Data를 전달하고자 합니다.어떻게 하나요 ?
[A38] TDdeClientConv과 TDdeClientItem component를 사용합니다.

DdeClientItem1의 DdeConv property를 DdeClientConv1로 선택합니다.
그리고 Data를 전달하는 방법은 다음과 같습니다.

var P : array [0..10] of char ;
begin
DDEClientConv1.SetLink('Excel','Sheet1');
try
DDEClientConv1.OpenLink;
DDEClientItem1.DDEItem:= 'R1C1';
DDEClientConv1.PokeData(DDEClientItem1.DDEItem, StrPCopy(P, 'Test')) ;
finally
DDEClientConv1.CloseLink;
end;
end ;

[Q39] Windows 프로그램 Group을 만들고 그 그룹에 item을 추가하려면 ?
[A39] 프로그램 Group을 만드는 방법은다음과 같습니다.

procedure TForm1.CreateButtonClick(Sender: TObject);
var
Name: string;
Macro: string;
Cmd: array[0..255] of Char;
begin
if GroupName.Text = '' then
MessageDlg('Group name can not be blank.', mtError, [mbOK], 0)
else
begin
Name := GroupName.Text;
Macro := Format('[CreateGroup(%s)]', [Name]) + #13#10;
StrPCopy (Cmd, Macro);

DDEClient.OpenLink;
if not DDEClient.ExecuteMacro(Cmd, False) then
MessageDlg('Unable to create group.', mtInformation, [mbOK], 0);
DDEClient.CloseLink;
end;
end;

해당 Group에 item을 추가하는 방법은 다음과 같습니다.

procedure TForm1.Button1Click(Sender: TObject);
var
item,command,dir: string;
Macro: string;
Cmd: array[0..255] of Char;
begin
item := ItemName.text;
command := CmdLine.text;
dir := WorkDir.Text;

Macro := Format('[AddItem(%s,%s)]', [command,item,dir]) + #13#10;
StrPCopy (Cmd, Macro);

DDEClient.OpenLink;
if not DDEClient.ExecuteMacro(Cmd, False) then
MessageDlg('Unable to create item.', mtInformation, [mbOK], 0);
DDEClient.CloseLink;
end;


ReportSmith
[Q40] ReportSmith에서 Server DB에 연결하여 보고서를 작성한 후에 Delphi프로그램에서 Report를 실행시키면 또다시 server l ogin을 위해 Dialog가 나타납니다.이 과정을 매번 하지 않으려면 ?
[A40] ReportSmith component의 connect method를 사용합니다.

Report1.Connect(ctOracle, 'T:lambda:ORA7', 'scott', 'tiger', '') ;
Rpoert1.Run ;

위의 ctOracle과 같은 Server Type을 정의하는 상수는 DELPHI\SOURCE\VCL\REPORT.PAS화일에 정의되어 있습니다.

[Q41] ReportSmith에서 테이블의 특정 필드를 다른 문자열로 대치하고자합니다. 어떻게 하면 좋을까요 ?
[A41] Derived Field를 macro를 사용하도록 정의합니다.
그리고 다음과 같이 macro를 작성하면 Derived Field가 추가됩니다.

Sub Test()
if Field$("필드명") = "TRUE" then
DerivedField "참값"
else
DerivedField "거짓값"
end if
End Sub

[Q42] Report Variable로 값을 넘겨주는 방법은 ?
[A42] Report component의 ReportName property에 ReportSmith에서 작성된보고서를 선택합니다. 그리고 나서 다음과 같이 프로그램 합니다.

Report1.InitialValues.Clear ;

{integer형 변수}
Report1.InitialValues.Add('@empno=<''' + Edit1.Text + '''>') ;

{string형 변수}
Report1.InitialValues.Add('@enddate=<''' + Edit2.Text + '''>') ;

{date형 변수}
{ReportSmith에서 Date Type의 variable을 정의할 때 Format을 mm/dd/yy로 설정하고,Edit3.Text 에는 월/일/년의 순서로 입력 되었다고 가정한다.}
Report1.InitialValues.Add('@saledate=<''' + Edit3.Text + '''>') ;

{ReportSmith Run-Time 구동}
Report1.Run ;

ChartFX
[Q43] Chart에 Value를 assign 하는 방법은 ?
[A43] 다음과 같이 프로그램 합니다.

{MAKELONG의 1st parameter:series 갯수, 2nd parameter:value 갯수}
ChartFX1.OpenData[COD_VALUES] := MAKELONG(2, 3);

ChartFX1.ThisSerie := 0;
ChartFX1.Value[0] := 30;
ChartFX1.Value[1] := 20;
ChartFX1.Value[2] := 40;

ChartFX1.ThisSerie := 1;
ChartFX1.Value[0] := 45;
ChartFX1.Value[1] := 60;
ChartFX1.Value[2] := 30;

ChartFX1.CloseData[COD_VALUES] := 0;

[Q44] Chart의 Title, Legend, Series Legend 추가하는 방법은 ?
[A44] 다음과 같이 프로그램 합니다.

ChartFX1.pType := ChartFX1.pType or CT_LEGEND or CT_SERLEGEND ;

ChartFX1.Title[CHART_BOTTOMTIT] := 'Person'; {X축 Title}
ChartFX1.Title[CHART_LEFTTIT] := 'Sales'; {Y축 Title}

ChartFX1.YLeg[0] := 'Really Bad';
ChartFX1.YLeg[1] := 'Bad';
ChartFX1.YLeg[2] := 'Regular';
ChartFX1.YLeg[3] := 'Good';
ChartFX1.YLeg[4] := 'Excellent';

{ Tell Chart FX how to use the legends (GAP) }
ChartFX1.Adm[CSA_YLEGGAP] := 20;

{ Set the legends }
ChartFX1.Legend[0] := 'Peter Gabriel';
ChartFX1.KeyLeg[0] := 'PG';
ChartFX1.Legend[1] := 'Phil Collins';
ChartFX1.KeyLeg[1] := 'PC';
ChartFX1.Legend[2] := 'Bruce Springsteen';
ChartFX1.KeyLeg[2] := 'BS';
ChartFX1.Legend[3] := 'Tracy Chapman';
ChartFX1.KeyLeg[3] := 'TC';
ChartFX1.Legend[4] := 'Big Mamma Thornton';
ChartFX1.KeyLeg[4] := 'BM';
ChartFX1.Legend[5] := 'Paul Simon';
ChartFX1.KeyLeg[5] := 'PS';
ChartFX1.Legend[6] := 'Louis Armstrong';
ChartFX1.KeyLeg[6] := 'LA';
ChartFX1.Legend[7] := 'John Lennon';
ChartFX1.KeyLeg[7] := 'JL';

{ Series Legends }
ChartFX1.SerLeg[0] := 'First Test';
ChartFX1.SerLeg[1] := 'Second Test';

ChartFX1.LeftGap := 70;


[Q45] Chart를 3차원으로, 배경 Color, Font 정보를 바꾸는 방법은 ?
[A45] 다음과 같이 프로그램 합니다.

ChartFX1.View3D := True;
ChartFX1.Angles3D := MAKELONG(30, 60);

ChartFX1.Grid := CHART_HORZGRID;

ChartFX1.RGBBk := RGB(0, 255, 0);
ChartFX1.RGB2DBk := RGB(200, 20, 90);
ChartFX1.RGB3DBk := RGB(200, 20, 90);

ChartFX1.Title[CHART_BOTTOMTIT] := 'Times Font';
ChartFX1.Font[CHART_BOTTOMFT] := CF_TIMES OR CF_BOLD OR 12;
ChartFX1.RGBFont[CHART_BOTTOMFT] := RGB(255, 0, 0);


[Q46] Chart의 Status Line을 그리는 방법은 ?
[A46] 다음과 같이 프로그램 합니다.

ChartFX1.OpenData[COD_STATUSITEMS] := 4;
l:= chart_SetStatusItem(ChartFX1.Handle,0,True,101,True,100,50,4,CHART_STLEFT);
l:= chart_SetStatusItem(ChartFX1.Handle,1,True,102,False,80,80,5,CHART_STCENTER);
l:= chart_SetStatusItem(ChartFX1.Handle,2,False,0,True,40,40,10,0);
l:= chart_SetStatusItem(ChartFX1.Handle,3,True,103,True,50,30,4,CHART_STRIGHT);
ChartFX1.CloseData[COD_STATUSITEMS] := 4;

ChartFX1.StatusText[101] := 'Text 1';
ChartFX1.StatusText[102] := 'Text 2';
ChartFX1.StatusText[103] := 'Text 3';
ChartFX1.ShowStatus := True;


[Q47] Chart에서 Y축 계열값의 특정 범위를 구별되게 표시하려면 ?
[A47] 다음과 같이 프로그램 합니다.

procedure TForm1.FormCreate(Sender: TObject);
begin
ChartFX1.OpenData[COD_STRIPES] := 1;
chart_SetStripe(ChartFX1.Handle,0,25,50,RGB(128,0,128));
ChartFX1.CloseData[COD_STRIPES] := 0;
end ;

procedure TForm1.ChartFX1LButtonDblClk(Sender: TObject; var X, Y, nSerie,
nPoint, nRes: Integer);
var
sx,sy,sPoint,sSerie: String;
dValue: Double;
begin
Str(X, sX);
Str(Y, sY);
Str(nPoint, sPoint);
Str(nSerie, sSerie);

If (nSerie = -1) OR (nPoint = -1) Then
MessageDlg('Empty DobleClick X:' + sX + ' Y:' + sY, mtWarning, [mbOK],0)
Else
begin
ChartFX1.ThisSerie := nSerie;
dValue := ChartFX1.Value[nPoint];
If (dValue < 25) Then
nRes := 1
Else
If (dValue < 50) Then
ChartFX1.HText := 'Value between 25 and 50'
end
end;


[Q48] Chart의 각 Point에서 Menu를 사용하게 하려면 ?
[A48] Chart의 OnMenu event handler를 다음과 같이 작성합니다.

procedure TForm1.ChartFX1Menu(Sender: TObject; var wParam, nSerie, nPoint,
nRes: Integer);
var
s1, s2, s3 : string[10];
begin
Str(wParam-1, s1);
Str(nPoint, s2);
Str(nSerie, s3);
MessageDlg('Menu Option:'+s1+' nPoint:'+s2+' nSerie:'+s3, mtWarning, [mbOK],0);
end;

단, 다음과 같이 Chart의 property에 보이고자 하는 Popup 메뉴를 지정해야합니다.

ChartFX1.RigClk[CHART_MENUCLK] := PopupMenu1.Handle;

1.8 VBX
[Q49] VBX datatype(예를 들면 TBasicString)의 선언과 이들 Datatype을 다루기 위한 기능은 어디에 있습니까?
[A49] 모든 VBX와 관련된 datatype과 기능은 \DELPHI\DOC 디렉토리에 있는VBXCTRL.INT라는 화일에 Interface 부분이 준비 되어 있습니다. VBXCtrl Unit의내용에 있는 정보는 완전한 실제 Source입니다.

[Q50] application에서 VBX를 사용할 때 어떤 file을 배포해야 합니까 ?
[A50] 사용된 VBX file과 Windows\System directory에 있는 BIVBX11.Dllfile을 배포하면 됩니다.

[Q51] 가지고 있는 VBX를 Delphi에 load할려고 했으나 되지가 않습니다.왜 그렇습니까 ?
[A51] Delphi는 VBX 1.0 버전만 지원합니다. 가지고 있는 VBX가 2.0 또는3.0일 경우는 사용할 수가 없습니다.

1.9 기타 component
[Q52] 응용프로그램의 icon을 가져와서 특정 SpeedButton에 보여주려면 ?
[A52] 다음과 같이 프로그램 합니다.

procedure TForm1.Button1Click(Sender: TObject);
var
imgIcon: TIcon;
imgRect: TRect;
begin
imgIcon := TIcon.Create;
imgIcon.Handle := ExtractIcon(handle, 'project1.exe', 0 );

with SpeedButton1.Glyph do begin
Width := imgIcon.Width;
Height := imgIcon.Height;
imgRect := Rect( 0, 0, Width, Height );
Canvas.Draw(0,0, imgIcon);
end;
end ;

[Q53] Bitmap을 다른 component에 투명하게 보이도록 만들려면 ?
[A53] 아래의 DrawTransparent procedure를 사용합니다.
이 procedure는 bitmap에서 투명하게 보이고자 하는 부분의 색을 지정하면 그부분은 바탕의 다른 component 색을 그대로 유지 시킵니다.

t = 대상 canvas
x,y = bitmap을 write할 위치
s = 그리고자 하는 bitmap
TrCol = 그리고자 하는 bitmap에서 투명하게 보일 부분의 색

주의: 대상 component를 반드시 다시 그려야 함. (즉 Image1.Invalidate)

procedure DrawTransparent(t: TCanvas; x,y: Integer; s: TBitmap; TrCol:TColor);
var
bmpXOR, bmpAND, bmpINVAND, bmpTarget: TBitmap;
oldcol: Longint;
begin
try
bmpAND := TBitmap.Create;
bmpAND.Width := s.Width;
bmpAND.Height := s.Height;
bmpAND.Monochrome := True;
oldcol := SetBkColor(s.Canvas.Handle, ColorToRGB(TrCol));
BitBlt(bmpAND.Canvas.Handle, 0,0,s.Width,s.Height, Canvas.Handle, 0,0,SRCCOPY);
SetBkColor(s.Canvas.Handle, oldcol);

bmpINVAND := TBitmap.Create;
bmpINVAND.Width := s.Width;
bmpINVAND.Height := s.Height;
bmpINVAND.Monochrome := True;
BitBlt(bmpINVAND.Canvas.Handle, 0,0,s.Width,s.Height, bmpAND.Canvas.Handle,0,0, NOTSRCCOPY);

bmpXOR := TBitmap.Create;
bmpXOR.Width := s.Width;
bmpXOR.Height := s.Height;
BitBlt(bmpXOR.Canvas.Handle, 0,0,s.Width,s.Height, s.Canvas.Handle, 0,0,SRCCOPY);
BitBlt(bmpXOR.Canvas.Handle, 0,0,s.Width,s.Height, bmpINVAND.Canvas.Handle,0,0, SRCAND);

bmpTarget := TBitmap.Create;
bmpTarget.Width := s.Width;
bmpTarget.Height := s.Height;
BitBlt(bmpTarget.Canvas.Handle, 0,0,s.Width,s.Height, t.Handle, x,y, SRCCOPY);
BitBlt(bmpTarget.Canvas.Handle, 0,0,s.Width,s.Height, bmpAND.Canvas.Handle,0,0, SRCAND);
BitBlt(bmpTarget.Canvas.Handle, 0,0,s.Width,s.Height, bmpXOR.Canvas.Handle,0,0, SRCINVERT);
BitBlt(t.Handle, x,y,s.Width,s.Height, bmpTarget.Canvas.Handle, 0,0, SRCCOPY);
finally
bmpXOR.Free;
bmpAND.Free;
bmpINVAND.Free;
bmpTarget.Free;
end;{End of TRY section}
end;


[Q54] Clipboard의 자료를 가져오는 방법은 ?
[A54] 다음과 같이 프로그램 합니다.

var
Buffer: PChar;
MyHandle : THandle;
TextLength : intger ;
begin
MyHandle := Clipboard.GetAsHandle(CF_TEXT);
Buffer := GlobalLock(MyHandle);
If Buffer = Nil then
begin
GlobalUnlock(MyHandle);
exit;
end;

{since buffer is of type PChar, all the functions applicable to PChar canbe applied}
TextLength := StrLen(buffer);

단, Windows의 Clipboard에 담을 수 있는 자료는 64K로 제한됩니다.

[Q55] Canvas 를 가장 빠르게 다시 그리는 방법은 ?
[A55] InValidateRect(Canvas.handle,NIL,True);

[Q56] TPanel로부터 새로운 component를 만들었습니다. constructor에 BevelWidthproperty를 보면 설계시 정한 값과는 무관하게 항상 1로 setting되어 있습니다.constructor가 실행된 다음 설계시에 지정한 값으로 수정될 것인데 이 작업은 언제 일어납니까?
[A56] component들이 읽혀지고, 각 component가 create된 다음에 property값들이 다시 읽혀집니다. 모두 다 읽은 후에는 c omponent의 Loaded method가실행되므로 그 component에 대해서 무엇인가 작업을 하려면 Loaded method를자신의 procedure로 대 치시키면 됩니다.

[Q57] TMediaPlayer를 사용하여 Avi 화일을 동작시킬 수 있습니까?
[A57] TMediaPlayer를 사용하여 Avi 화일들을 동작시킬 수 있습니다.
TMediaPlayer component의 Filename property에 AVI 화일이름을 주고, Displayproperty를 TPanel로 설정한후 Open Method를 사 용합니다.
AVI 화일들을 동작하기 위해 사용자의 시스템는 Video for Windows의 정식 버젼이설치되어 있어야 합니다. 또한 WAV 화일도 마 찬가지로 동작시킬 수 있습니다.

[Q58] Password에 해당되는 자료를 입력할 때 화면에 보이지 않도록 하려면?
[A58] TEdit component의 PasswordChar property를 사용합니다.
실행시에 TEdit control에 입력되는 data는 PasswordChar property에서 주어진문자로 표시됩니다.

[Q59] 대화상자내의 특정 control을 enable/disable 시키는 방법은?
[A59] EnableWindow(Wnd: Hwnd, Enable: Bool) API 함수를 사용하십시오.
두개의 parameters중에 하나는 원하는 control의 window handle이고, Enableflag는 True이면 enable, False이면 disable 됩니 다.

[Q60] TDBNavigator component의 각각의 button이 enable 되었는지 알 수 있는 방법이 있습니까 ?
[A60] 다음과 같이 하면 됩니다.

type
TDBNavCracker = class(TDBnavigator);
...
if TDBNavCracker(DBNavigator1).Buttons[nbEdit].Enabled then
{your code}

[Q61] TEdit Component의 OnExit event는 사용자가 Speed Button에서 마우스를 클릭했을 경우 왜 실행되지 않습니까? Speed Button이 눌려졌을때 OnExit event를실행하기 위해 어떤 방법이 있습니까?
[A61] Speed Button은 동적인 Focus를 결코 갖지 않습니다. 그래서 Speedbutton이눌려지기 전에 Active 상태인 control에 서는 Focus를 잃어 버리지 않습니다.즉, Control의 OnExit event는 발생하지 않습니다.

OnExit event handler를 실행하도록 하는 한가지 방법은 SpeedButton의 OnClick에서명확하게 호출하는 것입니다.

Procedure TForm1.SpeedButton1Cliek(Sender:TObject);
Begin
if ActiveControl is TEdit then (ActiveControl as TEdit).OnExit(ActiveControl);
End;

[Q62] TEdit가 Focus를 가지고 있는지 알 수 있는 방법은 ?
[A62] ActiveControl이 TEdit형식 인지 다음과 같이 확인할 수 있고 TEditcomponent의 일반적인 method를 사용할 수 있습 니다.

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
If (ActiveControl is TEdit) Then TEdit(ActiveControl).CopyToClipboard;
end;

[Q63] Runtime시에 TTabbedNoteBook의 원하는 페이지에 새로운 Component를추가할 수 있습니까? 새로운 Component에 대한 부모가 무엇인지 어떻게 결정합니까?
[A63] Runtime시에 TTabbedNoteBook의 원하는 페이지에 Component를 추가하기위해서는 새로운 Component의 부모 특성을 지 정해야 합니다.

Runtime시에 TTabbedNotebook의 모든 페이지에 접근하기 위한 방법은 TabbedNotebook의Page 개체의 Object property 의 개체 배열 특성을 사용하는 것입니다.

다른 방법으로는 Pages Component는 Pages 문자열 목록 특성에서 Page 이름들과연결되어 있는 개체들이 저장되어 있습니다.

다음은 TabbedNotebook1의 두번째 페이지에 새로운 Button을 생성하는 방법입니다.

var
NewButton:TButton;
Begin
NewButton := TButton.Create(Self);
NewButton.Caption := 'New' ;
NewButton.Parent := TWinControl(TabbedNotebook1.Pages.Objects[1])
...

다음은 TTabSet Tab Page의 해당 Tab Page위에 새로이 생성된 Component에 부모를어떻게 사용하는지에 대한 것입니다.

NewButton.Parent := TWinControl(NoteBook1.Pages.Objects[1])

[Q64] 특정 component가 존재하는지 알 수 있는 방법은 ?
[A64] 다음과 같이 FindComponent를 사용합니다.

Procedure TForm1.Button1Cliek(Sender:TObject);
var FormExists: Boolean;
Begin
FormExists := FindComponent('Button2') <> nil;
end ;

[Q65] 실행시에 component의 총 갯수를 알 수 있는 방법은 ?
[A65] 각 Form은 Screen.Forms 라는 array를 통해서 access 할 수 있고,각 Form의 component수는 ComponentCount 값에 있 습니다.
즉, 다음과 같이 프로그램 합니다.

function GetTotalComponents : Integer;
var
TotalComps, CurForm : Integer;
begin
TotalComps := 0;

for CurForm := 0 to (Screen.FormCount - 1) do begin
TotalComps := TotalComps + Screen.Forms[CurForm].ComponentCount;
end;

Result := TotalComps;
end;

이 코드는 실행시에 생성된 component에 대하여 특별한 작업을 하지 않아도이상 없이 작동됩니다.
또한 Application.ComponentCount는 프로그램의 Form 또는 windows 갯수를 돌려줍니다.단, 보이지 않는 application window 하 나를 포함한 갯수 입니다.

[Q66] component를 배열 형태로 사용하려면 ?
[A66] component의 Tag property를 사용합니다.
설계시에 component의 Tag property에 유일한 번호를 할당한 후에 다음과 같이프로그램합니다.

procedure TForm1.Button1Click(Sender: TObject);
var i : integer ;
begin
for I := 0 to ComponentCount -1 do
if Components[I] is TRadioButton then
if TRadioButton(Components[i]).checked then
case TRadioButton(Components[I]).Tag of
1 : Edit1.Text := 'RadioButton1' ;
2 : Edit1.Text := 'RadioButton2' ;
3 : Edit1.Text := 'RadioButton3' ;
4 : Edit1.Text := 'RadioButton4' ;
end ;
end;

[Q67] 새로운 component를 install했을 때 component palette에 원하는 icon이 보여지도록 하려면 ?
[A67] Component Writer's Guide 8장(Registering components)의 "Addingpalette bitmaps"를 참조합니다.

Image Editor에서 component resource(.DCR)를 만들어 24*24 bitmap을 추가합니다.이 때 주의할 것은 bitmap의 이름은 반드시 대문자로 적어야 한다는 것입니다.

 

[Q1] VCL 소스 코드를 구입할 수가 있습니까 ?
[A1] 컴포넌트 설계에 관심이 있다면 얼만든지 구입이 가능합니다. VCL소스 코드를 가지고 있다면, 개인적으로 컴포넌트 생성 을 정확하게 시험할수가 있습니다. 이것은 자기소유의 사용자정의 컴포넌트를 생성하려고 할 때매유 유용한 방법입니다. 또한 디버거를 사용하여 소스 코드를 분석할 수가있습니다.

[Q2] tabbed 콘트롤(예, TTabbedNotebook 등)에 대한 소스 코드는 어디에있습니까 ?
[A2] tabbed 콘트롤에 대한 소스는 법적인 문제로 인하여 소스에 포함되어있지 않습니다.
그러나, 인터페이스 소스는 DELPHI\DOC 디렉토리 밑에 INT 확장자로서 제공됩니다.
참고: Delphi RTL 소스 코드 등록자는 Borland Corporate로 부터 TTabSet과TTabbedNotebook에 대한 소스를 요청할 수 있습니다 .

[Q3] TString 리스트에 문자열에 붙여서 object나 property로서 정수값을저장할 수 있는 방법이 있읍니까?
[A3] 그렇습니다만 약간의 type 변환이 필요합니다. TString component는String array에 따라 같이 붙여 쓰도록 되어있는 Object array가 있습니다.이 Object array를 정수 데이타를 저장하는 목적으로 사용하면 됩니다. Objectarray가 가지는 자료형 은 TObject 입니다. 이것은 실제로는 4바이트의 포인터값입니다. 따라서 정수값을 여기 저장하려면 형변환(Type cast)이 필요합 니다.다음의 코드는 ListBox component의 items property(TString 개체)에 문자열과정수값 100을 저장합니다.

ListBox1.Items.AddObject('Text string', TObject(100));

이 값을 얻으려면 다음과 같이 합니다. (Result 가 Longint형이고 방금 추가된개체의 index 위치가 0이라고 가정하면)
Result := LongInt ( ListBox1.Items.Objects[0]);

주의 : 이것이 동작한다고는 하더라도 내부적 동작까지 완전히 믿어서는 안됩니다.이것은 트릭일 뿐이므로 꼭 주의해야합니다.

만약 하나의 값 이상을 넣어야 한다면 다음과 같이 TObject 클래스를 베이스로두 개의 정수를 갖는 다음과 같은 클래스를 새로 정의하면 됩니다.

type
ManyValues = class(TObject)
Value1 : Integer;
Value2 : Integer;
end;

[Q4] TStrings, TStringList의 차이는 무엇입니까 ?
[A4] TStrings는 create되더라도 자체적으로 저장할 공간을 가지고 있지않습니다.
예를들면, TListbox의 Items의 type은 TStrings 입니다. 그러나 create 시에는TListboxStrings의 type으로 create 합니다. 따 라서 다음과 같은 방법으로는TStrings를 사용할 수 없습니다.
ItemString = TStrings.Create;
ItemString.Add('test');

TStrings를 사용하고자 할 경우에는 다음과 같은 방법등으로 쓸 수 있습니다.
ItemString = TStringList.Create;
ItemString.Add('test');

그러나 TStringList에서는 자체적으로 저장할 공간을 가지고 있기 때문에 create한후에 Add Method를 사용할 수 있습니다.

[Q5] component를 그것의 name property를 가지고 참조하는 것이 가능합니까?
[A5] 가능합니다. 다음 예는 Form1의 FindComponent method를 가지고 처음부터10번째 까지의 SpeedButton들의 Enable prop erty를 FALSE로 만듭니다.

for I := 1 to 10 do
with Form1.FindComponent('SpeedButton' + IntToStr(i)) as TSpeedButton do
Enable := False;

[Q6] component에 나오는 font의 default 크기를 변경할 수 있읍니까?
[A6] 일단 폼의 font proerty를 원하는 크기로 변경한 다음 그 폼을 gallery에추가하면 됩니다.
component는 기본적으로 그것의 parent의 font를 반영하도록 되어 있으므로,이후로 그 폼에 추가하는 component는 폼의 font 크기를 따르게 될 것입니다.
Options | Gallery 명령을 통해 원하는 폼을 default mainform이나 defaultnewForm으로 지정할 수 있습니다.

[Q7] font property의 값을 Canvas.Font.Style := [fsBold] 와 같이 지정한뒤에 그것을 다시 보통 상태로 되돌리려면 어떻 게 합니까? 온라인 도움말에서는[fsBold],[fsItalic] 같은 것은 나와있지만 보통상태에 대한 기호는 없던데요?
[A7] 간단합니다. 빈 집합을 지정하면 됩니다.
Canvas.Font.Style := [];

또는 fsBold 만을 없애고 싶다면 다음과 같이 합니다.
Canvas.Font.Style := Canvas.Font.Style - [fsBold];

[Q8] 각각의 내장된 component가 사용하는 GDI resource의 양은 얼마나 됩니까?
[A8] TGraphicControl에서 계승된 TLabel이나 TBevel 같은것들은 systemresource를 전혀 사용하지 않습니다. 그러나 TWinC ontrol 에서 계승된 TEdit이나TPanel 같은것들은 resource를 사용합니다. TRadioGroup 안의 각각의 radiobutton들 또한 윈도우 이며 따라서 윈도우 핸들을 가지게 됩니다.

[Q9] TTabbedNotebook은 한 번에 한 페이지만이 보여지는데도 system resource들을왜 그렇게 많이 사용하는지 알고싶습니다 .
[A9] 한 번에 하나의 페이지만이 보여지고 있다고는 해도 모든 페이지의각각의 component는 이미 모두 생성되어있기 때문 에 resource를 사용합니다.이 문제를 해결하려면 notebook을 사용하는 대신에 페이지마다 각각의 분리된폼을 사용하여 user가 tab을 클릭하면 현재의 페이지를 파괴하고 새로운 것을생성하는 것입니다. 이렇게 하려면 다음과 같이 합니다.

각각의 child 폼은 어떤 방법으로든 CreateParams setup이 필요합니다.

...
private
{ Private declarations }
PRODCEDURE CreateParams(VAR Params: TCreateParams); override;
...

procedure TForm2.CreateParams(VAR Params: TCreateParams);
begin
Inherited CreateParams(Params);
with Params do begin
WndParent:= Application.MainForm.Handle;
Style := (Style OR WS_CHILD) AND NOT (WS_POPUP);
end;
end;

child 폼의 BorderStyle은 반드시 bsNone 으로 되어있어야 합니다. 메인폼에서TForm 형으로 된 Child 라는 private 데이타 필 드를 정의합니다. 그리고 OnCreate가아닌 OnActivate 이벤트에서 그것을 초기화 합니다. 페이지를 바꾸기 위해 tab이클릭될 때 마다 가지고 있던 child를 해제하고 새로운 것을 OnActivate event에서했듯이 원하는 타입으로 다시 초기화 합니다.

Child := TForm2.Create(Self);
with Child do begin
Parent := Self;
Align := alClient;
Visible := True;
end;

tab이 바뀜에 따라 child 페이지를 생성할 때 위에 보여진 것과 같이 하십시오.물론 child window가 해제될 때 그 child windo w에 있던 데이타는 사라져 버리기때문에 주어진 child window의 상태를 유지하기 위해 필요한 데이타는 main폼에 저장해야 할 것입니다.

[Q10] 새로운 component를 만들고자 하는데 Parent class를 무엇으로 해야하나요 ?
[A10] 가장 쉬운 방법은 특성을 알기 쉬운 component를 선택하는 방법입니다.

TComponent - non-visual component를 만들때의 기본입니다.
TWinControl - window handle이 필요할 때의 기본입니다.
TGraphicControl - window handle에 대한 overhead가 필요없는 visual component를
만들때의 좋은 기본입니다. 이 class는 paint method를
가지고 있습니다.
TCustomControl - Visual component에 대한 가장 일반적인 기본입니다.
이 class는 Window handle과 일반적인 event, property를
가지고 있으며, paint() method에 대한 canvas를 가지고
있습니다.

[Q11] TPanel로부터 derive된 component를 하나 만들었습니다. constructor에는BevelWidth 값이 항상 1로 되어있습니다. pr operty는 constructor가 끝나고나서 설계시 update되는 것으로 알고 있습니다. 언제 이것이 일어납니까? 그리고component의 초 기화 값을 위치시키는 위치는 어디입니까 ?
[A11] Component가 stream으로부터 읽혀질 때, 각각의 component는 먼저construct되고, property 값이 stream으로부터 읽 혀집니다. component의 로드된method는 모든 stream 과정이 끝났을 때 불려집니다. component가 stream으로부터load된 후에 어 떤것을 override Load할 수 있습니다.

[Q12] publish에 array property를 설정하였는데 #202 error가 발생합니다.무엇때문에 publish 될 수가 없습니까 ?
[A12] online help의 "published parts"를 보면 어떤 property와field가 publish될 수 있는지 나와있습니다. no n-standard data type (arrayproperty 포함) 데이타만 stream할 수있습니다. 참고적으로 TStringList source를참고 하십시오.

[Q13] 특수한 font를 사용한후 문자의 fixel에서 길이를 어떻게 결정해야합니까?
[A13] 픽셀에서 문자열의 문자 높이와 넓이를 결정하기 위해 TextHeight와TextWidth인 Canvas Method를 사용합니다. 그리 거나, 크기를 결정하기 전에Canvas에서 font를 지정해야만 합니다.

[Q14] Release/Free와 Close method의 다른점은 무엇입니까 ?
[A14] release와 free method는 본질적으로 기능이 같습니다. 따라서 발생하는event도 동일하며 아래와 같습니다. 특징은 close event가 발생하지 않는 다는것입니다.

Hide, Destroy

Close method를 사용했을 경우에는 Destroy가 발생하지 않습니다.

[Q15] 표준 Delphi controls의 용량 한계는 무엇입니까?
[A15] 정보를 저장하기 위해 TList를 사용하는 component는 16368 아이템이상을 넘을 수 없습니다. 예를 들어 TTabControl 은 16368개의 tab을 포함할수있으며, Delphi의 component pallete는 16368개의 pallete 페이지를 포함할수 있습니다.

Dephi Standard component의 숫자는 표준 윈도우 control을 포함할 수 있습니다.
Windows 3.1은 이들 component 내의 한계를 지우고 있습니다. 예를 들어: TComboBox나TListBox는 5440개의 아이템을 포함할 수 있으며, TMemo나 TEdit (또는 연관된컴포넌트)는 32KB의 문자를 포함할 수 있습니다.

Windows 3.1 Resource 공간은 TNoteBook component에서 570 페이지의 한계를가지고 있습니다.(이것은 다른 Windows 어플리케이 션에서 500 Window Handle이상을할 수 있는 것과는 다릅니다.)

주의 1 : 이 한계를 넘을 경우 Exception이 발생하거나, Windows가 이상한 행동을하는 원인이 될 수 있습니다.
주의 2 : Windows에 기초된 많은 것들의 용량 한계는 Windows NT와 Windows95의 16-bit WOW Box에서 보다 많을 수 있습니다. D elphi의 32Bit version은이런 한계의 가정된 모든것이 발생하지 않습니다.

[Q16] TPanel과 TEdit 같은 어떤 visual component는 왜 Canvas 특성을 가지고있지 않습니까?
[A16] 모든 TCustomControl의 상속은 Canvas 특성을 가지고 있습니다. 그렇지만,대부분은Component에 그려지는것을 '외부' 로 제한하기 위해 보호되고 있습니다.하나의 Component의 상속들은 항상 Component(Canvas와 같은)로 부터 상속받은특성이 보 호된채 접근할 수 있습니다. 그러므로 다음과 같이 Canvas를 publicproperty로 만들어 줍니다.

Type
TCanvasPanel = calss(TPanel)
public
Property Canvas;
End;

[Q17] Delphi가 Currency/money 컴포넌트를 가지고 있습니까?
[A17] 아니오. 그러나 천리안의 Delphi Forum이나 internet 등에서 CurrencyEdit Component를 다운로드 받아서 사용할 수 있습니다.

[Q18] Component들을 오목과 볼록으로 보이게 만들 수 있습니까?
[A18] TBevel이나 TPanel Component의 Frame특성인 raise나 lower특성을사용하여 오목과 볼록으로 보이게 할 수 있습니다.

[Q19] Visual Basic에서 Control Array와 같은 것을 생성하는게 가능합니까?
[A19] 이것을 하기 위해 Sender의 Tag field에서 보이는 공통적인 OnClickevent handler를 생성하거나, 다른 번호로 각각 의 버튼에 대한 Tag field를설정하는 방법이 있습니다.
그룹되어진 모든 버튼에게 같은 OnClick event handler를 지정합니다. 그리고이렇게 OnClick event handler를 지정하면 됩니다 .

Procedure TForm1.Button1Click(Sender:TObject);
Begin
case TButton(Sender).Tag of
1:ShowMessage('1st Button Pressed');
2:ShowMessage('2nd Button Pressed');
3:ShowMessage('3rd Button Pressed');
end;
end;

[Q20] 가로(페이지의 옆면에) Tab Components가 가능한, 상업적인, Shareware나Freeware가
있는곳은 어디 입니까?
[A20] TurboPower's Orpheus Product가 이것을 지원할 것입니다. 추가적인정보는 compuserve의
'GO TURBOPOWER'로 하시기 바랍니다.

[Q21] non-visual component를 만들려고 할 때, 하나의 property를 FileNameproperty로 하려고 합니다. 설계시에 사용자가 object inspector에서 생략(...)버튼을 눌렀을 경우에OpenDialogbox을 띄워서 선택한 filename이 property 값으로assign되게 하는 방법은 무엇입니까 ?
[A21] 다음과 같이 하면 됩니다.

TFileNameProperty = class (TStringProperty)
public
function getattributes: TPropertyattributes; override;
procedure Edit; override;
end;

RegisterPropertyEditor(Typeinfo(String),
TMyComponent, 'Filename', TFileNameProperty);

function TFileNameProperty.GetAttributes;
begin
Result := [paDialog];
end;

Procedure TFilenameProperty.edit;
var
MFileOpen: TOpenDialog;
begin
MFileOpen := TOpenDialog.Create(Application);
MFileOpen.Filename := GetValue;
MFileOpen.Filter := 'The Right Kind Of Files|*.*';
MFileOpen.Options := MFileOpen.Options + [ofPathMustExist,ofFileMustExist];
try
if MFileOpen.Execute then SetValue(MFileOpen.Filename);
finally
MFileOpen.Free;
end;
end;

[Q22] Delphi는 Serial 통신을 지원하는 Component를 가지고 있습니까?
[A22] 없습니다. 그러나, TurboPower, SaxComm와 같은 Third-Party 회사들로부터Delphi에서 사용가능한 Serial Communicat ions Libraries가 있습니다.

Database

[Q1] IDAPI의 정의는 무엇입니까? 그리고 SQL Links는 무엇입니까?
[A1] IDAPI는 Integrated Database Application Program Interface의 약어입니다.BDE는 일관된 API 를 가지고 복수개의 data source들과 접속하기 위한 한 방법입니다.IDAPI는 바로 BDE에 대한 API입니다. 그것은 데이타를 액세스하고 조작하는등의 필요한 모든 function들이 포함되어 있습니다. Delphi, dBASE for Windows,Paradox for Windows등이 data를 액세스하기 위해 이들 function들을 사용합니다.개발자는 스스로 자신의 프로그램들에 이들을 사용할 수가 있습니다.
BDE를 구입하여 이들 관련 문서를 얻을 수 있고, 제품에는 모든 가용한 function들이리스트되어 있고 이용할 수 있습니다. Del phi source를 찾아보면 사용된 이들function들을 볼 수가 있을 것입니다. 그것들은 "Dbi"로 시작되어집니다.(예를들면, DbiCreateTable) SQL Links는 remote database server에 연결하기 위해서사용할 수 있는 선택 가능한 내장 드라이버들입 니다.

[Q2] SQL Links가 지원하는 Informix(Online, I-NET)의 버전은?
[A2] SQL Links는 DELPHI 1.02 버전이상 부터는 Informix server의 모든버전들과 잘 동작합니다.

[Q3] Delphi에서 data 접속을 위해 IDAPI가 필요합니까? 배포되는 어플리케이션이사용자의 컴퓨터들에 IDAPI를 설치할 필 요 없도록 Delphi EXE내에 IDAPI를내장할 수 있습니까?
[A3] IDAPI는 Delphi에서 data 접속을 위해 필요합니다. Delphi는 IDAPI를설치하는 BDE 재분 배 가능한 디스켓과 함께 따 라옵니다.

[Q4] 제가 가지고 있는 SQL Link 구 버젼을 Delphi와 호환성있는 IDAPI와같이 사용할 수 있습니까?
[A4] 구 버젼의 SQL Link는 사용하지 못합니다. Client/Server에는 모든것이 포함되어 있으며, Delphi와 새로운 SQL Lin k만이 가능합니다.

[Q5] Quattro Pro 6.0과 IDAPI 를 네트웍에 가지고 있읍니다. 델파이와 새로운IDAPI를 네트웍에 설치한 뒤에 Quattro Pro 를 다른 기계에서 실행시키면 언어드라이버를읽어들일 수 없다는 에러가 납니다.
[A5] WIN.INI 파일에 IDAPI/LANGDRV 디렉토리를 지칭하기 위해 [BorlandLanguage Drivers] 섹션을 추가합니다. 예를들면 다음과 같습니다.

[Borland Language Drivers]
LDPATH=C:\IDAPI\LANGDRV

[Q6] ReportSmith, Interbase, SQL Links/ODBC 연결성에 대한 도움은 어디서얻을 수 있읍니까?
[A6] 볼랜드 개발 툴 포럼(Borland Development Tools forum : BDEVTOOLS)에 가십시오. ReportSmith, InterBase, Borland Database Engine, SQL Links/ODBC연결성에 대한 섹션이 있읍니다.

[Q7] IDAPI.CFG 화일에 한 alias를 추가하기 위한 프로그램적인 방법이 있습니까?
[A7] BDE는 DbiAddAlias()라고 하는 함수를 포함합니다. Specification들은AddAlias.txt 화일의 Section 6(Database) library에서 확인할 수 있습니다.또한, AliasManager라고 하는 Delphi component도 Section 6(Database) library에서가능합 니다.

[Q8] 'IDAPI error $2C08' 이 무슨뜻입니까?
[A8] IDAPI01.DLL을 읽어들일 수 없다는 뜻입니다. WIN.INI 파일의 다음섹션에 DLLPATH 가 정확한 위치를 지칭하고 있는지 를 확인하십시오.

[IDAPI]
DLLPATH=C:\IDAPI
CONFIGFILE01=C:\IDAPI\IDAPI.CFG

[Q9] 데이터베이스 응용프로그램을 델파이에서 실행시키려고 하자 EDatabaseError예외와 함께 'An Error occurred while at tempting to initialize the BorlandDatabase Engine (Error $2C09)' 라는 에러가 발생했읍니다.
[A9] SHARE.EXE /F4096 /L40 를 AUTOEXEC.BAT 에 추가하거나 SYSTEM.INI파일의 [386Enh] 섹션에 DEVICE = VSHARE.386을 넣고 다시 부트하세요.

[Q10] 프로그램에서 서버 데이타베이스(즉, Informix, Oracle, Sybase등)를연결하고자 할 때 해야 할 것은 ?
[A10] Delphi를 사용하여 데이타베이스 프로그램을 작성하려면 우선 해당Server 데이타베이스에 해당되는 Client Module이 개발자 PC에 설치되어 있어야합니다.
예를 들면 Informix의 경우에는 I*Net for windows, Oracle의 경우에는 SQL*Net을말합니다.
이것이 설치되어 설정사항이 모두 정확하여 데이타베이스로의 Ping이 성공적으로이루어 지면 다음과 같이 합니다. 이것이 우선 되지 않으면 서버 데이타베이스로접속하실 수 없습니다.

Delphi C/S Version에서 제공되는 IDAPI driver를 사용하는 경우에는,
IDAPI Configuration Utility에서 해당 driver로 부터 하나의 Alias를 추가시킵니다.
그리고 나서 그 Alias에 적절한 Parameter를 설정하면 Delphi IDE 환경에서각종 데이타베이스에 관련된 component를 사용할 수 있습니다.
Informix의 경우에는 Alias Parameter중 SERVER NAME, DATABASE NAME, USERNAME을 반드시 명시합니다.
또한 Oracle의 경우에는 Driver Parameter중 VENDOR INIT과 Alias Parameter중SERVER NAME, USER NAME, NET PROTOCOL을 반드시 명시합니다. 예를 들어 SERVERNAME은 @T:lambda:ORA7 과 같이 작성합니다. 여기에서 IDAPI의 경우 @를 빼면접속되지 않음을
유의하여 주십시오.

또한 Delphi가 제공하는 IDAPI driver로 접속할 수 없는 다른 종류의 데이타베이스를사용하려면 우선 ODBC driver를 구입하십 시오.
데이타베이스 vendor가 제공하거나 또는 3rd party 회사로 부터 구입한 ODBCdriver를 설치한 후에 제어판에서 ODBC driver를 s etup합니다.
사용할 데이타베이스 이름, 서버명 등 접속에 필요한 모든 정보는 ODBC driversetup 화면에서 설정해야 합니다.
이들 설정이 완성되지 않으면 마찬가지로 다음 Configuration 작업은 무의미합니다.
ODBC Driver 설정을 마친후에 IDAPI Configuration Utility에서 해당 ODBC driver의정보를 사용하는 새로운 driver를 추가시킵 니다.
또한 새로 추가한 driver로 부터 새로운 Alias를 추가합니다. 이 때 ODBC 제어판에서설정사항을 맞추었던 Data Source 이름을 ODBC DSN이라는 Parameter에서 확인할수 있으므로 이것이 올바르게 지정되었는지 살펴보십시오.

위의 작업이 끝나고 Configuration 화일이 저장되면 Delphi IDE 환경에서 각종데이타베이스에 관련된 component를 사용하여 프 로그램 하실 수 있습니다.

[Q11] database component를 이용하여 login prompt 없애는 방법?
[A11]
1.database component의 popupmenu인 database editer 선택
2.default button를 누른후에 'password ='에 사용자password 입력
3.login prompt를 check 안함

[Q12] 새로운 Table을 하나 만들고 Index를 정의하려고 합니다. 어떻게 합니까?
[A12] 그방법은 NewTable에서 index를 정의하는 정확한 방법입니다. 그러나아마도 Table의 IndexDefs property가 update 되지 않았을 것입니다. 그러므로,아래와 같이 Update method를 사용할 필요가 있습니다.

with NewTable do begin
Active := False;
DatabaseName := 'DBDEMOS';
TableName := 'Temp';
TableType := ttParadox;
FieldDefs.Assign(Table1.FieldDefs);
Table1.IndexDefs.Update; { Do an update first }
IndexDefs.Assign(Table1.IndexDefs);
CreateTable;
end;

[Q13] transaction 사용법은 ?
[A13]

procedure TForm1.FormCreate(Sender: TObject);
begin
database1.connected := true;
database1.starttransaction;
table1.open;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
table1.close;
database1.rollback;
database1.connected := false;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
database1.commit;
database1.starttransaction;

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
database1.rollback;
database1.starttransaction;
end;

[Q14] 여러table에 대한 작업을 하나의 connection으로 유지하려는 작업은?
[A14] database component를 이용하여 transaction 처리

procedure TForm1.FormCreate(Sender: TObject);
begin
database1.connected := true;
database1.starttransaction;
table1.open;
table2.open;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
table1.close;
table2.close;
database1.rollback;
database1.connected := false;
end;

[Q15] table의 field명을 가져오려면 ?
[A15] fieldcount와 fieldname 사용

procedure TForm1.Button1Click(Sender: TObject);
var i : integer;
begin
with table1 do
begin
for i := 0 to fieldcount -1 do
listbox1.items.add( fields[i].fieldname);
end;
end;

[Q16] field editer에서 editmask를 setting했을때 literal문자를 자료로저장하지않고 단지 display용으로만 사용하려면 ?
[A16] editmask대화창(input mask editor)의 save literal characters option를check 하지 않는다.

editmask에 대한 예제는 DB\Q16 참조

[Q17] 다른 table의 정보를 calculated field로 load 시키려면 ?
[A17]

procedure TForm1.Table1CalcFields(DataSet: TDataset);
begin
if table2.findkey([table1.fields[1].asinteger]) then
table1company.value := table2.fields[1].asstring
else
table1company.value := 'none assign';
end;

예를 들어서 table1의 custno = 1221를 가지고 table2의 custno에서 1221를찾은후 table2의 특정 field내용을(compony)를 tab le1compony(calculated field)에넣는다.

[Q18] datatype field에 대한 조건을 주고 query를 하려는 경우 ?
[A18]

{sql문를 sql property에 editing}
SELECT ORDERS."OrderNo" , ORDERS."CustNo", ORDERS."SaleDate", ORDERS."EmpNo"
FROM "ORDERS.DB" ORDERS WHERE ( ORDERS."SaleDate" >=:dd )

procedure TForm1.Button1Click(Sender: TObject);
begin
Query1.Close ;
Query1.ParambyName('dd').asDatetime := strtodatetime(edit1.text);
query1.open;
end;

[Q19] query에서 outer join 하는 방법은 ?
[A19] 다음과 같이 참조 하십시오.

select proj_id,full_name
from employee left outer join employee_project
on employee.emp_no = employee_project.emp_no;

이것은 interbase용 sql 입니다. 사용하시는 db에 적합한 outer join용 sql문을사용하십시오.

[Q20] onCloseQuery Event는 언제 사용합니까 ?
[A20] 일반적으로 onClose와 onCloseQuery는 해당 form이 close될 때 발생합니다.하지만 차이점은 onClose는 해당폼이 clo se할때만 발생하지만 onCloseQuery는Parent form이 close될때도 발생됩니다.

[Q21] sql문에서 substring format은 ?
[A21] visual query builder의 expression 대화창의 substring(str,st,len)이아니고, substring(from 처음자리수 for 길이 )입니다.

sql문 예제 :
SELECT ANIMALS."NAME", ( substring( ANIMALS.NAME from 1 for 3) ) as Expr__1
FROM "ANIMALS.DBF" ANIMALS

[Q22] record의 특정필드가 비어있는 곳을 찾으려면 ?
[A22] date field의 입력이 안된 부분을 찾고싶을때 사용하는 sql문 입니다.
SELECT * from orders where orders."adate" is null;

[Q23] TQuery와 TDataSource 가 있읍니다. TQuery의 TStrings 프로퍼티에'SELECT * FROM dbo.AnyTable' 을 넣었읍니다. (여 기서 dbo 는 SQL 서버에있는 데이타베이스입니다.) Active 프로퍼티를 TRUE 로 두자 'Token not found.Token : dbo. line numb er : 1'이라는 에러가 발생했읍니다. 뭐가 잘못된 것일까요?
[A23] RequestLive 프로퍼티가 True 로 되어있으면 테이블 이름을 따옴표로둘러싸야합니다.
예) SELECT * FROM "dbo.table"

만약 RequestLive 프로퍼티가 False로 되어있으면 따옴표를 쓰면 안됩니다.
예) SELECT * FROM dbo.table

[Q24] stored procedure를 실행하려면 ?
[A24] storedproc1의 procedure는 input data(dno), output data(tot)이며table의 특정field값을 input data값에 assign하 면, 한 record가 변할때마다output data값이 변하여 label2에 display됩니다.

procedure TForm1.DataSource1DataChange(Sender: TObject; Field: TField);
begin
WITH STOREDPROC1 DO
BEGIN
IF PREPARED = FALSE THEN PREPARE;
params.parambyname('dno').asstring :=
table1.fieldbyname('dept_no').asstring;
execproc;
label2.caption := parambyname('tot').asstring;

END;
end;

[Q25] DBGrid에 나타나지 않게 필드를 만들 수 있습니까?
[A25] Fields Editor의 필드 목록으로 부터 입력된 필드를 제거하거나,Visible 특성을 False로 설정함으로써 할 수 있습니 다.

[Q26] TDBGrid의 현재 레코드와 필드의 위치를 어떻게 알릴 수 있습니까?
[A26] 현재의 Column과 Row의 트랙을 유지하기 위한 Method의 예가 아래에있습니다. 메쏘드 MyDBGridDrawDataCell에서 grid가 다시 그려질 때마다 변수Col과 Row는 매번 갱신되어 집니다. 이 코드를 사용하여 현재의 column과 row에대해 Col과 Ro w 변수가 포인트하는 것으로 가정할 수가 있습니다.

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;Field: TField; State: TGridDrawState);
var
RowHeight: Integer;
begin
if gdFocused in State then
begin
RowHeight := Rect.Bottom - Rect.Top;
Row := (Rect.Top div RowHeight) - 1;
Col := Field.Index;
edit1.text := inttostr(row);
edit2.text := inttostr(col);
end;
end;

[Q27] TDBGrid에서 현재의 row에 대해 어떻게 선택표시(highlight)할 수있습니까?
[A27] TDBGrid의 Option property에서 dbRowSelect 항목을 enable 로 설정합니다.

[Q28] dbgrid의 각COLUMN별로 색상를 넣는법 ?
[A28]

procedure TForm1.DBGrid1DrawDataCell(Sender: TObject; const Rect: TRect;Field: TField; State: TGridDrawState);
begin
if gdFocused in State then
with(Sender as TDBGrid).Canvas do
begin
Brush.Color := clRed;
FillRect(Rect);
TextOut(Rect.Left,Rect.Top,Field.AsString);
end;
end;

[Q29] Windows상에서 사용자 message를 정의하여 사용하려면 ?
[A29] Windows상에서 사용자 message로 정의하여 쓸 수 있는 message는WM_USER 이후의 숫자로 제한됩니다. 그러므로 다음 과 같이 사용자 message를정의할 수 있습니다.

RequestMsgID = wm_User+1000;
ResponseMsgID = wm_User+1001;

그리고 다른 종류의 Windows message를 처리하는 것과 동일한 방법으로 messageprocedure를 정의합니다.

TForm1 = class(TForm)
private
{ Private declarations }
Procedure RespondToRequest(Var Msg:TMessage);Message RequestMsgID;
Procedure ReceiveData(Var Msg:TMessage);Message ResponseMsgID;
public
{ Public declarations }
end;

Procedure TForm1.RespondToRequest(Var Msg:TMessage);
Begin
{your message procedure}
end ;

[Q30] dbgrid의 last record에서 downkey를 누르면 자동으로 record가 삽입되는데이것을 막고 싶을때는 어떻게 하나요?
[A30]

procedure TForm1.TTable1BeforeInsert(DataSet: TDataset);
begin
Abort;
end;

{table의 before insert event handeler를 발생시킨후 abort 사용 }

[Q31] component의 icon을 만드는 방법은 ?
[A31]

1) tools/image editor선택
2) file/project type(component resource (DCR))선택
3) new resource에서 color를 16color, size in pixels width 24,height 24를설정
4) icon를 그린 후 default로 생긴 bitmap_1를 user가 define한 class명으로변경
(반드시 대문자)
5) save as로 pas 화일명과 동일한 이름으로 dcr화일을 저장(반드시 같은 directory)

[Q32] 데이타 입력을 위하여 Tab 또는 마우스 대신에 Return 키를 사용할수 있습니까 ?
[A32] Edit 컴포넌트의 OnKeyPress 이벤트에 다음과 같은 코드를 사용하면됩니다.

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
If Key = #13 Then
Begin
SelectNext(Sender as tWinControl, True, True );
Key := #0;
end;
end;

이것은 Enter를 Tab처럼 동작하게 합니다. 폼에 있는 전체의 콘트롤(버튼을제외한)에 대해서 이와같은 동작을 원하면 전체의 콘트롤을 선택한 후에 OnKeyPress핸들러를 Edit1KeyPress로 지정하면 됩니다. 이제 각각의 콘트롤에 대해서 Enter가Tab처럼 작 동됩니다.
만약, 폼 레벨에서 이와같은 동작을 원하면(폼에 있는 전체의 콘트롤의 OnKeyPress핸들러에 전부 지정하기를 원하지 않는다면) 폼의 OnKeyPress에 다음과 같은코드를 사용하면 됩니다. 위의 코드에서 Sender만 ActiveControl로 바꾸고 폼의Property에서 K eyPreview를 true로 바꾸어 주면 됩니다.

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
If Key = #13 Then
begin
SelectNext(ActiveControl as tWinControl, True, True );
Key := #0;
end;
end;

이것은 폼에 있는 각각의 콘트롤에 대해서 Enter가 Tab처럼 작동합니다.

[Q33] 이미지화일을 db의 blob 필드로 load 하는법?
[A33]

procedure TForm2.Button1Click(Sender: TObject);
begin
Table1.Edit ;
DBImage1.Picture := Image1.Picture ;
Table1.Post ;
end;

procedure TForm2.BitBtn1Click(Sender: TObject);
begin
Image1.Picture.LoadFromFile('C:\windows\256color.bmp') ;
end;

[Q34] dbgrid의 원하는 field로 control를 보내는법?
[A34]

procedure TForm1.Button1Click(Sender: TObject);
var i:integer;
begin
for i:= 0 to 5 do
postmessage(dbgrid1.handle,WM_keydown, VK_TAB, 0);
end;

dbgrid의 6번째 field에 control를 보내는법(사실 tab key를 6번 보내준것)

[Q35] memo의 내용을 DBMemo로 put 또는 get 하는 방법은 ?
[A35]

dbmemo1.lines.assign(memo1.lines); (put하는법)
memo1.lines.assign(dbmemo1.lines); (get하는법)

[Q36] 테이블에 저장된 것과 같은 blob 필드의 실제 크기를 어떻게 결정할수 있습니까?
[A36] blob, memo, graphic 필드의 크기를 돌려주는 함수로써 GetBlobSize()를사용해 보십시오.

Function GetBlobSize(Field:TBlobField):LongInt;
var
bi:tblobstream;
begin
bi := TBlobStream.Create(Field,bmRead);
with bi do
try
Result := Seek(0,2);
finally
Free;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Text := IntToStr(GetBlobSize(table1Notes));
end;

[Q37] run time시에 database property를 설정하는 방법은 ?
[A37] datbase component를 사용할때는 다음과 같이 합니다. 이와 같이하면 사용자가 BDE configuration utility에서 Alia s를 추가로 설정할 필요가없습니다.

database1.aliasname := 'dbdemos';
database1.databasename := 'testdb';
database1.connected := true;
table1.databasename := 'testdb';
table1.tablename := 'animals.dbf';

[Q38] 두개의 form에서 처음 form의 table과 datasource를 사용하려면 ?
[A38] 처음 Form이 정의되어 있는 Form의 Unit 명을 uses절에 추가시킵니다.

unit unit2;
interface
{...}
implementation
uses
unit1;

{$R *.DFM}

procedure TForm2.FormActivate(Sender: TObject);
begin
table1.databasename := form1.table1.databasename;
table1.tablename := form1.table1.tablename;
datasource1.dataset := form1.datasource1.dataset;
dbgrid1.datasource := form1.dbgrid1.datasource;
table1.open;
end ;
end.

[Q39] database에 포함된 table list를 얻을 수 있는 방법은 ?
[A39]

procedure TForm1.Listbox1Click(Sender: TObject);
begin
Listbox2.Clear;
Session.GetTableNames(Listbox1.Items[Listbox1.ItemIndex], '', True, False,Listbox2.Items);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Session.GetDatabaseNames(Listbox1.Items);
end;

[Q40] control의 events에서 예외상항(exceptions)들을 처리할 간단한 방법은?
[A40] 예외처리에 대한 추적을 위해 form의 method를 작성합니다. 이 method는어플리케이션의 OnException method상에 서 호출되어질 것입니다. 이 method에서확인하려는 예외 상황을 check해 봅니다.(예를 들면, EdatabaseError). OnExceptioneve nt에 대한 on-line Help를 확인해 봅니다. 이 event에 대해 만든 method를호출하는 방법에 대한 정보가 설명되어 있습니다.

type
TForm1 = class(TForm)
Table1: TTable;
DataSource1: TDataSource;
Database1: TDatabase;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
Procedure MyExcept(Sender:TObject; E:Exception);
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

Procedure TForm1.MyExcept(Sender:TObject; E:Exception);
{Don't forget to do a forward declaration for this in the class definition}
begin
If E is Edivbyzero then
MessageDlg('zero로 나눌수 없습니다. ',mtInformation, [mbOk],0)
else
{ it's not the error you're looking for, raise it }
end;

procedure TForm1.FormCreate(Sender:TObject);
var i,io : integer;
begin
Application.OnException := MyExcept;
{ Here is how you assign the OnException event to your handler }
io := 0;
i :=i div io;
end;

[Q41] db에 data를 입력할때 error 처리 방법 및 TDBEdit에 대한 mask 생성법은?
[A41]

procedure TForm1.MaskEdit1Exit(Sender: TObject);
begin
MaskEdit1.Text := FormatDateTime('HH:MM', StrToTime(MaskEdit1.Text));
Edit1.Text := FormatDateTime('HHMM', StrToTime(MaskEdit1.Text));
end;

procedure TForm1.MaskEdit2Exit(Sender: TObject);
begin
MaskEdit2.Text := FormatDateTime('HH:MM', StrToTime(MaskEdit2.Text));
Edit2.Text := FormatDateTime('HHMM', StrToTime(MaskEdit2.Text));
if StrToTime(MaskEdit2.text) < StrToTime(MaskEdit1.text) then
ShowMessage('From 시간보다 작습니다.')
else
MaskEdit3.Text := FormatDateTime('HH:MM', StrToTime(MaskEdit2.text) - StrToTime(MaskEdit1.text));
end;

[Q42] dBase 테이블의 expression 인덱스를 가지고 tTable.FindNearest나tTable.FindKey를 사용하면 'Index out of range' 에러가 왜 납니까?
[A42] FindKey 와 FindNearest 는 dBase 의 expression 인덱스에 대해 동작하도록설계되지 않았읍니다. 그러나 tTable 의 GoToKey나 GoToNearest 는 dBase의expression 인덱스에 대해 잘 작동합니다.

[Q43] dBASE 테이블을 pack하기 위한 BED API나 DLL이 있습니까?
[A43] BDE는 dBASE 테이블을 pack하기 위한 함수로써 DbiPackTable()을포함하고 있습니다. 만들고 있는 unit의 USES 절 에 DBITYPES, DBIPROCS, 그리고DBIERRS를 추가하고, 다음과 같이 BDE function을 호출합니다:

DBIPackTable(Table1.DbHandle, Table1.Handle, 'TABLENAME.DBF', szDBASE,TRUE);

주의: 테이블은 property exclusive를 true로 setting 해야합니다.

[Q44] 삭제 표시된 dBASE 레코드들을 어떻게 볼 수 있습니까?
[A44] table의 AfterOpen event 에 다음의 function을 호출합니다. 먼저,DBITYPES, DBIPROCS, DBIERRS를 USES 절에 포 함시킵니다. 그리고 호출하기위해, Ttable의 이름과 삭제된 레코드들을 보이거나 보이지 않도록 하는 TRUE/FALSE를 argument로 서 보냅니다.

주의) dbase table에서만 가능

[Q45] dBASE 테이블에서 레코드들이 삭제를 위한 표시가 되어 있는 것을grid의 column에 어떻게 만들 수 있습니까?
[A45] 계산필드(calculated field)를 만들고, 테이블의 OnCalcField event에대하여 계산필드에 아래와 같이 만들어진 모듈 로 내용을 치환합니다:

{다음 프로그램은 pack된data를 찾아서 calculated field에 표시, 단 dbasetable에 해당됩니다}
procedure SetDelete(oTable:TTable; Value:Boolean);
var
rslt: DBIResult;
szErrMsg:DBIMSG;
begin
try
oTable.DisableControls;
try
rslt := DbiSetProp(hDBIObj(oTable.Handle), curSOFTDELETEON, LongInt(Value));
if rslt <> DBIERR_NONE then
begin
DbiGetErrorString(rslt, szErrMsg);
raise Exception.create(StrPas(szerrmsg));
end;
except
on E: EDBEngineError do ShowMessage(E.Message);
on E: Exception do ShowMessage(E.Message);
end; { except ending}
finally
oTable.Refresh;
oTable.EnableControls;
end; {finally ending}
end; {procedure end}

procedure TForm1.Table1AfterOpen(DataSet: TDataset);
begin
SetDelete(Table1,TRUE);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
table1.open;
end;

procedure TForm1.Table1CalcFields(DataSet: Tdataset);
var
RCProps: RecProps;
Result: DBIResult;
begin
Result :=DbiGetRecord(Table1.Handle, DbiNoLock, Nil, @RCProps);
if RCProps.bDeleteFlag then Table1Del.Value := 'X' else
Table1Del.Value := '';
end;

[Q46] Paradox의 TCursor와 같은것은 Delphi에서 무엇입니까?
[A46] TTable 컴포넌트입니다.

[Q47] Paradox의 Auto Increment형의 필드를 프로그램으로 생성하려면 어떻게해야합니까?
[A47] TQuery를 가지고 SQL의 CREATE TABLE 명령을 사용하십시오.

procedure TForm1.Button1Click(Sender: TObject);
begin
with Query1 do
begin
DatabaseName := 'DBDemos';
with SQL do
begin
Clear;
Add('CREATE TABLE "PDoxTb6.db" (ID AUTOINC,');
Add('Name CHAR(255),');
Add('PRIMARY KEY(ID))');
ExecSQL;
Clear;
Add('CREATE INDEX ByName ON "PDoxTb6.db" (Name)');
ExecSQL;
Clear;
add('select * from "PDoxTb6.db"');
open;
end;
end;
end;

[Q48] Paradox 테이블을 만들때, TTable 컴포넌트의 AddIndex 메쏘드로 index를생성할 때 ixUnique 선택사항을 사용할 수 없는 것은 무엇 때문입니까?"
[A48] TTable 컴포넌트의 AddIndex 메쏘드를 사용할 때의 Index 선택사항은테이블에 특정적입니다. 예를들어 ixUnique 선택사항은 Paradox 테이블에서는사용 못하고 dBASE 테이블에서 사용되는 선택사항입니다. 아래의 표는 dBASE또는 Paradox 테 이블에서 사용할 수 있는 선택사항을 나타냅니다.

Index 선택사항 dBASE Paradox
----------------------------------------------------------
ixUnique *
ixDescending * *
ixNonMaintained * *
ixPrimary *
ixCaseInsensitive *

[Q49] 현재 record 번호를 display하는 방법은 ?
[A49] install component에 rct.pas를 add 시킨후 recordposition component를form에 첨가합니다.

[Q50] Index 되지않은 필드에서 찾을 수 있는 방법은 무엇입니까 ?
[A50] 아래의 Locate() 함수를 사용해 보십시오.

Locate(Table1, Table1LName, '홍길동');

Table1은 table컴포넌트 입니다. Table1LName은 field editor를 통하여 추가된TField이며 찾고자 하는 이름은 '홍길동' 입니다 .

Function Locate( const oTable: TTable; const oField: TField; const sValue:String): Boolean;
var
bmPos : TBookMark;
bFound : Boolean;
begin
Locate := False;
bFound := False;
If not oTable.Active then Exit;
If oTable.FieldDefs.IndexOf( oField.FieldName ) < 0 then Exit;
bmPos := oTable.GetBookMark;

WithoTable do
begin
DisableControls;
First;
While not EOF do
if oField.AsString = sValue then
begin
Locate := True;
bFound := True;
Break;
end
else Next;
end ;

If (Not bFound) then oTable.GotoBookMark( bmPos);
oTable.FreeBookMark( bmPos );
oTable.EnableControls;
end;

[Q51] 패스워드 보호된 테이블을 열때, 패스워드 대화상자을 어떻게 취할수 있습니까?
[A51]
1. database desktop에서 table을 만든 후 table properties의 password security를PASSWORD로 정의합니다.
2. 간단히 다음과 같이 테이블을 열기 전에 추가를 원하는 패스워드와 함께Session object를 지정합니다.

Session.AddPassword('PASSWORD');

일단 테이블을 닫으면 RemovePassword('PASSWORD')로 패스워드를 제거하거나,또는 RemoveAllPasswords로 모든 현재의 패스워 드들을 제거할 수 있습니다.(단,Paradox 테이블일 경우로만 국한됩니다.)

[Q52] 파손된 index들을 rebuild하기 위한 BDE API 나 DLL이 있습니까?
[A52] BDE는 index들을 rebuild하기 위한 함수로써 DbiRegenIndexes()를포함하고 있습니다. USES절에 DBITYPES, DBIPR OCS, 그리고 DBIERRS를 추가하고,다음과 같이 BDE function을 호출합니다:

DBIRegenIndexes(Table1.Handle);

주의: 테이블은 exclusive property가 ture로 설정되어 있고 index는 미리 구성되어있어야 합니다.

[Q53] 어떻게 레코드 포인터가 변할때를 알수 있습니까 ?
[A53] State가 dsBrowse일때 OnDataChanged 이벤트를 사용하십시오.

[Q54] 레코드를 편집할 때 BDEngine 메세지인 'Multiple records found butonly one expected' 가 나오는 데 이것은 무엇을 의미합니까 ?
[A54] 아마도 테이블에 unique index가 생성되어 있을 것입니다. 그러므로먼저 테이블의 unique index를 unique하지 않은 index로 수정하면 중복되는값을 입력할 수가 있습니다. 그러나, 만약 unique index를 원한다면, 중복된레코드를 삭제하여야 합 니다.

[Q55] table로부터 Fixed Length ASCII text table을 만드는 방법은 무엇입니까?
[A55] 다음과 같이 하면 됩니다.
1.아래의 프로그램을 실행시키면 .TXT와 .SCH 화일이 생성됩니다. .SCH 화일은Table의 구조에 대한 정보를 가지고 있습니다.

procedure TForm1.Button1Click(Sender: TObject);
var
t1, t2: tTable; {t1 = PW table; t2 = ASCII version}
begin
t1 := tTable.create(self);
with t1 do
begin
DataBaseName := 'pw'; { Personal Alias for Paradox Directory }
tableName := 'customer.db'; { Source Table }
open;
end;

t2 := tTable.create(self);
with t2 do
begin
DataBaseName := 'pw'; { Personal Alias for Paradox Directory }
tableName := 'asdf.txt';
TableType := ttASCII;

createTable;
open;
edit;
BatchMove(t1, batCopy);
close;
end;

t1.close;
end;

2. ODBC driver를 이용할 수도 있습니다.

1) 제어판에서 Rs_text driver를 load할때 define format(각 column을 정의)을하면 schema.ini화일이 생성됩니다.
2) BDE config에서 ODBC driver와 Alias를 등록합니다.
3) Table의 tabletype property를 ttascii로 선택하고 원하는 Table명을 지정합니다.

[Q56] DBGrid component에click procedure를 추가하는 방법은 ?
[A56] New Component를 만들어 다음과 같이 OnClick event가 published되도록 정의합니다.
이 새로운 Component를 Install Component시키면 OnClick event가 Object Inspector창에 나타납니다.

TMyGrid = class(TDBGrid)
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
property OnClick ;
end;

[Q57] BDE Function들과 data type들의 리스트와 설명을 어느곳에서 찾을수 있습니까?
[A57] DELPHI\DOC\ 디렉토리에서 DBIPROCS.INT 화일은 BDE Function들 및필요한 parameter 들, return value, 그리고 각 각의 개략적인 설명이 포함되어있습니다.
DBIPROCS.INT는 BDE function들과 함께 사용되는 type들의 리스트입니다. BDEfunction들을 호출하기 위해서는 USES 절에 다 음의 unit들을 추가합니다: DBITYPES,DBIPROCS, DBIERRS.
IDAPI function들을 사용하는데 있어서 보다 자세한 정보는 Customer Service에서Database Engine User's guide를 얻을 수 있 습니다.

[Q58] 델파이로 만든 DB 프로그램에서의 한글 입력문제 해결 방안.
[A58] 델파이의 DB 에서 한글 문제가 발생하는 이유는대부분이 DatabaseEngine Configuration에서 설정을 잘못하였기 때 문입니다.

환경설정 방법은 다음과 같습니다.

프로그램 매니저의 델파이 그룹에서 Database Engine Configuration 프로그램을실행시킨 후

Ⅰ)왼쪽의 Driver들을 보면 DBASE, PARADOX, INTRBASE 등이 있습니다.

먼저 마우스로 DBASE를 선택하고, 오른쪽의 Prameters를 보면 LANGDRIVER라는란이 있습니다. 여기를 다시 클릭하면 오른쪽에 아랫쪽 화살표 모양의 버튼이생깁니다. 버튼을 누르면 밑에 선택할 수 있는 랭귀지 드라이버 리스트가 나옵니다.

DBASE에 대해서는 dBASE KOR cp949를 선택하시고,
INTRBASE에 대해서는(만약 INTRBASE 가 있다면) 빈칸으로 만드시고,
그 외 나머지 드라이버에 대해서는 모두 Paradox Korea 949로 만드세요.

Ⅱ) 이 프로그램 윈도우의 바닥쪽을 살펴보면 Aliases라는 탭이보입니다. 이탭을 누르시면 페이지가 바뀝니다. 각각의 Alias 에 대해 오른쪽의 Parameters중LANGDRIVER를 INTRBASE인 경우에는 비워놓고 그 외의 것은 모두 Paradox Korea949로 맞추십시오 .

Ⅲ) 프로그램의 System 페이지로 가기 위해 System 탭을 누르시면 여기에도LANGDRIVER란이 있습니다. 이것도 Paradox Korda 9 49로 바꾸십시오.

=====================================================================
이렇게 하면 델파이의 언어드라이버 세팅이 맞춰진 것입니다. 이후에 만들어진테이블에 대해서는 한글 문제가 발생하지 않을 것입니다.
그러나 테이블 마다 정해진 언어드라이버가 있기 때문에 이전에 만들어진 테이블에대해서는 아직도 잘못 정해져 있을 수가 있 습니다. 그런 경우에는 그 테이블에대해 언어 드라이버를 다시 맞춰줘야 합니다.

그 방법은 다음과 같습니다.

Ⅰ) Database Desktop 을 실행합니다. 이것은 프로그램매니저의 델파이 그룹안에있습니다.
Ⅱ) 변경하고자 하는 테이블을 엽니다.
File |Open |Table 하시고, 적절한 파일타입과 알리아스 또는 드라이버를 지정하여테이블을 선택한 후 OK 버튼을 클릭합니다.
Ⅲ)Table |Restructure Table 로써 테이블의 구조를 바꾸는 윈도우로 들어갑니다.
Ⅳ) Restructure... 윈도우에서 오른쪽에 있는 Table Properties 항목에서 TableLanguage 를 선택합니다.
Ⅴ) 아래에 있는 Modify 버튼을 눌러 테이블 형식에 따라 위에서 설명한 대로지정하고 OK 버튼을 누릅니다.

======================================================================
마지막으로, Database Desktop 에서는 한글을 입력할 때에 키보드의 NUMLOCK버튼이 눌러져있어야 합니다. 즉, 오른쪽 키패드의 NUMLOCK에 불이 들어와 있어야합니다. 그렇지 않으면 Database Desktop 에서는 한글을 입력할 수 없습니다.이것은 이 유틸리 티만의 문제이며 델파이
에서는 상관 없이 한글을 입력할 수 있습니다.

참고로 Oracle을 사용하는 경우에 한글이 깨져 보일때는 Windows 디렉토리의ORACLE.INI 화일에NLS_LANG parameter를 DBMS에서 의 설정값과 동일하게 맞추어야합니다.
Oracle 7.X에서는 NLS_DATABASE_PARAMETERS table의 NLS_CHARSET을 확인하면됩니다.

[Q59] TDBGridd의 특정 field에 focus를 주는 방법?
[A59] 다음과 같이 프로그램 합니다.

DBGrid1.SelectedField := Table1SIZE;
DBGrid1.SetFocus;

 


제품 구성
[Q1] Delphi와 Delphi Client/Server 그리고 Delphi WorkGroup의 차이점은 무엇입니까?
[A1] Delphi Client/Server는 Delphi의 모든것에 추가적으로 아래의 것을포함하고 있습니다.

* SQL Links native drivers for Oracle, Sybase, MS SQL Server, Informix,
and InterBase.
* Rights for UNLIMITED redistribution of above drivers.
* Local InterBase Server Deployment Kit.
* Team Development Tools (integrates with existing PVCS installation).
* Visual Component Library source code.
* Visual Query Builder.

Delphi WorkGroup은 Delphi Client/Server에다가 InterSolv사의 PVCS VersionManager 제품이 추가로(포장은 별도로 되어있음) 제공되는 것입니다.

[Q2] 숨겨진 'Methods'를 배우기 위해 구입하거나, 읽어야 할것이 있습니까?
[A2] Component Writer's의 도움말 부분을 숙지하거나, VCL Source코드를구입하여 직접 보는것이 가장 좋습니다.

Project
[Q3] Object Inspector 표시는 무엇을 하는 것입니까 ?
[A3] object inspector는 모든 공개된 Class의 property을 표시합니다.(배열특성은 아니지만 쓰고 읽을 수 있습니다.) obj ect inspector는 Class의 Method에대해서는 표시할 수 없습니다.

[Q4] VB에서 스크린 세이버를 작성하듯이 Delphi에서도 만들 수 있습니까?
[A4]
(1) Project Source에 다음을 삽입합니다.
{$D SCRNSAVE:NameOfScreenSaver}
(2) Project를 컴파일합니다.
(3) .EXE를 .SCR로 이름을 변경하고 윈도우 디렉토리에 복사합니다. Close라고불리는 Mothod를 OnKeyUp과 OnClick에 지정합니 다.

[Q5] 아주 간단한 프로그램인 EXE가 왜그렇게 큰가요 ? (1개의 폼에 1개의버튼만 작성시 200KB)
[A5] Delphi의 VCL은 RTTI와 예외된 것에 기초하고 있습니다. 이것은 공백어플리케이션에 대해 약 120KB의 'footprint'를 요구합니다. 이 200KB는 사용자가디버그 정보를 포함했거나, 컴파일시 최적화를 시키지 않아서 그렇습니다. 버튼두개에 대하여 400KB인 사용자의 .EXE가 되지않지만, 201정도 되는 것을 주의하여보십시요. 데이타/코드 크기의 단지 추가되는 '일반적인'양 이 각각의 추가되는콘트롤과 함께 footprint가 되지 않습니다. 추가적으로 Option/Project 대화상자의Linker Page안에 있는 Ch eckBox는 크기와 읽는 시간를 최적화 합니다.

[Q6] 프로그램이 task list로 부터 없어지지 않은 상태에서 최소화된 icon을숨기는 방법은 무엇입니까 ?
[A6] SetWindowPos나 MoveWindow를 사용하여 icon을 화면 밖으로 이동시키십시오.
이 때 음수좌표를 할당하면 됩니다.

[Q7] 같은 application을 두번이상 실행되지 않게 하는 방법은 무엇입니까?
[A7] HPrevInst variable을 사용하면 됩니다. HPrevInst값이 0이 아니면같은 Application이 현재 Loading되어 있는 상태를 의미합니다. 따라서 .DPRsource에 다음과 같은 방법으로 사용할 수 있습니다.

program Project1;

uses
Forms,
Unit1 in 'UNIT1.PAS' {Form1};

{$R *.RES}

begin
if HPrevInst <> 0 then
Dialogs.ShowMessage('이미 실행중입니다')
else begin
Application.CreateForm(TForm1, Form1);
Application.Run;
end;
end.

[Q8] Splash screen을 보이는 루틴을 프로그램 어디에 포함시키면 좋을까요?
[A8] splash screen은 project source 화일의 첫번 FormCreate와 Run 사이에넣는것이 가장 좋습니다.

Splash unit에 다음과 같이 SplashForm이 정의되어 있습니다.

{$R *.RES}
var
SplashForm : TSplashForm; {in the Splash unit}

응용프로그램의 project source 화일은 다음과 같이 구성합니다.

program Project1;

uses Forms, Unit1 in 'UNIT1.PAS' {Form1}, Splash;
begin
Application.CreateForm(TForm1, Form1);
SplashForm := TSplashForm.Create(Application);
try
SplashForm.Show;
SplashForm.Update;
{
do other CreatForms or anyother processing
before the app is to be opened
}
SplashForm.Close;
finally
SplashForm.Free;
end;
Application.Run;
end.

[Q9] 왜 Unit를 닫으면, Form도 같이 닫히는지요 ?
[A9] Delphi는 사용자가 대화상자로 작업할때 코드를 제어할 수 있도록하기 때문입니다.
폼을 융통성있게 변경하기 위해 사용자의 변경한 점을 연관시켜 작업되기 때문입니다.

[Q10] minimize button이 눌러졌을 때(실제로 form이 작아지기 전에) capture할수 있는 방법이 무엇입니까 ?
[A10] WM_SYSCOMMAND message를 intercept해서 다음과 같이 사용하면 됩니다.

unit Unit1;

interface

uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs;

type
TForm1 = class(TForm)
public
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.WMSysCommand;
begin
if (Msg.CmdType = SC_MINIMIZE) or (Msg.CmdType = SC_MAXIMIZE) then
MessageBeep(0);
DefaultHandler(Msg);
end;

end.

[Q11] Sub form에서 전체 프로그램을 종료하려면 어떻게 해야 합니까 ?
[A11] 어느 form에서든 간에 MainForm.Close하면 전체 program은 종료됩니다.

[Q12] 실행시에 응용프로그램의 Icon을 다양하게 변경시키려면 ?
[A12] ICON은 Image Editor를 사용하여 Resource 화일에 저장시킵니다.
이 .RES 화일을 load 시키기 위해서 다음과 같이 선언합니다.
implementation
{$R test.res}

그리고 나서 Application.Icon property를 다음과 같이 설정합니다.
if FileExists( 'test.res' ) then
Application.Icon.Handle := LoadIcon( hInstance, 'ICON_NAME' );

[Q13] 프로그램을 실행시킬 때 입력 Parameter를 얻는 방법은 ?
[A13] ParamStr, ParamCount를 다음과 같이 사용하면 됩니다.

Y := 10 ;
for i := 1 to ParamCount do
begin
Canvas.TextOut(5, Y, ParamStr(i)) ;
Y := Y + Canvas.TextHeight(ParamStr(i)) + 5 ;
end ;

Debugger
[Q14] Delphi에서 BP7 프로젝트를 컴파일할 경우, 이것으로 Delphi의 통합된디버거를 사용 할 수 있습니까 ? 또한 무엇이 '주 화일'인지 어떻게 Delphi에전달하나요 ? 전 폼을 가지고 있지 않습니다.
[A14] 예, 통합된 디버거를 사용할 수 있습니다. 주 화일은 프로젝트 화일과같이 Open 하십시오. Open Project를 선택하시 고, 화일 형식을 *.DPR에서 *.PAS로변경한 후 컴파일 하고자 하는 BP7을 선택하시면 됩니다.

[Q15] 디버거 메세지중 "Debugger Is Unable To Stop Due To 'HardMode'"가 의미하는 것은 무엇입니까 ?
[A15] Hard Mode는 메세지 처리를 위치시킬 수 없는 경우 윈도우의 상태를이야기 합니다.
이것은 어떤 Kernel이 동작하거나 메뉴가 동작되는 동안 발생합니다. 이것이의미하는 것은 윈도우의 Lock없이 사용자의 어플리 케이션이 "freeze"할수 없는 Delphi의 상태에 사용자가 있다는 것을 의미 합니다.

[Q16] 나의 Resource Workshop project에서 .RES file 또는 .RC file을 저장할수 있습니까 ?
[A16] .RC file은 ASCII file이므로 debug하기 쉽고, 다른 프로그램에서도사용할 수가 있습니다. 그러므로 그것이 .RC fil e을 저장하고 자동적으로 .RESfile을 create하는 가장 좋은 방법입니다. 그렇게 하기 위해서는 먼저 .RC project를만들고 FILE |Preference에서 "Multi-Save .RES file" checkbox를check해주면 됩니다. 이제는 project를 저장할 때마다 자동적으 로 .RES file이생길 것입니다.

[Q17] WinSpector와 WinSight는 무엇입니까 ?
[A17] WinSpector는 windows application이 General Protection Fault나Unrecoverable Application Error가 발생했을 경우 에 postmortem inspection을실행하는 것을 허용하는 utility 입니다. WinSpector는 아래의 것을 보여줍니다.

* The call stack.
* function and procedures names in the call stack (with a little help fromyou).
* CPU registers.
* A disassembly of the instructions.
* Windows information.

WinSight는 application이 실행되는 동안 window classes, windows, 그리고message에 대한 정보를 보여주는 utility 입니다. 이것을 사용해서 application이어떻게 class와 window를 create하는지 그리고 window가 message를 주고받는것을 배울 수가 있 습니다.

[Q18] Borland Pascal 프로그램 출력을 지켜보기 위해 보조 모니터를 사용할수 있습니까 ?
[A18] 두개의 모니터를 사용하기 위해 하나는 반드시 MDA 모니터를 사용해야하고,(옛날의 Hercules Monochrome 형식) 다른 것은 VGA를(또는 EGA) 사용해야합니다.
이들은 MDA를 위한 $B000과 VGA를 위한 $B800의 2개의 주소 공간을 사용합니다.
Options/Environment/StartUp에서 보조 모니터를 사용하기 위헤 BP IDE에게사용자가 설정할 수 있도록 이들 모니터들을 설치해 야 합니다. 기본적인 모니터는프로그램의 출력을 표시하기 위한 BP IDE에서 설정되는 것입니다. (Delphi가아님)

주의 : Hercules 카드가 설치되었으면, 사용자의 VGA 카드는 8Bit로접근하게됩니다.

Installation
[Q19] Delphi를 install하는 동안 일부 Visual Basic program이 문제를 일으킵니다.왜 그렇습니까 ?
[A19] \Delphi directory에 있는 INSTALL.TXT file을 참고하십시오.
__________________________________________________________
|
| 2. BEFORE YOU RUN SETUP
| -----------------------
| .
| .
| .
| o VBX controls - SETUP installs the following VBX files
| into the \WINDOWS\SYSTEM directory that will
| overwrite any existing VBX files with the same name:
|
| GAUGE.VBX
| SWITCH.VBX
| PICT.VBX
| CHART2FX.VBX
|
| Before running SETUP, check for filename collisions
| and backup your existing copies of these files.
|
| .
| .
| .
| _______________________________________________________

Delphi에서 install하는 VBX file과 Visual Basic application에서 사용하는VBX file의 이름이 같을 경우는 다음과 같이 하십 시오.(GAUGE.VBX를 예로 설명하겠습니다.)

1) Delphi의 component palette에서 GAUGE.VBX를 제거합니다.
a) Options | Install Components를 선택합니다.
b) Installed list에서 GAUGE를 선택합니다.
c) REMOVE button을 클릭합니다.
d) OK Button을 누르면 delphi는 component library를 다시 컴파일 합니다.
e) Delphi를 빠져 나갑니다.

2) GAUGE.VBX를 다른 이름으로 바꿉니다.(예를들어 BIGAUGE.VBX 처럼)

3) 다시 Delphi로 가서 BIGAUGE.VBX를 component palette에 추가합니다.
a) Options | Install Components를 선택합니다.
b) VBX Button을 클릭합니다.
c) VBX File을 선택합니다(BIGAUGE.VBX).
d) OK Button을 누르면 component library를 다시 컴파일 합니다.

4) Visual Basic application에서 사용되었던 원래 GAUGE.VBX file을 \Windows\Systemdirectory로 복사합니다.

위와같이 하면 문제를 해결할 수있습니다.

[Q20] 'Database Desktop'이나 'Database Engine Configuration' 아이콘을클릭할 때, "multiple net files found "라는 error가 나옵니다.
[A20] System에 있는 *.lck file을 찾아서 지우십시오.

[Q21] Delphi에서 Version Control 기능을 사용하려면 어떻게 해야 합니까?
[A21] On-Line Help에서 "Version Control" topic을 참고하십시오.이 기능은 Client/Server 제품에서만 가능합 니다.

[Q22] Delphi를 실행했을 때 "can't open c:\delphi\bin\complib.dcl"이라는 error message가 나옵니다. 어떻게 해야 합니까 ?
[A22] 이러한 error는 여러가지의 경우에 발생합니다. Share 또는 VShare가올라오지 않았거나 또는 parameter가 잘못되어 있을 수도 있습니다. (F:4096L:40 권장)
또는 WIN.INI file에 [IDAPI] section이 빠졌거나 잘못되어 있을 수도 있습니다.아래를 참조하십시오.

[IDAPI]
CONFIGFIL01=C:\IDAPI\IDAPI.CFG
DLLPATH=C:\IDAPI

COMPLIB.DCL이 잘못되었을 경우에는 CD \RunImage\Delphi\Bin directory에 있는COMPLIB.DCL file을 새로 복사하십시오. 경우에 따라서는 windows가 잘못 install되어 있을 수도 있습니다.
아래의 file이 맞는지 확인하십시오.

VER.DLL 9,008
USER.EXE 264,016
KRNL386.EXE 76,400

[Q23] W8LOSS.EXE file은 무엇입니까 ?
[A23] W8LOSS.EXE file은 command line tool 입니다. 이것은 application의size를 optimize 해 주는 것으로써 Delphi의 OP TIONS|PROJECT|LINKER에서 'optimizefor size and load time.'를 선택하는것과 동일합니다.

 

 

'Delphi' 카테고리의 다른 글

델파이 API  (0) 2014.02.13
날짜/시간형식 변경 및 강제 시간세팅  (0) 2014.02.13
Tip 정리  (0) 2014.02.13
올림 / 내림(버림)  (0) 2011.08.03
델파이의 소숫점 반올림 방식  (2) 2011.08.03