[[20151210140915]] 『ユーザーフォームを隠す』(はg) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『ユーザーフォームを隠す』(はg)

調べても出てこなかったためこちらで質問させていただきます。

ユーザーフォームを隠すことは可能でしょうか。
左端に位置を固定させておき、カーソルが左端にいったら表示、離れたら隠したいです。
ここまでくるとエクセルでは難しいような気もするのですが・・・。

< 使用 Excel:Excel2010、使用 OS:Windows7 >


 左端 とは 何 の 左端ですか?

(β) 2015/12/10(木) 14:20


βさん
画面の左端です。この(ユーザーフォームのある)エクセル以外のエクセルファイルも複数開いているので、開くたびに前面中央にくると邪魔になるので、左でも右でもいいんですけど、端に寄せて、カーソルが端に来れば表示、離れたら隠れるようにしたいです。
位置を固定するのは「StartUpPosition」を使えば良いということはわかったのですが、それから隠したりするやり方がわかりません。。
(はg) 2015/12/10(木) 14:26

ちょっとわかりにくいかもしれませんが、隠すというより透明にします。
表示されているエクセル画面の一番左の列のどこかにマウスが当たれば表示、はずれれば透明。
裏の監視ルーティンの終了はユーザーフォームを閉じたときに行います。
なので、ユーザーフォームが一番左の列とは異なる場所に表示されていると、ユーザーフォームを閉じることができなくなりますので
ご注意を。
 (マウスではなく、カーソロでのセル選択での判断も可能ですが、とりあええずマウスです)

 標準モジュール

 Private Declare Function GetCursorPos Lib "User32" (lpPoint As POINTAPI) As Long
 Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" _
    (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
 Private Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" _
    (ByVal hwnd As Long, ByVal nIndex As Long) As Long
 Private Declare Function SetLayeredWindowAttributes Lib "user32.dll" _
    (ByVal hwnd As Long, ByVal crKey As Long, ByVal bAlpha As Long, ByVal dwFlags As Long) As Long

 Const GWL_EXSTYLE = (-20)
 Const LWA_ALPHA = 2
 Const WS_EX_LAYERED = &H80000

 Type POINTAPI
    x As Long
    y As Long
 End Type

 Public FlagLoop As Boolean
 Public myHwnd As Long

 Sub DoLoop()
    Dim vv As Object
    Dim MPt As POINTAPI
    Dim oldPt As String
    Dim newPt As String

    Do While FlagLoop

        GetCursorPos MPt
        Set vv = ActiveWindow.RangeFromPoint(MPt.x, MPt.y)
        If Not vv Is Nothing Then
            If TypeName(vv) = "Range" Then
                If vv.Column = ActiveWindow.VisibleRange.Columns(1).Column Then
                    Transparency 255
                Else
                    Transparency 0
                End If
            End If
        End If

        DoEvents

    Loop

 End Sub

 Private Sub Transparency(level As Integer)
  Dim i As Long
  Call SetWindowLong(myHwnd, GWL_EXSTYLE, GetWindowLong(myHwnd, GWL_EXSTYLE) Or WS_EX_LAYERED)
  Call SetLayeredWindowAttributes(myHwnd, 0, level, LWA_ALPHA)
 End Sub

 ユーザーフォームモジュール

 Private Declare Function WindowFromAccessibleObject Lib "oleacc" ( _
      ByVal pacc As Object, _
      ByRef phwnd As Long) As Long

 Private Sub UserForm_Initialize()
    WindowFromAccessibleObject Me, myHwnd
    FlagLoop = True
    Application.OnTime Now(), "DoLoop"
 End Sub

 Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    FlagLoop = False
 End Sub

(β) 2015/12/10(木) 15:06


βさんの透過案とは別に、私はリサイズして少しマウス移動先ウィンドウを残す例なぞ。
(タスクバーの「自動的に隠す」機能みたいなもの)

【標準モジュール】

 Const GWL_STYLE = (-16)
 Const WS_CAPTION = &HC00000
 Const WS_SYSMENU = &H80000
 Const WS_BORDER = &H800000
 Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" ( _
    ByVal hWnd As Long, _
    ByVal nIndex As Long) As Long
 Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" ( _
    ByVal hWnd As Long, _
    ByVal nIndex As Long, _
    ByVal dwNewLong As Long) As Long
 Declare Function GetActiveWindow Lib "user32" () As Long
 Declare Function MoveWindow Lib "user32.dll" ( _
    ByVal hWnd As Long, _
    ByVal X As Long, _
    ByVal Y As Long, _
    ByVal nWidth As Long, _
    ByVal nHeight As Long, _
    ByVal bRepaint As Long) As Long
 Declare Function GetWindowRect Lib "user32.dll" ( _
     ByVal hWnd As Long, _
     lpRect As RECT _
     ) As Long

 Type RECT
     Left As Long
     Top As Long
     Right As Long
     Bottom As Long
 End Type

 Dim RC As RECT
 Dim hWnd As Long
 Dim iFlag As Long
 Dim iStyle(1) As Long
 Dim iWidth As Long
 Dim iHeight As Long

 Sub sInitWnd()
    hWnd = GetActiveWindow()
    Call GetWindowRect(hWnd, RC)
    iWidth = RC.Right - RC.Left
    iHeight = RC.Bottom - RC.Top
    iStyle(0) = GetWindowLong(hWnd, GWL_STYLE)
    iStyle(1) = iStyle(0) And (Not (WS_CAPTION Or WS_SYSMENU Or WS_BORDER))
    iFlag = 1
    Call sHideWnd
 End Sub

 Sub sShowWnd()
    If iFlag = 0 Then
        Call SetWindowLong(hWnd, GWL_STYLE, iStyle(0))
        Call MoveWindow(hWnd, 0, 0, iWidth, iHeight, 1)
        iFlag = 1
    End If
 End Sub

 Sub sHideWnd()
    If iFlag = 1 Then
        Call SetWindowLong(hWnd, GWL_STYLE, iStyle(1))
        Call MoveWindow(hWnd, 0, 0, 10, iHeight, 1)
        iFlag = 0
    End If
 End Sub

