をるふちゃんのブログ

めもっぽいやつ

Chrome上でホイールを回してつい拡大縮小しちゃう問題を解決する

発端

Chromeを使いこなす諸兄におかれましてはCtrl + W でタブを閉じたり、Ctrl + Tでタブを新しく作ったりする方がたくさんおられるかと思いますが、
タブを一気に閉じるとき記事をざっと流し読みして(ホイールを回して)閉じるかどうか検討するときにうっかりCtrlに触ってたり、そうでなくても操作の最中にうっかりマウスホイールに触ると

拡大縮小 してしまう

ことはございませんでしょうか???

そのたびに歯噛みしてゆっくりゆっくりマウスホイールを回す(反応が遅いので様子を見ながら100%に戻るまで回す)か、
アドレスバーにある虫眼鏡のマークを押して「デフォルトに戻す」をクリックすることと思いますが、そもそもマウスを動かして「デフォルトに戻す」まで持っていくのがダルい!しかもあのポップアップすぐ消えちゃう。 Ctrl + 0を押してもいいけどマウスから手を離して0に指を置くのが面倒くさい。

ということで無効化したいと思った次第。
だってCtrl + [+/-]で拡大縮小できますし。

Chromeの設定

Chromeの設定にホットキーって無いんですね、びっくりしました。
そういえば以前「Backspace」を押すとブラウザバックしてしまうのを阻止できないと嘆いた記憶があったりなかったり。

Chromeウェブストアの拡張機能

探してみました。いかにも怪しげな拡張機能で無効化できそうなことが書いてありましたが、私の環境では できません でした。Chromeはバージョン更新激しいですしね。対応しなくなったのかも。

というわけで前置きが長くなりましたが

AutoHotKeyというアプリケーションを入れることにしました。
かいつまむと、WinAPIのメッセージを監視できるアプリケーションで、任意のキー押下に反応して様々な動作をスクリプティングできるというおしゃれなソフトみたいです。

導入~設定まで

サクッとインストールしちゃってください。
私はインストールオプションには全部チェックを入れましたが、なくても動くかもしれません。

続いて、邪魔にならなさそうな任意のディレクトリに以下のようなスクリプトを書きます。

#IfWinActive ahk_class Chrome_WidgetWin_1
^WheelDown::
Send, {WheelDown}
return
^WheelUp::
Send, {WheelUp}
return

拡張子は.ahkです。chrome_WheelBlock.ahkとでも命名しておきましょう。
これを保存してダブルクリックするとスクリプトが裏で動き始めます。
タスクトレイアイコンに「H」のアイコンが出ていれば大丈夫でしょう。

親切なことに、スクリプトに文法エラーがあった場合エラーダイアログを吐いてくれるし、既存のスクリプトを編集した場合、置き換えてよいか?というダイアログが出たりします。

せっかくなのでスタートアップに登録しておきましょう。
C:\Users\任意のユーザーアカウント名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup このあたりにそのディレクトリがある気がするので、ショートカットを作ってそこに放り込んでおけば、Windowsの起動時にそのスクリプトを実行(開始)してくれます。

とりあえずこれでChromeアクティブの状態の時は Ctrl + Wheelをブロックしてくれます。

既知の問題

非アクティブ時

アプリケーションが非アクティブ時も、マウスがChromeの上に載っていればWindows10ではマウスイベントが送信されます。
これはこのスクリプトでは解消できません。

(ここからは面倒な話になります)
このアプリケーションはWindowメッセージを監視して処理していますが、実装上(あとスクリプトの文法的な限界もあって)非アクティブウィンドウにメッセージを投げるのが簡単ではありません。
スクリプト書いてみたのですが、Chromeのウィンドウクラス(Chrome_WidgetWin_1)に送られるウィンドウメッセージのうち0x020A(マウスホイール操作)だけを捕捉してそれをブロックするいい方法がこのAutoHotKeyの関数には用意されていませんでした。
任意のdllを呼んで結果を取ってくる関数があったので、user32.dllGetClassNameを使ってむりくりなんとかなるかもしれませんが、それをやるくらいなら多分自分でアプリケーション書いたほうが早いかも…。
ということで棚上げ。

Chrome非アクティブ時にマウスが乗った状態でCtrl + Wheel操作を行ってしまった」という状況は、前述のCtrl+WやTの誤動作に比べれば遥かに少ないので誤差の範囲かなと思ってここはひとつ。

それを踏まえた上で、先のスクリプトの一行目の#IfWinActive#IfWinExistに書き換えると、Chrome(Chromium)のアプリケーションが1つでも存在している間はCtrl + Wheelをブロックするように動作させることができます。

さらにいうと、一行目をまるっと消して恒久的にCtrl + Wheelをブロックしてしまうのも手かもしれません。
他アプリケーションでもCtrl + Wheelの誤動作はそこそこあると思いますし、タスクトレイアイコン右クリックしてPause Scriptをすれば済む話ですし。

他のキーとの組み合わせ

今回のスクリプトではCtrl + Wheelをブロックしていますが、その2つに加えてAltかWinかShiftキーを一緒に押すと従来通り拡大縮小が行われます。
というのも文法規則で「^を先頭につけるとCtrlを付け加えるとみなす」とあるわけですが、+がShift、!がAlt、#がWinキーとそれぞれ対応しており、組み合わせた際の動作はそれぞれ別になっているようなのです。
ですからある意味「Ctrl + Wheelを完全に止めてしまってもAltあたりのキーを追加で押せば従来通り拡大縮小されるという仕様」と捉えることもできますね(誤動作しにくくなったのは良いこと)。

他アプリケーションでの動作

今話題のギフハブ製のテキストエディタ:AtomChromiumベースらしいです。
このスクリプトではウィンドウクラス名を判定してWheel回転を検知しているのですが、Spyで調べたらAtomのウィンドウクラス名もChrome_WidgetWin_1だったので同じように作動します。
移植する際にウィンドウクラス名くらい変えておけよって思うんですけど。

おきまりのやつ

なお、この記事を利用して(中略)

  • 事故っても関知しない、自己責任で
  • いやこれ動かない、とか言われても困るけど、気が乗ったらサポートするかもしれない
  • 導入できないとか気合でなんとかして。

以上!

DirectInputとは【自分用まとめ】

概要

アプリケーションがバックグラウンドで動作していても、基本的な入力デバイスからデータを取得することができる。
DirectX8 SDKが必要。
ちなみにDirectX8から更新されていないのには深いわけがあるらしい。
最近はXInputなるものを推奨していて、Windowsストアアプリ(Xbox版)などはそちらを使えと言われたり。
通常のアプリではWindowsメッセージを使った実装を推奨されている。
が、ゲーム動かすならドライバレベルで動作するほうが楽っちゃ楽かも。
だいたい入出力APIなんて16年経ってもそう変わるものではないのだろう。

動作について

デバイスドライバを直接叩く。
そのためWindowsのマウス・キーボードメッセージは抑制または無視される。
さらに、ユーザがコントロールパネルで行ったマウス・キーボードの設定も無視するが、入力デバイスに直接設定されているキャリブレーションなどは使用する。
※ゲーミングマウスや一部のジョイスティックなどの設定は生きるということ。

キーボードの文字反復の設定は認識しない(押下と解放を反復なしのイベントとして認識し、押しっぱなしにしても続けて入力されない)。
これはつまりキーの物理的な状態のみに着目し、Windowsで解釈されるイベントには関与しないということでもある。
また文字変換や翻訳は実行しない。

マウスもドライバレベルで直接動作するので、ウィンドウアプリケーションについてマウスデータを解釈するWindowsのサブシステムをバイパスする。
排他モードで取得した場合はマウスメッセージを抑制するのでWindowsは標準カーソルを表示できない。

また、マウスの加速やボタン機能の入れ替えなどのコントロールパネルの設定は無視される(ドライバレベルの設定ならば認識する)。

文字コードサポート

ANSIまたはUnicode
#define UNICODE と定義されている場合は、コンパイル時にUnicode バージョンが使用される。

