プロが教えるわが家の防犯対策術!

 Access初心者です。
 特定のフォームでマウスのホイールの動作を受付けなくしたく、
下記URLを参考にVBEにコードを貼り付けてみましたが、うまく
動きません。

http://www.accessclub.jp/bbs2/0027/beginter08905 …

 VBE上でコンパイルすると、メッセージウィンドウが開き、
コンパイルエラー:
 SubまたはFunctionの属性が適切ではありません。

と表示され、同時に、該当するフォームのVBAコードに追加で
貼り付けたコードのうち
 WithEvents clsMouseWheel As CMouseWheel
の部分が反転表示されます。

  とりあえずOKとして、VBEを閉じ、再度プログラムを実行
させ、該当のフォームを開いてみても、やはり

  イベントプロパティに指定した指揮 読み込み時 でエラーが発生
しました:SubまたはFunctionの属性が適切ではありません。

が表示されてしまい、うまく動きません。

 どのようにすれば良いでしょうか?
 コードの貼り付ける位置が間違っている等でしょうか?
 どなたか教えてください、よろしくお願い致します。

以上

A 回答 (4件)

> 1.フォームには貼り付ける際、前回は末尾に貼り付けたが今回は冒頭に


>  貼り付けた

あ。。これですね。原因は。

Private WithEvents ~ はモジュールの先頭でなければなりません。
先頭というのは、1行目という意味ではなく、他プロシージャよりも
必ず前の部分に書くという意味です。

Sub aaa()
  '処理
End Sub

Private WithEvents ~

はダメなのですが、

Private hoge As Long
Private WithEvents ~

Sub aaa()
  '処理
End Sub

のようならば OK。他 Sub プロシージャよりも前のブロックに書か
ないといけない決まりになってます。

> サブクラス化の危険性を考慮した、より安全な手法による、
> 参考ソースの方はいかがでしょうか?

表現の仕方が悪かったようです。Access でマウスホイールの挙動を
制御するには、

 1. サブクラス化を行う
 2. ActiveX 等を使う

以外の方法はありません。

2. は別途で Dll または OCX 等のファイルをインストールする必要
があります。未確認ですが、Vector 等で探せば VBA 用のものが
見つかるかもしれません。なければ自作するしかないんですが・・・

ただし、社内で配布するものとして追加インストールが必要な手法
というのは難点になりますよね...?

 # システム管理者や社内のOA運用方針との兼ね合いで

一方、1. のサブクラス化では、追加インストールは不要ですが、
先述のようなリスクもあるわけです。これは、ユーザー側という
よりも、システム設計・開発しているあなたの側に細心の注意を
払う必要があるということを意味しています。

つまり、バグの無いものを作る必要があるということです。
そして、十分にテストする必要もあります。

#2 を回答した時点では、参考にされたソースを詳しく検証して
ませんでしたから、ソースに不備があるのかも? ならば、手元に
ある以前開発したものを参考ソースとして提示・・といった発言を
してしまったのですが、特に参考にされたソースには問題がありま
せんでした。

 # 元々は MSDN (Microsoft の技術サポート情報サイト)に
 # 公開されていたもののようです

似たようなソースをアップしても有益な情報とはならないでしょう。
従いまして参考ソースのアップは控えさせて頂きました。

私の回答の結論としては、繰り返しになりますが、

 ・サブクラス化の手法を使う(参考にされたソースを活用する)
 ・エラーが発生しないように、十分にテストを繰り返し、バグの
  無いモノをリリースする

いうことになります。

誤解を与えてしまったようで、申し訳ありません。

この回答への補足

 一点だけ気になっていることがあるのですが、それは、先の補足に
書かせていただきました『VBEによるコード修正後、Accessを閉じる際の
操作の違いによって、VBAのセーブがうまく行ったり行かなかったりという
ことがあるのか・・・?』 という点です。

 実は、昨日、うまくいきましたとの状況報告をアップした後に、再びうまく
いかないことがありました(・・・・・・該当フォームを開くと、「計算しています」
の状態が延々と続きフリーズしてしまう現象)。

 このときは、一旦タスクマネージャで強制終了した後、データベース
ウィンドウを開き、モジュールオブジェクトがウィンドウ右側に表示されている
状態で、データベースウィンドウの右上の×をクリックして閉じる、という
ことを行い、再度アプリ起動すると、今度はうまくいきました。
 その後はいまのところ問題ありません。

 Accessは、他のOfficeソフトと異なり、ウィンドウを閉じる行為が、セーブ
されるデフォルトになっていて、少し感覚が違うのですが、上記についても
このあたりの関係で、VBAを使う際に何か留意しておくべき事項がある
ということなのでしょうか?

 また、念のため確認ですが、上記のような状況は、サブクラス化による
不安定現象ではないと考えてよろしいのですよね?

 これらについて、なにか見識がありましたら最後にコメントいただけません
でしょうか?
 よろしくお願い致します。

補足日時:2009/12/18 08:26
    • good
    • 0
この回答へのお礼

 丁寧な解説をいただき有り難うございます。
 よくわかりました。
 1. サブクラス化を行う
 2. ActiveX 等を使う
のふたつの方法があり、2はユーザに負担をかける(あるいはそのサポート
の為の管理者側の負担もあるかも?)、一方、1についてはもしバグがあると
システム全体に影響を及ぼすので、管理者側がしっかり検証したものである
必要があるが、今回のソースのように検証されたものであれば問題はない、
ということですね。

 なお、ほかに一点だけ気になることがあり、補足質問の方に書かせて
いただきます。
 もし、なにか見識があればコメントいただければ幸いです。

 今回はどうも有り難うございました。大変助かりました。

以上
 

お礼日時:2009/12/18 08:26

