● 色の設定ダイアログ ●

2010/8/21追記
もうこのページのネタは古いです。
色の設定ダイアログを拡張するをご覧あれ!!

私はこのダイアログボックスを気に入っていたりする。

VB4.0時代、このダイアログボックスをどうにかして表示させてやろうといきり立っていた。当時の私のVB知識は、納豆1粒みたいなものであったから当然できなかった。また、ある掲示板によるとVBでは表示不可能という記述があったような気もする…(かなり曖昧だが、それを読み、「やっぱ、駄目なんだなぁ」とあきらめた記憶がある)。

なぜ不可能かというと、CHOOSECOLOR 構造体のメンバ lpCustColors にカスタムカラー配列へのポインタを渡さなければならないが、VBにはそういう機能が無いと思われていたからである。だがある時、それが実現された。API関数 GlobalAlloc、GlobalLock を使用する方法である。また VatPtr 関数を使用する方法も出てきた。VarPtr はオブジェクトブラウザでは隠し関数として位置づけられいる関数で、その機能は、「変数のアドレスを取得する」というもの。Long型の配列変数 CustomColor(15) を宣言し、VarPtr(CustomColor(0)) としてやればよいのである。なるほど、API関数を使うより楽チンではある。が、今後Microsoft がサポートするかは不明なので使わないにこしたことはない(←当時は本当にこのように思っていました(2010/8/6 追記))。その他の方法はないのであろうか。

それではどうするか。VarPtrで渡した変数に注目する。Long型変数が16個、即ち64バイト。ただ、これから単純な発想で String$(64, Chr$(0)) としたら…、驚いたことに動いてしまった。

本当に正しいかどうかは分からないが、ここでのサンプルは String$(64, Chr$(0)) を使用した例にする。

Private Type CHOOSECOLOR
    lStructSize As Long   'この構造体のサイズ
    hWndOwner As Long    '親ウインドウハンドル
    hInstance As Long    'インスタンス
    rgbResult As Long    '選択したRGB値
    lpCustColors As String    'カスタムカラー配列へのポインタ
    flags As Long    '動作指定フラグ
    lCustData As Long   'カスタムダイアログへのデータ
    lpfnHook As Long    'フック関数へのポインタ
    lpTemplateName As String   '???
End Type

Private Declare Function ChooseColor Lib "comdlg32.dll" Alias "ChooseColorA" (pChoosecolor As CHOOSECOLOR) As Long

Private Const CC_RGBINIT = &H1 'ダイアログボックスの色の初期値を設定する
Private Const CC_LFULLOPEN = &H2 '色の作成を行う部分を表示する
Private Const CC_PREVENTFULLOPEN = &H4 'ダイアログボックスの [色の作成]ボタンを無効にする
Private Const CC_SHOWHELP = &H8   'ヘルプボタンを表示する
Private Const CC_ENABLEHOOK = &H10 'lpfnHoolで指定されたフック関数を有効にする
Private Const CC_ENABLETEMPLATE = &H20 'hInstanceとlpTemplateNameで指定されたダイアログテンプレートを使って作成する
Private Const CC_ENABLETEMPLATEHANDLE = &H40 'hInstanceがロード済みのテンプレートを含むメモリブロックを差す

早速、関数を書いてみます。

'----------------------------------------------------------------
'  関数名 : GetColorValue
'  機能   : 色の設定ダイアログボックスを表示し、指定色のRGB値を得る
'  引数   : (in) hWnd … フォームのハンドル
'  戻り値 : 成功 : RGB値
'                キャンセルが押された :-1
'                エラー : -2
'----------------------------------------------------------------
Public Function GetColorValue(ByVal hWnd As Long) As Long

    Dim udtChooseColor As CHOOSECOLOR
    Dim ret As Long    'ChooseColor関数の返り値

    With udtChooseColor
        .lStructSize = Len(udtChooseColor)  '構造体のサイズ設定
        .hWndOwner = hWnd            'オーナーハンドルの設定
        .hInstance = App.hInstance    'インスタンス設定
        .lpCustColors = String$(64, Chr$(0))    'カスタムカラー配列の設定
        .flags = CC_RGBINIT              'フラグ設定
    End With

    ret = ChooseColor(udtChooseColor)

    If ret <> 0 Then
        'もし RGB(255, 255, 255) 以上の値を受け取ったらエラー
        If udtChooseColor.rgbResult > RGB(255, 255, 255) Then
            GetColorValue = -2
        Else
            'RGB値をセット
            GetColorValue = udtChooseColor.rgbResult
        End If
    Else
        'キャンセル
        GetColorValue = 0
    End If

  End Function

以下のコードをお試しあれ

Private Sub Command1_Click()
    Me.BackColor = GetColorValue(Me.hWnd)
End Sub

戻る