Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

886 lines
32 KiB

  1. // Copyright (C) 1996-1997 Microsoft Corporation. All rights reserved.
  2. #include "header.h"
  3. #include "strtable.h"
  4. #include "hhctrl.h"
  5. #include "resource.h"
  6. #include "secwin.h"
  7. #include "htmlhelp.h"
  8. #include "cpaldc.h"
  9. #include "system.h"
  10. #include "fts.h"
  11. #include "TCHAR.h"
  12. #include "parserhh.h"
  13. #include "collect.h"
  14. #include "hhtypes.h"
  15. #include "toc.h"
  16. #include "search.h"
  17. #include "csubset.h"
  18. #include "cctlww.h"
  19. // Common Control Macros
  20. #include <windowsx.h>
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static const char THIS_FILE[] = __FILE__;
  24. #endif
  25. ///////////////////////////////////////////////////////////
  26. //
  27. // Contants
  28. //
  29. //TODO: Sizes and spaces should not be hard coded!
  30. const int BUTTON_WIDTH = 80;
  31. const int BUTTON_HEIGHT = 24;
  32. const int S_BOX_HEIGHT = 17;
  33. const int BOX_HEIGHT = 24;
  34. const int c_MaxSearchKeywordLength=256 ;
  35. const int c_StaticControlSpacing = 3; // Space between text and static control.
  36. const int c_ControlSpacing = 8 ; // Space between two controls.
  37. ///////////////////////////////////////////////////////////
  38. //
  39. // Static Member functions
  40. //
  41. WNDPROC CSearch::s_lpfnlComboWndProc = NULL;
  42. WNDPROC CSearch::s_lpfnlListViewWndProc = NULL;
  43. WNDPROC lpfnlSearchDisplayBtnWndProc = NULL;
  44. WNDPROC lpfnlSearchListBtnWndProc = NULL;
  45. ///////////////////////////////////////////////////////////
  46. //
  47. // Construction
  48. //
  49. ///////////////////////////////////////////////////////////
  50. //
  51. // Constructor
  52. //
  53. CSearch::CSearch(CHHWinType* phh)
  54. : m_hwndResizeToParent(NULL)
  55. {
  56. ASSERT(phh) ;
  57. m_phh = phh;
  58. m_pTitleCollection = phh->m_phmData->m_pTitleCollection;
  59. ASSERT(m_pTitleCollection);
  60. m_padding = 2; // padding to put around the window
  61. m_NavTabPos = phh->tabpos ;
  62. m_plistview = NULL;
  63. }
  64. ///////////////////////////////////////////////////////////
  65. //
  66. // Destructor
  67. //
  68. CSearch::~CSearch()
  69. {
  70. DESTROYIFVALID(m_hwndListBox);
  71. DESTROYIFVALID(m_hwndDisplayButton);
  72. DESTROYIFVALID(m_hwndListTopicsButton);
  73. DESTROYIFVALID(m_hwndComboBox);
  74. DESTROYIFVALID(m_hwndStaticKeyword);
  75. DESTROYIFVALID(m_hwndStaticTopic);
  76. if(m_plistview && m_plistview->m_pResults != NULL )
  77. {
  78. // Free the results list
  79. //
  80. m_pTitleCollection->m_pFullTextSearch->FreeResults(m_plistview->m_pResults);
  81. }
  82. if( m_plistview )
  83. delete m_plistview;
  84. }
  85. ///////////////////////////////////////////////////////////
  86. //
  87. // Create
  88. //
  89. static const char txtHHSearchClass[] = "HH FTSearch";
  90. BOOL CSearch::Create(HWND hwndParent)
  91. {
  92. /* Note: hwndParent is either the Naviagtion Frame or its the tab ctrl.
  93. This class does not parent to the tab ctrl, but to the navigation frame.
  94. GetParentSize will always return the hwndNaviation, if hwndParent is the
  95. tabctrl.
  96. The reason that it doesn't parent to the tab ctrl is that the tab ctrl
  97. steals commands. What should really have happened is that all of the windows
  98. in this control should be contained in another window. However, its too late to
  99. change this now.
  100. */
  101. RECT rcParent, rcChild, rcStatic, rcButton;
  102. DWORD dwExt;
  103. PCSTR psz;
  104. HFONT hfUI = _Resource.GetUIFont();
  105. BOOL fUnicodeWindow;
  106. // Save the hwndParent for ResizeWindow.
  107. m_hwndResizeToParent = hwndParent ;
  108. // Note: GetParentSize will return hwndNavigation if hwndParent is the tab ctrl.
  109. hwndParent = GetParentSize(&rcParent, hwndParent, m_padding, m_NavTabPos);
  110. rcParent.top += GetSystemMetrics(SM_CYSIZEFRAME)*2 ; //HACK: Fudge the top since we are not parented to the tabctrl.
  111. CopyRect(&rcChild, &rcParent);
  112. // Place the "Keyword" static text on top of the edit control
  113. m_hwndStaticKeyword = CreateWindowEx(WS_EX_TRANSPARENT, "STATIC", "",
  114. WS_CHILD , rcChild.left, rcChild.top,
  115. RECT_WIDTH(rcChild), S_BOX_HEIGHT, hwndParent,
  116. (HMENU) ID_STATIC_KEYWORDS, _Module.GetModuleInstance(), NULL);
  117. // set the font
  118. SendMessage(m_hwndStaticKeyword, WM_SETFONT, (WPARAM)hfUI, FALSE);
  119. // Get the dimensions of the text for sizing and spacing needs.
  120. if(g_bWinNT5)
  121. {
  122. WCHAR *pwz = (WCHAR *) GetStringResourceW(IDS_TYPE_KEYWORD);
  123. dwExt = GetStaticDimensionsW( m_hwndStaticKeyword, hfUI, pwz, RECT_WIDTH(rcChild) );
  124. rcChild.bottom = rcChild.top + HIWORD(dwExt) ;
  125. MoveWindow(m_hwndStaticKeyword, rcChild.left, rcChild.top,
  126. RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), FALSE );
  127. SetWindowTextW(m_hwndStaticKeyword, pwz);
  128. }
  129. else
  130. {
  131. psz = GetStringResource(IDS_TYPE_KEYWORD);
  132. dwExt = GetStaticDimensions( m_hwndStaticKeyword, hfUI, psz, RECT_WIDTH(rcChild) );
  133. rcChild.bottom = rcChild.top + HIWORD(dwExt) ;
  134. MoveWindow(m_hwndStaticKeyword, rcChild.left, rcChild.top,
  135. RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), FALSE );
  136. SetWindowText(m_hwndStaticKeyword, psz);
  137. }
  138. rcChild.top = rcChild.bottom + c_StaticControlSpacing; // Add space between static and control.
  139. rcChild.bottom = rcChild.top + BOX_HEIGHT;
  140. // create the edit control for entering the search text
  141. // leave room for the static text on top
  142. m_hwndComboBox = W_CreateWindowEx(WS_EX_CLIENTEDGE | g_RTL_Style, L"EDIT", L"",
  143. WS_CHILD | WS_BORDER | WS_TABSTOP | ES_AUTOHSCROLL, rcChild.left, rcChild.top,
  144. RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), hwndParent,
  145. (HMENU) IDSIMPLESEARCH_COMBO, _Module.GetModuleInstance(), NULL, &fUnicodeWindow);
  146. if (!m_hwndComboBox)
  147. goto _Error;
  148. // Sub-class the combo box
  149. if (NULL == s_lpfnlComboWndProc)
  150. s_lpfnlComboWndProc = (WNDPROC) W_GetWndProc(m_hwndComboBox, fUnicodeWindow);
  151. W_SubClassWindow(m_hwndComboBox, (LONG_PTR) ComboProc, fUnicodeWindow);
  152. SETTHIS(m_hwndComboBox);
  153. // Limit the amount of text which can be typed in.
  154. Edit_LimitText(m_hwndComboBox, c_MaxSearchKeywordLength-1) ;
  155. // set the font
  156. SendMessage(m_hwndComboBox, WM_SETFONT, (WPARAM) m_phh->GetContentFont(), FALSE);
  157. // create the "List Topics" button and place it
  158. // below the edit control and to the parent's right edge
  159. rcChild.top = rcChild.bottom + c_ControlSpacing;
  160. rcChild.bottom = rcChild.top + BUTTON_HEIGHT;
  161. if(g_bWinNT5)
  162. {
  163. m_hwndListTopicsButton = CreateWindowW(L"BUTTON",
  164. GetStringResourceW(IDS_LIST_TOPICS),
  165. WS_CHILD | WS_TABSTOP, rcChild.right-(BUTTON_WIDTH+2), rcChild.top,
  166. BUTTON_WIDTH, BUTTON_HEIGHT, hwndParent,
  167. (HMENU) IDBTN_LIST_TOPICS, _Module.GetModuleInstance(), NULL);
  168. }
  169. else
  170. {
  171. m_hwndListTopicsButton = CreateWindow("BUTTON",
  172. GetStringResource(IDS_LIST_TOPICS),
  173. WS_CHILD | WS_TABSTOP, rcChild.right-(BUTTON_WIDTH+2), rcChild.top,
  174. BUTTON_WIDTH, BUTTON_HEIGHT, hwndParent,
  175. (HMENU) IDBTN_LIST_TOPICS, _Module.GetModuleInstance(), NULL);
  176. }
  177. if (!m_hwndListTopicsButton)
  178. goto _Error;
  179. if (NULL == lpfnlSearchListBtnWndProc)
  180. lpfnlSearchListBtnWndProc= (WNDPROC) GetWindowLongPtr(m_hwndListTopicsButton, GWLP_WNDPROC);
  181. SetWindowLongPtr(m_hwndListTopicsButton, GWLP_WNDPROC, (LONG_PTR) ListBtnProc);
  182. SETTHIS(m_hwndListTopicsButton);
  183. rcChild.top = rcChild.bottom + c_ControlSpacing;
  184. rcChild.bottom = rcChild.top + S_BOX_HEIGHT;
  185. m_hwndStaticTopic = CreateWindowEx(WS_EX_TRANSPARENT, "STATIC", "",
  186. WS_CHILD , rcChild.left, rcChild.top - S_BOX_HEIGHT,
  187. RECT_WIDTH(rcChild), S_BOX_HEIGHT, hwndParent,
  188. (HMENU) ID_STATIC_SELECT_TOPIC, _Module.GetModuleInstance(), NULL);
  189. if (!m_hwndStaticTopic)
  190. goto _Error;
  191. GetWindowRect(m_hwndStaticTopic, &rcStatic);
  192. if(g_bWinNT5)
  193. {
  194. WCHAR *pwz = (WCHAR *) GetStringResourceW(IDS_SELECT_TOPIC);
  195. dwExt = GetStaticDimensionsW(m_hwndStaticTopic, hfUI, pwz, RECT_WIDTH(rcStatic) );
  196. rcStatic.bottom = rcStatic.top+HIWORD(dwExt);
  197. MoveWindow(m_hwndStaticTopic, rcStatic.left, rcStatic.top,
  198. RECT_WIDTH(rcStatic), RECT_HEIGHT(rcStatic), FALSE);
  199. SendMessage(m_hwndStaticTopic, WM_SETFONT, (WPARAM) hfUI, FALSE);
  200. SetWindowTextW(m_hwndStaticTopic, pwz);
  201. }
  202. else
  203. {
  204. psz = GetStringResource(IDS_SELECT_TOPIC);
  205. dwExt = GetStaticDimensions( m_hwndStaticTopic, hfUI, psz, RECT_WIDTH(rcStatic) );
  206. rcStatic.bottom = rcStatic.top+HIWORD(dwExt);
  207. MoveWindow(m_hwndStaticTopic, rcStatic.left, rcStatic.top,
  208. RECT_WIDTH(rcStatic), RECT_HEIGHT(rcStatic), FALSE);
  209. SendMessage(m_hwndStaticTopic, WM_SETFONT, (WPARAM) hfUI, FALSE);
  210. SetWindowText(m_hwndStaticTopic, psz);
  211. }
  212. // create the list view control and place it
  213. // +BOX_HEIGHT for combo box and adjust for spacing.
  214. // Note: leave space for the static text on top of the list box control
  215. rcChild.top = rcChild.bottom + c_StaticControlSpacing; // Space between static and control.
  216. rcChild.bottom = rcParent.bottom - (c_ControlSpacing) - BUTTON_HEIGHT; // BUG 2204: Also subtract off the space for the display button.
  217. m_hwndListBox = W_CreateControlWindow (
  218. WS_EX_CLIENTEDGE | g_RTL_Style,
  219. WS_CHILD | WS_BORDER | WS_TABSTOP | WS_VSCROLL |
  220. LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOCOLUMNHEADER,
  221. W_ListView,
  222. L"HH FTSearch",
  223. rcChild.left, rcChild.top, RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild),
  224. hwndParent,
  225. (HMENU)IDSEARCH_LIST,
  226. _Module.GetModuleInstance(),
  227. NULL
  228. );
  229. if (!m_hwndListBox)
  230. goto _Error;
  231. W_ListView_SetExtendedListViewStyle( m_hwndListBox, LVS_EX_FULLROWSELECT | g_RTL_Style);
  232. m_plistview = new CFTSListView(m_pTitleCollection, m_hwndListBox );
  233. // Sub-class the list view
  234. fUnicodeWindow = IsWindowUnicode(m_hwndListBox);
  235. if (NULL == s_lpfnlListViewWndProc)
  236. s_lpfnlListViewWndProc = W_GetWndProc(m_hwndListBox, fUnicodeWindow);
  237. W_SubClassWindow(m_hwndListBox, reinterpret_cast<LONG_PTR>(ListViewProc), fUnicodeWindow);
  238. SETTHIS(m_hwndListBox);
  239. // BUG 3204 ---
  240. // In 3204, the listview control was painting BEFORE the tabctrl which was then painting over the top of it.
  241. // Therefore, I've added code here and in resize to force the listbox to be the top most window in this grouping.
  242. if (hwndParent != m_hwndResizeToParent )
  243. {
  244. SetWindowPos(m_hwndListBox, m_hwndResizeToParent, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE );
  245. }
  246. SendMessage(m_hwndListBox, WM_SETFONT, (WPARAM) m_phh->GetAccessableContentFont(), FALSE);
  247. // create the "Display" button and place it
  248. rcChild.bottom = rcParent.bottom;
  249. rcChild.top = rcChild.bottom - BUTTON_HEIGHT;
  250. if(g_bWinNT5)
  251. {
  252. m_hwndDisplayButton = CreateWindowW(L"BUTTON",
  253. GetStringResourceW(IDS_ENGLISH_DISPLAY),
  254. WS_CHILD | WS_TABSTOP, rcChild.right-BUTTON_WIDTH-2, rcChild.top,
  255. BUTTON_WIDTH, BUTTON_HEIGHT, hwndParent,
  256. (HMENU) IDBTN_DISPLAY, _Module.GetModuleInstance(), NULL);
  257. }
  258. else
  259. {
  260. m_hwndDisplayButton = CreateWindow("BUTTON",
  261. GetStringResource(IDS_ENGLISH_DISPLAY),
  262. WS_CHILD | WS_TABSTOP, rcChild.right-BUTTON_WIDTH-2, rcChild.top,
  263. BUTTON_WIDTH, BUTTON_HEIGHT, hwndParent,
  264. (HMENU) IDBTN_DISPLAY, _Module.GetModuleInstance(), NULL);
  265. }
  266. if (!m_hwndDisplayButton)
  267. goto _Error;
  268. EnableWindow(m_hwndDisplayButton, FALSE);
  269. if (NULL == lpfnlSearchDisplayBtnWndProc)
  270. lpfnlSearchDisplayBtnWndProc = (WNDPROC) GetWindowLongPtr(m_hwndDisplayButton, GWLP_WNDPROC);
  271. SetWindowLongPtr(m_hwndDisplayButton, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(DisplayBtnProc));
  272. SETTHIS(m_hwndDisplayButton);
  273. SendMessage(m_hwndDisplayButton, WM_SETFONT, (WPARAM) hfUI, FALSE);
  274. GetWindowRect(m_hwndDisplayButton, &rcButton);
  275. dwExt = GetButtonDimensions(m_hwndDisplayButton, hfUI, GetStringResource(IDS_ENGLISH_DISPLAY));
  276. MoveWindow(m_hwndDisplayButton, rcChild.right - LOWORD(dwExt), rcButton.top,
  277. LOWORD(dwExt), HIWORD(dwExt), FALSE);
  278. SendMessage(m_hwndListTopicsButton, WM_SETFONT, (WPARAM) hfUI, FALSE);
  279. GetWindowRect(m_hwndListTopicsButton, &rcButton);
  280. dwExt = GetButtonDimensions(m_hwndListTopicsButton, hfUI, GetStringResource(IDS_LIST_TOPICS));
  281. MoveWindow(m_hwndListTopicsButton, rcChild.right - LOWORD(dwExt), rcButton.top,
  282. LOWORD(dwExt), HIWORD(dwExt), FALSE);
  283. ShowWindow();
  284. SetFocus( m_hwndComboBox );
  285. EnableWindow(m_hwndListTopicsButton, W_HasText(m_hwndComboBox));
  286. // Initialize the array containing the dialog information.
  287. InitDlgItemArray() ;
  288. return TRUE;
  289. _Error:
  290. DESTROYIFVALID(m_hwndComboBox);
  291. DESTROYIFVALID(m_hwndListTopicsButton);
  292. DESTROYIFVALID(m_hwndListBox);
  293. DESTROYIFVALID(m_hwndStaticKeyword);
  294. DESTROYIFVALID(m_hwndStaticTopic);
  295. DESTROYIFVALID(m_hwndDisplayButton);
  296. return FALSE;
  297. }
  298. ///////////////////////////////////////////////////////////
  299. //
  300. // ResizeWindow
  301. //
  302. // if the parent window size changes, resize and place the child windows.
  303. void CSearch::ResizeWindow()
  304. {
  305. ASSERT(::IsValidWindow(m_hwndStaticKeyword)) ;
  306. // Resize to fit the client area of the tabctrl if it exists.
  307. ASSERT(::IsValidWindow(m_hwndResizeToParent )) ;
  308. RECT rcParent, rcChild;
  309. DWORD dwExt;
  310. HFONT hfUI = _Resource.GetUIFont();
  311. GetParentSize(&rcParent, m_hwndResizeToParent, m_padding, m_NavTabPos);
  312. rcParent.top += GetSystemMetrics(SM_CYSIZEFRAME)*2 ; //HACK: Fudge the top since we are not parented to the tabctrl.
  313. CopyRect(&rcChild, &rcParent);
  314. // Resize the Static above the combo control
  315. dwExt = GetStaticDimensions( m_hwndStaticKeyword, hfUI, GetStringResource(IDS_TYPE_KEYWORD), RECT_WIDTH(rcChild) );
  316. rcChild.bottom = rcChild.top+HIWORD(dwExt);
  317. if (g_fDBCSSystem || g_langSystem == LANG_ARABIC || g_langSystem == LANG_HEBREW)
  318. {
  319. PCSTR pszTabVertSize = GetStringResource(IDS_TAB_VERT_PADDING);
  320. DWORD dwPad = 2;
  321. if(pszTabVertSize && IsDigit((BYTE) *pszTabVertSize))
  322. dwPad = Atoi(pszTabVertSize);
  323. MoveWindow(m_hwndStaticKeyword, rcParent.left, rcParent.top+dwPad,
  324. RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE);
  325. }
  326. else
  327. MoveWindow(m_hwndStaticKeyword, rcParent.left, rcParent.top,
  328. RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE);
  329. // Resize the Combo control
  330. rcChild.top = rcChild.bottom + c_StaticControlSpacing; //space for the static
  331. dwExt = GetStaticDimensions(m_hwndComboBox, GetContentFont(),"Test", RECT_WIDTH(rcChild) );
  332. rcChild.bottom = rcChild.top+HIWORD(dwExt) + GetSystemMetrics(SM_CYSIZEFRAME)*2 ;
  333. MoveWindow(m_hwndComboBox, rcChild.left, rcChild.top,
  334. RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE);
  335. // Resize the List Topics Button
  336. rcChild.top = rcChild.bottom + c_ControlSpacing;
  337. dwExt = GetButtonDimensions(m_hwndListTopicsButton, hfUI, GetStringResource(IDS_LIST_TOPICS));
  338. rcChild.bottom = rcChild.top + HIWORD(dwExt);
  339. MoveWindow(m_hwndListTopicsButton, rcChild.right - LOWORD(dwExt), rcChild.top,
  340. LOWORD(dwExt), RECT_HEIGHT(rcChild), TRUE);
  341. // Resize the Static text above the list box
  342. rcChild.top = rcChild.bottom+ c_ControlSpacing;
  343. dwExt = GetStaticDimensions( m_hwndStaticTopic, hfUI, GetStringResource(IDS_SELECT_TOPIC), RECT_WIDTH(rcChild) );
  344. rcChild.bottom = rcChild.top+HIWORD(dwExt);
  345. MoveWindow(m_hwndStaticTopic, rcChild.left, rcChild.top,
  346. RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE);
  347. // Resize the List Box
  348. rcChild.top = rcChild.bottom + c_StaticControlSpacing;
  349. dwExt = GetButtonDimensions(m_hwndDisplayButton, hfUI, GetStringResource(IDS_ENGLISH_DISPLAY) );
  350. rcChild.bottom = rcParent.bottom - (HIWORD(dwExt) + c_ControlSpacing);
  351. MoveWindow(m_hwndListBox, rcChild.left, rcChild.top,
  352. RECT_WIDTH(rcChild), RECT_HEIGHT(rcChild), TRUE);
  353. // BUG 3204 ---
  354. // In 3204, the listview control was painting BEFORE the tabctrl which was then painting over the top of it.
  355. // Therefore, I've added code here and in create to force the listbox to be the top most window in this grouping.
  356. SetWindowPos(m_hwndListBox, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE );
  357. // Resize the Display Button
  358. rcChild.bottom = rcParent.bottom ;
  359. rcChild.top = rcChild.bottom - HIWORD(dwExt);
  360. MoveWindow(m_hwndDisplayButton, rcChild.right - LOWORD(dwExt), rcChild.top,
  361. LOWORD(dwExt), RECT_HEIGHT(rcChild), TRUE);
  362. m_plistview->SizeColumns();
  363. }
  364. void CSearch::HideWindow(void)
  365. {
  366. ::ShowWindow(m_hwndListBox, SW_HIDE);
  367. ::ShowWindow(m_hwndDisplayButton, SW_HIDE);
  368. ::ShowWindow(m_hwndListTopicsButton, SW_HIDE);
  369. ::ShowWindow(m_hwndComboBox, SW_HIDE);
  370. ::ShowWindow(m_hwndStaticKeyword, SW_HIDE);
  371. ::ShowWindow(m_hwndStaticTopic, SW_HIDE);
  372. }
  373. void CSearch::ShowWindow(void)
  374. {
  375. ::ShowWindow(m_hwndListBox, SW_SHOW);
  376. ::ShowWindow(m_hwndDisplayButton, SW_SHOW);
  377. ::ShowWindow(m_hwndListTopicsButton, SW_SHOW);
  378. ::ShowWindow(m_hwndComboBox, SW_SHOW);
  379. ::ShowWindow(m_hwndStaticKeyword, SW_SHOW);
  380. ::ShowWindow(m_hwndStaticTopic, SW_SHOW);
  381. SetFocus(m_hwndComboBox);
  382. }
  383. ///////////////////////////////////////////////////////////
  384. //
  385. // OnCommand
  386. //
  387. LRESULT CSearch::OnCommand(HWND hwnd, UINT id, UINT uNotifiyCode, LPARAM lParam)
  388. {
  389. switch (id) {
  390. case IDSIMPLESEARCH_COMBO:
  391. if (uNotifiyCode == CBN_EDITCHANGE)
  392. m_plistview->ResetQuery();
  393. return 0;
  394. case IDSEARCH_LIST: // the list view control
  395. return 0;
  396. case IDBTN_LIST_TOPICS: // The List Topics button
  397. WCHAR szQuery[500];
  398. int cResultCount;
  399. HRESULT hr;
  400. // Get the query text
  401. //
  402. W_GetWindowText(m_hwndComboBox, szQuery, 500);
  403. if ( lstrlenW(szQuery) <= 0 )
  404. return 0;
  405. {
  406. SEARCH_RESULT *pTempResults;
  407. // Submit the query
  408. //
  409. CHourGlass HourGlass;
  410. hr = m_pTitleCollection->m_pFullTextSearch->SimpleQuery(szQuery,&cResultCount, &pTempResults);
  411. // Check for search failure
  412. //
  413. if (FAILED(hr)) {
  414. BOOL bContinue = FALSE;
  415. UINT idMsg = IDS_SEARCH_FAILURE;
  416. switch (hr)
  417. {
  418. case FTS_NO_INDEX: idMsg = IDS_NO_FTS_DATA; break;
  419. case FTS_NOT_INITIALIZED: idMsg = IDS_BAD_ITIRCL; break;
  420. case FTS_E_SKIP_TITLE: // bContinue = TRUE;
  421. case FTS_E_SKIP_VOLUME:// bContinue = TRUE;
  422. case FTS_E_SKIP_ALL: bContinue = TRUE; break;
  423. case FTS_INVALID_SYNTAX: idMsg = IDS_INCORRECT_SYNTAX; break;
  424. }
  425. if( !bContinue )
  426. {
  427. MsgBox(idMsg);
  428. SetFocus(m_hwndComboBox);
  429. return 0;
  430. }
  431. SetFocus(m_hwndComboBox);
  432. }
  433. // Check for no results
  434. //
  435. if(!cResultCount)
  436. {
  437. MsgBox(IDS_NO_TOPICS_FOUND);
  438. SetFocus(m_hwndComboBox);
  439. return 0;
  440. }
  441. else
  442. {
  443. m_plistview->ResetQuery();
  444. m_plistview->SetResults(cResultCount, pTempResults) ;
  445. m_plistview->AddItems();
  446. EnableWindow(m_hwndDisplayButton, TRUE);
  447. }
  448. }
  449. #if 0
  450. // For testing purposes, I'm going to display a message box containing a
  451. // comma delmited list of topic numbers that contained the search term(s).
  452. //
  453. char szResultList[1000],szTemp[20];
  454. szResultList[0]=0;
  455. int c;
  456. for(c=0;c<cResultCount;c++)
  457. {
  458. wsprintf(szTemp,"%d,",m_plistview->m_pResults[c].dwTopicNumber);
  459. strcat(szResultList,szTemp);
  460. }
  461. szResultList[strlen(szResultList)-1] = 0;
  462. // Show the list of resulting topic numbers
  463. //
  464. MessageBox(NULL,szResultList,"Full-Text Search Results",MB_OK|MB_TASKMODAL);
  465. #endif
  466. return 0;
  467. case IDBTN_DISPLAY:
  468. if( (m_plistview->m_pResults != NULL) && (m_plistview->m_ItemNumber!= -1))
  469. {
  470. DWORD dwtemp = m_plistview->m_pResults[m_plistview->m_ItemNumber].dwTopicNumber;
  471. CExTitle* pTitle = m_plistview->m_pResults[m_plistview->m_ItemNumber].pTitle;
  472. if ( pTitle )
  473. {
  474. char szURL[MAX_URL];
  475. if ((pTitle->GetTopicURL(dwtemp, szURL, sizeof(szURL)) == S_OK))
  476. ChangeHtmlTopic(szURL, GetParent(m_plistview->m_hwndListView), 1);
  477. }
  478. }
  479. return 0;
  480. #ifdef _DEBUG
  481. case ID_VIEW_MEMORY:
  482. OnReportMemoryUsage();
  483. return 0;
  484. #endif
  485. }
  486. return 0;
  487. }
  488. ///////////////////////////////////////////////////////////
  489. //
  490. // CALLBACKS
  491. //
  492. ///////////////////////////////////////////////////////////
  493. //
  494. // ComboProc
  495. //
  496. LRESULT WINAPI
  497. CSearch::ComboProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  498. {
  499. switch (msg)
  500. {
  501. case WM_CHAR:
  502. {
  503. if (wParam == VK_TAB) // The virt code is the same as the tab character.
  504. {
  505. // Not handling this message was causing a beep.
  506. return 0 ;
  507. }
  508. }
  509. break ;
  510. case WM_KEYUP:
  511. EnableWindow(GETTHIS(CSearch, hwnd)->m_hwndListTopicsButton, W_HasText(GETTHIS(CSearch, hwnd)->m_hwndComboBox));
  512. break;
  513. case WM_KEYDOWN:
  514. switch (wParam)
  515. {
  516. case VK_RETURN:
  517. SendMessage(FindMessageParent(hwnd), WM_COMMAND, MAKELONG(IDBTN_LIST_TOPICS, BN_CLICKED), 0);
  518. return 0;
  519. case VK_TAB:
  520. if (GetKeyState(VK_SHIFT) < 0)
  521. {
  522. if (IsWindowEnabled(GETTHIS(CSearch, hwnd)->m_hwndDisplayButton))
  523. SetFocus(GETTHIS(CSearch, hwnd)->m_hwndDisplayButton);
  524. else
  525. SetFocus(GETTHIS(CSearch, hwnd)->m_hwndListBox);
  526. }
  527. else
  528. {
  529. if (IsWindowEnabled(GETTHIS(CSearch, hwnd)->m_hwndListTopicsButton))
  530. SetFocus(GETTHIS(CSearch, hwnd)->m_hwndListTopicsButton);
  531. else
  532. SetFocus(GETTHIS(CSearch, hwnd)->m_hwndListBox);
  533. }
  534. return 0;
  535. }
  536. // fall through
  537. }
  538. return W_DelegateWindowProc(s_lpfnlComboWndProc, hwnd, msg, wParam,lParam);
  539. }
  540. ///////////////////////////////////////////////////////////
  541. //
  542. // ListViewProc
  543. //
  544. LRESULT WINAPI
  545. CSearch::ListViewProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  546. {
  547. switch (msg)
  548. {
  549. case WM_KEYDOWN:
  550. if (wParam == VK_TAB)
  551. {
  552. if (GetKeyState(VK_SHIFT) < 0)
  553. {
  554. if (IsWindowEnabled(GETTHIS(CSearch, hwnd)->m_hwndListTopicsButton))
  555. SetFocus(GETTHIS(CSearch, hwnd)->m_hwndListTopicsButton);
  556. else
  557. SetFocus(GETTHIS(CSearch, hwnd)->m_hwndComboBox);
  558. }
  559. else
  560. {
  561. if (IsWindowEnabled(GETTHIS(CSearch, hwnd)->m_hwndDisplayButton))
  562. SetFocus(GETTHIS(CSearch, hwnd)->m_hwndDisplayButton);
  563. else
  564. SetFocus(GETTHIS(CSearch, hwnd)->m_hwndComboBox);
  565. }
  566. return 0;
  567. }
  568. break;
  569. }
  570. return W_DelegateWindowProc(s_lpfnlListViewWndProc, hwnd, msg, wParam, lParam);
  571. }
  572. ///////////////////////////////////////////////////////////
  573. //
  574. // ListBtnProc
  575. //
  576. LRESULT WINAPI
  577. CSearch::ListBtnProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  578. {
  579. switch(msg)
  580. {
  581. case WM_KEYDOWN:
  582. switch (wParam)
  583. {
  584. case VK_RETURN:
  585. SendMessage(FindMessageParent(hwnd), WM_COMMAND, MAKELONG(IDBTN_LIST_TOPICS, BN_CLICKED), 0);
  586. return 0;
  587. case VK_TAB:
  588. if (GetKeyState(VK_SHIFT) < 0)
  589. SetFocus(GETTHIS(CSearch, hwnd)->m_hwndComboBox);
  590. else
  591. SetFocus(GETTHIS(CSearch, hwnd)->m_hwndListBox);
  592. return 0;
  593. }
  594. break;
  595. }
  596. return W_DelegateWindowProc(lpfnlSearchListBtnWndProc, hwnd, msg, wParam, lParam);
  597. }
  598. ///////////////////////////////////////////////////////////
  599. //
  600. // DisplayBtnProc
  601. //
  602. LRESULT WINAPI
  603. CSearch::DisplayBtnProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  604. {
  605. switch(msg) {
  606. case WM_KEYDOWN:
  607. if (wParam == VK_RETURN) {
  608. SendMessage(FindMessageParent(hwnd), WM_COMMAND,
  609. MAKELONG( IDBTN_DISPLAY, BN_CLICKED), 0);
  610. return 0;
  611. }
  612. if (wParam == VK_TAB) {
  613. CSearch* pThis = (CSearch*) GetWindowLongPtr(hwnd, GWLP_USERDATA);
  614. if (GetKeyState(VK_SHIFT) < 0)
  615. SetFocus(pThis->m_hwndListBox);
  616. else
  617. SetFocus(pThis->m_hwndComboBox);
  618. }
  619. break;
  620. }
  621. return W_DelegateWindowProc(lpfnlSearchDisplayBtnWndProc, hwnd, msg, wParam, lParam);
  622. }
  623. ///////////////////////////////////////////////////////////
  624. //
  625. // INavUI New Interface functions
  626. //
  627. ///////////////////////////////////////////////////////////
  628. //
  629. // SetDefaultFocus
  630. //
  631. void
  632. CSearch::SetDefaultFocus()
  633. {
  634. if (IsValidWindow(m_hwndComboBox))
  635. {
  636. ::SetFocus(m_hwndComboBox) ;
  637. }
  638. }
  639. ///////////////////////////////////////////////////////////
  640. //
  641. // ProcessMenuChar
  642. //
  643. bool
  644. CSearch::ProcessMenuChar(HWND hwndParent, int ch)
  645. {
  646. return ::ProcessMenuChar(this, hwndParent, m_aDlgItems, c_NumDlgItems, ch) ;
  647. }
  648. ///////////////////////////////////////////////////////////
  649. //
  650. // OnNotify
  651. //
  652. LRESULT
  653. CSearch::OnNotify(HWND hwnd, WPARAM wParam, LPARAM lParam)
  654. {
  655. // Delegate all of the WM_NOTIFY messages to the listview control.
  656. if ((wParam == IDSEARCH_LIST) && (::IsValidWindow(m_hwndListBox)) && m_plistview)
  657. {
  658. m_plistview->ListViewMsg(m_hwndListBox, (NM_LISTVIEW*) lParam);
  659. }
  660. return 0;
  661. }
  662. ///////////////////////////////////////////////////////////
  663. //
  664. // Helper Functions
  665. //
  666. ///////////////////////////////////////////////////////////
  667. //
  668. // InitDlgItemArray
  669. //
  670. void
  671. CSearch::InitDlgItemArray()
  672. {
  673. //TODO: This the m_aDlgItems array has not been fully utilized. Yet. Currently. we
  674. // are only using it here for accelerator handling. See Bookmark.cpp and adsearch.cpp for
  675. // the complete useage.
  676. //RECT rectCurrent ;
  677. //RECT rectDlg ;
  678. //::GetClientRect(m_hWnd, &rectDlg) ;
  679. //--- Setup the dlg array for each control.
  680. //--- Keyword Edit
  681. int i = c_KeywordEdit;
  682. m_aDlgItems[i].m_hWnd = m_hwndComboBox; //::GetDlgItem(m_hWnd, IDSIMPLESEARCH_COMBO) ;
  683. //::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
  684. //ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  685. m_aDlgItems[i].m_id = IDSIMPLESEARCH_COMBO;
  686. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_hwndStaticKeyword);
  687. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  688. /*
  689. m_aDlgItems[i].m_bIgnoreEnabled = TRUE ;
  690. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  691. m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter.
  692. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  693. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically.
  694. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  695. //m_aDlgItems[i].m_iOffsetV = ; // Distance from our justification point.
  696. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  697. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  698. //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding.
  699. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding.
  700. m_aDlgItems[i].m_rectMin = rectCurrent;
  701. m_aDlgItems[i].m_rectCur = rectCurrent;
  702. //m_aDlgItems[i].m_rectMax ; // Max size.
  703. */
  704. //--- ListTopics Btn
  705. i = c_ListTopicBtn;
  706. m_aDlgItems[i].m_hWnd = m_hwndListTopicsButton ;//::GetDlgItem(m_hWnd, IDBTN_LIST_TOPICS) ;
  707. //::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
  708. //ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  709. m_aDlgItems[i].m_id = IDBTN_LIST_TOPICS;
  710. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd);
  711. m_aDlgItems[i].m_Type = ItemInfo::Button;
  712. /*
  713. m_aDlgItems[i].m_bIgnoreEnabled = TRUE ;
  714. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  715. m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter.
  716. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  717. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically.
  718. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  719. //m_aDlgItems[i].m_iOffsetV = ; // Distance from our justification point.
  720. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  721. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  722. //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding.
  723. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding.
  724. m_aDlgItems[i].m_rectMin = rectCurrent;
  725. m_aDlgItems[i].m_rectCur = rectCurrent;
  726. //m_aDlgItems[i].m_rectMax ; // Max size.
  727. */
  728. //--- Results List
  729. i = c_ResultsList;
  730. m_aDlgItems[i].m_hWnd = m_hwndListBox;//::GetDlgItem(m_hWnd, IDSEARCH_LIST) ;
  731. //::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
  732. //ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  733. m_aDlgItems[i].m_id = IDSEARCH_LIST;
  734. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_hwndStaticTopic);
  735. m_aDlgItems[i].m_Type = ItemInfo::Generic;
  736. /*
  737. m_aDlgItems[i].m_bIgnoreEnabled = TRUE ;
  738. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  739. m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter.
  740. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  741. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically.
  742. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  743. //m_aDlgItems[i].m_iOffsetV = ; // Distance from our justification point.
  744. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  745. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  746. //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding.
  747. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding.
  748. m_aDlgItems[i].m_rectMin = rectCurrent;
  749. m_aDlgItems[i].m_rectCur = rectCurrent;
  750. //m_aDlgItems[i].m_rectMax ; // Max size.
  751. */
  752. //--- Display Button
  753. i = c_DisplayBtn;
  754. m_aDlgItems[i].m_hWnd = m_hwndDisplayButton ; //::GetDlgItem(m_hWnd, IDBTN_DISPLAY) ;
  755. //::GetWindowRect(m_aDlgItems[i].m_hWnd, &rectCurrent) ; // Get screen coordinates.
  756. //ScreenRectToClientRect(m_hWnd, &rectCurrent); // Convert to client
  757. m_aDlgItems[i].m_id = IDBTN_DISPLAY;
  758. m_aDlgItems[i].m_accelkey = (CHAR)GetAcceleratorKey(m_aDlgItems[i].m_hWnd);
  759. m_aDlgItems[i].m_Type = ItemInfo::Button;
  760. /*
  761. m_aDlgItems[i].m_bIgnoreEnabled = TRUE ;
  762. //m_aDlgItems[i].m_bEnabled; // Is the control enabled?
  763. m_aDlgItems[i].m_bIgnoreMax = TRUE ; // Ignore the Max parameter.
  764. m_aDlgItems[i].m_bGrowH = FALSE; // Grow Horizontally.
  765. m_aDlgItems[i].m_bGrowV = FALSE ; // Grow Vertically.
  766. m_aDlgItems[i].m_JustifyV = Justify::Top; // Do we stick to the top or the bottom.
  767. //m_aDlgItems[i].m_iOffsetV = ; // Distance from our justification point.
  768. m_aDlgItems[i].m_JustifyH = Justify::Right; // Do we stick to the right or the left
  769. m_aDlgItems[i].m_iOffsetH = rectDlg.right - rectCurrent.left;
  770. //m_aDlgItems[i].m_iPadH = ; // Right Horizontal Padding.
  771. //m_aDlgItems[i].m_iPadV = ; // Bottom Vertical Padding.
  772. m_aDlgItems[i].m_rectMin = rectCurrent;
  773. m_aDlgItems[i].m_rectCur = rectCurrent;
  774. //m_aDlgItems[i].m_rectMax ; // Max size.
  775. */
  776. }