[BlueLeaf1336]> PROBLEMS> winbeads>

winbeads > 方針変更-GUIに手を出してみる

historyTOP

2005/02/06:作成

ソースコードと実行ファイルはココにあります

2005/02/06TOP

CPU情報の取得でくじけて、ネットワーク情報の取得で(一度やったことがあるということもあって)邪魔くさくなってきたので、気分を変えるために、アプリケーションそのものの動作について考えてみることにします。..実は、決めているんですが。どんな感じかというと、いかにもありがちなマッキントッシュ風の画面てっぺん占有メニューで行くことにします。

で、そのメニューから呼び出される中に、今回すこーしだけつくってほとんどパクッてきた取得情報を表示させようじゃないかと。

とりあえず、画面はなくてメニューだけ、つまり起動時にメニューの高さとデスクトップの幅と同じサイズの幅を持つフォームを表示しようと思います。

procedure TMainForm.FormCreate(Sender: TObject);
var
    R: TRect;
begin
    //  キャプションを表示しない
    Self.BorderStyle := bsNone;
    //  デスクトップの作業領域を取得する
    SystemParametersInfo(SPI_GETWORKAREA, 0, @R, 0);
    //  フォームのサイズを設定する
    Self.BoundsRect := Rect(0,
                            0,
                            R.Right - R.Left,           //  作業領域の幅
                            GetSystemMetrics(SM_CYMENU) //  メニューの高さ
                            );
end;

こんな感じです。ただ、このままだとマイコンピュータなどの画面のてっぺんに表示されているアイコンが隠れてしまうので、アプリケーションバー(Delphi Win32 Graphics API リファレンスで初めて知ったんですが、タスクバーなどデスクトップ上のアイコンが領域侵犯してこないように画面を占有するウィンドウのこと)にしようと思います。

アプリケーションバー(タスクバー風な動作をする何か)TOP

(******略******)

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, Buttons, Menus, ShellApi;

const
    WM_DELAPPBAR = WM_APP + 1024;

type
  TMainForm = class(TForm)
    (******略******)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    (******略******)
  protected
    procedure CreateParams(var Params: TCreateParams); override;
    procedure WMDELAPPBAR(var Msg: TMessage); message WM_DELAPPBAR;
  public

  end;

var
  MainForm: TMainForm;

implementation

(******略******)

{$R *.dfm}

//=============================================================================
//  TAppBarData 構造体操作関数
//=============================================================================

//  グローバル変数でないと駄目です。理由は知りません。
var
    AppBarInfo: TAppBarData;

//-----------------------------------------------------------------------------
//  アプリケーションバーのサイズと位置を主張
procedure RequestAppBarPos();
begin
    //  占有したい領域を設定する
    AppBarInfo.rc := Rect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYMENU));
end;
//-----------------------------------------------------------------------------
//  アプリケーションバーのサイズと位置に影響するイベントが発生した!
procedure AppBarPosChanged();
var
    R: TRect;
begin
    //  占有したい領域を設定する
    RequestAppBarPos();
    //  使用できる領域をシステムに問い合わせる
    SHAppBarMessage(ABM_QUERYPOS, AppBarInfo);
    //  アプリケーションバーの位置を調節する
    AppBarInfo.rc.Bottom := AppBarInfo.rc.Top + GetSystemMetrics(SM_CYMENU);
    //  システムに新しいアプリケーションバーの位置を通知
    SHAppBarMessage(ABM_SETPOS, AppBarInfo);
    //  アプリケーションバーを指定位置に移動
    R := AppBarInfo.rc;
    MoveWindow(AppBarInfo.hWnd, R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top, true);
end;

//=============================================================================
//  アプリケーションバーになるための処理
//=============================================================================

//-----------------------------------------------------------------------------
//  スタイル設定
procedure TMainForm.CreateParams(var Params: TCreateParams);
begin
    inherited CreateParams(Params);
    //  WS_EX_TOOLWINDOW と WS_POPUP が必須のようです。
    Params.ExStyle := WS_EX_TOOLWINDOW;
    Params.Style := WS_POPUP;// or WS_CLIPCHILDREN;
end;
//-----------------------------------------------------------------------------
//  アプリケーションバーに影響するイベントを受けとる
procedure TMainForm.WMDELAPPBAR(var Msg: TMessage);
begin
    case Msg.WParam of
    //  画面がフルスクリーンモード
    ABN_FULLSCREENAPP:
        begin
        end;
    //  アプリケーションバーのサイズと位置に影響するイベントが発生
    ABN_POSCHANGED:
        begin
            AppBarPosChanged();
        end;
    //
    ABN_STATECHANGE:
        begin
        end;
    //
    ABN_WINDOWARRANGE:
        begin
        end;
    end;
end;
//-----------------------------------------------------------------------------
//  フォームクリエイト
procedure TMainForm.FormCreate(Sender: TObject);
begin
    //  キャプションを表示しない
    Self.BorderStyle := bsNone;

    //  構造体にアプリケーションバーのハンドルを設定
    AppBarInfo.hWnd := Self.Handle;
    //  アプリケーションバーを登録
    SHAppBarMessage(ABM_NEW, AppBarInfo);
    //  アプリケーションバーの位置決定
    AppBarPosChanged();
end;
//-----------------------------------------------------------------------------
//  フォーム破棄
procedure TMainForm.FormDestroy(Sender: TObject);
begin
    AppBarInfo.cbSize := SizeOf(AppBarInfo);
    AppBarInfo.hWnd := Self.Handle;
    AppBarInfo.lParam := 0;
    //  アプリケーションバーの登録解除
    SHAppBarMessage(ABM_REMOVE, AppBarInfo);
end;
//-----------------------------------------------------------------------------
//  フォームがアクティブになったとき
procedure TMainForm.FormActivate(Sender: TObject);
begin
    //  アプリケーションバーをアクティブにする
    SHAppBarMessage(ABM_ACTIVATE, AppBarInfo)
end;

(******略******)

//=============================================================================
//  初期化時・終了時処理
//=============================================================================

initialization
    //  念のためゼロクリアしておく
    FillChar(AppBarInfo, SizeOf(AppBarInfo), 0);
    //  いくつかの項目をセットする(どれを設定すべきかは丸写し)
    //  構造体のサイズを設定
    AppBarInfo.cbSize := SizeOf(AppBarInfo);
    //  天辺に表示するタイプで
    AppBarInfo.uEdge := ABE_TOP;
    //  占有したい領域を設定する
    RequestAppBarPos();
    //  コールバック用のメッセージ
    AppBarInfo.uCallbackMessage := WM_DELAPPBAR;
end.

とりあえず、何となく動いているような様子です。もちろん動くようなサンプルからもらってきているコードだから動かない方がおかしいんですが。あとはメニューから呼び出すいろんな便利そうな、あるいはココまでの話に絡まるような処理をちまちまと追加するだけです。

それから、以前に作ったりパクッたりした、ココまでの話とは全く関係のない話の参考文献はこんな感じです。こちらはアプリケーションバーとは全く関係がないです。単に今日時点でダウンロードできるソースコードでコメント内に参考文献表示してあるサイト(ただし既にリンク済みのサイトは再掲載は省略させて戴いてます)をかき集めただけです。

EOFTOP