どうしてこうなるのか...。
またもや厄介ごとが増えてしまったようだ。
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のパターンはどのスクロールバーにも見られる。
もしかしたら最初は擬似色のつもりが今ではそれがスクロールバーのデザインとなっているのかもしれない。
このことはまた新しいことがわかり次第扱いたい。