以下に示すのは、ダイアログウィンドウ(フォーム)をベースとしたビューウィンドウを作成する例です。
プロジェクトにView.hというヘッダファイルを追加し、そこにCFormViewというクラスを定義します。
ビューウィンドウの上部には、システムで使用可能なフォントを列挙したリストボックスコントロールを配置し、
フォントを選択するとビューウィンドウの下部にそのフォントでフォント名を描画します。
// View.h
#pragma once
class CFormView : public CDialogImpl<CFormView>
{
public:
enum { IDD = IDD_FORMVIEW_FONT };
CListBox m_list_font;
CString m_strFont; // 描画するフォント名
BOOL PreTranslateMessage(MSG* pMsg){
return CWindow::IsDialogMessage(pMsg);
}
BEGIN_MSG_MAP(CFormView)
MSG_WM_INITDIALOG(OnInitDialog)
MSG_WM_PAINT(OnPaint)
MSG_WM_SIZE(OnSize)
COMMAND_CODE_HANDLER_EX(LBN_SELCHANGE, OnListSelChange)
END_MSG_MAP()
BOOL OnInitDialog(CWindow wndFocus, LPARAM lInitParam){
m_list_font = GetDlgItem(IDC_LIST_FONT);
// 使用可能なフォント名を列挙
CClientDC dc(m_hWnd);
EnumFontFamilies(dc, NULL,
(FONTENUMPROC)FontProc, (LPARAM)m_list_font.m_hWnd);
return TRUE;
}
static int CALLBACK FontProc(ENUMLOGFONT *lpelf,
NEWTEXTMETRIC *lpntm, int nFontType, LPARAM lParam)
{
CListBox list = (HWND)lParam;
list.AddString(lpelf->elfLogFont.lfFaceName);
return 1;
}
void OnPaint(CDCHandle /*dc*/){
CPaintDC dc(m_hWnd);
if(!m_strFont.IsEmpty()){
// サイズ20ポイントのフォントを作成し、選択
CFont font;
font.CreatePointFont(200, m_strFont);
HFONT hOldFont = dc.SelectFont(font);
// ビューウィンドウ下部にフォント名を描画
CRect rcFontView = GetFontViewRect();
dc.SetBkMode(TRANSPARENT);
dc.DrawText(m_strFont,
m_strFont.GetLength(), rcFontView, DT_VCENTER | DT_SINGLELINE);
// 元のフォントを選択
dc.SelectFont(hOldFont);
}
}
void OnSize(UINT nType, CSize size){
if(m_list_font.IsWindow()){
// ビューウィンドウ上部にリストボックスコントロールを配置
CRect rcForm;
GetClientRect(rcForm);
rcForm.bottom /= 2;
m_list_font.MoveWindow(rcForm);
// ビューウィンドウ下部を更新
InvalidateRect(GetFontViewRect());
}
}
void OnListSelChange(UINT uNotifyCode, int nID, CWindow wndCtl){
// 現在選択されているアイテムを取得して表示
int nIndex = m_list_font.GetCurSel();
if(nIndex != LB_ERR){
m_list_font.GetText(nIndex, m_strFont);
// ビューウィンドウ下部を更新
InvalidateRect(GetFontViewRect());
}
}
CRect GetFontViewRect(){
// フォント名を描画する矩形(ビューウィンドウの下部)を取得
CRect rcForm;
GetClientRect(rcForm);
rcForm.top = rcForm.bottom / 2;
return rcForm;
}
};
|
CFormViewクラスでは、まず、
ダイアログを作成する時と同様にenumによってダイアログリソース(IDD_FORMVIEW_FONT)をCFormViewクラスに関連付けます。
次に、WM_INITDIALOGメッセージハンドラで使用可能なフォント名を列挙し、
WM_PAINTメッセージハンドラでm_strFontに代入されているフォント名をビューウィンドウの下部に描画します。
描画する領域はGetFontViewRect()という独自の関数で取得します。
この関数はビューウィンドウの下半分の矩形を返します。
次に、WM_SIZEメッセージハンドラでビューウィンドウの上部にリストボックスコントロールを配置します。
次に通知コードがLBN_SELCHANGEのWM_COMMANDメッセージハンドラとしてOnListSelChange()を追加します。
このハンドラ関数では選択されているフォント名をm_strFontに代入し、
ビューウィンドウの下部を更新します。
次に示すのは、CFormViewクラスを使用する例です。
// stdafx.h
#pragma once
#define WINVER 0x0420
#include <atlbase.h>
#if _ATL_VER == 0x900
#define _SECURE_ATL 1
#endif
#define _WTL_USE_CSTRING
#include <atlapp.h>
extern CAppModule _Module;
#include <atlwin.h>
#include <tpcshell.h>
#include <aygshell.h>
#pragma comment(lib, "aygshell.lib")
#include <atlcrack.h>
#include <atlmisc.h>
#include <atlframe.h>
#include <atlctrls.h>
#define _WTL_CE_NO_ZOOMSCROLL
#define _WTL_CE_NO_FULLSCREEN
#include <atlwince.h>
|
// SampleProjectFrame.h
#pragma once
class CSampleProjectFrame :
public CFrameWindowImpl<CSampleProjectFrame>,
public CUpdateUI<CSampleProjectFrame>,
public CAppWindow<CSampleProjectFrame>,
public CMessageFilter, public CIdleHandler
{
public:
DECLARE_APP_FRAME_CLASS(NULL, IDR_MAINFRAME, L"Software\\WTL")
CFormView m_view;
virtual BOOL PreTranslateMessage(MSG* pMsg){
if(CFrameWindowImpl<CSampleProjectFrame>::PreTranslateMessage(pMsg))
return TRUE;
return m_view.IsWindow() ? m_view.PreTranslateMessage(pMsg) : FALSE;
}
virtual BOOL OnIdle(){
return FALSE;
}
BEGIN_UPDATE_UI_MAP(CSampleProjectFrame)
END_UPDATE_UI_MAP()
BEGIN_MSG_MAP(CSampleProjectFrame)
MSG_WM_CREATE(OnCreate)
MSG_WM_DESTROY(OnDestroy)
CHAIN_MSG_MAP(CAppWindow<CSampleProjectFrame>)
CHAIN_MSG_MAP(CUpdateUI<CSampleProjectFrame>)
CHAIN_MSG_MAP(CFrameWindowImpl<CSampleProjectFrame>)
END_MSG_MAP()
int OnCreate(LPCREATESTRUCT lpCreateStruct){
// メニューバー作成
CreateSimpleCEMenuBar(0, SHCMBF_EMPTYBAR);
// ビューを作成
m_hWndClient = m_view.Create(m_hWnd);
// メッセージループにメッセージフィルタとアイドルハンドラを追加
CMessageLoop* pLoop = _Module.GetMessageLoop();
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);
return 0;
}
void OnDestroy(){
// メッセージループからメッセージフィルタとアイドルハンドラを削除
CMessageLoop* pLoop = _Module.GetMessageLoop();
pLoop->RemoveMessageFilter(this);
pLoop->RemoveIdleHandler(this);
SetMsgHandled(false);
}
};
|
// SampleProject.cpp
#include "stdafx.h"
#include "resourceppc.h"
#include "View.h"
#include "SampleProjectFrame.h"
CAppModule _Module;
int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
HRESULT hRes =
CSampleProjectFrame::ActivatePreviousInstance(hInstance, lpstrCmdLine);
if(FAILED(hRes) || S_FALSE == hRes){
return hRes;
}
hRes = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
ATLASSERT(SUCCEEDED(hRes));
AtlInitCommonControls(ICC_DATE_CLASSES);
SHInitExtraControls();
hRes = _Module.Init(NULL, hInstance);
ATLASSERT(SUCCEEDED(hRes));
int nRet = CSampleProjectFrame::AppRun(lpstrCmdLine, nCmdShow);
_Module.Term();
::CoUninitialize();
return nRet;
}
|
まず、リソースを作成します。プロジェクトにダイアログリソースを追加してリストボックスコントロールを配置し、
それぞれの[ID]を次のように設定します。
なお、ダイアログリソースの[プロパティ]では[Visible]を[True]に、
[Border]を[なし]に、[Style]を[子]に、[System Menu]を[False]に設定します。
| コントロール名 |
ID |
備考 |
| ダイアログ |
IDD_FORMVIEW_FONT |
IDD_POCKETPC_PORTRAIT |
| リストボックス |
IDC_LIST_FONT |
|

次に、CFormViewクラスのインスタンスを
CSampleProjectFrameクラスのメンバ変数として宣言し、
WM_CREATEメッセージハンドラでCreate()を呼び出してビューウィンドウを作成します。
最後に、SampleProject.cppファイルでSampleProjectFrame.hヘッダの前にView.hヘッダをインクルードします。
このようにフォームビューウィンドウは、
フレームウィンドウのクライアント領域上にモードレスダイアログを置いたような仕組みになっています。
|