聊天服务器——ATL

WTL

WTL有一定的封装基础、不是mfc的框架、能够自己定制一些窗口行为

WTL对模板编程有一点要求,对UI要求高。

WTL更快的基本原理

template<class T>
class Edoyun
{
public:
    void show()
    {
        T* p = static_cast<T*>(this);
        p->Name();
    }
protected:
    void Name() {std::cout << "Edoyun" << std::endl;}      //这不是虚函数
}
​
class Sub : public Edoyun<Sub>
{
public:
    void name() {std::cout<<"Sub"<<std::endl;}
}
​
class Sub2 : public Edoyun<Sub2>
{
};
​
int main()
{
    Sub sub;
    Sub2 sub2;
    sub.show();
    sub2.show();
}

WTL就采用了上述模板的方式来编写每个class的name,而不是采用虚函数,因为采用虚函数,子类

继承父类会导致编译占用很多空间。

ATL GUI类

ATL:Activity Template Library

ATL 窗口类

因为是基于.COM的,所以后面需要写一个CComModule,并进行初始化。

写一个窗口类MyWindow,基于模板CWindowImpl

MyWindow里DECLARE_WND_CLASS是注册名字

BEGIN_MSG_MAP和END_MSG_MAP之间注册消息和命令

#include <iostream>
#include <atlbase.h>
#include <atlwin.h>
#include "resource.h"
​
//定义窗口风格
typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, WS_EX_APPWINDOW> EdoyunTraits;
class MyWindow : public CWindowImpl<MyWindow, CWindow, EdoyunTraits>
{
public:
    //注册信息
    DECLARE_WND_CLASS(_T("Edoyun Window Class"));
    BEGIN_MSG_MAP(MyWindow)
        MESSAGE_HANDLER(WM_CLOSE, OnClose)
        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
        COMMAND_ID_HANDLER(IDR_ABOUT, OnAbout) //命令菜单
    END_MSG_MAP()
    LRESULT OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        DestroyWindow();
        return 0;
    }
    LRESULT OnDestroy(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        PostQuitMessage(0);
        return 0;
    }
    LRESULT OnAbout(UINT wNotifyCode, WORD wParam, HWND lParam, BOOL& bHandled)
    {
        OutputDebugString(_T("OnAbout called!\r\n"));
        return 0;
    }
};
​
//因为基于.COM,需要初始化
CComModule gModule;
int main()
{
    HRESULT  hRes = gModule.Init(NULL, GetModuleHandle(NULL));
    if (hRes != 0)
    {
        std::cout << hRes << std::endl;
    }
    MyWindow win;
    HWND hwnd = win.Create(NULL, CWindow::rcDefault, _T("edoyun atl window!"));
    if (hwnd == NULL)
    {
        std::cout << "create window failed\r\n";
    }
    win.ShowWindow(SW_SHOW);
    win.UpdateWindow();
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    gModule.Term();
    return 0;
}

ATL对话框

IDD_ABOUT是添加的对话框dlg

ID_HELLO_WORLD是menu里的

#include <iostream>
#include <atlbase.h>
#include <atlwin.h>
#include "resource.h"
​
//定义窗口风格
typedef CWinTraits<WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, WS_EX_APPWINDOW> EdoyunTraits;
​
//因为基于.COM,需要初始化
CComModule gModule;
class CAboutDlg : public CDialogImpl<CAboutDlg, CWindow>
{
public:
    enum {IDD = IDD_ABOUT};
    BEGIN_MSG_MAP(CAboutDlg)
        MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
        MESSAGE_HANDLER(WM_CLOSE, OnClose)
        COMMAND_ID_HANDLER(IDOK, OnOK)
    END_MSG_MAP()
​
    LRESULT OnInitDialog(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        CenterWindow();
        return true;
    }
​
    LRESULT OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        EndDialog(IDOK);
        return true;
    }
    
    LRESULT OnOK(WORD wNotifyCode, WORD wID, HWND hWndCtrl, BOOL& bHandled)
    {
        EndDialog(wID);
        return 0;
    }
};
​
​
class MyWindow : public CWindowImpl<MyWindow, CWindow, EdoyunTraits>
{
public:
    //注册信息
    DECLARE_WND_CLASS(_T("Edoyun Window Class"));
    BEGIN_MSG_MAP(MyWindow)
        MESSAGE_HANDLER(WM_CREATE, OnCreate)
        MESSAGE_HANDLER(WM_CLOSE, OnClose)
        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
        COMMAND_ID_HANDLER(ID_HELLO_WORLD, OnAbout) //命令菜单
    END_MSG_MAP()
    LRESULT OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        HMENU hMenu = LoadMenu(gModule.GetResourceInstance(), MAKEINTRESOURCE(IDR_ABOUT));
​
        SetMenu(hMenu);
        return 0;
    }
