VBの描画の遅さについて
投稿者 るきお  (社会人)
投稿日時
2013/4/13 00:36:23
詳細が分からないことと、ゼロから自作して試すと骨が折れそうなことから、なんとも回答できないです。
Tatibanaffさんが作成されたプログラムを貼っていただければ、それを見て試したり、何か問題があるか指摘できたりするかもしれません。
Tatibanaffさんが作成されたプログラムを貼っていただければ、それを見て試したり、何か問題があるか指摘できたりするかもしれません。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2013/4/13 15:17:28
ためしに作ってみました。
新規にクラス「MarqueeLabel.vb」を作成し、下記のコードを記載してみてください。
コンパイルすると、ツールボックスに MarqueeLabel コントロールが追加されます。
通常のラベルに「Speed As Single」なプロパティを追加しただけのコントロールです。
Speed = 0 でスクロール停止、Speed > 0.0 では、値が大きいほど早くスクロールします。
もし、コンパイルしてもツールボックスにコントロールが表示されない場合には、
メニューから[ツール]-[オプション]画面を開き、[Windows フォームデザイナー]-[全般]タブで
「AutoToolboxPopulate(ツールボックスを自動取得する)」を True にしてからビルドしてみてください。
新規にクラス「MarqueeLabel.vb」を作成し、下記のコードを記載してみてください。
コンパイルすると、ツールボックスに MarqueeLabel コントロールが追加されます。
通常のラベルに「Speed As Single」なプロパティを追加しただけのコントロールです。
Speed = 0 でスクロール停止、Speed > 0.0 では、値が大きいほど早くスクロールします。
Imports System.Windows.Forms
Imports System.ComponentModel
Public NotInheritable Class MarqueeLable
Inherits System.Windows.Forms.Label
Private components As System.ComponentModel.IContainer
Private internalTimer As System.Windows.Forms.Timer
Private internalLocation As Single = 0.0F
Public Sub New()
MyBase.UseCompatibleTextRendering = True
Me.components = New System.ComponentModel.Container()
Me.internalTimer = New System.Windows.Forms.Timer(components)
Me.internalTimer.Interval = 50
AddHandler internalTimer.Tick, AddressOf internalTimer_Tick
MyBase.SetStyle(ControlStyles.UserPaint, True)
MyBase.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
MyBase.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.internalTimer.Start()
End Sub
''' <summary>
''' テキストの位置を初期値に戻します。
''' </summary>
Public Sub ResetPosition()
Me.internalLocation = 0.0F
Me.Invalidate()
End Sub
''' <summary>
''' 流れるスピードを指定します。
''' </summary>
<System.ComponentModel.Description("流れるスピードを指定します。")> _
<System.ComponentModel.Category("Action")> _
<System.ComponentModel.DefaultValue(20.0F)> _
Public Property Speed() As Single
Get
Return Math.Max(0.0F, Math.Min(CSng(Me.Width), speedValue))
End Get
Set(ByVal value As Single)
If value < 0.0F Then
Throw New ArgumentOutOfRangeException("Speed", value, "0以上の値を指定してください。")
End If
speedValue = Math.Min(Me.Width, value)
internalTimer.Enabled = (value <> 0)
If value = 0.0F Then
internalTimer.Enabled = False
If Me.DesignMode Then
ResetPosition()
End If
Else
internalTimer.Enabled = True
End If
End Set
End Property
Private speedValue As Single = 20.0F
Protected Overrides Sub OnPaint(e As PaintEventArgs)
e.Graphics.TranslateTransform(-internalLocation, 0.0F)
MyBase.OnPaint(e)
End Sub
Private Sub internalTimer_Tick(sender As Object, e As EventArgs)
If Me.internalLocation > Me.Width Then
internalLocation = -Me.Width
Else
internalLocation += speedValue / 10
End If
Me.Invalidate()
End Sub
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
Me.components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
End Class
もし、コンパイルしてもツールボックスにコントロールが表示されない場合には、
メニューから[ツール]-[オプション]画面を開き、[Windows フォームデザイナー]-[全般]タブで
「AutoToolboxPopulate(ツールボックスを自動取得する)」を True にしてからビルドしてみてください。
投稿者 バーバラ  (社会人)
投稿日時
2013/4/13 15:22:57
VBでも滑らかな動きをさせることは可能なはずですが、
どのようにオーナードローをしているか、描画のタイミングをどのように設定しているかにもよります。
どのようにオーナードローをしているか、描画のタイミングをどのように設定しているかにもよります。
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2013/4/13 16:54:53
MarqueeLabel と書いたつもりだったのですが、改めて見直してみたら、
MarqueeLable に typo っていますね…先のコードは適宜読み替えてください。
MarqueeLable に typo っていますね…先のコードは適宜読み替えてください。
投稿者 Tatibanaff  (社会人)
投稿日時
2013/4/14 15:43:38
るきおさん、 魔界の仮面弁士さん、バーバラさん 回答くださり有難うございます。
私が考えたのは下のようなものです。
Private Sub スタート(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Call SrtingSet(0)
Timer1.Enabled = True '初回文字セット、タイマースタート
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Label1.Left -= 変数 '左へ移動
If Label1.Left < pLength Then
Label1.Left += pLength '1行分右へ移動
Call SrtingSet(pCount)
pCount += 1
End If
End Sub
Private Sub SrtingSet(ByVal pCount)
Label1.Text = ""
For Idx = pCount To Sample.Length - 1
Label1.Text &= Sample(Idx)
If Idx = pCount Then
pLength = Label1.Width '先頭行の長さ
End If
If Label1.Height > Me.Width + pLength Then '全体の長さ
Exit For
End If
Next
End Sub
バーバラさん オーナードローはまだ習得していないので使っておりません。
参考になるサイトなどありましたら是非お知らせください。
魔界の仮面弁さんの方法は
System.Windows.Forms.Design.ISlectionUIServiceは既にサービスコンテナに存在します。
というメッセージでMarqueeLableは追加されません。
何回か全く新しいフォームを作って試したのですがうまくいきません、もう少し頑張ってみますが取り急ぎ報告いたします。
Tatibanafff
私が考えたのは下のようなものです。
Private Sub スタート(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Call SrtingSet(0)
Timer1.Enabled = True '初回文字セット、タイマースタート
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Label1.Left -= 変数 '左へ移動
If Label1.Left < pLength Then
Label1.Left += pLength '1行分右へ移動
Call SrtingSet(pCount)
pCount += 1
End If
End Sub
Private Sub SrtingSet(ByVal pCount)
Label1.Text = ""
For Idx = pCount To Sample.Length - 1
Label1.Text &= Sample(Idx)
If Idx = pCount Then
pLength = Label1.Width '先頭行の長さ
End If
If Label1.Height > Me.Width + pLength Then '全体の長さ
Exit For
End If
Next
End Sub
バーバラさん オーナードローはまだ習得していないので使っておりません。
参考になるサイトなどありましたら是非お知らせください。
魔界の仮面弁さんの方法は
System.Windows.Forms.Design.ISlectionUIServiceは既にサービスコンテナに存在します。
というメッセージでMarqueeLableは追加されません。
何回か全く新しいフォームを作って試したのですがうまくいきません、もう少し頑張ってみますが取り急ぎ報告いたします。
Tatibanafff
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2013/4/16 19:30:48
自分のコードは、オーナードローの一種です。既定の描画処理の直前に、
e.Graphics.TranslateTransform メソッドを呼び出すことで、原点座標を
左方向に少しずつずらすことで、描画位置を変わるようにしています。
一応、VB2005、2008、2010、2012 の各バージョンで動くことを確認済みです。
> ISlectionUIServiceは既にサービスコンテナに存在します。
「ISlectionUIService」ではなく
「ISelectionUIService」であろうとは思いますが、
今のところ、そのエラーの再現方法が分かりませんでした。
Tatibanaff さん以外の方でも、同様のエラーが発生するようであれば教えてください。
> もう少し頑張ってみますが取り急ぎ報告いたします。
Tatibanaff さんがお使いの VB バージョンは何でしょうか。
ByVal が記載されているので、少なくとも VB2010SP1 以降では無いようですが。
お使いの開発環境が分かれば、そのバージョン向けに
実際の動作するサンプルコードを ZIP ファイルで提供します。
e.Graphics.TranslateTransform メソッドを呼び出すことで、原点座標を
左方向に少しずつずらすことで、描画位置を変わるようにしています。
一応、VB2005、2008、2010、2012 の各バージョンで動くことを確認済みです。
> ISlectionUIServiceは既にサービスコンテナに存在します。
「ISlectionUIService」ではなく
「ISelectionUIService」であろうとは思いますが、
今のところ、そのエラーの再現方法が分かりませんでした。
Tatibanaff さん以外の方でも、同様のエラーが発生するようであれば教えてください。
> もう少し頑張ってみますが取り急ぎ報告いたします。
Tatibanaff さんがお使いの VB バージョンは何でしょうか。
ByVal が記載されているので、少なくとも VB2010SP1 以降では無いようですが。
お使いの開発環境が分かれば、そのバージョン向けに
実際の動作するサンプルコードを ZIP ファイルで提供します。
投稿者 Tatibanaff  (社会人)
投稿日時
2013/4/19 22:02:16
返事が遅くなり申し訳ありません!
foamを作成し作っていただいたコードを貼り付けたのですが貼り付けた場所がForm1の前だったので
デザイナーウィンドからForm1が消えプロパティウィンドにはMarqueeLable1しかなくなってしまいあれこれと悩まされました。
スタートフォームのコードは先頭になければならないことは全く知りませんでした、
クラス内のイベントやプロシージャはどこにあっても関係ないのでスタートクラスも同じだと思ってしまったのが大きな間違いでした。
オーナードローはどう動いているのか教えていただいたコードを見て勉強します。
本当にありがとうございました。
foamを作成し作っていただいたコードを貼り付けたのですが貼り付けた場所がForm1の前だったので
デザイナーウィンドからForm1が消えプロパティウィンドにはMarqueeLable1しかなくなってしまいあれこれと悩まされました。
スタートフォームのコードは先頭になければならないことは全く知りませんでした、
クラス内のイベントやプロシージャはどこにあっても関係ないのでスタートクラスも同じだと思ってしまったのが大きな間違いでした。
オーナードローはどう動いているのか教えていただいたコードを見て勉強します。
本当にありがとうございました。
左への移動はタイマーで50ミリ秒間隔で 2~15ドットづらしています、移動量が少ないときはうまく流れるのですが多くしたりフォントを大きく(36くらい)にすると描画が追い付かないようで、何回分かを一度に移動するようで「カクカク」してしまいます。
以前 ピクチャボックスに文字をグラフィック表示させることも試しましたが結果は大差ありませんでした。
.NetFrameWorkだけではしょうがないのでしょうか?
まだまだ勉強中で API や CUDAの勉強まで手が回らないのでうまい方法がありましたらご教授お願いいたします。