1 // Copyright (c) 2012 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 "chrome_frame/find_dialog.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome_frame/chrome_frame_automation.h"
13 const int kMaxFindChars
= 1024;
15 HHOOK
CFFindDialog::msg_hook_
= NULL
;
17 CFFindDialog::CFFindDialog() {}
19 void CFFindDialog::Init(ChromeFrameAutomationClient
* automation_client
) {
20 automation_client_
= automation_client
;
23 LRESULT
CFFindDialog::OnDestroy(UINT msg
, WPARAM wparam
, LPARAM lparam
,
25 // In order to cancel the selection when the Find dialog is dismissed, we
26 // do a fake search for a string that is unlikely to appear on the page.
27 // TODO(robertshield): Change this to plumb through a StopFinding automation
28 // message that triggers a ViewMsg_StopFinding.
29 std::string
guid(base::GenerateGUID());
30 automation_client_
->FindInPage(ASCIIToWide(guid
), FWD
, CASE_SENSITIVE
, false);
32 UninstallMessageHook();
36 LRESULT
CFFindDialog::OnFind(WORD wNotifyCode
, WORD wID
, HWND hWndCtl
,
38 string16
find_text(kMaxFindChars
, L
'\0');
39 find_text
.resize(GetDlgItemText(IDC_FIND_TEXT
, &find_text
[0], kMaxFindChars
));
41 // Repeated searches for the same string should move to the next instance.
42 bool find_next
= (find_text
== last_find_text_
);
44 last_find_text_
= find_text
;
46 bool match_case
= IsDlgButtonChecked(IDC_MATCH_CASE
) == BST_CHECKED
;
47 bool search_down
= IsDlgButtonChecked(IDC_DIRECTION_DOWN
) == BST_CHECKED
;
49 automation_client_
->FindInPage(find_text
,
50 search_down
? FWD
: BACK
,
51 match_case
? CASE_SENSITIVE
: IGNORE_CASE
,
57 LRESULT
CFFindDialog::OnCancel(WORD wNotifyCode
, WORD wID
, HWND hWndCtl
,
63 LRESULT
CFFindDialog::OnInitDialog(UINT msg
, WPARAM wparam
, LPARAM lparam
,
65 // Init() must be called before Create() or DoModal()!
66 DCHECK(automation_client_
.get());
69 SendDlgItemMessage(IDC_FIND_TEXT
, EM_EXLIMITTEXT
, 0, kMaxFindChars
);
70 BOOL result
= CheckRadioButton(IDC_DIRECTION_DOWN
, IDC_DIRECTION_UP
,
73 HWND text_field
= GetDlgItem(IDC_FIND_TEXT
);
74 ::SetFocus(text_field
);
76 return FALSE
; // we set the focus ourselves.
79 LRESULT CALLBACK
CFFindDialog::GetMsgProc(int code
, WPARAM wparam
,
81 // Mostly borrowed from http://support.microsoft.com/kb/q187988/
82 // and http://www.codeproject.com/KB/atl/cdialogmessagehook.aspx.
83 LPMSG msg
= reinterpret_cast<LPMSG
>(lparam
);
84 if (code
>= 0 && wparam
== PM_REMOVE
&&
85 msg
->message
>= WM_KEYFIRST
&& msg
->message
<= WM_KEYLAST
) {
86 HWND hwnd
= GetActiveWindow();
87 if (::IsWindow(hwnd
) && ::IsDialogMessage(hwnd
, msg
)) {
88 // The value returned from this hookproc is ignored, and it cannot
89 // be used to tell Windows the message has been handled. To avoid
90 // further processing, convert the message to WM_NULL before
93 msg
->message
= WM_NULL
;
99 // Passes the hook information to the next hook procedure in
100 // the current hook chain.
101 return ::CallNextHookEx(msg_hook_
, code
, wparam
, lparam
);
104 bool CFFindDialog::InstallMessageHook() {
105 // Make sure we only call this once.
106 DCHECK(msg_hook_
== NULL
);
107 msg_hook_
= ::SetWindowsHookEx(WH_GETMESSAGE
, &CFFindDialog::GetMsgProc
,
108 _AtlBaseModule
.m_hInst
, GetCurrentThreadId());
109 DCHECK(msg_hook_
!= NULL
);
110 return msg_hook_
!= NULL
;
113 bool CFFindDialog::UninstallMessageHook() {
114 DCHECK(msg_hook_
!= NULL
);
115 BOOL result
= ::UnhookWindowsHookEx(msg_hook_
);
119 return result
!= FALSE
;