ラベル RibbonUI の投稿を表示しています。 すべての投稿を表示
ラベル RibbonUI の投稿を表示しています。 すべての投稿を表示

2011/09/06

access2010 Ribbon group

久しぶりのリボン。
group要素の属性 autoScale と image
アプリケーションウィンドウを狭くしていったときの挙動みたいなもの。
<group id="ObjectGroup" 
               label="Create Objects" 
               autoScale="true" 
               imageMso="CreateTable">
と、した場合どうなっていくか。

2011/05/04

access2010 access2007 IRibbonUIオブジェクトの永続化って感じ

RibbonUIのことなら、ここを見るって。
Gunter Aveniusさんのとこか、きぬあささんのところ。

久しぶりにRibbonXmlを書いていたからいろいろ情報をあさっていたのだけど、なるほどなぁという記事があった。

IRibbonUIオブジェクトがNothingになったときの対処法

記事ではExcelについてなのだけど、当然Accessでもつかえるはず。
IRibbonUIオブジェクトをObjPtrを使って補ってやろうということは変わりはないのだが、オブジェクトのポインタをレジストリに書き込むということはAccessではしなくてもよいだろうな。TempVarsコレクションに格納しておけば、Removeメソッドなど実行しない限り消えないのだから。

2011/04/22

access2010 Webデータベース その30 リボンを制御

** Office365beta(プランP1) 環境 **  
Webデータベースとして運用はaccdbの形式だから、リボンのコントロールをしておきたい。ユーザは原則的にSharePointユーザで限定や特定できるから、きっちりかっちり固める必要がないのかもしれないが、不用意なことが起きないようにということぐらいの意味合いで用意しておこうと思う。
基本的には通常のリボン制御と何ら変わりはない。USysRibbonsテーブルもしくはRibbonXMLが格納されているテーブルがWebテーブルになるということだけ。
強いて言えば、SharePointグループ/ユーザ情報を参照してグループもしくはユーザごとに使用するリボンを切り替えることができるから、この特徴的な機能は使用していくことを検討しておく。

【サンプル】
アクセス許可レベルがデザインのグループとそれ以外のグループでリボンを制御する。
単純な制御として、前者は既定のリボンを表示し使用できるようにする。後者はリボンを非表示にする。

access2010 accdeのアプリケーションパーツ

accdeで配布する場合、アプリケーションパーツは少なくとも使用不可の状態にしておいたほうがいい。

使用不可にした
 そうしないと、消せないフォームが追加されることになるから。

2011/02/11

access2010 “閉じる”をできるだけ検知

閉じるということをできるだけ検知してみようとしている。
基本的にフォームだけなのだけど、PopUpの時もしくはカスケード表示の時のフォーム上のシステムメニュー(っていうでしたっけ、フォームアイコン右クリメニュー)は検知できていない。
以下コードは64bit用。

2010/12/24

access2010 Quick Access Display(仮)

これの制御方法がわかんない。accessのオプションなんだけど、
Application.SetOption "Size of MRU File List", 0 じゃないんだよな。そもそも、Size of MRU File List 使えてないみたいだし。
[クライアントの設定]→[表示]→[最近使用した...]の設定は、
キー名:HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Access\File MRU
名前:Max Display
で、backstageから投入するのは、
名前:Max Quick Access Display
に入ってるしな。SetOptionメソッドで設定する方法が不明だから、そのうちにでも。
で、本題のショートカットの件。

キー名:HKEY_CURRENT_USER\Software\Microsoft\Office\14.0\Access\File MRU
名前:Quick Access Display
に情報がある。 レジストリを直接いじればなんとか。
Sub setQuickAccessDisplay()
    Dim kHnd As LongPtr, lngvalue As Long, lngrtn As Long
    lngvalue = 0 '0:非表示 1:表示
    Const strSubKey = "Software\Microsoft\Office\14.0\Access\File MRU"
    Const strName = "Quick Access Display"
    lngrtn = RegOpenKeyEx(HKEY_CURRENT_USER, strSubKey, 0, KEY_SET_VALUE, kHnd)
    If lngrtn = ERROR_SUCCESS Then
        RegSetValueEx kHnd, strName, 0, REG_DWORD, lngvalue, Len(lngvalue)
    End If
    RegCloseKey kHnd
End Sub
もしくは、
[カレントデータベース]→[リボンとツールバーのオプション]→[すべてのメニューを表示する]で非表示にする。だけど、この場合、セパレータが残る。

CustomUI/backstage要素内で制御する方法はなさそう。

2010/12/17

access2010 Ribbon comboBoxの不具合

invalidateControlで再キャッシュ後getTextで取得した値を中の人が忘れてしまう。

フォームを閉じるとき、invalidatecontrolを実行。開く時では、リボンがキャッシュされていないことがあるからと普通に考えた。要はフォームを開いたときは初期化しておきたかっただけ。
で、どうなるかというと、
comboBoxのItemを選択もしくは同じ文字列を投入し、フォームを閉じる。この時、comboBoxの値の初期化が成功するのは目視できる。だけど、フォームを再び開いたときには最後に投入したItemが選択された状態に戻っている。
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" 
               onLoad="onLoad">
  <ribbon startFromScratch="false">
    <tabs>
      <tab id="tab01" label="タブ01">
        <group id="g01" label="グループ01">
          <comboBox id="cb01" label="コンボボックス" getText="getText">
            <item id="i01" label="item01" imageMso="Info" />
            <item id="i02" label="item02" imageMso="HappyFace" />
            <item id="i03" label="item03" imageMso="PanningHand" />
          </comboBox>
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>
Option Compare Database
Option Explicit

Private rbn As IRibbonUI

Sub onLoad(ribbon As IRibbonUI)
    Set rbn = ribbon
End Sub

Sub getText(ctr As IRibbonControl, rtn)
    rtn = "(未選択)"
End Sub

Sub Invalidate_cb01()
    rbn.InvalidateControl "cb01"
End Sub
Option Compare Database
Option Explicit

Private Sub Form_Close()
    Module1.Invalidate_cb01
End Sub

で、現時点での対策その1。但し、該当comboBoxが配置されているタブがアクティブになること
Option Compare Database
Option Explicit

Private rbn As IRibbonUI

Sub onLoad(ribbon As IRibbonUI)
    Set rbn = ribbon
End Sub

Sub getText(ctr As IRibbonControl, rtn)
    rtn = "(未選択)"
    DoEvents
End Sub

Sub Invalidate_cb01()
    rbn.InvalidateControl "cb01"
End Sub
Option Compare Database
Option Explicit

Private Sub Form_Load()
On Error Resume Next '初回のエラーだけ処理したい
    Module1.Invalidate_cb01
End Sub

対策その2。初期化なんて考えない。

access2010 Ribbon RibbonXmlが読み込まれるのはいつだ

RibbonXmlが読み込まれるタイミングの話。
CutomUI要素のonLoadはリボンが初めて使用される時のことでキャッシュされる時。どっちかっていうとonCacheって感じで違う話。

USysRibbonsに登録したRibbonXmlは自動的に全て読み込まれるのだが、これはAutoExecより先。
AutoExecでLoadCustomUIメソッドを同一RibbonNameで実行してみると明白。
で、BackstageをカスタマイズするRibbonXmlは、AutoExecでのLoadCustomUIメソッド実行が読み込みの最終期限。コマンドラインスイッチ /x マクロ実行では間に合わない。

Backstageに配置したコントロールを実行時に操作にする場合は、USysRibbonsで自動読み込むのではなく、AutoExecでCurrentProject.IsTrusted検査後、LoadCustomUIメソッドで読み込むことが大事なポイント。

Backstage以外をカスタマイズするRibbonXmlは、実際に使う時、つまりキャッシュされる直前までに読み込まれていればいい。

たぶんa2007も同じ。

2010/12/16

access2010 Ribbon contextualTabs TabSetFormReportExtensibility

ユーザ定義ができる組み込みtabSet。idMsoは、TabSetFormReportExtensibility
通常のタブと違うのはタブの表示とオブジェクトが開いたときタブがアクティブになる。
そして、一番右に表示される。

<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
  <ribbon>
    <contextualTabs>
      <tabSet idMso="TabSetFormReportExtensibility">
        <tab id="tab02" label="オブジェクトが開かれたときアクティブになる">
          <group id="g02" label="グループ02">
            <labelControl id="lbl01" label="contextualTabs" />
          </group>
        </tab>
        <tab id="tab03" label="タブ03">
          <group id="g03" label="グループ03">
            <button id="btn02" label="ボタン02" imageMso="Info" />
          </group>
        </tab>
      </tabSet>
    </contextualTabs>
    <tabs>
      <tab id="tab01" label="タブ01" insertAfterMso="TabHomeAccess">
        <group id="g01" label="グループ01">
          <button idMso="ApplicationOptionsDialog" visible="true" />
          <button idMso="FileCloseDatabase" />
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

2010/12/13

office2010 Win32API keybd_event Backstageを表示させない

access2010でファイルタブ押下してもBackstageを表示させない。といっても、onShowでESCキー押下しているだけ。

Option Compare Database
Option Explicit

Private Const VK_ESCAPE = &H1B
Private Const KEYEVENTF_KEYUP = &H2
Private Const KEYEVENTF_EXTENDEDKEY = &H1

'http://msdn.microsoft.com/ja-jp/library/cc364822.aspx
'SendInputを使えとなってるけど、別途x64対応せにゃならんからこっち使う。
Private Declare PtrSafe Sub keybd_event Lib "user32" ( _
                                ByVal bVk As Byte, _
                                ByVal bScan As Byte, _
                                ByVal dwFlags As Long, _
                                ByVal dwExtraInfo As LongPtr)

Sub onShow(cntxt As Object)
    keybd_event VK_ESCAPE, 0, 0, 0
    keybd_event VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0
End Sub
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
  <backstage onShow="onShow" />
</customUI>
なのだけど、結局ribbonXmlを書かにゃならん。
SendInputを使うよりは、keybd_eventの方が64bit対応がすっきりしてていいかなということだけ。まぁとりあえず作動するし。

2010/11/13

access2010 Ribbon dynamicMenu


そのまんまで、dynamicなMenuということ。
dynamicMenu要素には、getContent属性が必須で、このコールバックでメニュー表示に必要なRibbonXmlを取得する。子要素はmenuと同じで、

<menu xmlns="http://schemas.microsoft.com/office/2009/07/customui">
   <!--menu子要素-->
</menu>

のXmlを用意してあげないとならない。
invalidateContentOnDrop属性をtrueにすることでメニュー展開時にコールバックを要求してくる。
どんな方法でもいいからRibbonXmlを返せばいい。
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
  <ribbon>
    <tabs>
      <tab id="tab01" label="タブ01">
        <group id="g01" label="グループ01">
          <dynamicMenu id="dm01" 
                       getContent="getContent" 
                       size="large" 
                       imageMso="CreateForm"
                       label="ダイナミックメニュー" 
                       invalidateContentOnDrop="true" />
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>
Option Compare Database
Option Explicit

Sub getContent(ctr As IRibbonControl, rtnXml)
    rtnXml = CreateContents
End Sub

Sub onAction(ctr As IRibbonControl)
    MsgBox ctr.id & vbTab & ctr.Tag
End Sub

Private Function CreateContents()
    Dim xdoc As New DOMDocument
    Dim xelem(1) As IXMLDOMElement
    Dim objCount As Integer, i As Integer
    Dim dbs As Database, accdoc As Document
    
    Set dbs = CurrentDb
    
    Set xelem(0) = xdoc.createElement("menu")
    xelem(0).setAttribute "xmlns", "http://schemas.microsoft.com/office/2009/07/customui"
    xelem(0).setAttribute "itemSize", "large"
    xdoc.appendChild xelem(0)
    
    objCount = dbs.Containers("Forms").Documents.Count
    
    If objCount > 0 Then
        Set xelem(1) = xdoc.createElement("menuSeparator")
        xelem(1).setAttribute "id", "sep01"
        xelem(1).setAttribute "title", "フォーム"
        xelem(0).appendChild xelem(1)
        For i = 0 To objCount - 1
            Set accdoc = dbs.Containers("Forms").Documents(i)
            Set xelem(1) = xdoc.createElement("button")
            With xelem(1)
                .setAttribute "id", "form" & Format(i, "00")
                .setAttribute "label", accdoc.Name
                .setAttribute "tag", accdoc.Name
                .setAttribute "imageMso", "CreateForm"
                .setAttribute "onAction", "onAction"
                .setAttribute "description", docDescription(accdoc)
            End With
            xelem(0).appendChild xelem(1)
        Next
    End If
    
    CreateContents = xdoc.XML
'    Debug.Print xdoc.XML
    
    Set xdoc = Nothing
    Set dbs = Nothing
End Function

Private Function docDescription(doc As Document) As String
On Error GoTo ErrHnd
    docDescription = Nz(doc.Properties("Description"), " ")
Exit Function
ErrHnd:
    docDescription = " "
