Home | History | Annotate | Download | only in internal
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_FRAME_INFOBARS_INTERNAL_SUBCLASSING_WINDOW_WITH_DELEGATE_H_
      6 #define CHROME_FRAME_INFOBARS_INTERNAL_SUBCLASSING_WINDOW_WITH_DELEGATE_H_
      7 
      8 #include <atlbase.h>
      9 #include <atlcrack.h>
     10 #include <atlwin.h>
     11 
     12 #include "base/basictypes.h"
     13 #include "base/logging.h"
     14 #include "base/memory/scoped_ptr.h"
     15 #include "chrome_frame/pin_module.h"
     16 
     17 // Implements behavior common to HostWindowManager and DisplacedWindowManager.
     18 template<typename T> class SubclassingWindowWithDelegate
     19     : public CWindowImpl<T> {
     20  public:
     21   // Allows clients to modify the dimensions of the displaced window.
     22   // Through its destructor, allows clients to know when the subclassed window
     23   // is destroyed.
     24   class Delegate {
     25    public:
     26     // The delegate will be deleted when the subclassed window is destroyed.
     27     virtual ~Delegate() {}
     28 
     29     // Receives the natural dimensions of the displaced window. Upon return,
     30     // rect should contain the adjusted dimensions (i.e., possibly reduced to
     31     // accomodate an infobar).
     32     virtual void AdjustDisplacedWindowDimensions(RECT* rect) = 0;
     33   };  // class Delegate
     34 
     35   SubclassingWindowWithDelegate() {}
     36 
     37   // Returns true if the window is successfully subclassed, in which case this
     38   // instance will take responsibility for its own destruction when the window
     39   // is destroyed. If this method returns false, the caller should delete the
     40   // instance immediately.
     41   //
     42   // Takes ownership of delegate in either case, deleting it when the window
     43   // is destroyed (or immediately, in case of failure).
     44   bool Initialize(HWND hwnd, Delegate* delegate) {
     45     DCHECK(delegate != NULL);
     46     DCHECK(delegate_ == NULL);
     47     scoped_ptr<Delegate> new_delegate(delegate);
     48 
     49     if (!::IsWindow(hwnd) || !SubclassWindow(hwnd)) {
     50       PLOG(ERROR) << "Failed to subclass an HWND";
     51       return false;
     52     }
     53 
     54     // Ensure we won't be unloaded while our window proc is attached to the tab
     55     // window.
     56     chrome_frame::PinModule();
     57 
     58     delegate_.swap(new_delegate);
     59 
     60     return true;
     61   }
     62 
     63   // Returns the delegate associated with the specified window, if any.
     64   static Delegate* GetDelegateForHwnd(HWND hwnd) {
     65     return reinterpret_cast<Delegate*>(
     66         ::SendMessage(hwnd, RegisterGetDelegateMessage(), NULL, NULL));
     67   }
     68 
     69   BEGIN_MSG_MAP_EX(SubclassingWindowWithDelegate)
     70     MESSAGE_HANDLER(RegisterGetDelegateMessage(), OnGetDelegate)
     71     MSG_WM_DESTROY(OnDestroy)
     72   END_MSG_MAP()
     73 
     74   // This instance is now free to be deleted.
     75   virtual void OnFinalMessage(HWND hwnd) {
     76     delete this;
     77   }
     78 
     79  protected:
     80   scoped_ptr<Delegate>& delegate() { return delegate_; }
     81 
     82  private:
     83   // Registers a unique ID for our custom event.
     84   static UINT RegisterGetDelegateMessage() {
     85     static UINT message_id(
     86         RegisterWindowMessage(L"SubclassingWindowWithDelegate::OnGetDelegate"));
     87     return message_id;
     88   }
     89 
     90   // The subclassed window has been destroyed. Delete the delegate. We will
     91   // delete ourselves in OnFinalMessage.
     92   void OnDestroy() {
     93     delegate_.reset();
     94   }
     95 
     96   LRESULT OnGetDelegate(UINT message,
     97                         WPARAM wparam,
     98                         LPARAM lparam,
     99                         BOOL& handled) {
    100     return reinterpret_cast<LRESULT>(delegate_.get());
    101   }
    102 
    103   scoped_ptr<Delegate> delegate_;
    104   DISALLOW_COPY_AND_ASSIGN(SubclassingWindowWithDelegate);
    105 };  // class SubclassingWindowWithDelegate
    106 
    107 #endif  // CHROME_FRAME_INFOBARS_INTERNAL_SUBCLASSING_WINDOW_WITH_DELEGATE_H_
    108