C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: コンボボックスのオーナードロウがうまくいかない


(過去ログ 113 を表示中)

[トピック内 11 記事 (1 - 11 表示)]  << 0 >>

■67102 / inTopicNo.1)  コンボボックスのオーナードロウがうまくいかない
  
□投稿者/ kiku (9回)-(2013/07/03(Wed) 17:25:37)

分類:[VB.NET/VB2005 以降] 

コンボボックス表示をカスタマイズしたく、下記サイトを参考に
(ttp://youryella.wankuma.com/Library/Extensions/ComboBox/OwnerDraw.aspx)
DrawItemイベントで実装しようと思っていますが、
デフォルトのDrawItem機能を呼び出したいのですが
どのように呼び出したら良いかわかりません。

そもそも参考にしたサイトではオーバーライドを前提とした
サンプルであるため、イベントで実装することは出来ないのでしょうか?

※イベントにこだわっている理由は、自動生成されたデザインファイルを
 直接編集したくないからになります。

アドバイス頂けないでしょうか?

VB.NET、VS2010

    Private Sub cboCardSelect_DrawItem(sender As Object, e As System.Windows.Forms.DrawItemEventArgs) Handles cboCardSelect.DrawItem
        If e.Index = -1 Then
            Return
        End If

        ' 背景を描画
        e.DrawBackground()

        ' テキストを描画
        Dim txt As String = cboCardSelect.Items(e.Index).ToString
        Using sb As New SolidBrush(e.ForeColor)
            e.Graphics.DrawString(txt, e.Font, sb, e.Bounds)
        End Using

        ' フォーカス枠を描画
        e.DrawFocusRectangle()

        'MyBase.OnDrawItem(e)    'このベースクラスのOnDrawItemを呼びたい
    End Sub

引用返信 編集キー/
■67104 / inTopicNo.2)  Re[1]: コンボボックスのオーナードロウがうまくいかない
□投稿者/ Hongliang (64回)-(2013/07/03(Wed) 17:54:56)
呼び出す必要はありません。
引用返信 編集キー/
■67105 / inTopicNo.3)  Re[1]: コンボボックスのオーナードロウがうまくいかない
□投稿者/ shu (346回)-(2013/07/03(Wed) 17:57:55)
No67102 (kiku さん) に返信

OnDrawItemはDrawItemイベントを発生させる為にあり描画処理は何もしてないです。
なのでDrawItemイベント内でOnDrawItemを呼ぶ必要はありません。
参考にされたコードではイベントを発生させる前に独自の描画を行っているだけであり
MyBase.OnDrawItemの記述がなくても描画自体は正常に行われます。
逆に呼んでしまったら無限ループになってしまいます。

背景、テキスト、フォーカス枠の描画をしていれば標準の描画は大丈夫です。
引用返信 編集キー/
■67106 / inTopicNo.4)  Re[2]: コンボボックスのオーナードロウがうまくいかない
□投稿者/ とっちゃん (125回)-(2013/07/03(Wed) 18:09:43)
とっちゃん さんの Web サイト
No67102 (kiku さん) に返信

ちょっと丁寧に書いておきますね。

> DrawItemイベントで実装しようと思っていますが、
> デフォルトのDrawItem機能を呼び出したいのですが
> どのように呼び出したら良いかわかりません。
>
ComboBox.DrawItem イベントにデフォルトの動作はありません。
参考にした、派生メソッドの実装での、base.OnDrawItem は内部で、DrawItem イベントを発行する形として実装されています。

オーバーライドのサンプルとしては残しておくほうがいい場合が多いのですが、
ことオーナードローに関してだけで言えば、base.OnDrawItem() を呼び出してしまうと、せっかく描画した内容がイベントハンドラの実装で
全部書き換えられてしまうので呼び出してしまうことそのものが動作としてはよろしくない状況といえます。


一応。。。イベントの各ハンドラには、デフォルトの呼出しというのはありません。
イベントとは、発行元(呼び出し元)の動作の一部(または全部)をカスタマイズ(余計なことをさせてくれるタイミング)するための機能として用意された仕組みです。

ここでいう余計なこととは、システム(OSレベルで考えてもいい)が、作者の意図をそのままで実現できないすべての事象を指します。
もちろん、イベントによってできる内容は異なります(そのために多種多様なイベントが存在している)。

単純な通知レベルのものもあります(例えば、ボタンが押された。ウィンドウが閉じたなどの後戻りできないイベント)し
そのタイミングで描画処理をしなければならないものもあります(Paint イベントやDrawItem イベント)。
何か計算してそのあとの処理を行えるようにするもの(MeasureItemイベントなど)というものもあります。


