2021年4月4日日曜日

17: WindowsクリップボードをC++で: マルチフォーマットにて

<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>

Win32 APIが使われます。'Bitmap'および'EnhancedMetafile'を含むあらゆるフォーマットがサポートされます。

話題


About: C++

この記事の目次


開始コンテキスト


  • 読者は、C++の基本的知識を持っている。

ターゲットコンテキスト



  • 読者は、C++にてフォーマット別データの複合体をWindowsクリップボードから取得し、そこへセットする方法を知る。

オリエンテーション


あらゆるフォーマットが、本テクニックによってサポートされています。

あらゆるフォーマットが、LinuxでのC++によるあるテクニックによってサポートされています、ある以降の記事にて紹介されるとおり。

多くの、しかし全てではない、フォーマットが、LinuxおよびMicrosoft Windows用のPythonによるあるテクニックによってサポートされています。

多くの、しかし全てではない、フォーマットが、Microsoft Windows用のC#によるあるテクニックによってサポートされています。


本体


1: 目的: あるワードプロセッサにマルチ・コピーバッファを実装する


Hypothesizer 7
私はVimをテキストエディターとして使っているが、その恩恵の1つは、それにはマルチ・コピーバッファがあるとういことだ: あるテキストをバッファ'a'へ、別のテキストをバッファ'b'へ、等コピーできる。それは、巨大な助けになる。

私はLibreOffice Writerをワードプロセッサとして使っているが、その機能をそれに欲しい。

実は、その機能をPythonにて実装しようとしたが、それは部分的には機能するが、理想的にではない。

そのテクニックについての2つの不満として、1) あり得るデータフォーマットが先験的に知られていなければならない 2) サポートされているデータフォーマットが限られている。

そこで、私はその機能をC#にて実装しようとし、それはより良く機能するが、理想的にではない。

そのテクニックについての不満は、サポートされているデータフォーマットがまだ限られていることだ。

結局のところ、私はWin32 APIを直接に使わなければならないようだ、Windowsクリップボードを十分に操作するためには。

もしも、当該Win32 API機能が満足のいくものであれば、私はそれをグローバルUNOサービスに組み込むことができ、それを私のPythonマクロが使用することになる。


2: Win32 APIクリップボード機能の基本事項


Hypothesizer 7
各データフォーマットは1つの番号によって同定され、そのフォーマットの名前は必ずしも取得できない、API的には。

例えば、'1'で同定されるフォーマット(それは'Text'フォーマットである)の名前は、'GetClipboardFormatNameA (UINT format, LPSTR lpszFormatName, int cchMaxCount)'ファンクションで取得することはできない。

しかしながら、そうしたフォーマットたちのそれぞれは固定された番号を持っており、その一方、他のフォーマットたちのそれぞれの番号は束の間のものである(そのフォーマットは、ある時にはある番号を持ち、別の時には別の番号を持つことを意味する)。

クリップボードは、'OpenClipboard (HWND hWndNewOwner)'および'CloseClipboard ()'というファイルで明示的にオープンされクローズされなければならない。

クリップボード内のフォーマット番号群は、'EnumClipboardFormats'ファンクションで列挙できる。

各フォーマットのデータへのハンドルは、the 'GetClipboardData (UINT uFormat)'ファンクションで取得できる。

各フォーマットのデータは必ずしもバイト群配列としてストレートな方法で取得できないことを知ることが重要だ。

例えば、'Bitmap'フォーマットに対して取得できるハンドルは、'HBITMAP'ハンドルであり、当該'Bitmap'データを取り出すには、特定のファンクション('GetObject (HANDLE h, int c, LPVOID pv)'のような)を使用しなければならない。

しかし、実際には、多くのフォーマットでは、データは、バイト群配列としてある共通の方法で(the 'GlobalLock (HGLOBAL hMem)'ファンクションを介して)取得することができる。

取っておいたデータをクリップボードへセットする場合も同様だ: 多くのフォーマットでは、データをある共通の方法('GlobalLock (HGLOBAL hMem)'が使用される)でセットできるが、他のもののそれぞれは特殊な操作を必要とする。

