Windows API Tutorials

Здесь есть возможность читать онлайн «Windows API Tutorials» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Windows API Tutorials: краткое содержание, описание и аннотация

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

Windows API Tutorials — читать онлайн бесплатно полную книгу (весь текст) целиком

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

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

Интервал:

Закладка:

Сделать

virtual ~DlgController () {}

// In case derived class overrides

virtual void OnInitDialog (HWND hwnd) = 0;

virtual bool OnCommand (HWND hwnd, int ctrlID, int notifyCode) = 0;

virtual bool OnNotify (HWND hwnd, int idCtrl, NMHDR *hdr) = 0;

};

The central reusable piece of software is the ModalDialogclass. It does all the work in its constructor by calling the DialogBoxParamWindows API. The parameter that we are passing to the dialog box (actually, to its dialog procedure) is the pointer to the controller factory. The dialog procedure is defined as a static method (no this pointer — the dialog procedure is callable from Windows, so it has no access to the this pointer).

class ModalDialog{

public:

ModalDialog (HINSTANCE hInst, HWND hwnd, int dlgResource, CtrlFactory *ctrlFactory) {

_result = DialogBoxParam(hInst, MAKEINTRESOURCE (dlgResource), hwnd, (DLGPROC) ModalDialogProc, (LPARAM) ctrlFactory);

}

bool IsOk () const { return (_result == -1)? false: _result != 0; }

static BOOL CALLBACK ModalDialogProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

private:

int _result;

};

Finally, the dialog procedure, common to all types of dialogs, is implemented to respond to three kinds of messages: WM_INITDIALOG, WM_COMMAND and WM_NOTIFY. Actually, all it does is to direct these messages to the controller object. It obtains the pointer to the polymorphic controller object for the first time by calling the MakeControllermethod of the factory.

Notice that, from that point on, we let Windows keep track of the pointer to the controller. We store it as GWL_USERDATA — a special long that is associated with every window, in particular with our dialog, and accessible through its window handle.

template

inline T GetWinLong(HWND hwnd, int which = GWL_USERDATA) {

return reinterpret_cast (:: GetWindowLong(hwnd, which));

}

template

inline void SetWinLong(HWND hwnd, T value, int which = GWL_USERDATA) {

:: SetWindowLong(hwnd, which, reinterpret_cast (value));

}

We have to be careful, though. First of all, we need to deallocate the controller after we are done. We do it when processing WM_DESTROY.

Second of all, Windows has this unfortunate habit of sending WM_COMMAND and WM_NOTIFY messages before WM_INITDIALOG and after WM_DESTROY. What can I say — if I were the manager of the poor schmuck who's responsible for this "feature" things would have been different. As it is, we have to protect ourselves by testing if ctrlis non-zero before calling OnCommandand OnNotify.

BOOL CALLBACK ModalDialog::ModalDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {

DlgController * ctrl = GetWinLong (hwnd);

switch (message) {

case WM_INITDIALOG:

{

CtrlFactory *ctrlFactory = reinterpret_cast (lParam);

ctrl = ctrlFactory->MakeController (hwnd);

SetWinLong (hwnd, ctrl);

ctrl->OnInitDialog (hwnd);

}

return TRUE;

case WM_COMMAND:

if (ctrl && ctrl->OnCommand (hwnd, LOWORD(wParam), HIWORD (wParam))) {

return TRUE;

}

break;

case WM_NOTIFY:

if (ctrl && ctrl->OnNotify (hwnd, wParam, (NMHDR *)lParam)) return TRUE;

break;

case WM_DESTROY:

delete ctrl;

SetWinLong (hwnd, 0);

break;

}

return FALSE;

}

Here's the beauty of polymorphism in action. The factory object is created by the client using a template class. This object is passed to the constructor of ModalDialog. ModalDialogpasses it to the dialog procedure as a void pointer (that's because it has to go through Windows). Dialog procedure gets it inside the WM_INITDIALOG message as LPARAM. After going through the digestive tract of Windows it has to be restored to its original shape by casting it back to the pointer to CtrlFactory— the base class of all controller factories.

When we call its virtual method MakeController, we are calling the method overridden in the class template ControllerFactory. It creates a new object of the client-defined class ActualCtrl. But again, it returns this object to us disguised as a generic pointer to DlgController. So whenever we call any of the virtual methods of ctrl, we are executing client overrides defined in the class ActualCtrl. That's your polymorphism at its best: you write code using generic pointers, but when the code is executed, it is called with very specific pointers. When you call methods through these pointers, you are executing specific methods provided by the client of your code.

This is what happens to the object factory whose actual class is ControllerFactory

Passed to ModalDialog constructor as void *
Passed by Windows to ModalDialogProcedure as LPARAM
Cast in ModalDialogProcedure to CtrlFactory *

And this is what happens to the object data whose actual class is EditorData.

Passed to factory constructor as void *
Cast in the MakeController method of ControllerFactory to EditorData *
Passed to the constructor of EditCtrl as EditorData *

The object of class EditCtrlcreated in the MakeControllermethod of ControllerFactoryis returned from it as DlgController *and stored in this form as a static data member of ModalDialog.

If you have problems following my explanation, don't despair. The object oriented techniques I just described are difficult, but essential. They are called design patterns. I highly recommend reading the book by Gamma, Helm, Johnson and Vlissides called Design Patterns, Elements of Reusable Object-Oriented Software or look at the Patterns Home Page. it describes a lot of creative ways of using polymorphism, inheritance and templates to make software more reusable.

Now it's time to talk some more about the Canvas.

Canvas, or Windows Device Context

To paint, draw or printin a window you need a device context, DC for short. A DC is a resource that you borrow from Windows and you're supposed to return it immediately after you're done. That's where the Canvas object comes. The Canvas' constructor obtains the DC and the Canvas' destructor releases it. It is important that you create Canvas objects as automatic (stack) variables. That will guarantee that their destructor is always called when the program exits the local scope where they are defined (this class is an example of a more general Resource Management methodology). The typical use of the Canvas object is as follows (as you've already seen in the Generic program):

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Windows API Tutorials»

Представляем Вашему вниманию похожие книги на «Windows API Tutorials» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Windows API Tutorials»

Обсуждение, отзывы о книге «Windows API Tutorials» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x