SetClipboardData

SetClipboardDataは、クリップボードにデータをセットする。

SetClipboardData function (winuser.h) - Win32 apps | Microsoft Docs

クリップボードの下準備の後、文字コード変換を挟んでから、ここに来たのは、どうもそのままではうまくクリップボードにセットできない問題が発生したためである。

					// Copyが選択された時.
					case ID_ITEM_COPY:

						// ID_ITEM_COPYブロック
						{

							// 変数の宣言
							BOOL bOpen;	// 開いたかどうかの結果bOpen.
							BOOL bEmpty;	// 空にできたかどうかの結果bEmpty.
							size_t len;	// 文字列の長さlen.
							size_t size;	// 文字列のサイズ.
							HGLOBAL hGlobal;	// グローバルハンドルhGlobal.
							PTSTR lptszText;	// PTSTR型テキスト.

							// クリップボードを開く.
							bOpen = OpenClipboard(hwnd);	// OpenClipboardでクリップボードを開く.
							if (bOpen){	// 成功.
								bEmpty = EmptyClipboard();	// EmptyClipboardでクリップボードを空にする.
								if (bEmpty){	// 成功.
									// メモリを確保.
									len = _tcslen(_T("あいうえお"));	// _T("あいうえお")の長さlen.
									size = len * sizeof(TCHAR);	// ワイド文字としてのサイズ.
									hGlobal = GlobalAlloc(GHND | GMEM_SHARE, size + 2);	// GlobalAllocでsize + 2(NULL文字分)のメモリ確保.
									lptszText = (PTSTR)GlobalLock(hGlobal);	// 確保
									_tcscpy(lptszText, _T("あいうえお"));	// コピー.
									GlobalUnlock(hGlobal);	// アンロック.
									SetClipboardData(CF_TEXT, hGlobal);	// SetClipboardDataでhGlobalをセット.
									CloseClipboard();	// CloseClipboardで閉じる.
								}
								else{	// 失敗.
									MessageBox(hwnd, _T("EmptyClipboard Failure!"), _T("SetClipboardData"), MB_OK | MB_ICONHAND);	// "EmptyClipboard Failure!"と表示.
								}
								CloseClipboard();	// CloseClipboardでクリップボードを閉じる.
							}
						}

						// 既定の処理へ向かう.
						break;	// breakで抜けて, 既定の処理(DefWindowProc)へ向かう.

このように、GlobalAllocで確保したメモリにそのまま格納してSetClipboardDataしても、

Copy
Copy

Copyの後、Ctrl+Vで、

文字化け
文字化け

こうなってしまう。

					// Copyが選択された時.
					case ID_ITEM_COPY:

						// ID_ITEM_COPYブロック
						{

							// 変数の宣言
							BOOL bOpen;	// 開いたかどうかの結果bOpen.
							BOOL bEmpty;	// 空にできたかどうかの結果bEmpty.
							HGLOBAL hGlobal;	// グローバルハンドルhGlobal.
							PTSTR ptszText;	// PTSTR型テキスト.
							HWND hEdit1;	// ID_EDIT1のハンドルhEdit1.
							int iLen;	// テキストの長さiLen.

							// テキストを取得.
							hEdit1 = GetDlgItem(hwnd, ID_EDIT1);	// ID_EDIT1のハンドルhEdit1を取得.
							iLen = GetWindowTextLength(hEdit1);	// テキストの長さを取得.
							hGlobal = GlobalAlloc(GHND | GMEM_SHARE, (iLen + 1) * 2);	// 長さ(iLen + 1) * 2のメモリを確保.
							ptszText = (PTSTR)GlobalLock(hGlobal);	// ロックしてptszText取得.
							TCHAR tszText[128] = {0};	// tszTextを{0}で初期化.
							GetWindowText(hEdit1, tszText, iLen + 1);	// テキストを取得.
							lstrcpy(ptszText, tszText);	// コピー.
							GlobalUnlock(hGlobal);	// アンロック.
							
							// クリップボードを開く.
							bOpen = OpenClipboard(hwnd);	// OpenClipboardでクリップボードを開く.
							if (bOpen){	// 成功.
								bEmpty = EmptyClipboard();	// EmptyClipboardでクリップボードを空にする.
								if (bEmpty){	// 成功.
									SetClipboardData(CF_TEXT, hGlobal);	// SetClipboardDataでhGlobalをテキストとしてクリップボードにコピー.
								}
								CloseClipboard();	// CloseClipboardでクリップボードを閉じる.
							}

						}

						// 既定の処理へ向かう.
						break;	// breakで抜けて, 既定の処理(DefWindowProc)へ向かう.

もちろん、エディットコントロールの中身をコピーしても、

ここから
ここから

ここから、

Copy
Copy

Copyで、

文字化け
文字化け

Ctrl+Vで文字化け。

面倒だけど、マルチバイトにしてからセットする。

この状態から
この状態から

この状態から、

Copy
Copy

Copyで、

Ctrl+Vで文字化けせずに貼り付けできた
Ctrl+Vで文字化けせずに貼り付けできた

Ctrl+Vで文字化けせずに貼り付けできた。

Sample/winapi/SetClipboardData/SetClipboardData/src/SetClipboardData at master · bg1bgst333/Sample · GitHub