Oluseyi Sonaiya - Creating a Win32 Window Wrapper Class

Здесь есть возможность читать онлайн «Oluseyi Sonaiya - Creating a Win32 Window Wrapper Class» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Creating a Win32 Window Wrapper Class: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Creating a Win32 Window Wrapper Class»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Creating a Win32 Window Wrapper Class — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Creating a Win32 Window Wrapper Class», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

// m_MsgHandlers is a tyMessageMap instance

tyMessageIterator it = m_MsgHandlers.find(message);

if (it == m_MsgHandlers.end()) return NULL;

return it;

}

// Window::OnClose is a static method called in response to WM_CLOSE

long Window::OnClose(Window &wnd, HWND hwnd, long param0, long param1) {

DestroyWindow(hwnd);

return 0;

}

// Window::OnDestroy is a static method called in response to WM_DESTROY

long Window::OnDestroy(Window &wnd, HWND hwnd, long param0, long param1) {

PostQuitMessage(0);

return 0;

}

// Final message handler version

LRESULT CALLBACK Window::MsgRouter(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {

Window *wnd = 0;

if (message == WM_NCCREATE) {

// retrieve Window instance from window creation data and associate

wnd = reinterpret_cast((LPCREATESTRUCT)lparam)->lpCreateParams;

::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast(wnd));

// save window handle

wnd->SetHWND(hwnd);

} else

// retrieve associated Window instance

wnd = reinterpret_cast(::GetWindowLong(hwnd, GWL_USERDATA));

if (wnd) {

tyMessageIterator it;

it = wnd->GetMessageHandler(message);

if (it != NULL) return (it->second)((*wnd), hwnd, wparam, lparam);

}

return DefWindowProc(hwnd, message, wparam, lparam);

}

Okay, so the message router takes care of object association, checks to see if there is an appropriate message handler and calls the default window procedure if there isn't. Fine. Now how do you add these message handlers? Behold the Window::RegisterMessageHandler method!

tyMessageHandler Window::RegisterMessageHandler(long message, tyMessageHandler handler) {

tyMessageHandler m = NULL;

tyMessageIterator it = m_MsgHandlers.find(message);

if (it != m_MsgHandlers.end()) m = it->second;

m_MsgHandlers.insert(std::pair(message, handler));

return m;

}

Alright, so it wasn't so dramatic. The RegisterMessageHandler method inserts a message handler into the message map and returns the previous message handler, if there was one. That about wraps it up for message handling (I say about because I'll revisit one of the methods described above later). Now let's turn to integrating the Window with the application message pump.

The Window Class and the Application Message Pump

A typical Windows message pump looks something like this:

MSG msg;

while(GetMessage(&msg, hwnd, 0, 0)) {

TranslateMessage(&msg);

DispatchMessage(&msg);

// other procedures

}

Microsoft actually advises against this form of message loop because GetMessage has a tri-state return value and the above may cause an attempt at execution even when there was an error.

We do it anyway.

This article is getting long and I'm getting tired, so I'll dump the code and then break it down.

// Window::OnDestroy, revisited

long Window::OnDestroy(Window &wnd, HWND hwnd, long param0, long param1) {

PostQuitMessage(0);

wnd->SetExit(true);

return 0;

}

// Window::HandleMessage ties everything together

bool Window::HandleMessages() {

static MSG msg;

if (!m_hwnd) throw std::runtime_error(std::string("Window not yet created"));

if ((m_UsePeekMessage) ? ::PeekMessage(&msg, m_hwnd, 0, 0, PM_REMOVE) : ::GetMessage(&msg, m_hwnd, 0, 0)) {

::TranslateMessage(&msg);

::DispatchMessage(&msg);

} else {

if (IsExit()) {

SetExitCode((long)msg.lParam);

return false;

}

if (m_UseWaitMessage) WaitMessage();

}

return true;

}

There's a bunch of functions not introduced here. Obviously, the constructor and methods like Create and ShowWindow ; I leave this as an exercise for the inexperienced reader and a chore for the expert. There are also the boolean variables m_UseWaitMessage , m_UsePeekMessage and m_Exit ; the exit code for the Window (to pass to the application if the Window is the main window); and the static method to register the windowclass. The code above is fairly self-explanatory. As is evident, I use exceptions to avoid having to pass and compare return values for application-terminating errors. I also use the m_UsePeekMessage and m_UseWaitMessage as discriminants between using GetMessage and PeekMessage , and whether or not to use WaitMessage respectively.

That's it. And here's a simple example of my implementation in use:

Window *g_wnd;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /* hPrevInstance */,

LPSTR lpCmdLine, int nShowCmd) {

try {

g_wnd = new Window(hInstance);

g_wnd->Create(NULL, WS_OVERLAPPEDWINDOW|WS_VISIBLE);

if (!g_wnd) throw std::runtime_error(std::string("Initialization Failed: Window::Create"));

g_wnd->UsePeekMessage();

g_wnd->UseWaitMessage(false);

g_wnd->ShowWindow(nShowCmd);

while(true) {

if (!g_wnd->HandleMessages()) break;

}

} catch(std::runtime_error &e) {

::MessageBox(NULL, e.what(), "Runtime Error", MB_OK|MB_ICONERROR|MB_DEFBUTTON1|MB_TASKMODAL|MB_TOPMOST);

return –1;

} catch(std::logic_error &e) {

::MessageBox(NULL, e.what(), "Logic Error", MB_OK|MB_ICONERROR|MB_DEFBUTTON1|MB_TASKMODAL|MB_TOPMOST);

return –1;

} catch(…) {

::MessageBox(NULL, "Unhandled Exception", "Unknown Error", MB_OK|MB_ICONERROR|MB_DEFBUTTON1|MB_TASKMODAL|MB_TOPMOST);

return –1;

}

return g_wnd->ExitCode();

}

Hopefully this article has been useful as a solution, but more importantly has inspired you to even better implementations which I hope you share with us all.

Cheers!

© 1999-2002 Gamedev.net. All rights reserved.
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Creating a Win32 Window Wrapper Class»

Представляем Вашему вниманию похожие книги на «Creating a Win32 Window Wrapper Class» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Creating a Win32 Window Wrapper Class»

Обсуждение, отзывы о книге «Creating a Win32 Window Wrapper Class» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x