2008年4月24日木曜日

VC++2005/2008 コンボボックスの使用方法

VC++2005/2008 コンボボックスの使用方法
コンボボックスはテキストボックスとリストボックスを組合わせた便利なコンポーネントです。おもな使用方法を示します。

array<System::String^>^ arr = gcnew array<System::String^>{"bbb","ccc"}; // 配列宣言

comboBox1->Items->Clear(); // コンボボックスのアイテムクリア
comboBox1->Items->Add( "aaa" ); // コンボボックスにアイテム1つ追加
comboBox1->Items->AddRange( arr ); // コンボボックスにアイテムまとめて追加
comboBox1->Text = String::Format("{0} : {1}",comboBox1->Items->Count , comboBox1->Items[0] ); // コンボボックスのテキスト表示

2008年4月23日水曜日

VC++2005/2008 .NET SerialPort を使用する方法

VC++2005/2008 .NET SerialPort を使用する方法

.NET の SerialPort を使用してシリアル送受信する方法を示します。
SerialPort はそのまま使うよりクラス(CUartクラス)にラップするほうがすっきりします。
シリアル受信はスレッドで行い、受信データをデリゲート渡しにしてテキストボックスに表示します。

■■ Uart.h (CUartクラス) ■■■■■■■■■■■■■■■■■■■■■■■
#pragma once
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
using namespace System::IO::Ports; // シリアルポート

#define BUF_SIZE 10

ref class CUart
{
///------------------------------------------------
/// テーブル宣言
///------------------------------------------------
public: SerialPort^ port;
public: System::String^ nowPort;

///------------------------------------------------
/// コンストラクタ
///------------------------------------------------
public:CUart()
{
nowPort = "----"; // 現在ポート名クリア
port = gcnew SerialPort(); // シリアルポートインスタンス化
}
///------------------------------------------------
/// オープン可能ポート調査
///------------------------------------------------
public: System::String^ portInvestigation()
{
String^ na = nowPort;
if( na != "----" ){ // 現在ポートオープン中のとき
port->Close(); // ポートクローズ
}
array<String^>^ ports = SerialPort::GetPortNames(); // 全ポート名取得
ports->Sort( ports ); // 並び替え
char ct = ports->Length::get();

array<String^>^ names = gcnew array<String^>(ct); // 利用可能なポート名取得
char cnt = 0;
for(char ii=0; ii<ct; ii++)
{
if( portOpenTest( ports[ii] ) == true ){ // オープンに成功したとき
names[cnt++] = ports[ii]; // ポート名取得
}
}

char flg = 0;
if( nowPort == "----" ){
flg = 1;
}
for(char ii=0; ii<cnt; ii++)
{
if( names[ii] == nowPort ){ // 現在のポートと同じ時
flg = 1;
}
else{
if( flg == 1 ){
nowPort = names[ii];
break;
}
}
}

if( na == nowPort ){
nowPort = "----";
}
return nowPort;
}
///------------------------------------------------
/// ポートオープンテスト
///------------------------------------------------
private: bool portOpenTest( System::String^ name )
{
port->Close();
bool result = portOpen( name );
port->Close();
return result;
}
///------------------------------------------------
/// ポートオープン
/// SerialPort port = new SerialPort(COM4, 9600, Parity.None, 8, StopBits.One);
///------------------------------------------------
public: bool portOpen( System::String^ name )
{
System::String^ err = "";
port->PortName = name; // ポート名設定
port->BaudRate = 9600;
port->Parity = Parity::None;
port->StopBits = StopBits::One;
try
{
port->Open(); // ポートオープン
}
catch(Exception^ e)
{
err = System::String::Format("{0}",e);
}
if( err == "" ){
return true;
}
else{
return false;
}
}
///------------------------------------------------
/// 送信
///------------------------------------------------
public: void write( array<unsigned char>^ buffer, int offset, int count )
{
port->Write( buffer , offset , count );
}
///------------------------------------------------
/// 受信
///------------------------------------------------
public: void read( array<unsigned char>^ buffer, int offset, int count )
{
System::String^ err = "";
try
{
port->Read( buffer , offset , count );
}
catch(Exception^ e)
{
err = System::String::Format("{0}",e);
}
}
///------------------------------------------------
/// オープンしているかどうか
///------------------------------------------------
public: bool isOpen()
{
return port->IsOpen::get();
}
///------------------------------------------------
};
■■ Form1.h ■■■■■■■■■■■■■■■■■■■■■■■
※必要な部分だけを記載しています。
///------------------------------------------
/// ■インクリュード宣言
///------------------------------------------
#include "Uart.h"
///------------------------------------------
/// ■変数宣言
///------------------------------------------
private: CUart^ uart;
private: array<unsigned char>^ buff;
private: bool RxLoopFlg;
///------------------------------------------
/// ■ボタン1
/// シリアルポート設定(変更)
///------------------------------------------
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
String^ com = uart->portInvestigation();
if( com == "----" ){
textBox1->Text = com;
RxLoopFlg = false;
}
else{
if( uart->portOpen(com) == true ){
textBox1->Text = com;
RxLoopFlg = true;
}
else{
textBox1->Text = "失敗";
RxLoopFlg = false;
}
}
}
///------------------------------------------
/// ■ボタン2
/// シリアル送信(適当な値を送信)
///------------------------------------------
private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {
array<unsigned char>^ buff = gcnew array<unsigned char>(BUF_SIZE);
for(char ii=0 ; ii<BUF_SIZE; ii++){
buff[ii] = 0x30 + ii;
}
uart->write( buff , 0 , BUF_SIZE);
}
///------------------------------------------
/// ■フォームロード
///------------------------------------------
private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
RxLoopFlg = false;
buff = gcnew array<unsigned char>(BUF_SIZE); // シリアル受信バッファ領域宣言
buff->Clear(buff,0,BUF_SIZE); // シリアル受信バッファクリア
uart = gcnew CUart(); // シリアルポートインスタンス
button1_Click(sender,e); // シリアルポート設定(変更)
backgroundWorker1->RunWorkerAsync(); // スレッド開始(シリアル受信)
}
///------------------------------------------
/// ■デリゲート
/// ■テキストボックスセット
///------------------------------------------
delegate void SetTextCallback(array<unsigned char>^ buff);
private: void SetText_A(array<unsigned char>^ buff){
if( this->textBox2->InvokeRequired ){
SetTextCallback^ d = gcnew SetTextCallback(this, &at3200::Form1::SetText_A);
this->BeginInvoke( d, buff );
}
else{
unsigned char bf[BUF_SIZE];
for(char ii=0; ii<BUF_SIZE; ii++){
bf[ii] = buff[ii];
}
buff->Clear(buff,0,BUF_SIZE); // シリアル受信バッファクリア
// this->textBox2->Text += System::Runtime::InteropServices::Marshal::PtrToStringAnsi((IntPtr)bf);
this->textBox2->AppendText(System::Runtime::InteropServices::Marshal::PtrToStringAnsi((IntPtr)bf));
}
}
///------------------------------------------
/// ■スレッド1
///------------------------------------------
private: System::Void backgroundWorker1_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) {
while(1){
if( RxLoopFlg == true ){
if( uart->isOpen() == true ){
uart->read( buff , 0 , BUF_SIZE ); // シリアル受信
SetText_A( buff );
}
else{
}
}
else{
}
}
}
■■ Form1.h の終わり ■■■■■■■■■■■■■■■■■■

