< June 2005 | July 2005 | August 2005 >

July 3, 2005

システムメニューを持たない CDialog で、タイトルバーをダブルクリックされたら最大化 <-> 元のサイズに戻す

MFC CDialog ネタをもいっちょ。前回サンプル作ったので、その続きに実装しちゃいます。

今回のお題は、システムメニューを持たないダイアログに、「タイトルバーをダブルクリックされたら最大化 <-> 元のサイズに戻す」の機能を実装せよと言うもの。当然、最大化、最小化ボタンもありません。

ところで、VB6 でサイズ変更可能な Form を作成して、ControlBox プロパティに False を設定すると、システムメニューも最大化・最小化ボタンないウインドウができますが、ちゃあんとタイトルバーダブルクリックが効くんですよね。Spy++ でメッセージをキャプチャすると、WM_NCLBUTTONDBLCLK nHitTest = HTCAPTION が落ちてきているのが見えます。そこで、AP 内でもそれを判断させてみることにしてみました。

StatusDialog.cpp 内のメッセージマップ部分に1行追加します。

BEGIN_MESSAGE_MAP(CStatusDialog, CDialog)
    //{{AFX_MSG_MAP(CStatusDialog)
    ON_WM_SIZE()
    ON_WM_NCLBUTTONDBLCLK()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

CStatusDialog クラスに OnNcLButtonDblClk を追加します。

// StatusDialog.h: CStatusDialog クラスの宣言の中。
// どこでもいいんだけど、他のメッセージハンドラと同じ位置に追加しておくと、後で見やすいかも。

protected:

    // 生成されたメッセージ マップ関数
    //{{AFX_MSG(CStatusDialog)
    virtual BOOL OnInitDialog();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnNcLButtonDblClk (UINT nHitTest, CPoint point);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()

// StatusDialog.cpp

void CStatusDialog::OnNcLButtonDblClk (UINT nHitTest, CPoint point)
{
    if (HTCAPTION == nHitTest)
    {// ダブルクリックされたのはタイトルバー
        if (IsZoomed ())
        {// 最大化中
            SendMessage (WM_SYSCOMMAND, SC_RESTORE, 0);
        }
        else
        {// 最大化されてない
            SendMessage (WM_SYSCOMMAND, SC_MAXIMIZE, 0);
        }
        return;
    }

    CDialog::OnNcLButtonDblClk (nHitTest, point);
}

実行してみると、なかなか期待したとおりの動き。でもよく見ると、なぜか最大化した時にタスクバーと重なってしまいます。前回ステータスバーを付けてなかったら気付かないかもですが、とにかく、タスクバーのサイズを無視して、デスクトップいっぱいいっぱいまで最大化してしまっているようです。

続きを読む...

July 2, 2005

CDialog より派生したダイアログにステータスバーをつける

MFC ネタ。 CDialog より派生したダイアログウインドウに、ステータスバーをつけなきゃならなくなりました。とりあえずは AppWizard で SDI アプリケーションを作ってみて、それを参考にダイアログクラスに CStatusBar 型のメンバ変数を追加し、OnInitDialog に初期化コードを書いてみました。

#if !defined(AFX_STATUSDIALOG_H__815300F5_01CC_433D_9286_4C8CEEC28D27__INCLUDED_)
#define AFX_STATUSDIALOG_H__815300F5_01CC_433D_9286_4C8CEEC28D27__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// StatusDialog.h : ヘッダー ファイル
//

/////////////////////////////////////////////////////////////////////////////
// CStatusDialog ダイアログ

class CStatusDialog : public CDialog
{
// コンストラクション
public:
    CStatusDialog(CWnd* pParent = NULL);   // 標準のコンストラクタ

// ダイアログ データ
    //{{AFX_DATA(CStatusDialog)
    enum { IDD = IDD_STATUSDIALOG };
        // メモ: ClassWizard はこの位置にデータ メンバを追加します。
    //}}AFX_DATA


// オーバーライド
    // ClassWizard は仮想関数のオーバーライドを生成します。
    //{{AFX_VIRTUAL(CStatusDialog)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV サポート
    //}}AFX_VIRTUAL

// インプリメンテーション
protected:

    // 生成されたメッセージ マップ関数
    //{{AFX_MSG(CStatusDialog)
    virtual BOOL OnInitDialog();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()

    CStatusBar m_StatusBar;
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ は前行の直前に追加の宣言を挿入します。

#endif // !defined(AFX_STATUSDIALOG_H__815300F5_01CC_433D_9286_4C8CEEC28D27__INCLUDED_)
// CStatusDialog.cpp の OnInitDialog
/////////////////////////////////////////////////////////////////////////////
// CStatusDialog メッセージ ハンドラ

BOOL CStatusDialog::OnInitDialog() 
{
    CDialog::OnInitDialog();
    
    // TODO: この位置に初期化の補足処理を追加してください

    if (!m_StatusBar.Create (this))
    {
        MessageBox (_T ("CStatusBar::Create failed"));
    }
    
    return TRUE;  // コントロールにフォーカスを設定しないとき、戻り値は TRUE となります
                  // 例外: OCX プロパティ ページの戻り値は FALSE となります
}

実行してみましたが・・あれ?効いてませんね・・

スクリーンショット (失敗編)

続きを読む...