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

📄 ch07.htm

📁 用VC开发activeX控件的电子书,很不错的
💻 HTM
📖 第 1 页 / 共 5 页
字号:
]<BR>
    dispinterface _DMFCControlWin<BR>
           {<BR>
           properties:<BR>
                  // NOTE - ClassWizard will maintain property information here.<BR>
                  //    Use extreme caution when editing this section.<BR>
                  //{{AFX_ODL_PROP(CMFCControlWinCtrl)<BR>
                  [id(DISPID_READYSTATE), readonly] long ReadyState;<BR>
                  [id(1)] EALIGNMENT Alignment;<BR>
                  [id(DISPID_BACKCOLOR), bindable, requestedit] OLE_COLOR BackColor;<BR>
                  [id(2)] BSTR TextData;<BR>
                  //}}AFX_ODL_PROP<BR>
           methods:<BR>
. . .</TT></FONT>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<P><B>Dynamic Property Enumeration </B><SPACER TYPE="HORIZONTAL" SIZE="10">Dynamic
property enumeration is the most flexible of the two types of property enumeration.
It requires only a little more work on the part of the developer, and is worth the
effort. Dynamic enumeration is perfect for situations where you need to restrict
the data that can be entered into a property but are unable to determine until runtime
what the valid values are. For example, a <TT>LocaleID</TT> property can enumerate
all of the available <TT>LocaleIDs</TT> on the machine that the application is running
on. Another property could enumerate the key field of a SQL database table. The possibilities
are limitless and will provide your control a look and feel that goes far beyond
the effort that was required to enable it. Dynamic property enumeration using MFC
requires the implementation of three methods within your control: <TT>OnGetPredefinedStrings</TT>,
<TT>OnGetPredefinedValue</TT>, and <TT>OnGetDisplayString</TT>, all of which are
virtual functions declared in the <TT>COleControl</TT> class. Listing 7.9 shows the
function prototypes that need to be added to the control's class declaration.
<H3><A NAME="Heading13"></A>Listing 7.9 MFCCONTROLWINCTL.H--Dynamic Property Enumeration
Function Prototypes Added to the CMFCControlWinCtrl Class</H3>
<P><FONT COLOR="#0066FF"><TT>class CMFCControlWinCtrl : public COleControl<BR>
{<BR>
         DECLARE_DYNCREATE(CMFCControlWinCtrl)<BR>
<BR>
// Constructor<BR>
public:<BR>
         CMFCControlWinCtrl();<BR>
<BR>
         BOOL OnGetPredefinedStrings(DISPID dispid, CStringArray* pStringArray, 
              CDWordArray* pCookieArray);<BR>
         BOOL OnGetPredefinedValue(DISPID dispid, DWORD dwCookie, VARIANT FAR*  
           lpvarOut);<BR>
         BOOL OnGetDisplayString( DISPID dispid, CString&amp; strValue );<BR>
<BR>
// Overrides<BR>
. . .</TT></FONT>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<P><TT>OnGetPredefinedStrings</TT> is called by the container application when it
needs to load the strings and cookies for the enumeration (see Listing 7.10). The
string is used as the text representation of the enumerated value to make it more
meaningful to the user. The cookie is a 32-bit value that can be used in any way
that is appropriate to identify the value associated with the display string of the
enumeration. In your case, you are going to store the actual value that the string
represents, but it could just as easily have been a pointer or index into some form
of storage.
<H3><A NAME="Heading14"></A>Listing 7.10 MFCCONTROLWINCTL.CPP--OnGetPredefinedStrings
Implementation</H3>
<P><FONT COLOR="#0066FF"><TT>BOOL CMFCControlWinCtrl::OnGetPredefinedStrings(DISPID
dispid, CStringArray* pStringArray, CDWordArray* pCookieArray)<BR>
{<BR>
       BOOL bResult = FALSE;<BR>
<BR>
       // which property is it<BR>
    switch(dispid)<BR>
    {<BR>
    case dispidAlignment:<BR>
    {<BR>
           // add the string to the array<BR>
           pStringArray-&gt;Add(_T(&quot;Left Justify&quot;));<BR>
           // add the value to the array<BR>
           pCookieArray-&gt;Add(EALIGN_LEFT);<BR>
<BR>
           // add the string to the array<BR>
           pStringArray-&gt;Add(_T(&quot;Center&quot;));<BR>
           // add the value to the array<BR>
           pCookieArray-&gt;Add(EALIGN_CENTER);<BR>
<BR>
           // add the string to the array<BR>
           pStringArray-&gt;Add(_T(&quot;Right Justify&quot;));<BR>
           // add the value to the array<BR>
           pCookieArray-&gt;Add(EALIGN_RIGHT);<BR>
<BR>
           // set the return value<BR>
           bResult = TRUE;<BR>
    }<BR>
    break;<BR>
    }<BR>
<BR>
    return bResult;<BR>
}</TT></FONT>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<P>The <TT>OnGetPredefinedStrings</TT> function is called for every one of the properties
in your control, so your code will have to check the <TT>dispid</TT> that is passed
to the function to make sure that the correct enumeration is going to the correct
property. The <TT>dispid</TT>s of the control properties can be found in the class
declaration of your control and are maintained automatically by the ClassWizard (see
Listing 7.11).
<H3><A NAME="Heading15"></A>Listing 7.11 MFCCONTROLWINCTL.H--Control dispid Enumeration</H3>
<P><FONT COLOR="#0066FF"><TT>. . .<BR>
// Dispatch and event IDs<BR>
public:<BR>
       enum {<BR>
       //{{AFX_DISP_ID(CMFCControlWinCtrl)<BR>
       dispidAlignment = 1L,<BR>
       dispidTextData = 2L,<BR>
       dispidCaptionMethod = 3L,<BR>
       dispidCaptionProp = 4L,<BR>
       eventidChange = 1L,<BR>
       //}}AFX_DISP_ID<BR>
       };<BR>
<BR>
. . .</TT></FONT>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<P>When the user selects one of the enumerated values in the property browser, the
control's <TT>OnGetPredefinedValue</TT> function is fired (see Listing 7.12). This
allows the container to retrieve the actual value that should be stored in the property
in place of the string representation. The function is passed the <TT>dispid</TT>
identifying the property that is being changed and the cookie value that was assigned
to the string representation in the <TT>OnGetPredefinedStrings</TT> function.
<H3><A NAME="Heading16"></A>Listing 7.12 MFCCONTROLWINCTL.CPP-- OnGetPredefinedValue
Implementation</H3>
<P><FONT COLOR="#0066FF"><TT>BOOL CMFCControlWinCtrl::OnGetPredefinedValue(DISPID
dispid, DWORD dwCookie,       VARIANT FAR* lpvarOut)<BR>
{<BR>
    BOOL bResult = FALSE;<BR>
<BR>
    // which property is it<BR>
    switch(dispid)<BR>
    {<BR>
    case dispidAlignment:<BR>
            // clear the variant<BR>
            ::VariantInit(lpvarOut);<BR>
            // set the type to a long<BR>
            lpvarOut-&gt;vt = VT_I4;<BR>
            // set the value to the value that was stored with the string<BR>
            lpvarOut-&gt;lVal = dwCookie;<BR>
            // set the return value<BR>
            bResult = TRUE;<BR>
    break;<BR>
    }<BR>
<BR>
    return bResult;<BR>
}</TT></FONT>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<P><TT>OnGetDisplayString</TT> (see Listing 7.13) is the last method to be called
and is required if the programmer wants the text representation to appear next to
the property in the property browser when the property is not being edited. The function
is passed a <TT>dispid</TT>, again reflecting the current property, and a <TT>CString</TT>
object reference. The control should place the string, as reflected by the current
state of the property, into the <TT>CString</TT> object and exit the function.
<H3><A NAME="Heading17"></A>Listing 7.13 MFCCONTROLWINCTL.CPP--OnGetDisplayString
Implementation</H3>
<P><FONT COLOR="#0066FF"><TT>BOOL CMFCControlWinCtrl::OnGetDisplayString( DISPID
dispid, CString&amp; strValue )<BR>
{<BR>
        BOOL bResult = FALSE;<BR>
<BR>
        // which property is it<BR>
        switch(dispid)<BR>
        {<BR>
        case dispidAlignment:<BR>
           {<BR>
           switch(m_lAlignment)<BR>
           {<BR>
           case EALIGN_LEFT:<BR>
               strValue = _T(&quot;Left Justify&quot;);<BR>
           break;<BR>
           case EALIGN_CENTER:<BR>
               strValue = _T(&quot;Center&quot;);<BR>
           break;<BR>
           case EALIGN_RIGHT:<BR>
               strValue = _T(&quot;Right Justify&quot;);<BR>
           break;<BR>
           }<BR>
<BR>
           // set the return value<BR>
           bResult = TRUE;<BR>
        }<BR>
        break;<BR>
        }<BR>
<BR>
        return bResult;<BR>
}</TT></FONT>
<H2><A NAME="Heading18"></A>Drawing the Control</H2>
<P>Optimized drawing allows you to create drawing objects, such as pens or brushes,
and rather than removing them when you are finished drawing, you can store them in
your control member variables and use them again the next time your control draws
itself. The benefit is that you create a pen once for the drawing lifetime of your
control, instead of every time it draws. One thing to remember, though: Optimized
drawing does not guarantee performance improvements. It simply supplies a framework
for how drawing should be performed and how drawing resources should be used. A poorly
written control is still poorly written, no matter how you slice it.</P>
<P>Standard and optimized drawings have a single tradeoff, and that is size versus
speed. Standard drawing does not require member variables for the drawing objects
that are created and used--thus requiring less instance data but more processing
time--whereas optimized code will be the opposite.</P>
<P>An additional drawback to optimized drawing is that a container may not support
it. A control must, at the very least, support standard drawing functionality, deferring
to optimized only if appropriate.</P>
<P>For MFC, the scope of optimized drawing is very narrow compared to the OC 96 specification,
but it will, nonetheless, result in performance improvements if taken advantage of.
The OC 96 specification further breaks optimized drawing into what is known as <I>aspects</I>,
but MFC is not designed to allow that kind of drawing. For more information on aspect
drawing, please see the OLE Control 96 Specification that ships with the ActiveX
SDK. <B><BR>
<BR>
Optimized Drawing</B><SPACER TYPE="HORIZONTAL" SIZE="10"><B> </B>In <A HREF="ch06.htm">Chapter
6</A>, you learn how to implement standard drawing. In this chapter, you will enhance
the original implementation to take advantage of drawing optimization. Listing 7.14
reflects the change that is made to the original drawing code to use optimization.
That's it. You just check to see whether the container supports optimized drawing.
If the container supports optimized drawing, you leave the <TT>CBrush</TT> object
alone and use it again when you have to draw the control's UI. Thus, you save time
every time you redraw the UI because you load the brush only once. When the control
is destroyed, the <TT>CBrush</TT> object will go out of scope and will remove the
brush object for you. Optimized drawing is that simple, but it depends on the container
application for support.
<H3><A NAME="Heading19"></A>Listing 7.14 MFCCONTROWINCTL.CPP--Optimized OnDraw Function</H3>
<P><FONT COLOR="#0066FF"><TT>. . .<BR>
<BR>
        // set the old font back<BR>
        pdc-&gt;SelectObject(pOldFont);<BR>
// **<BR>
// ****** Get the text font ******<BR>
<BR>
        // The container does not support optimized drawing.<BR>
        if(!IsOptimizedDraw())<BR>
        {<BR>
                // select the old brush back<BR>
                pdc-&gt;SelectObject(pOldBrush);<BR>
        }<BR>
}</TT></FONT>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<H2><A NAME="Heading20"></A>Adding Clipboard and Drag and Drop Support</H2>
<P>The <I>Clipboard</I> is an area of the Windows operating system that acts like
a bulletin board for data that can be shared between applications. By means of a
series of keystrokes or menu options, a user can copy data to the Clipboard from
one application and paste the data from the Clipboard into another application.</P>

⌨️ 快捷键说明

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