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
47 #define EDIT_HEIGHT 20
49 static const WCHAR szEmpty
[] = {0};
51 /* Loads a string from the resource file */
52 static LPWSTR
HH_LoadString(DWORD dwID
)
55 LPCWSTR stringresource
;
58 iSize
= LoadStringW(hhctrl_hinstance
, dwID
, (LPWSTR
)&stringresource
, 0);
60 string
= heap_alloc((iSize
+ 2) * sizeof(WCHAR
)); /* some strings (tab text) needs double-null termination */
61 memcpy(string
, stringresource
, iSize
*sizeof(WCHAR
));
67 static HRESULT
navigate_url(HHInfo
*info
, LPCWSTR surl
)
72 TRACE("%s\n", debugstr_w(surl
));
75 V_BSTR(&url
) = SysAllocString(surl
);
77 hres
= IWebBrowser2_Navigate2(info
->web_browser
, &url
, 0, 0, 0, 0);
82 TRACE("Navigation failed: %08x\n", hres
);
87 BOOL
NavigateToUrl(HHInfo
*info
, LPCWSTR surl
)
93 static const WCHAR url_indicator
[] = {':', '/', '/', 0};
95 TRACE("%s\n", debugstr_w(surl
));
97 if (strstrW(surl
, url_indicator
)) {
98 hres
= navigate_url(info
, surl
);
101 } /* look up in chm if it doesn't look like a full url */
103 SetChmPath(&chm_path
, info
->pCHMInfo
->szFile
, surl
);
104 ret
= NavigateToChm(info
, chm_path
.chm_file
, chm_path
.chm_index
);
106 heap_free(chm_path
.chm_file
);
107 heap_free(chm_path
.chm_index
);
112 BOOL
NavigateToChm(HHInfo
*info
, LPCWSTR file
, LPCWSTR index
)
114 WCHAR buf
[INTERNET_MAX_URL_LENGTH
];
115 WCHAR full_path
[MAX_PATH
];
118 static const WCHAR url_format
[] =
119 {'m','k',':','@','M','S','I','T','S','t','o','r','e',':','%','s',':',':','%','s','%','s',0};
120 static const WCHAR slash
[] = {'/',0};
121 static const WCHAR empty
[] = {0};
123 TRACE("%p %s %s\n", info
, debugstr_w(file
), debugstr_w(index
));
125 if (!info
->web_browser
)
128 if(!GetFullPathNameW(file
, sizeof(full_path
)/sizeof(full_path
[0]), full_path
, NULL
)) {
129 WARN("GetFullPathName failed: %u\n", GetLastError());
133 wsprintfW(buf
, url_format
, full_path
, (!index
|| index
[0] == '/') ? empty
: slash
, index
);
136 if((ptr
= strchrW(buf
, '#')))
139 return SUCCEEDED(navigate_url(info
, buf
));
144 #define SIZEBAR_WIDTH 4
146 static const WCHAR szSizeBarClass
[] = {
147 'H','H',' ','S','i','z','e','B','a','r',0
150 /* Draw the SizeBar */
151 static void SB_OnPaint(HWND hWnd
)
157 hdc
= BeginPaint(hWnd
, &ps
);
159 GetClientRect(hWnd
, &rc
);
164 FrameRect(hdc
, &rc
, GetStockObject(GRAY_BRUSH
));
166 /* white highlight */
167 SelectObject(hdc
, GetStockObject(WHITE_PEN
));
168 MoveToEx(hdc
, rc
.right
, 1, NULL
);
170 LineTo(hdc
, 1, rc
.bottom
- 1);
173 MoveToEx(hdc
, 0, rc
.bottom
, NULL
);
174 LineTo(hdc
, rc
.right
, rc
.bottom
);
179 static void SB_OnLButtonDown(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
184 static void SB_OnLButtonUp(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
186 HHInfo
*pHHInfo
= (HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
189 pt
.x
= (short)LOWORD(lParam
);
190 pt
.y
= (short)HIWORD(lParam
);
192 /* update the window sizes */
193 pHHInfo
->WinType
.iNavWidth
+= pt
.x
;
199 static void SB_OnMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
201 /* ignore WM_MOUSEMOVE if not dragging the SizeBar */
202 if (!(wParam
& MK_LBUTTON
))
206 static LRESULT CALLBACK
SizeBar_WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
211 SB_OnLButtonDown(hWnd
, wParam
, lParam
);
214 SB_OnLButtonUp(hWnd
, wParam
, lParam
);
217 SB_OnMouseMove(hWnd
, wParam
, lParam
);
223 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
229 static void HH_RegisterSizeBarClass(HHInfo
*pHHInfo
)
233 wcex
.cbSize
= sizeof(WNDCLASSEXW
);
235 wcex
.lpfnWndProc
= SizeBar_WndProc
;
238 wcex
.hInstance
= hhctrl_hinstance
;
239 wcex
.hIcon
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
240 wcex
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
)IDC_SIZEWE
);
241 wcex
.hbrBackground
= (HBRUSH
)(COLOR_MENU
+ 1);
242 wcex
.lpszMenuName
= NULL
;
243 wcex
.lpszClassName
= szSizeBarClass
;
244 wcex
.hIconSm
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
246 RegisterClassExW(&wcex
);
249 static void SB_GetSizeBarRect(HHInfo
*info
, RECT
*rc
)
251 RECT rectWND
, rectTB
, rectNP
;
253 GetClientRect(info
->WinType
.hwndHelp
, &rectWND
);
254 GetClientRect(info
->WinType
.hwndToolBar
, &rectTB
);
255 GetClientRect(info
->WinType
.hwndNavigation
, &rectNP
);
257 rc
->left
= rectNP
.right
;
258 rc
->top
= rectTB
.bottom
;
259 rc
->bottom
= rectWND
.bottom
- rectTB
.bottom
;
260 rc
->right
= SIZEBAR_WIDTH
;
263 static BOOL
HH_AddSizeBar(HHInfo
*pHHInfo
)
266 HWND hwndParent
= pHHInfo
->WinType
.hwndHelp
;
267 DWORD dwStyles
= WS_CHILDWINDOW
| WS_VISIBLE
| WS_OVERLAPPED
;
268 DWORD dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
;
271 SB_GetSizeBarRect(pHHInfo
, &rc
);
273 hWnd
= CreateWindowExW(dwExStyles
, szSizeBarClass
, szEmpty
, dwStyles
,
274 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
275 hwndParent
, NULL
, hhctrl_hinstance
, NULL
);
279 /* store the pointer to the HH info struct */
280 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (LONG_PTR
)pHHInfo
);
282 pHHInfo
->hwndSizeBar
= hWnd
;
288 static const WCHAR szChildClass
[] = {
289 'H','H',' ','C','h','i','l','d',0
292 static LRESULT
Child_OnPaint(HWND hWnd
)
298 hdc
= BeginPaint(hWnd
, &ps
);
300 /* Only paint the Navigation pane, identified by the fact
301 * that it has a child window
303 if (GetWindow(hWnd
, GW_CHILD
))
305 GetClientRect(hWnd
, &rc
);
307 /* set the border color */
308 SelectObject(hdc
, GetStockObject(DC_PEN
));
309 SetDCPenColor(hdc
, GetSysColor(COLOR_BTNSHADOW
));
311 /* Draw the top border */
312 LineTo(hdc
, rc
.right
, 0);
314 SelectObject(hdc
, GetStockObject(WHITE_PEN
));
315 MoveToEx(hdc
, 0, 1, NULL
);
316 LineTo(hdc
, rc
.right
, 1);
324 static void ResizeTabChild(HHInfo
*info
, int tab
)
326 HWND hwnd
= info
->tabs
[tab
].hwnd
;
331 GetClientRect(info
->WinType
.hwndNavigation
, &rect
);
332 SendMessageW(info
->hwndTabCtrl
, TCM_GETITEMRECT
, 0, (LPARAM
)&tabrc
);
333 cnt
= SendMessageW(info
->hwndTabCtrl
, TCM_GETROWCOUNT
, 0, 0);
335 rect
.left
= TAB_MARGIN
;
336 rect
.top
= TAB_TOP_PADDING
+ cnt
*(tabrc
.bottom
-tabrc
.top
) + TAB_MARGIN
;
337 rect
.right
-= TAB_RIGHT_PADDING
+ TAB_MARGIN
;
338 rect
.bottom
-= TAB_MARGIN
;
339 width
= rect
.right
-rect
.left
;
340 height
= rect
.bottom
-rect
.top
;
342 SetWindowPos(hwnd
, NULL
, rect
.left
, rect
.top
, width
, height
,
343 SWP_NOZORDER
| SWP_NOACTIVATE
);
348 int scroll_width
= GetSystemMetrics(SM_CXVSCROLL
);
349 int border_width
= GetSystemMetrics(SM_CXBORDER
);
350 int edge_width
= GetSystemMetrics(SM_CXEDGE
);
352 /* Resize the tab widget column to perfectly fit the tab window and
353 * leave sufficient space for the scroll widget.
355 SendMessageW(info
->tabs
[TAB_INDEX
].hwnd
, LVM_SETCOLUMNWIDTH
, 0,
356 width
-scroll_width
-2*border_width
-2*edge_width
);
361 int scroll_width
= GetSystemMetrics(SM_CXVSCROLL
);
362 int border_width
= GetSystemMetrics(SM_CXBORDER
);
363 int edge_width
= GetSystemMetrics(SM_CXEDGE
);
366 SetWindowPos(info
->search
.hwndEdit
, NULL
, 0, top_pos
, width
,
367 EDIT_HEIGHT
, SWP_NOZORDER
| SWP_NOACTIVATE
);
368 top_pos
+= EDIT_HEIGHT
+ TAB_MARGIN
;
369 SetWindowPos(info
->search
.hwndList
, NULL
, 0, top_pos
, width
,
370 height
-top_pos
, SWP_NOZORDER
| SWP_NOACTIVATE
);
371 /* Resize the tab widget column to perfectly fit the tab window and
372 * leave sufficient space for the scroll widget.
374 SendMessageW(info
->search
.hwndList
, LVM_SETCOLUMNWIDTH
, 0,
375 width
-scroll_width
-2*border_width
-2*edge_width
);
382 static LRESULT
Child_OnSize(HWND hwnd
)
384 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
387 if(!info
|| hwnd
!= info
->WinType
.hwndNavigation
)
390 GetClientRect(hwnd
, &rect
);
391 SetWindowPos(info
->hwndTabCtrl
, HWND_TOP
, 0, 0,
392 rect
.right
- TAB_RIGHT_PADDING
,
393 rect
.bottom
- TAB_TOP_PADDING
, SWP_NOMOVE
);
395 ResizeTabChild(info
, TAB_CONTENTS
);
396 ResizeTabChild(info
, TAB_INDEX
);
400 static LRESULT
OnTabChange(HWND hwnd
)
402 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hwnd
, GWLP_USERDATA
);
409 if(info
->tabs
[info
->current_tab
].hwnd
)
410 ShowWindow(info
->tabs
[info
->current_tab
].hwnd
, SW_HIDE
);
412 info
->current_tab
= SendMessageW(info
->hwndTabCtrl
, TCM_GETCURSEL
, 0, 0);
414 if(info
->tabs
[info
->current_tab
].hwnd
)
415 ShowWindow(info
->tabs
[info
->current_tab
].hwnd
, SW_SHOW
);
420 static LRESULT
OnTopicChange(HHInfo
*info
, void *user_data
)
422 LPCWSTR chmfile
= NULL
, name
= NULL
, local
= NULL
;
427 if(!user_data
|| !info
)
430 switch (info
->current_tab
)
433 citer
= (ContentItem
*) user_data
;
435 local
= citer
->local
;
437 if(citer
->merge
.chm_file
) {
438 chmfile
= citer
->merge
.chm_file
;
441 citer
= citer
->parent
;
445 iiter
= (IndexItem
*) user_data
;
446 if(iiter
->nItems
== 0) {
447 FIXME("No entries for this item!\n");
450 if(iiter
->nItems
> 1) {
454 SendMessageW(info
->popup
.hwndList
, LVM_DELETEALLITEMS
, 0, 0);
455 for(i
=0;i
<iiter
->nItems
;i
++) {
456 IndexSubItem
*item
= &iiter
->items
[i
];
457 WCHAR
*name
= iiter
->keyword
;
461 memset(&lvi
, 0, sizeof(lvi
));
463 lvi
.mask
= LVIF_TEXT
|LVIF_PARAM
;
464 lvi
.cchTextMax
= strlenW(name
)+1;
466 lvi
.lParam
= (LPARAM
) item
;
467 SendMessageW(info
->popup
.hwndList
, LVM_INSERTITEMW
, 0, (LPARAM
)&lvi
);
469 ShowWindow(info
->popup
.hwndPopup
, SW_SHOW
);
472 name
= iiter
->items
[0].name
;
473 local
= iiter
->items
[0].local
;
474 chmfile
= iiter
->merge
.chm_file
;
477 siter
= (SearchItem
*) user_data
;
478 name
= siter
->filename
;
479 local
= siter
->filename
;
480 chmfile
= info
->pCHMInfo
->szFile
;
483 FIXME("Unhandled operation for this tab!\n");
489 FIXME("No help file found for this item!\n");
493 TRACE("name %s loal %s\n", debugstr_w(name
), debugstr_w(local
));
495 NavigateToChm(info
, chmfile
, local
);
499 /* Capture the Enter/Return key and send it up to Child_WndProc as an NM_RETURN message */
500 static LRESULT CALLBACK
EditChild_WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
502 WNDPROC editWndProc
= (WNDPROC
)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
504 if(message
== WM_KEYUP
&& wParam
== VK_RETURN
)
508 nmhdr
.hwndFrom
= hWnd
;
509 nmhdr
.code
= NM_RETURN
;
510 SendMessageW(GetParent(GetParent(hWnd
)), WM_NOTIFY
, wParam
, (LPARAM
)&nmhdr
);
512 return editWndProc(hWnd
, message
, wParam
, lParam
);
515 static LRESULT CALLBACK
Child_WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
520 return Child_OnPaint(hWnd
);
522 return Child_OnSize(hWnd
);
524 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
525 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
527 switch(nmhdr
->code
) {
529 return OnTabChange(hWnd
);
530 case TVN_SELCHANGEDW
:
531 return OnTopicChange(info
, (void*)((NMTREEVIEWW
*)lParam
)->itemNew
.lParam
);
535 switch(info
->current_tab
)
538 return OnTopicChange(info
, (void*)((NMITEMACTIVATE
*)lParam
)->lParam
);
540 return OnTopicChange(info
, (void*)((NMITEMACTIVATE
*)lParam
)->lParam
);
546 switch(info
->current_tab
) {
548 HWND hwndList
= info
->tabs
[TAB_INDEX
].hwnd
;
551 lvItem
.iItem
= (int) SendMessageW(hwndList
, LVM_GETSELECTIONMARK
, 0, 0);
552 lvItem
.mask
= TVIF_PARAM
;
553 SendMessageW(hwndList
, LVM_GETITEMW
, 0, (LPARAM
)&lvItem
);
554 OnTopicChange(info
, (void*) lvItem
.lParam
);
558 if(nmhdr
->hwndFrom
== info
->search
.hwndEdit
) {
562 len
= GetWindowTextA(info
->search
.hwndEdit
, needle
, sizeof(needle
));
565 FIXME("Unable to get search text.\n");
568 /* Convert the requested text for comparison later against the
569 * lower case version of HTML file contents.
572 needle
[i
] = tolower(needle
[i
]);
573 InitSearch(info
, needle
);
575 }else if(nmhdr
->hwndFrom
== info
->search
.hwndList
) {
576 HWND hwndList
= info
->search
.hwndList
;
579 lvItem
.iItem
= (int) SendMessageW(hwndList
, LVM_GETSELECTIONMARK
, 0, 0);
580 lvItem
.mask
= TVIF_PARAM
;
581 SendMessageW(hwndList
, LVM_GETITEMW
, 0, (LPARAM
)&lvItem
);
582 OnTopicChange(info
, (void*) lvItem
.lParam
);
593 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
599 static void HH_RegisterChildWndClass(HHInfo
*pHHInfo
)
603 wcex
.cbSize
= sizeof(WNDCLASSEXW
);
605 wcex
.lpfnWndProc
= Child_WndProc
;
608 wcex
.hInstance
= hhctrl_hinstance
;
609 wcex
.hIcon
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
610 wcex
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
)IDC_ARROW
);
611 wcex
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
612 wcex
.lpszMenuName
= NULL
;
613 wcex
.lpszClassName
= szChildClass
;
614 wcex
.hIconSm
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
616 RegisterClassExW(&wcex
);
623 static void TB_OnClick(HWND hWnd
, DWORD dwID
)
625 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
630 DoPageAction(info
, WB_STOP
);
633 DoPageAction(info
, WB_REFRESH
);
636 DoPageAction(info
, WB_GOBACK
);
639 NavigateToChm(info
, info
->pCHMInfo
->szFile
, info
->WinType
.pszHome
);
642 DoPageAction(info
, WB_GOFORWARD
);
649 case IDTB_BROWSE_FWD
:
650 case IDTB_BROWSE_BACK
:
661 static void TB_AddButton(TBBUTTON
*pButtons
, DWORD dwIndex
, DWORD dwID
)
663 /* FIXME: Load the correct button bitmaps */
664 pButtons
[dwIndex
].iBitmap
= STD_PRINT
;
665 pButtons
[dwIndex
].idCommand
= dwID
;
666 pButtons
[dwIndex
].fsState
= TBSTATE_ENABLED
;
667 pButtons
[dwIndex
].fsStyle
= BTNS_BUTTON
;
668 pButtons
[dwIndex
].dwData
= 0;
669 pButtons
[dwIndex
].iString
= 0;
672 static void TB_AddButtonsFromFlags(TBBUTTON
*pButtons
, DWORD dwButtonFlags
, LPDWORD pdwNumButtons
)
676 if (dwButtonFlags
& HHWIN_BUTTON_EXPAND
)
677 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_EXPAND
);
679 if (dwButtonFlags
& HHWIN_BUTTON_BACK
)
680 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_BACK
);
682 if (dwButtonFlags
& HHWIN_BUTTON_FORWARD
)
683 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_FORWARD
);
685 if (dwButtonFlags
& HHWIN_BUTTON_STOP
)
686 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_STOP
);
688 if (dwButtonFlags
& HHWIN_BUTTON_REFRESH
)
689 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_REFRESH
);
691 if (dwButtonFlags
& HHWIN_BUTTON_HOME
)
692 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_HOME
);
694 if (dwButtonFlags
& HHWIN_BUTTON_SYNC
)
695 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_SYNC
);
697 if (dwButtonFlags
& HHWIN_BUTTON_OPTIONS
)
698 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_OPTIONS
);
700 if (dwButtonFlags
& HHWIN_BUTTON_PRINT
)
701 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_PRINT
);
703 if (dwButtonFlags
& HHWIN_BUTTON_JUMP1
)
704 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_JUMP1
);
706 if (dwButtonFlags
& HHWIN_BUTTON_JUMP2
)
707 TB_AddButton(pButtons
,(*pdwNumButtons
)++, IDTB_JUMP2
);
709 if (dwButtonFlags
& HHWIN_BUTTON_ZOOM
)
710 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_ZOOM
);
712 if (dwButtonFlags
& HHWIN_BUTTON_TOC_NEXT
)
713 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_TOC_NEXT
);
715 if (dwButtonFlags
& HHWIN_BUTTON_TOC_PREV
)
716 TB_AddButton(pButtons
, (*pdwNumButtons
)++, IDTB_TOC_PREV
);
719 static BOOL
HH_AddToolbar(HHInfo
*pHHInfo
)
722 HWND hwndParent
= pHHInfo
->WinType
.hwndHelp
;
724 TBBUTTON buttons
[IDTB_TOC_PREV
- IDTB_EXPAND
];
726 DWORD dwStyles
, dwExStyles
;
727 DWORD dwNumButtons
, dwIndex
;
729 if (pHHInfo
->WinType
.fsWinProperties
& HHWIN_PARAM_TB_FLAGS
)
730 toolbarFlags
= pHHInfo
->WinType
.fsToolBarFlags
;
732 toolbarFlags
= HHWIN_DEF_BUTTONS
;
734 TB_AddButtonsFromFlags(buttons
, toolbarFlags
, &dwNumButtons
);
736 dwStyles
= WS_CHILDWINDOW
| WS_VISIBLE
| TBSTYLE_FLAT
|
737 TBSTYLE_WRAPABLE
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
;
738 dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
;
740 hToolbar
= CreateWindowExW(dwExStyles
, TOOLBARCLASSNAMEW
, NULL
, dwStyles
,
741 0, 0, 0, 0, hwndParent
, NULL
,
742 hhctrl_hinstance
, NULL
);
746 SendMessageW(hToolbar
, TB_SETBITMAPSIZE
, 0, MAKELONG(ICON_SIZE
, ICON_SIZE
));
747 SendMessageW(hToolbar
, TB_BUTTONSTRUCTSIZE
, sizeof(TBBUTTON
), 0);
748 SendMessageW(hToolbar
, WM_SETFONT
, (WPARAM
)pHHInfo
->hFont
, TRUE
);
750 /* FIXME: Load correct icons for all buttons */
751 tbAB
.hInst
= HINST_COMMCTRL
;
752 tbAB
.nID
= IDB_STD_LARGE_COLOR
;
753 SendMessageW(hToolbar
, TB_ADDBITMAP
, 0, (LPARAM
)&tbAB
);
755 for (dwIndex
= 0; dwIndex
< dwNumButtons
; dwIndex
++)
757 LPWSTR szBuf
= HH_LoadString(buttons
[dwIndex
].idCommand
);
758 DWORD dwLen
= strlenW(szBuf
);
759 szBuf
[dwLen
+ 1] = 0; /* Double-null terminate */
761 buttons
[dwIndex
].iString
= (DWORD
)SendMessageW(hToolbar
, TB_ADDSTRINGW
, 0, (LPARAM
)szBuf
);
765 SendMessageW(hToolbar
, TB_ADDBUTTONSW
, dwNumButtons
, (LPARAM
)buttons
);
766 SendMessageW(hToolbar
, TB_AUTOSIZE
, 0, 0);
767 ShowWindow(hToolbar
, SW_SHOW
);
769 pHHInfo
->WinType
.hwndToolBar
= hToolbar
;
773 /* Navigation Pane */
775 static void NP_GetNavigationRect(HHInfo
*pHHInfo
, RECT
*rc
)
777 HWND hwndParent
= pHHInfo
->WinType
.hwndHelp
;
778 HWND hwndToolbar
= pHHInfo
->WinType
.hwndToolBar
;
779 RECT rectWND
, rectTB
;
781 GetClientRect(hwndParent
, &rectWND
);
782 GetClientRect(hwndToolbar
, &rectTB
);
785 rc
->top
= rectTB
.bottom
;
786 rc
->bottom
= rectWND
.bottom
- rectTB
.bottom
;
788 if (!(pHHInfo
->WinType
.fsValidMembers
& HHWIN_PARAM_NAV_WIDTH
) &&
789 pHHInfo
->WinType
.iNavWidth
== 0)
791 pHHInfo
->WinType
.iNavWidth
= WINTYPE_DEFAULT_NAVWIDTH
;
794 rc
->right
= pHHInfo
->WinType
.iNavWidth
;
797 static DWORD
NP_CreateTab(HINSTANCE hInstance
, HWND hwndTabCtrl
, DWORD index
)
800 LPWSTR tabText
= HH_LoadString(index
);
803 tie
.mask
= TCIF_TEXT
;
804 tie
.pszText
= tabText
;
806 ret
= SendMessageW( hwndTabCtrl
, TCM_INSERTITEMW
, index
, (LPARAM
)&tie
);
812 static BOOL
HH_AddNavigationPane(HHInfo
*info
)
814 HWND hWnd
, hwndTabCtrl
;
815 HWND hwndParent
= info
->WinType
.hwndHelp
;
816 DWORD dwStyles
= WS_CHILDWINDOW
| WS_VISIBLE
;
817 DWORD dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
;
820 NP_GetNavigationRect(info
, &rc
);
822 hWnd
= CreateWindowExW(dwExStyles
, szChildClass
, szEmpty
, dwStyles
,
823 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
824 hwndParent
, NULL
, hhctrl_hinstance
, NULL
);
828 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
830 hwndTabCtrl
= CreateWindowExW(dwExStyles
, WC_TABCONTROLW
, szEmpty
, dwStyles
,
832 rc
.right
- TAB_RIGHT_PADDING
,
833 rc
.bottom
- TAB_TOP_PADDING
,
834 hWnd
, NULL
, hhctrl_hinstance
, NULL
);
838 if (*info
->WinType
.pszToc
)
839 info
->tabs
[TAB_CONTENTS
].id
= NP_CreateTab(hhctrl_hinstance
, hwndTabCtrl
, IDS_CONTENTS
);
841 if (*info
->WinType
.pszIndex
)
842 info
->tabs
[TAB_INDEX
].id
= NP_CreateTab(hhctrl_hinstance
, hwndTabCtrl
, IDS_INDEX
);
844 if (info
->WinType
.fsWinProperties
& HHWIN_PROP_TAB_SEARCH
)
845 info
->tabs
[TAB_SEARCH
].id
= NP_CreateTab(hhctrl_hinstance
, hwndTabCtrl
, IDS_SEARCH
);
847 if (info
->WinType
.fsWinProperties
& HHWIN_PROP_TAB_FAVORITES
)
848 info
->tabs
[TAB_FAVORITES
].id
= NP_CreateTab(hhctrl_hinstance
, hwndTabCtrl
, IDS_FAVORITES
);
850 SendMessageW(hwndTabCtrl
, WM_SETFONT
, (WPARAM
)info
->hFont
, TRUE
);
852 info
->hwndTabCtrl
= hwndTabCtrl
;
853 info
->WinType
.hwndNavigation
= hWnd
;
859 static void HP_GetHTMLRect(HHInfo
*info
, RECT
*rc
)
861 RECT rectTB
, rectWND
, rectNP
, rectSB
;
863 GetClientRect(info
->WinType
.hwndHelp
, &rectWND
);
864 GetClientRect(info
->WinType
.hwndToolBar
, &rectTB
);
865 GetClientRect(info
->WinType
.hwndNavigation
, &rectNP
);
866 GetClientRect(info
->hwndSizeBar
, &rectSB
);
868 rc
->left
= rectNP
.right
+ rectSB
.right
;
869 rc
->top
= rectTB
.bottom
;
870 rc
->right
= rectWND
.right
- rc
->left
;
871 rc
->bottom
= rectWND
.bottom
- rectTB
.bottom
;
874 static BOOL
HH_AddHTMLPane(HHInfo
*pHHInfo
)
877 HWND hwndParent
= pHHInfo
->WinType
.hwndHelp
;
878 DWORD dwStyles
= WS_CHILDWINDOW
| WS_VISIBLE
| WS_CLIPCHILDREN
;
879 DWORD dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
| WS_EX_CLIENTEDGE
;
882 HP_GetHTMLRect(pHHInfo
, &rc
);
884 hWnd
= CreateWindowExW(dwExStyles
, szChildClass
, szEmpty
, dwStyles
,
885 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
886 hwndParent
, NULL
, hhctrl_hinstance
, NULL
);
890 if (!InitWebBrowser(pHHInfo
, hWnd
))
893 /* store the pointer to the HH info struct */
894 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (LONG_PTR
)pHHInfo
);
896 ShowWindow(hWnd
, SW_SHOW
);
899 pHHInfo
->WinType
.hwndHTML
= hWnd
;
903 static BOOL
AddContentTab(HHInfo
*info
)
905 if(info
->tabs
[TAB_CONTENTS
].id
== -1)
906 return TRUE
; /* No "Contents" tab */
907 info
->tabs
[TAB_CONTENTS
].hwnd
= CreateWindowExW(WS_EX_CLIENTEDGE
, WC_TREEVIEWW
,
908 szEmpty
, WS_CHILD
| WS_BORDER
| 0x25, 50, 50, 100, 100,
909 info
->WinType
.hwndNavigation
, NULL
, hhctrl_hinstance
, NULL
);
910 if(!info
->tabs
[TAB_CONTENTS
].hwnd
) {
911 ERR("Could not create treeview control\n");
915 ResizeTabChild(info
, TAB_CONTENTS
);
916 ShowWindow(info
->tabs
[TAB_CONTENTS
].hwnd
, SW_SHOW
);
921 static BOOL
AddIndexTab(HHInfo
*info
)
923 char hidden_column
[] = "Column";
926 if(info
->tabs
[TAB_INDEX
].id
== -1)
927 return TRUE
; /* No "Index" tab */
928 info
->tabs
[TAB_INDEX
].hwnd
= CreateWindowExW(WS_EX_CLIENTEDGE
, WC_LISTVIEWW
,
929 szEmpty
, WS_CHILD
| WS_BORDER
| LVS_SINGLESEL
| LVS_REPORT
| LVS_NOCOLUMNHEADER
, 50, 50, 100, 100,
930 info
->WinType
.hwndNavigation
, NULL
, hhctrl_hinstance
, NULL
);
931 if(!info
->tabs
[TAB_INDEX
].hwnd
) {
932 ERR("Could not create ListView control\n");
935 memset(&lvc
, 0, sizeof(lvc
));
936 lvc
.mask
= LVCF_TEXT
;
937 lvc
.pszText
= hidden_column
;
938 if(SendMessageW(info
->tabs
[TAB_INDEX
].hwnd
, LVM_INSERTCOLUMNA
, 0, (LPARAM
) &lvc
) == -1)
940 ERR("Could not create ListView column\n");
944 ResizeTabChild(info
, TAB_INDEX
);
945 ShowWindow(info
->tabs
[TAB_INDEX
].hwnd
, SW_HIDE
);
950 static BOOL
AddSearchTab(HHInfo
*info
)
952 HWND hwndList
, hwndEdit
, hwndContainer
;
953 char hidden_column
[] = "Column";
957 if(info
->tabs
[TAB_SEARCH
].id
== -1)
958 return TRUE
; /* No "Search" tab */
959 hwndContainer
= CreateWindowExW(WS_EX_CONTROLPARENT
, szChildClass
, szEmpty
,
960 WS_CHILD
, 0, 0, 0, 0, info
->WinType
.hwndNavigation
,
961 NULL
, hhctrl_hinstance
, NULL
);
963 ERR("Could not create search window container control.\n");
966 hwndEdit
= CreateWindowExW(WS_EX_CLIENTEDGE
, WC_EDITW
, szEmpty
, WS_CHILD
967 | WS_VISIBLE
| ES_LEFT
| SS_NOTIFY
, 0, 0, 0, 0,
968 hwndContainer
, NULL
, hhctrl_hinstance
, NULL
);
970 ERR("Could not create search ListView control.\n");
973 if(SendMessageW(hwndEdit
, WM_SETFONT
, (WPARAM
) info
->hFont
, (LPARAM
) FALSE
) == -1)
975 ERR("Could not set font for edit control.\n");
978 editWndProc
= (WNDPROC
) SetWindowLongPtrW(hwndEdit
, GWLP_WNDPROC
, (LONG_PTR
)EditChild_WndProc
);
980 ERR("Could not redirect messages for edit control.\n");
983 SetWindowLongPtrW(hwndEdit
, GWLP_USERDATA
, (LONG_PTR
)editWndProc
);
984 hwndList
= CreateWindowExW(WS_EX_CLIENTEDGE
, WC_LISTVIEWW
, szEmpty
,
985 WS_CHILD
| WS_VISIBLE
| WS_BORDER
| LVS_SINGLESEL
986 | LVS_REPORT
| LVS_NOCOLUMNHEADER
, 0, 0, 0, 0,
987 hwndContainer
, NULL
, hhctrl_hinstance
, NULL
);
989 ERR("Could not create search ListView control.\n");
992 memset(&lvc
, 0, sizeof(lvc
));
993 lvc
.mask
= LVCF_TEXT
;
994 lvc
.pszText
= hidden_column
;
995 if(SendMessageW(hwndList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
) &lvc
) == -1)
997 ERR("Could not create ListView column\n");
1001 info
->search
.hwndEdit
= hwndEdit
;
1002 info
->search
.hwndList
= hwndList
;
1003 info
->search
.hwndContainer
= hwndContainer
;
1004 info
->tabs
[TAB_SEARCH
].hwnd
= hwndContainer
;
1006 SetWindowLongPtrW(hwndContainer
, GWLP_USERDATA
, (LONG_PTR
)info
);
1008 ResizeTabChild(info
, TAB_SEARCH
);
1013 /* The Index tab's sub-topic popup */
1015 static void ResizePopupChild(HHInfo
*info
)
1017 int scroll_width
= GetSystemMetrics(SM_CXVSCROLL
);
1018 int border_width
= GetSystemMetrics(SM_CXBORDER
);
1019 int edge_width
= GetSystemMetrics(SM_CXEDGE
);
1026 GetClientRect(info
->popup
.hwndPopup
, &rect
);
1027 SetWindowPos(info
->popup
.hwndCallback
, HWND_TOP
, 0, 0,
1028 rect
.right
, rect
.bottom
, SWP_NOMOVE
);
1030 rect
.left
= TAB_MARGIN
;
1031 rect
.top
= TAB_TOP_PADDING
+ TAB_MARGIN
;
1032 rect
.right
-= TAB_RIGHT_PADDING
+ TAB_MARGIN
;
1033 rect
.bottom
-= TAB_MARGIN
;
1034 width
= rect
.right
-rect
.left
;
1035 height
= rect
.bottom
-rect
.top
;
1037 SetWindowPos(info
->popup
.hwndList
, NULL
, rect
.left
, rect
.top
, width
, height
,
1038 SWP_NOZORDER
| SWP_NOACTIVATE
);
1040 SendMessageW(info
->popup
.hwndList
, LVM_SETCOLUMNWIDTH
, 0,
1041 width
-scroll_width
-2*border_width
-2*edge_width
);
1044 static LRESULT CALLBACK
HelpPopup_WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1046 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1051 ResizePopupChild(info
);
1054 DestroyWindow(hWnd
);
1057 ShowWindow(hWnd
, SW_HIDE
);
1061 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
1067 static LRESULT CALLBACK
PopupChild_WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1072 NMHDR
*nmhdr
= (NMHDR
*)lParam
;
1076 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1079 if(info
== 0 || lParam
== 0)
1081 iter
= (IndexSubItem
*) ((NMITEMACTIVATE
*)lParam
)->lParam
;
1084 NavigateToChm(info
, info
->index
->merge
.chm_file
, iter
->local
);
1085 ShowWindow(info
->popup
.hwndPopup
, SW_HIDE
);
1089 HHInfo
*info
= (HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1096 lvItem
.iItem
= (int) SendMessageW(info
->popup
.hwndList
, LVM_GETSELECTIONMARK
, 0, 0);
1097 lvItem
.mask
= TVIF_PARAM
;
1098 SendMessageW(info
->popup
.hwndList
, LVM_GETITEMW
, 0, (LPARAM
)&lvItem
);
1099 iter
= (IndexSubItem
*) lvItem
.lParam
;
1100 NavigateToChm(info
, info
->index
->merge
.chm_file
, iter
->local
);
1101 ShowWindow(info
->popup
.hwndPopup
, SW_HIDE
);
1108 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
1114 static BOOL
AddIndexPopup(HHInfo
*info
)
1116 static const WCHAR szPopupChildClass
[] = {'H','H',' ','P','o','p','u','p',' ','C','h','i','l','d',0};
1117 static const WCHAR windowCaptionW
[] = {'S','e','l','e','c','t',' ','T','o','p','i','c',':',0};
1118 static const WCHAR windowClassW
[] = {'H','H',' ','P','o','p','u','p',0};
1119 HWND hwndList
, hwndPopup
, hwndCallback
;
1120 char hidden_column
[] = "Column";
1124 if(info
->tabs
[TAB_INDEX
].id
== -1)
1125 return TRUE
; /* No "Index" tab */
1127 wcex
.cbSize
= sizeof(WNDCLASSEXW
);
1128 wcex
.style
= CS_HREDRAW
| CS_VREDRAW
;
1129 wcex
.lpfnWndProc
= HelpPopup_WndProc
;
1130 wcex
.cbClsExtra
= 0;
1131 wcex
.cbWndExtra
= 0;
1132 wcex
.hInstance
= hhctrl_hinstance
;
1133 wcex
.hIcon
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
1134 wcex
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
)IDC_ARROW
);
1135 wcex
.hbrBackground
= (HBRUSH
)(COLOR_MENU
+ 1);
1136 wcex
.lpszMenuName
= NULL
;
1137 wcex
.lpszClassName
= windowClassW
;
1138 wcex
.hIconSm
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
1139 RegisterClassExW(&wcex
);
1141 wcex
.cbSize
= sizeof(WNDCLASSEXW
);
1143 wcex
.lpfnWndProc
= PopupChild_WndProc
;
1144 wcex
.cbClsExtra
= 0;
1145 wcex
.cbWndExtra
= 0;
1146 wcex
.hInstance
= hhctrl_hinstance
;
1147 wcex
.hIcon
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
1148 wcex
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
)IDC_ARROW
);
1149 wcex
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
1150 wcex
.lpszMenuName
= NULL
;
1151 wcex
.lpszClassName
= szPopupChildClass
;
1152 wcex
.hIconSm
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
1153 RegisterClassExW(&wcex
);
1155 hwndPopup
= CreateWindowExW(WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_APPWINDOW
1156 | WS_EX_WINDOWEDGE
| WS_EX_RIGHTSCROLLBAR
,
1157 windowClassW
, windowCaptionW
, WS_POPUPWINDOW
1158 | WS_OVERLAPPEDWINDOW
| WS_VISIBLE
1159 | WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
, CW_USEDEFAULT
,
1160 CW_USEDEFAULT
, 300, 200, info
->WinType
.hwndHelp
,
1161 NULL
, hhctrl_hinstance
, NULL
);
1165 hwndCallback
= CreateWindowExW(WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
,
1166 szPopupChildClass
, szEmpty
, WS_CHILDWINDOW
| WS_VISIBLE
,
1168 hwndPopup
, NULL
, hhctrl_hinstance
, NULL
);
1172 ShowWindow(hwndPopup
, SW_HIDE
);
1173 hwndList
= CreateWindowExW(WS_EX_CLIENTEDGE
, WC_LISTVIEWW
, szEmpty
,
1174 WS_CHILD
| WS_BORDER
| LVS_SINGLESEL
| LVS_REPORT
1175 | LVS_NOCOLUMNHEADER
, 50, 50, 100, 100,
1176 hwndCallback
, NULL
, hhctrl_hinstance
, NULL
);
1178 ERR("Could not create popup ListView control\n");
1181 memset(&lvc
, 0, sizeof(lvc
));
1182 lvc
.mask
= LVCF_TEXT
;
1183 lvc
.pszText
= hidden_column
;
1184 if(SendMessageW(hwndList
, LVM_INSERTCOLUMNA
, 0, (LPARAM
) &lvc
) == -1)
1186 ERR("Could not create popup ListView column\n");
1190 info
->popup
.hwndCallback
= hwndCallback
;
1191 info
->popup
.hwndPopup
= hwndPopup
;
1192 info
->popup
.hwndList
= hwndList
;
1193 SetWindowLongPtrW(hwndPopup
, GWLP_USERDATA
, (LONG_PTR
)info
);
1194 SetWindowLongPtrW(hwndCallback
, GWLP_USERDATA
, (LONG_PTR
)info
);
1196 ResizePopupChild(info
);
1197 ShowWindow(hwndList
, SW_SHOW
);
1204 static LRESULT
Help_OnSize(HWND hWnd
)
1206 HHInfo
*pHHInfo
= (HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1213 NP_GetNavigationRect(pHHInfo
, &rc
);
1214 SetWindowPos(pHHInfo
->WinType
.hwndNavigation
, HWND_TOP
, 0, 0,
1215 rc
.right
, rc
.bottom
, SWP_NOMOVE
);
1217 SB_GetSizeBarRect(pHHInfo
, &rc
);
1218 SetWindowPos(pHHInfo
->hwndSizeBar
, HWND_TOP
, rc
.left
, rc
.top
,
1219 rc
.right
, rc
.bottom
, SWP_SHOWWINDOW
);
1221 HP_GetHTMLRect(pHHInfo
, &rc
);
1222 SetWindowPos(pHHInfo
->WinType
.hwndHTML
, HWND_TOP
, rc
.left
, rc
.top
,
1223 rc
.right
, rc
.bottom
, SWP_SHOWWINDOW
);
1225 /* Resize browser window taking the frame size into account */
1226 dwSize
= GetSystemMetrics(SM_CXFRAME
);
1227 ResizeWebBrowser(pHHInfo
, rc
.right
- dwSize
, rc
.bottom
- dwSize
);
1232 static LRESULT CALLBACK
Help_WndProc(HWND hWnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1237 if (HIWORD(wParam
) == BN_CLICKED
)
1238 TB_OnClick(hWnd
, LOWORD(wParam
));
1241 return Help_OnSize(hWnd
);
1243 ReleaseHelpViewer((HHInfo
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
));
1251 return DefWindowProcW(hWnd
, message
, wParam
, lParam
);
1257 static BOOL
HH_CreateHelpWindow(HHInfo
*info
)
1260 RECT winPos
= info
->WinType
.rcWindowPos
;
1262 DWORD dwStyles
, dwExStyles
;
1263 DWORD x
, y
, width
= 0, height
= 0;
1266 static const WCHAR windowClassW
[] = {
1267 'H','H',' ', 'P','a','r','e','n','t',0
1270 wcex
.cbSize
= sizeof(WNDCLASSEXW
);
1271 wcex
.style
= CS_HREDRAW
| CS_VREDRAW
;
1272 wcex
.lpfnWndProc
= Help_WndProc
;
1273 wcex
.cbClsExtra
= 0;
1274 wcex
.cbWndExtra
= 0;
1275 wcex
.hInstance
= hhctrl_hinstance
;
1276 wcex
.hIcon
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
1277 wcex
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
)IDC_ARROW
);
1278 wcex
.hbrBackground
= (HBRUSH
)(COLOR_MENU
+ 1);
1279 wcex
.lpszMenuName
= NULL
;
1280 wcex
.lpszClassName
= windowClassW
;
1281 wcex
.hIconSm
= LoadIconW(NULL
, (LPCWSTR
)IDI_APPLICATION
);
1283 RegisterClassExW(&wcex
);
1285 /* Read in window parameters if available */
1286 if (info
->WinType
.fsValidMembers
& HHWIN_PARAM_STYLES
)
1287 dwStyles
= info
->WinType
.dwStyles
| WS_OVERLAPPEDWINDOW
;
1289 dwStyles
= WS_OVERLAPPEDWINDOW
| WS_VISIBLE
|
1290 WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
1292 if (info
->WinType
.fsValidMembers
& HHWIN_PARAM_EXSTYLES
)
1293 dwExStyles
= info
->WinType
.dwExStyles
;
1295 dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_APPWINDOW
|
1296 WS_EX_WINDOWEDGE
| WS_EX_RIGHTSCROLLBAR
;
1298 if (info
->WinType
.fsValidMembers
& HHWIN_PARAM_RECT
)
1302 width
= winPos
.right
- x
;
1303 height
= winPos
.bottom
- y
;
1305 if (!width
|| !height
)
1307 x
= WINTYPE_DEFAULT_X
;
1308 y
= WINTYPE_DEFAULT_Y
;
1309 width
= WINTYPE_DEFAULT_WIDTH
;
1310 height
= WINTYPE_DEFAULT_HEIGHT
;
1313 caption
= info
->WinType
.pszCaption
;
1314 if (!*caption
) caption
= info
->pCHMInfo
->defTitle
;
1316 hWnd
= CreateWindowExW(dwExStyles
, windowClassW
, caption
,
1317 dwStyles
, x
, y
, width
, height
, NULL
, NULL
, hhctrl_hinstance
, NULL
);
1321 ShowWindow(hWnd
, SW_SHOW
);
1324 /* store the pointer to the HH info struct */
1325 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (LONG_PTR
)info
);
1327 info
->WinType
.hwndHelp
= hWnd
;
1331 static void HH_CreateFont(HHInfo
*pHHInfo
)
1335 GetObjectW(GetStockObject(ANSI_VAR_FONT
), sizeof(LOGFONTW
), &lf
);
1336 lf
.lfWeight
= FW_NORMAL
;
1337 lf
.lfItalic
= FALSE
;
1338 lf
.lfUnderline
= FALSE
;
1340 pHHInfo
->hFont
= CreateFontIndirectW(&lf
);
1343 static void HH_InitRequiredControls(DWORD dwControls
)
1345 INITCOMMONCONTROLSEX icex
;
1347 icex
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
1348 icex
.dwICC
= dwControls
;
1349 InitCommonControlsEx(&icex
);
1352 /* Creates the whole package */
1353 static BOOL
CreateViewer(HHInfo
*pHHInfo
)
1355 HH_CreateFont(pHHInfo
);
1357 if (!HH_CreateHelpWindow(pHHInfo
))
1360 HH_InitRequiredControls(ICC_BAR_CLASSES
);
1362 if (!HH_AddToolbar(pHHInfo
))
1365 HH_RegisterChildWndClass(pHHInfo
);
1367 if (!HH_AddNavigationPane(pHHInfo
))
1370 HH_RegisterSizeBarClass(pHHInfo
);
1372 if (!HH_AddSizeBar(pHHInfo
))
1375 if (!HH_AddHTMLPane(pHHInfo
))
1378 if (!AddContentTab(pHHInfo
))
1381 if (!AddIndexTab(pHHInfo
))
1384 if (!AddIndexPopup(pHHInfo
))
1387 if (!AddSearchTab(pHHInfo
))
1390 InitContent(pHHInfo
);
1396 void ReleaseHelpViewer(HHInfo
*info
)
1398 TRACE("(%p)\n", info
);
1403 /* Free allocated strings */
1404 heap_free(info
->pszType
);
1405 heap_free(info
->pszCaption
);
1406 heap_free(info
->pszToc
);
1407 heap_free(info
->pszIndex
);
1408 heap_free(info
->pszFile
);
1409 heap_free(info
->pszHome
);
1410 heap_free(info
->pszJump1
);
1411 heap_free(info
->pszJump2
);
1412 heap_free(info
->pszUrlJump1
);
1413 heap_free(info
->pszUrlJump2
);
1416 CloseCHM(info
->pCHMInfo
);
1418 ReleaseWebBrowser(info
);
1419 ReleaseContent(info
);
1421 ReleaseSearch(info
);
1423 if(info
->WinType
.hwndHelp
)
1424 DestroyWindow(info
->WinType
.hwndHelp
);
1430 HHInfo
*CreateHelpViewer(LPCWSTR filename
)
1432 HHInfo
*info
= heap_alloc_zero(sizeof(HHInfo
));
1435 /* Set the invalid tab ID (-1) as the default value for all
1436 * of the tabs, this matches a failed TCM_INSERTITEM call.
1438 for(i
=0;i
<sizeof(info
->tabs
)/sizeof(HHTab
);i
++)
1439 info
->tabs
[i
].id
= -1;
1441 OleInitialize(NULL
);
1443 info
->pCHMInfo
= OpenCHM(filename
);
1444 if(!info
->pCHMInfo
) {
1445 ReleaseHelpViewer(info
);
1449 if (!LoadWinTypeFromCHM(info
)) {
1450 ReleaseHelpViewer(info
);
1454 if(!CreateViewer(info
)) {
1455 ReleaseHelpViewer(info
);