例えば、'Bitmap'データをセットするのに、私はthe 'CreateBitmapIndirect (const BITMAP *pbm)'ファンクションを使用する。

いずれにせよ、'SetClipboardData (UINT uFormat, HANDLE hMem)'が、結局のところ使用される。


3: 私のコード


Hypothesizer 7
私の目的はクリップボードデータのヒストリーを保存することなので、そのストレージとして、いくつかのクラスを私は作成した、以下のように。

theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDatum.hpp

@C++ ソースコード
#ifndef __theBiasPlanet_coreUtilities_clipboardHandling_ClipboardFormatSpecificDatum_hpp__
	#define __theBiasPlanet_coreUtilities_clipboardHandling_ClipboardFormatSpecificDatum_hpp__
	
	#include <string>
	#include "theBiasPlanet/coreUtilities/visualCplusplusSpecificHeaders/VisualCplusplusSpecificDefinitions.hpp"
	
	namespace theBiasPlanet {
		namespace coreUtilities {
			namespace clipboardHandling {
				class __theBiasPlanet_coreUtilities_symbolExportingOrImportingForVisualCplusplus__ ClipboardFormatSpecificDatum {
					private:
						::std::string i_formatName;
						unsigned int i_formatNumber;
						bool i_datumIsArray;
						int i_datumSize;
						void * i_datum;
					public:
						ClipboardFormatSpecificDatum ();
						ClipboardFormatSpecificDatum (::std::string const & a_formatName, unsigned int const & a_formatNumber, bool const & a_datumIsArray, int const & a_datumSize, void * const a_datum);
						virtual ~ClipboardFormatSpecificDatum ();
						ClipboardFormatSpecificDatum (ClipboardFormatSpecificDatum const & a_copiedObject) = delete; // because the datum is not meant to be shared by multiple instances
						virtual ClipboardFormatSpecificDatum & operator = (ClipboardFormatSpecificDatum const & a_assignedFromObject) = delete; // because the datum is not meant to be shared by multiple instances
						virtual ::std::string const & getFormatName () const;
						virtual unsigned int const & getFormatNumber () const;
						virtual int const & getDatumSize () const;
						virtual void * const getDatum () const;
				};
			}
		}
	}
#endif

theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDatum.cpp

@C++ ソースコード
#include "theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDatum.hpp"

namespace theBiasPlanet {
	namespace coreUtilities {
		namespace clipboardHandling {
			ClipboardFormatSpecificDatum::ClipboardFormatSpecificDatum () {
			}
			
			ClipboardFormatSpecificDatum::ClipboardFormatSpecificDatum (::std::string const & a_formatName, unsigned int const & a_formatNumber, bool const & a_datumIsArray, int const & a_datumSize, void * const a_datum): i_formatName (a_formatName), i_formatNumber (a_formatNumber), i_datumIsArray (a_datumIsArray), i_datumSize (a_datumSize), i_datum (a_datum) {
			}
			
			ClipboardFormatSpecificDatum::~ClipboardFormatSpecificDatum () {
				if (i_datumIsArray) {
					delete [] i_datum;
				}
				else {
					delete i_datum;
				}
			}
			
			::std::string const & ClipboardFormatSpecificDatum::getFormatName () const {
				return i_formatName;
			}
			
			unsigned int const & ClipboardFormatSpecificDatum::getFormatNumber () const {
				return static_cast <unsigned int const> (i_formatNumber);
			}
			
			int const & ClipboardFormatSpecificDatum::getDatumSize () const {
				return i_datumSize;
			}
			
			void * const ClipboardFormatSpecificDatum::getDatum () const {
				return i_datum;
			}
		}
	}
}

theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDataComposite.hpp

