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 "rtc_base/win32_window.h"
12
13 #include "rtc_base/checks.h"
14 #include "rtc_base/logging.h"
15
16 namespace rtc {
17
18 ///////////////////////////////////////////////////////////////////////////////
19 // Win32Window
20 ///////////////////////////////////////////////////////////////////////////////
21
22 static const wchar_t kWindowBaseClassName[] = L"RtcWindowBaseClass";
23 HINSTANCE Win32Window::instance_ = nullptr;
24 ATOM Win32Window::window_class_ = 0;
25
Win32Window()26 Win32Window::Win32Window() : wnd_(nullptr) {}
27
~Win32Window()28 Win32Window::~Win32Window() { RTC_DCHECK(nullptr == wnd_); }
29
Create(HWND parent,const wchar_t * title,DWORD style,DWORD exstyle,int x,int y,int cx,int cy)30 bool Win32Window::Create(HWND parent, const wchar_t* title, DWORD style,
31 DWORD exstyle, int x, int y, int cx, int cy) {
32 if (wnd_) {
33 // Window already exists.
34 return false;
35 }
36
37 if (!window_class_) {
38 if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
39 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
40 reinterpret_cast<LPCWSTR>(&Win32Window::WndProc),
41 &instance_)) {
42 RTC_LOG_GLE(LS_ERROR) << "GetModuleHandleEx failed";
43 return false;
44 }
45
46 // Register or reregister the class as necessary. window_class_ == nullptr
47 // is not an infallible indicator that the class is unregistered.
48 WNDCLASSEXW wcex;
49 memset(&wcex, 0, sizeof(wcex));
50 wcex.cbSize = sizeof(wcex);
51 if (::GetClassInfoExW(instance_, kWindowBaseClassName, &wcex) &&
52 !::UnregisterClassW(kWindowBaseClassName, instance_)) {
53 RTC_LOG_GLE(LS_ERROR) << "UnregisterClass failed.";
54 }
55
56 memset(&wcex, 0, sizeof(wcex));
57 wcex.cbSize = sizeof(wcex);
58 wcex.hInstance = instance_;
59 wcex.lpfnWndProc = &Win32Window::WndProc;
60 wcex.lpszClassName = kWindowBaseClassName;
61 window_class_ = ::RegisterClassExW(&wcex);
62 if (!window_class_) {
63 RTC_LOG_GLE(LS_ERROR) << "RegisterClassEx failed";
64 return false;
65 }
66 }
67 wnd_ = ::CreateWindowExW(exstyle, kWindowBaseClassName, title, style, x, y,
68 cx, cy, parent, nullptr, instance_, this);
69 return (nullptr != wnd_);
70 }
71
Destroy()72 void Win32Window::Destroy() {
73 const bool success = ::DestroyWindow(wnd_);
74 RTC_DCHECK(success);
75 }
76
Shutdown()77 void Win32Window::Shutdown() {
78 if (window_class_) {
79 if (!::UnregisterClass(MAKEINTATOM(window_class_), instance_)) {
80 RTC_LOG_GLE(LS_ERROR) << "UnregisterClass failed.";
81 }
82 window_class_ = 0;
83 }
84 }
85
OnMessage(UINT uMsg,WPARAM wParam,LPARAM lParam,LRESULT & result)86 bool Win32Window::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
87 LRESULT& result) {
88 switch (uMsg) {
89 case WM_CLOSE:
90 if (!OnClose()) {
91 result = 0;
92 return true;
93 }
94 break;
95 }
96 return false;
97 }
98
OnClose()99 bool Win32Window::OnClose() { return true; }
100
OnNcDestroy()101 void Win32Window::OnNcDestroy() {
102 // Do nothing. }
103 }
104
WndProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)105 LRESULT Win32Window::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
106 LPARAM lParam) {
107 Win32Window* that =
108 reinterpret_cast<Win32Window*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
109 if (!that && (WM_CREATE == uMsg)) {
110 CREATESTRUCT* cs = reinterpret_cast<CREATESTRUCT*>(lParam);
111 that = static_cast<Win32Window*>(cs->lpCreateParams);
112 that->wnd_ = hwnd;
113 ::SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that));
114 }
115 if (that) {
116 LRESULT result;
117 bool handled = that->OnMessage(uMsg, wParam, lParam, result);
118 if (WM_DESTROY == uMsg) {
119 for (HWND child = ::GetWindow(hwnd, GW_CHILD); child;
120 child = ::GetWindow(child, GW_HWNDNEXT)) {
121 RTC_LOG(LS_INFO) << "Child window: " << static_cast<void*>(child);
122 }
123 }
124 if (WM_NCDESTROY == uMsg) {
125 ::SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL);
126 that->wnd_ = nullptr;
127 that->OnNcDestroy();
128 }
129 if (handled) {
130 return result;
131 }
132 }
133 return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
134 }
135
136 } // namespace rtc
137