用語

バイ

キーボード・マウス・ジョイスティックその他の入力デバイスのこと。

DirectInput オブジェクト

COMモデルでIDirectInput8 インターフェイスをサポートする。

DirecInputDevice オブジェクト

IDirectInputDevice8 インターフェイスインスタンス化し、各種の入力デバイスを表す。
タッチパッド付きキーボードなどは複数のDirectInputDeviceで表される。

バイスオブジェクト

DirectInputDevice オブジェクト上のキー・ボタン・トリガなどを表す。
バイスオブジェクト インスタンスとも呼ぶ。

ジョイスティック

DirectInputにおいては、マウス・キーボード以外のすべての種類の入力デバイスのことを総称してジョイスティックと呼ぶ。
入出力両方を処理するジョイスティックオブジェクトを作成することもできる。

流れ

1. DirecInput オブジェクトを作成

このオブジェクトのメソッドを使ってデバイスを列挙、DirectInputバイスオブジェクトを作成する。

2. デバイスを列挙

システムマウス・キーボード以外を使う場合は省略してもよし。
ユーザのシステムで、それ以外に使用可能な入力デバイスがある場合は列挙する。
DirectInputに設定した基準と一致したデバイスを検出したらその機能を調べることができ、一意なIDを取得する。

IDirectInputDevice8::EnumObjects メソッド

使用可能なデバイス オブジェクトの数と種類を確認する。
個別のデバイスオブジェクトは DIDEVICEOBJECTINSTANCE 構造体で記述される。

3. DirecInputDeviceオブジェクトの作成

使用するデバイスごとにDirecInputDeviceオブジェクトを作成する。
列挙時に取得した一意のIDを使う。
システムマウス・キーボードは標準の一意の識別子(GUID)を使用できる。

4. デバイスのセットアップ

バイスの、他アプリケーションやシステムとの共有の方法(協調レベル)を決定する。
データパケット内でデバイスを識別するフォーマットを決める。
イベントを取得する場合、バッファサイズの設定も必要。
ジョイスティック等の場合値の範囲も設定できる。

5. デバイスを取得

バイスからデータを受信できるようになったということをDirectInputに知らせる。

6. データを取得

ループ毎などで、各デバイスの現在の状態・最後の取得以降に発生したイベントの記録を取得。
イベント駆動型に設定することもできる。

7. データに基づいて処理を行う

ゲームの処理など。

8. DirectInputを終了

終了する前にアプリは全てのデバイスの取得を解除し、各種オブジェクトを解放する必要がある。

参考

DirectInput の概要 (MSDN)
DirectInput について (MSDN)

Boost導入メモ

MSVCだとどうしたらいいのってなる

ダウンロード

とりあえずboost.orgから最新版を落としてくる。
boost_1_62_0.zipをダウンロードした。

解凍

何も考えずにC:\直下にboostというディレクトリを作り、UnZipして出てくるboost_1_62_0をその中に放り込む。
以下のようになる。

C:
   |-boost
      |-boost_1_62_0

ここで色々面倒なので環境変数BOOST_ROOTC:\boost\boost_1_62_0を設定しておいた。
これで%BOOST_ROOT%とすればアクセスができる。

一応これでヘッダオンリーのライブラリ部分は使えるようになるようだ。
というか、使えた。

動作確認

boost.orgのサンプルコードほぼそのままで恐縮であるが、以下のコードが通ればうまくいっている。
もっとも、解凍してパスを通すだけなのだが。

#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>

int main() {
    std::for_each( std::istream_iterator<int>( std::cin ), std::istream_iterator<int>(), std::cout << (boost::lambda::_1 * 3) << "\n" );
}

MSVCの場合、プロジェクト設定で追加のインクルードディレクトリに$(BOOST_ROOT)を追加する必要がある。

リンクライブラリを要求される

調子に乗ってコードを書いていくと以下のようなエラーを吐く。

1>LINK : fatal error LNK1104: ファイル 'libboost_regex-vc140-mt-gd-1_62.lib' を開くことができません。

