From: David Lowndes on
>What would be the problem with using accelerators in a stand-alone
>control?

You may not have the opportunity to use the accelerator mechanism -
which usually is done by calling TranslateAccelerator in the
application's message loop.

Dave
From: Joseph M. Newcomer on
See below...
On Fri, 21 May 2010 21:19:50 +0200, Oliver Regenfelder <oliver.regenfelder(a)gmx.at> wrote:

>Hello,
>
>Joseph M. Newcomer wrote:
>> There is no specific mechanism for doing this. And you need to understand what you will
>> do with the copied (not cut) information.
>
>Yes I meant copy not cut.
>
>> I tend to do this by subclassing the control and handling WM_KEYDOWN or WM_CHAR messages.
>> Ctrl+C is character code 0x03.
>
>Is it portable to use character code 0x03. In my solution I use KEYDOWN
>and KEYUP to keep track of the CTRL key and when c/C comes in while ctrl
>is pressed I call my OnCopy method.
>****
Probably unnecessary. I have no idea what you mean by "portable" because a Windows app
can only run on Windows and Windows-like clones (e.g. WINE) so there is no portability
issue. Whenever you suggest the work "portable" you imply that the application will run
on a non-Windows platform, and this is not going to happen.

By definition, character code 01 is Ctrl+A, 02==Ctrl+B, etc. These are not optional; this
is the DEFINITION of what these characters do. So I'd ignore trying to simulate the
action of the control key.
****

>> If what I want is text (suitable for pasting into Word, NotePad, etc.) then I will
>> typically loop over the selected entries (I usually do this when there is a multi-select
>> capability); essentially, I just extract the text in some useful form and just
>> concatenate each item with a CRLF sequence to form a multi-line string, then put that
>> string in the clipboard. For a list control, I would put a TAB between each column; not
>> the most elegant solution, but one which can work acceptably in a variety of contexts.
>> Your Mileage May Vary. You may just want to put spaces between, or do something else that
>> makes sense for your app. If I want to paste it into another list control in my app, I
>> might create a new clipboard format, CF_MYLISTCTRL, and register it; and in this, I will
>> create something interesting, perhaps just a sequence of lines separated by CRLF and
>> colums separated by tabs, and the PASTE operation will know how to handle this and do the
>> paste correctly.
>
>After I got the CTRL-C done I found out (with horror) about the
>clipboard. But I only need to cut text for now and although it is a
>ListCtrl the requirement is to only copy the items name so I do not
>have to deal with the columns (yet). But it is good to know about the
>problems in advance.
>
>I used the following code to access the clipboard:
>
>::OpenClipboard(NULL);
>
>ItemData *item_data = reinterpret_cast<ItemData*>(GetItemData(index));
****
What is in the ItemData field? You have not said.
****
>
>HANDLE hMem = ::GlobalAlloc(0
****
Why 0? For clipboard data, it is supposed to be GMEM_MOVEABLE!
****
> , (item_data->epc.GetLength() + 1)* sizeof(TCHAR));
****
WHy is the comma for the first parameter the first character of the second line?
****
>
>if(hMem == NULL) {
> ::CloseClipboard();
> return;
>}
>
>LPVOID lptstrCopy = ::GlobalLock(hMem);
****
If it is an LPVOID, why did you call it an lptstrCopy? Nonsense. Don't use Hungarian
Notation if you can't use it correctly! This is an incorrect usage. Just drop it
entirely, it is confusing and in this case misleading.
****
>::memcpy(lptstrCopy, item_data->epc, (item_data->epc.GetLength() + 1) *
>sizeof(TCHAR));
>::GlobalUnlock(hMem);
>
>::SetClipboardData(CF_TEXT, hMem);
****
As long as item_data->epc is a TCHAR array or CString, this will be correct. Otherwise, I
have no idea what you just put into the clipboard.