@C++ ソースコード
#ifndef __theBiasPlanet_coreUtilities_clipboardHandling_ClipboardFormatSpecificDataComposite_hpp__
	#define __theBiasPlanet_coreUtilities_clipboardHandling_ClipboardFormatSpecificDataComposite_hpp__
	
	#include <list>
	#include <string>
	#include "theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDatum.hpp"
	#include "theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.hpp"
	#include "theBiasPlanet/coreUtilities/visualCplusplusSpecificHeaders/VisualCplusplusSpecificDefinitions.hpp"
	
	using namespace ::theBiasPlanet::coreUtilities::collections;
	
	namespace theBiasPlanet {
		namespace coreUtilities {
			namespace clipboardHandling {
				class __theBiasPlanet_coreUtilities_symbolExportingOrImportingForVisualCplusplus__ ClipboardFormatSpecificDataComposite {
					private:
						NavigableLinkedMap <::std::string const, ClipboardFormatSpecificDatum const *> i_formatNameToDatumMap;
					public:
						ClipboardFormatSpecificDataComposite ();
						virtual ~ClipboardFormatSpecificDataComposite ();
						ClipboardFormatSpecificDataComposite (ClipboardFormatSpecificDataComposite const & a_copiedObject) = delete; // because the data are not meant to be shared by multiple instances
						virtual ClipboardFormatSpecificDataComposite & operator = (ClipboardFormatSpecificDataComposite const & a_assignedFromObject) = delete; // because the data are not meant to be shared by multiple instances
						virtual bool addFormatSpecificDatum (ClipboardFormatSpecificDatum const * const a_formatSpecificDatum);
						virtual ::std::list <::std::string> getFormatNames () const;
						virtual ClipboardFormatSpecificDatum const * const getFormatSpecificDatum (::std::string const & a_formatName) const;
				};
			}
		}
	}
#endif

theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDataComposite.cpp

@C++ ソースコード
#include "theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDataComposite.hpp"

namespace theBiasPlanet {
	namespace coreUtilities {
		namespace clipboardHandling {
			ClipboardFormatSpecificDataComposite::ClipboardFormatSpecificDataComposite () {
			}
			
			ClipboardFormatSpecificDataComposite::~ClipboardFormatSpecificDataComposite () {
				for (::std::pair <::std::string const, ClipboardFormatSpecificDatum const *> const & l_formatNameToDatumMapEntry: i_formatNameToDatumMap) {
					delete l_formatNameToDatumMapEntry.second;
				}
			}
			
			bool ClipboardFormatSpecificDataComposite::addFormatSpecificDatum (ClipboardFormatSpecificDatum const * const a_formatSpecificDatum) {
				i_formatNameToDatumMap [a_formatSpecificDatum->getFormatName ()] = a_formatSpecificDatum;
				return true;
			}
			
			::std::list <::std::string> ClipboardFormatSpecificDataComposite::getFormatNames () const {
				::std::list <::std::string> l_formatNames;
				for (::std::pair <::std::string const, ClipboardFormatSpecificDatum const *> const & l_formatNameToDatumMapEntry: i_formatNameToDatumMap) {
					l_formatNames.push_back (l_formatNameToDatumMapEntry.first);
				}
				return l_formatNames;
			}
			
			ClipboardFormatSpecificDatum const * const ClipboardFormatSpecificDataComposite::getFormatSpecificDatum (::std::string const & a_formatName) const {
				return i_formatNameToDatumMap.at (a_formatName);
			}
		}
	}
}

theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDataCompositesHistory.hpp