【UserForm1】

 Private Sub UserForm_Initialize()
    Application.OnTime Now, "sInitWnd"
 End Sub

 Private Sub UserForm_MouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If X < 10 Then
        Call sShowWnd
    Else
        Application.OnTime Now + TimeValue("00:00:01"), "sHideWnd"
    End If
 End Sub
(???) 2015/12/10(木) 17:23

 全く別の発想というか、カーソルが・・・ということですから、ユーザーフォームはモードレス表示ですよね。

 なので、難しいことは考えず、カーソルの動きのみで、画面左端の列にカーソルがいけば表示、はずれれば非表示。
 表示されたときに、シート操作を可能にしています。
 もし、表示されたときにはユーザーフォーム側操作可能にしたいのであれば★印のコードを消してください。

 当該シートのシートモジュールに以下のみ。

 Dim flag As Boolean

 Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Dim pos As Boolean

    If Not Intersect(Target, ActiveWindow.VisibleRange.Columns(1)) Is Nothing Then pos = True

    If pos Then
        If Not flag Then
            UserForm1.Show vbModeless
            flag = True
            AppActivate ActiveWindow.Caption    '★
        End If
    Else
        If flag Then
            UserForm1.Hide
            flag = False
        End If
    End If

 End Sub

(β) 2015/12/10(木) 18:11


βさん、???さん
ありがとうございます!!想像通りものをいただけて大変感謝です!
この内容を理解できるように頑張ります。。
(はg) 2015/12/10(木) 18:21


βさんへ

昨日は本当にありがとうございました。
一つお聞きしたいことがあるのですが、ユーザーフォームが表示される位置はどこで指定されているのでしょうか?

標準モジュールの、
Set vv = ActiveWindow.RangeFromPoint(MPt.x, MPt.y)

        If Not vv Is Nothing Then
            If TypeName(vv) = "Range" Then
                If vv.Column = ActiveWindow.VisibleRange.Columns(1).Column Then

この中のどこかにあるのかなと思い調べてみて、MPtは現在のマウスの位置を取得していて、RangeFromPointは画面の左端から目的のポイントまでの縦・横方向の距離を指定しているということはわかったのですが、知識が足らずうまく理解することができませんでした。

マウスを左端から離した状態(隠れた状態)で、左端にマウスを持っていくときのことです。
(はg) 2015/12/11(金) 11:37


 いえ、提示したコードではユーザーフォームの表示場所は指定していません。
 デザインでStartUpPosition プロパティに適切なものを設定してあるんだろうという推測というか前提です。

 >>位置を固定するのは「StartUpPosition」を使えば良いということはわかったのですが

 とコメントしておられましたから。

 ただ、本件、目的にもよりますが、APIを使った大がかりな構えにするまでもなく、
 (β) 2015/12/10(木) 18:11 で提示したコードで充分な気がします。

(β) 2015/12/11(金) 11:44


(はg)さん
横入りすみません。ちょっと失礼します
(β)さん提示の 2015/12/10(木) 18:11ですが
非常に、使いやすいと思いいろいろ試してみました。
以下の条件では、どのようにコードを追加すればようですか?

?@複数列に同じユーザーフォームを表示する場合
B列 UserForm1
E列 UserForm1
F列 UserForm1

?A同じく複数列に別々のユーザーフォームの場合
J列 UserForm3
K列 UserForm4

2通り考えられるのですが よろしくお願いします

(昴) 2015/12/11(金) 13:06


文字化けでした
1.複数列に同じユーザーフォームを表示する場合
B列 UserForm1
E列 UserForm1
F列 UserForm1

2.同じく複数列に別々のユーザーフォームの場合
J列 UserForm3
K列 UserForm4
(昴) 2015/12/11(金) 13:08