End Function
<menu xmlns="http://schemas.microsoft.com/office/2009/07/customui" itemSize="large"><menuSeparator id="sep01" title="フォーム"/>
<button id="form00" label="フォーム1" tag="フォーム1" imageMso="CreateForm" onAction="onAction" description="DescriptionDescription"/>
<button id="form01" label="フォーム2" tag="フォーム2" imageMso="CreateForm" onAction="onAction" description=" "/>
<button id="form02" label="フォーム3" tag="フォーム3" imageMso="CreateForm" onAction="onAction" description="DescriptionDescription"/>
<button id="form03" label="フォーム4" tag="フォーム4" imageMso="CreateForm" onAction="onAction" description="DescriptionDescription"/>
<button id="form04" label="フォーム5" tag="フォーム5" imageMso="CreateForm" onAction="onAction" description=" "/>
</menu>

2010/11/09

access2010 Ribbon control


control要素は、sharedControls(qat)/documentContorls(qat)/group(tab)の子要素として使用できる。
groupの子要素である場合、id属性は使用できないから、組み込みコントロールのクローンとしてのみ使用可能。 sharedControls/documentContorlsの場合は、id属性を使用できて、指定したid属性値をもつコントロールをクローンする。だから、qatでbutton以外のカスタムコントロール(menuとかgalleryとか)をcontrol要素を使って配置することが可能。qatでクローンを使う場合、当然元になるコントロールがキャッシュされていないとだから、必要な場合は起動時にキャッシュさせておくなど整えておくことが必要かもね。qatにcheckBoxやtoggleButtonを配置することも可能なんだけど、group子要素に配置されているクローン元をは同期しない。ステータスを持たせるコントロールはあんまり使わないと思うけど。

2010/11/08

access2010 Ribbon menu


menuの子要素には、button/checkBox/gallery/menu/menuSeparator/splitButton/toggleButton、確認してないけど、control/dynamicMenu が使える。子要素にmenuが配置できるからmenuの入れ子で展開されるUIが作れる。
子要素に配置されるコントロールのサイズは、menuのitemSize属性値が適用される。配置コントロールがsize属性値を持っているとUIエラーになる。
itemSize="large"である場合、配置コントロールのdescription属性値が展開アイテムに表示される。

menuの子要素としてsplitButtonを配置した場合、splitButtonがgetLabelコールバックを実行してくる現象が発生している。

access2010 Ribbon splitButton


splitButtonの子要素は、button+menu/toggleButton+menuのいずれかの組み合わせで、子要素先頭のbutton/toggleButtonがsplitButtonの親表示コントロールになる。子要素menuが展開後に表示されれるコントロールになる。
splitButtonにsize属性はないから、表示コントロールのsize属性を使う。子要素menuについては、menuの属性itemSizeが適用される。

要素:splitButton
子要素:button/toggleButton/menu
属性:size

2010/11/04

access2010 Ribbon gallery


galleryコントロールの子要素は、item/buttonのみ。itemの後だけにbutton配置が可能。
gallery要素内のitemのitemHeight/itemWidth属性はアイテムサイズではなくて、itemのイメージが配置されるエリアのサイズ。itemここのサイズはitemのラベルによって伸縮する。
dropDown/comboBox同様、getItemCount/getItemID/getItemLabel/getItemImageコールバックでgallery子要素を構成できる。buttonはだめよ。
コントロールからの情報取得はonActionで、要素内buttonはそれぞれにonActionを。
rows/columns属性はお好みで。

invalidateContentOnDrop属性は、office2007でも使える。

要素:gallery
子要素:item/button
コールバック:onAction/getItemHeight/getItemWidth/getItemCount/getItemID/getItemLabel/getItemImage
属性:rows/columns/showItemLabel/showItemImage/invalidateContentOnDrop

2010/11/02

access2010 Ribbon dropDown comboBox


まずは、コントロールからの情報を取得
dropDownはonActionコールバックプロシージャで、comboBoxはonChangeで。
dropDownからは、itemID(String)/itemIndex(Integer)が取得できる。いずれかを使用するかは自由、どちらとも使うのも自由。コレクションからitemを作っているならindexが手早いかもと思うくらい。
selectedItemIndexまたはselectedItemIDで選択された状態にすることはできるが、このときonActionは発生しない。まぁ当たり前だけど、何が起こるか分からないし。
comboBoxは、editBoxも同じなんだけど、コントロール内の文字列が取得できる。
動画終盤でcomboBoxの挙動がちょっとあやしいと感じた。意図的にInvalidateしても、いったんは更新されるが、フォームを閉じ再び開いたときには更新される前の状態に戻っている。この状態が発生するのは、itemを選択時/itemLabelと同じ手投入をした時。デグレとは思えないので、調査中。

