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

📄 ch08.htm

📁 用VC开发activeX控件的电子书,很不错的
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<P>Next you add a member variable to your class declaration that will store the <TT>BackColor</TT>
property (see Listing 8.12).
<H3><A NAME="Heading20"></A>Listing 8.12 ATLCONTROLWIN.H--m_BackColor Member Variable
Added to the Class Declaration</H3>
<P><FONT COLOR="#0066FF"><TT>. . . <BR>
protected: <BR>
// storage variable for the caption <BR>
LPTSTR m_lptstrCaption; <BR>
// storage variable for the alignment <BR>
long m_lAlignment; <BR>
// storage variable for the BackColor stock property <BR>
OLE_COLOR m_BackColor; <BR>
}; <BR>
#endif //__ATLCONTROLWIN_H_ </TT></FONT></P>
<P>Finally you must update the <TT>get_BackColor/put_BackColor</TT> functions to
return and store the <TT>BackColor</TT> property (see Listing 8.13).
<H3><A NAME="Heading21"></A>Listing 8.13 ATLCONTROLWIN.CPP--BackColor Property Source
File Implementation</H3>
<P><FONT COLOR="#0066FF"><TT>STDMETHODIMP CATLControlWin::get_BackColor(OLE_COLOR
* pVal) <BR>
{ <BR>
// return the color <BR>
*pVal = m_BackColor; <BR>
return S_OK; <BR>
} <BR>
STDMETHODIMP CATLControlWin::put_BackColor(OLE_COLOR newVal) <BR>
{ <BR>
// if the value is the same <BR>
if(newVal == m_BackColor) <BR>
return S_OK; <BR>
// store the value <BR>
m_BackColor = newVal; <BR>
// let the container know that the value has changed <BR>
this-&gt;FireOnChanged(DISPID_BACKCOLOR); <BR>
// this-&gt;AmbientPropertyChanged(DISPID_BACKCOLOR); &lt;== MFC Version <BR>
// redraw the control <BR>
this-&gt;FireViewChange(); <BR>
// this-&gt;InvalidateControl(); &lt;== MFC Version <BR>
// set the dirty flag <BR>
this-&gt;SetDirty(TRUE); <BR>
// this-&gt;SetModifiedFlag(); &lt;== MFC Version <BR>
// exit <BR>
return S_OK; <BR>
} </TT></FONT></P>
<P>The last thing is to initialize the <TT>m_BackColor</TT> member within the constructor
of the class (see Listing 8.14).
<H3><A NAME="Heading22"></A>Listing 8.14 ATLCONTROLWIN.H--Initialize the BackColor
Property to an Initial Value</H3>
<P><FONT COLOR="#0066FF"><TT>. . . <BR>
CATLControlWin() <BR>
{ <BR>
// NULL terminate the string reference <BR>
m_lptstrCaption = new TCHAR[1]; <BR>
m_lptstrCaption[0] = `\0'; <BR>
// set the alignment to the default of left <BR>
m_lAlignment = EALIGN_LEFT; <BR>
// set the backcolor to the system default <BR>
m_BackColor = 0x80000000 | COLOR_WINDOW; <BR>
} <BR>
. . . </TT></FONT></P>
<P>Regardless of the implementation style that you use, you can now access the <TT>BackColor</TT>
stock property through the member variable in your class, just as you do any other
property. This implementation differs from the MFC implementation of stock properties,
which hides all of the details regarding their implementation from you.
<H3><A NAME="Heading23"></A>Using Ambient Properties</H3>
<P><I>Ambient properties</I> are properties implemented in the container in which
the control resides, as opposed to <I>stock properties, </I>which are implemented
in the control and not the container. Ambient properties share the same set of predefined
meanings and dispids as those of stock properties. To use an ambient property, the
control must request only the property value from the container and apply it in whatever
manner is appropriate for the property type. The use of ambient properties allows
the control to conform to the same settings as those of the container in which it
resides. This procedure provides much better integration between the control and
its container.</P>
<P>Take the previous example of adding the <TT>BackColor</TT> stock property to the
sample control implementation. Defined as a stock property, the user of the control
can change the background color of the control or leave it as is. If the color is
different from that of the container or if the container's background color changes
for some reason, the colors won't match and will give the appearance of a poorly
integrated and written application. However, if the control simply used the ambient
background color of its container, the control's background will always match that
of the container. The specific requirements of your control implementation will decide
which route you choose when implementing the properties your control supports.</P>
<P>To access an ambient property, you can call one of the many ambient property functions
defined in the <TT>CComControlBase</TT> class, for example, Get<TT>AmbientBackColor()</TT>
in the case of the <TT>BackColor</TT> property.
<H3><A NAME="Heading24"></A>Creating Property Sheets</H3>
<P>Property sheets are a way for a control to display its properties for review and
editing using a tabbed-dialog format. The original intent of property sheets were
for the cases when the control container did not support property browsing facilities.
While property sheets have their purpose, they are probably not necessary for all
implementations. Your specific requirements will determine whether your control should
contain a property sheet. The official OLE line is that all controls should have
property sheets. This is true for commercially developed and distributed controls
but is probably not the case for in-house implementations. The majority of development
environments already have excellent property browsing facilities. Implement property
sheets only if you feel that you absolutely have to.</P>
<P>Removing the property sheets and their corresponding implementation infrastructure
will definitely reduce the size of your control and should not take away from its
implementation in any way.</P>
<P>Before you can work on the implementation of the property sheet, you must add
a property sheet object to your control. This is done through the ATL Object Wizard.
From the <U>I</U>nsert menu, select the New <U>A</U>TL Object menu item. Within the
ATL Object Wizard, select the Controls item in the left panel to display the types
of control components that can be added (see fig. 8.15). Your implementation will
be a Property Page, so select the Property Page icon. Click the <U>N</U>ext button
to continue. <B><BR>
<BR>
</B><A HREF="Art/08/gfigs15.jpg"><B>FIG. 8.15</B></A> <I><BR>
Add a property page object to your class with the ATL Object Wizard.</I></P>
<P>Select the Names tab in the ATL Object Wizard Properties dialog, and in the <U>S</U>hort
Name edit field, type ATLControlWinPPG; the remainder of the edit fields will automatically
update, reflecting the short name that you added (see fig. 8.16). The other fields
can be changed, but in this case, you use the default values. <B><BR>
<BR>
</B><A HREF="Art/08/gfigs16.jpg"><B>FIG. 8.16</B></A> <I><BR>
Enter the name of the property page object.</I></P>
<P>Select the Strings tab, and enter the string <TT>General</TT> to the <U>T</U>itle
edit field and <TT>ATLControlWin</TT> Property Page to the <U>D</U>oc String edit
fields. The <U>H</U>elpfile edit field is where you add the name of the help file
associated with the property page; for now, leave the value at its default setting.
Click OK to add the property page object to your control.</P>
<P>The ATL Object Wizard adds all of the necessary code to your control implementation
to include the new property page object, including the <TT>OBJECT_MAP</TT>, the IDL
file, and all of the registry and resource information.</P>
<P>Because property sheets are tabbed dialogs, most of your work is done with the
dialog editor. Select the Resource View in the Project Workspace window. From the
list of dialogs, select <TT>IDD_ATLCONTROLWINPPG</TT>, and double-click the entry
to open the resource editor.</P>
<P>Using the resource editor, remove the static text control with the caption Insert
your controls here, and place a static text control and a combo box on the dialog.</P>
<P>Using the mouse, select the label control on the form, and click the right mouse
button. In the menu that appears, select the <U>P</U>roperties menu item. On the
General tab, set the <U>I</U>D of the control to <TT>IDC_ALIGNMENTLABEL</TT>, and
set the <U>C</U>aption to <TT>Alignment</TT>; you see the control in Figure 8.17.
Select the Styles tab, and set the Align Te<U>x</U>t property to <TT>Right</TT>.
Close the dialog to save the information. <B><BR>
<BR>
</B><A HREF="Art/08/gfigs17.jpg"><B>FIG. 8.17</B></A> <BR>
<I>Add the controls to the Property Sheet dialog to display your property data.</I></P>
<P>Again, using the mouse, select the combo box, use the right mouse to click the
control, and in the menu that appears, select the <U>P</U>roperties menu item. On
the General tab, set the <U>I</U>D of the control to <TT>IDC_ALIGNMENTCOMBO</TT>.
On the Styles tab, set the T<U>y</U>pe to Dropdown, and uncheck the S<U>o</U>rt check
box. Close the dialog to save the information.</P>
<P>You have placed your two controls onto the property sheets and successfully modified
their properties. Now you need to add some code to complete the implementation. Close
the resource editor, and open the file ATLControlWinPPG.h. Your implementation of
the property page requires several resource definitions and the <TT>Alignment</TT>
enumeration that you created earlier. The values are added to the property page header
file in the form of <TT>include</TT> statements (see Listing 8.15).
<H3><A NAME="Heading25"></A>Listing 8.15 ATLCONTROLWINPPG.H--Add the Necessary Include
Files to the Property Page Header File</H3>
<P><FONT COLOR="#0066FF"><TT>. . . <BR>
#include &quot;resource.h&quot; // main symbols <BR>
#include &quot;alignmentenums.h&quot; <BR>
#include &quot;ATLControl.h&quot; <BR>
EXTERN_C const CLSID CLSID_ATLControlWinPPG; <BR>
. . . </TT></FONT></P>
<P>Since the property page is based on a dialog, you add a message handler for the
<TT>WM_INITDIALOG</TT> message so that you can load the <TT>Alignment</TT> combo
box with the value from the control's property when the property page is first created
(see Listing 8.16). ATL message maps are very similar to MFC; however, ATL lacks
the ClassWizard support that makes MFC so attractive. The message handler consists
of a single line added to the <TT>BEGIN_MSG_MAP</TT> macro. This line identifies
the message and receiving function that you want to implement, in this case <TT>WM_INITDIALOG</TT>
and <TT>OnInitDialog</TT>. The <TT>OnInitDialog</TT> function retrieves the window
handle to the <TT>Alignment</TT> combo box and resets its content. Next you add the
three string representations of the different <TT>Alignment</TT> styles possible
to the combo box. Then you retrieve a pointer to the control and get the current
property value of the <TT>Alignment</TT> property, and using the value, set the current
selection in the <TT>Alignment</TT> combo box. Note the use of the standard Win32
<TT>SendMessage</TT> function to update the data and settings of the combo box, which
is different from MFC, which has classes that wrap most of the core Win32 functions.
<H3><A NAME="Heading26"></A>Listing 8.16 ATLCONTROLWINPPG.H--Add the OnInitDialog
Message Handler so the Property Page Can Be Initialized</H3>
<P><FONT COLOR="#0066FF"><TT>. . . <BR>
BEGIN_MSG_MAP(CATLControlWinPPG) <BR>
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog) <BR>
COMMAND_HANDLER(IDC_ALIGNMENTCOMBO, CBN_SELCHANGE, <BR>
OnAlignmentComboSelChange) <BR>
CHAIN_MSG_MAP(IPropertyPageImpl&lt;CATLControlWinPPG&gt;) <BR>
END_MSG_MAP() <BR>
LRESULT OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &amp; bHandled)
<BR>
{ <BR>
// get the window handle of the combobox control <BR>
HWND hTempWnd = ::GetDlgItem(m_hWnd, IDC_ALIGNMENTCOMBO); <BR>
// make sure that the control is empty <BR>
::SendMessage(hTempWnd, CB_RESETCONTENT, 0, 0); <BR>
// set the selection strings in the control - it is important that the control <BR>
// be unsorted since the entries index will relate to the property setting <BR>
::SendMessage(hTempWnd, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) EALIGN_LEFT_TEXT); <BR>
::SendMessage(hTempWnd, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) <BR>
EALIGN_CENTER_TEXT); <BR>
::SendMessage(hTempWnd, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR) EALIGN_RIGHT_TEXT); <BR>
// see if the object supports the interface we need <BR>
CComQIPtr&lt;IATLControlWin, &amp;IID_IATLControlWin&gt;pControl(m_ppUnk[0]); <BR>
long lAlignment; <BR>
// set the control with the new value and if it failed <BR>
pControl-&gt;get_Alignment(&amp;lAlignment); <BR>
// get the current selection in the listbox <BR>
::SendMessage(::GetDlgItem(m_hWnd, IDC_ALIGNMENTCOMBO), <BR>
CB_SETCURSEL, lAlignment, 0); <BR>
return TRUE; <BR>
} <BR>
LRESULT OnAlignmentComboSelChange(WORD wNotify, WORD wID, HWND hWnd, <BR>
BOOL&amp; bHandled) <BR>
{ <BR>
SetDirty(TRUE); <BR>
return FALSE; <BR>
} <BR>
. . . </TT></FONT></P>
<P>The property page contains a combo box that the user can use to change the value
of the <TT>Alignment</TT> property. When the user changes the value, the property
page has to be notified of the change so that the property page will update the control
with the new property value. As for the <TT>WM_INITDIALOG</TT> message, you are required
to add a <TT>WM_COMMAND</TT> message handler for the <TT>CBN_SELCHANGE</TT> message
that the combo box will fire when its value changes. Adding the message handler is
done through a slightly different type of message map called a <TT>COMMAND_HANDLER</TT>,
which assumes that the primary message is <TT>WM_COMMAND</TT> (see Listing 8.16)
and breaks the submessage into its appropriate values for you. The function<TT> OnAlignmenComboSelChange</TT>
simply sets the dirty flag for the property page and exits.</P>
<P>The last step is the actual updating of the control's properties when the property
page exits. By setting the dirty flag of the property page, you instruct the <TT>Apply</TT>
function to execute, which allows you the opportunity to update all the property
values that the property page is responsible for. The <TT>Apply</TT> function is
already supplied to you as part of the property page implementation (see Listing
8.17). You need only add your support for your specific properties.</P>
<P>Since more than one object may have a reference to the property page, you are
required to notify all of the objects that the properties have changed. The <TT>Apply</TT>
function cycles through all of the references checking to see whether each contains
the interface that you are looking for. If you find an interface that you can use,
you then need only call the appropriate member fu

⌨️ 快捷键说明

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