1.3. chromium源代码分析 - chromiumframe - 窗口类

view之window系列
在_tWinMain中有这样两条语句:
MainWindowDelegate delegate;
view::Window::CreateNativeWindow(NULL, gfx::Rect(), &delegate);


从这我们开始window相关的探索,目的就是要找到WNDCLASS与创建窗口的地方。
window顾名思义就是windows上的窗口。google对windows的原始窗口做的封装。window相关的类主要有Window / WindowDelegate / WindowWin / Widget / WidgetDelegate / WidgetWin.
我的理解,window为有标题栏和边框的窗口,widget则为无标题栏的HWND。window其实是在widget上加了标题栏和边框相关的处理。google已经在window和widget中加入默认消息处理,以及默认的窗口属性。我们自己的程序当然要有自己窗口属性和窗口行为,这时就需要继承相应的delegate类。
我在学习代码的时候画了一下类图,辅助自己理解。



根据类图,从基类开始看起。
class MessageMapInterface
{
public:
	virtual BOOL ProcessWindowMessage(HWND window,
		UINT message,
		WPARAM w_param,
		LPARAM l_param,
		LRESULT& result,
		DWORD msg_mad_id = 0) = 0;
};
只有一个函数,主要用于处理消息,在消息响应函数(WndProc)中会调用此函数进行消息处理。

接下来就是WindowImpl类,WindowImpl中最重要的就是WndProc,这个函数就是我们注册在WNDCLASS里的消息响应函数。
class WindowImpl : public MessageMapInterface
{
private:
	static LRESULT CALLBACK WndProc(HWND window, UINT message,
		WPARAM w_param, LPARAM l_param);
};
WndProc会使用基类指针来调用基类的ProcessWindowMessage函数,消息的控制权就交给ProcessWindowMessage,多态多态行为。

再下来是widget基类,我们可以理解为是HWND的属性 行为的封装。
class Widget
{
public:
	// Delegate类在这被加入
	virtual WidgetDelegate* GetWidgetDelegate() = 0;
	virtual void SetWidgetDelegate(WidgetDelegate* delegate) = 0;


	// 这都是HWND的常规属性与行为
	virtual void GetBounds(gfx::Rect* out, bool including_frame) const = 0;
	virtual void SetBounds(const gfx::Rect& bounds) = 0;
	virtual void MoveAbove(Widget* widget) = 0;
	virtual void SetShape(HRGN shape) = 0;
	virtual void Close() = 0;
	virtual void CloseNow() = 0;
	virtual void Show() = 0;
	virtual void Hide() = 0;
	virtual void SetAlwaysOnTop(bool on_top) = 0;
	virtual bool IsVisible() const = 0;
	virtual bool IsActive() const = 0;

	// tooltip、主题管理、焦点管理
	virtual TooltipManager* GetTooltipManager() = 0;
	virtual bool GetAccelerator(int cmd_id, MenuAccelerator* accelerator) = 0;
	virtual ThemeProvider* GetThemeProvider() const = 0;
	virtual ThemeProvider* GetDefaultThemeProvider() const = 0;
	virtual FocusManager* GetFocusManager() = 0;

	// 更新界面函数
	virtual void PaintNow(const gfx::Rect& update_rect) = 0;
};

widget的实现类为WidgetWin,平台相关Win,就是windows平台的widget子类。

    class WidgetWin : public gfx::WindowImpl,
        public Widget,
        public MessageLoopForUI::Observer,
        public FocusTraversable
    {
    public:
        VIEW_BEGIN_MSG_MAP_EX(WidgetWin)
            // Range handlers must go first!
            VIEW_MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
            VIEW_MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE, WM_NCMOUSEMOVE, OnMouseRange)

            // Reflected message handler
            VIEW_MESSAGE_HANDLER_EX(kReflectedMessage, OnReflectedMessage)

            // CustomFrameWindow hacks
            VIEW_MESSAGE_HANDLER_EX(WM_NCUAHDRAWCAPTION, OnNCUAHDrawCaption)
            VIEW_MESSAGE_HANDLER_EX(WM_NCUAHDRAWFRAME, OnNCUAHDrawFrame)

            // Vista and newer
            VIEW_MESSAGE_HANDLER_EX(WM_DWMCOMPOSITIONCHANGED, OnDwmCompositionChanged)

            // Non-atlcrack.h handlers
            VIEW_MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
            VIEW_MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnNCMouseLeave)
            VIEW_MESSAGE_HANDLER_EX(WM_MOUSELEAVE, OnMouseLeave)
            VIEW_MESSAGE_HANDLER_EX(WM_MOUSEWHEEL, OnMouseWheel)

            // This list is in _ALPHABETICAL_ order! OR I WILL HURT YOU.
            VIEW_MSG_WM_ACTIVATE(OnActivate)
            VIEW_MSG_WM_ACTIVATEAPP(OnActivateApp)
            VIEW_MSG_WM_APPCOMMAND(OnAppCommand)
            VIEW_MSG_WM_CANCELMODE(OnCancelMode)
            VIEW_MSG_WM_CAPTURECHANGED(OnCaptureChanged)
            VIEW_MSG_WM_CLOSE(OnClose)
            VIEW_MSG_WM_COMMAND(OnCommand)
            VIEW_MSG_WM_CREATE(OnCreate)
            VIEW_MSG_WM_DESTROY(OnDestroy)

            VIEW_MSG_WM_SETTEXT(OnSetText)
            VIEW_MSG_WM_SETTINGCHANGE(OnSettingChange)
            VIEW_MSG_WM_SIZE(OnSize)
            VIEW_MSG_WM_SYSCOMMAND(OnSysCommand)
            VIEW_MSG_WM_THEMECHANGED(OnThemeChanged)
            VIEW_MSG_WM_VSCROLL(OnVScroll)
            VIEW_MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
            VIEW_MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)
        VIEW_END_MSG_MAP()

        // Overridden from Widget:
        // Overridden from MessageLoop::Observer:
        // Overridden from FocusTraversable:


    protected:
        virtual void OnActivate(UINT action, BOOL minimized, HWND window);
        virtual void OnActivateApp(BOOL active, DWORD thread_id);
        virtual LRESULT OnAppCommand(HWND window, short app_command, WORD device,
            int keystate);
        virtual void OnCancelMode();
        virtual void OnCaptureChanged(HWND hwnd);
        virtual void OnClose();
        virtual void OnCommand(UINT notification_code, int command_id, HWND window);
        virtual LRESULT OnCreate(CREATESTRUCT* create_struct);
        // WARNING: If you override this be sure and invoke super, otherwise we'll
        // leak a few things.
        virtual void OnDestroy();

        virtual LRESULT OnSetText(const wchar_t* text);
        virtual void OnSettingChange(UINT flags, const wchar_t* section);
        virtual void OnSize(UINT param, const gfx::Size& size);
        virtual void OnSysCommand(UINT notification_code, gfx::Point click);
        virtual void OnThemeChanged();
        virtual void OnVScroll(int scroll_type, short position, HWND scrollbar);
        virtual void OnWindowPosChanging(WINDOWPOS* window_pos);
        virtual void OnWindowPosChanged(WINDOWPOS* window_pos);

        // deletes this window as it is destroyed, override to provide different
        // behavior.
        virtual void OnFinalMessage(HWND window);
    };