@C++ ソースコード
#ifndef __theBiasPlanet_coreUtilities_clipboardHandling_ClipboardFormatSpecificDataCompositesHistory_hpp__
	#define __theBiasPlanet_coreUtilities_clipboardHandling_ClipboardFormatSpecificDataCompositesHistory_hpp__
	
	#include "theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDataComposite.hpp"
	#include "theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.hpp"
	#include "theBiasPlanet/coreUtilities/visualCplusplusSpecificHeaders/VisualCplusplusSpecificDefinitions.hpp"
	
	using namespace ::theBiasPlanet::coreUtilities::collections;
	
	namespace theBiasPlanet {
		namespace coreUtilities {
			namespace clipboardHandling {
				class __theBiasPlanet_coreUtilities_symbolExportingOrImportingForVisualCplusplus__ ClipboardFormatSpecificDataCompositesHistory {
					private:
						NavigableLinkedMap <string const, ClipboardFormatSpecificDataComposite const *> i_dataCompositeKeyToDataCompositeMap;
					public:
						ClipboardFormatSpecificDataCompositesHistory ();
						virtual ~ClipboardFormatSpecificDataCompositesHistory ();
						ClipboardFormatSpecificDataCompositesHistory (ClipboardFormatSpecificDataCompositesHistory const & a_copiedObject) = delete; // because the data are not meant to be shared by multiple instances
						virtual ClipboardFormatSpecificDataCompositesHistory & operator = (ClipboardFormatSpecificDataCompositesHistory const & a_assignedFromObject) = delete; // because the data are not meant to be shared by multiple instances
						virtual bool addDataComposite (string const & a_dataCompositeKey, ClipboardFormatSpecificDataComposite const * const a_dataComposite);
						virtual bool removeDataComposite (string const & a_dataCompositeKey);
						virtual ClipboardFormatSpecificDataComposite const * const getDataComposite (string const & a_dataCompositeKey);
				};
			}
		}
	}
#endif

theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDataCompositesHistory.cpp

@C++ ソースコード
#include "theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDataCompositesHistory.hpp"

namespace theBiasPlanet {
	namespace coreUtilities {
		namespace clipboardHandling {
			ClipboardFormatSpecificDataCompositesHistory::ClipboardFormatSpecificDataCompositesHistory () {
			}
			
			ClipboardFormatSpecificDataCompositesHistory::~ClipboardFormatSpecificDataCompositesHistory () {
				for (::std::pair <string const, ClipboardFormatSpecificDataComposite const *> const & l_dataCompositeKeyToDataCompositeMapEntry: i_dataCompositeKeyToDataCompositeMap) {
					delete l_dataCompositeKeyToDataCompositeMapEntry.second;
				}
			}
			
			bool ClipboardFormatSpecificDataCompositesHistory::addDataComposite (string const & a_dataCompositeKey, ClipboardFormatSpecificDataComposite const * const a_dataComposite) {
				i_dataCompositeKeyToDataCompositeMap [a_dataCompositeKey] = a_dataComposite;
				return true;
			}
			
			bool ClipboardFormatSpecificDataCompositesHistory::removeDataComposite (string const & a_dataCompositeKey) {
				delete i_dataCompositeKeyToDataCompositeMap.at (a_dataCompositeKey);
				i_dataCompositeKeyToDataCompositeMap.erase (i_dataCompositeKeyToDataCompositeMap.find (a_dataCompositeKey));
				return true;
			}
			
			ClipboardFormatSpecificDataComposite const * const ClipboardFormatSpecificDataCompositesHistory::getDataComposite (string const & a_dataCompositeKey) {
				return i_dataCompositeKeyToDataCompositeMap.at (a_dataCompositeKey);
			}
		}
	}
}

クリップボード操作クラスは以下のものだ。

theBiasPlanet/coreUtilities/clipboardHandling/MicrosoftWindowsClipboard.hpp

@C++ ソースコード
#ifndef GCC
	#ifndef __theBiasPlanet_coreUtilities_clipboardHandling_MicrosoftWindowsClipboard_hpp__
		#define __theBiasPlanet_coreUtilities_clipboardHandling_MicrosoftWindowsClipboard_hpp__
		
		#include "theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDataComposite.hpp"
		#include "theBiasPlanet/coreUtilities/visualCplusplusSpecificHeaders/VisualCplusplusSpecificDefinitions.hpp"
		
		namespace theBiasPlanet {
			namespace coreUtilities {
				namespace clipboardHandling {
					class __theBiasPlanet_coreUtilities_symbolExportingOrImportingForVisualCplusplus__ MicrosoftWindowsClipboard {
						private:
						public:
							static bool openClipboard ();
							static bool closeClipboard ();
							static bool clearClipboard ();
							static ClipboardFormatSpecificDataComposite * const getFormatSpecificDataComposite ();
							static bool setFormatSpecificDataComposite (ClipboardFormatSpecificDataComposite const * const a_formatSpecificDataComposite);
					};
				}
			}
		}
	#endif
#endif

theBiasPlanet/coreUtilities/clipboardHandling/MicrosoftWindowsClipboard.cpp

@C++ ソースコード
#ifndef GCC
	#include <windows.h> // This has to be before the primary header file in order to avoid the conflict of the '::std::' namespace and the Win32 API namespace.
	#include "theBiasPlanet/coreUtilities/clipboardHandling/MicrosoftWindowsClipboard.hpp"
	#include "theBiasPlanet/coreUtilities/messagingHandling/Publisher.hpp"
	#include "theBiasPlanet/coreUtilities/stringsHandling/StringHandler.hpp"
	
	using namespace ::theBiasPlanet::coreUtilities::messagingHandling;
	using namespace ::theBiasPlanet::coreUtilities::stringsHandling;
	
	namespace theBiasPlanet {
		namespace coreUtilities {
			namespace clipboardHandling {
				bool MicrosoftWindowsClipboard::openClipboard () {
					return OpenClipboard (nullptr);
				}
				
				bool MicrosoftWindowsClipboard::closeClipboard () {
					return CloseClipboard ();
				}
				
				bool MicrosoftWindowsClipboard::clearClipboard () {
					return EmptyClipboard ();
				}
				
				ClipboardFormatSpecificDataComposite * const MicrosoftWindowsClipboard::getFormatSpecificDataComposite () {
					UINT l_datumFormatNumber = 0;
					int l_datumFormatNameMaximumSize = 100;
					HGLOBAL l_datumFormatNameGlobalMemoryArea = GlobalAlloc (GMEM_MOVEABLE, l_datumFormatNameMaximumSize);
					LPSTR l_datumFormatName = (LPSTR) GlobalLock (l_datumFormatNameGlobalMemoryArea);
					ClipboardFormatSpecificDataComposite * const l_formatSpecificDataComposite = new ClipboardFormatSpecificDataComposite ();
					while (true) {
						l_datumFormatNumber = EnumClipboardFormats (l_datumFormatNumber);
						if (l_datumFormatNumber == 0) {
							break;
						}
						if (l_datumFormatNumber == 1) {
							strcpy (l_datumFormatName, "Text");
						}
						else if (l_datumFormatNumber == 2) {
							strcpy (l_datumFormatName, "Bitmap");
						}
						else if (l_datumFormatNumber == 3) {
							strcpy (l_datumFormatName, "MetaFilePict");
						}
						else if (l_datumFormatNumber == 4) {
							strcpy (l_datumFormatName, "SymbolicLink");
						}
						else if (l_datumFormatNumber == 5) {
							strcpy (l_datumFormatName, "DataInterchangeFormat");
						}
						else if (l_datumFormatNumber == 7) {
							strcpy (l_datumFormatName, "OEMText");
						}
						else if (l_datumFormatNumber == 8) {
							strcpy (l_datumFormatName, "DeviceIndependentBitmap");
						}
						else if (l_datumFormatNumber == 13) {
							strcpy (l_datumFormatName, "UnicodeText");
						}
						else if (l_datumFormatNumber == 14) {
							strcpy (l_datumFormatName, "EnhancedMetafile");
						}
						else if (l_datumFormatNumber == 16) {
							strcpy (l_datumFormatName, "Locale");
						}
						else if (l_datumFormatNumber == 17) {
							strcpy (l_datumFormatName, "Format17");
						}
						else {
							strcpy (l_datumFormatName, "???");
							GetClipboardFormatNameA (l_datumFormatNumber, l_datumFormatName, l_datumFormatNameMaximumSize);
						}
						HANDLE l_formatSpecificDatumHandle = GetClipboardData (l_datumFormatNumber);
						if (l_formatSpecificDatumHandle != nullptr) {
							if (l_datumFormatNumber == 2) {
								HBITMAP l_formatSpecificDatumHandleForBitmap = (HBITMAP) l_formatSpecificDatumHandle;
								BITMAP * const l_copiedFormatSpecificDatumForBitmap = new BITMAP ();
								GetObject (l_formatSpecificDatumHandleForBitmap, sizeof (BITMAP), l_copiedFormatSpecificDatumForBitmap);
								l_formatSpecificDataComposite->addFormatSpecificDatum (new ClipboardFormatSpecificDatum (l_datumFormatName, l_datumFormatNumber, false, sizeof (BITMAP), l_copiedFormatSpecificDatumForBitmap));
							}
							else if (l_datumFormatNumber == 14) {
								HENHMETAFILE l_formatSpecificDatumHandleForEnhancedMetafile = (HENHMETAFILE) l_formatSpecificDatumHandle;
								int const l_formatSpecificDatumForEnhancedMetafileMaximumSize = 10000;
								::std::byte * const l_copiedFormatSpecificDatumForEnhancedMetafile = new ::std::byte [l_formatSpecificDatumForEnhancedMetafileMaximumSize];
								int const l_formatSpecificDatumForEnhancedMetafileSize (GetEnhMetaFileBits (l_formatSpecificDatumHandleForEnhancedMetafile, l_formatSpecificDatumForEnhancedMetafileMaximumSize, (LPBYTE) l_copiedFormatSpecificDatumForEnhancedMetafile));
								l_formatSpecificDataComposite->addFormatSpecificDatum (new ClipboardFormatSpecificDatum (l_datumFormatName, l_datumFormatNumber, true, l_formatSpecificDatumForEnhancedMetafileSize, l_copiedFormatSpecificDatumForEnhancedMetafile));
							}
							else {
								LPVOID l_formatSpecificDatumForUsualFormats = GlobalLock (l_formatSpecificDatumHandle);
								if (l_formatSpecificDatumForUsualFormats != nullptr) {
									SIZE_T l_formatSpecificDatumSizeForUsualFormats = GlobalSize (l_formatSpecificDatumHandle);
									::std::byte * const l_copiedFormatSpecificDatumForUsualFormats = new ::std::byte [l_formatSpecificDatumSizeForUsualFormats];
									::std::memcpy (l_copiedFormatSpecificDatumForUsualFormats, l_formatSpecificDatumForUsualFormats, l_formatSpecificDatumSizeForUsualFormats);
									l_formatSpecificDataComposite->addFormatSpecificDatum (new ClipboardFormatSpecificDatum (l_datumFormatName, l_datumFormatNumber, true, l_formatSpecificDatumSizeForUsualFormats, l_copiedFormatSpecificDatumForUsualFormats));
									GlobalUnlock (l_formatSpecificDatumHandle);
								}
								else {
									Publisher::logWarningInformation (StringHandler::format (::std::string ("The clipboard datum for the '%d' format could not be gotten."), (int) l_datumFormatNumber));
								}
							}
						}
						else {
							return false;
						}
					}
					GlobalUnlock (l_datumFormatNameGlobalMemoryArea);
					GlobalFree (l_datumFormatNameGlobalMemoryArea);
					return l_formatSpecificDataComposite;
				}
				
				bool MicrosoftWindowsClipboard::setFormatSpecificDataComposite (ClipboardFormatSpecificDataComposite const * const a_formatSpecificDataComposite) {
					for (::std::string const & l_datumFormatName: a_formatSpecificDataComposite->getFormatNames ()) {
						ClipboardFormatSpecificDatum const * const l_formatSpecificDatum (a_formatSpecificDataComposite->getFormatSpecificDatum (l_datumFormatName));
						if (l_datumFormatName == "Bitmap") {
							BITMAP const * const l_copiedFormatSpecificDatumForBitmap = (BITMAP const * const) (l_formatSpecificDatum->getDatum ());
							HBITMAP l_formatSpecificDatumHandleForBitmap = CreateBitmapIndirect (l_copiedFormatSpecificDatumForBitmap);
							HANDLE l_formatSpecificDatumHandle = SetClipboardData (l_formatSpecificDatum->getFormatNumber (), l_formatSpecificDatumHandleForBitmap);
						}
						else if (l_datumFormatName == "EnhancedMetafile") {
							LPBYTE const l_copiedFormatSpecificDatumForEnhancedMetafile = (LPBYTE const) (l_formatSpecificDatum->getDatum ());
							HENHMETAFILE l_formatSpecificDatumHandleForEnhancedMetafile = SetEnhMetaFileBits (l_formatSpecificDatum->getDatumSize (), l_copiedFormatSpecificDatumForEnhancedMetafile);
							HANDLE l_formatSpecificDatumHandle = SetClipboardData (l_formatSpecificDatum->getFormatNumber (), l_formatSpecificDatumHandleForEnhancedMetafile);
						}
						else {
							::std::byte const * const l_copiedFormatSpecificDatumForUsualFormats = (::std::byte const * const) (l_formatSpecificDatum->getDatum ());
							HGLOBAL l_formatSpecificDatumForUsualFormatsGlobalMemoryArea = GlobalAlloc (GMEM_MOVEABLE, l_formatSpecificDatum->getDatumSize ());
							LPBYTE l_formatSpecificDatumForUsualFormats = (LPBYTE) GlobalLock (l_formatSpecificDatumForUsualFormatsGlobalMemoryArea);
							::std::memcpy (l_formatSpecificDatumForUsualFormats, l_copiedFormatSpecificDatumForUsualFormats, l_formatSpecificDatum->getDatumSize ());
							GlobalUnlock (l_formatSpecificDatumForUsualFormatsGlobalMemoryArea);
							HANDLE l_formatSpecificDatumHandle = SetClipboardData (l_formatSpecificDatum->getFormatNumber (), l_formatSpecificDatumForUsualFormatsGlobalMemoryArea);
						}
					}
					return true;
				}
			}
		}
	}
