アプリ版:「スタンプのみでお礼する」機能のリリースについて

Visual C++のCLRでフォームアプリケーションを作っていて、ListBoxのオーナードローの方法がわからないので質問させてもらいました。
CLRでプログラミングしたことが無く書籍などを読んだこともなく見よう見まねで作っています。
やりたいことはとりあえず
http://dobon.net/vb/dotnet/control/lbownerdraw.h …
にあることです。
サンプルプログラムはVBとC#でC++がありません。
MSDN(http://msdn.microsoft.com/ja-jp/library/system.w …)も同様でVBとC#のサンプルプログラムでC++がありませんでした。

とりあえず。

C#のサンプル-----------------------------------------------
//DrawItemイベントハンドラ
//項目を描画する
private void ListBox1_DrawItem(object sender,
System.Windows.Forms.DrawItemEventArgs e)
{
//背景を描画する
//項目が選択されている時は強調表示される
e.DrawBackground();

//文字を描画する色の選択
Brush b = null;
if ((e.State & DrawItemState.Selected) !=
DrawItemState.Selected)
{
//選択されていない時
switch (e.Index % 3)
{
case 0:
b = new SolidBrush(Color.Red);
break;
case 1:
b = new SolidBrush(Color.Blue);
break;
case 2:
b = new SolidBrush(Color.Green);
break;
}
}
else
{
//選択されている時はそのままの前景色を使う
b = new SolidBrush(e.ForeColor);
}
//描画する文字列の取得
string txt = ((ListBox) sender).Items[e.Index].ToString();
//文字列の描画
e.Graphics.DrawString(txt, e.Font, b, e.Bounds);
//後始末
b.Dispose();

//フォーカスを示す四角形を描画
e.DrawFocusRectangle();
}
-----------------------------------------------

を参考にしてForm1に
private: System::Void ListBox1_DrawItem(System::Object^ sender, System::Windows::Forms::DrawItemEventArgs^ e)
{
//背景を描画する
//項目が選択されている時は強調表示される
e->DrawBackground();
//文字を描画する色の選択

}
と書いてみたのですが、そのあとどうすればよいかわかりません。

わかる方、回答お願いします。

A 回答 (6件)

ある程度の法則性はあるのでC# → C++/CLIはそれほど難しい置き換えじゃないはずですが。



1.new → gcnew
2.gcnewで確保するオブジェクトを宣言するときは^を付けて参照型に
3.メンバー参照の.を->に(第1階層だけ)
4.ネームスペース参照の.を::に

#他に何かあったかな……

もちろん単純に置き換えではうまく行かないケースもあるはずなのでそこはケースバイケースで。

この回答への補足

回答ありがとうございます。
参考にさせてもらいます。

とりあえず
Brush b = null;
でコンパイルエラーになります。
C3622: 'System::Drawing::Brush': 'abstract' として宣言されたクラスをインスタンス生成することはできません
C2065: 'null' : 定義されていない識別子です。

どういうことでしょうか

補足日時:2009/06/07 20:55
    • good
    • 0

> Brush b = null;


> でコンパイルエラーになります。

これは後に続くswitch()の中と合わせて1と2の複合です。
なお、nullはNULLとしてください。
    • good
    • 0

ちょっと変なので修正。



ここは、後ろのswitch内でオブジェクトを生成する部分が1に該当するため、遡って2のケースが適用されます。
null→NULLとするのは#2で書いた通り。
    • good
    • 0
この回答へのお礼

ありがとうございます。
うまくできました。
他もC#からの変換できそうです。

お礼日時:2009/06/10 05:17

 こんばんは。


 このオーナードローは、様々なコントロールをカバーしているので、モノによっては使わないフラグもあります。
 その他、選択はされているが、キーボード操作によってフォーカスが別のアイテムに逃げている、コントロール自体がディセーブルされた、特定のアイテムだけがディセーブルされたなど、色々な状況があり、これ等はモノによって違いがありますので、取り出したに確認し、順を追って描きあげて行きます。

 一通り描いた後は、アイテムやコントロールをディセーブルにしたり、アイテムを選択したままタブを押して、フォーカスを逃がす等、色々と確認して下さい。

 また、再描画が必要になるとアイテムが一つも存在しない時ですら、飛び込んでくるので其の点も要注意です。
 C#サンプルの修正ではありませんが、以下参考程度で。

private: generic<typename T> static System::Boolean IsA(T a, T b)
{
return (safe_cast<int>(a) & safe_cast<int>(b)) == safe_cast<int>(b);
}

private: System::Void listBox1_DrawItem(System::Object^ sender, System::Windows::Forms::DrawItemEventArgs^ e)
{
//このキャストは確定的な筈
System::Windows::Forms::ListBox^ listBox = static_cast<System::Windows::Forms::ListBox^>(sender);

//アイテムの色
System::Drawing::Color crItem = e->BackColor;

//フォントの色
System::Drawing::Color crFont = e->ForeColor;

//背景を描画する
e->DrawBackground();

//アイテムが一つも無い時でも入り込んでくるので引き返す
if(e->Index == -1)
return;

//項目が選択されている時は強調表示される
if(this->IsA(e->State, DrawItemState::Selected))
{
crItem = System::Drawing::Color::FromArgb(220, 220, 255);
crFont = System::Drawing::Color::FromArgb(170, 170, 255);
}

//マウスが当たった時
if(this->IsA(e->State, DrawItemState::HotLight))
{
crItem = System::Drawing::Color::FromArgb(248, 248, 255);
}

//灰化又はディセーブルされた時
if(this->IsA(e->State, DrawItemState::Disabled) || this->IsA(e->State, DrawItemState::Grayed))
{
crItem = System::Drawing::Color::FromArgb(220, 220, 220);
}

//ブラシの作成
System::Drawing::Brush^ brItem = gcnew System::Drawing::SolidBrush(crItem);
System::Drawing::Brush^ brFont = gcnew System::Drawing::SolidBrush(crFont);

//アイテムに着色
e->Graphics->FillRectangle(brItem, e->Bounds);

//フォントを描く
e->Graphics->DrawString(listBox->Items[e->Index]->ToString(), listBox->Font, brFont, e->Bounds);

//フォーカスが当たっていれば描く(アイテムの色彩を反転させるので、最後に描く)
if(this->IsA(e->State, DrawItemState::Focus))
{
e->DrawFocusRectangle();
}

//ブラシの消去
delete brItem;
delete brFont;
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
うまく自分のやりたいことができました。
オーナードローするときはいろいろ考えたほうが良いのですね。
とても勉強になりました。

お礼日時:2009/06/10 05:40

下記URL参照。


VS2008:C++/CLIprojectです。

参考URL:http://cid-07c558f8e11e708f.skydrive.live.com/se …
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
わざわざ作例を作ってくれありがとうございます。
うまく作れました。

お礼日時:2009/06/10 05:42

・・・ほぼそのままだと思うんだけど


private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) {
ListBox1->DrawMode = DrawMode::OwnerDrawFixed;
//ListBox1に項目を追加する
for (int i = 0; i < 10; i++)
ListBox1->Items->Add(String::Format("{0}番目の項目", i));
}

//DrawItemイベントハンドラ
//項目を描画する
private: System::Void ListBox1_DrawItem(System::Object^ sender,
System::Windows::Forms::DrawItemEventArgs^ e) {
{
//背景を描画する
//項目が選択されている時は強調表示される
e->DrawBackground();

//文字を描画する色の選択
Brush^ b = nullptr;
if ((e->State & DrawItemState::Selected) != DrawItemState::Selected)
{
//選択されていない時
switch (e->Index % 3)
{
case 0:
b = gcnew SolidBrush(Color::Red);
break;
case 1:
b = gcnew SolidBrush(Color::Blue);
break;
case 2:
b = gcnew SolidBrush(Color::Green);
break;
}
}
else
{
//選択されている時はそのままの前景色を使う
b = gcnew SolidBrush(e->ForeColor);
}
//描画する文字列の取得
String^ txt = safe_cast<ListBox^>(sender)->Items[e->Index]->ToString();
//文字列の描画
e->Graphics->DrawString(txt, e->Font, b, e->Bounds);

//フォーカスを示す四角形を描画
e->DrawFocusRectangle();
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
C#からの変換ってほとんど変えなくで済むんですね。

お礼日時:2009/06/10 05:43

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!