Delphi -- 기술 탐색:
{1번}
모달 형식을 만드는 문장:
클래스 PROcedure TMyForm.RunForm(AObj1, AObj2: TObject);
var
vForm: TMyForm;
시작하다
vForm := TMyForm.Create(응용프로그램);
vForm을 사용하면
노력하다
InitForm(AObj1, AObj2);
쇼모달;
마지막으로
무료;
끝;
끝;
//*설명:
클래스를 통해 선언된 함수는 VC의 정적 함수와 유사합니다. TMyForm.RunForm(vObj1, vObj2);
기타 구체적인 정보는 Delphi 도움말의 클래스 설명을 참조하십시오.
이 관용어를 강조하는 목적은 다음과 같습니다.
1. 이 양식이 여러 곳에서 사용되는 경우 이 코드가 균일하게 호출되는지 확인할 수 있습니다.
2. 함수가 수정되는 경우(예: ShowModal의 반환 값을 기반으로 처리하는 경우) 이 함수만 수정합니다.
3. 프로그램의 캡슐화 상태가 양호하며 유지관리 및 작업 인계가 쉽습니다. *//
{2번}//태그의 용도
양식 도구 모음 버튼 이벤트에 대한 응답
절차 TMyForm.RunOperate(ATag: Integer);
시작하다
케이스 A태그
1: MyButton.Color := clRed;
2: MyButton.Color := clGreen;
3: MyButton.Color := clBlack;
끝;
끝;
절차 TMyForm.ToolBtnClick(Sender: TObject);
시작하다
RunOperate(TControl(Sender).Tag);
끝;
드롭다운 메뉴에 있고 유사한 기능을 수행해야 하는 경우,
절차 TMyForm.MenuItemClick(Sender: TObject);
시작하다
RunOperate(TMenuItem(Sender).Tag);
끝;
//*설명:
1. 명확한 구조
2. 관련정보가 집중되어 있어 확인, 수정, 유지관리가 용이합니다.
3. 프로그램의 적응성과 확장성을 향상시킵니다. 예를 들어 요구 사항이 도구 모음 버튼에 구현되지 않고 다른 버튼에 구현되면 쉽게 수정할 수 있습니다.
제안: 각 범주 뒤에는 한 줄 또는 몇 줄의 코드만 나옵니다. 코드가 많으면 대신 프로세스 함수를 사용하세요.
더 흥미로운 점은 제가 종종 다음과 같이 쓴다는 것입니다.
케이스 btnMyButton.Visible of
{표시} 사실: ...
{표시하지 않음} 거짓: ...
끝; *//
{ 3번 }//이벤트 포인터를 매개변수로 사용
//목록 읽기 등을 위해 이벤트 포인터를 사용합니다.
유형
TDataSetEvent = Object의 프로시저(DataSet: TDataSet; AIndex, ACount: Integer);
//TADOQuery에서 파생된 클래스
절차 TMyADOQuery.EnumRecord(AWhereStr: String; APro: TDataSetEvent);
시작하다
닫다;
SQL.지우기;
SQL.Add('Table1에서 * 선택');
AWhereStr <> ''이면
SQL.Add('Where' + AWhereStr);
열려 있는;
하지 않는 동안
시작하다
if Assigned(APro) then APro(Self, RecNo, RecordCount);
다음;
끝;
닫다;
끝;
//*설명:
이 메서드는 현재 모든 하위 창인 EnumChildWindow를 열거하는 Window의 API 함수에서 제공됩니다.
1. 원리: 데이터 읽기와 데이터 표시, 데이터 처리 등을 분리해 보십시오. MVC 등은 모두 이 목적을 위한 것입니다.
2. 프로그램의 확장성이 향상되었습니다. 원래 특정 열의 정보를 목록으로 표시하거나 처리하려고 했으나 나중에 ComboBox를 사용하도록 변경한 경우 프로그램 수정 시 데이터 읽기 부분을 읽을 필요가 없습니다. , 정보 표시 등만 수정하면 됩니다. 또 다른 예로, 이제 레코드를 읽을 때 읽기 진행률을 표시하기 위해 진행률 표시줄을 사용해야 합니다.
*//
{ 4번 } //상수 배열
{No.2에서는 다음 내용을 구현합니다.
절차 TMyForm.RunOperate(ATag: Integer);
시작하다
케이스 A태그
1: MyButton.Color := clRed;
2: MyButton.Color := clGreen;
3: MyButton.Color := clBlack;
끝;
끝;
}
//그렇다면 배열을 이용하여 구현하는 것이 이상적일 것입니다.
절차 TMyForm.RunOperate(ATag: Integer);
const
MyButtonColorMax := 3;
MyButtonColor: TColor = (clRed, clGreen, clBlack)의 배열 [1..MyButtonColorMax];
시작하다
케이스 A태그
1..MyButtonColorMax: MyButton.Color := MyButtonColor[ATag];
101:....
끝;
끝;
//*설명:
배열 모드에서 사용하려면 배열의 상한 또는 하한이 상수를 사용하여 구현된다는 점에 유의하세요. 그런 다음 나중에 사용할 때 배열 루프 읽기에 이 상수를 사용해 보십시오.
*//
{No. 5}메시지 메커니즘은 클래스 공개 기능을 줄입니다.
//양식에서 공용 함수의 정의를 최소화하는 방법;
{예: 현재 양식 컨트롤의 속성 목록 양식을 구현하려는 경우 특정 속성의 값을 새로 고쳐야 할 때 새 속성을 추가해야 합니다. 상호작용이 필요한 것입니다. 클래스 공개 함수를 사용하려면 많은 공개 함수를 정의해야 합니다. 동시에, 폼 타입 변환이 필요한 경우에는 대상 폼 타입으로 변환한 후에만 공용 함수를 사용할 수 있습니다. 따라서 두 단위가 서로를 포함해야 하는 상황이 발생합니다.}
//해결책:
TfrmMyForm = 클래스(TForm)
Ffrm속성: TForm;
끝;
...
FfrmProperty := TfrmProperty.MyCreate(응용 프로그램, 자체);
...
//속성창을 새로고침해야 하는 경우
FfrmProperty.Perform(WD_REFRESHPROPERTYLIST, 0, 0);
TfrmProperty = 클래스(TForm)
사적인
FMyForm: TForm;
절차 WDREFRESHPROPERTYLIST(var 메시지: TMessage); 메시지 WD_REFRESHPROPERTYLIST;
공공의
생성자 MyCreate(소유자: TComponent; AForm: TForm);
끝;
생성자 TfrmProperty.MyCreate(소유자: TComponent; AForm: TForm);
시작하다
상속받은 생성(소유자);
FMyForm := AForm;
끝;
//* 메시지를 사용하는 방식에 있어서, 폼의 공용 함수 정의가 줄어들 수 있습니다. 동시에 프로그램의 확장성을 향상시킵니다. 대신 그의 양식을 사용하면 쉽게 변환할 수 있습니다. 왜냐하면 기껏해야 양식이고 현재 메시지를 처리하지 않기 때문입니다*)//
{6번}등록 목록을 사용하여 가능한 확장 모듈을 관리합니다.
//프로젝트: 데이터 세트에 대해 여러 출력 표시 방법을 지원해야 합니다.
...예제는 나중에 설명하겠습니다.
//* 설명:
1. "다중 출력 방법"은 출력 방법이 향후 응용 프로그램에서 자주 확장될 수 있으므로 프로그램 설계 시 출력 방법의 쉬운 확장성을 고려해야 함을 의미합니다.
2. VCL의 컨트롤 등록(RegisterComponents) 메커니즘을 참조하면 VCL에서 많은 수의 등록 메커니즘이 사용된다는 것을 알 수 있습니다. 더 고전적인 것은 컨트롤 속성 편집기의 등록입니다.
*//
{No.7}사전 정의된 제어 프로그램 버전 사용
//보조 개발 플랫폼 프로그램을 수행하는 경우 제품 버전 관리 및 프로젝트 버전 관리 문제가 포함되어야 합니다.
//보통 미리 정의된 메소드를 사용하여 제어됩니다.
//문은 비교적 간단합니다.
{$DEFINE JOYYUAN97}
{$IFDEF JOYYUAN97} {ELSE} {ENDIF}
{$UNDEF JOYYUAN97}
*설명:
1. 사전 정의를 여러 개의 개별 파일로 나눕니다.
2. 각 단원의 시작 부분에서 단원 뒤에 {$I ...}를 사용하여 파일을 현재 단원에 포함시킵니다.
3. 미리 정의된 조건에 따라 현재 유닛이 포함할 수 있는 유닛 파일을 제어합니다.
4. 프로젝트에 대해 사전 정의된 파일을 분리해 보세요. 사전 정의된 파일을 모두 포함시킨 후 이 파일에 프로젝트의 필요에 따라 일부 사전 정의된 파일이 취소될 수 있습니다.
*//
{8번}함수 포인터를 사용하여 단위 프로젝트 포함을 줄입니다.
//공용 유닛을 만드는 첫 번째 단계는 유닛 포함을 줄이는 것이라고 생각하는 경우가 많은데, 유닛 포함을 최대한 줄이는 방법은 무엇입니까?
//즉, 프로그램 단위의 결합을 줄이는 방법에 대한 더 많은 노력이 필요합니다.
{시나리오 설명:
TMyFormManager: 양식 관리 클래스
TMyForm: 데이터 양식 기본 클래스
TMyFormaccess: 폼 정보 저장 및 읽기 수업입니다. 양식 정보를 데이터베이스나 다른 유형의 구조에 저장합니다.
분석하다:
1. 폼 기본 클래스(TMyForm)와 폼 관리 클래스(TMyFormManager)는 uManager 단위로 구현되어야 합니다.
2. 양식 특정 구현 클래스(TMyImageForm) 유닛 fMyImange에는 양식 상속 및 양식 관리를 위한 유닛 uManager가 포함되어야 합니다.
3. 양식 데이터 읽기 클래스(TMyFormAccess) 유닛 uMyAccess에는 uManagers 유닛과 fMyImange 유닛이 포함되어야 합니다.
질문:
양식을 저장하려면 양식의 버튼 이벤트에서 저장해야 합니다. 폼 유닛의 경우 폼 데이터 액세스 클래스 유닛을 포함해야 하며, 폼 기본 클래스에 배치되는 경우 uManager 유닛에는 uMyAccess 유닛이 포함되어야 합니다.
셀 포함은 데이터 액세스(예: 데이터 저장 형식)가 요구 사항에 따라 변경되고 확장성이 필요할 때 위험합니다.
해결책: 함수 포인터 변수를 사용하십시오.
1. uManagers 유닛에 데이터 정보를 저장할 함수 포인터 변수를 정의합니다.
2. 응용 프로그램이 초기화될 때 이 함수 포인터 변수에 값을 할당합니다.
3. 폼 정보를 저장해야 하는 경우 포인터가 비어 있지 않은지 확인한 후 폼 정보를 저장하는 기능을 실행합니다.
{No. 9}상수, 상수를 이해하고 상수를 사용하세요
상수 정의의 중요성을 소개하는 책들이 많아서 종종 생각하는데, VCL 소스 코드를 보면 다른 사람들이 상수를 사용하는 것을 무시했다는 것을 깨닫게 됩니다.
1. 우리가 자주 사용하는 메시지의 정의는 상수를 선언한 후 적절한 시점에 사용하는 것입니다.
일반적으로 정의되고 사용됩니다:
const
WD_MyMessage = WM_User + 101;
유형
TMyForm = 클래스(TForm)
...
절차 WDMyMessage(var 메시지: TMessage); 메시지 WD_MyMessage {응답 메시지 위치}
끝;
그러나 {응답 메시지 위치} 문을 다음과 같이 다시 작성하면:
절차 WDMyMessage(var 메시지: TMessage); 메시지 WM_User + 101;
마찬가지로 컴파일이 성공하고 정상적으로 사용됩니다. 따라서 상수 정의는 윈도우 시스템 처리 및 인터페이스에서 매우 일반적으로 사용됩니다.
2. 델파이에서는 색상 변수 clRed, clGreen 등을 정의했는데, 이는 향후 사용을 용이하게 하기 위해 상수로도 정의되었습니다. 이를 통해 상수의 정의는 프로젝트에서 부분적으로 재사용 가능해야 한다는 점을 알게 되었습니다. 따라서 정의된 상수를 각 프로젝트에서 재사용할 수 있도록 표준 상수 단위를 정의할 수 있습니다.
{No. 10}Delphi에서 일반적으로 사용되는 배열입니다.
Delphi에는 TIdentMapEntryd 유형의 배열 정의 및 사용을 위한 비교적 완전한 구현이 있습니다.
TIdentMapEntry = 기록
값: 정수;
이름: 문자열;
끝;
1. 배열 정의: TIdentMapEntry의 array[0..ArrMax]
참조하십시오: 제어 장치:
커서: TIdentMapEntry의 배열[0..21] = (
...
);
2. 서로를 평가하는 두 가지 함수: IntToIdent(값에서 이름 찾기) 및 IdentToInt(이름에서 값 찾기)
특정 애플리케이션의 경우 IdentToCursor 및 CursorToIdent를 참조하세요.
3. 적용: a. 이 트리 그룹 정의 방법과 배열 조작 기능을 직접 적용합니다. b. 함수에서 배열에 액세스하고 조작하는 방법을 알아봅니다. c. 표준 정보 액세스 함수 정의를 알아봅니다. function IntToIdent(Int: Longint; var Ident: string; const Map: array of TIdentMapEntry): Boolean; 반환된 특정 정보는 액세스가 유효한지 여부에 따라 반환됩니다. 함수를 통해 전달됩니다. Boolean 반환 값이 판단됩니다.
{No. 11}특별한 사례부터 일반적인 발견까지
커서의 정의와 작동 기능을 추적하면서 다음과 같은 사실을 발견했습니다.
1. {10}에서 소개한 바와 같이 커서의 정의와 일반적인 동작을 일반화한다.
2. Int와 Ident 간의 변환 기능을 제공합니다.
3. 배열 목록 정보를 주기적으로 읽어오는 기능을 제공합니다: GetCursorValues; 그 중 {3번}에서 소개한 "이벤트 포인터" 메소드를 사용하여 목록 정보를 읽어옵니다.
{No. 6}에 대한 보충:
예:
프로시저 RegisterComponents(const 페이지: 문자열;
ComponentClasses: TComponentClass의 배열);
시작하다
할당된 경우(RegisterComponentsProc)
RegisterComponentsProc(페이지, ComponentClasses)
또 다른
EComponentError.CreateRes(@SRegisterError)를 발생시킵니다.
끝;
해석:
1. 등록방법을 이용하여 사용할 수 있는 컨트롤 종류 등을 기록합니다.
3. RegisterComponentsProc의 경우 향후 프로그램 확장, 버전 업그레이드 등을 용이하게 하기 위해 {8번}의 "함수 포인터를 사용하여 단위 프로젝트 포함을 줄이는 방법"을 사용합니다.
{No. 11}공용함수는 하나만 정의하세요.
//프로젝트 설명: 이제 우수한 확장성과 쉬운 유지 관리가 필요한 CAD 드로잉 또는 Visio 시스템을 구현해야 합니다.
//그리고 시스템의 일부나 확장된 시스템을 패키징하여 향후 프로젝트에 직접 사용할 수 있도록 낮은 결합도가 필요합니다.
설계:
1. 그래픽 객체 추상 클래스를 디자인합니다. 이 클래스에서는 추상 함수 CadPerform을 정의합니다. 함수의 매개변수는 함수 TControl.Perform(Msg: Cardinal; WParam: Longint): Longint를 참조합니다.
2. 그래픽 관리 클래스에서 그래픽 객체 목록의 관리를 구현합니다. 목록에 저장되는 것은 추상 객체의 포인터입니다.
3. 특정 클래스 개체를 제어하려면 CanPerform 함수만 사용한 다음 현재 작업의 범주에 따라 Msg를 전달하고 해당 매개변수 정보를 전달하면 됩니다.
구현: TCad는 추상 클래스에서 상속된 첫 번째 수준 제어 클래스입니다.
함수 TCad.CadPerform(Msg: Cardinal; WParam, LParam: Longint): Longint;
시작하다
사례 메시지
My_Message1: 결과 := MyMessage1(WParam, LParam);
My_Message2: 결과 := MyMessage2(WParam, LParam);
끝;
끝;
TPoint가 TCad를 상속받은 경우 CadPerform 기능은 다음과 같이 구현됩니다.
함수 TPoint.CadPerform(Msg: Cardinal; WParam, LParam: Longint): Longint;
시작하다
사례 메시지
My_Message1: Result := MyMessage1(WParam, LParam); //TCad에서 이 작업 유형의 처리가 차단됩니다.
My_Message3: 결과 := MyMessage3(WParam, LParam);
else 결과 := 상속됨 CadPerform(Msg, WParam, LParam);
끝;
끝;
*설명:
우리는 그래픽 개체를 매우 자주 작동하기 때문에 클래스의 높은 캡슐화와 프로그램의 쉬운 유지 관리 및 확장을 달성하기 위해 공개 및 개방형 인터페이스 기능을 정의합니다.
*//
{12호}
다음은 내 프로그래밍 요구 사항입니다. (일부 정보에는 언어 제한이 없습니다.)
//다음 솔루션은 거의 모두 위의 방법에서 찾을 수 있습니다.
1. 프로그램의 복잡성을 줄입니다. a. 함수 수를 줄이고, Case 및 Tag 메서드를 사용하고, Perform을 정의하는 방법을 알아봅니다. b. 단위 중첩 관계를 줄이고, 메시지 전달 방법을 사용하고, 양식 단위의 상호 포함을 줄입니다.
2. 감소
{No. 13} 브로드캐스팅을 사용하여 관리 클래스에서 관리 목록 개체로 알림을 구현합니다.
//{No. 12} 프로젝트 설명의 경우, 도면 양식 제어의 속성이나 상태가 변경되면 모든 그래픽 객체에 알리고 그에 따라 변경해야 하는 경우가 많습니다.
//하나의 브로드캐스트 기능만 정의하면 부모-자식 알림이 실현될 수 있으며, 이는 프로그램의 재사용성, 확장성, 유지 관리 용이성 등도 향상되고 클래스 구조를 명확하게 합니다.
//예: 1. Visio 및 MapInfo에서 현재 양식의 배율(확대/축소 비율)이 변경되면 현재 표시된 모든 그래픽 개체를 새 배율로 다시 그려야 합니다. 2. 현재 양식의 기본 양식 글꼴이 변경되면 기본적으로 양식 글꼴을 사용하여 텍스트 정보를 표시하는 그래픽 개체의 텍스트 글꼴도 그에 따라 변경되어야 합니다.
//해결책, 속성이나 상태가 변경될 때 모든 하위 컨트롤에 알리는 TWinControl의 처리 메커니즘을 참조하세요.
절차 TWinControl.NotifyControls(Msg: Word);
var
메시지: TMessage;
시작하다
메시지.Msg := 메시지;
메시지.WParam := 0;
메시지.LParam := 0;
메시지.결과 := 0;
Broadcast(Message);//현재 변경 메시지를 브로드캐스트합니다.
끝;
안에:
절차 TWinControl.Broadcast(var Message);
var
I: 정수;
시작하다
for I := 0 ~ ControlCount - 1 do
시작하다
Controls[I].WindowProc(TMessage(Message));
//다음으로 변경: with TMessage(Message) do Cads[I].CadPerform(msg, WParam, LParam);
TMessage(Message).Result <> 0이면 종료합니다.
끝;
끝;
그러나 그래픽 객체를 다룰 때 Cads의 CanPerform 공용 함수를 직접 호출할 수도 있습니다.
{No. 14}필요할 때 동적으로 객체를 생성하세요.
예: http://www.delphibbs.com/keylife/iblog_show.asp?xid=824
//************옵션 2: 필요할 때 속성 양식 만들기
용도
...
f속성;
유형
TfrmMyMap = 클래스
...
절차 OnfrmMyMapDestroy(Sender: TObject);
절차 OnMapGeoSelected(AGeo: TGeometry);
사적인
Ffrm속성: Tfrm속성;
절차 ShowPropertyForm(aVisible: Boolean);
공공의
끝;
절차 TfrmMyMap.ShowPropertyForm(aVisible: Boolean);
시작하다
if Not Assigned(FfrmProperty) then FfrmProperty := TfrmProperty.Create(Application);
FfrmProperty.Visible := aVisible;
끝;
절차 TfrmMyMap.OnfrmMyMapDestroy(Sender: TObject);
시작하다
할당된 경우(FfrmProperty) 그러면 FfrmProperty.Free;
끝;
절차 TfrmMyMap.OnMapGeoSelected(AGeo: TGeometry);
시작하다
if Assigned(FfrmProperty) then FfrmProperty.MyRefresh(AGeo);
끝;
여기에 설명되어 있습니다:
1. 필요할 때 FfrmProperty 객체를 동적으로 생성합니다.
2. 현재 개체가 해제되면 해당 개체의 적법성을 판단한 후 동적으로 생성된 개체를 해제합니다.
{No. 15}인터페이스 생성 또는 구조 생성
//프로젝트 설명: 테이블 컨트롤을 개발할 때 셀을 Com으로 설정하면 테이블에 정보가 너무 많으면 로딩 속도를 보장할 수 없고 크래시가 발생할 가능성도 있습니다. 제가 Com을 사용하는 이유는 앞으로 각 셀의 처리와 정보를 통제 범위 밖으로 확장할 수 있기 위해서입니다.
내 해결책은 다음과 같습니다. Cell에서 파생된 각 컨트롤에 대한 인스턴스를 생성하고 여러 구조 개체를 동적으로 생성하여 각 셀의 정보를 기록합니다. 셀을 작동해야 하는 경우 구조 개체 포인터를 Cell 구성 요소에 할당하면 테스트 결과는 다음과 같습니다. 매우 만족스럽습니다.
따라서 컴의 인스턴스를 많이 사용해야 한다면 하나의 인스턴스를 관리하고 유지하는 것이 그 안의 데이터를 동적으로 생성 및 관리할 수 있어 속도 면에서 좋은 효과를 볼 수 있습니다.
또한 pMyInterface = ^IMyInterface 인터페이스 포인터를 선언해 보세요. 매개변수를 전달하거나 사용할 때 인터페이스 포인터를 직접 사용하세요. 이렇게 하면 _AddInft 등의 계산 함수 호출 횟수를 줄일 수 있고, 다음과 같은 경우 속도도 높일 수 있습니다. 작동은 평범합니다.