#endif

私は、特殊な扱いを必要とするデータフォーマットとして、'Bitmap'および'EnhancedMetafile'にのみ気づいたが、もしも、他のものにも気づいたら、それらにも対処しなければならないだろう。


4: テストする


Hypothesizer 7
私のテストコードは、以下のものだ。

theBiasPlanet/coreUtilitiesTests/clipboardHandlingTest1/Test1Test.hpp

@C++ ソースコード
#include <string>

using namespace ::std;

namespace theBiasPlanet {
	namespace coreUtilitiesTests {
		namespace clipboardHandlingTest1 {
			class Test1Test {
				public:
					static int main (int const & a_argumentsNumber, char const * const a_argumentsArray []);
					static void test ();
			};
		}
	}
}

theBiasPlanet/coreUtilitiesTests/clipboardHandlingTest1/Test1Test.cpp

@C++ ソースコード
#include "theBiasPlanet/coreUtilitiesTests/clipboardHandlingTest1/Test1Test.hpp"
#include <iostream>
#include <list>
#include "theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDataComposite.hpp"
#include "theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDataCompositesHistory.hpp"
#include "theBiasPlanet/coreUtilities/clipboardHandling/ClipboardFormatSpecificDatum.hpp"
#include "theBiasPlanet/coreUtilities/clipboardHandling/MicrosoftWindowsClipboard.hpp"
#include "theBiasPlanet/coreUtilities/messagingHandling/Publisher.hpp"
#include "theBiasPlanet/coreUtilities/stringsHandling/StringHandler.hpp"