> そもそも参考にしたサイトではオーバーライドを前提とした
> サンプルであるため、イベントで実装することは出来ないのでしょうか?
>
> ※イベントにこだわっている理由は、自動生成されたデザインファイルを
>  直接編集したくないからになります。
>
基本的にオーバーライドは、ユーザーコントロール(やカスタムコントロール)を作る場合に使うものと覚えておきましょう。

その場限り(あるプロジェクトで用意したコントロールでのみ使われるオーダーメイドな機能)の機能は基本的にイベントで賄うほうが実装が楽な場合が多いです。
.NET は任意のクラスのインスタンスメソッドとしてイベントを用意できるので。


> アドバイス頂けないでしょうか?
>
というあたりで参考になるでしょうか?

引用返信 編集キー/
■67114 / inTopicNo.5)  Re[3]: コンボボックスのオーナードロウがうまくいかない
□投稿者/ kiku (10回)-(2013/07/04(Thu) 11:30:21)
shuさん、Hongliangさん、とっちゃんさん、
丁寧にご回答頂きましてありがとうございます。
内容理解致しました。

後出しで申し訳ないのですが、
デフォルトの機能(今回呼び出さなくて良いこと判明)を呼び出さない状態で
動作を検証したところ、下記のように選択した内容が
表示されない状態でした。

コンボボックス(DropDownListを選択)
|0000|
------
|0000|
|0001|
|0002|
|0003|

0001を選択すると下記のようになるはずが、表示は0000のままになる。
ただしプログラムで取得すると0001が取得できる。
|0001|
------
|0000|
|0001|
|0002|
|0003|

このような状態であったため、デフォルトの機能の中に
選択した後の処理が実装されているためであると
勘違いしておりました。

どのようにしたら、0001を選択したらトップに
0001が表示されるようにできるでしょうか?

引用返信 編集キー/
■67115 / inTopicNo.6)  Re[4]: コンボボックスのオーナードロウがうまくいかない
□投稿者/ shu (347回)-(2013/07/04(Thu) 12:23:55)
No67114 (kiku さん) に返信

オーナードローでなければ思った通りに表示されるのでしょうか?
提示コードの記述には問題がないように思われます。
リストの設定はどのように行っていますでしょうか?
引用返信 編集キー/
■67120 / inTopicNo.7)  Re[5]: コンボボックスのオーナードロウがうまくいかない
□投稿者/ kiku (11回)-(2013/07/04(Thu) 14:15:51)
> オーナードローでなければ思った通りに表示されるのでしょうか?
> 提示コードの記述には問題がないように思われます。

オーナードローでなければ問題なく動作しています。

e.Index、e.State、cboCardSelect.Items(e.Index)の内容を
debug.printで表示し、イベントの発生の仕方などを
見ているのですが、トップの部分の描画のための
イベントは発生しているようです(e.State=ComboBoxEdit)。

環境は下記です。
 ・VB.NET
 ・.NETFramework4.0
 ・Windows7(32bit)

> リストの設定はどのように行っていますでしょうか?

こんな感じで行っています。
普通にaddでセットしているだけになります。
        rec_DATA = レコードセットを開く
            frmMain.cboCardSelect.Items.Clear()
            intIndex = 0
            Do While recETC_DATA.Read() = True
                frmMain.cboCardSelect.Items.Add(rec_DATA.Item("CARD_ID"))
                If frmMain.cboCardSelect.Items.Item(intCount) = strCARD_NO Then
                    intIndex = intCount
                End If
                intCount = intCount + 1
            Loop
            If frmMain.cboCardSelect.Items.Count > 0 Then
                frmMain.cboCardSelect.SelectedIndex = intIndex
            End If
        rec_DATA.Close() 'レコードセットを閉じる

引用返信 編集キー/
■67122 / inTopicNo.8)  Re[1]: コンボボックスのオーナードロウがうまくいかない
□投稿者/ ユージ (1回)-(2013/07/04(Thu) 14:29:36)
> そもそも参考にしたサイトではオーバーライドを前提とした
> サンプルであるため、イベントで実装することは出来ないのでしょうか?
>
> ※イベントにこだわっている理由は、自動生成されたデザインファイルを
>  直接編集したくないからになります。

そのサンプルは、オーバーライドを前提としたサンプルというわけではなく、
ComboBoxの継承を前提としたサンプルです。
「自動生成されたデザインファイル」が、フォームのDesigner.vbのことを
指すのであれば、これは全く関係なく、ComboBoxの継承クラスを作り、
これをデザイナ上に貼り付けるだけです。
引用返信 編集キー/
■67123 / inTopicNo.9)  Re[6]: コンボボックスのオーナードロウがうまくいかない
□投稿者/ kiku (12回)-(2013/07/04(Thu) 14:43:32)
追記情報

