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

投稿時間:2005/01/26(Wed) 16:36
投稿者名:ジム
Eメール:
URL :
タイトル:
SetMenuItemInfoについて
SetMenuItemInfoを利用してメニューを操作禁止にしたいのですが、どうパラメータを
与えたらよいかわかりません。(VB6の機能のEnabled プロパティではうまくいかなかったので
API関数を使用することになりました)

Private Declare Function SetMenuItemInfo Lib "user32" Alias "SetMenuItemInfo
A" (ByVal hMenu
As Long, ByVal un As Long, ByVal bool As Boolean, lpcMenuItemInfo As MENUITEMINFO) As Long

Private Type MENUITEMINFO
    cbSize As Long
    fMask As Long
    fType As Long
    fState As Long
    wID As Long
    hSubMenu As Long
    hbmpChecked As Long
    hbmpUnchecked As Long
    dwItemData As Long
    dwTypeData As String
    cch As Long
End Type

Private lpcMenuItemInfo As MENUITEMINFO

とここまではよかったのですが、メニューバーのハンドルはもちろん、その他の引数を
どう与えたらよいかわかりませんでした。

ハンドルを与えようと思い。mnuOption (メニューの名前です)のプロパティをみてもhWndは
ありませんでした。どなたか教えて下さい。

投稿時間:2005/01/26(Wed) 17:28
投稿者名:ポン助
Eメール:
URL :
タイトル:
Re: SetMenuItemInfoについて
> SetMenuItemInfoを利用してメニューを操作禁止にしたいのですが、どうパラメータを
> 与えたらよいかわかりません。(VB6の機能のEnabled プロパティではうまくいかなかったので
> API関数を使用することになりました)

VBのMenuオブジェクトからそのサブメニューハンドルやコマンドIDを参照
するのは、不可能ではありませんが、かなり面倒です。

それよりも、Enabled プロパティでうまくいかなかった原因を特定し、
それを回避する様にした方がいいのでは?

投稿時間:2005/01/26(Wed) 17:42
投稿者名:ジム
Eメール:
URL :
タイトル:
Re^2: SetMenuItemInfoについて
ご回答ありがとうございます。
Enabled を Falseにして操作禁止にはなってもマウスを移動してクリックすると
フォーカスが移動してしまい。他のプロセスが停止してしまうのです。ですから
API関数でなんとかならないかなと思い思考錯誤しています。

投稿時間:2005/01/26(Wed) 19:56
投稿者名:ポン助
Eメール:
URL :
タイトル:
Re^3: SetMenuItemInfoについて
> ご回答ありがとうございます。
> Enabled を Falseにして操作禁止にはなってもマウスを移動してクリックすると
> フォーカスが移動してしまい。他のプロセスが停止してしまうのです。ですから
> API関数でなんとかならないかなと思い思考錯誤しています。

このことかな?
hhttp://hpcgi1.nifty.com/MADIA/VBBBS/wwwlng.cgi?print+200412/04120059.txt

API関数でメニュー項目の状態を無効(MFS_DISABLED)に設定しても、
VBのEnabledプロパティをFalseにしたのと同じなので、解決にはならないと思いますよ。
どうしても、やってみたいなら、こんな感じ。

    ' メニューバーの左端アイテム(iIndex=0)を無効にする例。
    Dim hMenu As Long
    Dim mii As MENUITEMINFO
    Dim iIndex As Long
    Dim dwRetval As Long
        
    hMenu = GetMenu(Me.hwnd)
    iIndex = 0
    With mii
        .cbSize = Len(mii)
        .fMask = MIIM_STATE Or MIIM_ID Or MIIM_SUBMENU Or _
                 MIIM_CHECKMARKS Or MIIM_TYPE Or MIIM_DATA
        .fType = MFT_STRING
        .dwTypeData = StrPtr(Space$(128))
        .cch = 128
        dwRetval = GetMenuItemInfo(hMenu, iIndex, 1, mii)
        .fState = MFS_DISABLED
    End With
    dwRetval = SetMenuItemInfo(hMenu, iIndex, 1, mii)
    dwRetval = DrawMenuBar(Me.hwnd)

それよりも、旧スレの回答にあるSetMenuInfo API関数を試した方がいいかも?

投稿時間:2005/01/27(Thu) 00:09
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^4: SetMenuItemInfoについて
> hhttp://hpcgi1.nifty.com/MADIA/VBBBS/wwwlng.cgi?print+200412/04120059.txt

掲示板の移動ですか?

SetMenuItemInfo APIを使用してもメニューを非表示(一時削除)にしないとフォーカスが
移るのでModifyMenu APIを使った場合(先ほどのサンプル)も同じかと思います。

メニューを非表示(一時削除)にするのがいやなら
マウスでクリック出来ないようにすればいいのでは。
ここの逆引きヘルプの マウスの移動範囲を制限する で可能です。
又は、メニューのところへマウスが行かないようにすればいいのでは。

投稿時間:2005/01/27(Thu) 13:08
投稿者名:ジム
Eメール:
URL :
タイトル:
Re^5: SetMenuItemInfoについて
そうです。一度、「終わった」と思ったのですが、結局わからなくてここに書き込みました。
すみません。一度終わって移動するのもマルチポストになるのでしょうか?
マウスの移動範囲を制限すると確かにメニューバーにはマウスを移動できないです。
しかし、フォームにプログレスバーを貼り付けて動作させると、マウスの制限が解除されてしまいます

投稿時間:2005/01/27(Thu) 13:43
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^6: SetMenuItemInfoについて
> しかし、フォームにプログレスバーを貼り付けて動作させると、マウスの制限が解除されてしまいま

> 。
どのようにされたのでしょうか?
私がテストした限りでは問題がありませんでしたが、その上で提案したのですが。

投稿時間:2005/01/27(Thu) 15:54
投稿者名:ジム
Eメール:
URL :
タイトル:
コンボBOXを禁止にすると解除されてしまいます
毎回ありがとうございます。
プログレスバーのせいではありませんでした。間違いです。コンボBOXをFalseにすると解除
されてしまうようです。Command3_Click() 内の記述

Option Explicit     'SampleNo=104 WindowsXP VB6.0(SP5) 2002.05.19
'マウスカーソルの移動範囲を制限する(P384)
Private Declare Function ClipCursor Lib "user32" (lpRect As Any) As Long
'クライアント座標からスクリーン座標に交換する(P514)
Private Declare Function ClientToScreen Lib "user32" _
        (ByVal hwnd As Long, lpPoint As POINTAPI) As Long
'マウスカーソの移動範囲取得する(P386)
Private Declare Function GetClipCursor Lib "user32" (lprc As RECT) As Long
'カーソルを表示・非表示にする(P390)
'0以上の時表示  0未満の時非表示
Private Declare Function ShowCursor Lib "user32" _
        (ByVal bShow As Long) As Long
'座標の構造体
Private Type POINTAPI
    X As Long
    y As Long
End Type
'移動範囲の構造体
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private LookOff As RECT   '構造体用変数


Private Sub Form_Load()
    '初期値の取得
    GetClipCursor LookOff
    Timer1.Interval = 100
End Sub


Private Sub Command1_Click()
'マウスカーソルの移動範囲を制限し、非表示に
    Dim MoLook As RECT
    Dim LookPo As POINTAPI
    ClientToScreen Me.hwnd, LookPo
    '移動範囲を設定(何も貼り付けていない所)
    MoLook.Left = LookPo.X
    MoLook.Top = LookPo.y + 20
    MoLook.Right = LookPo.X + 300
    MoLook.Bottom = LookPo.y + 300
    'マウスカーソルを非表示
'    sMouseVisible False
    'マウスカーソルをロック
    ClipCursor MoLook
End Sub

Private Sub Command2_Click()
'マウスカーソルの移動範囲を解除し、表示する
    'マウスカーソルのロック解除
    ClipCursor LookOff
    'マウスカーソルを表示
'    sMouseVisible True
End Sub


Private Sub Form_Unload(Cancel As Integer)
'念のため終了時に初期値に戻す。
    ClipCursor LookOff
    sMouseVisible True
    Unload Me
End Sub

