更新前処理イベント内で閉じるボタンのクリックを判定する方法
をaccess2010でやってみた。
タブ付きドキュメントである場合の件。とりあえず動作することは確認できた。
Option Compare Database Option Explicit '************************* '参照設定 'oleacc.dll '************************* Const ROLE_SYSTEM_LIST = &H21 Const ROLE_SYSTEM_PUSHBUTTON = &H2B Const ROLE_SYSTEM_BUTTONMENU = &H39 Const ROLE_SYSTEM_PROPERTYPAGE = &H26 Const ROLE_SYSTEM_MENUITEM = &HC Const ROLE_SYSTEM_CLIENT = &HA Private IsRibbonAction As Boolean Type POINTAPI X As Long Y As Long End Type #If VBA7 Then Private Declare PtrSafe Sub CopyMemory Lib "kernel32" _ Alias "RtlMoveMemory" ( _ Destination As Any, _ Source As Any, _ ByVal Length As LongPtr) Private Declare PtrSafe Function GetCursorPos Lib "user32" ( _ lpPoint As POINTAPI _ ) As Long #If Win64 Then Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "oleacc" ( _ ByVal llXY As LongLong, _ ByRef ppvObject As Any, _ ByRef pvarChild As Variant _ ) As Long Private Function PointToLongLong(point As POINTAPI) As LongLong Dim ll As LongLong, cbLongLong As LongPtr cbLongLong = LenB(ll) If LenB(point) = cbLongLong Then CopyMemory ll, point, cbLongLong End If PointToLongLong = ll End Function #Else Private Declare PtrSafe Function AccessibleObjectFromPoint Lib "oleacc" ( _ ByVal xScreen As Long, _ ByVal yScreen As Long, _ ByRef ppvObject As Any, _ ByRef pvarChild As Variant _ ) As Long #End If #Else Private Declare Function GetCursorPos Lib "user32" ( _ lpPoint As POINTAPI _ ) As Long Private Declare Function AccessibleObjectFromPoint Lib "oleacc" ( _ ByVal xScreen As Long, _ ByVal yScreen As Long, _ ByRef ppvObject As Any, _ ByRef pvarChild As Variant _ ) As Long #End If Function IsCloseButtonClicked() As Boolean Dim xy As POINTAPI, acc As IAccessible Dim Child As Variant, btnName As String, tabCaption As String If IsRibbonAction Then IsCloseButtonClicked = True IsRibbonAction = False Exit Function End If GetCursorPos xy #If Win64 Then AccessibleObjectFromPoint PointToLongLong(xy), acc, Child #Else AccessibleObjectFromPoint xy.X, xy.Y, acc, Child #End If If acc Is Nothing Then IsCloseButtonClicked = False Exit Function End If btnName = acc.accName(Child) tabCaption = CodeContextObject.Caption If tabCaption = "" Then tabCaption = CodeContextObject.Name End If Select Case acc.accRole(Child) Case ROLE_SYSTEM_LIST MsgBox "タスクバー:すべてのウィンドウを閉じる" & _ vbCrLf & btnName Case ROLE_SYSTEM_PUSHBUTTON If InStr(1, btnName, "を閉じる") > 1 Then MsgBox "フォーム閉じるボタン" & _ vbCrLf & btnName Else MsgBox "Application閉じるボタン" & _ vbCrLf & btnName End If Case ROLE_SYSTEM_BUTTONMENU MsgBox "システムメニュー:閉じる" & _ vbCrLf & btnName Case ROLE_SYSTEM_MENUITEM MsgBox "フォームアイコンダブルクリック" & _ vbCrLf & btnName Case ROLE_SYSTEM_PROPERTYPAGE '結果的にこうなる MsgBox "Applicationアイコンダブルクリック" & _ vbCrLf & btnName Case Else MsgBox "不明 もしくは、Backstageのコマンド" & _ vbCrLf & btnName End Select IsCloseButtonClicked = True End Function 'RibbonXmlで検知:フォームが開いていること前提 Sub onActionClose(ctr As Object, CancelDefault) If Screen.ActiveForm.Dirty Then MsgBox "RibbonXmlで管理できるコマンド:" & ctr.ID IsRibbonAction = True End If CancelDefault = False End Sub
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"> <commands> <command idMso="WindowClose" onAction="onActionClose" /> <command idMso="CloseDocument" onAction="onActionClose" /> <command idMso="FileCloseDatabase" onAction="onActionClose" /> <command idMso="FileExit" onAction="onActionClose" /> </commands> </customUI>a2007でも動作するけどOfficeメニューから閉じる動作については対応は今のところ放置。同様に、BackStageから閉じる場合も反応できない。この辺はリボンカスタマイズでなんとかなるかな。タスクバーから閉じる場合もダメなんす。 a2010Runtimeだけシステムメニューから閉じるの場合反応なし。a2010(x64)についてはからっきし動作しない。調査してみるけど、これは俺には無理かも。AccessibleObjectFromPoint にXYをどのように渡すかだろうか。
64bitも動作するようになった。座標をLongLongで渡して成功。そして、デレクティブ。
でも、考えないといけないこと、たくさんあるな。どうしようかな。いずれにせよ、とりあえず。
いろいろ継ぎはぎしてみてBackstageとかOfficemenuもRibbonXmlで一応握ってみたと。
んー、やっぱりとりあえずレベル。たまに失敗している気配はしている。検証甘いから、何も考えずに実装するするにはちょっと心もとない。Accessibleを使うっつーところだけがポイントだろうか。
0 件のコメント:
コメントを投稿