1/*
2 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/base/common.h"
12#include "webrtc/base/logging.h"
13#include "webrtc/base/win32window.h"
14
15namespace rtc {
16
17///////////////////////////////////////////////////////////////////////////////
18// Win32Window
19///////////////////////////////////////////////////////////////////////////////
20
21static const wchar_t kWindowBaseClassName[] = L"WindowBaseClass";
22HINSTANCE Win32Window::instance_ = NULL;
23ATOM Win32Window::window_class_ = 0;
24
25Win32Window::Win32Window() : wnd_(NULL) {
26}
27
28Win32Window::~Win32Window() {
29  ASSERT(NULL == wnd_);
30}
31
32bool Win32Window::Create(HWND parent, const wchar_t* title, DWORD style,
33                         DWORD exstyle, int x, int y, int cx, int cy) {
34  if (wnd_) {
35    // Window already exists.
36    return false;
37  }
38
39  if (!window_class_) {
40    if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
41                           GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
42                           reinterpret_cast<LPCWSTR>(&Win32Window::WndProc),
43                           &instance_)) {
44      LOG_GLE(LS_ERROR) << "GetModuleHandleEx failed";
45      return false;
46    }
47
48    // Class not registered, register it.
49    WNDCLASSEX wcex;
50    memset(&wcex, 0, sizeof(wcex));
51    wcex.cbSize = sizeof(wcex);
52    wcex.hInstance = instance_;
53    wcex.lpfnWndProc = &Win32Window::WndProc;
54    wcex.lpszClassName = kWindowBaseClassName;
55    window_class_ = ::RegisterClassEx(&wcex);
56    if (!window_class_) {
57      LOG_GLE(LS_ERROR) << "RegisterClassEx failed";
58      return false;
59    }
60  }
61  wnd_ = ::CreateWindowEx(exstyle, kWindowBaseClassName, title, style,
62                          x, y, cx, cy, parent, NULL, instance_, this);
63  return (NULL != wnd_);
64}
65
66void Win32Window::Destroy() {
67  VERIFY(::DestroyWindow(wnd_) != FALSE);
68}
69
70void Win32Window::Shutdown() {
71  if (window_class_) {
72    ::UnregisterClass(MAKEINTATOM(window_class_), instance_);
73    window_class_ = 0;
74  }
75}
76
77bool Win32Window::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
78                            LRESULT& result) {
79  switch (uMsg) {
80  case WM_CLOSE:
81    if (!OnClose()) {
82      result = 0;
83      return true;
84    }
85    break;
86  }
87  return false;
88}
89
90LRESULT Win32Window::WndProc(HWND hwnd, UINT uMsg,
91                             WPARAM wParam, LPARAM lParam) {
92  Win32Window* that = reinterpret_cast<Win32Window*>(
93      ::GetWindowLongPtr(hwnd, GWLP_USERDATA));
94  if (!that && (WM_CREATE == uMsg)) {
95    CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lParam);
96    that = static_cast<Win32Window*>(cs->lpCreateParams);
97    that->wnd_ = hwnd;
98    ::SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that));
99  }
100  if (that) {
101    LRESULT result;
102    bool handled = that->OnMessage(uMsg, wParam, lParam, result);
103    if (WM_DESTROY == uMsg) {
104      for (HWND child = ::GetWindow(hwnd, GW_CHILD); child;
105           child = ::GetWindow(child, GW_HWNDNEXT)) {
106        LOG(LS_INFO) << "Child window: " << static_cast<void*>(child);
107      }
108    }
109    if (WM_NCDESTROY == uMsg) {
110      ::SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL);
111      that->wnd_ = NULL;
112      that->OnNcDestroy();
113    }
114    if (handled) {
115      return result;
116    }
117  }
118  return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
119}
120
121}  // namespace rtc
122