---- 1. 델파이에서 트리 컨트롤을 사용하는 팁
---- 우리 모두는 개발자가 데이터베이스 관리 소프트웨어를 개발하기 위해 주로 Delphi를 사용한다는 것을 알고 있습니다. 이 때문에 트리 컨트롤의 사용은 데이터베이스와 가장 잘 연결됩니다. Delphi는 복잡한 계층 관계를 설명하는 데 사용할 수 있는 트리 컨트롤 TTreeView를 제공합니다.
---- 1. 트리 노드 정보 저장 및 로딩
---- 일반적으로 사용되는 방법은 트리 컨트롤의 LoadFromFile 및 SavetoFile 메서드를 사용하여 트리 컨트롤과 파일 간의 상호 작용을 구현하거나 Assign 메서드를 사용하여 트리 컨트롤과 DBMemo 간의 상호 작용을 구현하는 것입니다. , 데이터베이스와의 상호 작용. 이 방법의 장점은 프로그래밍이 비교적 간단하다는 것입니다. 단점은 트리 제어의 실제 노드 수가 매우 클 수 있다는 것입니다. "빅 트리"의 경우 매번 로드되고 저장되는 데이터의 양이 증가하게 됩니다. 속도를 줄이고 시스템 오버헤드를 늘리며 데이터 중복성을 유발합니다. 또 다른 방법은 트리에 "표시되는" 노드만 생성하는 것입니다. 전체 트리 노드 구조를 기록하는 전용 파일이나 데이터베이스 필드가 없으며 트리 노드 구조가 데이터베이스의 각 레코드에 분산되어 있습니다.
---- 구체적인 방법은 다음과 같습니다. 데이터베이스를 생성하고, 필드는 실제 비즈니스에 따라 결정되며, 트리 컨트롤의 노드에 정보가 표시될 필드가 하나 있어야 하며, 이를 저장하는 필드도 있습니다. 노드의 고유 식별 번호입니다. 식별 번호는 동일한 길이의 두 부분으로 구성됩니다. 첫 번째 부분은 현재 노드의 상위 노드 번호를 나타내고, 뒷부분은 현재 노드의 노드 번호를 나타냅니다. 트리의 노드 구조를 기록하는 "연결된 목록"입니다. 이 방법의 장점: 사용자가 "큰 트리"를 운영할 때 일반적으로 모든 노드를 확장하지 않고 제한된 부분만 사용하며 동시에 트리의 루트부터 레이어별로 확장할 수 있습니다. 이 방법은 트리에서만 ""을 생성하므로 "빅 트리"를 저장하고 로드하는 속도가 빠르고 데이터 양이 적으며 시스템 오버헤드와 데이터 중복성이 적습니다. 단점: 프로그래밍은 더 복잡하지만 이 방법을 결합하여 새로운 트리 제어를 형성할 수 있어 프로그래밍 효율성이 크게 향상됩니다. ID 번호는 고유해야 하므로 프로그래밍에서 ID를 합리적으로 생성하는 방법이 특히 중요합니다.
---- 2. 데이터베이스 구조 예
----데이터베이스 생성 절차를 단순화하기 위해 다음과 같이 정의된 두 개의 데이터베이스 필드만 생성합니다.
필드 이름 유형 길이
텍스트C10
LongIDC6
----LongID 필드는 실제로 두 개의 세그먼트로 구성되며 각 세그먼트는 3자리입니다. 1000개의 레코드만 나타낼 수 있습니다. LongID를 인덱스 필드로 정의하고 c: esttree ree.dbf로 저장합니다. DBF 파일을 편집하고, 새 레코드를 만들고, 텍스트 필드를 TOP로 설정하고, LongID 필드를 "000"(3개의 "0" 앞에 3개의 공백)으로 설정합니다.
---- 3. 데모 프로그램 만들기
---- TreeView1, Table1, PopupMenu1, Edit1 및 Edit2를 Form1에 배치합니다. TreeView1의 PopupMenu 속성은 PopupMenu1로 설정되고, Table1의 DataBaseName 속성은 c: esttree로 설정되고, TableName 속성은 tree.dbf로 설정되며, IndexFieldNames 속성은 LongID로 설정됩니다. PopupMenu1에 단일 항목 Add1 및 Del1을 추가합니다. Caption은 각각 Add와 Del입니다. Edit1은 새 노드의 Text 속성 값을 입력하기 위해 Edit2를 사용하여 새 노드의 3자리 ID 번호를 입력합니다. c:esttree reeunit.pas 및 c:esttree esttree.dPR로 저장합니다. treeunit.pas에서 Type 키워드 뒤에 줄을 추가합니다. Pstr:^string;{Pstr은 문자열 포인터입니다.} Form1의 OnCreate 이벤트에 대한 코드를 추가합니다.
절차 TForm1.FormCreate(Sender: TObject);
var p:Pstr;노드:TTreeNode;
시작하다
Table1,Treeview1을 사용하면
시작하다
열려 있는;
첫 번째;
new(p);{포인터 p에 대한 메모리 할당}
p^:=FieldByName('LongID').AsString;
노드:=Items.AddChildObject(nil,FieldByName
('텍스트').AsString,p);
HasSubInDbf(Node)이면 항목
.AddChildObject(Node,′ ′,nil);{자식 노드가 있는 경우 빈 하위 노드를 추가}
끝;
끝;
---- HasSubInDbf는 사용자 정의 함수이고 독립 변수는 Node입니다. 노드 Node에 자식 노드가 있는지 확인하고 있으면 True를 반환하고, 그렇지 않으면 False를 반환하고 TForm1의 클래스 정의에 프로토타입 선언을 추가합니다( 다른 사용자 정의 함수도 추가 설명 없이 TForm1의 클래스 정의에 선언되어 있습니다. 함수 코드는 다음과 같습니다.
함수 TForm1.HasSubInDbf(Node:TTreeNode):Boolean;
시작하다
Table1을 사용하면
시작하다
Table1.FindNearest([copy(Pstr(Node.Data)^,4,3)+'000']);
결과:=복사(FieldByName('LongID').
AsString,1,3)=copy(Pstr(Node.Data)^,4,3);
{예를 들어, 데이터베이스에 있는 현재 레코드의 LongID 필드 내용 중 처음 3자리의 합
노드 Node의 데이터 마지막 세 자리가 동일하면 해당 노드에는 하위 노드가 있어야 합니다.}
끝;
끝;
TreeView1 컨트롤의 OnDeletion 이벤트에 대한 코드를 추가합니다.
OnDeletion 이벤트는 Delete 메서드를 호출하여 트리거될 수 있을 뿐만 아니라 트리 컨트롤 자체가 해제되기 전에도 발생합니다.
OnDeletion 이벤트도 트리거되므로 여기에 dispose(node.data)를 추가하는 것이 "안전"합니다.
절차 TForm1.TreeView1Deletion
(발신자: TObject; 노드: TTreeNode);
시작하다
Dispose(Node.Data);{노드 데이터 메모리 해제}
끝;
Add1 메뉴 항목의 OnClick 이벤트에 다음 코드를 추가합니다.
절차 TForm1.Add1Click(Sender: TObject);
var p:pstr;Tmpstr:string;i:integer;
시작하다
노력하다
StrToInt(Edit2.Text);
Tmpstr:=Edit2.Text;{참고: 실제로 ID를 생성하려면 더 나은 방법을 사용해야 합니다.}
제외하고;
ShowMessage('Edit2의 내용을 다시 입력하세요');
중단;
끝;
TreeView1을 사용하면
시작하다
새로운(p);
p^:=copy(Pstr(Selected.Data)^,4,3)+TmpStr;
Items.AddChildObject(Selected,Edit1.Text,p);
끝;
Table1 do{데이터베이스에 레코드 추가}
시작하다
추가;
FieldByName(′Text′).AsString:=Edit1.text;
FieldByName('LongID').AsString:=p^;
우편;
끝;
TmpStr:=inttostr(strtoint(TmpStr)+1);
for i:=length(TmpStr) to 2 do TmpStr:=′0′+TmpStr;
Edit2.Text:=TmpStr;
끝;
Del1 메뉴 항목의 OnClick 이벤트에 다음 코드를 추가합니다.
절차 TForm1.Del1Click(Sender: TObject);
var DelList:TStringList;LongID,NSubLongID:string;
시작하다
DelList:=TStringList.create;
DelList.Sorted:=True;
DelList.Add(Pstr(TreeView1.Selected.Data)^);
DelList.Count>0 하는 동안
시작하다
LongID:=DelList.Strings[0];
델리스트.삭제(0);
Table1.SetKey;
Table1.FieldByName('LongID').AsString:=LongID;
Table1.GotoKey이면 Table1.Delete이고;
if HasSubInDbf(TreeView1.Selected) 다음
시작하다
NSubLongID:=Table1.FieldByName('LongID').AsString;
동안(복사(NSubLongID,1,3)=복사
(LongID,4,3))and(Table1.Eof 아님) do
시작하다
dellist.Add(NSubLongId);
표1.다음;
NSubLongId:=Table1.FieldByName('LongID').AsString;
끝;
끝;
끝;
델리스트.프리;
TreeView1.Items.Delete(TreeView1.Selected);
끝;
TreeView1의 OnExpanding 이벤트에 대한 코드를 추가합니다.
절차 TForm1.TreeView1Expanding
(보내는 사람: TObject; 노드: TTreeNode;
var AllowExpansion: 부울);
var TmpNode:TTreeNode;NSubLongID:
문자열;p:Pstr;bm:TBookMark;
시작하다
Table1,TreeView1을 사용하면
시작하다
Items.BeginUpdate;
키 설정;
FieldByName('LongID').AsString:=Pstr(Node.Data)^;
GotoKey가 아닌 경우 Items.Delete(Node)
또 다른
시작하다
TmpNode:=Node.GetFirstChild;
if (TmpNode.Text=′ ′)and(TmpNode.Data=nil) then
시작하다
TmpNode.삭제;
HasSubInDbf(노드)이면
시작하다
NSubLongID:=FieldByName('LongID').AsString;
while (복사(NSubLongID,1,3)=복사(Pstr
(Node.Data)^,4,3))and(Eof 아님) do
시작하다
새로운(p);
p^:=FieldByName('LongID').AsString;
bm:=GetBookMark;
TmpNode:=Items.AddChildObject(노드,
FieldByName('Text').AsString,p);
HasSubInDbf(TmpNode)이면 항목입니다.
AddChildObject(TmpNode,′ ′,nil);
고토북마크(bm);
FreeBookMark(bm);
다음;
NSubLongId:=FieldByName('LongID').AsString;
끝; 끝;
끝;
항목.EndUpdate;
끝;
끝;
---- 위는 데이터베이스의 트리 표시의 기본 방법에 대해 간략하게 설명합니다. 또한, 트리에서 노드의 Text 속성을 편집할 때 동일한 데이터베이스를 운영할 때 데이터베이스도 동시에 수정됩니다. 동시에 여러 사용자가 데이터베이스와 트리의 일관성, 트리 상위 노드의 복사 및 복제에 대해서는 자세히 설명하지 않으며 독자가 스스로 개선할 수 있습니다.
---- 2. IP 제어 사용
---- 네트워크 프로그램에서 사용자가 IP 주소를 입력해야 하는 상황이 자주 발생합니다. 그러나 Delphi는 IP 문자열을 입력하는 데 사용할 수 있는 컨트롤을 제공하지 않으므로 사용자가 입력한 IP 문자열을 수락하려면 Tedit 컨트롤(한 줄 텍스트 상자)을 사용해야 합니다. 그러나 Tedit를 사용하여 IP 문자열을 입력하는 것은 처리가 매우 불편하므로 좋은 생각이 아닙니다. 실제로 IP 문자열을 입력하기 위한 Windows 컨트롤이 우리 옆에 있습니다. IP 컨트롤은 불법 IP 문자열을 거부합니다(각 부분에 0~255 사이의 숫자만 입력할 수 있음). 이를 통해 컨트롤의 IP 문자열에 해당하는 IP 값(32비트 정수)을 쉽게 얻을 수 있습니다. IP 문자열과 IP 값을 변환하는 수고를 덜고 IP 제어에 입력할 수 있는 IP 범위를 제한할 수도 있습니다. 이 섹션에서는 Delphi 프로그램에서 Windows IP 컨트롤을 사용하는 방법을 소개합니다.
---- Windows에는 Windows의 사용자 정의 컨트롤 라이브러리(Windows Common Controls)인 commctrl.dll과 comctl32.dll이라는 두 가지 매우 중요한 동적 링크 라이브러리가 있습니다. 사용자 정의 컨트롤 라이브러리에는 Delphi에서 Statusbar, Coolbar, HotKey 등과 같이 일반적으로 사용되는 많은 Windows 컨트롤이 포함되어 있으며 이러한 컨트롤의 대부분은 시각적 컨트롤로 패키지되어 있습니다. Microsoft가 Internet Explorer 3을 출시한 후 Windows IP 컨트롤(IP 주소 편집 컨트롤)을 포함하여 몇 가지 새로운 컨트롤이 사용자 지정 컨트롤 라이브러리에 추가되었습니다.
---- 1. Windows 사용자 정의 컨트롤 라이브러리 초기화
---- Windows는 사용자 정의 컨트롤 라이브러리를 초기화하기 위해 InitCommonControls 및 InitCommonControlsEx라는 두 가지 API 함수를 제공합니다. 이름에서 이 두 API 함수 간의 관계를 확인하는 것은 어렵지 않습니다. 후자는 전자의 향상된 기능입니다. 프로그램에서 IP 컨트롤을 사용하려면 InitCommonControlsEx를 사용하여 사용자 지정 컨트롤 라이브러리 및 클래스의 초기화를 완료해야 합니다. InitCommonControlsEx 함수의 프로토타입은 다음과 같습니다(파스칼 구문):
... ...
IP 제어 생성
... ...
IP 제어를 사용합니다. 프로그램에서 우리는 메시지를 보내 IP 컨트롤과 통신합니다.
IP 제어는 다음 6개 메시지에 응답할 수 있습니다. 이러한 메시지와 그 의미는 아래 표에 나와 있습니다.
... ...
IP 제어에서 IP 문자열에 해당하는 IP 값을 얻으려면 다음을 보내야 합니다.
IPM_GETADDRESS 메시지이며 다음과 같이 32비트 정수 주소가 필요합니다.
SendMessage의 마지막 매개변수입니다.
... ...
---- 2. IP 제어 알림 메시지
---- IP 문자열이 변경되거나 입력 포커스가 전송되면 IP 컨트롤은 IPN_FIELDCHANGED 알림 메시지를 상위 창으로 보냅니다. 대부분의 경우 이 알림 메시지를 무시할 수 있습니다. 다음은 IPN_FIELDCHANGED 알림 메시지를 처리하는 예입니다.
절차 Tform1.WndProc(var Msg: TMessage);
var p:PNMHDR;
시작하다
상속됨;
Msg.Msg=WM_NOTIFY인 경우
그럼 시작해
p:=포인터(Msg.lParam);
p^.code=IPN_FIELDCHANGED인 경우
그럼 시작해
{...
IP 제어의 IPN_FIELDCHANGED 알림 메시지 처리
...}
끝;
끝;
끝;
---- 3. 동적으로 생성되는 컨트롤의 방법 및 응용
---- 1.Delphi에서 컨트롤을 생성하는 두 가지 방법
---- (1) 양식 디자인에서 컨트롤을 생성합니다.
---- 폼을 디자인할 때 컨트롤 도구 상자에서 필요한 컨트롤을 직접 선택한 다음 해당 속성을 설정하고 이벤트에 응답하는 것이 일반적입니다.
---- (2) 프로그램에서 컨트롤을 동적으로 생성합니다.
---- 때로는 프로그램이 실행될 때 컨트롤을 동적으로 생성해야 합니다. 이는 두 가지 주요 이점이 있습니다. 첫째, 생성된 컨트롤의 수가 중간 실행 결과와 관련된 경우 프로그램의 유연성을 높일 수 있습니다. 프로그램의 방법 1은 당연히 실현될 수 없으며, 프로그램 내에서 동적 생성 방법을 사용해야 합니다.
---- 프로그램에서 컨트롤을 동적으로 생성하는 방법은 먼저 생성된 컨트롤의 종류를 정의한 다음 Create 함수를 사용하여 컨트롤을 생성하고 마지막으로 해당 속성에 값을 할당하는 세 단계로 나누어집니다. 제어. TButton 컨트롤을 예로 들면 단계는 다음과 같습니다.
---- a. 제어 유형을 정의합니다.
var
버튼1:T버튼;
---- b. 컨트롤 생성
Button1:=TButton.Create(self);
Button1.Parent:=자체;
//일반적으로 상위 컨트롤을 Self로 설정합니다. Parent 값이 설정되지 않은 경우
그러면 컨트롤이 화면에 표시되지 않습니다
//표시
---- c. 기타 속성을 설정하고 Caption, Left, Top, Height, Width, Visible, Enabled, Hint 및 onClick 이벤트 응답 기능 등과 같은 관련 이벤트 응답 기능을 정의합니다.
---- 2. 동적으로 생성된 제어방식 적용
---- 생산 일정 및 관리 시스템 개발에 있어서 간트 차트로 표현되는 생산 일정 차트를 동적으로 생성하는 것이 필요하며, Shape 컨트롤을 사용하여 부품의 처리 상태(처리 시작 시간)를 표시하는 것이 매우 유용합니다. 및 각 프로세스의 종료 시간)에 적합합니다. Chart 컨트롤을 사용하면 처리 장비 활용도가 3차원 히스토그램으로 표시되므로 매우 직관적입니다. 이제 프로그램에서 Shape 컨트롤과 Chart 컨트롤을 동적으로 생성하는 과정을 설명하겠습니다.
---- (1) 동적으로 Shape 컨트롤을 생성하여 생산 일정 계획 차트(Gantt 차트)를 표시합니다.
프로시저 TCreateMultiCharts.ProcCreateCharts;
var
i,j,행,열,RowSpace,ChartsHeight:Integer;
ShapeChart:TShape 배열의 배열;
시작하다
Rows:=16; //Shape 컨트롤 배열의 행 수
Columns:=8; //형상 제어 배열 열 번호
RowSpace:=20; // 모양 제어 행 간격
ChartsHeight:=20; // 모양 제어 높이
SetLength(ShapeChart,행,열);
//ShapeChart 배열 크기 설정
for i:=0 ~ 행 수행
j:=0에서 열까지 수행
시작하다
ShapeChart[i][j]:=TShape.Create(self);
ShapeChart[i,j] 사용
시작하다
Parent:=Self; //이 줄은 필수입니다.
그렇지 않으면 Shape 컨트롤이 화면에 표시되지 않습니다.
Shape:=stRectangle; // 모양 제어 모양은 직사각형입니다.
상단:=45+i*(RowSpace+ChartsHeight);
왼쪽:=Round(180+Q[i,j].StartTime);
//Q[i,j].StartTime은 실수이므로 반올림해야 합니다.
너비:=원형(Q[i,j].값)
높이:=차트 높이;
Brush.Color:=RandomColor;
//커스텀 함수, 지침 첨부
Brush.Style:=bsSolid; //채우기 방법 설정
활성화됨:=참;
끝;
끝;
끝;
---- 참고: aQ는 레코드형 2차원 배열로 다음과 같이 정의됩니다.
유형
임시데이터=기록
값:실제;
시작시간:실제;
끝;
Q: TempData 배열의 배열
그리고 Q의 구성 요소에는 다른 프로세스에서 값이 할당되었습니다.
---- b. 다른 부분을 구별하기 위해 Shape가 다른 색상으로 표시됩니다. 이때 RandomColor 함수가 호출됩니다. 기능은 다음과 같습니다:
함수 TCreateMultiCharts.RandomColor;
var
빨간색, 녹색, 파란색:바이트;
시작하다
빨간색:=random(255);
녹색:=random(255);
파란색:=무작위(255);
결과:=빨간색 또는 (녹색 shl 8) 또는 (파란색 shl 16);
끝;
---- (2) 장치 사용률을 표시하기 위해 Charts 컨트롤의 ChartSeries 구성 요소를 동적으로 생성합니다.
절차 TFormMultiMachinesBurthen.
ShowMachineBurthenCharts;
var
i:정수;
부담:진짜;
시리즈클래스:TChartSeriesClass;
NewSeries:TChartSeries 배열;
시작하다
SetLength(NewSeries,CreateMultiCharts.Rows);
MachinesBurthenCharts.height:=200;
MachinesBurthenCharts.Width:=550;
i:=0에서 CreateMultiCharts.Rows로 수행
시작하다
SeriesClass:=TBarSeries; //모양을 3차원 막대 차트로 설정합니다.
NewSeries[i]:=SeriesClass.Create(Self);
NewSeries[i].ParentChart:=MachinesBurthenCharts;
New시리즈[i].Clear;
Burthen:=MachineBurthen[i];
Burthen:=Round(Burthen*100)/100; //소수점 이하 두 자리만 취함
NewSeries[i].add(Burthen,',NewSeries[i].SeriesColor);
끝;
끝;
---- 참고: (a).MachineBurthen[i]는 실제 배열이며 해당 값은 다른 함수에서 계산된 해당 장치의 활용도입니다.
---- (b) MachinesBurthenCharts는 유형 섹션에 설명된 TChart 컨트롤입니다.
---- 3. 프로그램 실행 결과 표시
---- (1) 부품 일정 계획을 표시하기 위한 Shape 컨트롤을 동적으로 생성합니다(생략).
---- (2) Chart 컨트롤의 ChartSeries 구성 요소를 동적으로 생성하고 장치 사용률을 표시합니다(생략).