こんにちは。ネットエージェント株式会社、研究開発部の長谷川です。今日は少し低レイヤの話ということで簡単なハードウェア工作を楽しもうと思います。
-----
■ ディスプレイを回転させたい!
デュアルディスプレイの便利さはみなさんご存じのとおりだと思いますが、PDFやWordなどでA4サイズの文書を表示させているときなどに「ディスプレイを縦向きに表示させたい!」と思うことはありませんか? 私は普段からそう感じており、一時期、サブで使用しているディスプレイを縦向きに使用(表示)して使っていたのですが、日常的な作業では、やはり縦よりも横のほうが向いていることもあり、なかなか思ったほど気持ちよく作業できる環境ではありませんでした。
というわけで、もう少し気軽に縦横を変えられる仕組みを実現しようと思い、ディスプレイ回転ツールを自作しました。
■ 材料
今回使用した材料は以下になります。
- 液晶ディスプレイ用アーム(ARM-41C)
- スイッチ(5Aマイクロスイッチ)
- USB-シリアル変換ケーブル(USB-シリアル変換ケーブルUC-SGT)
- シリアルケーブル
- みんな大好きフリスクケース
まず必要なのは液晶ディスプレイ用のアームです。一般的な液晶ディスプレイ用アームは、視野に対する角度などは細かく調整できますが、ディスプレイそのものの縦横を回転できるものは少ないです。それでも、丹念に探すと液晶の縦横回転機構を備えたものもそれなりの価格で見つかります。今回調達したものは、ライブクリエータ社のARM-41Cというもので、ヨドバシカメラで7000円を切る価格で手に入りました。
次にスイッチですが、これはディスプレイの縦横を検出するために使用します。どのようなものでも構いませんが、今回はおもちゃ売り場で売っていたタミヤの5Aマイクロスイッチを使用しました。
また、スイッチのON/OFFをPCに取り込むために、シリアル通信(いわゆるRS-232C)を利用することにし、今時のPCだとCOMポートがついていないため、USB経由でCOMポートを利用可能にするために、エレコムのUSB-シリアル変換ケーブルUC-SGTを使いました。
あとは、クロスでもストレートでも構いませんので、スイッチに接続するために使用するシリアルケーブル。そして、スイッチを固定する台座として、みんな大好きフリスクケース。それ以外にもネジや両面テープなど適宜用意しておくと便利です。
■ ハードウェア工作
まずは、フリスクケース2個を振り子になるようネジで固定し、回転したときにスイッチが押されるようにスイッチも固定します。振り子側は、きちんとスイッチを押さえられるように中にコインを重りとして入れています(左図)。
シリアルケーブルのDTR、DSRをスイッチにハンダ付けします。また、ケーブルの自重でスイッチやハンダ付け部分が痛まないようにケースにケーブルを固定しておきます(右図)。
スイッチ部分ができあがれば、液晶ディスプレイ背面に両面テープでスイッチ機能付きフリスクケースを取り付けます。しっかりとスイッチが押されるように少し斜めに取り付けるのがコツです。縦、横とディスプレイの向きを変えたときにきちんとスイッチがON/OFFされるか確認します(左図-横、右図-縦)。
これで、ハードウェアの準備は完了です。あまりお金をかけない簡単な工作で、ディスプレイの向きに応じてシリアルポートのDTR-DSRがON/OFFされる装置が出来上がりました。
■ ソフトウェアの準備
ハードウェアを作成したので、次はソフトウェアを組みます。
ディスプレイの向きはシリアルポートのDSR信号を監視することで把握でき、監視するコードは、概ね以下のようになります(監視コードはサービスとして動作させています)。
HANDLE hComm;
OVERLAPPED ov;
DWORD dwCommState;
/* 略 */
EscapeCommFunction( hComm, SETDTR ); // DTR信号をON
SetCommMask( hComm, EV_DSR ); // DSR信号の変化を監視
ResetEvent( ov.hEvent ); // 非同期I/Oのためイベントをリセット
WaitCommEvent( hComm, &dwCommState, &ov ); // DSRの監視スタート
WaitForSingleObject( ov.hEvent, 30000 ); // イベント発生まで待機
ディスプレイ表示の向きを変えるには、以下のようなコードで実現できます(エラー処理等は省略)。
int iDevNum = 1; // Display No.2
DISPLAY_DEVICE d;
DEVMODE dm;
int w;
ZeroMemory( &d, sizeof( d ) );
d.cb = sizeof( d );
EnumDisplayDevices( NULL, iDevNum, &d, 0 ) );
EnumDisplaySettings( d.DeviceName, ENUM_CURRENT_SETTINGS, &dm ) );
w = dm.dmPelsHeight;
dm.dmPelsHeight = dm.dmPelsWidth;
dm.dmPelsWidth = w;
dm.dmDisplayOrientation = DMDO_90; // 90度回転
ChangeDisplaySettingsEx( d.DeviceName, &dm, NULL, CDS_UPDATEREGISTRY, NULL );
全ソースコードはGitHub上に置いてあります。興味がある方は参照してください。
サービスとしてシリアルポートを監視していると、ユーザのディスプレイ(デスクトップ)とは直接対話できないため、シリアルポートからの信号を受け取った時点でログオンしているユーザのトークンを用いてCreateProcessAsUserを使ってディスプレイ表示の向きを変えるためのプログラムを起動しています。
■ さいごに
このように、ディスプレイの向きを検出するスイッチと、それに応じて表示の向きを変えるプログラムを作成することによって、ディスプレイの向きを物理的に変えることで表示も連動して変わり、非常に快適になりました(左図:縦表示)。
ソフトウェアエンジニアにとって、ハードウェア工作は若干敷居が高そうに思えるかもしれませんが、ソフトウェアと同じくらい面白く、また出来ることの幅、可能性も広がると思います。興味があればぜひとも挑戦してみてください。
それにしてもフリスクケースはちょっとした工作にはとても便利ですね。Enjoy!