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

投稿時間:2006/10/27(Fri) 14:37
投稿者名:xuexue
Eメール:
URL :
タイトル:
ラバーバンドの応用
お世話になっています。
いつも勉強させてもらっています。
早速質問です。

環境はXP(sp2)+ VB6です。
以前、ピクチャボックス内に直線描画するとき、ユーザビリティ向上のために
ラバーバンド動作を作成したことがあります。

1、ピクチャボックスのDrawModeを vbNotXorPen にする
2、左クリックの検出
3、現在の座標を変数に格納
4、マウスポイント移動の検出
5、2の座標と3の座標を直線描画
6、2の座標と4後の座標を直線描画
7、3に戻る

6で書いた直線が、常にユーザに見える線です。
3に戻って、5で再び同じ場所に直線を書くことで、
先ほど表示されていた線が、排他されて打ち消され、消えます。
これにより、マウスに追従する動きが実現できました。

まったく同じ要領で、マウスクリック(ドラッグ)しているときのみ、
マウスの横にテキストを表示させたいと思っています。
これが、うまくいきません。
テキストが、書かれる一方で消えてくれません。
ドラッグするたびに、お絵かきペンのようにかかれてしまい、
ピクチャーボックスが真っ黒になってしまいます。

ピクチャボックスのCLSメソッドで消すのは避けたいですが、
なにか良い方法はないでしょうか?

投稿時間:2006/10/27(Fri) 15:33
投稿者名:y4yama
Eメール:
URL :
タイトル:
Re: ラバーバンドの応用
おっ修正が入りましたようですね
ばかなような、しろーと考えですが、picturebox1の中に text1ボックスを入れて、
Private Sub Picture1_MouseDown(Button As Integer
            , Shift As Integer, X As Single, Y As Single)
Text1.Text = X & ", " & Y
Text1.Left = X + 200
Text1.Top = Y - 100
End Sub
としたら、線を乱すことなくマウスの位置にうまくtext1ボックスが
くるので、ひとつの解法かと・・・・
テキストを、Command1ボタンのCAPTION文字にしてもいいようです。
こんなのは、やっぱりしろーとカナ?

投稿時間:2006/10/27(Fri) 15:50
投稿者名:xuexue
Eメール:
URL :
タイトル:
ラバーバンドの応用(質問内容を簡素にしました)
y4yamaさん、ありがとうございます!
早いレスポンスに感謝です。

もう一回、修正します。ごめんなさい。

やりたいことの詳細を記述します。
・前提
 ピクチャボックスに、任意の複雑な図面がある。(設計図や地図などの)
・仕様
 ユーザ操作時、案内文句をアナウンスするため、ドラッグ時など、一定の条件を満たして
 いる時は常に、マウスポイント付近にテキストを表示させたい。
・仕様の満たし方と問題点と理想
 このとき、ラベルを使用すると、処理が遅れる
 ピクチャボックスをクリアしてしまうと、1の図面が消える
 リドロウしてしまうと、1の図面の複雑さに比例して極端に処理が遅れる
※マウスが動いたら、動く前のテキストのみを消し、マウスが動いたポイントにテキストを描画したい。

現状、こんな感じです。宜しくお願いいたします。

投稿時間:2006/10/27(Fri) 16:57
投稿者名:y4yama
Eメール:
URL :
タイトル:
Re: ラバーバンドの応用(質問内容を簡素にしました)
やっぱり、シロートでした^^
えっと、以前にこちらで読ませてもらった中で、上に透明な部品を
かぶせておき、そこで文字を描いたり消したりなら、下に影響が無いような
ことがありました。
大きなlabel1をかぶせたら、確かに良い感じですが、文字のLOCATEでギブアップ
しました。すんませんです。

