[[TIPS/Programming]]
* Visual C++ 2008 によるクリップボードからの画像取得サンプルプログラム [#ec8559bb]
[[TIPS/Programming/SerialCommunication]]

** 概略 [#n8b96206]
このアプリケーションは、Visual C++ 2008 でクリップボードにコピーされた
画像を読み出すためのサンプルプログラムです。
* Visual C++ 2008 を用いたシリアル通信サンプル [#n6aebadb]
----
** 概要 [#v1af7454]
このページは、Microsoft Visual C++ 2008 を用いて、シリアル通信を行うためのサンプルソフトです。
このサンプルプログラムは、下記の機能を持っています
- SerialPort コントロールを使う
- 一行ずつの、テキストデータの送信と受信
- 有効なポート名の列挙
- ポート名・ボーレートなどのリストボックスからの選択

** 基本動作・機能 [#v4837425]
このサンプルプログラムは、下記の機能を持っています。

- クリップボードにコピーされた画像を取り込み、jpegファイルに保存します。
- 保存ファイル名を自動で生成し、連続して画像を取り込み、jpegファイルに保存します。
- クリップボードに画像ファイルがコピーされたことを自動で検知し、上記動作を行います。
** 基本動作 [#ef495a83]
このサンプルプログラムは、下記のように動作します。
- 「接続」ボタンを押すと、ポート名・ボーレートなどの設定ダイアログを表示する。
- 設定ダイアログにて、上記情報を設定する。
- SerialPort コントロールに、必要な情報を設定する。
- テキストボックス上に文字列を入力し「送信」ボタンを押すと、データが送信される。
- シリアルデータを受信すると、割り込みが発生し受信バッファに受信データを格納。
- 受信した文字は、シリアルポート上にエコーバックされる。
- 改行文字を受信すると、テキストボックス上に受信した文字列を表示する。

** 技術 [#y01d7aff]
このサンプルプログラムは、下記のような技術的要素を使用しています。
●スクリーンショット
メイン画面とハイパーターミナル
#ref("http://www.altemasoft.com/image/programmingtips_serial_mainwindow.png")

- Windowsメッセージ受信
- クリップボードビューワ(ClipBoard Viewer)
- ビューワチェイン(Viewer Chain)
   
上記の技術的要素の説明は下記の通りです。
- クリップボードにデータが貼り付けられた場合、クリップボードビューワより、WM_DRAWCLIPBOARDメッセージが送られてくる。
- 仮想関数(WndProc)をオーバーライドして、WM_DRAWCLIPBOARDメッセージを受信
- WM_DRAWCLIPBOARDメッセージを、ビューワチェインを用いて、次のチェインに登録されたウィンドウに転送する。~
 ※1ビューワチェイン(Viewer Chain)とは、クリップボードを利用するウィンドウのリストです。~
 ※2クリップボードを利用する各アプリケーションは、それぞれが次のビューワチェインに登録されているウィンドウにWM_DRAWCLIPBOARDメッセージを転送する必要があります。
設定ダイアログ
#ref("http://www.altemasoft.com/image/programmingtips_serial_configwindow.png")

** 利用条件・著作権・転載などについて [#ecadab6b]

** 実行環境(私がディバッグしていた環境です) [#y04b95b2]
- OS: WindowsXP SP3
- 開発環境: Microsoft Visual C++ 2008 Express Edition

** 利用条件など [#l4a3180b]
このサンプルを使う上で、特に制限はございません。このソフトを使った事による損害などは、作者は一切関知しませんので、ご了承ください。

このサンプルを使って何らかのソフトを作って公開したり、業務で使用することにもとくに制限はございません。ただし、その場合は相互リンクなどで紹介していただけると嬉しいです。

** ダウンロード [#oa9333bd]
** ダウンロード [#d2272494]
下記のファイルをダウンロードしてください。
Visual C++ 2008 のサンプルプロジェクトを丸ごとZIPしています。ダウンロード後、解凍してソリューションファイルを開いてください。

[[SerialCommSample010.zip(19kB)>http://www.altemasoft.com/download/ClipBoardSample100.zip]]
[[SerialCommSample010.zip(3.1MB)>http://www.altemasoft.com/download/SerialCommSample010.zip]]

** ソースコード説明 [#t93f4d0e]
下記に、一部の重要なソースコードを示します。
** ソースコード一部説明 [#h0302cce]
ここでは、ソースコードの一部をかいつまんで説明します。詳細は、上記ファイルをダウンロードしてください。


	private: String^	GenerateSaveFileName(){
				 //日付と現在時刻からファイル名を生成。
				 DateTime^	dt = DateTime::Now;
				 return( dt->ToString("yyyyMMddHHmmss"));
			 }
	private: void	SavePictureToFile(){
				 //クリップボードから画像を取得し、JPEG形式で保存する。
				 System::Windows::Forms::IDataObject	^data = System::Windows::Forms::Clipboard::GetDataObject();
				 //クリップボード内にデータがあるかどうか。
					 if(data->GetDataPresent(DataFormats::Bitmap) == true)
					 {					 
						 if( (checkFileNameAutoGenerate->Checked == true) || (textFileName->Text == "")){
							textFileName->Text = GenerateSaveFileName();
							}
						 //クリップボードからデータをGETする。
						 pictureShowPicture->Image = (Image^)data->GetData(DataFormats::Bitmap);
						 //フォルダの最後の文字を "\" にする。
						 if( textFolderDestination->Text[textFolderDestination->Text->Length - 1] != '\\'){
							textFolderDestination->Text = textFolderDestination->Text + "\\";
						 }
						 //JPEG形式で保存
						pictureShowPicture->Image->Save(textFolderDestination->Text + textFileName->Text + ".jpg");
					 }
			 }
	private:
		/// <summary>
		/// 必要なデザイナ変数です。
		/// </summary>
		System::ComponentModel::Container ^components;
	private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
					 SavePictureToFile();				
				 }
	private: System::Void button1_Click_1(System::Object^  sender, System::EventArgs^  e) {
					 folderBrowserDialog->ShowDialog(this);
					 if(folderBrowserDialog->SelectedPath != ""){
						 textFolderDestination->Text = folderBrowserDialog->SelectedPath;
					 }
				 }
	private: System::Void Form1_Load(System::Object^  sender, System::EventArgs^  e) {
				//クリップボードビュワーに登録して、次のウィンドウのハンドルを得る。
				 this->m_hWndNext = ::SetClipboardViewer(static_cast<HWND>(this->Handle.ToPointer()));
			 }
	private: System::Void Form1_FormClosed(System::Object^  sender, System::Windows::Forms::FormClosedEventArgs^  e) {
				//クリップボードチェインから、自分自身を削除する。
				 ::ChangeClipboardChain(static_cast<HWND>(this->Handle.ToPointer()), this->m_hWndNext);
			 }
	public: virtual	System::Void WndProc(System::Windows::Forms::Message% m) override
			{//メッセージを受け取る。横取り?
				System::Windows::Forms::IDataObject	^data = System::Windows::Forms::Clipboard::GetDataObject();
				
				this->Form::WndProc(m);	//元の方も処理する。
				//クリップボード関連のメッセージを受け取る。
				switch(m.Msg)
				{
					//クリップボードにデータがコピーされた。
					case WM_DRAWCLIPBOARD:
							SavePictureToFile();
							//次のクリップボードチェインにメッセージを転送。
							::SendMessage(this->m_hWndNext, m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32());
						break;
					case WM_CHANGECBCHAIN:
							//クリップボードチェインが変更された。
							//削除されたのが自分の次のウィンドウなら、それをその次のウィンドウのハンドルで上書き。
							if(this->m_hWndNext == static_cast<HWND>(m.WParam.ToPointer())){
								this->m_hWndNext = static_cast<HWND>(m.LParam.ToPointer());
							}
							else if(this->m_hWndNext != NULL){
								::SendMessage(this->m_hWndNext, m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32());
							}
							break;
				}
*** SerialPort コントロールを用いた送受信 [#q4d7b19b]
 private: String^ COMRevieveBuffer; // 受信バッファ
 //デリゲートする。
 delegate void SerialDataRecievedDelegate(String^ recvData);
 private: void SerialDataRecieved(String^ recvData){
			//別スレッドで起動される関数。
			textRecieved->Text =  recvData;
		 }
 //シリアル受信割り込み。1バイト受信するごとに、この関数がよびだされる。
 private: System::Void serialPort_DataReceived(System::Object^  sender,  System::IO::Ports::SerialDataReceivedEventArgs^  e) {
			SerialDataRecievedDelegate^ dlgte = gcnew    SerialDataRecievedDelegate( this, &SerialCommSample::Form1::SerialDataRecieved );
			String^ RecievedData = serialPort->ReadExisting();
			//1バイトずつ受信することを前提
			if(serialPort->IsOpen == true) {	//シリアルポートが開いていることを確認してから。
			COMRevieveBuffer = COMRevieveBuffer + RecievedData; //受信バッファに追加
			//改行コードを検出する
			if(RecievedData == "\r" ) {			
				RecievedData = RecievedData + "\n";
				COMRevieveBuffer = COMRevieveBuffer + RecievedData;
				//受信した一行をテキストボックスに転送する。テキストボックスの操作は別スレッドの関数にする。
				this->Invoke(dlgte, COMRevieveBuffer);
				COMRevieveBuffer = "";
			}
			if(RecievedData == "\n" ) {
				RecievedData = RecievedData + "\n";
				COMRevieveBuffer = COMRevieveBuffer + RecievedData;
				//受信した一行をテキストボックスに転送する。テキストボックスの操作は別スレッドの関数にする。
				this->Invoke(dlgte, COMRevieveBuffer);
				COMRevieveBuffer = "";
			}
			//エコーを返す
			serialPort->Write(RecievedData);
		 }
	}
	
	 
 private: System::Void buttonTransmit_Click(System::Object^  sender, System::EventArgs^  e) {
		 if(serialPort->IsOpen == true) {
			 //シリアルポートが開いていることを確認してから。
			 serialPort->Write( textTransmit->Text + "\r\n" );
		 }
		 }



トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS