⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 faq16.htm

📁 C++builder学习资料C++builder
💻 HTM
字号:


<HTML>

<HEAD>

   <TITLE>Respond to messages sent to the application.</TITLE>

   <META NAME="Author" CONTENT="Harold Howe">

</HEAD>

<BODY BGCOLOR="WHITE">



<CENTER>

<TABLE  BORDER=0 CELLPADDING=0 CELLSPACING=0 WIDTH="640">



<TR>

<TD>







<H3>

Respond to messages sent to the application.

</H3>

<P>

There is more than one way to catch messages that Windows sends to your program. You can override

the virtual <TT>WndProc</TT> function of the main form, you can create a message map, or you can create an

<TT>OnMessage</TT> handler for the application. This FAQ describes each one briefly.

</P>



<P>

<B>Overriding <TT>WndProc</TT>:</B> All descendants of <TT>TControl</TT>, including

<TT>TForm</TT>, contain a <TT>WndProc</TT> function that serves as the window procedure for

the component. This function is virtual, which means that you can override the

function to intercept messages. The argument to <TT>WndProc</TT> is a <TT>TMessage</TT>

structure passed by reference that contains the message command ID and the <TT>WPARAM</TT>

and <TT>LPARAM</TT> values.

</P>

<P>

<B>Step 1:</B> Add the <TT>WndProc</TT> declaration to your form's header.

</P>

<pre>

    <b>private</b><b>:</b>

        <b>void</b> <b>__fastcall</b> WndProc<b>(</b>Messages<b>:</b><b>:</b>TMessage <b>&</b>Message<b>)</b><b>;</b>

</pre>

<P>

<B>Step 2:</B> Code the function. The derived <TT>WndProc</TT> should call the base class

<TT>TForm::WndProc</TT> for all messages that you don't process. This function prevents the

windows screensaver from starting.

</P>

<pre>

    <b>void</b> <b>__fastcall</b> TForm1<b>:</b><b>:</b>WndProc<b>(</b>Messages<b>:</b><b>:</b>TMessage <b>&</b>Message<b>)</b>

    <b>{</b>

        <b>if</b><b>(</b>  <b>(</b>Message<b>.</b>Msg    <b>==</b> WM_SYSCOMMAND<b>)</b> <b>&&</b>

             <b>(</b>Message<b>.</b>WParam <b>==</b> SC_SCREENSAVE<b>)</b>    <b>)</b>

        <b>{</b>

            Application<b>-></b>MessageBox<b>(</b><font color="blue">"Good bye screen saver"</font><b>,</b> <font color="blue">"SCR No"</font><b>,</b> MB_OK<b>)</b><b>;</b>

            Message<b>.</b>Result <b>=</b> <b>true</b><b>;</b>

        <b>}</b>

        <b>else</b>

            TForm<b>:</b><b>:</b>WndProc<b>(</b>Message<b>)</b><b>;</b>

    <b>}</b>

</pre>



<B>Creating a Message Map:</B> Message maps allow you to write a function that receives only

one specific message, rather than all of a form's messages like <TT>WndProc</TT> does. Message

maps utilize the various message structures found in \INCLUDE\MESSAGES.HPP. For example, a

message map for <TT>WM_GETMINMAXINFO</TT> would utilize the <TT>TWMGetMinMaxInfo</TT>

structure. These structures are nice because the <TT>WPARAM</TT> and <TT>LPARAM</TT> values

are decoded into more meaningful structure members.

</P>

<P>

<B>Step 1:</B> Add a function declaration and the message map body to your form's header.

</P>

<pre>

    <b>private</b><b>:</b>

        <b>void</b> <b>__fastcall</b> WMSysCommand<b>(</b>TWMSysCommand <b>&</b>Message<b>)</b><b>;</b>

    <b>public</b><b>:</b>

        <b>__fastcall</b> TForm1<b>(</b>TComponent<b>*</b> Owner<b>)</b><b>;</b>



    BEGIN_MESSAGE_MAP

        MESSAGE_HANDLER<b>(</b>WM_SYSCOMMAND<b>,</b>TWMSysCommand<b>,</b>WMSysCommand<b>)</b>

    END_MESSAGE_MAP<b>(</b>TForm<b>)</b>

</pre>

<P>

<B>Step 2:</B> Code the function. If you need to pass the message on to the base class,

call the <TT>Dispatch</TT> function of the base class.

</P>

