S
simon22
Guest
Summary: CRichEditCtrl::Copy() does a copy to the clipboard but does not close the clipboard on return. This is causing problems for me.
I am using a CRichEditCtrl in my application. When the user copies a selection to the clipboard, I want the control to do its default copy in all the standard formats that it supports, but I also want to add one clipboard format of my own. I use this internal format when pasting data within my application. But if the user pastes into a word-processor, I want the ordinary rich formats to be available.
I tried to implement it like this: when the user clicks a copy button (say) I call CRichEditCtrl::Copy(); to copy all the default formats, and I then call my own AddInternalClipboardFormat function to add my own format. This function does the following: it calls OpenClipboard, and if that succeeds, sets up the data and calls SetClipboardData to add it to the clipboard, and then calls CloseClipboard() again. I don't call 'EmptyClipboard' because I want to keep all the formats created by the previous call to CRichEditCtrl::Copy(). My function AddInternalClipboardFormat works perfectly if I call it on its own. It doesn't work if I call it after calling CRichEditCtrl::Copy(); because then the OpenClipboard() call fails. It returns false.
It's nothing special about my program. You can reproduce the issue very easily. Create an MFC dialog-based application and add a rich edit control (you will need to add a call to AfxInitRichEdit(); in the application's "InitInstance" function to get the dialog to load). Add a button to the dialog and in the button's handler function, add this code:
CRichEditCtrl *pCtrl = (CRichEditCtrl *)GetDlgItem(IDC_RICHEDIT21);
bool bOK;
bOK = OpenClipboard();
if (bOK)
CloseClipboard();
pCtrl->Copy();
bOK = OpenClipboard();
if (bOK)
CloseClipboard();
To test this, type some text into the rich edit control, select and press the button.
It seems to me that that the first time I tried this, both calls to "OpenClipboard" returned true. However, since then, the second call always returns false (even the first time I run the code in a new session), unless I comment out the call the "pCtrl->Copy" in which case both always return true. Maybe I hallucinated the initial apparently successful result.
For interest, if I added 2 or more calls to "pCtrl->Copy();" in succession, and run the code in a debugger, I get debug error messages saying "OpenClipboard" failed for the second and subsequent ones.
So - how am I supposed to do what I am trying to do? i.e. add an additional format to the clipboard when the user does a copy?
Well I have actually found a way of doing it, but it seems pretty nasty to me, and I don't like doing it like this. So if anyone has any thoughts about it, or a better suggestion, I will be glad to hear it. My solution is this:
I changed my AddInternalClipboardFormat function so that now, if OpenClipboard succeeds, it sets a bClose flag. But whether or not the call succeeds, it continues with the rest of the function and calls 'SetClipboardData' to add my format to the clipboard. Finally, if the bClose flag is set (and only if it is set), it calls CloseClipboard(). That appears to work. But I don't like it. Anyone got any better suggestions (and/or an explanation of what is going on and why the Rich Edit Control is not closing the clipboard)?
Of course one solution would be that I should give up on the Rich Edit Control for clipboard operations, and handle all the formats that it supports myself. But that's 9 different formats, including Rich Text Format, Rich Text Format Without Objects, RTF as Text, DataObject, Ole Private Data, and more. I really don't want to do that.
All help much appreciated.
Simon
Continue reading...
I am using a CRichEditCtrl in my application. When the user copies a selection to the clipboard, I want the control to do its default copy in all the standard formats that it supports, but I also want to add one clipboard format of my own. I use this internal format when pasting data within my application. But if the user pastes into a word-processor, I want the ordinary rich formats to be available.
I tried to implement it like this: when the user clicks a copy button (say) I call CRichEditCtrl::Copy(); to copy all the default formats, and I then call my own AddInternalClipboardFormat function to add my own format. This function does the following: it calls OpenClipboard, and if that succeeds, sets up the data and calls SetClipboardData to add it to the clipboard, and then calls CloseClipboard() again. I don't call 'EmptyClipboard' because I want to keep all the formats created by the previous call to CRichEditCtrl::Copy(). My function AddInternalClipboardFormat works perfectly if I call it on its own. It doesn't work if I call it after calling CRichEditCtrl::Copy(); because then the OpenClipboard() call fails. It returns false.
It's nothing special about my program. You can reproduce the issue very easily. Create an MFC dialog-based application and add a rich edit control (you will need to add a call to AfxInitRichEdit(); in the application's "InitInstance" function to get the dialog to load). Add a button to the dialog and in the button's handler function, add this code:
CRichEditCtrl *pCtrl = (CRichEditCtrl *)GetDlgItem(IDC_RICHEDIT21);
bool bOK;
bOK = OpenClipboard();
if (bOK)
CloseClipboard();
pCtrl->Copy();
bOK = OpenClipboard();
if (bOK)
CloseClipboard();
To test this, type some text into the rich edit control, select and press the button.
It seems to me that that the first time I tried this, both calls to "OpenClipboard" returned true. However, since then, the second call always returns false (even the first time I run the code in a new session), unless I comment out the call the "pCtrl->Copy" in which case both always return true. Maybe I hallucinated the initial apparently successful result.
For interest, if I added 2 or more calls to "pCtrl->Copy();" in succession, and run the code in a debugger, I get debug error messages saying "OpenClipboard" failed for the second and subsequent ones.
So - how am I supposed to do what I am trying to do? i.e. add an additional format to the clipboard when the user does a copy?
Well I have actually found a way of doing it, but it seems pretty nasty to me, and I don't like doing it like this. So if anyone has any thoughts about it, or a better suggestion, I will be glad to hear it. My solution is this:
I changed my AddInternalClipboardFormat function so that now, if OpenClipboard succeeds, it sets a bClose flag. But whether or not the call succeeds, it continues with the rest of the function and calls 'SetClipboardData' to add my format to the clipboard. Finally, if the bClose flag is set (and only if it is set), it calls CloseClipboard(). That appears to work. But I don't like it. Anyone got any better suggestions (and/or an explanation of what is going on and why the Rich Edit Control is not closing the clipboard)?
Of course one solution would be that I should give up on the Rich Edit Control for clipboard operations, and handle all the formats that it supports myself. But that's 9 different formats, including Rich Text Format, Rich Text Format Without Objects, RTF as Text, DataObject, Ole Private Data, and more. I really don't want to do that.
All help much appreciated.
Simon
Continue reading...