1.3. chromium源代码分析

在_tWinMain中有这样两条语句:

1 MainWindowDelegate delegate;
2 view::Window::CreateNativeWindow(NULL, gfx::Rect(), &delegate);

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

按图索骥,从基类开始看起。

基类:MessageMapInterface

 1 class MessageMapInterface
 2 {
 3 public:
 4     virtual BOOL ProcessWindowMessage(HWND window,
 5         UINT message,
 6         WPARAM w_param,
 7         LPARAM l_param,
 8         LRESULT& result,
 9         DWORD msg_mad_id = 0) = 0;
10 };

只有一个函数,主要用于处理消息,在消息响应函数(WndProc)中会调用此函数进行消息处理。

接下来就是WindowImpl类,WindowImpl中最重要的就是WndProc,这个函数就是我们注册在WNDCLASS里的消息响应函数。

1 class WindowImpl : public MessageMapInterface
2 {
3 private:
4     static LRESULT CALLBACK WndProc(HWND window, UINT message,
5         WPARAM w_param, LPARAM l_param);
6 };

WndProc会使用基类指针来调用基类的ProcessWindowMessage函数,消息的控制权就交给ProcessWindowMessage,多态行为。

再下来是widget基类,我们可以理解为是HWND的属性 行为的封装。

 1 class Widget
 2 {
 3 public:
 4     // Delegate类在这被加入
 5     virtual WidgetDelegate* GetWidgetDelegate() = 0;
 6     virtual void SetWidgetDelegate(WidgetDelegate* delegate) = 0;
 7 
 8 
 9     // 这都是HWND的常规属性与行为
10     virtual void GetBounds(gfx::Rect* out, bool including_frame) const = 0;
11     virtual void SetBounds(const gfx::Rect& bounds) = 0;
12     virtual void MoveAbove(Widget* widget) = 0;
13     virtual void SetShape(HRGN shape) = 0;
14     virtual void Close() = 0;
15     virtual void CloseNow() = 0;
16     virtual void Show() = 0;
17     virtual void Hide() = 0;
18     virtual void SetAlwaysOnTop(bool on_top) = 0;
19     virtual bool IsVisible() const = 0;
20     virtual bool IsActive() const = 0;
21 
22     // tooltip、主题管理、焦点管理
23     virtual TooltipManager* GetTooltipManager() = 0;
24     virtual bool GetAccelerator(int cmd_id, MenuAccelerator* accelerator) = 0;
25     virtual ThemeProvider* GetThemeProvider() const = 0;
26     virtual ThemeProvider* GetDefaultThemeProvider() const = 0;
27     virtual FocusManager* GetFocusManager() = 0;
28 
29     // 更新界面函数
30     virtual void PaintNow(const gfx::Rect& update_rect) = 0;
31 };

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

 1     class WidgetWin : public gfx::WindowImpl,
 2         public Widget,
 3         public MessageLoopForUI::Observer,
 4         public FocusTraversable
 5     {
 6     public:
 7         VIEW_BEGIN_MSG_MAP_EX(WidgetWin)
 8             // Range handlers must go first!
 9             VIEW_MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseRange)
10             VIEW_MESSAGE_RANGE_HANDLER_EX(WM_NCMOUSEMOVE, WM_NCMOUSEMOVE, OnMouseRange)
11 
12             // Reflected message handler
13             VIEW_MESSAGE_HANDLER_EX(kReflectedMessage, OnReflectedMessage)
14 
15             // CustomFrameWindow hacks
16             VIEW_MESSAGE_HANDLER_EX(WM_NCUAHDRAWCAPTION, OnNCUAHDrawCaption)
17             VIEW_MESSAGE_HANDLER_EX(WM_NCUAHDRAWFRAME, OnNCUAHDrawFrame)
18 
19             // Vista and newer
20             VIEW_MESSAGE_HANDLER_EX(WM_DWMCOMPOSITIONCHANGED, OnDwmCompositionChanged)
21 
22             // Non-atlcrack.h handlers
23             VIEW_MESSAGE_HANDLER_EX(WM_GETOBJECT, OnGetObject)
24             VIEW_MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnNCMouseLeave)
25             VIEW_MESSAGE_HANDLER_EX(WM_MOUSELEAVE, OnMouseLeave)
26             VIEW_MESSAGE_HANDLER_EX(WM_MOUSEWHEEL, OnMouseWheel)
27 
28             // This list is in _ALPHABETICAL_ order! OR I WILL HURT YOU.
29             VIEW_MSG_WM_ACTIVATE(OnActivate)
30             VIEW_MSG_WM_ACTIVATEAPP(OnActivateApp)
31             VIEW_MSG_WM_APPCOMMAND(OnAppCommand)
32             VIEW_MSG_WM_CANCELMODE(OnCancelMode)
33             VIEW_MSG_WM_CAPTURECHANGED(OnCaptureChanged)
34             VIEW_MSG_WM_CLOSE(OnClose)
35             VIEW_MSG_WM_COMMAND(OnCommand)
36             VIEW_MSG_WM_CREATE(OnCreate)
37             VIEW_MSG_WM_DESTROY(OnDestroy)
38 
39             VIEW_MSG_WM_SETTEXT(OnSetText)
40             VIEW_MSG_WM_SETTINGCHANGE(OnSettingChange)
41             VIEW_MSG_WM_SIZE(OnSize)
42             VIEW_MSG_WM_SYSCOMMAND(OnSysCommand)
43             VIEW_MSG_WM_THEMECHANGED(OnThemeChanged)
44             VIEW_MSG_WM_VSCROLL(OnVScroll)
45             VIEW_MSG_WM_WINDOWPOSCHANGING(OnWindowPosChanging)
46             VIEW_MSG_WM_WINDOWPOSCHANGED(OnWindowPosChanged)
47         VIEW_END_MSG_MAP()
48 
49         // Overridden from Widget:
50         // Overridden from MessageLoop::Observer:
51         // Overridden from FocusTraversable:
52 
53 
54     protected:
55         virtual void OnActivate(UINT action, BOOL minimized, HWND window);
56         virtual void OnActivateApp(BOOL active, DWORD thread_id);
57         virtual LRESULT OnAppCommand(HWND window, short app_command, WORD device,
58             int keystate);
59         virtual void OnCancelMode();
60         virtual void OnCaptureChanged(HWND hwnd);
61         virtual void OnClose();
62         virtual void OnCommand(UINT notification_code, int command_id, HWND window);
63         virtual LRESULT OnCreate(CREATESTRUCT* create_struct);
64         // WARNING: If you override this be sure and invoke super, otherwise we'll
65         // leak a few things.
66         virtual void OnDestroy();
67 
68         virtual LRESULT OnSetText(const wchar_t* text);
69         virtual void OnSettingChange(UINT flags, const wchar_t* section);
70         virtual void OnSize(UINT param, const gfx::Size& size);
71         virtual void OnSysCommand(UINT notification_code, gfx::Point click);
72         virtual void OnThemeChanged();
73         virtual void OnVScroll(int scroll_type, short position, HWND scrollbar);
74         virtual void OnWindowPosChanging(WINDOWPOS* window_pos);
75         virtual void OnWindowPosChanged(WINDOWPOS* window_pos);
76 
77         // deletes this window as it is destroyed, override to provide different
78         // behavior.
79         virtual void OnFinalMessage(HWND window);
80     };

