[Win32API] OpenClipboard 関数を複数回呼ぶと落ちてしまう

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kanov

[Win32API] OpenClipboard 関数を複数回呼ぶと落ちてしまう

#1

投稿記事 by kanov » 1週間前

Visual Studio 2017 で C++ を使っているのですが、クリップボードに文字列をコピーしようとしたら、
1度目は成功しますが2度目で必ず失敗してしまいます。

2度目にOpenClipboard (Win32API) を実行しようとしたところで(関数が戻ってくる前に)
"OpenClipboardに失敗しました(HRESULTからの例外: 0x800401D0 (CLIPBRD_E_CANT_OPEN))"
となってしまうのですが、どこが悪いのでしょうか???

コード:

#include <Windows.h>

bool SetClipboardTextW(const wchar_t *wtext) {
	HGLOBAL hMem = NULL;
	{
		size_t num_wchars = wcslen(wtext) + 1; // 終端文字含む
		size_t num_bytes = sizeof(wchar_t) * num_wchars;
		hMem = GlobalAlloc(GHND|GMEM_SHARE, num_bytes);
		wchar_t *ptr = (wchar_t *)GlobalLock(hMem);
		if (ptr) {
			wcscpy_s(ptr, num_bytes, wtext);
			ptr[num_bytes-1] = L'\0'; // wcscpy_sは終端文字も書き込むはずだが、念のため
			GlobalUnlock(hMem);
		}
	}
	if (OpenClipboard(NULL)) { // <--- ここで落ちる
		EmptyClipboard();
		SetClipboardData(CF_UNICODETEXT, hMem);
		CloseClipboard();
		return true; // GlobalFreeしてはいけない
	} else {
		GlobalFree(hMem);
		return false;
	}
}

int WINAPI WinMain(HINSTANCE hCurrInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	SetClipboardTextW(L"HELLO WORLD");
	SetClipboardTextW(L"HELLO WORLD"); // <--- これが成功しない
	return 0;
}


アバター
usao
記事: 1574
登録日時: 7年前

Re: [Win32API] OpenClipboard 関数を複数回呼ぶと落ちてしまう

#2

投稿記事 by usao » 1週間前

関係あるかどうかわかりませんが,
EmptyClipboardとかSetClipboardDataが成功しているかを戻り値でチェックしてみてはどうでしょうか.

msdnでOpenClipboardやEmptyClipboardの説明を見ると,そのような呼び方をするとSetClipboardDataが失敗する,と書かれているように見えます.

Bull
記事: 141
登録日時: 5年前

Re: [Win32API] OpenClipboard 関数を複数回呼ぶと落ちてしまう

#3

投稿記事 by Bull » 6日前

2カ所ほど修正すれば正常に動作するようです。
wcscpy_s() 関数の第二引数(numberOfElements )は文字数であってバイト数ではないです。
ptr[num_bytes - 1] = L'\0'; は必要ない上に確保したメモリ以外の領域に書込んでいます。

コード:

if (ptr) {
	wcscpy_s(ptr, num_wchars, wtext);
	GlobalUnlock(hMem);
}
とすると、当方の環境ではエラーがなくなりました。

返信

“C言語何でも質問掲示板” へ戻る