​
    LRESULT OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        DestroyWindow();
        return 0;
    }
    LRESULT OnDestroy(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        PostQuitMessage(0);
        return 0;
    }
    LRESULT OnAbout(UINT wNotifyCode, WORD wParam, HWND lParam, BOOL& bHandled)
    {
        OutputDebugString(_T("OnAbout called!\r\n"));
        CAboutDlg dlg;
        dlg.DoModal();
        return 0;
    }
};
​
int main()
{
    HRESULT hRes = gModule.Init(NULL, GetModuleHandle(NULL));
    if (hRes != 0)
    {
        std::cout << hRes << std::endl;
    }
    MyWindow win;
    HWND hwnd = win.Create(NULL, CWindow::rcDefault, _T("edoyun atl window!"));
    if (hwnd == NULL)
    {
        std::cout << "create window failed\r\n";
    }
    win.ShowWindow(SW_SHOW);
    win.UpdateWindow();
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    gModule.Term();
    return 0;
}

装修模式

先定义装修模块,这个装修模块有两个参数,第一个是class,第二个是COLORREF。class就表示要装修的类,填入这个类,这个类就会去把背景颜色换成COLORREF。第二个COLORREF是我们要换的颜色,也可以是图片。这个模块可以用到dlg上,也可以用到其他的按钮上、控件上。

template<class T, COLORREF clr>
class CPaintBackground :public CMessageMap
{
public:
    CPaintBackground()
    {
        m_br = CreateSolidBrush(clr);
    }
    ~CPaintBackground()
    {
        if (m_br != NULL)
        {
            DeleteObject(m_br);
            m_br = NULL;
        }
    }
    BEGIN_MSG_MAP(CPaintBackground)
        MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBkgnd)
    END_MSG_MAP()
    LRESULT OnEraseBkgnd(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        T* p = static_cast<T*>(this);
        HDC dc = (HDC)wParam;
        RECT rc;
        p->GetClientRect(&rc);
        FillRect(dc, &rc, m_br);
        return true;
    }
private:
    HBRUSH m_br;
};

采用多继承的方式,让我们要装修的类去继承这个模块,同时把COLORREF填好。

typedef CPaintBackground<MyWindow, BACKGNDCLR> CPaintBkgndBase;

使用CHAIN_MSG_MAP,填入CPaintBkgndBase。将消息导入到其他类里面去处理,就是将消息导入到CPaintBkgndBase中去处理

#define BACKGNDCLR RGB(0, 255, 0)
class MyWindow : public CWindowImpl<MyWindow, CWindow, EdoyunTraits>,
      public CPaintBackground<MyWindow, BACKGNDCLR>
{
public:
    //注册信息
    DECLARE_WND_CLASS(_T("Edoyun Window Class"));
    typedef CPaintBackground<MyWindow, BACKGNDCLR> CPaintBkgndBase;
    BEGIN_MSG_MAP(MyWindow)
        MESSAGE_HANDLER(WM_CREATE, OnCreate)
        MESSAGE_HANDLER(WM_CLOSE, OnClose)
        MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
        COMMAND_ID_HANDLER(ID_HELLO_WORLD, OnAbout) //命令菜单
        CHAIN_MSG_MAP(CPaintBkgndBase)              //将消息导入到其他类里面去处理
    END_MSG_MAP()
    LRESULT OnCreate(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        HMENU hMenu = LoadMenu(gModule.GetResourceInstance(), MAKEINTRESOURCE(IDR_ABOUT));
​
        SetMenu(hMenu);
        return 0;
    }
​
    LRESULT OnClose(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        DestroyWindow();
        return 0;
    }
    LRESULT OnDestroy(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
    {
        PostQuitMessage(0);
        return 0;
    }
    LRESULT OnAbout(UINT wNotifyCode, WORD wParam, HWND lParam, BOOL& bHandled)
    {
        OutputDebugString(_T("OnAbout called!\r\n"));
        CAboutDlg dlg;
        dlg.DoModal();
        return 0;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值