Private Sub sMouseVisible(ByVal MoOnOff As Boolean)
'マウスカーソル表示・非表示用プロシージャ
    'マウスの表示・非表示の設定
    Dim flglook As Boolean
    Dim ret As Long
    flglook = MoOnOff
'    ret = ShowCursor(flglook)
    'カウント過剰UPの防止
    Do While ret <> flglook
        If ret < -1 Then
            flglook = True
        ElseIf ret > 0 Then
            flglook = False
        End If
        ret = ShowCursor(flglook)
    Loop
End Sub


Private Sub Command3_Click()
    Dim i As Integer
    Combo1.Enabled = False          ' コンボ BOX を操作禁止にする。
    ProgressBar1.Max = 30
    ProgressBar1.Min = 0
    Timer1.Enabled = True
    For i = 0 To 30
        ProgressBar1.Value = i
        Do Until Timer1.Enabled = False
            DoEvents
        Loop
        Timer1.Enabled = True
    Next i

End Sub

Private Sub Timer1_Timer()
    Timer1.Enabled = False
End Sub

投稿時間:2005/01/27(Thu) 16:09
投稿者名:ジム
Eメール:
URL :
タイトル:
Re: コンボBOXを禁止にすると・・・
すみません。コンボBOXを禁止にした後で、マウスをロックすればいいことでした。
でも、なぜコンボBOXを操作禁止にすれば、マウスロックが解除されるかわかりません。

投稿時間:2005/01/27(Thu) 18:30
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
不思議ですね
> でも、なぜコンボBOXを操作禁止にすれば、マウスロックが解除されるかわかりません。

私の所でも確認できましたが、原因は解りません。不思議な現象ですね。

でもこういった使い方をしていてこういう風になるといった現象は、最初の質問の時に
して置くべきかと思います。
そうすれば、もっと解決までの道が早かったと思いますよ。ポン助さんの投稿がなかったら
もっと時間がかかっていたり。

ここの初めにお読み下さいの中の掲示板の利用方法のところを読んでおいて下さい。

# マウスの移動範囲を下記のように指定すれば、ホーム内(メニューバーを除く)なら
 自由に移動できます。
  勿論、フォームのドラッグで処理が中断する事もありません。
    Dim MoLook As RECT
    Dim LookPo As POINTAPI
    ClientToScreen Me.hwnd, LookPo
    MoLook.Left = LookPo.X
    MoLook.Top = LookPo.Y  
    MoLook.Right = LookPo.X + (Me.ScaleWidth / 15)
    MoLook.Bottom = LookPo.Y + (Me.ScaleHeight / 15)
    'マウスカーソルをロック
    ClipCursor MoLook

投稿時間:2005/01/28(Fri) 11:17
投稿者名:ジム
Eメール:
URL :
タイトル:
(解決)
そうですね。どうもすみませんでした。手際が悪くて。

投稿時間:2005/01/27(Thu) 19:44
投稿者名:ポン助
Eメール:
URL :
タイトル:
Re^4: SetMenuItemInfoについて
> それよりも、旧スレの回答にあるSetMenuInfo API関数を試した方がいいかも?

既に、解決されているとは思いますが、
SetMenuInfo API関数で、モードレス・メニュー・スタイルに変更する方法です。
この方法の妥当性については、解かりませんが・・・

Option Explicit

Private Type MENUINFO
    cbSize As Long
    fMask As Long
    dwStyle As Long
    cyMax As Long
    hbrBack As Long
    dwContextHelpID As Long
    dwMenuData As Long
End Type

Private Const MIM_STYLE As Long = &H10
Private Const MNS_MODELESS As Long = &H40000000

Private Declare Function SetMenuInfo Lib "user32" _
        (ByVal hMenu As Long, lpcmi As MENUINFO) As Long
Private Declare Function GetMenu Lib "user32" _
        (ByVal hwnd As Long) As Long

Private Sub Command1_Click()
' メニューバーをモードレスに変更する。
Dim hMenu As Long
Dim mi As MENUINFO
    hMenu = GetMenu(Me.hwnd)
    With mi
        .cbSize = Len(mi)
        .fMask = MIM_STYLE
        .dwStyle = MNS_MODELESS
    End With
    Call SetMenuInfo(hMenu, mi)