βさん

回答ありがとうございます。
言われてみればそうですね、そこまで大がかりにする必要はないかもしれません……。
現在は左端に位置を固定させているんですが、A列に書き込む際にマウスでセルをクリックしようとするとフォームが出てきてしまうので、出てくる位置を指定できないかなと思いましたが、キーボードで移動すれば問題ないですよね。
丁寧にありがとうございました。(>_<)
(はg) 2015/12/11(金) 13:11


 To (昴)さん

 別トピを立てられたほうがいいとは思うんですが。

 それと、

 >>1.複数列に同じユーザーフォームを表示する場合 
 >>B列 UserForm1 
 >>E列 UserForm1 
 >>F列 UserForm1 

 浅学にして、どうしたら、このようなこと(同じユーザーフォームを画面上に複数表示する)ができるのかわかりません。
 教えていただけますか?

(β) 2015/12/11(金) 14:05


βさん

何度もコメントを付けて申し訳ありません。もう一つだけ質問させていただきたいのですが……。
ユーザーフォームを起動したまま新しくブックを開くことができないのですが、これは起動している間は処理が[実行中]となっているからなのでしょうか?
(はg) 2015/12/11(金) 14:24


> 浅学にして、どうしたら、このようなこと(同じユーザーフォームを画面上に複数表示する)ができるのかわかりません。
> 教えていただけますか?
3つ同じものはあまり多くないですが、帳票の項目で例えば
カレンダーのユーザーフォームなど、日付入力によって
請求日・入金日など出てきます。
よろしくお願いします。

(昴) 2015/12/11(金) 14:38


 (はg)さん

 >>ユーザーフォームを起動したまま新しくブックを開くことができないのですが

 最初にアップした「裏での監視」版ですね。
 うらでグルグル回っているので、なかなかサービスの順番が回ってこないと思いますが、
 それでも、できるはずです。

 ちょっと、試してみますが、その環境にいないのでしばらくお待ちください。

 ★ところで、こちらでは勝手に モードレス表示だと思っているんですが、それでいいのですね?

(β) 2015/12/11(金) 14:43


 To (昴)さん

 オリジナル質問、まだ継続中ですから、このトピ内でのやりとりはやめましょう。
 新規トぴを立ててください。

 なお、そのさいは、

 >>3つ同じものはあまり多くないですが

 多くないけど、もしあるなら、ほんとうにそうできるということを確認してから質問したほうがいいですよ。
 じゃないと、そこのところで、回答者さんから、おかしいよ! というコメントが入り、時間がもったいないですから。

(β) 2015/12/11(金) 14:46


(β) さん
了解しました
改めて質問します。
 (はg)さん
お邪魔してすみませんでした。

(昴) 2015/12/11(金) 14:51


βさん

ありがとうございます。お待ちしています。

はい、ユーザーフォームは、
UserForm1.Show vbModeless
で開いています。
(はg) 2015/12/11(金) 16:32


 今、エクセルのある環境に戻ってきました。

 こちらで、マクロを実行させながら

 ・ユーザーフォームが表示されている状態でファイルメニューから開く
 ・ユーザーフォームが非表示の状態でファイルメニューから開く

 いずれも、問題なく開くことができます。

 ただし、ファイルを開いた時点で、エクセル区画がプロジェクトリセットされ
 表示されていたユーザーフォームも消えますし、裏で【実行中】だったコードも
 実行停止になります。

 いずれにしても【開くことはできます】

 そちらでブックを開く、その操作手順は、どんな方式ですか?

 なお、事前予告(?) 明日、早朝から月曜日深夜まで外出し、PCを見ることができません。
 今晩中に解決しない場合は、火曜日以降になります。

(β) 2015/12/11(金) 17:17


βさん

回答ありがとうございます。
すみません、ファイル→開くでファイルを指定すれば開くことが出来ました。
ユーザーフォームを起動している状態で、フォルダを開きファイルをダブルクリックして開こうとすると開けないようです……。
裏で実行中のものは変わらず実行中となっています。

お忙しいのにお手数をお掛けしてすみません。私もこれからパソコンの使えない環境に移動するのですが、月曜日に必ず確認します。宜しくお願いします。

(はg) 2015/12/11(金) 18:01


 なるほど!
 こちらでも確認しました。

 う〜ん・・・・

 DoEvents制御に加え、API Sleep も加えてハンドリングしてみましたが、やはりダブルクリックが無視されますね。
 (無視 というか、おそらく、その指令を Windows から エクセルに渡そうとしても、エクセルが受け取らない?)

 調べてみて、何かわかればアップしますが、さてどうなりますか・・・

 エキスパートさんのヘルプがほしいところですねぇ。

(β) 2015/12/11(金) 19:26


一日調べてみましたが全く見当がつきません。
ファイル→開く では問題なく起動してくれますので、とりあえずそれで動かしてみます。

色々とありがとうございます。
(はg) 2015/12/14(月) 18:08


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.