Delphi - Tips: {No. 1} Creating a Sentence Mode Form: Class Procedure Tmyform.Runform (AOBJ1, AOBJ2: TOBJECT); Varvform: Tmyform; Beginvform: = TmyForm.create (Application); with Vform Dotry Initform AOBJ1, AOBJ2); ShowModal; Finally Free; End; End; // * Description: Through the function of the Class declaration, similar to the static function in the VC; use statement: TMYFORM.RUNFORM (Vobj1, Vobj2); other specific, reference : Delphi Help, Class Class Description. To emphasize this usual method, it is for: 1. If this form is used in multiple places, it can guarantee that this segment is called; 2. If the function is modified, for example, according to the return value of ShowModal. Then only modify this function. 3, the program is good, easy to maintain and work. * //
{No. 2} // TAG Using Form Toolbar Button Event Response Procedure Tmyform.Runoperate (ATAG: Integer); Begin Case Atag of 1: MyButton.Color: = CLRED; 2: MyButton.color: = CLGreen; 3: MyButton.Color: = CLBLACK; End; End; procedure TMYFORM.TOOLBTNCLICK (Sender: TOBJECT); begin runot (TControl (sender) .tag); end; if you are in a drop-down menu, you also need to perform similar functions. Procedure TMYFORM.MENUITEMCLICK (Sender: Tobject); Begin Runoperate (TMENUITEM (Sender) .tag); end; // * Description: 1, clear structure 2, related information concentration, more easy to find error, modification, and maintenance 3, improve The program adaptation, extension ability Recommendation: After each classification, only one line or not a few lines of code, if the code is more, use the process function replacement. What is interesting is, I often write as follows: Case btnmyButton.visible of {display} true: ... {not display} false: ... End; * //
{No. 3} // Event Pointer Do Parameters // Read Unspending Event Pointer for Lists TYPE TDATASETEVENT = Procedure (Dataset: TDataSet; Aindex, ACount: Integer) of object; // Delicate from TadoQuery Class Procedure TmyadoQuery.enumRecord (AwhereStr: String; Apro: tdatasetEvent); Begin Close; Sql.clear; Sql.add ('SELECT * from Table1'); if AwhereStr <> '' Then SQL.Add ('Where' awherestr ); WHILE NOT EOF Do Begin if Assigned (APRO) THEN APRO (Self, Recno, RecordCount); Next; End; End; End; End; End; // * Description: This method comes from Window, enumeration of all child windows API function, EnumchildWindow1, principle: Try to separate data read from data display, data processing, etc., such as: MVC, etc. 2. Program scalability is enhanced. If you want to display or process a column information in the list, then change to ComboBox, when modifying the program, only the data read portion is read, only the information display is required to be modified. For example, now ask you to use the progress bar when reading the record, and so on. * // {No. 4} // Constant array {in No.2, implemented the following content procedure tmyform.Runoperate (atag: integer); begincase atag of1: mybutton.color: = CLRED; 2: MyButton.color : = CLGreen; 3: MyButton.Color: = CLBLACK; END; END;} // Then the as a group mode is implemented, it is ideal for procedure TMYFORM.RUNOPERATE (Atag: integer); const mybuttoncolormax: = 3; MyButtonColor: Array [1..mybuttoncolormax] of tcolor = (CLRED, CLGREEN, CLBLACK); begincase atag of1..mybuttoncolormax: mybutton.color: = myButtonColor [ATAG]; 101: .... end; end; // * Description: For Array mode, as long as the upper or lower limit of the array is implemented, then use this constant as much as possible in the future, the array cycle read is available. * //
{No. 5} Message Mechanism Reduce Class Public Functions / / How to make a form to minimize the definition of public functions; {To implement a list of property list forms for a current form control, when you need to refresh the properties form; Change a property value; add new attributes, etc .; there will be many information that needs to interact. If we use class public functions, you need to define a lot of public functions. At the same time, if the form type conversion is required, the conversion to the target form type can be used to use public functions. Therefore, it will encounter two units that need to be included in each other} // Solution: tfrmmyform = Class (TFORM) FFRMPROPERTY: TFORM; End; ... ffrmproperty: = tfromproperty.mycreate (Application, Self); ... / when / if needed refresh property of the form FfrmProperty.Perform (WD_REFRESHPROPERTYLIST, 0, 0); TfrmProperty = class (TForm) private FMyForm: TForm; procedure WDREFRESHPROPERTYLIST (var Message: TMessage); message WD_REFRESHPROPERTYLIST; public constructor MyCreate (Owner: TComponent; AFORM: TFORM); End; Constructor TFRMPROPERTY.MYCREATE (Owner: tComponent; AFORM: TFORM); Begin Inherited Create (Owner); FtemYform: = AFORM; END; // * For use of messages, you can reduce formal functions Definition. At the same time, improve the program's expansion. If you use his form to replace, you can easily transform, because if you are, it is your form, it is not processed for the current message. *) // {No. 6} Using registration list management may expand Module // Project: Requires you to support a variety of output display modes for a data set, later gived // * description: 1, "multiple output mode", indicating that the output mode may be in future applications It is often expanded, so it is necessary to take into account the easy expansion of the output mode when designing. 2. Refer to the mechanism of the registerComponents in VCL, you can find a large number of registration mechanisms in the VCL; where the classic is the registration of the control attribute editor. * //
{No. 7} Using a predefined control program // If you do a secondary development platform, you must involve product version control and project control issues / / usually use predefined way to control // statement The relatively simple is: {$ define joyyuan97} {$ undef joyyuan97} {else} {endif} {$ undef joyyuan97} * Description: 1, the predefined division is divided into multiple separate files. 2, at the forehead of each unit, but after Unit, use {$ i ...} to enter the current unit 3, control the unit file 4 that the current unit can include according to the predefined case, as far as possible Divided a predefined file for the project After containing all predefined files, in this file, you can cancel some predefined {$ undef joyyuan97} * /////////////>
{No. 8} Using the function pointer, reduce the unit item containing // I often think that the unit is included, it is the first step of the public unit, so how to minimize the unit containing // how to reduce the coupling of the program unit Sex, there should be more labor. {Scenario: TMYFORMMANAGER: Form management class TMYFORM: Data form basic class TMYFORMACCESS: Form Information Save and Read Class. Save Form Information to Database or Other Types of Structures: 1. The Formwork (TMYFORM) and Form Management (TMYFORMMANAGER) need to be implemented in one unit umanagers. 2, the form specific implementation class FMYIMAGE needs to include unit umanagers, perform form inheritance, and form management. 3, the TMYFORMACCESS unit UmyAccess requires the unit umanagers and unit FMYIMANGE issues: If I want to implement the form, it should be implemented in a button event in the form. Then, the form unit needs to include a form data access class unit, and if in the form base class, the unit UManager must include unit umyaccess. When data access, that is, the data storage grain changes and requires expandable, the unit includes a hidden danger. Workaround: Use the function pointer variable. 1. Define a function pointer variable for saving data information in unit umanagers. 2. Assign this function pointer variable when the application is initialized. 3. When you need to save the form information, it is determined that if the pointer is not empty, the function saves the form information. {No. 9} constant, recognize constants, many books have been introduced to the importance of constant definitions, and I will always think of it, but look at the VCL source code, I know that I ignore it, others' use of constants. 1. The definition of the message we often use is: declare a constant and then use it when appropriate. Usually defined and used: const wd_mymessage = wm_user 101; type tmyform = class (tform) ... Procedure: TMESSAGE; message WD_MYMESSAGE; {Response message location} end; however, if you will {Response message location } The statement is rewritten as: Procedure WDMYMESSAGE (VAR Message: TMESSAGE); Message WM_USER 101; Similarly, compilation can be successful and used is normal. Therefore, constant definitions are very common in Window System Processing and Interfaces. 2. In Delphi, we define color variables, CLRED, CLGREEN, etc., which are also defined constants, which is convenient for future use. Through this observation, I found that the definition of constants should be in the project, which can be partially reused, so a standard constant unit can be defined to reserve the defined constant in a project.
{No. 10} A Delphi, the commonly used array is defined and used in the array of TIDENTMApenTryd types, and Delphi has a relatively complete implementation. TIDENTMAPENTRY = Record Value: integer; name: string; end; 1, array definition: Array [0..arrmax] of TIDENTMAPENTRY Reference: Controls unit: Cursors: array [0..21] of tidentmapenTry = (... ); 2, two mutual compliance functions: INTTOIDENT (seeking NAME by Value) and IDENTTOINT (seeking Value by Name); specific applications can be referred to: IdentTocursor and Cursortoident. 3, application: a, directly apply this tree group definition method and array manipulation function; B, learning function, access and manipulating an array. C. Learning standard information access function definition: function INTTOIDENT (INT: long): Boolean; The specific returned information is returned by the parameter mode, as for accessing whether it is valid, then pass the function Boolean return value is judged. {NO. 11} From special cases to ordinary discovery. I found that the definition and general operation of Cursors are discovered by tracking of Cursors definitions and operational functions: 1, such as {No. 10}. 2. Provide INT and IDENT transformation functions. 3. Provide a function of the array list information: getCursorValues; where the "Event Pointer" reading list information is read using the "Event Pointer to do parameters" in {No. 3}. {No. 6} supplement: Example: procedure RegisterComponents (const Page: string; ComponentClasses: array of TComponentClass); begin if Assigned (RegisterComponentsProc) then RegisterComponentsProc (Page, ComponentClasses) else raise EComponentError.CreateRes (@SRegisterError); end; Interpretation: 1. Use the registration method to record the type of control available. 3. For RegisterComponentsProc, "Use Function Pointer, Reducing Unit Items" in {No. 8}, which is convenient for future programs, and versions.
{No. 11} Only a public function // project description: now you want to implement a CAD drawing or Visio system, require good scalability and easy maintenance; // and require low coupling, easy, future system part Or after the extended system package, you can use the design in future projects: 1. Design a graphic object abstraction class. In this class, define a parameter of the abstract function CADPERFORM, the function of the function refers to Function Tcontrol.Perform (msg: cardinal; WPARAM, LPARAM: longint: longint; 2, in the graphics management class, implement a graphic object list management, the pointer to the abstract object is saved in the list. 3. When manipulating the specific class object, simply use the CANperform function by the strip, then pass the MSG according to the category of the current operation, and passes the corresponding parameter information. Implementation: TCAD is a first layer control class function tcad.cadperform (MSG: cardinal; wparam, lparam: longint): longint; begin case: = mymessage1: result: = my_MESSAGE2 : Result: = MyMessage2 (WPARAM, LPARAM); END; END; For TPOINT inheritance from TCAD, the CADPERFORM function is implemented below. Function TPOINT.CADPERFORM (MSG: cardinal; wparam, lparam: longint): longint; begin case: = mymessage1 (wparam, lparam); // Blocking TCAD in this operation type processing My_MESSAGE3: Result: = MyMessage3 (WPARAM, LPARAM); Else Res: = Inherited CADPERFORM (MSG, WPARAM, LPARAM); END; END; * Description: Because our operations of graphic objects will be very frequent, so we define a public open interface function To achieve, the high encapsulation and programs of the class are easy to maintain, and well expansion and other performance. * // {No. 12} The following is the requirements of my program: (some information is not language restrictions) // below the solution, almost all of the above methods, find 1, reducing the complexity of the program. a, reduce the number of functions, use the Case, TAG mode, learn the Perform definition method; B, reduce the unit nested relationship, use the message delivery mode, reduce the mutual containing of the form unit. 2, reduce
{No. 13} Using broadcast, implement the notification of the management class to the management list object // For {No. 12} item description, when the form control attribute or status of the drawing changes, all graphics objects often need to be notified. Perform a corresponding change. // If only one broadcast function is defined, you can implement the parent and child notification, and it will also improve the reusability, scaifery, easy maintenance, etc. of the program, so that the class structure is clear. // For example: 1, in Visio and MapInfo, if the current form scale (zoom ratio) changes, you need to focus on all current display graphics objects with new proportional ruler. 2. When the current form default form font changes, the graphic objects of the text information are displayed by default, their text fonts should also be changed. // Solution, refer to TWINCONTROL, when the property or status changes, notify all sub-controls processing mechanisms: Procedure TWINCONTROL.NOTIFYCONTROLS (MSG: Word); var message: tMessage; begin message.msg: = msg; message.wparam: = 0; message.lparam: = 0; message.Result: = 0; Broadcast (Message); // broadcast current change message END; where: procedure warontrol.broadcast (var message); var i: integer; begin for i : = 0 to ControlCount - 1 Do Begin Controls [i] .windowProc (TMESSAGE (MSSAG)); // Change to: with tMessage (Message) Do Cads [i] .cadperform (MSG, WPARAM, LPARAM); if Timentage Message) .Result <> 0 THEN EXIT; END; END; However, when we handle graphics objects, you may call the CANPERFORM public function of CADS directly to {No. 14}, dynamically create your object
For example: http://www.delphibbs.com/keylife/iblog_show.asp? Xid = 824 二 二 二 当 属 当 属 u ues ... fproperty; typeetfrmmymap = class ... procedure OnfrmMyMapDestroy (Sender: TObject); procedure OnMapGeoSelected (AGeo: TGeometry); private FfrmProperty: TfrmProperty; procedure ShowPropertyForm (aVisible: Boolean); publicend; procedure TfrmMyMap.ShowPropertyForm (aVisible: Boolean); beginif Not Assigned ( FfrmProperty) then FfrmProperty: = TfrmProperty.Create (Application); FfrmProperty.Visible: = aVisible; end; procedure TfrmMyMap.OnfrmMyMapDestroy (Sender: TObject); beginif Assigned (FfrmProperty) then FfrmProperty.Free; end; procedure TfrmMyMap.OnMapGeoSelected (AGeo : TGeometry; Beginif Assign (FFRMPROPERTY) THEN FFRMPROPERTY.MYREFRESH (AGEO); END; here: 1, when needed, dynamically create your object FFRMPROPERTY2, when the current object is released, determine your object's legality, then release Dynamically created objects. {No. 15} Creating an interface or creating a structure // Item Description: When I develop a table control, if I set the cell to a COM, if the information of the table is too much, the load speed cannot be guaranteed, even There is a possibility of crash. The reason why I use COM is to extends outside the control in the future. My solution is: Create an instance for each control from Cell derived, generate a number of structural object RECORDs to record the information of a cell, if you need to operate the cell, the structural object pointer is assigned to Cell components, test results are very satisfactory. So, if you need to use a COM's large number of instances, try to manage and maintain an instance, and for the data of them, it will have a good effect on the speed of dynamic creation. In addition, try to declare a PMYINTERFACE = ^ IMYIInterFace excuse, parameter delivery or use, directly use the interface pointer, which can reduce the call count function _Addinft, etc. If the operation is intact.
Note: This article is in the pen name: Joyyuan97. (I have a good dish, what can't I do, I hope everyone will share it together, and I am also grateful to the experience and skills brought about it)
The people who wanted to have left the opinion, the author's words: "In addition, it is best to give me a copy of the position. I have a suggestion to someone else. Thank you! Have a good experience!"