Initial prototype minus drop-shadow.

BUG=None
TEST=Manual

Review URL: http://codereview.chromium.org/8356032

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107011 0039d316-1c4b-4281-b951-d872f2087c98
parent 464750f4
......@@ -10,6 +10,9 @@
#include "base/logging.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "base/win/scoped_gdi_object.h"
#include "base/win/scoped_hdc.h"
#include "base/win/scoped_select_object.h"
#include "remoting/host/chromoting_host.h"
// TODO(wez): The DisconnectWindow isn't plugin-specific, so shouldn't have
// a dependency on the plugin's resource header.
......@@ -28,6 +31,7 @@
extern HMODULE g_hModule;
const int DISCONNECT_HOTKEY_ID = 1000;
const int kWindowBorderRadius = 14;
namespace remoting {
......@@ -53,6 +57,7 @@ private:
remoting::ChromotingHost* host_;
HWND hwnd_;
bool has_hotkey_;
base::win::ScopedGDIObject<HPEN> border_pen_;
DISALLOW_COPY_AND_ASSIGN(DisconnectWindowWin);
};
......@@ -60,7 +65,9 @@ private:
DisconnectWindowWin::DisconnectWindowWin()
: host_(NULL),
hwnd_(NULL),
has_hotkey_(false) {
has_hotkey_(false),
border_pen_(CreatePen(PS_SOLID, 5,
RGB(0.13 * 255, 0.69 * 255, 0.11 * 255))) {
}
DisconnectWindowWin::~DisconnectWindowWin() {
......@@ -86,17 +93,11 @@ BOOL CALLBACK DisconnectWindowWin::DialogProc(HWND hwnd, UINT msg,
BOOL DisconnectWindowWin::OnDialogMessage(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_HOTKEY:
ShutdownHost();
EndDialog(0);
return TRUE;
// Ignore close messages.
case WM_CLOSE:
// Ignore close messages.
return TRUE;
case WM_DESTROY:
// Ensure we don't try to use the HWND anymore.
hwnd_ = NULL;
return TRUE;
// Handle the Disconnect button.
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDC_DISCONNECT:
......@@ -104,21 +105,77 @@ BOOL DisconnectWindowWin::OnDialogMessage(HWND hwnd, UINT msg,
EndDialog(LOWORD(wParam));
return TRUE;
}
return FALSE;
// Ensure we don't try to use the HWND anymore.
case WM_DESTROY:
hwnd_ = NULL;
return TRUE;
// Handle the disconnect hot-key.
case WM_HOTKEY:
ShutdownHost();
EndDialog(0);
return TRUE;
// Let the window be draggable by its client area by responding
// that the entire window is the title bar.
case WM_NCHITTEST:
SetWindowLong(hwnd, DWL_MSGRESULT, HTCAPTION);
return TRUE;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd_, &ps);
RECT rect;
GetClientRect(hwnd_, &rect);
{
base::win::ScopedSelectObject border(hdc, border_pen_);
base::win::ScopedSelectObject brush(hdc, GetStockObject(NULL_BRUSH));
RoundRect(hdc, rect.left, rect.top, rect.right - 1, rect.bottom - 1,
kWindowBorderRadius, kWindowBorderRadius);
}
EndPaint(hwnd_, &ps);
return TRUE;
}
}
return FALSE;
}
void DisconnectWindowWin::Show(ChromotingHost* host,
const std::string& username) {
CHECK(!hwnd_);
host_ = host;
CHECK(!hwnd_);
hwnd_ = CreateDialogParam(g_hModule, MAKEINTRESOURCE(IDD_DISCONNECT), NULL,
(DLGPROC)DialogProc, (LPARAM)this);
if (!hwnd_) {
LOG(ERROR) << "Unable to create Disconnect dialog for remoting.";
return;
}
// Load the dialog resource so that we can modify the RTL flags if necessary.
// This is taken from chrome/default_plugin/install_dialog.cc
HRSRC dialog_resource =
FindResource(g_hModule, MAKEINTRESOURCE(IDD_DISCONNECT), RT_DIALOG);
CHECK(dialog_resource);
HGLOBAL dialog_template = LoadResource(g_hModule, dialog_resource);
CHECK(dialog_template);
DLGTEMPLATE* dialog_pointer =
reinterpret_cast<DLGTEMPLATE*>(LockResource(dialog_template));
CHECK(dialog_pointer);
// The actual resource type is DLGTEMPLATEEX, but this is not defined in any
// standard headers, so we treat it as a generic pointer and manipulate the
// correct offsets explicitly.
scoped_ptr<unsigned char> rtl_dialog_template;
if (host->ui_strings().direction == UiStrings::RTL) {
unsigned long dialog_template_size =
SizeofResource(g_hModule, dialog_resource);
rtl_dialog_template.reset(new unsigned char[dialog_template_size]);
memcpy(rtl_dialog_template.get(), dialog_pointer, dialog_template_size);
DWORD* rtl_dwords = reinterpret_cast<DWORD*>(rtl_dialog_template.get());
rtl_dwords[2] |= (WS_EX_LAYOUTRTL | WS_EX_RTLREADING);
dialog_pointer = reinterpret_cast<DLGTEMPLATE*>(rtl_dwords);
}
hwnd_ = CreateDialogIndirectParam(g_hModule, dialog_pointer, NULL,
(DLGPROC)DialogProc, (LPARAM)this);
CHECK(hwnd_);
// Set up handler for Ctrl-Alt-Esc shortcut.
if (!has_hotkey_ && RegisterHotKey(hwnd_, DISCONNECT_HOTKEY_ID,
......@@ -135,8 +192,21 @@ void DisconnectWindowWin::ShutdownHost() {
host_->Shutdown(NULL);
}
static int GetControlTextWidth(HWND control) {
RECT rect = {0, 0, 0, 0};
WCHAR text[256];
int result = GetWindowText(control, text, arraysize(text));
if (result) {
base::win::ScopedGetDC dc(control);
base::win::ScopedSelectObject font(
dc, (HFONT)SendMessage(control, WM_GETFONT, 0, 0));
DrawText(dc, text, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
}
return rect.right;
}
void DisconnectWindowWin::SetStrings(const UiStrings& strings,
const std::string& username) {
const std::string& username) {
SetWindowText(hwnd_, strings.product_name.c_str());
HWND hwndButton = GetDlgItem(hwnd_, IDC_DISCONNECT);
......@@ -144,13 +214,49 @@ void DisconnectWindowWin::SetStrings(const UiStrings& strings,
const WCHAR* label =
has_hotkey_ ? strings.disconnect_button_text_plus_shortcut.c_str()
: strings.disconnect_button_text.c_str();
int button_old_required_width = GetControlTextWidth(hwndButton);
SetWindowText(hwndButton, label);
int button_new_required_width = GetControlTextWidth(hwndButton);
HWND hwndSharingWith = GetDlgItem(hwnd_, IDC_DISCONNECT_SHARINGWITH);
CHECK(hwndSharingWith);
string16 text = ReplaceStringPlaceholders(
strings.disconnect_message, UTF8ToUTF16(username), NULL);
int label_old_required_width = GetControlTextWidth(hwndSharingWith);
SetWindowText(hwndSharingWith, text.c_str());
int label_new_required_width = GetControlTextWidth(hwndSharingWith);
int label_width_delta = label_new_required_width - label_old_required_width;
int button_width_delta =
button_new_required_width - button_old_required_width;
// Reposition the controls such that the label lies to the left of the
// disconnect button (assuming LTR layout). The dialog template determines
// the controls' spacing; update their size to fit the localized content.
RECT label_rect;
GetClientRect(hwndSharingWith, &label_rect);
SetWindowPos(hwndSharingWith, NULL, 0, 0,
label_rect.right + label_width_delta, label_rect.bottom,
SWP_NOMOVE|SWP_NOZORDER);
RECT button_rect;
GetWindowRect(hwndButton, &button_rect);
int button_width = button_rect.right - button_rect.left;
int button_height = button_rect.bottom - button_rect.top;
MapWindowPoints(NULL, hwnd_, reinterpret_cast<LPPOINT>(&button_rect), 2);
SetWindowPos(hwndButton, NULL,
button_rect.left + label_width_delta, button_rect.top,
button_width + button_width_delta, button_height, SWP_NOZORDER);
RECT window_rect;
GetWindowRect(hwnd_, &window_rect);
int width = (window_rect.right - window_rect.left) +
button_width_delta + label_width_delta;
int height = window_rect.bottom - window_rect.top;
SetWindowPos(hwnd_, NULL, 0, 0, width, height, SWP_NOMOVE|SWP_NOZORDER);
HRGN rgn = CreateRoundRectRgn(0, 0, width, height, kWindowBorderRadius,
kWindowBorderRadius);
SetWindowRgn(hwnd_, rgn, TRUE);
}
void DisconnectWindowWin::Hide() {
......
......@@ -91,14 +91,15 @@ END
// Dialog
//
IDD_DISCONNECT DIALOGEX 0, 0, 166, 59
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION
IDD_DISCONNECT DIALOGEX 0, 0, 145, 24
STYLE DS_SETFONT | WS_POPUP
EXSTYLE WS_EX_TOPMOST
CAPTION "kTitle"
FONT 9, "Microsoft Sans Serif", 400, 0, 0x0
BEGIN
DEFPUSHBUTTON "kDisconnectButton",IDC_DISCONNECT,20,38,126,14
LTEXT "kSharingWith",IDC_DISCONNECT_SHARINGWITH,7,7,152,28
DEFPUSHBUTTON "kDisconnectButton",IDC_DISCONNECT,68,5,70,14
LTEXT "kSharingWith",IDC_DISCONNECT_SHARINGWITH,18,7,43,8
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT,6,6,1,12
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDVERT,8,6,1,12
END
IDD_CONTINUE DIALOGEX 0, 0, 221, 58
......@@ -123,12 +124,8 @@ GUIDELINES DESIGNINFO
BEGIN
IDD_DISCONNECT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 159
VERTGUIDE, 20
VERTGUIDE, 146
TOPMARGIN, 7
BOTTOMMARGIN, 52
BOTTOMMARGIN, 23
END
IDD_CONTINUE, DIALOG
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment