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

📄 ch07.htm

📁 用VC开发ACTIVEX书籍和随书源码- Develops the ACTIVEX books and along with the book source code with VC
💻 HTM
📖 第 1 页 / 共 5 页
字号:
<P><I>Drag and Drop</I> provides the user with the ability to transfer data between
two applications by means of a mouse only. The user selects the data to transfer,
holds down a mouse button on the selected data, drags the data to the location where
is it to be added, and releases the mouse button, thus dropping the data into the
new location. Drag and Drop support is similar in its implementation to Clipboard
support, and you will take full advantage of it in your implementa</P>
<P>Adding Clipboard and Drag and Drop support to a control can make even the simplest
implementations appear more professional and well-rounded.
<H3><A NAME="Heading21"></A>Clipboard Support</H3>
<P>The first step is deciding which keystrokes will be used to initiate the cut,
copy, or paste operation. Fortunately, the Windows operating system already has a
number of standards in this area. You will use Ctrl+X or Shift+Delete for Cut, Ctrl+C
or Ctrl+Insert for Copy, and Ctrl+V or Shift+Insert for Paste.</P>
<P>Open the ClassWizard and select the Message Maps tab for the <TT>CMFCControlWinCtrl</TT>
class. Double-click <TT>WM_KEYDOWN</TT> in the list of messages to add the <TT>OnKeyDown</TT>
function to your message map (see fig. 7.2). The <TT>OnKeyDown</TT> function is where
you are going to add your code to look for the keystroke combinations that will initiate
the Clipboard transfers. Double-click the <TT>OnKeyDown</TT> member function to close
the ClassWizard and open the source file for editing. <B><BR>
<BR>
</B><A HREF="Art/07/w_fig02.jpg"><B>FIG. 7.2</B></A> <I><BR>
Add the <TT>OnKeyDown</TT> message map with the ClassWizard.</I></P>
<P>Listing 7.15 shows the code that is added to <TT>OnKeyDown</TT> to support the
keystroke combinations listed in the preceding paragraph. The implementation is simple;
based on the particular state of the Ctrl or Shift keys and the correct keystroke,
the function either copies the data to or copies the data from the Clipboard.
<H3><A NAME="Heading22"></A>Listing 7.15 MFCCONTROLWINCTL.CPP--OnKeyDown Implementation</H3>
<P><FONT COLOR="#0066FF"><TT>void CMFCControlWinCtrl::OnKeyDown(UINT nChar, UINT
nRepCnt, UINT nFlags) <BR>
{<BR>
       BOOL bHandled = FALSE;<BR>
<BR>
       // find out if the shift key is being held down<BR>
       short sShift = ::GetKeyState(VK_SHIFT);<BR>
       // find out if the control key is being held down<BR>
       short sControl = ::GetKeyState(VK_CONTROL);<BR>
<BR>
       switch(nChar)<BR>
       {<BR>
       case 0x56: // `V'    // PASTE<BR>
       case 0x76: // `v' <BR>
               // if the control key is being held down<BR>
               if(sControl &amp; 0x8000)<BR>
               {<BR>
                      // get any text from the clipboard<BR>
                      this-&gt;GetDataFromClipboard();<BR>
                      // force the control to redraw itself<BR>
                      this-&gt;InvalidateControl(NULL);<BR>
                      // we don't need to pass this key to the base implementation<BR>
                      bHandled = TRUE;<BR>
               }<BR>
       case 0x43: // `C'    // COPY or PASTE<BR>
       case 0x63: // `c'                     <BR>
       case VK_INSERT:<BR>
               // if the control key is being held down<BR>
               if(sControl &amp; 0x8000)<BR>
               {<BR>
                       // copy the data to the clipboard<BR>
                       this-&gt;CopyDataToClipboard();<BR>
<BR>
                       // we don't need to pass this key to the base implementation<BR>
                       bHandled = TRUE;<BR>
               }<BR>
               // if the shift key is being held down it is a PASTE<BR>
               else if(sShift &amp; 0x8000 &amp;&amp; nChar == VK_INSERT)<BR>
               {<BR>
               // get any text from the clipboard<BR>
               this-&gt;GetDataFromClipboard();<BR>
<BR>
               // force the control to redraw itself<BR>
               this-&gt;InvalidateControl(NULL);<BR>
<BR>
               // we don't need to pass this key to the base implementation<BR>
               bHandled = TRUE;<BR>
               }<BR>
<BR>
       break;<BR>
       case 0x58: // `X'        // CUT<BR>
       case 0x78: // `x'<BR>
       case VK_DELETE:<BR>
               // if this is a shift delete OR CTRL-X/x<BR>
               if((nChar == VK_DELETE &amp;&amp; (sShift &amp; 0x8000)) || ((nChar
== 0x58                                   || nChar == 0x78) &amp;&amp; (sControl
&amp; 0x8000)))<BR>
               {<BR>
                       this-&gt;CopyDataToClipboard();<BR>
<BR>
                       // clear the string since this is a CUT operation<BR>
                       m_cstrCaption.Empty();<BR>
<BR>
                       // fire the global change event<BR>
                       this-&gt;FireChange();<BR>
<BR>
                       // force the control to repaint itself<BR>
                       this-&gt;InvalidateControl(NULL);<BR>
<BR>
                       // we don't need to pass this key to the base implementation<BR>
                       bHandled = TRUE;<BR>
                       }<BR>
       break;<BR>
       }<BR>
<BR>
       // if we didn't handle the character<BR>
       if(!bHandled)<BR>
       {<BR>
           // and the control key is not being held down<BR>
           if(!(sControl &amp; 0x8000))<BR>
                   // send to the default handler<BR>
                   COleControl::OnKeyDown(nChar, nRepCnt, nFlags);<BR>
       }<BR>
}</TT></FONT>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<P>In addition to the code that you added to trap the keystrokes, you also need to
add four methods, which you will examine in detail in the next section, for dealing
with the Clipboard transfers.</P>
<P><TT>CopyDataToClipboard</TT> will, as the name implies, get the data from the
control, and using the helper function, <TT>PrepareDataForTransfer</TT>, will package
the data and put it on the Clipboard.</P>
<P><TT>GetDataFromClipboard</TT> will open the Clipboard and look for data formats
that the control understands. Upon finding a suitable format, <TT>GetDataFromClipboard</TT>
will use the helper function <TT>GetDataFromTransfer</TT> to store the data in the
control.</P>
<P>The fact that the data transfer functions have been separated into two separate
methods for each type of transfer, to and from the Clipboard, and then further broken
down in each type of transfer into two separate steps will aid you when you enable
the control for Drag and Drop support. This is because the basic data transfer mechanism
is the same between the Clipboard and Drag and Drop and will allow you to rely on
a large portion of shared code for each implementation. <B><BR>
<BR>
Using Built-In Clipboard Formats</B><SPACER TYPE="HORIZONTAL" SIZE="10"><B> </B>The
Windows operating system defines a number of built-in data transfer formats for use
with the Clipboard. You see the formats in the following list:</P>


<BLOCKQUOTE>
	<P>CF_TEXT <BR>
	CF_BITMAP <BR>
	CF_METAFILEPICT <BR>
	CF_SYLK CF_DIF <BR>
	CF_TIFF CF_OEMTEXT<BR>
	CF_DIB CF_PALETTE <BR>
	CF_PENDATA <BR>
	CF_RIFF <BR>
	CF_WAVE <BR>
	CF_UNICODETEXT <BR>
	CF_ENHMETAFILE <BR>
	CF_HDROP <BR>
	CF_LOCALE <BR>
	CF_MAX <BR>
	CF_OWNERDISPLAY <BR>
	CF_DSPTEXT <BR>
	CF_DSPBITMAP <BR>
	CF_DSPMETAFILEPICT <BR>
	CF_DSPENHMETAFILE <BR>
	CF_GDIOBJFIRST <BR>
	CF_GDIOBJLAST

</BLOCKQUOTE>

<P>The first implementation of Clipboard data transfer will rely on the <TT>CF_TEXT</TT>
format. This is a general format for transferring non-UNICODE text data. There are
two aspects to using the Clipboard: being a Clipboard source and being a Clipboard
target. Being a Clipboard source refers to an application's capability to copy data
<I>to</I> the Clipboard. Being a Clipboard target refers to an application's capability
to copy data <I>from</I> the Clipboard. You will first learn how to enable a control
as a Clipboard source and then how to enable a control as a Clipboard target. <B><BR>
<BR>
Enabling a Control as a Clipboard Source </B><SPACER TYPE="HORIZONTAL" SIZE="10">A
<I>Clipboard source</I> is an application that puts data on the Clipboard for other
applications to copy. An application must support two COM interfaces, <TT>IDataObject</TT><B>
</B>and<B> </B><TT>IEnumFORMATETC</TT>, in order to qualify as a valid Clipboard
source. MFC provides the classes <TT>COleDataSource</TT><B> </B>and<B> </B><TT>COleDataObject</TT>,
which perform all of the work of implementing the interfaces for you. The <TT>OnKeyDown</TT>
implementation takes advantage of two helper functions, <TT>CopyDataToClipboard</TT>
and <TT>PrepareDataForTransfer</TT>, when copying data to the Clipboard. First you
need to add the two function prototypes to the <TT>CMFCControlWinCtrl</TT> class
(see Listing 7.16).
<H3><A NAME="Heading23"></A>Listing 7.16 MFCCONTROLWINCTL.H--Clipboard Source Support
Helper Function Prototypes</H3>
<P><FONT COLOR="#0066FF"><TT>. . .<BR>
       void CopyDataToClipboard(void);<BR>
       void PrepareDataForTransfer(COleDataSource * opOleDataSource);<BR>
};<BR>
. . .</TT></FONT>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<P><TT>CopyDataToClipboard</TT> uses the <TT>COleDataSource</TT> class provided by
MFC to connect to the Clipboard (see Listing 7.17). By calling the <TT>GetClipboardOwner</TT>
function, your implementation first checks to see whether you already have an object
on the Clipboard. <TT>GetClipboardOwner</TT> returns a pointer to a <TT>COleDataSource</TT>
object if the Clipboard contains a <TT>COleDataSource</TT> object that you had previously
set to the Clipboard using the <TT>SetClipboard</TT> function. If you are not the
owner of the Clipboard, the method returns <TT>NULL</TT>. If you didn't get a reference
to a <TT>COleDataSource</TT> object, you need to create one. Next you call the general
method <TT>PrepareDataForTransfer</TT> passing in your <TT>COleDataSource</TT> object,
which will copy the data from the control to the <TT>COleDataSource</TT> object.
The final thing you do is put the <TT>COleDataSource</TT> object on the Clipboard,
but only if you weren't the owner of the Clipboard at the time the transfer occurred.
Setting the Clipboard again with the same object will result in an error.
<H3><A NAME="Heading24"></A>Listing 7.17 MFCCONTROLWINCTL.CPP--CopyDataToClipboard
Implementation</H3>
<P><FONT COLOR="#0066FF"><TT>void CMFCControlWinCtrl::CopyDataToClipboard(void)<BR>
{<BR>
       // get the clipboard if we are the owner<BR>
       COleDataSource * opOleDataSource = COleDataSource::GetClipboardOwner();<BR>
       BOOL bSetClipboard = FALSE;<BR>
       // if we didn't get back a pointer<BR>
       if(opOleDataSource == NULL)<BR>
       {<BR>
               // if this is a new clipboard object<BR>
               bSetClipboard = TRUE;<BR>
               // get a new data source object<BR>
               opOleDataSource = new COleDataSource;<BR>
               }<BR>
       // call the common data preparation function<BR>
       this-&gt;PrepareDataForTransfer(opOleDataSource);<BR>
       // did we get a new clipboard object?<BR>
       if(bSetClipboard)<BR>
               // pass the data to the clipboard<BR>
               opOleDataSource-&gt;SetClipboard();<BR>
               }</TT></FONT>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<P><TT>PrepareDataForTransfer</TT> is used to create the necessary memory structures
and to prepare the <TT>COleDataSource</TT> object that will be used in the data transfer
(see Listing 7.18). For your data transfer, you are going to place the Caption on
the Clipboard using the Clipboard format <TT>CF_TEXT</TT>. In order to put the text
data on the Clipboard, you have to create a global memory object and copy the data
to it. After you create the global object, you store it in the <TT>COleDataSource</TT>
object using the <TT>CacheGlobalData</TT> function. Don't worry about cleaning up
any data that was previously set in the <TT>COleDataSource</TT> object; the <TT>CacheGlobalData</TT>
function will do that for you.
<H3><A NAME="Heading25"></A>Listing 7.18 MFCCONTROLWINCTL.CPP-- PrepareDataForTransfer
Implementation</H3>
<P><FONT COLOR="#0066FF"><TT>void CMFCControlWinCtrl::PrepareDataForTransfer(COleDataSource
*            <BR>
opOleDataSource)<BR>
{<BR>
       // get the length of the data to copy<BR>
       long lLength = m_cstrCaption.GetLength() + 1;<BR>
       // create a global memory object<BR>

⌨️ 快捷键说明

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