using namespace ::std;
using namespace  ::theBiasPlanet::coreUtilities::clipboardHandling;
using namespace  ::theBiasPlanet::coreUtilities::messagingHandling;
using namespace  ::theBiasPlanet::coreUtilities::stringsHandling;

namespace theBiasPlanet {
	namespace coreUtilitiesTests {
		namespace clipboardHandlingTest1 {
			int Test1Test::main (int const & a_argumentsNumber, char const * const a_argumentsArray []) {
				Publisher::setLoggingLevel (3);
				test ();
				return 0;
			}
			
			void Test1Test::test () {
				ClipboardFormatSpecificDataCompositesHistory l_clipbardFormatSpecificDataCompositesHistory;
				while (true) {
					cout << "### Input 'S' (Set), 'G' (Get), 'D (Display)', or 'Q' (Quit):" << endl << flush;
					string l_userInput;
					getline (cin, l_userInput);
					string l_clipboardFormatSpecificDataCompositeKey;
					if (l_userInput == string ("S") || l_userInput == string ("G") || l_userInput == string ("D")) {
						cout << "### Input the key:" << endl << flush;
						getline (cin, l_clipboardFormatSpecificDataCompositeKey);
						if (l_userInput == string ("S")) {
#ifndef GCC
							MicrosoftWindowsClipboard::openClipboard ();
							MicrosoftWindowsClipboard::clearClipboard ();
							MicrosoftWindowsClipboard::setFormatSpecificDataComposite (l_clipbardFormatSpecificDataCompositesHistory.getDataComposite (l_clipboardFormatSpecificDataCompositeKey));
							MicrosoftWindowsClipboard::closeClipboard ();
#endif
						}
						else if (l_userInput == string ("G")) {
#ifndef GCC
							MicrosoftWindowsClipboard::openClipboard ();
							l_clipbardFormatSpecificDataCompositesHistory.addDataComposite (l_clipboardFormatSpecificDataCompositeKey, MicrosoftWindowsClipboard::getFormatSpecificDataComposite ());
							MicrosoftWindowsClipboard::closeClipboard ();
#endif
						}
						else if (l_userInput == string ("D")) {
							ClipboardFormatSpecificDataComposite const * const l_clipboardFormatSpecificDataComposite = l_clipbardFormatSpecificDataCompositesHistory.getDataComposite (l_clipboardFormatSpecificDataCompositeKey);
							list <string> l_clipboardDatumFormatNames = l_clipboardFormatSpecificDataComposite->getFormatNames ();
							for (string const & l_clipboardDatumFormatName: l_clipboardDatumFormatNames) {
								ClipboardFormatSpecificDatum const * const l_clipboardFormatSpecificDatum = l_clipboardFormatSpecificDataComposite->getFormatSpecificDatum (l_clipboardDatumFormatName);
								cout <<  StringHandler::format (string ("### clipboard datum format number, format name, size: %d, %s, %d"), (int) l_clipboardFormatSpecificDatum->getFormatNumber (), l_clipboardDatumFormatName, l_clipboardFormatSpecificDatum->getDatumSize ()) << endl << flush;
							}
						}
					}
					else {
						break;
					}
				}
			}
		}
	}
}