−−−−−−−−−−[追加]−−−−−−−−−−−−−
小さいラベルでも動かしたら、追従が遅いとの問題点を出してられますが、
OnMousemoveのイベントを全部処理したらそりゃぁ遅いです。座標が20以上
動いたら描くとか、タイマーで0.1秒に1回しかマウス位置を見ないとか
したら負荷にはならないはずですヨ
それにしても、良い解決法が登場することを願ってま〜す

投稿時間:2006/10/27(Fri) 17:04
投稿者名:xuexue
Eメール:
URL :
タイトル:
Re^2: ラバーバンドの応用(質問内容を簡素にしました)
y4yamaさん、ありがとうございました。

親切に対応いただき感謝しています。
ありがとうございました。

引き続き、レスをお待ち申し上げます。
ご教示いただける方、なにとぞ。

投稿時間:2006/10/28(Sat) 10:42
投稿者名:Renard
Eメール:
URL :
タイトル:
Re: ラバーバンドの応用(質問内容を簡素にしました)
> やりたいことの詳細を記述します。
> ・前提
>  ピクチャボックスに、任意の複雑な図面がある。(設計図や地図などの)
> ・仕様
>  ユーザ操作時、案内文句をアナウンスするため、ドラッグ時など、一定の条件を満たして
>  いる時は常に、マウスポイント付近にテキストを表示させたい。
> ・仕様の満たし方と問題点と理想
>  このとき、ラベルを使用すると、処理が遅れる
>  ピクチャボックスをクリアしてしまうと、1の図面が消える
>  リドロウしてしまうと、1の図面の複雑さに比例して極端に処理が遅れる
> ※マウスが動いたら、動く前のテキストのみを消し、マウスが動いたポイントにテキストを描画したい。

背景の設計図は、Imageである必要があるんでしょうか?
Pictureプロパティーに入れてしまえば、.Clsメソッドで消えませんが・・・。

 Picture1.Picture = Picture1.Image

投稿時間:2006/10/30(Mon) 17:19
投稿者名:Edward
Eメール:
URL :
タイトル:
Re: ラバーバンドの応用(質問内容を簡素にしました)
Renardさんからも有りましたととおりPictureでは.Clsを呼ぶだけでよいと思うのですが。
線分等を書き込んでいるのならば、こんな物を作ってみました。
PictureBoxが小さい時は快適に動くのですが
図面を表示するとの事ですから、きっと全画面表示に近いくらいの大きさになるのでは
ないかと思いますが。その位の大きさになると文字列がちらつきますのでMouseMoveの度に
文字列で隠れてしまう範囲だけを保存・貼付・解放を繰り返すようにすると使用メモリも
少なくよいのかもしれませんが。
何方かチャレンジしてみて下さい。

Option Explicit
Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function SetStretchBltMode Lib "gdi32" (ByVal hdc As Long, ByVal nStretchMode As Long) As Long
Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, _
     ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function StretchBlt Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, _
     ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, _
     ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Const SRCCOPY = &HCC0020
Private Const STRETCH_DELETESCANS = 3
Private Const STRETCH_HALFTONE = 4
Dim g_hMemoryDC  As Long
Dim g_hBitmap    As Long
Dim g_hOldBitmap As Long
Dim g_Mode       As Boolean

Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
    g_Mode = True
    Call PictureCopy(Picture1, 1)
End Sub

Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
    If g_Mode = True And Button = 1 Then
        Call PictureCopy(Picture1, 2)
        Picture1.ForeColor = RGB(255, 0, 0)
        Picture1.PSet (X, Y)
        Picture1.Print "  X=" & X & ",Y=" & Y
    End If
End Sub

Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    g_Mode = False
    Call PictureCopy(Picture1, 2)
    Call PictureCopy(Picture1, 3)
End Sub

Private Sub Form_Load()
    Dim i As Integer
    With Picture1
        .AutoRedraw = True
        .ScaleMode = vbPixels
        Set .Picture = LoadPicture("C:\WINNT\グリーン ストーン.bmp")
        For i = 0 To 10
            Picture1.Line (0, 0)-(Picture1.Width, Picture1.Height * (i / 10))
        Next i
    End With
