[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2005/01/19(Wed) 11:48
投稿者名:ダンボ
URL :
タイトル:
複数のボタンを楕円と直線で(実装方式検討)
★ - 複数のボタンを楕円で過不足無く囲む描画 - ダンボ 12/10-11:26 No.1211

で、アルゴリズムの検討を行いました。その結果、
(方式1)画面に平行な楕円で囲む(歪み率を黄金比、白銀比)。
(方式2)傾いた楕円で囲む。
(方式3)楕円にこだわらず、ボタンの最遠の端点をベジェ曲線で結ぶ。
の3方式を案出しました。これをそれぞれ実装して、私の感覚で見比べたところ、方式1の黄金比が1番心地よ
かったです。
Renardさん、よいアイデアを有難うございました。
綺麗に描画できました。この掲示板に画像が掲載できるものならば、各方式での描画結果を皆さんにお見せし
たいところですが。。。

今回は、線の移動に関する下記のことが次の問題と思っています。
前提条件:「各ボタンは、複数の直線で結んだり複数の楕円で囲んだりするが、ボタンを画面上で移動すると
それに追随して直線・楕円を移動させる」
現在の実装方式:直線は、Picture1.Line命令、楕円はPolyBezierTo命令(API)で描画
この前提下で、ボタンが移動されたとき、
(方式a)画面上の線を全て消し(Picture1.Cls)、全ての直線・楕円を再描画する。
(方式b)移動するボタンに関係する直線・楕円だけを消し(=背景色で描く)、ボタン移動完了後に関係する直
線・楕円だけを再描画する。
(方式c)一度描画した直線・楕円はPathToRegionでリージョン化し、移動に対しては「リージョンの変形」で対
処する。
の3方式を検討しています。
(方式a)は実装は簡単だが画面がちらつくし応答速度が問題。
(方式b)は実装が面倒。楕円の計算に伴う応答速度も問題。
(方式c)は「パスのリージョン化」「リージョンの変形」が未経験。です。

何かアドバイスあればコメントお願いします。

投稿時間:2005/01/25(Tue) 20:53
投稿者名:ダンボ
URL :
タイトル:
Re: 複数のボタンを楕円と直線で(実装方式検討)
> 綺麗に描画できました。この掲示板に画像が掲載できるものならば、各方式での描画結果を皆さんにお見せし
> たいところですが。。。

「わいわいがやがや広場」に画面を掲載しましたので見てやってください。

投稿時間:2005/01/28(Fri) 15:07
投稿者名:ダンボ
URL :
タイトル:
特定の線だけを消す方式を教えてください
ボタンの移動により、元の接続線や楕円を消す必要があるのですが、実現方式に手こずっています。

(方式a)画面上の線を全て消し(Picture1.Cls)、全ての直線・楕円を再描画する。
→実装方式は簡単で、結果も正しいのですが、全部の線が一度消えるのが気持ち悪い。
(方式b)移動するボタンに関係する直線・楕円だけを消し(=背景色で描く)、ボタン移動完了後に関係する直
線・楕円だけを再描画する。
→線・楕円が重なっていた場合にその交点が白く抜けてしまうのがまずい。
(方式c)各線を書く前に各背景を記録しておき、消すときに背景を書き戻す。(マスキングなど使う)
→これも線を書く順番により、後で書かれた線が(一部)消されてしまう場合がある。

わりと一般的な悩みなのでWeb検索しましたが、適切なものが見つかりませんでした。
描いた線の移動や削除をWindowsオブジェクトのように(コマンドボタンやラベルコントロールのように)扱いた
い。
ということなのですが。

投稿時間:2005/01/28(Fri) 17:26
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: 特定の線だけを消す方式を教えてください
こういう事でいいのでしょうか?
Command1 を実行後 Command2 Command3 と順次クリックして見てください。

Private Sub Form_Load()
    With Picture1
        .AutoRedraw = True
        .ScaleMode = vbPixels
        .DrawMode = vbXorPen
        .DrawStyle = vbSolid
        .DrawWidth = 10
        .ForeColor = BackColor
    End With
End Sub
Private Sub Command1_Click()
    Picture1.Line (10, 10)-(200, 100), QBColor(11)
    Picture1.Line (100, 20)-(190, 140), QBColor(14)
    Picture1.Line (30, 100)-(220, 100), QBColor(13)
End Sub
Private Sub Command2_Click()
    Picture1.Line (30, 100)-(220, 100), QBColor(13)
End Sub
Private Sub Command3_Click()
    Picture1.Line (100, 20)-(190, 140), QBColor(14)
End Sub

# .NET で同様の事がやりたかったのだが、vbXorPen に変るものが見つからず・・・・・

投稿時間:2005/02/01(Tue) 13:34
投稿者名:ダンボ
URL :
タイトル:
(解決)特定の線だけを消す方式を教えてください
> こういう事でいいのでしょうか?

花ちゃんさん、どうもありがとうございます。(方式b)の正しい実装方式ですね。
.DrawMode = vbXorPenがミソでしたか。
.ForeColor = .BackColor (.は書き忘れと思う)については、効果が分かりません。
つけたりつけなかったりして、効果を見比べているのですが同じように見える。。

線の交点や、背景が均一で無い場合は、重なった部分の色が変わるのがちょっと気になりますが、
vbXorPenを使う以上、仕様として割り切ります。

理想としては、EXCELのオートシェイプのように、直線や楕円がオブジェクトとして扱えると
良いかなと思います。ハンドルを表示してドラッグ移動・変形できるとか。

おっ。ここにこんな良い物が。
hhttp://www.bcap.co.jp/hanafusa/VBHLP/Shape.htm
こういうのを発展させて、直線や楕円のオートシェイプ・クラスを作ろうかな?
いや、すでに売り物かフリーウェアでありそうな気もする。。。

遅くなりましたが、御礼まで。

投稿時間:2005/02/01(Tue) 14:11
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: (解決)特定の線だけを消す方式を教えてください
> .DrawMode = vbXorPenがミソでしたか。
> .ForeColor = .BackColor (.は書き忘れと思う)については、効果が分かりません。

Formに書いていたものをPictureに書き直したので、どちらでも動作は同じですが
.BackColor の方が正解ですね。

> つけたりつけなかったりして、効果を見比べているのですが同じように見える。。
(投稿したコードでは、カラーコードを指定しているので無くてもいいのですが)

下記のコードだけで試して見て下さい。
Private Sub Form_Load()
    With Picture1
        .AutoRedraw = True
        .ScaleMode = vbPixels
        .DrawMode = vbXorPen
        .DrawStyle = vbSolid
        .DrawWidth = 10
        .BackColor = vbRed     'この部分をコメント化して試して下さい。
        .ForeColor = .BackColor  'この部分をコメント化して試して下さい。 
    End With
    Picture1.Line (10, 10)-(200, 100)  '何色で表示されましたか?
End Sub

投稿時間:2005/02/01(Tue) 16:18
投稿者名:ダンボ
URL :
タイトル:
理解を深めて。。
(1)
    .BackColor = vbRed         'この部分をコメント化して試して下さい。
    .ForeColor = .BackColor    'この部分をコメント化して試して下さい。
     Picture1.Line (10, 10)-(200, 100)  '何色で表示されましたか?
背景は赤くなり、線は黒色で引かれる。
(2)
   '.BackColor = vbRed         'この部分をコメント化して試して下さい。
    .ForeColor = .BackColor    'この部分をコメント化して試して下さい。
     Picture1.Line (10, 10)-(200, 100)  '何色で表示されましたか?
背景は変化無し、線は黒色で引かれる。
(3)
     .BackColor = vbRed     'この部分をコメント化して試して下さい。
    '.ForeColor = .BackColor  'この部分をコメント化して試して下さい。 
     Picture1.Line (10, 10)-(200, 100)  '何色で表示されましたか?
背景は赤くなり、線は見えない。
(4)
    '.BackColor = vbRed     'この部分をコメント化して試して下さい。
    '.ForeColor = .BackColor  'この部分をコメント化して試して下さい。 
     Picture1.Line (10, 10)-(200, 100)  '何色で表示されましたか?
背景は変化無し、線は見えない。

説明:.ForeColor = .BackColorとすることにより、線の表示色はXORの結果常に0即ち黒色となる。
.ForeColorを設定しない場合は既定値の黒即ち0と背景色のXORを取るから常に背景色となる。

疑問1:DrawModeプロパティのヘルプに書かれている表示色=.ForeColor、背景色=.BackColorかな。
      とするとヘルプのペン色はどこで指定するのだろう。VbCopyPenとVbBlacknessとVbWhitenessはわかる
が。
疑問2:Option Explicit設定なのに、BackColorはエラーにならない。どうもForm1.BackColorに予約されてい
るみたい。

投稿時間:2005/02/01(Tue) 21:42
投稿者名:Say
Eメール:
URL :
タイトル:
Re: 理解を深めて。。
> 疑問2:Option Explicit設定なのに、BackColorはエラーにならない。どうもForm1.BackColorに予約されて

> るみたい。
単に「Form1.」を省略した、とみなされているだけです。

「Text1.Text」が「Form1.Text1.Text」の省略形であるのと同じです。

Top = 100 でも Caption = "aaa" でもやってみてください。

投稿時間:2005/02/02(Wed) 09:45
投稿者名:ダンボ
URL :
タイトル:
Re^2: 理解を深めて。。
> 「Text1.Text」が「Form1.Text1.Text」の省略形であるのと同じです。

Sayさん、いつも有難うございます。

う〜ん。認識が薄かったです。フォーム上に配置されているオブジェクトや、フォームのプロパティは
「絶対的にはForm1.Text1.Textのように記される」「Form1.は省略して良い」ですか。
ちょっとファイル管理、HTMLの絶対パスと相対パスの話に似ていますね。
「フォームのプロパティ、例Form1.Top」の「Form1.は省略して良い」までは頭に無かったです。
だから、Dim TOPとかDim HEIGHTとかバンバン定義していました。今後は避けよう。

まあ、経験少ないですが、よそのFormやMDIFormの中を参照するのに、Form1!Text1.Text類は
使っていました。「!は.と記しても良い」というのもあったようです。確かに全部「.」で記すと分かりづらい。
「オブジェクトは!」「プロパティは.」「イベントは_」「メソッドは#」とか使い分けておけばよかったのかも>MS

投稿時間:2005/02/02(Wed) 11:01
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re^3: 理解を深めて。。
> 「絶対的にはForm1.Text1.Textのように記される」「Form1.は省略して良い」ですか。
省略しても同じ結果となりますね。
ほとんどの場合、「Form1.Text1」と「Text1」は同じ意味を持ちます。

# ただ、「Form1」は暗黙定義の変数なので、自フォーム内から呼ぶのであれば、
# 「Me.Text1」という記述の方が適切かもしれません。

ただ、両者は完全に同一の意味というわけではありませんので、その点は注意してください。
たとえば、下記のような状況です。
  Option Explicit
  Public X As Long
  Public Sub Test(ByVal X As String)
    Debug.Print TypeName(X)     'これは「String」と出力されます。
    Debug.Print TypeName(Me.X)  'これは「Long」となります。
  End Sub


> Form1!Text1.Text類は
この場合の Form1!Text1 は、「Form1("Text1")」の意味で扱われます。
「!」とは、『規定のメンバ』を呼び出すためのショートカットです。

そして、「!」によるアクセスと「.」によるアクセスは、必ずしも同一ではありませんので、
こちらも注意が必要です。たとえば、TextBoxの名前を「Name」という名前にした場合には、
Me.Name と Me!Name が、別の物を指し示すことになります。(実際に試してみてください)


ここで、「!」の動作について、少し実験してみましょう。
クラスモジュール Class1 を一つ追加して、そこに
  Option Explicit
  Public Function MyMethod(ByVal Param As String) As String
    MyMethod = Param
  End Function
のようなコードを追加します。ここで、VBのメニューから
[ツール]-[プロシージャ属性] のダイアログを開き、詳細ボタンから、
上記「MyMethod」メソッドの「プロシージャID」を「(規定値)」にします。


こうしておくと、
  Private Sub Form_Load()
    Dim X As Class1
    Set X = New Class1
    Debug.Print X.MyMethod("ab cd")
    Debug.Print X![0123]
    Debug.Print X!Z80
    Set X = Nothing
  End Sub
というコードを実行すると、この規定のメソッドが呼び出され、
  ab cd
  0123
  Z80
という出力結果が得られる事になります。「!」にはこのような意味があったわけですね。


ここで、先の TextBox コントロールの例に戻ってみますと、
   Me!Text1
   Me("Text1")
   Me.Controls!Text1
   Me.Controls("Text1")
   Me.Controls.Item("Text1")
これらはすべて、同一の「Text1コントロール」に対するアクセスを提供します。
上方にあるのが省略表記、一番最後のは省略せずに記述した場合です。

# なお、Formの規定のプロパティは「_Default」という名前ですので、
# 『Me.[_Default]("Text1")』や『Me.[_Default].Item("Text1")』でも、
# 同じ結果を得ることができます。


「Me!Text1」に対し、Me.Text1 や Text1 でのアクセスは、Text1 が文字列引数として
評価されるのではなく、そのフォーム上の TextBox コントロールを直接指し示すことが
できますので、個人的には、「!」ではなく「.」によるアクセスをお勧めします。

たとえば、「Text100」という名前のコントロールが存在しない時に、
  Private Sub Form_Load()
    Dim S As String
    S = Me!Text100.Text
  End Sub
というコードは、コンパイルができてしまう(実行時にエラー)のですが、
  Private Sub Form_Load()
    Dim S As String
    S = Me.Text100.Text
  End Sub
とすれば、コンパイルエラーとして報告されますので、スペルミスによるバグも防げますよ。

投稿時間:2005/02/01(Tue) 22:56
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: 理解を深めて。。
> 疑問1
上記の例題で納得がいかないなら、VB付属のヘルプで[ぺん]を調べて下さい。
以下ヘルプより抜粋(それぞれのステートメントやプロパティが詳しく知りたければ
ヘルプで見て下さい。それが出来る人ですから)

Line、Point、および Circle ステートメント、または現在の ForeColor プロパティおよび FillColor
プロパティの設定によって指定される、色などのグラフィカルな特徴を指します。

> 疑問2
Sayさんが回答されているようなので。
(こちらもヘルプでBackColorの使用例を見れば載っていますよ)