<pre>

    <b>void</b> <b>__fastcall</b> TForm1<b>:</b><b>:</b>WMSysCommand<b>(</b>TWMSysCommand <b>&</b>Message<b>)</b>

    <b>{</b>

        <b>if</b><b>(</b>Message<b>.</b>CmdType <b>==</b> SC_SCREENSAVE<b>)</b>

        <b>{</b>

            Application<b>-></b>MessageBox<b>(</b><font color="blue">"Good bye screen saver"</font><b>,</b> <font color="blue">"SCR No"</font><b>,</b> MB_OK<b>)</b><b>;</b>

            Message<b>.</b>Result <b>=</b> <b>true</b><b>;</b>

        <b>}</b>

        <b>else</b>

            TForm<b>:</b><b>:</b>Dispatch<b>(</b><b>&</b>Message<b>)</b><b>;</b>

    <b>}</b>

</pre>

<P>

<B>Note:</B> Make sure that you call the <TT>Dispatch</TT> method of the base class, and not the <TT>Dispatch</TT>

method of your derived class. Message maps are triggered from the <TT>Dispatch</TT> method of the derived class.

Calling the derived version of <TT>Dispatch</TT> triggers your message map again, and this results in infinite recursion.

</P>



<B>Creating an <TT>OnMessage</TT> handler:</B> The <TT>OnMessage</TT> handler allows you to

handle messages before they are processed by the application.

</P>

<P>

<B>Step 1:</B> Add a function declaration for the <TT>OnMessage</TT> handler.

</P>

<pre>

    <b>private</b><b>:</b>

        <b>void</b> <b>__fastcall</b> AppOnMessage<b>(</b>TMsg <b>&</b>Message<b>,</b> <b>bool</b> Handled<b>)</b><b>;</b>

</pre>

<P>

<B>Step 2:</B> Code the function. Set the <TT>Handled</TT> flag for messages that you handle.

</P>

<pre>

    <b>void</b> <b>__fastcall</b> TForm1<b>:</b><b>:</b>AppOnMessage<b>(</b>TMsg <b>&</b>Msg<b>,</b> <b>bool</b> <b>&</b>Handled<b>)</b>

    <b>{</b>

        <b>if</b><b>(</b>  <b>(</b>Msg<b>.</b>message <b>==</b> WM_SYSCOMMAND<b>)</b> <b>&&</b>

             <b>(</b>Msg<b>.</b>wParam  <b>==</b> SC_SCREENSAVE<b>)</b>   <b>)</b>

        <b>{</b>

            Application<b>-></b>MessageBox<b>(</b><font color="blue">"Good bye screen saver"</font><b>,</b> <font color="blue">"SCR No"</font><b>,</b> MB_OK<b>)</b><b>;</b>

            Handled <b>=</b> <b>true</b><b>;</b>

        <b>}</b>

        <b>else</b>

            Handled <b>=</b> <b>false</b><b>;</b>

    <b>}</b>

</pre>

<P>

<B>Step 3:</B> In the constructor of the main form, assign the function <TT>AppOnMessage</TT> to the <TT>OnMessage</TT>

event of the global <TT>Application</TT> object.

</P>

<pre>

    <b>void</b> <b>__fastcall</b> TForm1<b>:</b><b>:</b>TForm1<b>(</b>TComponent<b>*</b> Owner<b>)</b>

        <b>:</b> TForm<b>(</b>Owner<b>)</b>

    <b>{</b>

        Application<b>-></b>OnMessage <b>=</b> AppOnMessage<b>;</b>

    <b>}</b>

</pre>



<P>

<B>Notes: </B>So how do you decide which of the previous methods to use? Overriding

<TT>WndProc</TT> works well when you need to respond to a lot of different messages, or when

you have existing switch/case message handling code from an API project that you would like

to reuse with minimum effort. The message maps are nice because they allow you to focus on a

single message, and the message structures can make your code easy to read. The

<TT>OnMessage</TT> approach allows you to intercept messages before the program gets a chance

to process them. The downfall of <TT>OnMessage</TT> is that messages sent via

<TT>SendMessage</TT> or <TT>Perform</TT> don't get passed to the <TT>OnMessage</TT> handler.

Additionally, the <TT>OnMessage</TT> handler can bog down the system. </P>

<P>

In general, use <TT>WndProc</TT> or message maps for most cases. Use <TT>OnMessage</TT> only

when its the only way to intercept a message. Never use <TT>OnMessage</TT> from within a

component to intercept application messages. If necessary, use good ol' subclassing. The VCL makes

subclassing painless through the <TT>WindowProc</TT> property of classes

derived from <TT>TControl</TT>.

</P>   



</TD> </TR>



</TABLE>

</CENTER>

</BODY>

</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -