Использование редактора ресурсов для создания главной диалоговой панели
Используя редактор ресурсов, создаем внешний вид диалоговой панели, например, такой, как показано на рисунке:
Каждому элементу поставим в соответствие идентификатор.
Использование ClassWizard для создания класса главной диалоговой панели.
Используя ClassWizard, задайте имена и типы членов класса для каждого элемента диалога:
Элемент | Идентификатор | Имя | Тип |
Иконка | IDC_MYICON | m_Icon | CStatic |
Редактирование | IDC_MYEDIT | m_Edit | int |
Выпадающий список | IDC_MYCOMBO | m_Combo | CString |
Полоса прокрутки | IDC_MYSCROLLBAR | m_ScrollBar | int |
Ползунок | IDC_MYSLIDER | m_Slider | CSliderCtrl |
Класс CDialogDlg описан в файле DialogDlg.h:
/////////////////////////////////////////////////////////////////////////////
// CDialogDlg dialog
class CDialogDlg : public CDialog
{
// Construction
public:
CDialogDlg(CWnd* pParent = NULL); // стандартный //конструктор
// Dialog Data
//{{AFX_DATA(CDialogDlg)
enum { IDD = IDD_DIALOG_DIALOG };
CSliderCtrl m_Slider;
CStatic m_Icon;
int m_Edit;
CString m_Combo;
int m_ScrollBar;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDialogDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX);
// DDX/DDV поддержка
//}}AFX_VIRTUAL
// реализация
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CDialogDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
Объявление класса.
Класс CDialogDlg наследуется от базового класса CDialog, определенного в библиотеке классов MFC. Конструктор класса имеет один необязательный параметр pParent, используемый для передачи индекса главного окна приложения. Роль главного окна выполняет сама диалоговая панель, поэтому параметр pParent не используется.
Непосредственно после объявления конструктора класса следует объявление элементов данных класса, которые добавлены средствами MFC ClassWizard. Не рекомендуется вручную изменять код приложения, расположенный между комментариями AFX_DATA, между которыми заключены эти объявления.
Далее ClassWisard добавляет объявления переопределенных виртуальных методов базового класса. Сначала объявлен только метод DoDataExchange, переопределенный для данной диалоговой панели.
Диалоговая панель CDialogDlg будет обрабатывать ряд сообщений. Объявления обработчиков сообщений, созданных при помощи ClassWizard, располагаются между комментариями AFX_MSG.
Непосредственно после объявления конструктора класса следует объявление элементов данных класса, которые добавлены средствами MFC AppWizard. Не рекомендуется вручную изменять код приложения, расположенный между комментариями AFX_DATA, между которыми заключены эти объявления.
Далее AppWisard добавляет объявления переопределенных виртуальных методов базового класса. Сначала объявлен только метод DoDataExchange, переопределенный для данной диалоговой панели. Этот метод применяется для связывания органов управления диалоговой панели с элементами управляющего ею класса.
Практически со всеми приложениями связана пиктограмма, которая будет отображаться при минимизации приложения. Обычно эта пиктограмма определяется на этапе регистрации класса главного окна приложения. Приложение Dialog не имеет настоящего главного окна - вместо него используется диалоговая панель. Поэтому отображение пиктограммы не происходит автоматически, и, следовательно, необходимо управлять ее отображением (идентификатор пиктограммы m_hIcon определен в классе CDialogDlg).
Диалоговая панель CDialogDlg будет обрабатывать ряд сообщений. Объявления обработчиков сообщений, созданных при помощи AppWizard, располагаются между комментариями AFX_MSG. После создания проекта в нем объявлены обработчики 4-х сообщений: OnInitDialog, OnSysCommand, OnPaint и OnQueryDragIcon.
Определение класса.
Определение класса CDialogDlg приводится в файле CDialogDlg.cpp:
/////////////////////////////////////////////////////////////////////////////
// CDialogDlg dialog
CDialogDlg::CDialogDlg(CWnd* pParent /*=NULL*/)
: CDialog(CDialogDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CDialogDlg)
m_Edit = 0;
m_Combo = _T("");
m_ScrollBar = 0;
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CDialogDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDialogDlg)
DDX_Control(pDX, IDC_MYSLIDER, m_Slider);
DDX_Control(pDX, IDC_MYICON, m_Icon);
DDX_Text(pDX, IDC_MYEDIT, m_Edit);
DDX_CBString(pDX, IDC_MYCOMBO, m_Combo);
DDX_Scroll(pDX, IDC_MYSCROLLBAR, m_ScrollBar);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDialogDlg, CDialog)
//{{AFX_MSG_MAP(CDialogDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDialogDlg message handlers
BOOL CDialogDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Добавить меню "About..." в системное меню.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
//Установить иконку для диалогового окна
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
return TRUE; // вернуть TRUE, если вы не установили //фокус на контрольном элементе
}
void CDialogDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
//Если вы добавили минимизированную кнопку в диалог, то //нужен код, приводимый ниже
void CDialogDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context для рисования
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Отцентрировать иконку
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Нарисовать иконку
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// Эта функция вызывается, если пользователь переносит //минимизированное окно
HCURSOR CDialogDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
Конструктор класса.
Класс CDialogDlg наследуется от базового класса CDialog, определенного в библиотеке классов MFC. Конструктор класса имеет один необязательный параметр pParent, используемый для передачи индекса главного окна приложения. Роль главного окна выполняет сама диалоговая панель, поэтому параметр pParent не используется.
Конструктор класса CDialogDlg вызывает конструктор базового класса CDialog. При этом ему передаются идентификатор диалоговой панели и идентификатор главного окна приложения.
В теле конструктора расположен блок AFX_DATA_INIT. В него ClassWizard будет добавлять код инициализации элементов данных класса CMainDlg.
Конструктор также инициализирует m_hIcon, записывая в него идентификатор пиктограммы IDR_MAINFRAME:
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
Метод AfxGetAp возвращает указатель на объект главного класса приложения (в данном случае - указатель на объект theApp).
Метод DoDataExchange.
Даже, если диалоговая панель имеет только кнопки и не имеет связанных с ними переменных, метод DoDataExchange будет переопределен. Если к диалоговой панели добавить новые органы управления и связать их средствами ClassWizard с элементами данных класса CDialogDlg, то в блоке AFX_DATA_MAP будут размещены вызовы функций DDX и DDV, необходимые для выполнения обмена данными и проверки.
Таблица сообщений.
Таблица сообщений класса CDialogDlg содержит три макрокоманды, которые выполняют обработку сообщений WM_SYSCOMMAND, WM_PAINT и WM_QUERYDRAGICON. Они расположены в блоке AFX_MSG_MAP, поэтому для управления ими используется ClassWizard.
Метод OnInitDialog.
При отображении диалоговой панели при помощи функций DoModal, Create или CreateIndirect, функции диалоговой панели передается сообщение WM_INITDIALOG. Непосредственного доступа к функции диалога нет. Ее реализация содержится в классе CDialog.
В ответ на сообщение WM_INITDIALOG вызывается метод OnInitDialog, объявленный как виртуальный метод класса CDialog. Этот метод вызывается непосредственно перед выводом панели на экран.
Таблица сообщений класса CDialogDlg не содержит макрокоманд для обработки сообщения WM_INITDIALOG. Метод OnInitDialog вызывается непосредственно MFC. Чтобы реализовать собственную обработку сообщения WM_INITDIALOG, нужно просто переопределить метод OnInitDialog. Для этого не надо использовать ClassWizard, так как для главной диалоговой панели он добавляется автоматически. В методе реализуется отрисовка системного меню и иконки в заголовке диалоговой панели.
Метод OnInitDialog возвращает значение TRUE. Это означает, что фокус ввода будет установлен на первый орган управления диалоговой панели. Первый орган диалоговой панели можно выбрать в редакторе диалоговой панели.
Если во время инициализации диалоговой панели метод OnInitDialog устанавливает фокус ввода другому органу управления, метод должен вернуть значение FALSE.
Метод OnSysCommand.
Если при создании шаблонного приложения указать возможность отображения краткой справочной информации, то при этом средство AppWizard подготовит фрагмент кода, добавляющий соответствующую строку в системное меню, а также метод-обработчик OnSysCommand сообщений от системного меню.
Этот метод имеет два параметра - идентификатор строки системного меню, которую выбрал пользователь, и параметр, содержащий координаты мыши, если выбор сделан мышью.
Для обработки выбора стандартных пунктов меню переопределенный метод вызывается метод-обработчик базового класса (для обработки сообщений по умолчанию), а для добавленных пунктов выполняется специфическая обработка.
Метод OnPaint.
Диалоговая панель в отличие от обычного окна не содержит встроенных средств отображения пиктограммы приложения. Приложение должно само заботиться об отображении пиктограммы - для этого переопределяется метод OnPaint. В этом методе либо вызывается метод OnPaint базового класса, либо приложение само отображает пиктограмму, если оно в данный момент минимизировано.