End Sub

投稿時間:2005/01/28(Fri) 07:34
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^5: SetMenuItemInfoについて
> SetMenuInfo API関数で、モードレス・メニュー・スタイルに変更する方法です。
> この方法の妥当性については、解かりませんが・・・

どうも標準でモードレスになっているのではないでしょうか。必要ならもう少し
使っているサンプルが見つかると思うのですが、海外にしかそれも数件しか見つからないし
先のリンク先のこの回答は未検証の回答では。
>SetMenuInfo API関数で、モードレスメニューにしてしまう。
>ってのはありかな?

メモ帳やIEのメニューでも同様にグレー表示でもフォーカスが移動します。
但し、Excel や Word のメニューはフォーカスが移動しません。
従って何か方法があるのかも知れません。(アイコン付きのメニューにするとか。これも
未検証です。)

投稿時間:2005/01/28(Fri) 10:47
投稿者名:ポン助
Eメール:
URL :
タイトル:
Re^6: SetMenuItemInfoについて
> どうも標準でモードレスになっているのではないでしょうか。

ダメでしたか。
当方では、Win98+VB6でしか試していませんが、フォーカスも移動せず、
ProgressBarも停止しませんでした。
当然ながら、メニューのEnabledプロパティはFalseにしています。
環境に依存するんでしょうかね?

で、メニュースタイルが、モーダルかモードレスかを取得する
GetMenuInfoを追加してみました。
ボタンのクリックでモーダル/モードレスが交互に切り替わると思います。

Private Declare Function GetMenuInfo Lib "user32" _
        (ByVal hMenu As Long, lpcmi As MENUINFO) As Long

Private Sub Command1_Click()
    Dim mi As MENUINFO
    Dim hMenu As Long
    Dim dwRetval As Long
  
    hMenu = GetMenu(Me.hwnd)
    With mi
        .cbSize = Len(mi)
        .fMask = MIM_STYLE
        dwRetval = GetMenuInfo(hMenu, mi)
        If dwRetval = 0 Then Debug.Print "GetMenuInfo() fails"
        If (.dwStyle And MNS_MODELESS) = MNS_MODELESS Then
            .dwStyle = .dwStyle Xor MNS_MODELESS
            Command1.Caption = "Modal"
        Else
            .dwStyle = .dwStyle Or MNS_MODELESS
            Command1.Caption = "Modeless"
        End If
    End With
    dwRetval = SetMenuInfo(hMenu, mi)
    If dwRetval = 0 Then Debug.Print "SetMenuInfo() fails"
End Sub

投稿時間:2005/01/28(Fri) 12:35
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^7: SetMenuItemInfoについて
> 当方では、Win98+VB6でしか試していませんが、フォーカスも移動せず、
> ProgressBarも停止しませんでした。
> 当然ながら、メニューのEnabledプロパティはFalseにしています。
> 環境に依存するんでしょうかね?

私は、WinXP VB6.0(SP6) で試しました。
フォーカスが移動していたのだめだなと思って後は試さなかったのですが、ProgressBarは停止
しませんね。(フォーカスは移動します)

> ボタンのクリックでモーダル/モードレスが交互に切り替わると思います。
こちらについては特に変化がありませんね。
一度設定すれば、有効かどちらでもProgressBarが停止することはありませんね。
(どうも、メニューにフォーカスある状態で切り替えても有効にならないようですね)
フォーカスは、どちらでも相変わらず移りますね。

これで3方法が完成ですね。\(-o-)/

投稿時間:2005/01/26(Wed) 17:50
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: SetMenuItemInfoについて
API の使用方法が解らなければ、そのAPIをキーワードに検索して下さい。
又、SetMenuItemInfo だけでは操作できません。他に7個位のAPIを使用する事に
なるかと思います。
SetMenuItemInfo でのサンプルよりもModifyMenuで作成したサンプルの方が多いようです。
SetMenuItemInfo は少し複雑になるので、私のサンプル(No.142)もModifyMenu で作成しております。
宣言のところでつまづいていたのでは前途多難かと、ポン助さんのアドバイスで進めた方がいいような

投稿時間:2005/01/26(Wed) 18:23
投稿者名:ジム
Eメール:
URL :
タイトル:
SetMenuでの対処について
ご回答ありがとうございます。
メニュー表示は非表示になりましたが、ウィンドウ画面がメニューの分だけシフトしてしまいます。
非表示でもいいのですが、画面がずれない方法はないでしょうか?
ModifyMenu()についてヘルプで調べてみましたが、
「この関数は SetMenuItemInfo 関数に取って代わられましたが、まだ使用できます」となってました。
ので調査することはできませんでした。

投稿時間:2005/01/26(Wed) 19:04
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: SetMenuでの対処について
> 非表示でもいいのですが、画面がずれない方法はないでしょうか?
それを実現したら次の要求が出てくるでしょう。
(メニューの高さ分だけコントロールを移動させれば画面がずれないですが)

> ので調査することはできませんでした。
調べる気があるならいくらでも調査できます。VBのヘルプでも5番目に記載されています。

>API の使用方法が解らなければ、そのAPIをキーワードに検索して下さい。
hhttp://www.google.com/search?q=ModifyMenu&num=50&hl=ja&filter=0&lr=lang_ja&ie=Shift_JIS

又、ModifyMenu で調べていたら下記も見つかるし
hhttp://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpwinui/html/_win32_enablemenuitem.asp

調べる気がないなら使用をあきらめて下さい。

投稿時間:2005/01/27(Thu) 12:07
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
これもお気に召しませんか?
> > 非表示でもいいのですが、画面がずれない方法はないでしょうか?
> それを実現したら次の要求が出てくるでしょう。
> (メニューの高さ分だけコントロールを移動させれば画面がずれないですが)

Option Explicit
'メニューを設定・削除する(P138)
Private Declare Function SetMenu Lib "user32" _
    (ByVal hwnd As Long, ByVal hMenu As Long) As Long
'メニューオブジェクトのハンドルを取得する(P124)
Private Declare Function GetMenu Lib "user32" _
    (ByVal hwnd As Long) As Long
Private hwndMenu As Long
Private hFlag As Boolean
Private Hbar  As Long
Private Sub Command1_Click()
'メニューを削除(非表示)
    Dim sh  As Long
    Dim sh1 As Long
    sh = Me.ScaleHeight
    Call SetMenu(Me.hwnd, 0)
    sh1 = Me.ScaleHeight
    If sh <> sh1 Then
        hFlag = True
        Hbar = sh1 - sh
        Dim i As Long
        On Error Resume Next
        'メニューバーが消えてコントロールのTopが変った分だけ補正
        For i = 0 To Controls.Count - 1
            Controls(i).Top = Controls(i).Top + Hbar
        Next i
    End If
End Sub
Private Sub Command2_Click()
'メニューを設定(表示)
    Call SetMenu(Me.hwnd, hwndMenu)
    If hFlag = True Then
        hFlag = False
        Dim i As Long
        On Error Resume Next
        'コントロールのTopを元の位置に戻す
        For i = 0 To Controls.Count - 1
            Controls(i).Top = Controls(i).Top - Hbar
        Next i
    End If
End Sub
Private Sub Form_Load()
    'メニューのハンドルを取得
    hwndMenu = GetMenu(Me.hwnd)
End Sub

投稿時間:2005/01/27(Thu) 13:51
投稿者名:ジム
Eメール:
URL :
タイトル:
すごいです。
すばらしいです。実験では動作しました。ターゲットプログラムに組み込んで試してみます。

投稿時間:2005/01/28(Fri) 07:43
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
解決したなら解決報告を
解決したなら向うの掲示板にも解決報告(チェックマーク)しておいて下さい。
解決報告せずに掲示板を移れば当然マルチポストにもなり、それまで回答して下さった方々に
失礼になります。
 
当然こちらの掲示板にも解決報告は必要ですよ。

投稿時間:2005/01/28(Fri) 10:23
投稿者名:ジム
Eメール:
URL :
タイトル:
(解決)
なんとか対策できました。どうもありがとうございました。