1.オーナードローを行いないと正常動作
2.オーナードローを行っている状態でDropDownStyle=DropDownListだと異常動作
3.オーナードローを行っている状態でDropDownStyle=DropDownだと正常動作

上記3については、トップの部分が手入力により編集できてしまうので
運用上NGであるが、編集できないようにできればいいのですが・・・

上記2については、下記のように調査した結果
トップ部分の描画イベントは上がっているが、
描画する領域が適切に上がっていないのではないかと考えました。
これは回避方法ないですよね。きっと(涙)

デバック表示コード
        Debug.Print("--------")
        Debug.Print(e.Index.ToString)
        Debug.Print(e.State.ToString)
        Debug.Print(e.Bounds.ToString)
        Debug.Print(cboCardSelect.RectangleToScreen(e.Bounds).ToString) <−ここは正しいかちょっと怪しい

ログ内容
 アイテムが3つ追加されている状態で、
 全体を表示し、2番目を選択するまでのログ。

--------
0
Selected, NoAccelerator, NoFocusRect
{X=0,Y=0,Width=181,Height=18}
{X=563,Y=130,Width=181,Height=18}
--------
0
Selected, NoAccelerator, NoFocusRect
{X=0,Y=0,Width=181,Height=18}
{X=563,Y=130,Width=181,Height=18}
--------
1
NoAccelerator, NoFocusRect
{X=0,Y=18,Width=181,Height=18}
{X=563,Y=148,Width=181,Height=18}
--------
2
NoAccelerator, NoFocusRect
{X=0,Y=36,Width=181,Height=18}
{X=563,Y=166,Width=181,Height=18}
--------
0
Selected, Focus, NoAccelerator, NoFocusRect
{X=0,Y=0,Width=181,Height=18}
{X=563,Y=130,Width=181,Height=18}
--------
0
NoAccelerator, NoFocusRect, ComboBoxEdit
{X=3,Y=3,Width=161,Height=18}
{X=566,Y=133,Width=161,Height=18}
--------


--------
0
Selected, NoAccelerator, NoFocusRect
{X=0,Y=0,Width=181,Height=18}
{X=563,Y=130,Width=181,Height=18}
--------
0
NoAccelerator, NoFocusRect
{X=0,Y=0,Width=181,Height=18}
{X=563,Y=130,Width=181,Height=18}
--------
1
Selected, NoAccelerator, NoFocusRect
{X=0,Y=18,Width=181,Height=18}
{X=563,Y=148,Width=181,Height=18}
--------
1
Selected, Focus, NoAccelerator, NoFocusRect
{X=0,Y=18,Width=181,Height=18}
{X=563,Y=148,Width=181,Height=18}
--------
1
Selected, Focus, NoAccelerator, NoFocusRect, ComboBoxEdit
{X=3,Y=3,Width=161,Height=18}
{X=566,Y=133,Width=161,Height=18}
--------
1
Selected, Focus, NoAccelerator, NoFocusRect, ComboBoxEdit
{X=3,Y=3,Width=161,Height=18}
{X=566,Y=133,Width=161,Height=18}
--------


--------
1
NoAccelerator, NoFocusRect, ComboBoxEdit
{X=3,Y=3,Width=161,Height=18}
{X=566,Y=133,Width=161,Height=18}
--------

引用返信 編集キー/
■67124 / inTopicNo.10)  Re[7]: コンボボックスのオーナードロウがうまくいかない
□投稿者/ shu (348回)-(2013/07/04(Thu) 15:32:06)
No67123 (kiku さん) に返信

コンボボックスの幅が狭くて最後の桁が欠けてしまっている
とかではないですか?
引用返信 編集キー/
■67125 / inTopicNo.11)  Re[8]: コンボボックスのオーナードロウがうまくいかない
□投稿者/ kiku (13回)-(2013/07/04(Thu) 15:54:20)
No67124 (shu さん) に返信
> ■No67123 (kiku さん) に返信
>
> コンボボックスの幅が狭くて最後の桁が欠けてしまっている
> とかではないですか?

shuさん、回答ありがとうございます。

お恥ずかしい限りですが、ビンゴでした。(掲示板に記録が残るのが恥ずかしい(涙)
トップの部分だけ微妙に幅が長くないといけないようです。
オーナードローしなければ幅が足りるのに、
なんでオーナードローすると幅が足りないか愚痴を言って終了とさせて頂きます。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -