VB@NTでスクロールバーが真っ白!

どうしてこうなるのか...。 またもや厄介ごとが増えてしまったようだ。 2000年2月に発売されたWindows2000(NT*15)は一筋縄では言うことを聞いてくれないようである。 w2kをインストールしvb5をやっとこさ*2インストールし、 さあ開発の続きをやるぞと意気込んでとりあえずコンパイルしてみると、 そこにこっけいなコントロールがあるのを認めてしまった。(Fig.1)
[へんてこなスクロールバー] -Fig.1
どのように形容したら言いのだろう。 とにかくこうしてこのへんてこなスクロールバーを何とかしなければならない羽目になったのだった。

とりあえずこの現象がこのマシン特有のものなのかそれともNTにおけるVBの固有の現象なのか確かめるべく まったく異なる環境のNT機でも試してみたが見事、再現されてしまった。 どうしよう。 この重大な現象であらばMicrosoftのサポートに必ずあるはずだと考えてまず日本Microsoftのサポートページで検索してもたがそれらしきものは見つからなかった。 しかたがないので米国Microsftのサポートページで検索してみると(キーワードに苦労したが)それらしきページを見つけた。
Q244236 - HOWTO: Use the System Color on ScrollBars Under Windows NT
このページではずばり現象の説明、そして対処方法が記載されていた。つまり、
発生する理由
Win9xではシステムカラーを使っているがWinNTでは白を使っているから
対処方法
vbのスクロールバーはネイティブのスクロールバーではなくvb独自のスクロールバーであり VMがメッセージを処理してスクロールバーの描画処理を行っている。 つまり背景描画時のメッセージをサブクラスで捕捉してシステムに背景描画をさせればよい。
具体的には、標準モジュールに以下のコードを用いて
Option Explicit
Private Const GWL_WNDPROC = (-4)
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Private Const WM_CTLCOLORSCROLLBAR = &H137&

Private m_wndprcNext As Long

Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  Select Case uMsg
    Case WM_CTLCOLORSCROLLBAR
      Exit Function
    End Select

  WindowProc = CallWindowProc(m_wndprcNext, hwnd, uMsg, wParam, ByVal lParam)
End Function

Public Sub SubClass()
  m_wndprcNext = SetWindowLong(frmMain.hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub

Public Sub UnSubClass()
  SetWindowLong frmMain.hwnd, GWL_WNDPROC, m_wndprcNext
End Sub
またフォームモジュールには以下のコードを用いるとよい。
Option Explicit

Private Sub Form_Load()
  SubClass
End Sub

Private Sub Form_Unload(Cancel As Integer)
  UnSubClass

  Set frmMain = Nothing
End Sub
という訳である。 聞いてみると別段変わったこともないことである。 こうしてへんてこなスクロールバーは普通のスクロールバーに戻ったのである。(Fig.2)
[普通のスクロールバー] -Fig.2
しかし、発生する理由がいまいちピンとこない。 私の英語解釈能力の問題もあるかもしれないが、始めからシステムカラーを使えばいいのではと考えてしまう。 もしかしたらGDI関連でNTではややこしかったのでVMが実装するのは面倒だったとか、 ただ単にNTと9xでの動作の違いを考えていなかったとか、 色々考えられるがすべて推測の領域を出ていないしはたまた「仕様です」なんていわれようものなら「そうですね」としか言い様がない。 それにこの情報も扱いが"HOWTO"になっている。.NET*3とか言っているときに"HOWTO"じゃないだろ!といいたくもなる。 と、こんな文体だとよくある「M$*4こきおろし」のパターンでこんなことはもうわかりきっている人にとっては大変退屈なものになってしまう。

閑話休題。 ここで疑問に思ったのは「スクロールバーの背景はどのようにして描画されるのだろう」ということである。 スクロールバーの背景とはFig.3のことである。
[スクロールバーの背景](x5) -Fig.3
この一種のパターンはどのようにして描画されているのだろう。 パターンであるのでブラシつまりストックオブジェクトやシステムブラシにそんなブラシがあるのだろうかと思ったがなかった。 また、Fig.3のパターンは一種の擬似(ディザ)である。 そこでその方向で探ってみると...。
Pen
指定された色がシステムで使用できなかった場合は最近純色を使用する
Brush
指定された色がシステムで使用できなかった場合は擬似色を使用する
やはりブラシであると思った瞬間、TrueColorの時はどうなるんだ、ということに気づいてしまった。 確かにTrueColorのときも相変わらずFig.3のパターンはどのスクロールバーにも見られる。 もしかしたら最初は擬似色のつもりが今ではそれがスクロールバーのデザインとなっているのかもしれない。 このことはまた新しいことがわかり次第扱いたい。[終]

[注釈]
  1. NTというのは「NewTechnology」の略称である。 w2kのパッケージには"Built on NT Technology"とあったがどういうことだ。 [戻る]
  2. w2kにvb5やvc6をインストールしようと思ったらちょっとした"技"が必要である。 CDをセットしただけではエラーがでてだめで、また直接セットアップらしきものをたたいてもvb5ではインストールできるがvc6ではできない。 さてその"技"はvc6のCDで紹介されている。 すなわち、CDを入れた後エラーがでるがOkを押して消して右クリックのコンテキストメニューから「Install」とか「自動実行」を選ぶのだ。 最初はとってもあせった! (エラーが起こってこんな風になる時もあるしマシンによってはそんなこと全然起こらないようだ) [戻る]
  3. .NETというのは最近Microsoftが発表した指針(戦略かもしれないし思想かもしれなし計画かもしれなし構想かもしれなし、 はたまた方針かもしれない)。http://www.microsoft.com/japan/net/では.NETに関する情報を得ることが出来る。(デザインがCSSで出来ていたらそれこそすばらしい(おもしろい)と思ったが画像であった) [戻る]
  4. M$というのはMS+$のことだろうか。 よくできているといえばそうだ。 [戻る]
[参考文献]
  1. Microsoft Developer Network Library 2000.7 > Knowledge Base > Visual Basic > Visual Basic for Windows
    • Q244236 - HOWTO: Use the System Color on ScrollBars Under Windows NT
    • Q168795 - HOWTO: Hook Into a Window's Messages Using AddressOf
  2. ビジュアルベーシックマガジン 98年2月号(翔泳社)
    • p82-99 即解VB5から使うWindowsAPI > VisualBasicの限界を広げるサブクラスかの手法(酒井法雄)
[キーワード]
スクロールバー 背景 白 VisualBasic ScrollBar white