End Sub

Private Sub PictureCopy(Pic1 As PictureBox, WorkNo As Integer)
    Dim Ret     As Long
    With Pic1
        If WorkNo = 1 Then
            g_hMemoryDC = CreateCompatibleDC(.hdc)
            g_hBitmap = CreateCompatibleBitmap(.hdc, .ScaleWidth, .ScaleHeight)
            g_hOldBitmap = SelectObject(g_hMemoryDC, g_hBitmap)
            BitBlt g_hMemoryDC, 0&, 0&, .ScaleWidth, .ScaleHeight, .hdc, 0&, 0&, SRCCOPY
        ElseIf WorkNo = 2 Then
            Ret = SetStretchBltMode(.hdc, STRETCH_DELETESCANS)
            StretchBlt .hdc, 0&, 0&, .ScaleWidth, .ScaleHeight, g_hMemoryDC, 0&, 0&, .ScaleWidth, .ScaleHeight, SRCCOPY
            Ret = SetStretchBltMode(.hdc, Ret)
            .Refresh
        ElseIf WorkNo = 3 Then
            DeleteDC g_hMemoryDC
            DeleteObject g_hBitmap
        End If
    End With
End Sub

投稿時間:2006/10/30(Mon) 17:38
投稿者名:Edward
Eメール:
URL :
タイトル:
Re^2: ラバーバンドの応用(質問内容を簡素にしました)
PictureCopy()の中でMouseMoveの度に.Refreshを呼ぶのではなく
Picture1_MouseUpで一回呼ぶだけにしたらちらつかなくなりましたね。

Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
    g_Mode = False
    Call PictureCopy(Picture1, 2)
    Picture1.Refresh          'ここに移動
    Call PictureCopy(Picture1, 3)
End Sub

Private Sub PictureCopy(Pic1 As PictureBox, WorkNo As Integer)
    Dim Ret     As Long
    With Pic1
        If WorkNo = 1 Then
            g_hMemoryDC = CreateCompatibleDC(.hdc)
            g_hBitmap = CreateCompatibleBitmap(.hdc, .ScaleWidth, .ScaleHeight)
            g_hOldBitmap = SelectObject(g_hMemoryDC, g_hBitmap)
            BitBlt g_hMemoryDC, 0&, 0&, .ScaleWidth, .ScaleHeight, .hdc, 0&, 0&, SRCCOPY
        ElseIf WorkNo = 2 Then
            Ret = SetStretchBltMode(.hdc, STRETCH_DELETESCANS)
            StretchBlt .hdc, 0&, 0&, .ScaleWidth, .ScaleHeight, g_hMemoryDC, 0&, 0&, .ScaleWidth, .ScaleHeight, SRCCOPY
            Ret = SetStretchBltMode(.hdc, Ret)
'            .Refresh      'コメントアウト
        ElseIf WorkNo = 3 Then
            DeleteDC g_hMemoryDC
            DeleteObject g_hBitmap
        End If
    End With
End Sub

投稿時間:2006/10/31(Tue) 10:19
投稿者名:xuexue
Eメール:
URL :
タイトル:
Re^3: ラバーバンドの応用(質問内容を簡素にしました)
Edward さん

ご回答ありがとうございました。
ソースコードつきで、初心者にとって、わかりやすかったです。

とりあえず、これから試してみます。
また、何か出てきたらご相談差し上げることにします。
ありがとうございました!

投稿時間:2006/10/31(Tue) 12:21
投稿者名:xuexue
Eメール:
URL :
タイトル:
Re^3: ラバーバンドの応用(質問内容を簡素にしました)
Edward さん

ご回答ありがとうございました。
ソースコードつきで、初心者にとって、わかりやすかったです。

これから試してみます。
また、何か出てきたらご相談差し上げることにします。
ありがとうございました!