2008年4月15日火曜日

VC++2005/2008 シリアルポートを使用する

VC++2005/2008 シリアルポートを使用する

ボタン1を押すと、listBox1に全ポート名、listBox2に使用可能なポート名を表示します。

[ツールボックス]->[コンポーネント]->[SerialPort]を貼り付けて、以下のソースを使用します。


using namespace System::IO::Ports; // シリアルポート


public: SerialPort port; // シリアルポート宣言


private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {

listBox1->Items->Clear(); // リストボックス1初期化
array<System::String^>^ names = SerialPort::GetPortNames(); // ポート名取得
listBox1->Items->AddRange( names ); // リストボックス1へ出力する
// listBox1->Items->AddRange( SerialPort::GetPortNames() );

listBox2->Items->Clear(); // リストボックス2初期化
for(char ii=0; iiItems->Count; ii++)
{
System::String^ name;
try
{
name = listBox1->Items[ii]->ToString();
port.PortName = name;
port.Open();
}
catch(Exception^ e)
{
name = System::String::Format("{0}",e);
}
finally
{
port.Close();
if( name != "" )
{
listBox2->Items->Add(name);
}
}
}
}
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
できるだけ詳しく記述しました。よろしくお願いします。
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
(1)プロジェクトを simpleUart という名前で新規作成します。
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

■[ファイル]→[新規作成]→[プロジェクト]→ simpleUart

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
(2)Form1 にツールボックスの以下のコントロールを配置し、イベントハンドラを作成します。
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

