Notepad ++ source code reading-window encapsulation and inheritance

Source: Internet
Author: User
Introduction

I recently read the source code of notepad ++ and learned how to develop Win32 native APIs.

This article uses the source code of notepad ++ 1.0 as an example to explain how to encapsulate windows Windows, realize object-oriented development, and how to reuse code through window inheritance, the dynamic binding feature of C ++ is used to realize polymorphism. In addition, it also describes how to encapsulate the message processing program in the window encapsulation process, which is the key to implementing object-oriented. Let me explain in detail.

Implementation window class

It is the inheritance level of the window class of notepad ++ 1.0:

In notepad ++ 1.0, all window elements: edit window, Tab window, toolbar, Status Bar, and dialog box have a common parent class: window class, which is a virtual base class, the detroy function cannot be instantiated. The detroy function is a pure virtual function. It declares the variables required for each window: Window handle _ hself, parent window handle _ hparent, and instance handle _ hinst of the entire program. This class implements some basic window operations, some of which are virtual functions. Let's take a look at its source code:

# Include <windows. h> class window // virtual base class {public: window (): _ hself (null), _ hparent (null), _ hinst (null ){}; // constructor, called by the constructor In the subclass, which assigns values to the three variables, virtual ~ Window () {}; virtual void Init (hinstance hinst, hwnd parent) // implement your own version in the virtual function and subclass, such as the registration window, create window, etc. {_ hinst = hinst; _ hparent = parent;} virtual void destroy () = 0; // virtual void display (bool toshow = true) const {// display window: showwindow (_ hself, toshow? Sw_show: sw_hide) ;}; virtual void resizeTo (rect & rc) // shoshould never be const !!! {// Here, it is particularly emphasized that RC cannot be a const, because sometimes it should be used to return the customer zone above it, so that the window size on the customer can be reset. For example, the tab window // resizeTo returns the customer area of the tab and the rectangular area returned by the editing window // resets the size of movewindow (_ hself, RC. left, RC. top, RC. right, RC. bottom, true); redraw () ;}; virtual void redraw () const {// force refresh window: invalidaterect (_ hself, null, true );:: updatewindow (_ hself) ;}; virtual void getclientrect (rect & rc) const {// get the user rectangle: getclientrect (_ hself, & rc );}; virtual int getwidth () const {rect RC;: getclientrect (_ hself, & rc); Return (RC. right-RC. left) ;}; virtual int getheight () const {rect RC;: getclientrect (_ hself, & rc); Return (RC. bottom-RC. top) ;}; virtual bool isvisible () const {return bool (: iswindowvisible (_ hself) ;}; hwnd gethself () const {// get your own window handle if (! _ Hself) {: MessageBox (null, "_ hself = NULL", "class window", mb_ OK); throw int (999);} return _ hself ;}; void getfocus () const {: setfocus (_ hself) ;}; hinstance gethinst () const {If (! _ Hinst) {: MessageBox (null, "_ hinst = NULL", "class window", mb_ OK); throw int (1999);} return _ hinst ;}; protected: hinstance _ hinst; // program instance handle hwnd _ hparent; // parent window handle hwnd _ hself; // its own window handle };

This is the base class of the window. With this base class, we can generate our own window to implement specific functions. Below are several typical windows.

Encapsulation of the dialog box

The notepad ++ dialog box inherits staticdialog, and staticdialog inherits the window class above. The Declaration of the base class of the dialog box is as follows:

class StaticDialog : public Window{public :    StaticDialog() : Window() {};    ~StaticDialog(){};    virtual void create(int dialogID);    virtual bool isCreated() const {        return reinterpret_cast<bool>(_hSelf);    };    //virtual do        void destroy() {        ::DestroyWindow(_hSelf);    };protected :    static BOOL CALLBACK dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);    virtual BOOL CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) = 0;};
The key to the encapsulation of the dialog box is the implementation of the create function. The resource ID of the input function dialog box is created. The function implementation is as follows:

void StaticDialog::create(int dialogID) {    _hSelf = ::CreateDialogParam(_hInst, MAKEINTRESOURCE(dialogID), _hParent,  (DLGPROC)dlgProc, (LPARAM)this);        if (!_hSelf)    {        systemMessage("StaticDialog");        throw int(666);    }    display();}

A function is basically an API call created in the dialog box. It is used to input the resource and Message Processing Program of the dialog box: dlgproc. This function is a static function. Therefore, you can call this function and pass this pointer to it, the pointer can be obtained in the wm_initdialog message.

Let's take a look at the implementation of dlgproc:

BOOL CALLBACK StaticDialog::dlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {    switch (message)     {        case WM_INITDIALOG :        {            StaticDialog *pStaticDlg = (StaticDialog *)(lParam);            pStaticDlg->_hSelf = hwnd;            ::SetWindowLong(hwnd, GWL_USERDATA, (long)lParam);            pStaticDlg->run_dlgProc(message, wParam, lParam);            return TRUE;        }        default :        {            StaticDialog *pStaticDlg = reinterpret_cast<StaticDialog *>(::GetWindowLong(hwnd, GWL_USERDATA));            if (!pStaticDlg)                return FALSE;            return pStaticDlg->run_dlgProc(message, wParam, lParam);        }    }}

In the wm_initdialog message, convert lparam to the staticdialog pointer. In this way, you can obtain the window handle _ hself (base class member), put the pointer in userdata, and retrieve it from other messages, pointer and call the member function: run_dlgproc. This function is a pure virtual function. The inherited dialog box subclass can process your own specific messages. This is the encapsulation of the message processing program. At last, we will explain the encapsulation of Message Processing in the main window, which is similar to the method used in the dialog box.

Tab window

Tired of writing, to be continued

Main Window Type

Tired of writing, to be continued

Encapsulate the Message Processing Program (encapsulating wndproc)

The Code of notepad ++ 1.0 explains how to encapsulate the window message processing program.

Tired of writing, to be continued

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.