再度 URL 先のソースを試しましたが、特に問題なさそうです。



 # 今度はうまく動きました

標準モジュール、クラスモジュール、フォームと3つのモジュールに
ソースを間違いなく貼り付けてますか? 改造した部分はありませんか?

それから、各モジュールはちゃんと Save してから実行してますか?

動作確認が取れてますから、念のため、今一度説明を良く読んで、
再度貼り付け作業からやってみて下さい。

この回答への補足

 有り難うございました。
 もう一度全てクリアして、最初からやり直してみたらうまくいきました。

 前回どこがまずかったのか不明ですが、可能性としては以下の辺り
かと・・・・

1.フォームには貼り付ける際、前回は末尾に貼り付けたが今回は冒頭に
 貼り付けた

2.前回もちゃんとセーブしたつもりでしたが、以下の手順8~10を厳格に
 実行した

   8.VBE画面を閉じ、データベースウインドウからモジュールを選択します。
   9.Accessを一旦閉じます。
   10.再度Accessを開き該当フォームを開きます。

  なお、手順8の後半の意味がよくわからなかったのですが、データベース
 ウィンドウにてオブジェクトのうちからモジュールを選択し、種々の
モジュールオブジェクトがウィンドウ右側に表示されている状態で、
データベースウィンドウの右上の×をクリックして閉じる、ということを
厳格に行いました。
  前回の手順の詳しいところは、よく記憶していませんが、もしかすると
モジュールオブジェクトを選択していなかったかもしれませんし、Accessを
閉じる方法もデータベースウィンドウの×をクリックではなく、いきなり
Accessのウィンドウの×をクリックで閉じていたかもしれません。
  ともあれ、このあたりの操作の違いによって、セーブがうまく行ったり
行かなかったりということはあるのでしょうか?

 それと、あと1点確認させていただきたいのですが、2回目の回答で触れて
いただいていたサブクラス化の危険性を考慮した、より安全な手法による、
参考ソースの方はいかがでしょうか?
 
 よろしくお願い致します。

補足日時:2009/12/17 17:10
    • good
    • 0

そうですか。

。。

一応、参照された URL のソースを試してみたらマウスホイールを
禁止できましたが、そのままフリーズしてしまいました。

やっていることは、サブクラス化といって、本来 Windows (OS)
が行っていること(この場合、マウスホイールの挙動に関する
OS が発信した Access への制御メッセージ)を無理やり横取りし、
自前の処理に置き換えているわけです。

したがって、ヘタをするとアプリ、最悪 OS ごとダウンするリスキー
な手法でもあり、ある程度アプリや OS に精通している方以外には
お勧めできない手法なんですよね。。。

時間がなくて細かく検証してませんが、夜中か数日中にはその結果、
または参考ソースをアップしときます。

よろしければ締め切らず気長にお待ち下さい。

この回答への補足

 早速のレス有り難うございます。
 
 サブクラス化・・・・?、全くわかりません。。。。 (^^;)
 当方Accessに出会って1年にはなりますが、もとよりソフト開発者ではなく、
限りなくエンドユーザに近い立場であり、ましてやOSに精通など、ほど遠い
状況です。
 
 1週間ほど前にリリースさせ、すでに社内で稼働しているアプリなのですが、
ユーザに対しては、誤ってホイールに触れないように、注意喚起して使って
もらっています。これを、近々回避することができ、しかもシステム的に安定・
安全な方法を教えていただけるのであれば、非常に助かります。
 締め切らずにお待ちいたしますので、よろしくお願い致します。

以上

補足日時:2009/12/16 13:56
    • good
    • 0

レス番号 8910 にある


  
  > Class1モジュールの名前をCMouseWheelに変更します

をやってないとみた。

単に Access ではなく、Access2003 などバージョンまで明記して下さい。
ご参考になった URL のソースは、AddressOf 演算子が使われてますから、
Access2000 以降のバージョンである必要があります。

この回答への補足

KenKen_SPさん

 回答有り難うございます。
 連絡が漏れておりましたが、バージョンはAccess2003 SP3となっています。
 2000以降のバージョンである必要があるとのことですので、まずは対応して
いるということにはなるでしょうか。
 
 さて、
>レス番号 8910 にある  
>  > Class1モジュールの名前をCMouseWheelに変更します
>をやってないとみた。
とのことですが、一応やったつもりではあります。

 現状は、VBAの左下にあるプロパティのペインで、オブジェクト名欄に
CMouseWheel
と記述してありますし、その上のプロジェクトのペインで、クラスモジュール
の下にツリーでぶら下がっているモジュールのイメージの脇にも
CMouseWheelと表示されています。
 これでよろしいのですよね?

 ちなみに、CMouseWheelをダブルクリックして開く、VBAコードの表示
エリア上部左側には(General)と表示され、右側には(Declarations)と
表示されており、コード部分には以下を貼り付けています。

 それでもダメです。よろしくお願いします。
(以下、CMouseWheelのコード)
--------------------------------

Option Compare Database

Private frm As Object
Private intCancel As Integer
Public Event MouseWheel(Cancel As Integer)

Public Property Set Form(frmIn As Object)
Set frm = frmIn
End Property

Public Property Get MouseWheelCancel() As Integer
MouseWheelCancel = intCancel
End Property

Public Sub SubClassHookForm()
lpPrevWndProc = SetWindowLong(frm.hwnd, GWL_WNDPROC, AddressOf WindowProc)
Set CMouse = Me
End Sub

Public Sub SubClassUnHookForm()
Call SetWindowLong(frm.hwnd, GWL_WNDPROC, lpPrevWndProc)
End Sub

Public Sub FireMouseWheel()
RaiseEvent MouseWheel(intCancel)
End Sub

補足日時:2009/12/16 10:44
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!