お世話になります。
現在、ユーザーフォームにて管理アプリもどきを作成しているのですが、
以下の様な動作を行うことが可能かどうか、
また可能であればどのような方法があるのかをご教授ください。
//////////////////////////////////////////////////////////
フォーム上に、トグルボタンを複数個配置します。
例として、下図をトグルボタンを5つ配置したものと仮定します。
Valueプロパティは全てFalseを初期値とします。
□□□□□
左から2つ目のトグルボタン上でマウスクリックし、
そのままクリックを押し込んだままの状態にします。
この時点で、2つ目のボタンのValueプロパティをTrueに変更します。
□■□□□
↑クリック(押し込んだまま)
クリックを押し込んだまま、マウスを右に移動させます。
左から3つ目、4つ目のボタン上にカーソルがきた時点で
3つ目、4つ目のValueプロパティをTrueに変更します。
□■■■□
↑クリック(押し込んだまま)
左から4つ目のトグルボタン上でクリックを離します。
クリックされていない状態でマウスカーソルが上に乗っても
Valueの変更は行われません。
//////////////////////////////////////////////////////////
MouseMoveを試してみましたが、ドラッグ中は処理が発生しないようなので
どうしたものか困ってしまいました。
ご助力、よろしくお願い致します。
A 回答 (3件)
- 最新から表示
- 回答順に表示
No.3
- 回答日時:
#1-2ですが、ひょっとしてUserForm_MouseDownなら、OnTimeのお世話にならなくてもいけるのではと思ってトライしてみるとOKでした。
おかげで動作も軽快になりました。ついでに物好きな御仁のために若干のバグフィックス(誤動作防止)もしてあります。☆標準モジュール
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Declare Function GetActiveWindow Lib "user32" () As Long
Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Public Declare Function ScreenToClient Lib "user32" (ByVal hWnd As Long, lpPoint As POINTAPI) As Long
Public Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long
Public Type POINTAPI
X As Long
Y As Long
End Type
Public Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Public Const VK_LBUTTON = &H1 '[LeftClick]
Public Const VK_RBUTTON = &H2 '[RightClick]
Sub test()
UserForm1.Show
End Sub
☆UserForm1モジュール
Dim hWnd As Long
Private myToggle() As MSForms.ToggleButton
Private myRect() As RECT
Private initialColor As Long
'UserFormのハンドル取得。 ScreenToClient APIで使用。
Private Sub UserForm_Activate()
hWnd = GetActiveWindow()
End Sub
Private Sub UserForm_Initialize()
Dim myControl As Control
Dim scaleFactor As Single
scaleFactor = 96 / 72
'配列の添え字0の要素は使わない
ReDim myToggle(0 To 0)
ReDim myRect(0 To 0)
For Each myControl In Me.Controls
If TypeName(myControl) = "ToggleButton" Then
myControl.Enabled = False
myControl.Caption = ""
ReDim Preserve myToggle(0 To UBound(myToggle) + 1)
ReDim Preserve myRect(0 To UBound(myRect) + 1)
Set myToggle(UBound(myToggle)) = myControl
With myRect(UBound(myRect))
.Left = CLng(myControl.Left * scaleFactor)
.Top = CLng(myControl.Top * scaleFactor)
.Right = CLng((myControl.Left + myControl.Width) * scaleFactor)
.Bottom = CLng((myControl.Top + myControl.Height) * scaleFactor)
End With
End If
Next
initialColor = myToggle(1).BackColor
End Sub
'Private Sub UserForm_Click()だと、ボタンを離さないとEventが発生しない
Private Sub UserForm_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim tempToggle As MSForms.ToggleButton
Dim initialState As Boolean
Dim toggleNo As Long, currentToggleNo As Long
'最初のクリック箇所を保持
If Button <> VK_LBUTTON Then Exit Sub
currentToggleNo = getToggleNo()
With myToggle(currentToggleNo)
initialState = .Value
.Value = Not (initialState)
.BackColor = IIf(initialState, initialColor, vbBlue)
End With
'無限ループでマウスのモニタ
Do
DoEvents: DoEvents: DoEvents
Sleep 10
toggleNo = getToggleNo
If toggleNo <> 0 Then
Set tempToggle = myToggle(toggleNo)
With tempToggle
.Value = Not (initialState)
.BackColor = IIf(initialState, initialColor, vbBlue)
End With
Set tempToggle = Nothing
End If
'マウスの左ボタンを離すまでループ
Loop While GetAsyncKeyState(VK_LBUTTON)
End Sub
'マウスの存在する位置のトグルボックスのNoを取得。取得失敗は0を戻す。
Private Function getToggleNo() As Long
Dim pos As POINTAPI
Dim ret As Long
Dim i As Long
'Screen座標→Client座標に変換。RECT配列内の値はUserForm座標→Client座標に変換済み。
GetCursorPos pos
ret = ScreenToClient(hWnd, pos)
For i = 1 To UBound(myRect)
With myRect(i)
If (pos.X >= .Left) And (pos.X <= .Right) And (pos.Y >= .Top) And (pos.Y <= .Bottom) Then
getToggleNo = i
Exit Function
End If
End With
Next i
getToggleNo = 0
End Function
No.2
- 回答日時:
#1です。
だいぶ苦労の果てに動いたので、思わず投稿してしまいましたが、本来デバッグを容易にするために動的に配置したトグルボタンを対象にしていたのでした。既設トグルボタンを対象とする様に改造しました。一部のプロシージャの置き換え程度で可能です。なお、マウスの動かし初めで漏らしてしまう現象は、最初のトグルボタンの状態が変わるまで一呼吸待つと良い事がわかりました。ご参考まで。
変更部分のみ記載します。
☆ 標準モジュール toggleControlModule
'構造体追加
Public Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
☆ UserForm1モジュール
'変数の追加
Private myRect() As RECT
Private initialColor As Long
'関数の置き換え
Private Sub UserForm_Initialize()
Dim myControl As Control
Dim scaleFactor As Single
scaleFactor = 96 / 72
'配列の添え字0の要素は宣言しているだけで使っておりません
'都度添え字の最大を求めるのは誉められないと思いますが...
ReDim myToggle(0 To 0)
ReDim myRect(0 To 0)
'既設トグルボタンと、その座標を配列に取り込む
For Each myControl In Me.Controls
If TypeName(myControl) = "ToggleButton" Then
myControl.Enabled = False
myControl.Caption = ""
ReDim Preserve myToggle(0 To UBound(myToggle) + 1)
ReDim Preserve myRect(0 To UBound(myRect) + 1)
Set myToggle(UBound(myToggle)) = myControl
With myRect(UBound(myRect))
.Left = myControl.Left * scaleFactor
.Top = myControl.Top * scaleFactor
.Right = (myControl.Left + myControl.Width) * scaleFactor
.Bottom = (myControl.Top + myControl.Height) * scaleFactor
End With
End If
Next
initialColor = myToggle(1).BackColor
End Sub
'少しは高速かと思い、座標の照合はRECT構造体と行う様にしてみました
Private Function getToggleNo() As Long
Dim pos As POINTAPI
Dim ret As Long
Dim i As Long
GetCursorPos pos
ret = ScreenToClient(hWnd, pos)
For i = 1 To UBound(myRect)
With myRect(i)
If (pos.X >= .Left) And (pos.X <= .Right) And (pos.Y >= .Top) And (pos.Y <= .Bottom) Then
getToggleNo = i
Exit Function
End If
End With
Next i
getToggleNo = 0
End Function
'おまけ トグルボタンの色を変える
Public Sub ontimesub()の中で、
.Value = Not (initialState)
のところに、下記を追加する。
.BackColor = IIf(initialState, initialColor, vbBlue)
No.1
- 回答日時:
もうご覧になっていないかもしれませんが、それらしい動作が実現出来たのでUpしておきます。
自分でも来週には分からなくなるかも知れないので珍しくコメントを沢山入れました...
ToggleButtonのイベントを使うとうまくいかなかったので、DisableにしてUserFormのイベントで操作しています。
押し込んでない状態のボタンからスタートすると、通過したボタンを押し込み、押し込んだボタンからスタートすると逆の動作をします。特に動かし初めは、あまり速くマウスを動かすと漏らしますのでご注意下さい。
実用的ではないと存じますが、話の種にどうぞ。
☆標準モジュール toggleControlModule
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Declare Function GetActiveWindow Lib "user32" () As Long
Public Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
Public Declare Function ScreenToClient Lib "user32" (ByVal hWnd As Long, lpPoint As POINTAPI) As Long
Public Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long
Public Type POINTAPI
X As Long
Y As Long
End Type
Public Const VK_LBUTTON = &H1 '[LeftClick]
Public Const VK_RBUTTON = &H2 '[RightClick]
Private nextTriggerTime As Date
Sub test()
UserForm1.Show
End Sub
'UserForm側でApplication.Ontimeが実行出来ないので仲立ちをする
Public Sub setOnTime()
nextTriggerTime = [now()+"00:00:00.50"]
Application.OnTime nextTriggerTime, "onTimer"
End Sub
Public Sub onTimer()
UserForm1.ontimesub
End Sub
☆UserForm1モジュール toggleButtonは動的に設置するので、コントロールは配置無用
Dim hWnd As Long
Private myToggle() As MSForms.ToggleButton
Private xframe As Single, yframe As Single
Private myStartToggle As Long
Const BUTTONCOUNT As Long = 15
Const COLUMNCOUNT As Long = 5
Const SIDELENGTH As Long = 40
Private Sub UserForm_Initialize()
Dim i As Long
With Me
xframe = .Width - .InsideWidth
yframe = .Height - .InsideHeight
End With
ReDim myToggle(1 To BUTTONCOUNT)
For i = 1 To BUTTONCOUNT
Set myToggle(i) = Controls.Add("Forms.ToggleButton.1")
With myToggle(i)
'UserFormのイベントを用いるためにtoggleButtonはDisableにする。値の変更は可能。
.Enabled = False
.Width = SIDELENGTH
.Height = SIDELENGTH
.Left = SIDELENGTH * ((i - 1) Mod COLUMNCOUNT)
.Top = SIDELENGTH * ((i - 1) \ COLUMNCOUNT)
End With
Next i
With Me
.Width = xframe + SIDELENGTH * COLUMNCOUNT
.Height = yframe + SIDELENGTH * (BUTTONCOUNT \ COLUMNCOUNT)
End With
End Sub
Private Sub UserForm_Activate()
hWnd = GetActiveWindow()
End Sub
'Private Sub UserForm_Click()だと、ボタンを離さないとEventが発生しないらしい
Private Sub UserForm_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'最初のクリック箇所を保持
Me.startToggle = getToggleNo()
'イベントを直ぐに抜けるために、次の処理はApplication.OnTimeで起動する
'UserFormからは直には使えないので、標準モジュールに仲立ちをしてもらう
toggleControlModule.setOnTime
End Sub
Public Sub ontimesub()
Dim tempToggle As MSForms.ToggleButton
Dim initialState As Boolean
With myToggle(Me.startToggle)
initialState = .Value
'状態変更の前にEnabled=True,変更後にEnabled=Falseにする必要があると考えたが無くてもOKだった
.Value = Not (initialState)
End With
Do
DoEvents: DoEvents: DoEvents
Sleep 10
Set tempToggle = myToggle(getToggleNo())
With tempToggle
.Value = Not (initialState)
End With
Set tempToggle = Nothing
'マウスの左ボタンを離すまでループ
Loop While GetAsyncKeyState(VK_LBUTTON)
End Sub
Private Function getToggleNo() As Long
Dim pos As POINTAPI
Dim ret As Long
Dim toggleId As Long
GetCursorPos pos
ret = ScreenToClient(hWnd, pos)
With pos
'UserForm座標系の値に戻す
.X = .X * 72 / 96
.Y = .Y * 72 / 96
getToggleNo = (.X \ SIDELENGTH) + (.Y \ SIDELENGTH) * COLUMNCOUNT + 1
End With
End Function
Public Property Let startToggle(toggleNo As Long)
myStartToggle = toggleNo
End Property
Public Property Get startToggle() As Long
startToggle = myStartToggle
End Property
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/12】 急に朝起こしてきた母親に言われた一言とは?
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・好きな「お肉」は?
- ・あなたは何にトキメキますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・チョコミントアイス
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・あなたの習慣について教えてください!!
- ・ハマっている「お菓子」を教えて!
- ・高校三年生の合唱祭で何を歌いましたか?
- ・【大喜利】【投稿~11/1】 存在しそうで存在しないモノマネ芸人の名前を教えてください
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・家の中でのこだわりスペースはどこですか?
- ・つい集めてしまうものはなんですか?
- ・自分のセンスや笑いの好みに影響を受けた作品を教えて
- ・【お題】引っかけ問題(締め切り10月27日(日)23時)
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ロジクールのマウスのサイドボ...
-
マウスを左クリックすると、右...
-
マウスの左クリックを長押しし...
-
C# DataGridView の列ヘッダー...
-
クリックがボタンを離すときに...
-
マウスを左クリックしたとき、...
-
カチカチとクリック音がするマ...
-
マウスの左クリックで右クリッ...
-
右クリックができない場合の対...
-
マウスをクリックすると、たま...
-
マウスのチャタリング現象が起...
-
レーザーマウスのポインタだけ...
-
AutoCAD2010 マウスの動きがカ...
-
マウスの使いすぎで人差し指が...
-
マウスのホーイルクリックが反...
-
マウスの左クリックがホールド...
-
マウスで左クリックすると範囲...
-
マウスの持ち方を教えて下さい
-
仕事用PC、通信速度が測定でき...
-
マウスをクリックすると出てく...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ロジクールのマウスのサイドボ...
-
マウスを左クリックすると、右...
-
カチカチとクリック音がするマ...
-
マウスを左クリックしたとき、...
-
マウスの左クリックを長押しし...
-
マウスで左クリックすると範囲...
-
マウスの左クリックがホールド...
-
マウスの操作がおかしい
-
apex中に戦闘画面でマウスが動...
-
クリックがボタンを離すときに...
-
マウスの左クリックで右クリッ...
-
仕事用PC、通信速度が測定でき...
-
マウスの持ち方を教えて下さい
-
マウスをクリックすると、たま...
-
ロボみたいなマウス使ってる人...
-
マウスをクリックすると出てく...
-
右クリックができない場合の対...
-
C# DataGridView の列ヘッダー...
-
タッチパッドの左クリックが故...
-
マウスの反応がよすぎる・・・
おすすめ情報