blob: 775535a759e0cc4c0340ee37435cb22dbda072b2 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Steve Anton10542f22019-01-11 09:11:00 -080011#include "rtc_base/win32_window.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020012
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "rtc_base/checks.h"
14#include "rtc_base/logging.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000015
16namespace rtc {
17
18///////////////////////////////////////////////////////////////////////////////
19// Win32Window
20///////////////////////////////////////////////////////////////////////////////
21
Tim Halouna043b2b2019-10-15 11:24:30 -070022static const wchar_t kWindowBaseClassName[] = L"RtcWindowBaseClass";
deadbeef37f5ecf2017-02-27 14:06:41 -080023HINSTANCE Win32Window::instance_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000024ATOM Win32Window::window_class_ = 0;
25
deadbeef37f5ecf2017-02-27 14:06:41 -080026Win32Window::Win32Window() : wnd_(nullptr) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000027
Tim Halouna043b2b2019-10-15 11:24:30 -070028Win32Window::~Win32Window() { RTC_DCHECK(nullptr == wnd_); }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000029
Tim Halouna043b2b2019-10-15 11:24:30 -070030bool Win32Window::Create(HWND parent, const wchar_t* title, DWORD style,
31 DWORD exstyle, int x, int y, int cx, int cy) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000032 if (wnd_) {
33 // Window already exists.
34 return false;
35 }
36
37 if (!window_class_) {
Mirko Bonadei673f7e52019-03-25 09:01:02 +010038 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_)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010042 RTC_LOG_GLE(LS_ERROR) << "GetModuleHandleEx failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000043 return false;
44 }
45
Tim Halouna043b2b2019-10-15 11:24:30 -070046 // Register or reregister the class as necessary. window_class_ == nullptr
47 // is not an infallible indicator that the class is unregistered.
Mirko Bonadei673f7e52019-03-25 09:01:02 +010048 WNDCLASSEXW wcex;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000049 memset(&wcex, 0, sizeof(wcex));
50 wcex.cbSize = sizeof(wcex);
Tim Halouna043b2b2019-10-15 11:24:30 -070051 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);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000058 wcex.hInstance = instance_;
59 wcex.lpfnWndProc = &Win32Window::WndProc;
60 wcex.lpszClassName = kWindowBaseClassName;
Mirko Bonadei673f7e52019-03-25 09:01:02 +010061 window_class_ = ::RegisterClassExW(&wcex);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000062 if (!window_class_) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010063 RTC_LOG_GLE(LS_ERROR) << "RegisterClassEx failed";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000064 return false;
65 }
66 }
Mirko Bonadei673f7e52019-03-25 09:01:02 +010067 wnd_ = ::CreateWindowExW(exstyle, kWindowBaseClassName, title, style, x, y,
68 cx, cy, parent, nullptr, instance_, this);
deadbeef37f5ecf2017-02-27 14:06:41 -080069 return (nullptr != wnd_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000070}
71
72void Win32Window::Destroy() {
nissec16fa5e2017-02-07 07:18:43 -080073 const bool success = ::DestroyWindow(wnd_);
74 RTC_DCHECK(success);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000075}
76
77void Win32Window::Shutdown() {
78 if (window_class_) {
Tim Halouna043b2b2019-10-15 11:24:30 -070079 if (!::UnregisterClass(MAKEINTATOM(window_class_), instance_)) {
80 RTC_LOG_GLE(LS_ERROR) << "UnregisterClass failed.";
81 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000082 window_class_ = 0;
83 }
84}
85
Tim Halouna043b2b2019-10-15 11:24:30 -070086bool Win32Window::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000087 LRESULT& result) {
88 switch (uMsg) {
Yves Gerey665174f2018-06-19 15:03:05 +020089 case WM_CLOSE:
90 if (!OnClose()) {
91 result = 0;
92 return true;
93 }
94 break;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000095 }
96 return false;
97}
98
Tim Halouna043b2b2019-10-15 11:24:30 -070099bool Win32Window::OnClose() { return true; }
Steve Anton9de3aac2017-10-24 10:08:26 -0700100
101void Win32Window::OnNcDestroy() {
102 // Do nothing. }
103}
104
Tim Halouna043b2b2019-10-15 11:24:30 -0700105LRESULT Win32Window::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam,
Steve Anton9de3aac2017-10-24 10:08:26 -0700106 LPARAM lParam) {
107 Win32Window* that =
108 reinterpret_cast<Win32Window*>(::GetWindowLongPtr(hwnd, GWLP_USERDATA));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000109 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)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100121 RTC_LOG(LS_INFO) << "Child window: " << static_cast<void*>(child);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000122 }
123 }
124 if (WM_NCDESTROY == uMsg) {
125 ::SetWindowLongPtr(hwnd, GWLP_USERDATA, NULL);
deadbeef37f5ecf2017-02-27 14:06:41 -0800126 that->wnd_ = nullptr;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000127 that->OnNcDestroy();
128 }
129 if (handled) {
130 return result;
131 }
132 }
133 return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
134}
135
136} // namespace rtc