.lib.dllといったリンクライブラリを要求してきている(つまりヘッダオンリーではない関数を呼ぼうとした)
ということなので、これらのパスを通す必要があるわけだが、これらはboostの配布ファイルには直接同梱されていないので自分でビルドする必要がある。

リンクライブラリのビルド

幸いなことに、簡単にできるよう用意されているのでマニュアルに従って実施する。
まず%BOOST_ROOT%ディレクトリ直下にあるbootstrap.batを叩く。
続いて%BOOST_ROOT%ディレクトリでコマンドプロンプトを起動する。

コマンド.\b2と押下したら仮眠をとる。
※というのも、端末の冷却装置がboostするくらい熱くなりとても時間がかかる。
ともあれ、気づいたら%BOOST_ROOT%\stage\libにわんさとリンクライブラリが生産されている。

あとは適切なディレクトリパス(%BOOST_ROOT%\stage\lib)をプロジェクト設定の「リンカ-全般-追加のライブラリディレクトリ」に設定すれば良い。

64bitでも動かしたい場合

b2に色々と情報を与えてやらなければならない。
オプションの意味については公式のマニュアルに譲るとして、
せっかくなので32と64bit版それぞれ.dll.lib版を作ることとしよう。

%BOOST_ROOT%ディレクトリにて以下のコマンドを叩く。

b2 toolset=msvc-14.0 threading=multi variant=debug,release link=static runtime-link=static architecture=x86  address-model=32 --stagedir=stage/x86 -j 4 --without-python
b2 toolset=msvc-14.0 threading=multi variant=debug,release link=shared runtime-link=shared architecture=x86 address-model=32 --stagedir=stage/x86 -j 4 --without-python
b2 toolset=msvc-14.0 threading=multi variant=debug,release link=static runtime-link=static architecture=x86 address-model=64 --stagedir=stage/x64 -j 4 --without-python
b2 toolset=msvc-14.0 threading=multi variant=debug,release link=shared runtime-link=shared architecture=x86 address-model=64 --stagedir=stage/x64 -j 4 --without-python

この端末は2コア4スレッドのため、-j 4オプションを付けている。適宜調整されたい。
私はpythonは使わないため最後に--without-pythonオプションを付けた。これも必要に応じて削除すること。

それと私はVisual Studio 2015を使っているため--toolset=msvc-14.0とした。
このオプションはつけなくても適切なコンパイラを使ってくれるようであるが念のため付け加えておいた。

これによりディレクトリ構成は以下のようになる。

%BOOST_ROOT%
   |- stage
      |-x64
         |-lib
      |-x86
         |-lib

当ブログについて

はじめましての方は少ないだろうか。

当ブログについて

経験則上、日記にするとろくな事にならない(三日坊主を起点にブログ自体から遠ざかる) ので、技術的な話だけに限定して記事を書いていくことにします。

サブタイトルにもある通り、内容は C++ | DirectX | x86解析 | デザパタ | ゲーム制作 といったところかな。 連載などという高尚なことができるかどうかは不明なので過度な期待はしないように。
参考にした書籍はなるべく記載するようにするので、よければ購入の参考にされたい。

Facebook

個人的な日記(不定期)はこちらをご覧ください。 友人関係にない方の申請は削除します。ぜひMessageを添えていただければと思います。
(実際に会ったことがあるかどうかは友人の定義には含めていませんが常識の範囲で)
なお、多くの投稿はグローバル公開になっているのでフォローのみの対応もぜひご検討ください。

Twitter

手軽に会話したいとお考えの方はこちらをご覧になってください。
リプライによる会話を好みますが、基本的には垂れ流し状態です。
継続的に発信内容を摂取したいと感じたらフォローを実施します。
フォロー返ってこないとしてもリプライは基本的には歓迎ですのでどうぞ。
ブロック機能はめったに使いませんが、お手柔らかに。

Skype

IDは wolf_k_k です。絡みがある方なら申請通しますので一言添えていただければと思います。
通話の前にお声かけいただければ幸いです。さぎょいぷ歓迎。