?? ch20.htm
字號:
CLASSID="CLSID:46646B43-EA16-11CF-870C-00201801DDD6"
TYPE="application/oleobject"
CODEBASE="dieroll.cab#Version=1,0,0,1"
PARAM_ForeColor="0"
PARAM_BackColor="16777215">
</OBJECT>
<BR>
Here is some text after the die
</BODY>
</PRE>
<PRE></HTML>
</PRE>
<P>It is the <EMBED> tag that brings up the plug-in. Because it's inside the
<OBJECT>...</OBJECT> tag, Microsoft Internet Explorer and other browsers
that know the OBJECT tag will ignore the EMBED. This means that this HTML source
will display the control equally well in Netscape Navigator and in Explorer. You'll
probably want to include a link on your page to the NCompass page to help your readers
find the plug-in and learn about it.</P>
<P>Microsoft is committed to establishing ActiveX controls as a cross-platform, multibrowser
solution that will, in the words of its slogan, "Activate the Internet."
The ActiveX control specification is no longer a proprietary document but has been
released to a committee that will maintain the standard. Don't pay any attention
to people who suggest you should only build these controls if your readers use Internet
Explorer!</P>
<P>
<H2><A NAME="Heading3"></A>Registering as Safe for Scripting and Initializing</H2>
<P>For any of your readers who operate with a Medium safety level, the control should
be registered as safe for scripting and initializing. This assures anyone who wants
to view a page containing the control that no matter what functions are called from
a script or what parameters are initialized through the PARAM attribute, nothing
unsafe will happen. For an example of a control that isn't safe, think of a control
that deletes a file on your machine when it executes. The default file is one you
won't miss or that probably won't exist. A page that put this control in a script,
or that initialized the filename with PARAM attributes, might order the control to
delete a very important file or files, based on guesses about where most people keep
documents. It would be simple to delete C:\MSOFFICE\WINWORD\WINWORD.EXE, for example,
and that would be annoying for Word users. Figure 20.3 shows the error message displayed
in Explorer when you are using the Medium safety level and load a page featuring
a control that isn't registered as script-safe or init-safe. The NCompass Labs plug-in,
ScriptActive, also refuses to load controls that are not registered as script-safe
and init-safe.</P>
<P><A HREF="javascript:popUp('20uvc03.gif')"><B>FIG. 20.3</B></A><B> </B><I>Explorer
alerts you to controls that might run amok.</I></P>
<P>First, you need to add three functions to DierollCtl.cpp. (They come unchanged
from the ActiveX SDK.) These functions are called by code presented later in this
section. Don't forget to add declarations of these functions to the header file,
too. The code is in Listing 20.3.</P>
<P>
<H4>Listing 20.3  DierollCtl.cpp--New Functions to Mark the Control as
Safe</H4>
<PRE> ////////////////////////////////////////////////////////////////
// Copied from the ActiveX SDK
// This code is used to register and unregister a
// control as safe for initialization and safe for scripting
HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
{
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ;
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (FAILED(hr))
return hr;
// Make sure the HKCR\Component Categories\{..catid...}
// key is registered
CATEGORYINFO catinfo;
catinfo.catid = catid;
catinfo.lcid = 0x0409 ; // english
// Make sure the provided description is not too long.
// Only copy the first 127 characters if it is
int len = wcslen(catDescription);
if (len>127)
len = 127;
wcsncpy(catinfo.szDescription, catDescription, len);
// Make sure the description is null terminated
catinfo.szDescription[len] = `\0';
hr = pcr->RegisterCategories(1, &catinfo);
pcr->Release();
return hr;
}
HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
// Register your component categories information.
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ;
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (SUCCEEDED(hr))
{
// Register this category as being "implemented" by
// the class.
CATID rgcatid[1] ;
rgcatid[0] = catid;
hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
}
if (pcr != NULL)
pcr->Release();
return hr;
}
HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
{
ICatRegister* pcr = NULL ;
HRESULT hr = S_OK ;
hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
if (SUCCEEDED(hr))
{
// Unregister this category as being "implemented" by
// the class.
CATID rgcatid[1] ;
rgcatid[0] = catid;
hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);
}
if (pcr != NULL)
pcr->Release();
return hr;
</PRE>
<PRE>}
</PRE>
<P>Second, add two #include statements at the top of DierollCtl.cpp:</P>
<P>
<PRE>#include "comcat.h"
#include "objsafe.h"
</PRE>
<P>Finally, modify UpdateRegistry() in DierollCtl.cpp to call these new functions.
The new code calls CreateComponentCategory() to create a category called CATID_SafeForScripting
and adds this control to that category. Then it creates a category called CATID_SafeForInitializing
and adds the control to that category as well. Listing 20.4 shows the new version
of UpdateRegistry().</P>
<P>
<H4>Listing 20.4  DierollCtl.cpp--CDierollCtrl::CDierollCtrlFactory::UpdateRegistry()</H4>
<PRE>BOOL CDierollCtrl::CDierollCtrlFactory::UpdateRegistry(BOOL bRegister)
{
// TODO: Verify that your control follows apartment-model threading rules.
// Refer to MFC TechNote 64 for more information.
// If your control does not conform to the apartment-model rules, then
// you must modify the code below, changing the 6th parameter from
// afxRegInsertable | afxRegApartmentThreading to afxRegInsertable.
if (bRegister)
{
HRESULT hr = S_OK ;
// register as safe for scripting
hr = CreateComponentCategory(CATID_SafeForScripting,
L"Controls that are safely scriptable");
if (FAILED(hr))
return FALSE;
hr = RegisterCLSIDInCategory(m_clsid, CATID_SafeForScripting);
if (FAILED(hr))
return FALSE;
// register as safe for initializing
hr = CreateComponentCategory(CATID_SafeForInitializing,
L"Controls safely initializable from persistent data");
if (FAILED(hr))
return FALSE;
hr = RegisterCLSIDInCategory(m_clsid, CATID_SafeForInitializing);
if (FAILED(hr))
return FALSE;
return AfxOleRegisterControlClass(
AfxGetInstanceHandle(),
m_clsid,
m_lpszProgID,
IDS_DIEROLL,
IDB_DIEROLL,
afxRegInsertable | afxRegApartmentThreading,
_dwDierollOleMisc,
_tlid,
_wVerMajor,
_wVerMinor);
else
{
HRESULT hr = S_OK ;
hr = UnRegisterCLSIDInCategory(m_clsid, CATID_SafeForScripting);
if (FAILED(hr))
return FALSE;
hr = UnRegisterCLSIDInCategory(m_clsid, CATID_SafeForInitializing);
if (FAILED(hr))
return FALSE;
return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}
</PRE>
<PRE>}
</PRE>
<P>To confirm that this works, open Explorer and set your safety level to Medium.
Load the HTML page that uses the control; it should warn you the control is unsafe.
Then make these changes, build the control, and reload the page. The warning will
not reappear.</P>
<P>
<H2><A NAME="Heading4"></A>Choosing Between ActiveX and Java Applets</H2>
<P>Java is an application development language as well as an applet development language,
which means you can develop ActiveX controls in Java if you choose to, using a tool
like Microsoft's Visual J++ integrated into Developer Studio. When most people frame
a showdown like ActiveX versus Java, though, they mean ActiveX versus Java <I>applets</I>,
which are little, tightly contained applications that run on a Web page and can't
run standalone.</P>
<P>Many people are concerned about the security of running an application they did
not code, when they do not know the person or organization supplying the application.
The Java approach attempts to restrict the actions that applets can perform so that
even malicious applets can't do any real damage. However, regular announcements of
flaws in the restriction approach are damaging Java's credibility. Even if a Java
applet were guaranteed to be safe, these same restrictions prevent it from doing
certain useful tasks, since they cannot read or write files, send email, or load
information from other Internet sites.</P>
<P>The approach taken by Microsoft with ActiveX is the trusted supplier approach,
which is extendable to Java and any other code that can execute instructions. Code
is digitally signed so that you are sure who provided it and that it has not been
changed since it was signed. This won't prevent bad things from happening if you
run the code, but it will guarantee that you know who is to blame if bad things do
occur. This is just the same as buying shrink- wrapped software from the shelf in
the computer store. For more details, look at <A HREF="http://www.microsoft.com/ie/most/howto/trusted.htm"><B>http://www.microsoft.com/ie/most/howto/trusted.htm</B></A>
and follow some of the links from that page.</P>
<P>Probably the biggest difference between the ActiveX approach and the Java applet
approach is downloading. Java code is downloaded every time you load the page that
contains it. ActiveX code is downloaded once, unless you already have the control
installed some other way (perhaps a CD-ROM was sent to you in a magazine, for example)
and then never again. A copy is stored on the user's machine and entered in the Registry.
The Java code that is downloaded is small because most of the code involved is in
the Java Virtual Machine installed on your computer, probably as part of your browser.</P>
<P>The ActiveX code that's downloaded can be much larger, though the optimizations
discussed in the next section can significantly reduce the size by relying on DLLs
and other code already on the user's computer. If users come to this page once and
never again, they might be annoyed to find ActiveX controls cluttering their disk
and Registry. On the other hand, if they come to the same page repeatedly, they will
be pleased to find that there is no download time: The control simply activates and
runs.</P>
<P>There are still other differences. Java applets can't fire events to notify the
container that something has happened. Java applets can't be licensed and often don't
distinguish between design-time and runtime use. Java applets can't be used in Visual
Basic forms, VC++ programs, or Word documents in the same way that ActiveX controls
can. ActiveX controls are nearly 10 times faster than Java applets. In their favor,
Java applets are genuinely multiplatform and typically smaller than the equivalent
ActiveX control.</P>
<P>
<H2><A NAME="Heading5"></A>Using AppWizard to Create Faster ActiveX Controls</H2>
<P>Microsoft did not develop OCX controls to be placed in Web pages, and changing
their name to ActiveX controls didn't magically make them faster to load or smaller.
So the AppWizard that comes with Visual C++ has a number of options available to
achieve those ends. This chapter changes these options in the Dieroll control that
was already created, just to show how it's done. Because Dieroll is already a lean
control and loads quickly, these simple changes won't make much difference. It's
worth learning the techniques, though, for your own controls, which will surely be
fatter than Dieroll.</P>
<P>The first few options to reduce your control's size have always been available
on Step 2 of the ActiveX ControlWizard:</P>
<UL>
<LI>Activates When Visible
<P>
<LI>Invisible at Runtime
<P>
<LI>Available in Insert Object Dialog Box
<P>
<LI>Has an About Box
<P>
<LI>Acts as a Simple Frame Control
</UL>
<P>If you are developing your control solely for the Web, many of these settings
won't matter anymore. For example, it doesn't matter whether your control has an
About box; users won't be able to bring it up when they are viewing the control in
a Web page.</P>
<P>The Activates When Visible option is very important. Activating a control takes
a lot of overhead activity and should be postponed as long as possible so that your
control appears to load quickly. If your control activates as soon as it is visible,
you'll add to the time it takes to load your control. To deselect this option in
the existing Dieroll code, open the Dieroll project in Developer Studio if it isn't
still open, and open DierollCtl.cpp with FileView. Look for a block of code like
the one in Listing 20.5.</P>
<P>
<H4>Listing 20.5  Excerpt from DierollCtl.cpp--Setting Activates When Visible</H4>
<PRE>/////////////////////////////////////////////////////////////////////////////
// Control type information
static const DWORD BASED_CODE _dwDierollOleMisc =
OLEMISC_ACTIVATEWHENVISIBLE |
OLEMISC_SETCLIENTSITEFIRST |
OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE |
OLEMISC_RECOMPOSEONRESIZE;
</PRE>
<PRE>IMPLEMENT_OLECTLTYPE(CDierollCtrl, IDS_DIEROLL, _dwDierollOleMisc)
</PRE>
<P>Delete the OLEMISC_ACTIVATEWHENVISIBLE line. Build a release version of the application.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -