Мы выберем более традиционный для COM способ, когда проверяется HRESULT и вызывается метод ShowError, который предстоит создать.
LRESULT CGraphProp::OnInitDialog (UINT msg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
CComQIPtr<IOpenGL> p(m_ppUnk[0]); // Кроим умный указатель по шаблону IOpenGL
//=== Пытаемся связаться с классом COpenGL и выяснить значение переменной m_FillMode, В случае неудачи сообщаем об ошибке
DWORD mode;
if FAILED (p->GetFillMode(&mode))
{
ShowError();
return 0;
}
HWND hwnd = GetDlgItem (IDC_FILLMODE); // Работа с combobox по правилам API
//=== Наполняем список строками текста
SendMessage (hwnd, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)"Points");
SendMessage (hwnd, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)"Lines");
SendMessage (hwnd, CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)"Fill");
//=== Выбираем текущую позицию списка в соответствии со значением, полученным из COpenGL
WPARAM w = mode == GL_POINT ? 0 : mode == GL_LINE ? 1 : 2;
SendMessage(hwnd, CB_SETCURSEL, w, 0);
if FAILED (p->GetLightParams(m_Pos)) // Повторяем сеанс связи, выясняя позиции ползунков
{
ShowError();
return 0;
}
// Мы не надеемся на упорядоченность идентификаторов элементов и поэтому заводим массив отображений
UINT IDs[] =
{
IDC_XPOS, IDC_YPOS, IDC_ZPOS, IDC_AMBIENT, IDC_DIFFUSE, IDC_SPECULAR,
IDC_AMBMAT, IDC_DIFFMAT, IDC_SPECMAT, IDC_SHINE, IDC_EMISSION
};
for (int i=0; i<sizeof(IDs)/sizeof(IDs[0]); i++)// Установка позиций регуляторов
{
hwnd = GetDlgItem (IDs[i]); // Получаем описатель окна
UINT nID;
int num = GetSliderNum (hwnd, nID); // Узнаем идентификатор элемента
SendMessage (hwnd, TBM_SETPOS, TRUE, (LPARAM)m_Pos[i]); // Выставляем позицию
char s[8]; // Приводим в соответствие текстовый ярлык
sprintf (s,"%d",m_Pos[i]);
SetDlgItemText (nID, s);
}
if FAILED (p->GetQuad(&m_bQuad)) // Выясняем состояние режима изображения полигонов
{
ShowError();
return 0;
}
SetDlgItemText (IDC_QUADS,m_bQuad ? "Quads" : "Strips"); // Устанавливаем текст
return TRUE;
}
Обратите внимание на вызов SendMessage при управлении combo-box. Этот способ характерен для Win32 API. В процессе обработки сообщения нам понадобились вспомогательные функции GetSliderNum и ShowError. Первая функция уже участвовала в проекте на основе MFC, поэтому мы лишь напомним, что она позволяет по известному Windows-описателю окна элемента управления получить его порядковый номер в массиве позиций регуляторов. Кроме этого, функция позволяет получить идентификатор элемента nID, который нужен для управления им (например, при вызове SetDlgItemText).
int CGraphProp::GetSliderNum (HWND hwnd, UINT& nID)
{
switch (::GetDlgCtrlID(hwnd)) // Получаем ID по известному описателю окна
{
case IDC_XPOS: nID = IDC_XPOS_TEXT; return 0;
case IDC_YPOS: nID = IDC_YPOS_TEXT; return 1;
case IDC_ZPOS: nID = IDC_ZPOS_TEXT; return 2;
case IDC_AMBIENT: nID = IDC_AMB_TEXT; return 3;
case IDC_DIFFUSE: nID = IDC_DIFFUSE_TEXT; return 4;
case IDC_SPECULAR: nID = IDC_SPECULAR_TEXT; return 5;
case IDC_AMBMAT: nID = IDC_AMBMAT_TEXT; return 6;
case IDC_DIFFMAT: nID = IDC_DIFFMAT_TEXT; return 7;
case IDC_SPECMAT: nID = IDC_SPECMAT_TEXT; return 8;
case IDC_SHINE: nID = IDC_SHINE_TEXT; return 9;
case IDC_EMISSION: nID = IDC_EMISSION_TEXT; return 10;
}
return 0;
}
Функция ShowError демонстрирует, как в условиях COM можно обработать исключительную ситуацию. Если мы хотим выявить причину ошибки, спрятанную в HRESULT, то следует воспользоваться методом GetDescription интерфейса IErrorInfo. Сначала мы получаем указатель на него с помощью объекта класса CComPtr. Этот класс, так же как и CComQIPtr, автоматизирует работу с методами главного интерфейса IUnknown, за исключением метода QueryInterface.
void CGraphProp::ShowError()
{
USES_CONVERSION;
CComPtr<IErrorInfo> p; // Создаем инерфейсный указатель
GetErrorInfo (0, &p); // Выясняем причину отказа
CComBSTR s; // Класс для работы с Unicode-строками
p->GetDescription (&s);
//=== Преобразуем тип строкового объекта для вывода в окно
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.