getItemCount
コントロール内のアイテム数を通知。アイテムの数だけgetItem○○が実行される。
0 → (itemCount - 1)
getItemID/getItemLabel
コールバックで通知してくるindexを基にitemID(String)を渡す
getItemImage
indexを基にイメージを渡していけばいいのだけど、2つの手段がある。imageMsoで使われる名前か画像データを渡してあげる。pngとか透過を使ったデータがすんなり渡せればいいのだけど、GDI+とか使わないとダメことがあるので、基本的にはやらない方向で検討する。

invalidateContentOnDrop
office2010から使用できる属性
その名の通り、ドロップしたときにコンテンツを無効化にするということだが、comboBoxドロップした時アイテムが更新されるということ。特段のInvalidateを必要としない。trueで発生。

要素:dropDown/comboBox
コールバック:onAction/onChange/getItemCount/getItemID/getItemLabel/getItemImage/getSelectedItemIndex/getSelectedItemID/getText
属性:invalidateContentOnDrop

2010/10/31

access2010 IRibbonControl ID/Tag/Context プロパティ


コールバックプロシージャで参照できるIRibbonControlについて確認
コントロールのid属性値はリボンでユニークだから、IDプロパティを参照することでプロシージャ実行時コントロールを特定できる。だから、同じコールバックプロシージャでも処理を分岐して仕分けができる。tag属性値は、id属性値に使用できない文字とか処理分岐のキーとして使う方法も考えられる。AccessコントロールのTagプロパティと同じ感じでいいかな。Contextプロパティで参照できるのはAccessアプリケーションオブジェクトだから特に使うことはないんじゃなかろうか。

access2010 リボンをVBAで操作する Invalidate InvalidateControl


リボンに配置してあるコントロールには、VBAから直接に参照することはできない。フォーム上に配置されたaccessコントロールのようにプロパティの参照や設定ができないということ。

リボンのコントロール要素には、on~、get~というコールバックを示す属性があるので、これらとIRibbonUIオブジェクトのInvalidate/InvalidateControlメソッドを使用することでリボンコントロールを制御する。
コールバック属性に示されるプロシージャは、該当のリボンコントロールがキャッシュされるときに実行され、プロシージャから渡される値がコントロールの属性値になる。
例えば、enabled属性にはgetEnabledコールバック属性があり、属性値が示すプロシージャによってenabled属性値を取得する。取得した値がfalseであれば使用不可の状態になる。

コールバックプロシージャはキャッシュ時のみ動作でVBAから直接に実行を指示できないから、キャッシュ値を無効にするメソッドInvalidate/InvalidateControlを実行しリボンにシグナルを送信。
 リボンは自動的に再キャッシュを開始し、コールバックプロシージャを実行させ属性値を取得する。このとき、属性値として取得される変数をVBAで制御すれば、リボンコントロールの制御をすることになる。

リボンコントロールの再キャッシュ動作はVBAと非同期に実行されるから、リボンの動作に左右されるようなクリティカルな使い方をしちゃだめ。コントロールがキャッシュされる順番などは保証されないから、リボンコントロール間でも同じことが言える。

2010/10/30

access2010 customUI onLoad


customUIのonLoadについて
  • ribbonXmlの内容がキャッシュされる時に発生
  • なので、一度しか発生しない
  • そして、リボンは非同期で処理が進む
ActivateTabメソッド/ActivateTabMsoメソッド
IRibbonUIオブジェクトを参照できなければエラーになるのは当たり前。onLoad開始時からIRibbonUIオブジェクトが参照できるようになるまでの時間は配置コントロール要素次第だと思うから、待つか予めにキャッシュ(LoadCustomUIメソッド)させておく、もしくは使いどころを別に考える。
どえらい要素数のリボンでキャッシュ済みであった場合どうなるのか見ておけばいいのか。あてにしない方がよいかもだ。
ちょっと考えなおした。LoadCustomUIメソッドではキャッシュされずに読み込まれるだけ。読み込まれていても、未使用のリボンはキャッシュされていないと思う。

リボンを動的に操作するためには、onLoadでIRibbonUIオブジェクトを参照できるようにしなければならない。オブジェクトは実行時エラーが発生すると初期化されてしまうからエラー処理は特に大事。キャッシュはアプリケーション終了まで保持される。

要素:customUI
属性:onLoad(コールバック)
call back signature:Sub onLoad(ribbon as IRibbonUI)

2010/10/27

access2010 クイックアクセスツールバー(qat)をRibbonXmlで設定


まぁ特に複雑なことはない。
組み込みコントロールであれば、idMsoで指定。カスタムボタンであればonActionでプロシージャ指定。
startFromScratch="true"じゃないとだめ。また、qatに配置されるカスタムコントロールのIDはユニークで。