In-depth
VCL
understanding
BCB
Message mechanism
Method 2 Written By CKER
Method 2. The WNDPROC method for heavy-duty TCONTROL is to talk about the inheritance strategy of VCL first. The top of the inheritance chain in the VCL is the TOBJECT base class. All VCL components and objects are inherited from TOBJECT. Open BCB Help View TControl inheritance: Tobject-> TPERSISTENT-> Tcomponent-> tcontrol Oh, TControl is inherited from the subclass Tcomponent class from the TPERSISTENT class. The TPERSISTENT abstraction class has the ability to use the stream Stream to save the properties of the class. The Tcomponent class is the parent class of all VCL components. This is why all VCL components include your custom components can use the DFM file access attribute. "Of course, if you are TPERSISTEN classes, I think you rarely get your custom component directly from the TOBJECT class." The importance of TControl classes is no less than its parent class. In the inheritance relationship of the BCB, the TControl class is the parent class of all VCL visual components. In fact, it means the control. The so-called visualization means that you can see and manipulate controls during operation. Some basic properties and methods of such controls are defined in the TCONTROL class. TControl's implementation can be found in /borland/cbuilder5/source/vcl/control.pas. "There may be friends asking you how to know there? Use the Search provided by BCB -> Find in Files is easy to find. Or use the GREP function of a third-party plug-in. Ok, enter the source code of VCL. Say it here, you can't complain about Borland. Hey, why do you have to achieve this with PASCAL ..... :- (tControl inherits but does not override the Tobject's Dispatch () method. Instead, a new method is WndProc () mentioned in XYCLEO. How do you read Borland's engineers? Procedure Tcontrol.WndProc (var message: tMessage);
VAR
Form: tcustom;
Begin
// The message during the design is handled by a form of Control.
IF (csdesigning in componentstate) THEN
Begin
Form: = getParentForm (Self);
IF (Form <> nil) and (form.designer <> nil)
Form.designer.IsDesignMsg (self, message).
end
// If necessary, the keyboard message is handed over to the form with Control.
Else IF (Message.msg> = WM_KEYFIRST) AND (Message.msg <= WM_KEYLAST) THEN
Begin
Form: = getParentForm (Self);
IF (Form <> nil) and form.wantchildkey (self, message) THEN EXIT;
end
// Treat mouse message
Else IF (Message.msg> = WM_Mousefirst) and (Message.msg <= WM_MouseLast) THEN
Begin
IF not (csdoubleclicks in controlstyle) THEN
Case message.msg of
WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK:
DEC (Message.msg, WM_LButtondblClk - WM_LButtondown);
END;
Case message.msg of
WM_MOUSEMOVE: Application.hintMouseMessage (Self, Message); WM_LButtondown, wm_lbuttondblclk:
Begin
IF fdragmode = dmautomatic then
Begin
Beginautodrag;
EXIT;
END;
Include (FcontrolState, CSLbuttondown);
END;
WM_LBUTTONUP:
Exclude (FcontrolState, CSLbuttondown);
END;
end
// The following line is a bit special. If you carefully see this message is cm_visiblechanged.
// Instead of our familiar WM_ starting standard Windows message.
// Although Borland does not mention that there is a CM message with this class in its help. But it is obvious that this is BCB
// Customize the message. Oh, if you are interested in this, you can find the relevant content in the VCL source code. There will be a small harvest.
Else if message.msg = cm_visiblechanged then
WITH MESSAGE DO
SenddockNotification (MSG, WPARAM, LPARAM);
// Finally call the Dispatch method.
Dispatch (Message);
End; After reading this code, you will find that the TCONTROL class actually processes the mouse message, and the messages that are not processed are finally transferred to Dispatch (). But here you need to emphasize that tControl doesn't have the ability to get focus FOCUS. TControl's subclavants TwinControl have such an capability. What do I tell? Oh, or open the help of the BCB. Many friends complain that the help of the BCB is not as MSDN of the VC. Needless to say, it is indeed far. And this help often have problems. But there is always better than nothing. For a few words, under the branch of the help of the TWINCONTROL BRANCH, you can see the introduction to the TwinControl class. It is pointed out that the TwinControl class is the base class of all forms controls. The so-called formal control refers to such a type of control: 1. You can get the focus of the program when running. 2. Other controls can display data, but only the formats control can be interacting with the user. 3. Form Class controls can include other controls (containers). 4. Controls containing other controls are also known as parent controls. Only the form patrol can be used as a parent control of other controls. 5. Form Class control has a handle. In addition to being able to accept focus, everything of TwinControl is nothing to TControl. This means that TwinControl responds to many standard events, and Windows must also assign a handle to it. And the most important thing related to this topic is that it is mentioned by BCB to redraw and message processing on the control. That is, TWINControl encapsulates all this. It seems that it is too far away. But what I want to ask is to process the mouse message in the WndProc method of the TControl class. But this news only has its sub-class TwinControl to get it !? How can this ... How is Borland to achieve this? This problem is very mystery. In order to see, I will go deep into the VCL again. Still in Control.PAS, TwinControl inherits the WndProc method of TControl. The source code is as follows: Procedure TWINCONTROL.WndProc (var message: tMessage);
VAR
Form: tcustom;
KeyState: tKeyboardState;
Wheelmsg: tcmousewheel;
Begin
Case message.msg of
WM_SETFOCUS:
Begin
Form: = getParentForm (Self);
IF (form <> nil) and not form.setfocusedControl (self) kiln
END;
WM_KILLFOCUS:
IF csfocusing in controlstate kiln
WM_NCHITTEST:
Begin
Inherited WNDPROC (Message);
IF (Message.Result = httransparent) and (ControlatPos (ScreenToClient
SmallPointTopoint (twmnchittest (message) .pos), false <> nil) THEN
Message.Result: = htclient;
EXIT;
END;
WM_MOUSEFIRST..WM_MOUSELAST:
// This sentence is pointed out that the mouse message is actually transferred to the iSControlMouseMSG method.
IF iscontrolmousemsg (twmmouse (message)) THEN
Begin
IF message.result = 0 THEN
DefWindowProc (Handle, Message.msg, Message.wParam, Message.lparam);
EXIT;
END;
WM_KEYFIRST..WM_KEYLAST:
IF Dragging the EXIT;
WM_CANCELMODE:
IF (getCapture = Handle) and (CaptureControl <> nil) and
(CaptureControl.Parent = Self) THEN
CaptureControl.Perform (WM_CANCELMODE, 0, 0);
Else
WITH MOUSE DO
IF WheelPresent and (RegwheelMessage <> 0) and
(Message.msg = regWheelMessage) THEN
Begin
GetKeyboardState (KeyState);
With Wheelmsg Do
Begin
Msg: = message.msg;
ShiftState: = keyboardStatetoshiftState (KeyState);
Wheeldelta: = Message.wParam;
POS: = TsmallPoint (Message.lparam);
END;
MousewheelHandler (TMely (Wheelmsg));
EXIT;
END;
END;
Inherited WNDPROC (Message);
End; mouse message is processed by the iSControlMouseMSG method. Only with ISControlmousemsg go see it. The source code is as follows: Function TwinControl.isControlmousemsg (var message: twmmouse): boolean;
VAR
// tcontrol appears
Control: tcontrol;
P: tpoint;
Begin
IF getcapture = handle kil
Begin
Control: = NIL;
IF (CaptureControl <> nil) and (capturecontrol.parent = self) THEN
CONTROL: = CaptureControl;
END ELSE
Control: = ControlatPos (SmallPointTopoint (Message.POS), FALSE;
Result: = false; if Control <> nil dam
Begin
P.x: = message.xpos - Control.Left;
P.y: = message.ypos - control.top;
File: // TControl's Perform method paid the message to WndProc.
Message.Result: = Control.Perform (Message.msg, Message.Keys, Longint (P)));
RESULT: = TRUE;
END;
End; It turns out that TwinControl finally handed the mouse message to the WndProc of TControl. The PerForm method that appears here can find the method that starts to appear in the TControl class in the help of the BCB. Its role is to pass the specified message to the WndProc process of TControl. Conclusion The message of the TControl class WndProc method is to transfer the iscontrol method to the iscontrolmouseMSG method in its overloaded WndProc method. For this reason, the TCONTROL class in BCB and Delphi and all its derivatives have a congenital and must limit. That is all TCONTROL classes and its derived Owner must be a TWINCONTROL class or TWINControl derived class. Owner properties The earliest can be found in Tcomponent, a component or control is owned by its Owner and is responsible for the release of its memory. That is to say, when the Owner is released from memory, the memory it has all the contours is also released. The best example of Owner is Form. Owner also is also responsible for the distribution of messages. When the Owner receives the message, it is responsible for passing messages that should be passed to the controls they have. These controls can achieve the ability to process messages. TIMAGE is an example: You can find that Borland does not let TIMAGE overload TControl's WndProc methods, so TIMAGE only has the ability to deal with mouse messages, and this ability is from TControl. I said a lot of stacks. It is finally possible to say that the second method of processing messages is to overload the WndProc method of TControl. The routines are as follows: void __fastcall tform1 :: wndproc (tMessage & Message)
{
Switch (Message.MSG)
{
Case WM_Close:
Onclose (message); // How to handle WM_CLOSE messages
Break;
}
TFORM :: WndProc (Message);
} At first, this is similar to the last overloaded dispatch method. But actually there is still different. Differences are in the order, from the front TControl's WndProc, the message is to handle it to WndProc to process, and finally call the Dispatch method. Thus, the overloaded WndProc method can get a message and process the message earlier than the reloaded DISPATCH method. Ok, this time I said here. Is there any way to get messages earlier in your application? Yes, let's talk about it next time. Copyright Description: You can copy, distribute, download this document freely. However, you may not take it, change this article, or use this article to see any form of interest.