从继承关系widget_win不仅实现了widget,而且还加入了消息处理相关,焦点处理等的内容。
从类的接口看,确实是在处理消息了,这就是windows消息的默认处理类了。消息是怎么传送到这里的呢?
回到祖父类,ProcessWindowMessage消息处理总函数, 再看看WidgetWin中的VIEW_BEGIN_MSG_MAP_EX宏,
#define VIEW_BEGIN_MSG_MAP_EX(theClass) \
public: \
	BOOL m_bMsgHandled; \
	/* "handled" management for cracked handlers */ \
	BOOL IsMsgHandled() const \
	{ \
		return m_bMsgHandled; \
	} \
	void SetMsgHandled(BOOL bHandled) \
	{ \
		m_bMsgHandled = bHandled; \
	} \
	BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
	{ \
		BOOL bOldMsgHandled = m_bMsgHandled; \
		BOOL bRet = _ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID); \
		m_bMsgHandled = bOldMsgHandled; \
		return bRet; \
	} \
	BOOL _ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID) \
	{ \
		BOOL bHandled = TRUE; \
		hWnd; \
		uMsg; \
		wParam; \
		lParam; \
		lResult; \
		bHandled; \
		switch(dwMsgMapID) \
		{ \
		case 0:

已经看到ProcessWindowMessage的身影了,ProcessWindowMessage是虚函数重载,WndProc实际会把消息传送到这里,ProcessWindowMessage会调用_ProcessWindowMessage接下来就是switch case处理分发了,这应该是借鉴了WTL框架,

回看1.1的win32典型程序的消息处理函数,都是switch case 来分发消息,这里只是用宏伪装,用类进行了包装而已。

window类封装了title name,最大/小化支持等等一些窗口的属性和行为,这些都是纯虚的函数,最重要的就是在main.cpp被调用的static函数。
    class Window
    {
    public:
        virtual ~Window() {}

        // Creates an instance of an object implementing this interface.
        // TODO(beng): create a version of this function that takes a HWND, for
        //             constrained windows.
        static Window* CreateNativeWindow(HWND parent,
            const gfx::Rect& bounds, WindowDelegate* window_delegate);
};
    // static
    Window* Window::CreateNativeWindow(HWND parent,
        const gfx::Rect& bounds,
        WindowDelegate* window_delegate)
    {
        WindowWin* window = new WindowWin(window_delegate);   // 1. new出子类
        window->GetNonClientView()->SetFrameView(window->CreateFrameViewForWindow());
        window->Init(parent, bounds); //2.调用WindowWin::Init
        return window;
    }

// 3. 之后会掉到这

    void WindowImpl::Init(HWND parent, const Rect& bounds)
    {
        if(window_style_ == 0)
        {
            window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle;
        }

        if(parent && !::IsWindow(parent))
        {
            NOTREACHED() << "invalid parent window specified.";
            parent = NULL;
        }

        int x, y, width, height;
        if(bounds.IsEmpty())
        {
            x = y = width = height = CW_USEDEFAULT;
        }
        else
        {
            x = bounds.x();
            y = bounds.y();
            width = bounds.width();
            height = bounds.height();
        }

        hwnd_ = CreateWindowEx(window_ex_style_, GetWindowClassName().c_str(), NULL,
            window_style_, x, y, width, height, parent, NULL, NULL, this);                  // 这里就是创建窗口了
        DCHECK(hwnd_);
    }
到此,窗口的创建,消息的分发都已经展现出来了,剩下的就是消息循环了。

WindowWin继承自widget,重载了NC消息的处理。又继承了window类,实现窗口的行为及属性。

WindowDelegate则是window的委派,实质上应该是Window子类WindowWin的委派。我们要修改窗口的属性行为以及如何构建窗口也只需要继承WindowDelegate,重载windowDelegate的行为函数即可。main.cpp中就是这么干的,MainWindowDelegate就是继承WindowDelegate。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值