あるテキストをある'cmd'ターミナル上でコピーした後、'G' -> 'A' -> 'D' -> 'A'というインプットに対して、以下のようなアウトプットを得る。

@出力
### clipboard datum format number, format name, size: 13, UnicodeText, 12
### clipboard datum format number, format name, size: 16, Locale, 4
### clipboard datum format number, format name, size: 1, Text, 6
### clipboard datum format number, format name, size: 7, OEMText, 6

C#版の結果と比較すると、基本的に同じ結果が見える。

あるテキストをLibreOffice Writerインスタンス上でコピーした後、'G' -> 'A' -> 'D' -> 'A'というインプットに対して、以下のようなアウトプットを得る。

@出力
### clipboard datum format number, format name, size: 49161, DataObject, 8
### clipboard datum format number, format name, size: 49937, Star Embed Source (XML), 5946
### clipboard datum format number, format name, size: 49306, Rich Text Format, 2192
### clipboard datum format number, format name, size: 49946, Richtext Format, 2192
### clipboard datum format number, format name, size: 49948, HTML (HyperText Markup Language), 641
### clipboard datum format number, format name, size: 49412, HTML Format, 900
### clipboard datum format number, format name, size: 13, UnicodeText, 8
### clipboard datum format number, format name, size: 1, Text, 4
### clipboard datum format number, format name, size: 49949, Link, 44
### clipboard datum format number, format name, size: 49950, Star Object Descriptor (XML), 81
### clipboard datum format number, format name, size: 49171, Ole Private Data, 552
### clipboard datum format number, format name, size: 16, Locale, 4
### clipboard datum format number, format name, size: 7, OEMText, 4

C#版の結果と比較すると、そこには、より多くのデータフォーマット(「DataObject」、「Ole Private Data」、「Locale」、「OEMText」)が見える。


参考資料


<このシリーズの前の記事 | このシリーズの目次 | このシリーズの次の記事>