Delphi program design - experience skills

zhaozj2021-02-16  48

These days are too busy. Today, the remaining part is complete, I hope to be useful to everyone. I didn't tell the author and the author of this article.

{No. 16} // Analysis of Record Type RECORD. Example: type TBaseRec = record rStr: Integer; rStr2: String; rStr3: String; end; TStrRec = record rStr: Integer; rStr2: String; rStr3: String; rStr4: String; end; procedure TForm1.Button3Click (Sender: TObject) VAR VREC1: TSTRREC; VBASEREC: TBASEREC; begin Vrec1.rstr: = 1; VREC1.RSTR2: = '123123'; VREC1.RSTR3: = '1'; VREC1.RSTR4: = '1'; VBASEREC: = TBASEREC Pointer (@ VREC1) ^); showMessage (INTTOSREC.RSTR) '_' VBaseRec.rstr2 '_' vbaserec.rstr3); // end; {Description: 1, when the record type is transitioning each other, Ensure the basic RECORD type, the data size sizeOf should be less than or equal to the expansion type. Ensure that the data accesses of the converted record type object is legally correct. 2, in Delphi, the most ordinary transition using the record type is the implementation of the message RECORD. Delphi defines a number of records that can be described at the same time while TMessage, such as TWMKEY = Packed Record Msg: cardinal; charcode: word; unused: word; keydata: longint; result: longint; end; if you need to accept keydown and When Keyup's message, we can use TMESSAGE to use TWMKEY as a parameter type for messaging. Because Delphi provides us with a number of convenient message types, we will not be cumbersome and wrong when using the message processing. 3, the use of the record type also provides a way to access data information encapsulation between different languages. When using a record type and record type pointer between different languages, you should pay attention to the type matching problem of the internal defined variable.

Recording type Essential Test Research: Changing the implementation of the above example, test: procedure tform1.button3click (sender: TOBJECT); var Vrec1: TStrRec; RSTR: Integer; RSTR2: String; RSTR3: String; VPT: integer; begin VREC1. RSTR: = 1; VREC1.RSTR2: = '123123'; VREC1.RSTR3: = '1'; VREC1.RSTR4: = '1'; VPT: = Integer (@ VREC1); RSTR: = Integer (Pointer (VPT) ^); VPT: = VPT SIZEOF (RSTR); RSTR2: = String (Pointer (VPT) ^); VPT: = VPT SIZEOF (RSTR2); RSTR3: = String (Poinmessage (INTOSTR) (RSTR) ' RSTR3); END; The prompt information is the same as the start-up example, then speculates: 1, the data defined in the Record type is 2 in a continuous space, when defined functions If the information processed by the function can be considered in subsequent versions, the parameters can be transmitted using the recording variables. When the expansion function simply converts the recording variable according to the version number of this record to be accessed to the corresponding recording type variable. Specific instances can refer to the version upgrade and extension of the Windows API function. } 2003-6-17 19:52:00

2003-6-17 22:22:02

Event type properties, assigning function operations through attribute

{No. 17} {In Typinfo unit, there are several functions that allow us to manipulate the VMT of the class-managed class. Pass, attribute name, object VTM directly access or change the value of the property. Public attribute access function: getPropValue; Public property setting function: setPropValue. Among them, reading of event attribute information can be used with GetPropValue, but cannot assign event attributes via setPropValue. Solution: Use setMethodProp to assign a value to the control. Procedure setMethodProp (Instance: Tobject; const propname: string; const value: tmethod); overload; where TMethod is used to describe the operation function. TMETHOD = Record Code, // Function Address; You can obtain function addresses by class function methodaddress. Among them, only the function declared in the Published section can be accessed through MethodAddress. Data: Pointer; // Object address End;} // *************** Normal use type tmyform = class (tform) ... private fMyText: string; Published Procedure MyClick Sender: TOBJECT); END; // In the form, the button event; the implementation of the event of dynamic allocation of another button, Procedure TMYFORM.BUTTON1ONCLICK (Sender: TOBJECT); var vMethod: TMethod; begin fmytext: = 'Hello Joy!' VMethod.code: = self.methodaddress ('myclick'); // ************ Code 1 vMethod.Data: = Self; // ********** ** code 2 setMethodProp (Button2, 'onclick', vMethod); End; Procedure Tmyform.myClick (Sender: Tobject); Begin ShowMessage ('OK!'); // ************ Show 1 ShowMessage (Self.fmytext); // ************ Show 2 End; // *************** Modify One // [Code 1] and the SELF at [Code 2] is changed to TMYFORM. Then [Show 1] is normal, [Show 2] is displayed abnormal. // Description: When the class function is executed, the register EAX saves the address of the current class. So, when saved in TMETHOD.DATA should be the value of the EAX when performing the TMethod.code function, ie the class object pointer. // During [Show 1], it is not necessary to Eax, and the class object pointer is required, so it can be performed normally.

// *************** Modify the second // function address to read some procedure TMYFORM.BUTTON1ONCLICK (Sender: Tobject); var vMethod: TMethod; VEVENT: TNOTIFYEVENT; begin fMytext: = 'Hello Joy!'; VEVENT: = MyClick; vMethod.code: = @veth; // *********** Code 1 vMethod.Data: = Self; // ******* ****** Code 2 setMethodProp (Button2, 'OnClick', vMethod); END; // where myClick can be defined as a private function. // Description: vMethod just logs a class's function address and the address of the class object. The methodaddress function is only the read of the function address through the function name. 2003-6-18 12:48:38

Do not pass assembly [VMT]

VMT: Virtual Method Table // VMT access information egprocedure TForm1.Button1Click (Sender: TObject); var vpt: Pointer; vMethod: TMethod; begin vMethod.Code: = TForm.MethodAddress ( 'MyClick'); vMethod.Data: = Self; if vMethod.code = nil the showMessage ('error!'); Vpt: = pointer (tlistbox); Integer (VPT): = Integer (VPT) VMTTYPEINFO; / / In Delphi Help, according to offset ClassInfo can be obtained. Or you can refer to the definition of TOBJECT.CLAssInfo. SetMethodprop (ListBox2, getPropinfo (PtypeInfo (VPT ^), 'onclick'), vMethod; end; //, how to extract the class's class? Function TOBJECT.CLASSTYPE: TCLASS; Begin Mov Eax, [EAX] END; / / The statement can be translated into function TOBJECT.CLASSTYPE: TCLASS; Begin Result: = Tclass (Pointer (Self) ^); END; // So above The example can also be changed to Procedure TForm1.Button1Click (Sender: Tobject); VAR VPT: Pointer; VMethod: TMethod; Begin vMethod.code: = TFORM.MethodAddress ('myclick'); vMethod.Data: = Self; if vmethod. Code = nil then ShowMessage ( 'Error!'); vPt: = pointer (pointer (ListBox2) ^); // pointer acquired ClassType Integer (vPt): = Integer (vPt) vmtTypeInfo; SetMethodProp (ListBox2, GetPropInfo (pTypeInfo (vpt ^), 'onclick'), vMethod; end; {{{follow-up example, we can access all VMT entrance addresses and achieve the corresponding information} 2003-6-21 11:24:32

Remote function call using assembly

{No. 19} // How to call the function defined in the class function by the pointer (as follows: myfar)? // If we only pass a function pointer, then call the function, we will find that the variable FMYText of the current class object cannot be accessed in myfar. If an assembly is embedded, press the current location into the stack, then call this function, you can like the class function, where the variables are accessed. egtype pMyRec = ^ TMyRec; TMyRec = record rStr: String; rInt: Integer; end; procedure MyProc (APro: Pointer); var CallerBp: Cardinal; MyRec: TMyRec; vPt: Pointer; begin MyRec.rStr: = 'MyRec. RSTR '; MyRec.rint: =' myrec.rint '; VPT: = Pointer (@myrec); ASM MOV EAX, [EBP] MOV CALLERBP, EAX MOV END; End; Procedure Tmytemp.SetText (Atext) : String; procedure myfar; begin showMessage (format ('% s_% sd_% s', [self.fmytext, allc.); end; begin self.fmytext: =' Joyyuan '; MyProc (ADDR (Myfar)); end; {Description: Specific example can refer to: Grids unit, TsParsepointrarray.FORALL implementation.} 2003-6-21 11:47:21

Class function address

{No. 20} Test results list: It is also the process of testing methods and test thinking experience. Results 1: Button1.canfocus The address of Button2.canfocus is the same as the result of 2: Button1.canfocus is the same as the address of form1.canfocus, is also equivalent to ListBox1.canfocus results 3: When in the TFORM1 form class, back Form1.canfocus Button1.canfocus and form1.canfocus are not the same: If there is no virtual function of the parent class, the function is directly obtained and accessed directly and accessed. So, TButton, TListBox, TForm Access the CANFOCUS for TwinControl by default. So the function address is the same. Results 4: Defining Event Type TYPE TMYEVENT1 = Function (): Boolean Of Object; TMYEVENT2 = Function (): Boolean; result: sizeof (tmyevent1) = 8; sizeof (TMYEVEN2) = 4; Conclusion: Class Function Type, Save The contents of the room two pointers, see TMETHOD, CODE and DATA; one function pointer, an object pointer. Verification test example 1: Var vtestevent: tnotifyevent; begin Pointer ((@@ vtestevent) ^): = @ tform1.myclick; // or pass: tform1.methodaddress ('myclick') Way Function Address Pointer (Pointer @@ vtestevent) 4) ^): = Pointer (Self); vtestevent (nil); // is the same as executing Self.myClick. END; Verification Test Example 2: Var vMethod: Tmethod; Begin vMethod.code: = TFORM1.MethodAddress ('MyClick'); vMethod.Data: = Self; TNOTIFYEVENT (VMETHOD) (NIL); // Effect and execute Self.myclick same. end; author of the article: Monopoly joyyuan97

Source: http://www.delphibbs.com/keylife/iblog_show.asp? XID = 1134

转载请注明原文地址:https://www.9cbs.com/read-26479.html

New Post(0)