Where did you call ::EmptyClipboard?
****
>
>::CloseClipboard();
>
>
>It bothers me just now, when I am using CF_TEXT has this to be ASCII or
>unicode?
****
CF_TEXT will store the data in the format used by your app, and read about text
conversions on GetClipboardData. It will widen ANSI text if it needs Unicode and
down-convert (with possible errors) Unicode text if that's what is in the clipboard and it
needs ANSI
****
>
>> Think about "undo" if you implement "cut" rather than just "copy". I've found a one-level
>> undo is often sufficient (multi-level undo is complex and if you need it, be prepared to
>> do a lot of work)
>
>Luckily I do not need any cut so there is (not yet) any need for an
>undo.
****
I see this copies just a single selection. Nothing wrong with that, but if you ever allow
multiple select you will have to deal with that issue
joe
****
>
>Best regards,
>
>Oliver
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
From: Oliver Regenfelder on
Joseph M. Newcomer wrote:
> Probably unnecessary. I have no idea what you mean by "portable" because a Windows app
> can only run on Windows and Windows-like clones (e.g. WINE) so there is no portability
> issue. Whenever you suggest the work "portable" you imply that the application will run
> on a non-Windows platform, and this is not going to happen.

I think portable was a bad word to use. Will CTRL-C==03 hold on any version of windows
and with any locale character set?

As a first line of defense I have to say I copied that code from the MSDN almost
verbatim (for the Clippoard data bards).

>> ItemData *item_data = reinterpret_cast<ItemData*>(GetItemData(index));
> ****
> What is in the ItemData field? You have not said.
ItemData is a struct holding the data of each row.
struct ItemData {
...
CString epc;
...
};

> ****
>> HANDLE hMem = ::GlobalAlloc(0
> ****
> Why 0? For clipboard data, it is supposed to be GMEM_MOVEABLE!

Because MSDN hat it this way? Ok. I will change it. Are there any better
sources than MSDN on using the clipboard correctly?

> ****
>> , (item_data->epc.GetLength() + 1)* sizeof(TCHAR));
> ****
> WHy is the comma for the first parameter the first character of the second line?

In my opinion it is more readable, but that is a personal matter of coding style
I would say.

> ****
>> if(hMem == NULL) {
>> ::CloseClipboard();
>> return;
>> }
>>
>> LPVOID lptstrCopy = ::GlobalLock(hMem);
> ****
> If it is an LPVOID, why did you call it an lptstrCopy? Nonsense. Don't use Hungarian
> Notation if you can't use it correctly! This is an incorrect usage. Just drop it
> entirely, it is confusing and in this case misleading.

I copied it from the MSDN, and when it didn't compile (surprise) I only changed the
type to correct it. I wil remove the hungarian notation.

> ****
>> ::memcpy(lptstrCopy, item_data->epc, (item_data->epc.GetLength() + 1) *
>> sizeof(TCHAR));
>> ::GlobalUnlock(hMem);
>>
>> ::SetClipboardData(CF_TEXT, hMem);
> ****
> As long as item_data->epc is a TCHAR array or CString, this will be correct. Otherwise, I
> have no idea what you just put into the clipboard.

Sorry yes. item_data->epc is a CString.

> Where did you call ::EmptyClipboard?

I can not. I use
::OpenClipboard(NULL)
in that case the task itself holds the clipboard and you are not supposed to call
::EmptyClipboard(). This is a bad idea?

> CF_TEXT will store the data in the format used by your app, and read about text
> conversions on GetClipboardData.

So if I compile it as MBCS application it will automatically behave correctly and
if I later change it to be UNICODE then it will also automatically behave correctly.

Thanks,

Oliver
From: Joseph M. Newcomer on
See below...
On Sat, 22 May 2010 13:01:54 +0200, Oliver Regenfelder <oliver.regenfelder(a)gmx.at> wrote:

