1 // Copyright 2013 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.
5 #include "base/win/message_window.h"
7 #include "base/lazy_instance.h"
8 #include "base/logging.h"
9 #include "base/process/memory.h"
10 #include "base/win/wrapped_window_proc.h"
12 const wchar_t kMessageWindowClassName
[] = L
"Chrome_MessageWindow";
17 // Used along with LazyInstance to register a window class for message-only
18 // windows created by MessageWindow.
19 class MessageWindow::WindowClass
{
24 ATOM
atom() { return atom_
; }
25 HINSTANCE
instance() { return instance_
; }
31 DISALLOW_COPY_AND_ASSIGN(WindowClass
);
34 static LazyInstance
<MessageWindow::WindowClass
> g_window_class
=
35 LAZY_INSTANCE_INITIALIZER
;
37 MessageWindow::WindowClass::WindowClass()
39 instance_(base::GetModuleFromAddress(&MessageWindow::WindowProc
)) {
40 WNDCLASSEX window_class
;
41 window_class
.cbSize
= sizeof(window_class
);
42 window_class
.style
= 0;
43 window_class
.lpfnWndProc
= &base::win::WrappedWindowProc
<WindowProc
>;
44 window_class
.cbClsExtra
= 0;
45 window_class
.cbWndExtra
= 0;
46 window_class
.hInstance
= instance_
;
47 window_class
.hIcon
= NULL
;
48 window_class
.hCursor
= NULL
;
49 window_class
.hbrBackground
= NULL
;
50 window_class
.lpszMenuName
= NULL
;
51 window_class
.lpszClassName
= kMessageWindowClassName
;
52 window_class
.hIconSm
= NULL
;
53 atom_
= RegisterClassEx(&window_class
);
55 LOG_GETLASTERROR(ERROR
)
56 << "Failed to register the window class for a message-only window";
60 MessageWindow::WindowClass::~WindowClass() {
62 BOOL result
= UnregisterClass(MAKEINTATOM(atom_
), instance_
);
63 // Hitting this DCHECK usually means that some MessageWindow objects were
64 // leaked. For example not calling
65 // ui::Clipboard::DestroyClipboardForCurrentThread() results in a leaked
71 MessageWindow::MessageWindow()
75 MessageWindow::~MessageWindow() {
76 DCHECK(CalledOnValidThread());
78 if (window_
!= NULL
) {
79 BOOL result
= DestroyWindow(window_
);
84 bool MessageWindow::Create(const MessageCallback
& message_callback
) {
85 return DoCreate(message_callback
, NULL
);
88 bool MessageWindow::CreateNamed(const MessageCallback
& message_callback
,
89 const string16
& window_name
) {
90 return DoCreate(message_callback
, window_name
.c_str());
94 HWND
MessageWindow::FindWindow(const string16
& window_name
) {
95 return FindWindowEx(HWND_MESSAGE
, NULL
, kMessageWindowClassName
,
99 bool MessageWindow::DoCreate(const MessageCallback
& message_callback
,
100 const wchar_t* window_name
) {
101 DCHECK(CalledOnValidThread());
102 DCHECK(message_callback_
.is_null());
105 message_callback_
= message_callback
;
107 WindowClass
& window_class
= g_window_class
.Get();
108 window_
= CreateWindow(MAKEINTATOM(window_class
.atom()), window_name
, 0, 0, 0,
109 0, 0, HWND_MESSAGE
, 0, window_class
.instance(), this);
111 LOG_GETLASTERROR(ERROR
) << "Failed to create a message-only window";
119 LRESULT CALLBACK
MessageWindow::WindowProc(HWND hwnd
,
123 MessageWindow
* self
= reinterpret_cast<MessageWindow
*>(
124 GetWindowLongPtr(hwnd
, GWLP_USERDATA
));
127 // Set up the self before handling WM_CREATE.
129 CREATESTRUCT
* cs
= reinterpret_cast<CREATESTRUCT
*>(lparam
);
130 self
= reinterpret_cast<MessageWindow
*>(cs
->lpCreateParams
);
132 // Make |hwnd| available to the message handler. At this point the control
133 // hasn't returned from CreateWindow() yet.
134 self
->window_
= hwnd
;
136 // Store pointer to the self to the window's user data.
137 SetLastError(ERROR_SUCCESS
);
138 LONG_PTR result
= SetWindowLongPtr(
139 hwnd
, GWLP_USERDATA
, reinterpret_cast<LONG_PTR
>(self
));
140 CHECK(result
!= 0 || GetLastError() == ERROR_SUCCESS
);
144 // Clear the pointer to stop calling the self once WM_DESTROY is
147 SetLastError(ERROR_SUCCESS
);
148 LONG_PTR result
= SetWindowLongPtr(hwnd
, GWLP_USERDATA
, NULL
);
149 CHECK(result
!= 0 || GetLastError() == ERROR_SUCCESS
);
154 // Handle the message.
156 LRESULT message_result
;
157 if (self
->message_callback_
.Run(message
, wparam
, lparam
, &message_result
))
158 return message_result
;
161 return DefWindowProc(hwnd
, message
, wparam
, lparam
);