Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

LuxMenuにおいてCOMはどうやって実現されているのか

デザイン性に優れた拡張メニューコントロール 第2回

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2006/09/28 00:00

前回は洗練されたデザインのメニューコントロール「LuxMenu」と、その使い方を紹介しました。LuxMenuはActiveBasicで開発され、COMコンポーネントとして提供されています。今回は、LuxMenuがどのようなコードを使って、COMコンポーネントを提供しているかについて説明します。

目次

はじめに

 前回はLuxMenuの実装を行いましたが、今回からはそのLuxMenuの内容が果たしてどのようなコードで実現されているのかを解説していきます。

 LuxMenuが提供するモジュールの解説から行いたいところですが、前回説明した通り、LuxMenuはCOMコンポーネントとして提供しています。VC++環境ではMFCやATLなどを利用することで、比較的簡単にCOMコンポーネントを開発できますが、LuxMenuはActiveBasic 5.0(以下、AB)で開発されています。そこで、まずはABでどのようなコードを書けばCOMコンポーネントを生成できるのか、そもそもCOMコンポーネントとしてモジュールを作成するためには、どのようなロジックが必要になるのかを説明します。

準備

 ABは下記のサイトから開発環境をダウンロードできます。お持ちでない方はインストールしておきましょう。

そもそもCOMとは?

 COM(Component Object Model)とはクラスモジュールをバイナリレベルで連結したいという発想のもとに生まれた技術です(もちろん、利用用途はそれだけに留まりません)。簡単に言うと、あるクラスモジュールを外部アプリケーションで利用する場合、外部からの呼び出しが必要なメソッドを、インターフェイスを経由して提供する機能のことです。もともとはMicrosoft社が提唱するソフトウェア間通信の仕様規格であり、既存のソフトウェア市場を見ても非常に多くの部品がCOMによって構成されています。

 また、COMコンポーネントは独特な識別ID(CLSID)によって区別されます。CLSIDはGUIDで構成されており、世界で1つだけの値を持つことができます。

インターフェイス

 COMについての解説を始めると、至るところで「インターフェイス」という言葉が出てきます。このインターフェイスとは、クラスが提供する機能をメソッドベースでまとめ、定義付けたもののことです。

 なかなかイメージが沸かない方のために少し具体的に説明しましょう。インターフェイスは現実の世界でもさまざまな意味を持ちます。例えば、皆さんが今使っているパソコンには、さまざまな端子(インターフェイス)があると思います。LAN端子にモジュラージャックを差し込むことはできませんし、その逆も無理な話です。インターフェイスを通じて、さまざまな機器との接続が可能になり、それらの機能を活用することができますが、然るべき経路を使って、それらの機器を接続させなければならないことは当たり前の話です。

 ここで、話をプログラミングの話題に戻しましょう。COMの世界でインターフェイスと言うと、COMコンポーネントとそれを利用するアプリケーション間の繋ぎ目のことを指します。もっと簡単に言うと、インターフェイスとは、仮想関数の塊のことなのです。

インターフェイスのサンプルコード

 ということで早速、インターフェイスを活用したサンプルコードをABで動かしてみましょう。

インターフェイスのサンプルコード
#N88BASIC

'クラスを定義
Class CTest
    Inherits ITest
Public
    Sub CTest()
        Print "CTestのインスタンスを生成"
    End Sub
    Sub ~CTest()
        Print "CTestのインスタンスを破棄"
    End Sub

    Override Sub ShowMsg()
        Print "ShowMsgメソッドが呼ばれました"
    End Sub
End Class

'インターフェイスを定義
Interface ITest
    Sub ShowMsg()
End Interface

' インターフェイスの生成
Function CreateInstance() As *ITest
    Dim pObj As *CTest
    pObj=New CTest()
    Return pObj As *ITest
End Function

'インターフェイスの破棄
Sub Release(lpTest As *ITest)
    Delete lpTest
End Sub

'-----------------------------------------------------
' 一般的なオブジェクト操作
'-----------------------------------------------------
Dim pobj_Test As *CTest
pobj_Test=New CTest()
pobj_Test->ShowMsg()
Delete pobj_Test

Print
Print

'-----------------------------------------------------
' インターフェイスを経由したオブジェクトへのアクセス
'-----------------------------------------------------
Dim lpTest As *ITest
lpTest=CreateInstance()
lpTest->ShowMsg()
Release(lpTest)

 先頭の#N88BASICというのは、AB特有のディレクティブであり、N88BASICと互換性のある命令語を独自のプロンプト上で動作させるための意味を持ちます。随所でPrint命令を出せるのはある意味うれしい仕様なのかもしれません。

 まず、CTestクラスを宣言しています。コンストラクタとデストラクタがあって、プロンプトに文字列を出力するだけのShowMsgというメソッドを持つ、単純なクラスです。注目したいところは、ITestを継承しており、ShowMsgを実装しているところでしょうか。このように、明示的にITestとの関連性をアピールしています。

 次に、CTestに対応するインターフェイス、ITestを宣言してみましょう。ABではインターフェイスを定義するのに、Interfaceステートメントを利用します。ITestインターフェイスが提供する機能として、ShowMsgを定義しておきましょう。続けてインターフェイスを生成するための関数および破棄するための関数(それぞれCreateInstanceRelease)を用意します。内部では、NewDeleteを呼び出し、CTestオブジェクトの生成と破棄を行っています。外部からダイレクトにNewDeleteをさせないのがインターフェイスの生成と破棄のコツです。

 最後に、定義したクラスやインターフェイスを使って一般的なオブジェクト操作と、インターフェイスを経由したオブジェクトへのアクセスを行ってみましょう。どうですか?ITestからはまったくといっていいほど、CTestが見えなくなってはいないでしょうか。内部的にはCTestのオブジェクトが生成されるものの、表面的には、CreateInstanceでインターフェイスを生成し、実装されているShowMsgメソッドを呼び出し、Releaseで解放を行っているという形になっていますね。

実行画面
実行画面

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

バックナンバー

連載:デザイン性に優れた拡張メニューコントロール
All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5