从继承关系widget_win不仅实现了widget,而且还加入了消息处理相关,焦点处理等的内容。
从类的接口看,确实是在处理消息了,这就是windows消息的默认处理类了。消息是怎么传送到这里的呢?
回到祖父类,ProcessWindowMessage消息处理总函数, 再看看WidgetWin中的VIEW_BEGIN_MSG_MAP_EX宏,

 1 #define VIEW_BEGIN_MSG_MAP_EX(theClass) 
 2 public: 
 3     BOOL m_bMsgHandled; 
 4     /* "handled" management for cracked handlers */ 
 5     BOOL IsMsgHandled() const 
 6     { 
 7         return m_bMsgHandled; 
 8     } 
 9     void SetMsgHandled(BOOL bHandled) 
10     { 
11         m_bMsgHandled = bHandled; 
12     } 
13     BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) 
14     { 
15         BOOL bOldMsgHandled = m_bMsgHandled; 
16         BOOL bRet = _ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, dwMsgMapID); 
17         m_bMsgHandled = bOldMsgHandled; 
18         return bRet; 
19     } 
20     BOOL _ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID) 
21     { 
22         BOOL bHandled = TRUE; 
23         hWnd; 
24         uMsg; 
25         wParam; 
26         lParam; 
27         lResult; 
28         bHandled; 
29         switch(dwMsgMapID) 
30         { 
31         case 0:

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

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

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

 1     class Window
 2     {
 3     public:
 4         virtual ~Window() {}
 5 
 6         // Creates an instance of an object implementing this interface.
 7         // TODO(beng): create a version of this function that takes a HWND, for
 8         //             constrained windows.
 9         static Window* CreateNativeWindow(HWND parent,
10             const gfx::Rect& bounds, WindowDelegate* window_delegate);
11 };
 1     // static
 2     Window* Window::CreateNativeWindow(HWND parent,
 3         const gfx::Rect& bounds,
 4         WindowDelegate* window_delegate)
 5     {
 6         WindowWin* window = new WindowWin(window_delegate);   // 1. new出子类
 7         window->GetNonClientView()->SetFrameView(window->CreateFrameViewForWindow());
 8         window->Init(parent, bounds); //2.调用WindowWin::Init
 9         return window;
10     }
 1     void WindowImpl::Init(HWND parent, const Rect& bounds)
 2     {
 3         if(window_style_ == 0)
 4         {
 5             window_style_ = parent ? kWindowDefaultChildStyle : kWindowDefaultStyle;
 6         }
 7 
 8         if(parent && !::IsWindow(parent))
 9         {
10             NOTREACHED() << "invalid parent window specified.";
11             parent = NULL;
12         }
13 
14         int x, y, width, height;
15         if(bounds.IsEmpty())
16         {
17             x = y = width = height = CW_USEDEFAULT;
18         }
19         else
20         {
21             x = bounds.x();
22             y = bounds.y();
23             width = bounds.width();
24             height = bounds.height();
25         }
26 
27         hwnd_ = CreateWindowEx(window_ex_style_, GetWindowClassName().c_str(), NULL,
28             window_style_, x, y, width, height, parent, NULL, NULL, this);                  // 这里就是创建窗口了
29         DCHECK(hwnd_);
30     }

到此,窗口的创建,消息的分发都已经展现出来了,剩下的就是消息循环了。

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

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

原文地址:https://www.cnblogs.com/mfcjck/p/chromium003.html