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
), 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
);