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
)
54 LPCWSTR stringresource
;
57 iSize
= LoadStringW(hhctrl_hinstance
, dwID
, (LPWSTR
)&stringresource
, 0);
59 string
= heap_alloc((iSize
+ 2) * sizeof(WCHAR
)); /* some strings (tab text) needs double-null termination */
60 memcpy(string
, stringresource
, iSize
*sizeof(WCHAR
));
66 static HRESULT
navigate_url(HHInfo
*info
, LPCWSTR surl
)
71 TRACE("%s\n", debugstr_w(surl
));
74 V_BSTR(&url
) = SysAllocString(surl
);
76 hres
= IWebBrowser2_Navigate2(info
->web_browser
, &url
, 0, 0, 0, 0);
81 TRACE("Navigation failed: %08x\n", hres
);
86 BOOL
NavigateToUrl(HHInfo
*info
, LPCWSTR surl
)
92 static const WCHAR url_indicator
[] = {':', '/', '/', 0};
94 TRACE("%s\n", debugstr_w(surl
));
96 if (strstrW(surl
, url_indicator
)) {
97 hres
= navigate_url(info
, surl
);
100 } /* look up in chm if it doesn't look like a full url */
102 SetChmPath(&chm_path
, info
->pCHMInfo
->szFile
, surl
);
103 ret
= NavigateToChm(info
, chm_path
.chm_file
, chm_path
.chm_index
);
105 heap_free(chm_path
.chm_file
);
106 heap_free(chm_path
.chm_index
);
111 BOOL
NavigateToChm(HHInfo
*info
, LPCWSTR file
, LPCWSTR index
)
113 WCHAR buf
[INTERNET_MAX_URL_LENGTH
];
114 WCHAR full_path
[MAX_PATH
];
117 static const WCHAR url_format
[] =
118 {'m','k',':','@','M','S','I','T','S','t','o','r','e',':','%','s',':',':','%','s',0};
120 TRACE("%p %s %s\n", info
, debugstr_w(file
), debugstr_w(index
));
122 if (!info
->web_browser
)
125 if(!GetFullPathNameW(file
, sizeof(full_path
)/sizeof(full_path
[0]), full_path
, NULL
)) {
126 WARN("GetFullPathName failed: %u\n", GetLastError());
130 wsprintfW(buf
, url_format
, full_path
, index
);
133 if((ptr
= strchrW(buf
, '#')))
136 return SUCCEEDED(navigate_url(info
, buf
));
141 #define SIZEBAR_WIDTH 4
143 static const WCHAR szSizeBarClass
[] = {
144 'H','H',' ','S','i','z','e','B','a','r',0
147 /* Draw the SizeBar */
148 static void SB_OnPaint(HWND hWnd
)
154 hdc
= BeginPaint(hWnd
, &ps
);
156 GetClientRect(hWnd
, &rc
);
161 FrameRect(hdc
, &rc
, GetStockObject(GRAY_BRUSH
));
163 /* white highlight */
164 SelectObject(hdc
, GetStockObject(WHITE_PEN
));
165 MoveToEx(hdc
, rc
.right
, 1, NULL
);
167 LineTo(hdc
, 1, rc
.bottom
- 1);
170 MoveToEx(hdc
, 0, rc
.bottom
, NULL
);
171 LineTo(hdc
, rc
.right
, rc
.bottom
);
176 static void SB_OnLButtonDown(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
181 static void SB_OnLButtonUp(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
183 HHInfo
*pHHInfo
= (HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
186 pt
.x
= (short)LOWORD(lParam
);
187 pt
.y
= (short)HIWORD(lParam
);
189 /* update the window sizes */
190 pHHInfo
->WinType
.iNavWidth
+= pt
.x
;
196 static void SB_OnMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
198 /* ignore WM_MOUSEMOVE if not dragging the SizeBar */
199 if (!(wParam
& MK_LBUTTON
))
203 static LRESULT CALLBACK
SizeBar_WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
208 SB_OnLButtonDown(hWnd
, wParam
, lParam
);
211 SB_OnLButtonUp(hWnd
, wParam
, lParam
);
214 SB_OnMouseMove(hWnd
, wParam
, lParam
);
220 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
226 static void HH_RegisterSizeBarClass(HHInfo
*pHHInfo
)
230 wcex
.cbSize
= sizeof(WNDCLASSEXW
);
232 wcex
.lpfnWndProc
= SizeBar_WndProc
;
235 wcex
.hInstance
= hhctrl_hinstance
;
236 wcex
.hIcon
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
237 wcex
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
)IDC_SIZEWE
);
238 wcex
.hbrBackground
= (HBRUSH
)(COLOR_MENU
+ 1);
239 wcex
.lpszMenuName
= NULL
;
240 wcex
.lpszClassName
= szSizeBarClass
;
241 wcex
.hIconSm
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
243 RegisterClassExW(&wcex
);
246 static void SB_GetSizeBarRect(HHInfo
*info
, RECT
*rc
)
248 RECT rectWND
, rectTB
, rectNP
;
250 GetClientRect(info
->WinType
.hwndHelp
, &rectWND
);
251 GetClientRect(info
->WinType
.hwndToolBar
, &rectTB
);
252 GetClientRect(info
->WinType
.hwndNavigation
, &rectNP
);
254 rc
->left
= rectNP
.right
;
255 rc
->top
= rectTB
.bottom
;
256 rc
->bottom
= rectWND
.bottom
- rectTB
.bottom
;
257 rc
->right
= SIZEBAR_WIDTH
;
260 static BOOL
HH_AddSizeBar(HHInfo
*pHHInfo
)
263 HWND hwndParent
= pHHInfo
->WinType
.hwndHelp
;
264 DWORD dwStyles
= WS_CHILDWINDOW
| WS_VISIBLE
| WS_OVERLAPPED
;
265 DWORD dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
;
268 SB_GetSizeBarRect(pHHInfo
, &rc
);
270 hWnd
= CreateWindowExW(dwExStyles
, szSizeBarClass
, szEmpty
, dwStyles
,
271 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
272 hwndParent
, NULL
, hhctrl_hinstance
, NULL
);
276 /* store the pointer to the HH info struct */
277 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (LONG_PTR
)pHHInfo
);
279 pHHInfo
->hwndSizeBar
= hWnd
;
285 static const WCHAR szChildClass
[] = {
286 'H','H',' ','C','h','i','l','d',0
289 static LRESULT
Child_OnPaint(HWND hWnd
)
295 hdc
= BeginPaint(hWnd
, &ps
);
297 /* Only paint the Navigation pane, identified by the fact
298 * that it has a child window
300 if (GetWindow(hWnd
, GW_CHILD
))
302 GetClientRect(hWnd
, &rc
);
304 /* set the border color */
305 SelectObject(hdc
, GetStockObject(DC_PEN
));
306 SetDCPenColor(hdc
, GetSysColor(COLOR_BTNSHADOW
));
308 /* Draw the top border */
309 LineTo(hdc
, rc
.right
, 0);
311 SelectObject(hdc
, GetStockObject(WHITE_PEN
));
312 MoveToEx(hdc
, 0, 1, NULL
);
313 LineTo(hdc
, rc
.right
, 1);
321 static void ResizeTabChild(HHInfo
*info
, HWND hwnd
)
326 GetClientRect(info
->WinType
.hwndNavigation
, &rect
);
327 SendMessageW(info
->hwndTabCtrl
, TCM_GETITEMRECT
, 0, (LPARAM
)&tabrc
);
328 cnt
= SendMessageW(info
->hwndTabCtrl
, TCM_GETROWCOUNT
, 0, 0);
330 rect
.left
= TAB_MARGIN
;
331 rect
.top
= TAB_TOP_PADDING
+ cnt
*(tabrc
.bottom
-tabrc
.top
) + TAB_MARGIN
;
332 rect
.right
-= TAB_RIGHT_PADDING
+ TAB_MARGIN
;
333 rect
.bottom
-= TAB_MARGIN
;
335 SetWindowPos(hwnd
, NULL
, rect
.left
, rect
.top
, rect
.right
-rect
.left
,
336 rect
.bottom
-rect
.top
, SWP_NOZORDER
| SWP_NOACTIVATE
);
339 static LRESULT
Child_OnSize(HWND hwnd
)
341 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
344 if(!info
|| hwnd
!= info
->WinType
.hwndNavigation
)
347 GetClientRect(hwnd
, &rect
);
348 SetWindowPos(info
->hwndTabCtrl
, HWND_TOP
, 0, 0,
349 rect
.right
- TAB_RIGHT_PADDING
,
350 rect
.bottom
- TAB_TOP_PADDING
, SWP_NOMOVE
);
352 ResizeTabChild(info
, info
->tabs
[TAB_CONTENTS
].hwnd
);
356 static LRESULT
OnTabChange(HWND hwnd
)
358 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
365 if(info
->tabs
[info
->current_tab
].hwnd
)
366 ShowWindow(info
->tabs
[info
->current_tab
].hwnd
, SW_HIDE
);
368 info
->current_tab
= SendMessageW(info
->hwndTabCtrl
, TCM_GETCURSEL
, 0, 0);
370 if(info
->tabs
[info
->current_tab
].hwnd
)
371 ShowWindow(info
->tabs
[info
->current_tab
].hwnd
, SW_SHOW
);
376 static LRESULT
OnTopicChange(HWND hwnd
, ContentItem
*item
)
378 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
379 LPCWSTR chmfile
= NULL
;
380 ContentItem
*iter
= item
;
385 TRACE("name %s loal %s\n", debugstr_w(item
->name
), debugstr_w(item
->local
));
388 if(iter
->merge
.chm_file
) {
389 chmfile
= iter
->merge
.chm_file
;
395 NavigateToChm(info
, chmfile
, item
->local
);
399 static LRESULT CALLBACK
Child_WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
404 return Child_OnPaint(hWnd
);
406 return Child_OnSize(hWnd
);
408 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
409 switch(nmhdr
->code
) {
411 return OnTabChange(hWnd
);
412 case TVN_SELCHANGEDW
:
413 return OnTopicChange(hWnd
, (ContentItem
*)((NMTREEVIEWW
*)lParam
)->itemNew
.lParam
);
418 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
424 static void HH_RegisterChildWndClass(HHInfo
*pHHInfo
)
428 wcex
.cbSize
= sizeof(WNDCLASSEXW
);
430 wcex
.lpfnWndProc
= Child_WndProc
;
433 wcex
.hInstance
= hhctrl_hinstance
;
434 wcex
.hIcon
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
435 wcex
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
)IDC_ARROW
);
436 wcex
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
437 wcex
.lpszMenuName
= NULL
;
438 wcex
.lpszClassName
= szChildClass
;
439 wcex
.hIconSm
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
441 RegisterClassExW(&wcex
);
448 static void TB_OnClick(HWND hWnd
, DWORD dwID
)
450 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
455 DoPageAction(info
, WB_STOP
);
458 DoPageAction(info
, WB_REFRESH
);
461 DoPageAction(info
, WB_GOBACK
);
464 NavigateToChm(info
, info
->pCHMInfo
->szFile
, info
->WinType
.pszHome
);
467 DoPageAction(info
, WB_GOFORWARD
);
474 case IDTB_BROWSE_FWD
:
475 case IDTB_BROWSE_BACK
:
486 static void TB_AddButton(TBBUTTON
*pButtons
, DWORD dwIndex
, DWORD dwID
)
488 /* FIXME: Load the correct button bitmaps */
489 pButtons
[dwIndex
].iBitmap
= STD_PRINT
;
490 pButtons
[dwIndex
].idCommand
= dwID
;
491 pButtons
[dwIndex
].fsState
= TBSTATE_ENABLED
;
492 pButtons
[dwIndex
].fsStyle
= BTNS_BUTTON
;
493 pButtons
[dwIndex
].dwData
= 0;
494 pButtons
[dwIndex
].iString
= 0;
497 static void TB_AddButtonsFromFlags(TBBUTTON
*pButtons
, DWORD dwButtonFlags
, LPDWORD pdwNumButtons
)
501 if (dwButtonFlags
& HHWIN_BUTTON_EXPAND
)
502 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_EXPAND
);
504 if (dwButtonFlags
& HHWIN_BUTTON_BACK
)
505 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_BACK
);
507 if (dwButtonFlags
& HHWIN_BUTTON_FORWARD
)
508 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_FORWARD
);
510 if (dwButtonFlags
& HHWIN_BUTTON_STOP
)
511 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_STOP
);
513 if (dwButtonFlags
& HHWIN_BUTTON_REFRESH
)
514 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_REFRESH
);
516 if (dwButtonFlags
& HHWIN_BUTTON_HOME
)
517 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_HOME
);
519 if (dwButtonFlags
& HHWIN_BUTTON_SYNC
)
520 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_SYNC
);
522 if (dwButtonFlags
& HHWIN_BUTTON_OPTIONS
)
523 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_OPTIONS
);
525 if (dwButtonFlags
& HHWIN_BUTTON_PRINT
)
526 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_PRINT
);
528 if (dwButtonFlags
& HHWIN_BUTTON_JUMP1
)
529 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_JUMP1
);
531 if (dwButtonFlags
& HHWIN_BUTTON_JUMP2
)
532 TB_AddButton(pButtons
,(*pdwNumButtons
)++, IDTB_JUMP2
);
534 if (dwButtonFlags
& HHWIN_BUTTON_ZOOM
)
535 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_ZOOM
);
537 if (dwButtonFlags
& HHWIN_BUTTON_TOC_NEXT
)
538 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_TOC_NEXT
);
540 if (dwButtonFlags
& HHWIN_BUTTON_TOC_PREV
)
541 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_TOC_PREV
);
544 static BOOL
HH_AddToolbar(HHInfo
*pHHInfo
)
547 HWND hwndParent
= pHHInfo
->WinType
.hwndHelp
;
549 TBBUTTON buttons
[IDTB_TOC_PREV
- IDTB_EXPAND
];
551 DWORD dwStyles
, dwExStyles
;
552 DWORD dwNumButtons
, dwIndex
;
554 if (pHHInfo
->WinType
.fsWinProperties
& HHWIN_PARAM_TB_FLAGS
)
555 toolbarFlags
= pHHInfo
->WinType
.fsToolBarFlags
;
557 toolbarFlags
= HHWIN_DEF_BUTTONS
;
559 TB_AddButtonsFromFlags(buttons
, toolbarFlags
, &dwNumButtons
);
561 dwStyles
= WS_CHILDWINDOW
| WS_VISIBLE
| TBSTYLE_FLAT
|
562 TBSTYLE_WRAPABLE
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
;
563 dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
;
565 hToolbar
= CreateWindowExW(dwExStyles
, TOOLBARCLASSNAMEW
, NULL
, dwStyles
,
566 0, 0, 0, 0, hwndParent
, NULL
,
567 hhctrl_hinstance
, NULL
);
571 SendMessageW(hToolbar
, TB_SETBITMAPSIZE
, 0, MAKELONG(ICON_SIZE
, ICON_SIZE
));
572 SendMessageW(hToolbar
, TB_BUTTONSTRUCTSIZE
, sizeof(TBBUTTON
), 0);
573 SendMessageW(hToolbar
, WM_SETFONT
, (WPARAM
)pHHInfo
->hFont
, TRUE
);
575 /* FIXME: Load correct icons for all buttons */
576 tbAB
.hInst
= HINST_COMMCTRL
;
577 tbAB
.nID
= IDB_STD_LARGE_COLOR
;
578 SendMessageW(hToolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbAB
);
580 for (dwIndex
= 0; dwIndex
< dwNumButtons
; dwIndex
++)
582 LPWSTR szBuf
= HH_LoadString(buttons
[dwIndex
].idCommand
);
583 DWORD dwLen
= strlenW(szBuf
);
584 szBuf
[dwLen
+ 1] = 0; /* Double-null terminate */
586 buttons
[dwIndex
].iString
= (DWORD
)SendMessageW(hToolbar
, TB_ADDSTRINGW
, 0, (LPARAM
)szBuf
);
590 SendMessageW(hToolbar
, TB_ADDBUTTONSW
, dwNumButtons
, (LPARAM
)buttons
);
591 SendMessageW(hToolbar
, TB_AUTOSIZE
, 0, 0);
592 ShowWindow(hToolbar
, SW_SHOW
);
594 pHHInfo
->WinType
.hwndToolBar
= hToolbar
;
598 /* Navigation Pane */
600 static void NP_GetNavigationRect(HHInfo
*pHHInfo
, RECT
*rc
)
602 HWND hwndParent
= pHHInfo
->WinType
.hwndHelp
;
603 HWND hwndToolbar
= pHHInfo
->WinType
.hwndToolBar
;
604 RECT rectWND
, rectTB
;
606 GetClientRect(hwndParent
, &rectWND
);
607 GetClientRect(hwndToolbar
, &rectTB
);
610 rc
->top
= rectTB
.bottom
;
611 rc
->bottom
= rectWND
.bottom
- rectTB
.bottom
;
613 if (!(pHHInfo
->WinType
.fsValidMembers
& HHWIN_PARAM_NAV_WIDTH
) &&
614 pHHInfo
->WinType
.iNavWidth
== 0)
616 pHHInfo
->WinType
.iNavWidth
= WINTYPE_DEFAULT_NAVWIDTH
;
619 rc
->right
= pHHInfo
->WinType
.iNavWidth
;
622 static DWORD
NP_CreateTab(HINSTANCE hInstance
, HWND hwndTabCtrl
, DWORD index
)
625 LPWSTR tabText
= HH_LoadString(index
);
628 tie
.mask
= TCIF_TEXT
;
629 tie
.pszText
= tabText
;
631 ret
= SendMessageW( hwndTabCtrl
, TCM_INSERTITEMW
, index
, (LPARAM
)&tie
);
637 static BOOL
HH_AddNavigationPane(HHInfo
*info
)
639 HWND hWnd
, hwndTabCtrl
;
640 HWND hwndParent
= info
->WinType
.hwndHelp
;
641 DWORD dwStyles
= WS_CHILDWINDOW
| WS_VISIBLE
;
642 DWORD dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
;
645 NP_GetNavigationRect(info
, &rc
);
647 hWnd
= CreateWindowExW(dwExStyles
, szChildClass
, szEmpty
, dwStyles
,
648 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
649 hwndParent
, NULL
, hhctrl_hinstance
, NULL
);
653 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
655 hwndTabCtrl
= CreateWindowExW(dwExStyles
, WC_TABCONTROLW
, szEmpty
, dwStyles
,
657 rc
.right
- TAB_RIGHT_PADDING
,
658 rc
.bottom
- TAB_TOP_PADDING
,
659 hWnd
, NULL
, hhctrl_hinstance
, NULL
);
663 if (*info
->WinType
.pszToc
)
664 info
->tabs
[TAB_CONTENTS
].id
= NP_CreateTab(hhctrl_hinstance
, hwndTabCtrl
, IDS_CONTENTS
);
666 if (*info
->WinType
.pszIndex
)
667 info
->tabs
[TAB_INDEX
].id
= NP_CreateTab(hhctrl_hinstance
, hwndTabCtrl
, IDS_INDEX
);
669 if (info
->WinType
.fsWinProperties
& HHWIN_PROP_TAB_SEARCH
)
670 info
->tabs
[TAB_SEARCH
].id
= NP_CreateTab(hhctrl_hinstance
, hwndTabCtrl
, IDS_SEARCH
);
672 if (info
->WinType
.fsWinProperties
& HHWIN_PROP_TAB_FAVORITES
)
673 info
->tabs
[TAB_FAVORITES
].id
= NP_CreateTab(hhctrl_hinstance
, hwndTabCtrl
, IDS_FAVORITES
);
675 SendMessageW(hwndTabCtrl
, WM_SETFONT
, (WPARAM
)info
->hFont
, TRUE
);
677 info
->hwndTabCtrl
= hwndTabCtrl
;
678 info
->WinType
.hwndNavigation
= hWnd
;
684 static void HP_GetHTMLRect(HHInfo
*info
, RECT
*rc
)
686 RECT rectTB
, rectWND
, rectNP
, rectSB
;
688 GetClientRect(info
->WinType
.hwndHelp
, &rectWND
);
689 GetClientRect(info
->WinType
.hwndToolBar
, &rectTB
);
690 GetClientRect(info
->WinType
.hwndNavigation
, &rectNP
);
691 GetClientRect(info
->hwndSizeBar
, &rectSB
);
693 rc
->left
= rectNP
.right
+ rectSB
.right
;
694 rc
->top
= rectTB
.bottom
;
695 rc
->right
= rectWND
.right
- rc
->left
;
696 rc
->bottom
= rectWND
.bottom
- rectTB
.bottom
;
699 static BOOL
HH_AddHTMLPane(HHInfo
*pHHInfo
)
702 HWND hwndParent
= pHHInfo
->WinType
.hwndHelp
;
703 DWORD dwStyles
= WS_CHILDWINDOW
| WS_VISIBLE
| WS_CLIPCHILDREN
;
704 DWORD dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
| WS_EX_CLIENTEDGE
;
707 HP_GetHTMLRect(pHHInfo
, &rc
);
709 hWnd
= CreateWindowExW(dwExStyles
, szChildClass
, szEmpty
, dwStyles
,
710 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
711 hwndParent
, NULL
, hhctrl_hinstance
, NULL
);
715 if (!InitWebBrowser(pHHInfo
, hWnd
))
718 /* store the pointer to the HH info struct */
719 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (LONG_PTR
)pHHInfo
);
721 ShowWindow(hWnd
, SW_SHOW
);
724 pHHInfo
->WinType
.hwndHTML
= hWnd
;
728 static BOOL
AddContentTab(HHInfo
*info
)
730 info
->tabs
[TAB_CONTENTS
].hwnd
= CreateWindowExW(WS_EX_CLIENTEDGE
, WC_TREEVIEWW
,
731 szEmpty
, WS_CHILD
| WS_BORDER
| 0x25, 50, 50, 100, 100,
732 info
->WinType
.hwndNavigation
, NULL
, hhctrl_hinstance
, NULL
);
733 if(!info
->tabs
[TAB_CONTENTS
].hwnd
) {
734 ERR("Could not create treeview control\n");
738 ResizeTabChild(info
, info
->tabs
[TAB_CONTENTS
].hwnd
);
739 ShowWindow(info
->tabs
[TAB_CONTENTS
].hwnd
, SW_SHOW
);
746 static LRESULT
Help_OnSize(HWND hWnd
)
748 HHInfo
*pHHInfo
= (HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
755 NP_GetNavigationRect(pHHInfo
, &rc
);
756 SetWindowPos(pHHInfo
->WinType
.hwndNavigation
, HWND_TOP
, 0, 0,
757 rc
.right
, rc
.bottom
, SWP_NOMOVE
);
759 SB_GetSizeBarRect(pHHInfo
, &rc
);
760 SetWindowPos(pHHInfo
->hwndSizeBar
, HWND_TOP
, rc
.left
, rc
.top
,
761 rc
.right
, rc
.bottom
, SWP_SHOWWINDOW
);
763 HP_GetHTMLRect(pHHInfo
, &rc
);
764 SetWindowPos(pHHInfo
->WinType
.hwndHTML
, HWND_TOP
, rc
.left
, rc
.top
,
765 rc
.right
, rc
.bottom
, SWP_SHOWWINDOW
);
767 /* Resize browser window taking the frame size into account */
768 dwSize
= GetSystemMetrics(SM_CXFRAME
);
769 ResizeWebBrowser(pHHInfo
, rc
.right
- dwSize
, rc
.bottom
- dwSize
);
774 static LRESULT CALLBACK
Help_WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
779 if (HIWORD(wParam
) == BN_CLICKED
)
780 TB_OnClick(hWnd
, LOWORD(wParam
));
783 return Help_OnSize(hWnd
);
785 ReleaseHelpViewer((HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
));
793 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
799 static BOOL
HH_CreateHelpWindow(HHInfo
*info
)
802 RECT winPos
= info
->WinType
.rcWindowPos
;
804 DWORD dwStyles
, dwExStyles
;
805 DWORD x
, y
, width
, height
;
807 static const WCHAR windowClassW
[] = {
808 'H','H',' ', 'P','a','r','e','n','t',0
811 wcex
.cbSize
= sizeof(WNDCLASSEXW
);
812 wcex
.style
= CS_HREDRAW
| CS_VREDRAW
;
813 wcex
.lpfnWndProc
= Help_WndProc
;
816 wcex
.hInstance
= hhctrl_hinstance
;
817 wcex
.hIcon
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
818 wcex
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
)IDC_ARROW
);
819 wcex
.hbrBackground
= (HBRUSH
)(COLOR_MENU
+ 1);
820 wcex
.lpszMenuName
= NULL
;
821 wcex
.lpszClassName
= windowClassW
;
822 wcex
.hIconSm
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
824 RegisterClassExW(&wcex
);
826 /* Read in window parameters if available */
827 if (info
->WinType
.fsValidMembers
& HHWIN_PARAM_STYLES
)
828 dwStyles
= info
->WinType
.dwStyles
;
830 dwStyles
= WS_OVERLAPPEDWINDOW
| WS_VISIBLE
|
831 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
833 if (info
->WinType
.fsValidMembers
& HHWIN_PARAM_EXSTYLES
)
834 dwExStyles
= info
->WinType
.dwExStyles
;
836 dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_APPWINDOW
|
837 WS_EX_WINDOWEDGE
| WS_EX_RIGHTSCROLLBAR
;
839 if (info
->WinType
.fsValidMembers
& HHWIN_PARAM_RECT
)
843 width
= winPos
.right
- x
;
844 height
= winPos
.bottom
- y
;
848 x
= WINTYPE_DEFAULT_X
;
849 y
= WINTYPE_DEFAULT_Y
;
850 width
= WINTYPE_DEFAULT_WIDTH
;
851 height
= WINTYPE_DEFAULT_HEIGHT
;
854 hWnd
= CreateWindowExW(dwExStyles
, windowClassW
, info
->WinType
.pszCaption
,
855 dwStyles
, x
, y
, width
, height
, NULL
, NULL
, hhctrl_hinstance
, NULL
);
859 ShowWindow(hWnd
, SW_SHOW
);
862 /* store the pointer to the HH info struct */
863 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
865 info
->WinType
.hwndHelp
= hWnd
;
869 static void HH_CreateFont(HHInfo
*pHHInfo
)
873 GetObjectW(GetStockObject(ANSI_VAR_FONT
), sizeof(LOGFONTW
), &lf
);
874 lf
.lfWeight
= FW_NORMAL
;
876 lf
.lfUnderline
= FALSE
;
878 pHHInfo
->hFont
= CreateFontIndirectW(&lf
);
881 static void HH_InitRequiredControls(DWORD dwControls
)
883 INITCOMMONCONTROLSEX icex
;
885 icex
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
886 icex
.dwICC
= dwControls
;
887 InitCommonControlsEx(&icex
);
890 /* Creates the whole package */
891 static BOOL
CreateViewer(HHInfo
*pHHInfo
)
893 HH_CreateFont(pHHInfo
);
895 if (!HH_CreateHelpWindow(pHHInfo
))
898 HH_InitRequiredControls(ICC_BAR_CLASSES
);
900 if (!HH_AddToolbar(pHHInfo
))
903 HH_RegisterChildWndClass(pHHInfo
);
905 if (!HH_AddNavigationPane(pHHInfo
))
908 HH_RegisterSizeBarClass(pHHInfo
);
910 if (!HH_AddSizeBar(pHHInfo
))
913 if (!HH_AddHTMLPane(pHHInfo
))
916 if (!AddContentTab(pHHInfo
))
919 InitContent(pHHInfo
);
924 void ReleaseHelpViewer(HHInfo
*info
)
926 TRACE("(%p)\n", info
);
931 /* Free allocated strings */
932 heap_free(info
->pszType
);
933 heap_free(info
->pszCaption
);
934 heap_free(info
->pszToc
);
935 heap_free(info
->pszIndex
);
936 heap_free(info
->pszFile
);
937 heap_free(info
->pszHome
);
938 heap_free(info
->pszJump1
);
939 heap_free(info
->pszJump2
);
940 heap_free(info
->pszUrlJump1
);
941 heap_free(info
->pszUrlJump2
);
944 CloseCHM(info
->pCHMInfo
);
946 ReleaseWebBrowser(info
);
947 ReleaseContent(info
);
949 if(info
->WinType
.hwndHelp
)
950 DestroyWindow(info
->WinType
.hwndHelp
);
956 HHInfo
*CreateHelpViewer(LPCWSTR filename
)
958 HHInfo
*info
= heap_alloc_zero(sizeof(HHInfo
));
962 info
->pCHMInfo
= OpenCHM(filename
);
963 if(!info
->pCHMInfo
) {
964 ReleaseHelpViewer(info
);
968 if (!LoadWinTypeFromCHM(info
)) {
969 ReleaseHelpViewer(info
);
973 if(!CreateViewer(info
)) {
974 ReleaseHelpViewer(info
);