Управление
с помощью объекта класса-оболочки
- Поставьте фокус на окно
внедренного элемента IDC_OPENGL в форме диалога и вызовите контекстное меню.
- В меню выберите команду
Variable, которая запустит мастер Add Member Variable Wizard.
- Установите флажок Control
Variable и задайте в полях диалоговой страницы мастера следующие значения:
Access — public, Variable type — COpenGL, Variable name — * m_Ctrl, Control
ID - IDC_OPENGL
- Обратите внимание на
то, что в.поле Control type уже выбран тип элемента OCX, и нажмите кнопку
Finish.
- объявление переменной
COpenGL m_ctrl; в файле заголовков TestGLDlg.h;
- вызов функции DDX_Control(pDX,
IDC_OPENGL, m_ctrl), связывающей элемент управления в окне диалога с переменной
m_ctrl. Этот вызов вы найдете в теле функции CTestGLDlg::DoDataExchange;
#include "opengl.h"
В конец файла Stdafx.h вставьте директивы подключения заголовков библиотеки OpenGL:
#include <gl/gl.h> // Будем пользоваться OpenGL #include <gl/glu.h>
Теперь следует поместить в окно диалога элементы управления. Здесь мы не будем пользоваться страницами свойств элемента, созданными нами в рамках предыдущего проекта. Вместо этого мы покажем, как можно управлять внедренным элементом ActiveX с помощью объекта m_ctrl. Перейдите в окно диалогового редактора и придайте окну диалога IDD_TESTGL_DIALOG.
Идентификаторы для элементов управления можно задать так, как показано в табл. 9.2.
Таблица
9.2. Идентификаторы элементов управления
Элемент |
Идентификатор |
Диалог |
IDD_TESTGL_DIALOG |
Кнопка Data File |
IDCJILENAME |
Кнопка Back Color |
IDC.BKCLR |
Переключатель
Quads |
IDC_QUADS |
Переключатель
Strips |
IDC_STRIPS |
Выпадающий список
Fill Mode |
IDC_FILL |
Ползунок Light
(X) |
IDC_XPOS |
Кнопка Close |
IDOK |
- OnClickedFilename —
нажата кнопка IDC_FILENAME,
- OnCiickedBkcir — нажата
кнопка IDC_BKCLR,
- OnSelchangeFill — изменился
выбор в списке IDC_FILL,
- OnClickedQuads — нажата
кнопка IDC_QUADS,
- OnHScroll — изменилась
позиция ползунка IDC_XPOS,
- OnClickedStrips — нажата
кнопка IDC_STRIPS.
class CTestGLDlg : public CDialog
{
public:
CTestGLDlg(CWnd* p = NULL);
enum { IDD = IDD_TESTGL_DIALOG };
//======= Объект класса-оболочки
COpenGL m_Ctrl;
//======= Запоминаем способ изображения
BOOL m_bQuads;
//======= Реакции на регуляторы в окне диалога
void OnSelchangeFill(void);
void OnClickedFilename(void);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
void OnCiickedBkcir(void);
void OnClickedQuads(void); void OnClickedStrips(void);
protected:
virtual void DoDataExchange(CDataExchange* pDX) ; virtual BOOL OnlnitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM IParam); DECLARE_MESSAGE_MAP()
};
В файл реализации методов класса мы кроме функций обработки сообщений от элементов управления вставили код начальной установки этих элементов. Для этой цели нам опять понадобилась связь с сервером, которую обеспечивает объект m_ctrl класса-оболочки. Характерным моментом является то, что обрабатываем событие WM_HSCROLL, которое поступает окну диалога, вместо того чтобы обработать уведомляющее событие NM_RELEASEDCAPTURE, которое идет от элемента типа Slider Control. Такая тактика позволяет реагировать на управление ползунком клавишами, а не только мышью:
#include "stdafx.h" #include "TestGL.h"
#include "TestGLDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = _FILE_;
#endif
//====== Пустое тело конструктора
CTestGLDlg::CTestGLDlg(CWnd* p) : CDialog(CTestGLDlg::IDD, p){}
void CTestGLDlg::DoDataExchange(CDataExchange* pDX) {
//====== Связывание переменной с элементом
DDX_Control(pDX, IDCJDPENGL, m_Ctrl);
CDialog::DoDataExchange(pDX); }
//====== Здесь мы убрали ON_WM_PAINT и т. д.
BEGIN_MESSAGE_MAP(CTestGLDlg, CDialog) ON_WM_SYSCOMMAND()
// } } AFX_MSG_MAP
ON_CBN_SELCHANGE(IDC_FILL, OnSelchangeFill) ON_BN_CLICKED(IDC_FILENAME, OnClickedFilename) ON_WM_HSCROLL()
ON_BN_CLICKED(IDC_BKCLR, OnClickedBkclr) ON_BN_CLICKED(IDC_QUADS, OnClickedQuads) ON_BN_CLICKED(IDC_STRIPS, OnClickedStrips)
END_MESSAGE_MAP()
//===== CTestGLDlg message handlers
BOOL CTestGLDlg::OnInitDialog() { //====== Добываем адрес меню управления окном
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu)
{
//====== Добавляем команду About
pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING,
IDM_ABOUTBOX,"About..."); }
//====== Загружаем стандартный значок
HICON hMylcon = ::LoadIcon(0,(char*)IDI_WINLOGO); Setlcon(hMylcon, TRUE); // Set big icon Setlcon(hMylcon, FALSE); // Set small icon
CDialog::OnInitDialog();
//====== Начальная установка элементов
CComboBox *pBox = (CComboBox*)GetDlgltem(IDC_FILL); pBox->AddString("Points"); pBox->AddString("Lines"); pBox->AddString("Fill"); pBox->SetCurSel (2);
//==== Выясняем состояние режима изображения полигонов
m_Ctrl.GetQuad(&m_bQuads);
WPARAM w = m_bQuads ? BST_CHECKED : BST_UNCHECKED;
//===== Устанавливаем состояние переключателя GetDlgltem(IDC_QUADS)->SendMessage(BM_SETCHECK, w, 0); w = m_bQuads ? BST_UNCHECKED : BST_CHECKED; GetDlgltem(IDC_STRIPS)->SendMessage(BM_SETCHECK, w, 0);
return TRUE; }
void CTestGLDlg::OnSysCommand(UINT nID, LPARAM iParam) {
if ((nID S OxFFFO) == IDM_ABOUTBOX)
{
CDialog(IDD_ABOUTBOX).DoModal();
}
else
{
CDialog::OnSysCommand(nID, IParam);
} }
//====== Выбор из списка типа Combo-box
void CTestGLDlg::OnSelchangeFill(void) "'* { DWORD sel = ((CComboBox*)GetDlgltem(IDC_FILL))->GetCurSel();
sel = sel==0 ? GL_POINT : sel==l ? GL_LINE
: GL_FILL;
m_Ctrl.SetFillMode(sel); }
//==== Нажатие на кнопку запуска файлового диалога
void CTestGLDlg::OnClickedFilename(void)
{
m_Ctrl.ReadData(); }
//====== Реакция на сдвиг ползунка
void CTestGLDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) {
//====== Выясняем текущую позицию, которая не во
//====== всех случаях отражена в параметре nPos
nPos = ((CSliderCtrl*)GetDlgItem(IDC_XPOS))->GetPos() ;
m_Ctrl.SetLightParam (0, nPos); }
//====== Запускаем стандартный диалог
void CTestGLDlg::OnClickedBkclr(void) {
DWORD clr = m_Ctrl.GetFillColor() ;
CColorDialog dig (clr);
dig.m_cc.Flags |= CC_FULLOPEN;
if (dlg.DoModal()==IDOK)
{
m_Ctrl.SetFillColor(dlg.m_cc.rgbResult);
} }
//====== Запоминаем текущее состояние и
//====== вызываем метод сервера
void CTestGLDlg::OnClickedQuads(void) {
m_Ctrl.SetQuad(m_bQuads = TRUE); }
void CTestGLDlg::OnClickedStrips(void) {
m_Ctrl.SetQuad(m_bQuads = FALSE); } В настоящий момент вы можете запустить приложение, которое должно найти и запустить DLL-сервер ATLGL, генерирующий изображение по умолчанию и демонстрирующий его в окне внедренного элемента типа ActiveX. Сервер должен достаточно быстро реагировать на изменение регулировок органов управления клиентского приложения. Подведем итог. В этом уроке мы научились:
- вносить функциональность
окна OpenGL в окно, управляемое ATL-классом CWindow;
- добавлять с помощью Studio.Net
новые методы в интерфейс, представляемый ко-классом;
- учитывать особенности
обработки сообщений Windows в рамках ATL;
- управлять контекстом
передачи OpenGL, связанным с окном внедренного СОМ-объекта;
- создавать приложение-контейнер на базе MFC и пользоваться услугами класса-оболочки для управления СОМ-объектом.
Назад | Содержание |