>Joseph M. Newcomer wrote:
>> Probably unnecessary. I have no idea what you mean by "portable" because a Windows app
>> can only run on Windows and Windows-like clones (e.g. WINE) so there is no portability
>> issue. Whenever you suggest the work "portable" you imply that the application will run
>> on a non-Windows platform, and this is not going to happen.
>
>I think portable was a bad word to use. Will CTRL-C==03 hold on any version of windows
>and with any locale character set?
****
Yes, because it is a character set standard. Ctrl+C=0x03 on any encoding, including
Unicode.
****
>
>As a first line of defense I have to say I copied that code from the MSDN almost
>verbatim (for the Clippoard data bards).
>
>>> ItemData *item_data = reinterpret_cast<ItemData*>(GetItemData(index));
>> ****
>> What is in the ItemData field? You have not said.
>ItemData is a struct holding the data of each row.
>struct ItemData {
> ...
> CString epc;
****
OK, that makes sense. Presumably this is a string which represents the entire row. I
would typically compute this string at the point I needed it, but then I'm lazy.
****
> ...
>};
>
>> ****
>>> HANDLE hMem = ::GlobalAlloc(0
>> ****
>> Why 0? For clipboard data, it is supposed to be GMEM_MOVEABLE!
>
>Because MSDN hat it this way? Ok. I will change it. Are there any better
>sources than MSDN on using the clipboard correctly?
****
Sadly, I find that many of the MSDN examples seem to have been written by summer interns
right after their "introduction to Windows programming" course. The kinds of errors they
contain are often newbie errors. I have no idea why 0 would be used.

All the examples I found under "Using the Clipboard" show GMEM_MOVEABLE
>
>> ****
>>> , (item_data->epc.GetLength() + 1)* sizeof(TCHAR));
>> ****
>> WHy is the comma for the first parameter the first character of the second line?
>
>In my opinion it is more readable, but that is a personal matter of coding style
>I would say.
>
>> ****
>>> if(hMem == NULL) {
>>> ::CloseClipboard();
>>> return;
>>> }
>>>
>>> LPVOID lptstrCopy = ::GlobalLock(hMem);
>> ****
>> If it is an LPVOID, why did you call it an lptstrCopy? Nonsense. Don't use Hungarian
>> Notation if you can't use it correctly! This is an incorrect usage. Just drop it
>> entirely, it is confusing and in this case misleading.
>
>I copied it from the MSDN, and when it didn't compile (surprise) I only changed the
>type to correct it. I wil remove the hungarian notation.
>
>> ****
>>> ::memcpy(lptstrCopy, item_data->epc, (item_data->epc.GetLength() + 1) *
>>> sizeof(TCHAR));
>>> ::GlobalUnlock(hMem);
>>>
>>> ::SetClipboardData(CF_TEXT, hMem);
>> ****
>> As long as item_data->epc is a TCHAR array or CString, this will be correct. Otherwise, I
>> have no idea what you just put into the clipboard.
>
>Sorry yes. item_data->epc is a CString.
>
>> Where did you call ::EmptyClipboard?
>
>I can not. I use
>::OpenClipboard(NULL)
>in that case the task itself holds the clipboard and you are not supposed to call
>::EmptyClipboard(). This is a bad idea?
****
No; typically you always specify a window, even if it is the main application window. It's
safer that way; I never opened a clipboard with a NULL handle. The problems arise if you
try to paste from another app, and I've long since forgotten the conditions under which
this fails (it is more widespread than failing to know who to call for WM_RENDERFORMAT and
friends, but it is Just One Of Those Things To Avoid)

But if you do OpenClipboard(NULL), you should not call EmptyClipboard, for the reasons
stated in the MSDN.
****
>
>> CF_TEXT will store the data in the format used by your app, and read about text
>> conversions on GetClipboardData.
>
>So if I compile it as MBCS application it will automatically behave correctly and
>if I later change it to be UNICODE then it will also automatically behave correctly.
>
****
Yes. The conversion table is under SetClipboardData, not GetClipboardData.
joe
****
>Thanks,
>
>Oliver
Joseph M. Newcomer [MVP]
email: newcomer(a)flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm