2 * Help Viewer Implementation
4 * Copyright 2005 James Hawkins
5 * Copyright 2007 Jacek Caban for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(htmlhelp);
34 static LRESULT Help_OnSize(HWND hWnd);
36 /* Window type defaults */
38 #define WINTYPE_DEFAULT_X 280
39 #define WINTYPE_DEFAULT_Y 100
40 #define WINTYPE_DEFAULT_WIDTH 740
41 #define WINTYPE_DEFAULT_HEIGHT 640
42 #define WINTYPE_DEFAULT_NAVWIDTH 250
44 #define TAB_TOP_PADDING 8
45 #define TAB_RIGHT_PADDING 4
48 static const WCHAR szEmpty[] = {0};
50 /* Loads a string from the resource file */
51 static LPWSTR HH_LoadString(DWORD dwID)
56 iSize = LoadStringW(hhctrl_hinstance, dwID, NULL, 0);
57 iSize += 2; /* some strings (tab text) needs double-null termination */
59 string = heap_alloc(iSize * sizeof(WCHAR));
60 LoadStringW(hhctrl_hinstance, dwID, string, iSize);
65 static HRESULT navigate_url(HHInfo *info, LPCWSTR surl)
70 TRACE("%s\n", debugstr_w(surl));
73 V_BSTR(&url) = SysAllocString(surl);
75 hres = IWebBrowser2_Navigate2(info->web_browser, &url, 0, 0, 0, 0);
80 TRACE("Navigation failed: %08x\n", hres);
85 BOOL NavigateToUrl(HHInfo *info, LPCWSTR surl)
91 hres = navigate_url(info, surl);
95 SetChmPath(&chm_path, info->pCHMInfo->szFile, surl);
96 ret = NavigateToChm(info, chm_path.chm_file, chm_path.chm_index);
98 heap_free(chm_path.chm_file);
99 heap_free(chm_path.chm_index);
104 BOOL NavigateToChm(HHInfo *info, LPCWSTR file, LPCWSTR index)
106 WCHAR buf[INTERNET_MAX_URL_LENGTH];
107 WCHAR full_path[MAX_PATH];
110 static const WCHAR url_format[] =
111 {'m','k',':','@','M','S','I','T','S','t','o','r','e',':','%','s',':',':','%','s',0};
113 TRACE("%p %s %s\n", info, debugstr_w(file), debugstr_w(index));
115 if (!info->web_browser)
118 if(!GetFullPathNameW(file, sizeof(full_path)/sizeof(full_path[0]), full_path, NULL)) {
119 WARN("GetFullPathName failed: %u\n", GetLastError());
123 wsprintfW(buf, url_format, full_path, index);
126 if((ptr = strchrW(buf, '#')))
129 return SUCCEEDED(navigate_url(info, buf));
134 #define SIZEBAR_WIDTH 4
136 static const WCHAR szSizeBarClass[] = {
137 'H','H',' ','S','i','z','e','B','a','r',0
140 /* Draw the SizeBar */
141 static void SB_OnPaint(HWND hWnd)
147 hdc = BeginPaint(hWnd, &ps);
149 GetClientRect(hWnd, &rc);
154 FrameRect(hdc, &rc, GetStockObject(GRAY_BRUSH));
156 /* white highlight */
157 SelectObject(hdc, GetStockObject(WHITE_PEN));
158 MoveToEx(hdc, rc.right, 1, NULL);
160 LineTo(hdc, 1, rc.bottom - 1);
163 MoveToEx(hdc, 0, rc.bottom, NULL);
164 LineTo(hdc, rc.right, rc.bottom);
169 static void SB_OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
174 static void SB_OnLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam)
176 HHInfo *pHHInfo = (HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
179 pt.x = (short)LOWORD(lParam);
180 pt.y = (short)HIWORD(lParam);
182 /* update the window sizes */
183 pHHInfo->WinType.iNavWidth += pt.x;
189 static void SB_OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
191 /* ignore WM_MOUSEMOVE if not dragging the SizeBar */
192 if (!(wParam & MK_LBUTTON))
196 static LRESULT CALLBACK SizeBar_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
201 SB_OnLButtonDown(hWnd, wParam, lParam);
204 SB_OnLButtonUp(hWnd, wParam, lParam);
207 SB_OnMouseMove(hWnd, wParam, lParam);
213 return DefWindowProcW(hWnd, message, wParam, lParam);
219 static void HH_RegisterSizeBarClass(HHInfo *pHHInfo)
223 wcex.cbSize = sizeof(WNDCLASSEXW);
225 wcex.lpfnWndProc = SizeBar_WndProc;
228 wcex.hInstance = hhctrl_hinstance;
229 wcex.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
230 wcex.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_SIZEWE);
231 wcex.hbrBackground = (HBRUSH)(COLOR_MENU + 1);
232 wcex.lpszMenuName = NULL;
233 wcex.lpszClassName = szSizeBarClass;
234 wcex.hIconSm = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
236 RegisterClassExW(&wcex);
239 static void SB_GetSizeBarRect(HHInfo *info, RECT *rc)
241 RECT rectWND, rectTB, rectNP;
243 GetClientRect(info->WinType.hwndHelp, &rectWND);
244 GetClientRect(info->WinType.hwndToolBar, &rectTB);
245 GetClientRect(info->WinType.hwndNavigation, &rectNP);
247 rc->left = rectNP.right;
248 rc->top = rectTB.bottom;
249 rc->bottom = rectWND.bottom - rectTB.bottom;
250 rc->right = SIZEBAR_WIDTH;
253 static BOOL HH_AddSizeBar(HHInfo *pHHInfo)
256 HWND hwndParent = pHHInfo->WinType.hwndHelp;
257 DWORD dwStyles = WS_CHILDWINDOW | WS_VISIBLE | WS_OVERLAPPED;
258 DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
261 SB_GetSizeBarRect(pHHInfo, &rc);
263 hWnd = CreateWindowExW(dwExStyles, szSizeBarClass, szEmpty, dwStyles,
264 rc.left, rc.top, rc.right, rc.bottom,
265 hwndParent, NULL, hhctrl_hinstance, NULL);
269 /* store the pointer to the HH info struct */
270 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)pHHInfo);
272 pHHInfo->hwndSizeBar = hWnd;
278 static const WCHAR szChildClass[] = {
279 'H','H',' ','C','h','i','l','d',0
282 static LRESULT Child_OnPaint(HWND hWnd)
288 hdc = BeginPaint(hWnd, &ps);
290 /* Only paint the Navigation pane, identified by the fact
291 * that it has a child window
293 if (GetWindow(hWnd, GW_CHILD))
295 GetClientRect(hWnd, &rc);
297 /* set the border color */
298 SelectObject(hdc, GetStockObject(DC_PEN));
299 SetDCPenColor(hdc, GetSysColor(COLOR_BTNSHADOW));
301 /* Draw the top border */
302 LineTo(hdc, rc.right, 0);
304 SelectObject(hdc, GetStockObject(WHITE_PEN));
305 MoveToEx(hdc, 0, 1, NULL);
306 LineTo(hdc, rc.right, 1);
314 static void ResizeTabChild(HHInfo *info, HWND hwnd)
319 GetClientRect(info->WinType.hwndNavigation, &rect);
320 SendMessageW(info->hwndTabCtrl, TCM_GETITEMRECT, 0, (LPARAM)&tabrc);
321 cnt = SendMessageW(info->hwndTabCtrl, TCM_GETROWCOUNT, 0, 0);
323 rect.left = TAB_MARGIN;
324 rect.top = TAB_TOP_PADDING + cnt*(tabrc.bottom-tabrc.top) + TAB_MARGIN;
325 rect.right -= TAB_RIGHT_PADDING + TAB_MARGIN;
326 rect.bottom -= TAB_MARGIN;
328 SetWindowPos(hwnd, NULL, rect.left, rect.top, rect.right-rect.left,
329 rect.bottom-rect.top, SWP_NOZORDER | SWP_NOACTIVATE);
332 static LRESULT Child_OnSize(HWND hwnd)
334 HHInfo *info = (HHInfo*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
337 if(!info || hwnd != info->WinType.hwndNavigation)
340 GetClientRect(hwnd, &rect);
341 SetWindowPos(info->hwndTabCtrl, HWND_TOP, 0, 0,
342 rect.right - TAB_RIGHT_PADDING,
343 rect.bottom - TAB_TOP_PADDING, SWP_NOMOVE);
345 ResizeTabChild(info, info->tabs[TAB_CONTENTS].hwnd);
349 static LRESULT OnTabChange(HWND hwnd)
351 HHInfo *info = (HHInfo*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
358 if(info->tabs[info->current_tab].hwnd)
359 ShowWindow(info->tabs[info->current_tab].hwnd, SW_HIDE);
361 info->current_tab = SendMessageW(info->hwndTabCtrl, TCM_GETCURSEL, 0, 0);
363 if(info->tabs[info->current_tab].hwnd)
364 ShowWindow(info->tabs[info->current_tab].hwnd, SW_SHOW);
369 static LRESULT OnTopicChange(HWND hwnd, ContentItem *item)
371 HHInfo *info = (HHInfo*)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
372 LPCWSTR chmfile = NULL;
373 ContentItem *iter = item;
378 TRACE("name %s loal %s\n", debugstr_w(item->name), debugstr_w(item->local));
381 if(iter->merge.chm_file) {
382 chmfile = iter->merge.chm_file;
388 NavigateToChm(info, chmfile, item->local);
392 static LRESULT CALLBACK Child_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
397 return Child_OnPaint(hWnd);
399 return Child_OnSize(hWnd);
401 NMHDR *nmhdr = (NMHDR*)lParam;
402 switch(nmhdr->code) {
404 return OnTabChange(hWnd);
405 case TVN_SELCHANGEDW:
406 return OnTopicChange(hWnd, (ContentItem*)((NMTREEVIEWW *)lParam)->itemNew.lParam);
411 return DefWindowProcW(hWnd, message, wParam, lParam);
417 static void HH_RegisterChildWndClass(HHInfo *pHHInfo)
421 wcex.cbSize = sizeof(WNDCLASSEXW);
423 wcex.lpfnWndProc = Child_WndProc;
426 wcex.hInstance = hhctrl_hinstance;
427 wcex.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
428 wcex.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
429 wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
430 wcex.lpszMenuName = NULL;
431 wcex.lpszClassName = szChildClass;
432 wcex.hIconSm = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
434 RegisterClassExW(&wcex);
441 static void TB_OnClick(HWND hWnd, DWORD dwID)
443 HHInfo *info = (HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
448 DoPageAction(info, WB_STOP);
451 DoPageAction(info, WB_REFRESH);
454 DoPageAction(info, WB_GOBACK);
457 NavigateToChm(info, info->pCHMInfo->szFile, info->WinType.pszHome);
460 DoPageAction(info, WB_GOFORWARD);
467 case IDTB_BROWSE_FWD:
468 case IDTB_BROWSE_BACK:
479 static void TB_AddButton(TBBUTTON *pButtons, DWORD dwIndex, DWORD dwID)
481 /* FIXME: Load the correct button bitmaps */
482 pButtons[dwIndex].iBitmap = STD_PRINT;
483 pButtons[dwIndex].idCommand = dwID;
484 pButtons[dwIndex].fsState = TBSTATE_ENABLED;
485 pButtons[dwIndex].fsStyle = BTNS_BUTTON;
486 pButtons[dwIndex].dwData = 0;
487 pButtons[dwIndex].iString = 0;
490 static void TB_AddButtonsFromFlags(TBBUTTON *pButtons, DWORD dwButtonFlags, LPDWORD pdwNumButtons)
494 if (dwButtonFlags & HHWIN_BUTTON_EXPAND)
495 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_EXPAND);
497 if (dwButtonFlags & HHWIN_BUTTON_BACK)
498 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_BACK);
500 if (dwButtonFlags & HHWIN_BUTTON_FORWARD)
501 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_FORWARD);
503 if (dwButtonFlags & HHWIN_BUTTON_STOP)
504 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_STOP);
506 if (dwButtonFlags & HHWIN_BUTTON_REFRESH)
507 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_REFRESH);
509 if (dwButtonFlags & HHWIN_BUTTON_HOME)
510 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_HOME);
512 if (dwButtonFlags & HHWIN_BUTTON_SYNC)
513 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_SYNC);
515 if (dwButtonFlags & HHWIN_BUTTON_OPTIONS)
516 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_OPTIONS);
518 if (dwButtonFlags & HHWIN_BUTTON_PRINT)
519 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_PRINT);
521 if (dwButtonFlags & HHWIN_BUTTON_JUMP1)
522 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_JUMP1);
524 if (dwButtonFlags & HHWIN_BUTTON_JUMP2)
525 TB_AddButton(pButtons,(*pdwNumButtons)++, IDTB_JUMP2);
527 if (dwButtonFlags & HHWIN_BUTTON_ZOOM)
528 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_ZOOM);
530 if (dwButtonFlags & HHWIN_BUTTON_TOC_NEXT)
531 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_TOC_NEXT);
533 if (dwButtonFlags & HHWIN_BUTTON_TOC_PREV)
534 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_TOC_PREV);
537 static BOOL HH_AddToolbar(HHInfo *pHHInfo)
540 HWND hwndParent = pHHInfo->WinType.hwndHelp;
542 TBBUTTON buttons[IDTB_TOC_PREV - IDTB_EXPAND];
544 DWORD dwStyles, dwExStyles;
545 DWORD dwNumButtons, dwIndex;
547 if (pHHInfo->WinType.fsWinProperties & HHWIN_PARAM_TB_FLAGS)
548 toolbarFlags = pHHInfo->WinType.fsToolBarFlags;
550 toolbarFlags = HHWIN_DEF_BUTTONS;
552 TB_AddButtonsFromFlags(buttons, toolbarFlags, &dwNumButtons);
554 dwStyles = WS_CHILDWINDOW | WS_VISIBLE | TBSTYLE_FLAT |
555 TBSTYLE_WRAPABLE | TBSTYLE_TOOLTIPS | CCS_NODIVIDER;
556 dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
558 hToolbar = CreateWindowExW(dwExStyles, TOOLBARCLASSNAMEW, NULL, dwStyles,
559 0, 0, 0, 0, hwndParent, NULL,
560 hhctrl_hinstance, NULL);
564 SendMessageW(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(ICON_SIZE, ICON_SIZE));
565 SendMessageW(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
566 SendMessageW(hToolbar, WM_SETFONT, (WPARAM)pHHInfo->hFont, TRUE);
568 /* FIXME: Load correct icons for all buttons */
569 tbAB.hInst = HINST_COMMCTRL;
570 tbAB.nID = IDB_STD_LARGE_COLOR;
571 SendMessageW(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbAB);
573 for (dwIndex = 0; dwIndex < dwNumButtons; dwIndex++)
575 LPWSTR szBuf = HH_LoadString(buttons[dwIndex].idCommand);
576 DWORD dwLen = strlenW(szBuf);
577 szBuf[dwLen + 2] = 0; /* Double-null terminate */
579 buttons[dwIndex].iString = (DWORD)SendMessageW(hToolbar, TB_ADDSTRINGW, 0, (LPARAM)szBuf);
583 SendMessageW(hToolbar, TB_ADDBUTTONSW, dwNumButtons, (LPARAM)&buttons);
584 SendMessageW(hToolbar, TB_AUTOSIZE, 0, 0);
585 ShowWindow(hToolbar, SW_SHOW);
587 pHHInfo->WinType.hwndToolBar = hToolbar;
591 /* Navigation Pane */
593 static void NP_GetNavigationRect(HHInfo *pHHInfo, RECT *rc)
595 HWND hwndParent = pHHInfo->WinType.hwndHelp;
596 HWND hwndToolbar = pHHInfo->WinType.hwndToolBar;
597 RECT rectWND, rectTB;
599 GetClientRect(hwndParent, &rectWND);
600 GetClientRect(hwndToolbar, &rectTB);
603 rc->top = rectTB.bottom;
604 rc->bottom = rectWND.bottom - rectTB.bottom;
606 if (!(pHHInfo->WinType.fsValidMembers & HHWIN_PARAM_NAV_WIDTH) &&
607 pHHInfo->WinType.iNavWidth == 0)
609 pHHInfo->WinType.iNavWidth = WINTYPE_DEFAULT_NAVWIDTH;
612 rc->right = pHHInfo->WinType.iNavWidth;
615 static DWORD NP_CreateTab(HINSTANCE hInstance, HWND hwndTabCtrl, DWORD index)
618 LPWSTR tabText = HH_LoadString(index);
621 tie.mask = TCIF_TEXT;
622 tie.pszText = tabText;
624 ret = SendMessageW( hwndTabCtrl, TCM_INSERTITEMW, index, (LPARAM)&tie );
630 static BOOL HH_AddNavigationPane(HHInfo *info)
632 HWND hWnd, hwndTabCtrl;
633 HWND hwndParent = info->WinType.hwndHelp;
634 DWORD dwStyles = WS_CHILDWINDOW | WS_VISIBLE;
635 DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
638 NP_GetNavigationRect(info, &rc);
640 hWnd = CreateWindowExW(dwExStyles, szChildClass, szEmpty, dwStyles,
641 rc.left, rc.top, rc.right, rc.bottom,
642 hwndParent, NULL, hhctrl_hinstance, NULL);
646 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)info);
648 hwndTabCtrl = CreateWindowExW(dwExStyles, WC_TABCONTROLW, szEmpty, dwStyles,
650 rc.right - TAB_RIGHT_PADDING,
651 rc.bottom - TAB_TOP_PADDING,
652 hWnd, NULL, hhctrl_hinstance, NULL);
656 if (*info->WinType.pszToc)
657 info->tabs[TAB_CONTENTS].id = NP_CreateTab(hhctrl_hinstance, hwndTabCtrl, IDS_CONTENTS);
659 if (*info->WinType.pszIndex)
660 info->tabs[TAB_INDEX].id = NP_CreateTab(hhctrl_hinstance, hwndTabCtrl, IDS_INDEX);
662 if (info->WinType.fsWinProperties & HHWIN_PROP_TAB_SEARCH)
663 info->tabs[TAB_SEARCH].id = NP_CreateTab(hhctrl_hinstance, hwndTabCtrl, IDS_SEARCH);
665 if (info->WinType.fsWinProperties & HHWIN_PROP_TAB_FAVORITES)
666 info->tabs[TAB_FAVORITES].id = NP_CreateTab(hhctrl_hinstance, hwndTabCtrl, IDS_FAVORITES);
668 SendMessageW(hwndTabCtrl, WM_SETFONT, (WPARAM)info->hFont, TRUE);
670 info->hwndTabCtrl = hwndTabCtrl;
671 info->WinType.hwndNavigation = hWnd;
677 static void HP_GetHTMLRect(HHInfo *info, RECT *rc)
679 RECT rectTB, rectWND, rectNP, rectSB;
681 GetClientRect(info->WinType.hwndHelp, &rectWND);
682 GetClientRect(info->WinType.hwndToolBar, &rectTB);
683 GetClientRect(info->WinType.hwndNavigation, &rectNP);
684 GetClientRect(info->hwndSizeBar, &rectSB);
686 rc->left = rectNP.right + rectSB.right;
687 rc->top = rectTB.bottom;
688 rc->right = rectWND.right - rc->left;
689 rc->bottom = rectWND.bottom - rectTB.bottom;
692 static BOOL HH_AddHTMLPane(HHInfo *pHHInfo)
695 HWND hwndParent = pHHInfo->WinType.hwndHelp;
696 DWORD dwStyles = WS_CHILDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN;
697 DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_CLIENTEDGE;
700 HP_GetHTMLRect(pHHInfo, &rc);
702 hWnd = CreateWindowExW(dwExStyles, szChildClass, szEmpty, dwStyles,
703 rc.left, rc.top, rc.right, rc.bottom,
704 hwndParent, NULL, hhctrl_hinstance, NULL);
708 if (!InitWebBrowser(pHHInfo, hWnd))
711 /* store the pointer to the HH info struct */
712 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)pHHInfo);
714 ShowWindow(hWnd, SW_SHOW);
717 pHHInfo->WinType.hwndHTML = hWnd;
721 static BOOL AddContentTab(HHInfo *info)
723 info->tabs[TAB_CONTENTS].hwnd = CreateWindowExW(WS_EX_CLIENTEDGE, WC_TREEVIEWW,
724 szEmpty, WS_CHILD | WS_BORDER | 0x25, 50, 50, 100, 100,
725 info->WinType.hwndNavigation, NULL, hhctrl_hinstance, NULL);
726 if(!info->tabs[TAB_CONTENTS].hwnd) {
727 ERR("Could not create treeview control\n");
731 ResizeTabChild(info, info->tabs[TAB_CONTENTS].hwnd);
732 ShowWindow(info->tabs[TAB_CONTENTS].hwnd, SW_SHOW);
739 static LRESULT Help_OnSize(HWND hWnd)
741 HHInfo *pHHInfo = (HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
748 NP_GetNavigationRect(pHHInfo, &rc);
749 SetWindowPos(pHHInfo->WinType.hwndNavigation, HWND_TOP, 0, 0,
750 rc.right, rc.bottom, SWP_NOMOVE);
752 SB_GetSizeBarRect(pHHInfo, &rc);
753 SetWindowPos(pHHInfo->hwndSizeBar, HWND_TOP, rc.left, rc.top,
754 rc.right, rc.bottom, SWP_SHOWWINDOW);
756 HP_GetHTMLRect(pHHInfo, &rc);
757 SetWindowPos(pHHInfo->WinType.hwndHTML, HWND_TOP, rc.left, rc.top,
758 rc.right, rc.bottom, SWP_SHOWWINDOW);
760 /* Resize browser window taking the frame size into account */
761 dwSize = GetSystemMetrics(SM_CXFRAME);
762 ResizeWebBrowser(pHHInfo, rc.right - dwSize, rc.bottom - dwSize);
767 static LRESULT CALLBACK Help_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
772 if (HIWORD(wParam) == BN_CLICKED)
773 TB_OnClick(hWnd, LOWORD(wParam));
776 return Help_OnSize(hWnd);
778 ReleaseHelpViewer((HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA));
786 return DefWindowProcW(hWnd, message, wParam, lParam);
792 static BOOL HH_CreateHelpWindow(HHInfo *info)
795 RECT winPos = info->WinType.rcWindowPos;
797 DWORD dwStyles, dwExStyles;
798 DWORD x, y, width, height;
800 static const WCHAR windowClassW[] = {
801 'H','H',' ', 'P','a','r','e','n','t',0
804 wcex.cbSize = sizeof(WNDCLASSEXW);
805 wcex.style = CS_HREDRAW | CS_VREDRAW;
806 wcex.lpfnWndProc = Help_WndProc;
809 wcex.hInstance = hhctrl_hinstance;
810 wcex.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
811 wcex.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
812 wcex.hbrBackground = (HBRUSH)(COLOR_MENU + 1);
813 wcex.lpszMenuName = NULL;
814 wcex.lpszClassName = windowClassW;
815 wcex.hIconSm = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION);
817 RegisterClassExW(&wcex);
819 /* Read in window parameters if available */
820 if (info->WinType.fsValidMembers & HHWIN_PARAM_STYLES)
821 dwStyles = info->WinType.dwStyles;
823 dwStyles = WS_OVERLAPPEDWINDOW | WS_VISIBLE |
824 WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
826 if (info->WinType.fsValidMembers & HHWIN_PARAM_EXSTYLES)
827 dwExStyles = info->WinType.dwExStyles;
829 dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_APPWINDOW |
830 WS_EX_WINDOWEDGE | WS_EX_RIGHTSCROLLBAR;
832 if (info->WinType.fsValidMembers & HHWIN_PARAM_RECT)
836 width = winPos.right - x;
837 height = winPos.bottom - y;
841 x = WINTYPE_DEFAULT_X;
842 y = WINTYPE_DEFAULT_Y;
843 width = WINTYPE_DEFAULT_WIDTH;
844 height = WINTYPE_DEFAULT_HEIGHT;
847 hWnd = CreateWindowExW(dwExStyles, windowClassW, info->WinType.pszCaption,
848 dwStyles, x, y, width, height, NULL, NULL, hhctrl_hinstance, NULL);
852 ShowWindow(hWnd, SW_SHOW);
855 /* store the pointer to the HH info struct */
856 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)info);
858 info->WinType.hwndHelp = hWnd;
862 static void HH_CreateFont(HHInfo *pHHInfo)
866 GetObjectW(GetStockObject(ANSI_VAR_FONT), sizeof(LOGFONTW), &lf);
867 lf.lfWeight = FW_NORMAL;
869 lf.lfUnderline = FALSE;
871 pHHInfo->hFont = CreateFontIndirectW(&lf);
874 static void HH_InitRequiredControls(DWORD dwControls)
876 INITCOMMONCONTROLSEX icex;
878 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
879 icex.dwICC = dwControls;
880 InitCommonControlsEx(&icex);
883 /* Creates the whole package */
884 static BOOL CreateViewer(HHInfo *pHHInfo)
886 HH_CreateFont(pHHInfo);
888 if (!HH_CreateHelpWindow(pHHInfo))
891 HH_InitRequiredControls(ICC_BAR_CLASSES);
893 if (!HH_AddToolbar(pHHInfo))
896 HH_RegisterChildWndClass(pHHInfo);
898 if (!HH_AddNavigationPane(pHHInfo))
901 HH_RegisterSizeBarClass(pHHInfo);
903 if (!HH_AddSizeBar(pHHInfo))
906 if (!HH_AddHTMLPane(pHHInfo))
909 if (!AddContentTab(pHHInfo))
912 InitContent(pHHInfo);
917 void ReleaseHelpViewer(HHInfo *info)
919 TRACE("(%p)\n", info);
924 /* Free allocated strings */
925 heap_free(info->pszType);
926 heap_free(info->pszCaption);
927 heap_free(info->pszToc);
928 heap_free(info->pszIndex);
929 heap_free(info->pszFile);
930 heap_free(info->pszHome);
931 heap_free(info->pszJump1);
932 heap_free(info->pszJump2);
933 heap_free(info->pszUrlJump1);
934 heap_free(info->pszUrlJump2);
937 CloseCHM(info->pCHMInfo);
939 ReleaseWebBrowser(info);
940 ReleaseContent(info);
942 if(info->WinType.hwndHelp)
943 DestroyWindow(info->WinType.hwndHelp);
949 HHInfo *CreateHelpViewer(LPCWSTR filename)
951 HHInfo *info = heap_alloc_zero(sizeof(HHInfo));
955 info->pCHMInfo = OpenCHM(filename);
956 if(!info->pCHMInfo) {
957 ReleaseHelpViewer(info);
961 if (!LoadWinTypeFromCHM(info)) {
962 ReleaseHelpViewer(info);
966 if(!CreateViewer(info)) {
967 ReleaseHelpViewer(info);