①Button1 (コモンコントロール)
②ListBox1 (コモンコントロール)
③ListBox2 (コモンコントロール)
④serialPort1 (コンポーネント)
⑤Button1のイベントハンドラを作成します。(Button1ダブルクリックで "button1_Click"を作成します)

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
(3)Form.h の全ソースコードを以下に示します。
↓追加 ~↑追加で囲まれた部分がデフォルトから追加したところを示します。
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
// ソースコードの始まり
// ■注意■ ">"と"<"は全角なので半角に置換してください。
// (半角ではHTML表示で問題があるため)

#pragma once


namespace simpleUart {

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
// ■■■■■■■■■■■■■■■■■↓追加
using namespace System::IO::Ports; // シリアルポート
// ■■■■■■■■■■■■■■■■■↑追加

/// <summary>
/// Form1 の概要
///
/// 警告: このクラスの名前を変更する場合、このクラスが依存するすべての .resx ファイルに関連付けられた
/// マネージ リソース コンパイラ ツールに対して 'Resource File Name' プロパティを
/// 変更する必要があります。この変更を行わないと、
/// デザイナと、このフォームに関連付けられたローカライズ済みリソースとが、
/// 正しく相互に利用できなくなります。
/// </summary>
public ref class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
//
//TODO: ここにコンストラクタ コードを追加します
//
}

protected:
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
~Form1()
{
if (components)
{
delete components;
}
}
private: System::IO::Ports::SerialPort^ serialPort1;
protected:
private: System::Windows::Forms::ListBox^ listBox1;
private: System::Windows::Forms::ListBox^ listBox2;
private: System::Windows::Forms::Button^ button1;
private: System::ComponentModel::IContainer^ components;

private:
/// <summary>
/// 必要なデザイナ変数です。
/// </summary>
// ■■■■■■■■■■■■■■■■■↓追加
public: SerialPort port; // シリアルポート宣言
// ■■■■■■■■■■■■■■■■■↑追加


#pragma region Windows Form Designer generated code
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
void InitializeComponent(void)
{
this->components = (gcnew System::ComponentModel::Container());
this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
this->listBox1 = (gcnew System::Windows::Forms::ListBox());
this->listBox2 = (gcnew System::Windows::Forms::ListBox());
this->button1 = (gcnew System::Windows::Forms::Button());
this->SuspendLayout();
//
// listBox1
//
this->listBox1->FormattingEnabled = true;
this->listBox1->ItemHeight = 12;
this->listBox1->Location = System::Drawing::Point(13, 43);
this->listBox1->Name = L"listBox1";
this->listBox1->Size = System::Drawing::Size(106, 76);
this->listBox1->TabIndex = 0;
//
// listBox2
//
this->listBox2->FormattingEnabled = true;
this->listBox2->ItemHeight = 12;
this->listBox2->Location = System::Drawing::Point(144, 43);
this->listBox2->Name = L"listBox2";
this->listBox2->Size = System::Drawing::Size(106, 76);
this->listBox2->TabIndex = 1;
//
// button1
//
this->button1->Location = System::Drawing::Point(13, 10);
this->button1->Name = L"button1";
this->button1->Size = System::Drawing::Size(85, 22);
this->button1->TabIndex = 2;
this->button1->Text = L"button1";
this->button1->UseVisualStyleBackColor = true;
this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
//
// Form1
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 12);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(292, 266);
this->Controls->Add(this->button1);
this->Controls->Add(this->listBox2);
this->Controls->Add(this->listBox1);
this->Name = L"Form1";
this->Text = L"Form1";
this->ResumeLayout(false);

}
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
// ■■■■■■■■■■■■■■■■■↓追加
listBox1->Items->Clear(); // リストボックス1初期化
array<System::String^>^ names = SerialPort::GetPortNames(); // ポート名取得
listBox1->Items->AddRange( names ); // リストボックス1へ出力する
listBox2->Items->Clear(); // リストボックス2初期化
for(char ii=0; ii<listBox1->Items->Count; ii++)
{
System::String^ name;
try
{
name = listBox1->Items[ii]->ToString();
port.PortName = name;
port.Open();
}
catch(Exception^ e)
{
name = System::String::Format("{0}",e);
}
finally
{
port.Close();
if( name != "" )
{
listBox2->Items->Add(name);
}
}
}
}
// ■■■■■■■■■■■■■■■■■↑追加
};
}

// ソースコードの終わり

■■■■■■■■■■■■■■■■■■■■■■■■
質問の回答は最新のブログで記載させていただきました。
■■■■■■■■■■■■■■■■■■■■■■■■


■■■■■■■■■■■■■■■■■■■■■
>プログラムの、L"button1";のところの
>Lというのはどういった意味があるのでしょうか?
>初歩的な質問かもしれませんが教えてほしいです。

Lの意味
Lをつけるとコンパイル時に""内の文字を変換なしで実行されるようです。
Lをつけないときはコンパイル時に""内の文字をUnicodeへ変換してから実行されます。
■■■■■■■■■■■■■■■■■■■■■
>private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
>は、どういった動作をさせるために書いているんですか?

ボタン1(button1)を押したときに、させたいことを記述する場所です。
本稿では、ボタン1を押すことで、リストボックスに使用可能なシリアルポートを表示するようにしたものです。
()内にあるのは引数(ひきすう)と呼ばれるものです(とりあえずは使う必要はないと思います)。

■■■■■■■■■■■■■■■■■■■■■
大変失礼なことをお聞きして申し訳ありませんが、
VC++2005/2008 は少し敷居が高いと感じているのではないでしょうか?
VC++2005/2008 という言語は、「C言語」と「C++」の経験が無いとなかなか難しいと思います。
だからといって、「C言語」から勉強するというのも大変ですよね。
でもやはり、「C言語」と「C++」の基本は習得しておいたほうが良いと思います。

私の場合ですが、初心者の頃は以下のサイトの「C言語」と「C++」を活用させていただきました。
毎日1時間程度、サンプルを入力して動かして、という勉強をしていました。
すると、2、3ヶ月で基本がマスターできました。参考まで。

http://www.geocities.jp/ky_webid/index.html
http://wisdom.sakura.ne.jp/programming/

VC#2005/2008 シリアルポートを使用する

VC#2005/2008 シリアルポートを使用する

ボタン1を押すと、listBox1に全ポート名、listBox2に使用可能なポート名を表示します。

[ツールボックス]->[コンポーネント]->[SerialPort]を貼り付けて、以下のソースを使用します。
//------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports; // シリアルポート

namespace at3200
{
public partial class Form1 : Form
{
SerialPort port; // シリアルポート宣言

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
listBox1.Items.Clear(); // リスト1初期化
foreach (string name in SerialPort.GetPortNames())
{
listBox1.Items.Add(name); // ポート名を追加する
}

listBox2.Items.Clear(); // リスト2初期化
for (int ii = 0; ii < listBox1.Items.Count; ii++)
{
string name = ""; // ポート名初期化
try
{
name = listBox1.Items[ii].ToString(); // ポート名取得
port = new SerialPort(name);
port.Open(); // ポートオープン
}
catch (System.Exception err)
{
System.Console.WriteLine(err.Message);
name = ""; // ポート名消す
}
finally
{
port.Close(); // ポートクローズ
if (name.CompareTo("") != 0)
{
listBox2.Items.Add(name); // ポート名追加
}
}
}
}
}
}
//------------------------------------------------------------

2008年4月14日月曜日

VC++2005/2008 で Managed DirectX の環境を設定する方法

VC++2005/2008 で Managed DirectX の環境を設定する方法

とりあえず、JOYSTICKが使用できる環境を設定します。

(1)DirectX SDK と Microsoft プラットフォーム SDK をインストールする。
(2)ツール -> オプション -> VC++ディレクトリ で以下の設定を行う。
●ディレクトリを表示するプロジェクト(S):実行可能ファイル
C:\Program Files\Microsoft DirectX SDK(November 2007)\Utilities\Bin\x86
C:\Program Files\Microsoft Platform SDK\Bin
●ディレクトリを表示するプロジェクト(S):インクリュードファイル
C:\Program Files\Microsoft DirectX SDK(November 2007)\Utilities\Include\x86
C:\Program Files\Microsoft Platform SDK\Include
●ディレクトリを表示するプロジェクト(S):ライブラリファイル
C:\Program Files\Microsoft DirectX SDK(November 2007)\Utilities\Lib\x86
C:\Program Files\Microsoft Platform SDK\Lib

(3)ソリューションエクスプローラーのプロジェクト名で右クリック -> 参照 -> 新しい参照の追加で以下を追加する。
●Microsoft.DirectX
●Microsoft.DirectX.DirectInput
●その他、DirectXで使用したいものがあれば追加する

(4)form1.hで以下を宣言する。
using namespace Microsoft::DirectX;
using namespace Microsoft::DirectX::DirectInput;

2008年4月5日土曜日

VC#2005/2008 string型を数値に変換する方法(変換失敗にも対応)

VC#2005/2008 string型を数値に変換する方法(変換失敗にも対応)
変換できる場合のみ変換します。

■C++
int result;
int::TryParse( textBox1->Text , result );

■C#
int result;
int.TryParse(textBox1.Text , out result);