In-depth VCL understands BCB Message Mechanism (3)

zhaozj2021-02-08  210

In-depth

VCL

understanding

BCB

Message mechanism

Method 3 Written by cker

Method 3. RH pointed out that the method from Tapplication doesn't have to be more non-use, everyone knows the importance of Tapplication in BCB. In the help of BCB, it is pointed out that Tapplication, Tscreen and TForm constitute the spine of all BCB style Win32 GUI programs that control your program. The properties and methods provided by the TAPPLICATION class encapsulate the behavior of the standard Windows program. Tapplication performances have created, run, supported, and destroy the application of the application in the Windows operating system. Therefore, Tapplication greatly simplifies the interface between the developer and the Windows environment. This is the RAD feature of the BCB. The standard Windows behavior of the TAPPLICATION package generally includes the following sections: 1> Windows message processing 2> Context associated Online Help 3> Menu Shortcuts and Keyboard Event Processing 4> Exception Process 5> Manage the Basic section defined by the operating system, Such as: MainWindow main window, WindowClass window, and so on. In general, BCB will automatically generate an instance of a TAPPLICATION class for each program. This part of the source code can be seen in yourProject.cpp file (here you assume your project name is YourProject.bpr). Of course, Tapplication is invisible, he is always on your form to control your program's behavior behind your form. But not to find a spider silk. If you create a new application, then don't make any changes, you will find the Caption of the program form is Form1, but the CAPTION on the Windows status bar is made to write the words of Project1. This is the evidence of TApplication existence. Of course, this is just a kind of speculation, and the actual method should open the Winsight with the BCB to view the system's process. You can clearly see the existence of the Tapplication class, his size is 0 "hidden. ", Then it is TFORM1 class. Ok, since Tapplication encapsulates the content of the message. Let's take a look at the actual action of Tapplication. In fact, when the message reaches the BCB program, the first to get them is the TAPPLICATION object. After the Tapplication, it is passed to Form. The previous method is to overload TFORM methods, obviously to receive the message later than the method mentioned in this article. For you, is it hoped to receive the message in the first time and handle them? To clearly know that the TAPPLICATION mechanism is still in-depth VCL source: first look at the most common code. #include

#pragma HDRSTOP

Useres ("Project1.Res");

Useform ("Unit1.cpp", Form1);

/ / -------------------------------------------------------------------------------------------- ----------------

WinApi Winmain (Hinstance, Hinstance, LPSTR, INT)

{

Try

{

// Initialize Application

Application-> Initialize ();

/ / Create a main window and display

Application-> CREATEFORM (__ classid (tform1), & form1);

// Enter the message loop until the program exits Application-> Run ();

}

Catch (Exception & Exception)

{

Application-> Showexception (& Exception);

Return 0;

}

/ / -------------------------------------------------------------------------------------------- ----------------

A short a few lines of code allows your BCB program to run. Because everything has been encapsulated in the background. Application-> Run () method Enter the message loop to the program until the program exits. Follow the VCL source together to see it. Tapplication defines in Forms.PAS. Procedure payplication.run;

Begin

Frunning: = TRUE;

Try

AddExitProc (doneApplication);

IF FMAINFORM <> NIL THEN

Begin // Set the display attribute of the main window

Case cmdshow of

SW_SHOWMINNOACTIVE: Fmainform.fWindowState: = wsminimized;

SW_SHOWMAXIMIZED: MainForm.WindowState: = wsmaximized;

END;

IF fshowmainform kil

IF fmbleform.fWindowState = wsminimized then

Minimize Else

Fmainform.visible: = true; // See it, there is a loop here until the TERMINATED property is true exit. What does terminate do mean, it is canceled, end

Repeat

HandleMessage

Until terminated;

END;

Finally

Frunning: = false;

END;

END;

The specific implementation of the message processing is not in the RUN method, it is obvious that the keyMessage method is in the HandleMessage method, see this function name - message processing. Only follow up HandleMessage 喽. Procedure Tapplication.handleMessage;

VAR

MSG: TMSG;

Begin

If not processmessage (msg) THEN IDLE (MSG);

END;

Cough, this is not a case site. The program will first hand over the message to the ProcessMessage method. If there is nothing to handle, transfer to the Application.Idle method "Method for calling when idle". Page, follow up the ProcessMessage method. Function Tapplication.ProcessMessage (VAR MSG: TMSG): Boolean

VAR

Handled: boolean;

Begin

Result: = FALSE;

IF PeekMessage (MSG, 0, 0, 0, PM_Remove) THEN

Begin

RESULT: = TRUE;

IF msg.Message <> wm_quit then

Begin

Handled: = false;

IF Assigned (Fonmessage) THEN FONMESSAGE (MSG, Handled);

IF not ishintmsg (msg) and not handled and not ismdimsg (msg) and NOD

Not iskeymsg (msg) and not isdlgmsg (msg) THEN

Begin

TranslateMessage (MSG);

DispatchMessage (MSG);

END;

end

Else

Fterminate: = true;

END;

END;

Oops, I finally have a eyebrow. ProcessMessage adopts a set of standard Windows API functions PeekMessage .... TranslateMessage; DispatchMessage. The previous post RH follows a few posts Application-> onMessage = myonMessage; // cannot respond to sendMessage messages, but can respond to the message sent by PostMessage, that is, the message SendMessage and PostMessage in the message queue are transmitted. The message has a message queue. The reason is here. ProcessMessage uses PeekMessage (MSG, 0, 0, 0, PM_Remove) to extract messages from the message queue. Then check it first if it is exit message. No, check if there is an onMessage method. Transfer to the onMessage processing message if there is. Finally, distribute the news. The onMessage method that is overloaded by this is more than the first two methods, which can be said to be the fastest way. For example: void __fastcall tform1 :: MyonMessage (tagmsg & msg, bool & hand) {

TMESSAGE MESSAGE;

Switch (msg.message)

{

Case WM_KeyDown:

Message.msg = msg.MESSAGE;

Message.wparam = msg.wparam;

Message.lparam = msg.lparam;

Messagedlg ("You Pressed Key!", MTWARNING, TMSGDLGBUTTONS () << mbok, 0);

Handled = True;

Break;

}

}

Void __fastcall tform1 :: formcreate (TOBJECT * SENDER)

{

Application-> onMessage = MyonMessage;

}

It is now a short summary of the VCL's message mechanism. The standard BCB program uses Application-> Run () into the message loop. In the Application's ProcessMessage method, use the PeekMessage method to extract messages from the message queue and remove this message from the message queue. The ProcessMessage method then checks if there is an Application-> OnMessage method. Presence, transfer to this method to process the message. The processed message distribution will then give each object in the program. At this point, the WndProc method receives the message and processes. If there is a DISPATCH method that cannot be handled overloaded. If you still can't handle it, you will be handed over to the DISPATCH method of the parent class. Finally, the Dispatch method actually transfer the message to the defaultHandler method. "Hey, actually, you can overload the DefaultHandler method to process the message. But it's too late. I think no one is willing to handle the last message ... :-) 」I seem to be over here. But if you have seen the previous one, you will pay attention to the Application-> hookmainWindow method mentioned by RH. What is this again? If you plan to use Application-> OnMessage to capture all messages sent to your application, you are about to be disappointed. The reason has been talked, it can't capture messages sent directly to the window using SendMessage, because this does not pass the message queue. You may say that I can directly overload the WndProc method of the TAPPLICATION. Oh, no. Because the WndProc method of Tapplication is static by Borland, it cannot be overloaded. Obviously, this reason is probably Borland worried that the side effects brought. What should this be good? View the Pascal source code for Tapplication WndProc You can see: Procedure Tapplication.WndProc (var message: tMessage); ... // Save the space, here is unrelated to the subject, Begin

Try

Message.Result: = 0;

For i: = 0 to fwindowhooks.count - 1 DO

If TwindowHook (FWindowHooks [i] ^) (Message) The Exit; ... // Save the space, here is a custom message processing method for the hookmainwindow hook first with the subject-unrelated code, and then call the custom message processing method of the hookmainwindow hook first, then call the lack Provincial process processing message. This allows you to add your own message processing method in WndProc using hookmainwindow. Use this method to respond to message sent by SendMessage. Finally, remind it to use the hookmainwindow hook to call the UnHookMainWindow uninstall the hook program. Give an example: void __fastcall tform1 :: formcreate (TOBJECT * Sender)

{

Application-> hookmainwindow (apphookfunc);

}

/ / -------------------------------------------------------------------------------------------- ---------------------------

BOOL __FASTCALL TFORM1 :: AppHookFunc (TMESSAGE & Message)

{

BOOL HANDLED;

Switch (Message.MSG)

{

Case WM_Close:

MRYES == Messagedlg ("Really Close ??", MTWARNING, TMSGDLGBUTTONS () << mbyes << mbno, 0)? Handled = false: handled = true;

Break;

}

Return Handled;

} // ----------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------

Void __fastcall tform1 :: formdestroy (TOBJECT * Sender)

{

Application-> unhookmainwindow (apphookfunc);

}

/ / -------------------------------------------------------------------------------------------- ---------------------------

Void __fastcall tform1 :: button1click (Tobject * Sender)

{

SendMessage (Application-> Handle, WM_Close, 0, 0);

}

/ / -------------------------------------------------------------------------------------------- ------------------------- This combines the two methods in this article, you can deal with your app Various news.

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.

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

New Post(0)