• 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。

  • 相关阅读:
    BrowserSync,自动刷新,解放F5,去掉更新提示
    js获取手机系统语言
    块元素,行内元素,行内块区别
    原生js判断某个元素是否有指定的class名的几种方法
    如何实现调用console.log(‘good’.repeat(3))时输出goodgoodgood?
    数组如何去除重复数据,只保留一条
    Sentinel笔记-Flow流控规则
    sentinel笔记 NodeSelectorSlot,ClusterBuilderSlot
    Sentinel笔记--Slotchain
    Sentinel笔记-核心类
  • 原文地址:https://www.cnblogs.com/mfcjck/p/chromium003.html
Copyright © 2020-2023  润新知