Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhelp.c
Go to the documentation of this file.
00001 /* 00002 * Help Viewer Implementation 00003 * 00004 * Copyright 2005 James Hawkins 00005 * Copyright 2007 Jacek Caban for CodeWeavers 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "hhctrl.h" 00023 00024 #include "wingdi.h" 00025 #include "commctrl.h" 00026 #include "wininet.h" 00027 00028 #include "wine/debug.h" 00029 00030 #include "resource.h" 00031 00032 WINE_DEFAULT_DEBUG_CHANNEL(htmlhelp); 00033 00034 static LRESULT Help_OnSize(HWND hWnd); 00035 00036 /* Window type defaults */ 00037 00038 #define WINTYPE_DEFAULT_X 280 00039 #define WINTYPE_DEFAULT_Y 100 00040 #define WINTYPE_DEFAULT_WIDTH 740 00041 #define WINTYPE_DEFAULT_HEIGHT 640 00042 #define WINTYPE_DEFAULT_NAVWIDTH 250 00043 00044 #define TAB_TOP_PADDING 8 00045 #define TAB_RIGHT_PADDING 4 00046 #define TAB_MARGIN 8 00047 #define EDIT_HEIGHT 20 00048 00049 static const WCHAR szEmpty[] = {0}; 00050 00051 /* Loads a string from the resource file */ 00052 static LPWSTR HH_LoadString(DWORD dwID) 00053 { 00054 LPWSTR string = NULL; 00055 LPCWSTR stringresource; 00056 int iSize; 00057 00058 iSize = LoadStringW(hhctrl_hinstance, dwID, (LPWSTR)&stringresource, 0); 00059 00060 string = heap_alloc((iSize + 2) * sizeof(WCHAR)); /* some strings (tab text) needs double-null termination */ 00061 memcpy(string, stringresource, iSize*sizeof(WCHAR)); 00062 string[iSize] = 0; 00063 00064 return string; 00065 } 00066 00067 static HRESULT navigate_url(HHInfo *info, LPCWSTR surl) 00068 { 00069 VARIANT url; 00070 HRESULT hres; 00071 00072 TRACE("%s\n", debugstr_w(surl)); 00073 00074 V_VT(&url) = VT_BSTR; 00075 V_BSTR(&url) = SysAllocString(surl); 00076 00077 hres = IWebBrowser2_Navigate2(info->web_browser, &url, 0, 0, 0, 0); 00078 00079 VariantClear(&url); 00080 00081 if(FAILED(hres)) 00082 TRACE("Navigation failed: %08x\n", hres); 00083 00084 return hres; 00085 } 00086 00087 BOOL NavigateToUrl(HHInfo *info, LPCWSTR surl) 00088 { 00089 ChmPath chm_path; 00090 BOOL ret; 00091 HRESULT hres; 00092 00093 static const WCHAR url_indicator[] = {':', '/', '/', 0}; 00094 00095 TRACE("%s\n", debugstr_w(surl)); 00096 00097 if (strstrW(surl, url_indicator)) { 00098 hres = navigate_url(info, surl); 00099 if(SUCCEEDED(hres)) 00100 return TRUE; 00101 } /* look up in chm if it doesn't look like a full url */ 00102 00103 SetChmPath(&chm_path, info->pCHMInfo->szFile, surl); 00104 ret = NavigateToChm(info, chm_path.chm_file, chm_path.chm_index); 00105 00106 heap_free(chm_path.chm_file); 00107 heap_free(chm_path.chm_index); 00108 00109 return ret; 00110 } 00111 00112 BOOL NavigateToChm(HHInfo *info, LPCWSTR file, LPCWSTR index) 00113 { 00114 WCHAR buf[INTERNET_MAX_URL_LENGTH]; 00115 WCHAR full_path[MAX_PATH]; 00116 LPWSTR ptr; 00117 00118 static const WCHAR url_format[] = 00119 {'m','k',':','@','M','S','I','T','S','t','o','r','e',':','%','s',':',':','%','s','%','s',0}; 00120 static const WCHAR slash[] = {'/',0}; 00121 static const WCHAR empty[] = {0}; 00122 00123 TRACE("%p %s %s\n", info, debugstr_w(file), debugstr_w(index)); 00124 00125 if (!info->web_browser) 00126 return FALSE; 00127 00128 if(!GetFullPathNameW(file, sizeof(full_path)/sizeof(full_path[0]), full_path, NULL)) { 00129 WARN("GetFullPathName failed: %u\n", GetLastError()); 00130 return FALSE; 00131 } 00132 00133 wsprintfW(buf, url_format, full_path, (!index || index[0] == '/') ? empty : slash, index); 00134 00135 /* FIXME: HACK */ 00136 if((ptr = strchrW(buf, '#'))) 00137 *ptr = 0; 00138 00139 return SUCCEEDED(navigate_url(info, buf)); 00140 } 00141 00142 /* Size Bar */ 00143 00144 #define SIZEBAR_WIDTH 4 00145 00146 static const WCHAR szSizeBarClass[] = { 00147 'H','H',' ','S','i','z','e','B','a','r',0 00148 }; 00149 00150 /* Draw the SizeBar */ 00151 static void SB_OnPaint(HWND hWnd) 00152 { 00153 PAINTSTRUCT ps; 00154 HDC hdc; 00155 RECT rc; 00156 00157 hdc = BeginPaint(hWnd, &ps); 00158 00159 GetClientRect(hWnd, &rc); 00160 00161 /* dark frame */ 00162 rc.right += 1; 00163 rc.bottom -= 1; 00164 FrameRect(hdc, &rc, GetStockObject(GRAY_BRUSH)); 00165 00166 /* white highlight */ 00167 SelectObject(hdc, GetStockObject(WHITE_PEN)); 00168 MoveToEx(hdc, rc.right, 1, NULL); 00169 LineTo(hdc, 1, 1); 00170 LineTo(hdc, 1, rc.bottom - 1); 00171 00172 00173 MoveToEx(hdc, 0, rc.bottom, NULL); 00174 LineTo(hdc, rc.right, rc.bottom); 00175 00176 EndPaint(hWnd, &ps); 00177 } 00178 00179 static void SB_OnLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam) 00180 { 00181 SetCapture(hWnd); 00182 } 00183 00184 static void SB_OnLButtonUp(HWND hWnd, WPARAM wParam, LPARAM lParam) 00185 { 00186 HHInfo *pHHInfo = (HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA); 00187 POINT pt; 00188 00189 pt.x = (short)LOWORD(lParam); 00190 pt.y = (short)HIWORD(lParam); 00191 00192 /* update the window sizes */ 00193 pHHInfo->WinType.iNavWidth += pt.x; 00194 Help_OnSize(hWnd); 00195 00196 ReleaseCapture(); 00197 } 00198 00199 static void SB_OnMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam) 00200 { 00201 /* ignore WM_MOUSEMOVE if not dragging the SizeBar */ 00202 if (!(wParam & MK_LBUTTON)) 00203 return; 00204 } 00205 00206 static LRESULT CALLBACK SizeBar_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 00207 { 00208 switch (message) 00209 { 00210 case WM_LBUTTONDOWN: 00211 SB_OnLButtonDown(hWnd, wParam, lParam); 00212 break; 00213 case WM_LBUTTONUP: 00214 SB_OnLButtonUp(hWnd, wParam, lParam); 00215 break; 00216 case WM_MOUSEMOVE: 00217 SB_OnMouseMove(hWnd, wParam, lParam); 00218 break; 00219 case WM_PAINT: 00220 SB_OnPaint(hWnd); 00221 break; 00222 default: 00223 return DefWindowProcW(hWnd, message, wParam, lParam); 00224 } 00225 00226 return 0; 00227 } 00228 00229 static void HH_RegisterSizeBarClass(HHInfo *pHHInfo) 00230 { 00231 WNDCLASSEXW wcex; 00232 00233 wcex.cbSize = sizeof(WNDCLASSEXW); 00234 wcex.style = 0; 00235 wcex.lpfnWndProc = SizeBar_WndProc; 00236 wcex.cbClsExtra = 0; 00237 wcex.cbWndExtra = 0; 00238 wcex.hInstance = hhctrl_hinstance; 00239 wcex.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION); 00240 wcex.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_SIZEWE); 00241 wcex.hbrBackground = (HBRUSH)(COLOR_MENU + 1); 00242 wcex.lpszMenuName = NULL; 00243 wcex.lpszClassName = szSizeBarClass; 00244 wcex.hIconSm = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION); 00245 00246 RegisterClassExW(&wcex); 00247 } 00248 00249 static void SB_GetSizeBarRect(HHInfo *info, RECT *rc) 00250 { 00251 RECT rectWND, rectTB, rectNP; 00252 00253 GetClientRect(info->WinType.hwndHelp, &rectWND); 00254 GetClientRect(info->WinType.hwndToolBar, &rectTB); 00255 GetClientRect(info->WinType.hwndNavigation, &rectNP); 00256 00257 rc->left = rectNP.right; 00258 rc->top = rectTB.bottom; 00259 rc->bottom = rectWND.bottom - rectTB.bottom; 00260 rc->right = SIZEBAR_WIDTH; 00261 } 00262 00263 static BOOL HH_AddSizeBar(HHInfo *pHHInfo) 00264 { 00265 HWND hWnd; 00266 HWND hwndParent = pHHInfo->WinType.hwndHelp; 00267 DWORD dwStyles = WS_CHILDWINDOW | WS_VISIBLE | WS_OVERLAPPED; 00268 DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR; 00269 RECT rc; 00270 00271 SB_GetSizeBarRect(pHHInfo, &rc); 00272 00273 hWnd = CreateWindowExW(dwExStyles, szSizeBarClass, szEmpty, dwStyles, 00274 rc.left, rc.top, rc.right, rc.bottom, 00275 hwndParent, NULL, hhctrl_hinstance, NULL); 00276 if (!hWnd) 00277 return FALSE; 00278 00279 /* store the pointer to the HH info struct */ 00280 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)pHHInfo); 00281 00282 pHHInfo->hwndSizeBar = hWnd; 00283 return TRUE; 00284 } 00285 00286 /* Child Window */ 00287 00288 static const WCHAR szChildClass[] = { 00289 'H','H',' ','C','h','i','l','d',0 00290 }; 00291 00292 static LRESULT Child_OnPaint(HWND hWnd) 00293 { 00294 PAINTSTRUCT ps; 00295 HDC hdc; 00296 RECT rc; 00297 00298 hdc = BeginPaint(hWnd, &ps); 00299 00300 /* Only paint the Navigation pane, identified by the fact 00301 * that it has a child window 00302 */ 00303 if (GetWindow(hWnd, GW_CHILD)) 00304 { 00305 GetClientRect(hWnd, &rc); 00306 00307 /* set the border color */ 00308 SelectObject(hdc, GetStockObject(DC_PEN)); 00309 SetDCPenColor(hdc, GetSysColor(COLOR_BTNSHADOW)); 00310 00311 /* Draw the top border */ 00312 LineTo(hdc, rc.right, 0); 00313 00314 SelectObject(hdc, GetStockObject(WHITE_PEN)); 00315 MoveToEx(hdc, 0, 1, NULL); 00316 LineTo(hdc, rc.right, 1); 00317 } 00318 00319 EndPaint(hWnd, &ps); 00320 00321 return 0; 00322 } 00323 00324 static void ResizeTabChild(HHInfo *info, int tab) 00325 { 00326 HWND hwnd = info->tabs[tab].hwnd; 00327 INT width, height; 00328 RECT rect, tabrc; 00329 DWORD cnt; 00330 00331 GetClientRect(info->WinType.hwndNavigation, &rect); 00332 SendMessageW(info->hwndTabCtrl, TCM_GETITEMRECT, 0, (LPARAM)&tabrc); 00333 cnt = SendMessageW(info->hwndTabCtrl, TCM_GETROWCOUNT, 0, 0); 00334 00335 rect.left = TAB_MARGIN; 00336 rect.top = TAB_TOP_PADDING + cnt*(tabrc.bottom-tabrc.top) + TAB_MARGIN; 00337 rect.right -= TAB_RIGHT_PADDING + TAB_MARGIN; 00338 rect.bottom -= TAB_MARGIN; 00339 width = rect.right-rect.left; 00340 height = rect.bottom-rect.top; 00341 00342 SetWindowPos(hwnd, NULL, rect.left, rect.top, width, height, 00343 SWP_NOZORDER | SWP_NOACTIVATE); 00344 00345 switch (tab) 00346 { 00347 case TAB_INDEX: { 00348 int scroll_width = GetSystemMetrics(SM_CXVSCROLL); 00349 int border_width = GetSystemMetrics(SM_CXBORDER); 00350 int edge_width = GetSystemMetrics(SM_CXEDGE); 00351 00352 /* Resize the tab widget column to perfectly fit the tab window and 00353 * leave sufficient space for the scroll widget. 00354 */ 00355 SendMessageW(info->tabs[TAB_INDEX].hwnd, LVM_SETCOLUMNWIDTH, 0, 00356 width-scroll_width-2*border_width-2*edge_width); 00357 00358 break; 00359 } 00360 case TAB_SEARCH: { 00361 int scroll_width = GetSystemMetrics(SM_CXVSCROLL); 00362 int border_width = GetSystemMetrics(SM_CXBORDER); 00363 int edge_width = GetSystemMetrics(SM_CXEDGE); 00364 int top_pos = 0; 00365 00366 SetWindowPos(info->search.hwndEdit, NULL, 0, top_pos, width, 00367 EDIT_HEIGHT, SWP_NOZORDER | SWP_NOACTIVATE); 00368 top_pos += EDIT_HEIGHT + TAB_MARGIN; 00369 SetWindowPos(info->search.hwndList, NULL, 0, top_pos, width, 00370 height-top_pos, SWP_NOZORDER | SWP_NOACTIVATE); 00371 /* Resize the tab widget column to perfectly fit the tab window and 00372 * leave sufficient space for the scroll widget. 00373 */ 00374 SendMessageW(info->search.hwndList, LVM_SETCOLUMNWIDTH, 0, 00375 width-scroll_width-2*border_width-2*edge_width); 00376 00377 break; 00378 } 00379 } 00380 } 00381 00382 static LRESULT Child_OnSize(HWND hwnd) 00383 { 00384 HHInfo *info = (HHInfo*)GetWindowLongPtrW(hwnd, GWLP_USERDATA); 00385 RECT rect; 00386 00387 if(!info || hwnd != info->WinType.hwndNavigation) 00388 return 0; 00389 00390 GetClientRect(hwnd, &rect); 00391 SetWindowPos(info->hwndTabCtrl, HWND_TOP, 0, 0, 00392 rect.right - TAB_RIGHT_PADDING, 00393 rect.bottom - TAB_TOP_PADDING, SWP_NOMOVE); 00394 00395 ResizeTabChild(info, TAB_CONTENTS); 00396 ResizeTabChild(info, TAB_INDEX); 00397 return 0; 00398 } 00399 00400 static LRESULT OnTabChange(HWND hwnd) 00401 { 00402 HHInfo *info = (HHInfo*)GetWindowLongPtrW(hwnd, GWLP_USERDATA); 00403 00404 TRACE("%p\n", hwnd); 00405 00406 if (!info) 00407 return 0; 00408 00409 if(info->tabs[info->current_tab].hwnd) 00410 ShowWindow(info->tabs[info->current_tab].hwnd, SW_HIDE); 00411 00412 info->current_tab = SendMessageW(info->hwndTabCtrl, TCM_GETCURSEL, 0, 0); 00413 00414 if(info->tabs[info->current_tab].hwnd) 00415 ShowWindow(info->tabs[info->current_tab].hwnd, SW_SHOW); 00416 00417 return 0; 00418 } 00419 00420 static LRESULT OnTopicChange(HHInfo *info, void *user_data) 00421 { 00422 LPCWSTR chmfile = NULL, name = NULL, local = NULL; 00423 ContentItem *citer; 00424 SearchItem *siter; 00425 IndexItem *iiter; 00426 00427 if(!user_data || !info) 00428 return 0; 00429 00430 switch (info->current_tab) 00431 { 00432 case TAB_CONTENTS: 00433 citer = (ContentItem *) user_data; 00434 name = citer->name; 00435 local = citer->local; 00436 while(citer) { 00437 if(citer->merge.chm_file) { 00438 chmfile = citer->merge.chm_file; 00439 break; 00440 } 00441 citer = citer->parent; 00442 } 00443 break; 00444 case TAB_INDEX: 00445 iiter = (IndexItem *) user_data; 00446 if(iiter->nItems == 0) { 00447 FIXME("No entries for this item!\n"); 00448 return 0; 00449 } 00450 if(iiter->nItems > 1) { 00451 int i = 0; 00452 LVITEMW lvi; 00453 00454 SendMessageW(info->popup.hwndList, LVM_DELETEALLITEMS, 0, 0); 00455 for(i=0;i<iiter->nItems;i++) { 00456 IndexSubItem *item = &iiter->items[i]; 00457 WCHAR *name = iiter->keyword; 00458 00459 if(item->name) 00460 name = item->name; 00461 memset(&lvi, 0, sizeof(lvi)); 00462 lvi.iItem = i; 00463 lvi.mask = LVIF_TEXT|LVIF_PARAM; 00464 lvi.cchTextMax = strlenW(name)+1; 00465 lvi.pszText = name; 00466 lvi.lParam = (LPARAM) item; 00467 SendMessageW(info->popup.hwndList, LVM_INSERTITEMW, 0, (LPARAM)&lvi); 00468 } 00469 ShowWindow(info->popup.hwndPopup, SW_SHOW); 00470 return 0; 00471 } 00472 name = iiter->items[0].name; 00473 local = iiter->items[0].local; 00474 chmfile = iiter->merge.chm_file; 00475 break; 00476 case TAB_SEARCH: 00477 siter = (SearchItem *) user_data; 00478 name = siter->filename; 00479 local = siter->filename; 00480 chmfile = info->pCHMInfo->szFile; 00481 break; 00482 default: 00483 FIXME("Unhandled operation for this tab!\n"); 00484 return 0; 00485 } 00486 00487 if(!chmfile) 00488 { 00489 FIXME("No help file found for this item!\n"); 00490 return 0; 00491 } 00492 00493 TRACE("name %s loal %s\n", debugstr_w(name), debugstr_w(local)); 00494 00495 NavigateToChm(info, chmfile, local); 00496 return 0; 00497 } 00498 00499 /* Capture the Enter/Return key and send it up to Child_WndProc as an NM_RETURN message */ 00500 static LRESULT CALLBACK EditChild_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 00501 { 00502 WNDPROC editWndProc = (WNDPROC)GetWindowLongPtrW(hWnd, GWLP_USERDATA); 00503 00504 if(message == WM_KEYUP && wParam == VK_RETURN) 00505 { 00506 NMHDR nmhdr; 00507 00508 nmhdr.hwndFrom = hWnd; 00509 nmhdr.code = NM_RETURN; 00510 SendMessageW(GetParent(GetParent(hWnd)), WM_NOTIFY, wParam, (LPARAM)&nmhdr); 00511 } 00512 return editWndProc(hWnd, message, wParam, lParam); 00513 } 00514 00515 static LRESULT CALLBACK Child_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 00516 { 00517 switch (message) 00518 { 00519 case WM_PAINT: 00520 return Child_OnPaint(hWnd); 00521 case WM_SIZE: 00522 return Child_OnSize(hWnd); 00523 case WM_NOTIFY: { 00524 HHInfo *info = (HHInfo*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); 00525 NMHDR *nmhdr = (NMHDR*)lParam; 00526 00527 switch(nmhdr->code) { 00528 case TCN_SELCHANGE: 00529 return OnTabChange(hWnd); 00530 case TVN_SELCHANGEDW: 00531 return OnTopicChange(info, (void*)((NMTREEVIEWW *)lParam)->itemNew.lParam); 00532 case NM_DBLCLK: 00533 if(!info) 00534 return 0; 00535 switch(info->current_tab) 00536 { 00537 case TAB_INDEX: 00538 return OnTopicChange(info, (void*)((NMITEMACTIVATE *)lParam)->lParam); 00539 case TAB_SEARCH: 00540 return OnTopicChange(info, (void*)((NMITEMACTIVATE *)lParam)->lParam); 00541 } 00542 break; 00543 case NM_RETURN: 00544 if(!info) 00545 return 0; 00546 switch(info->current_tab) { 00547 case TAB_INDEX: { 00548 HWND hwndList = info->tabs[TAB_INDEX].hwnd; 00549 LVITEMW lvItem; 00550 00551 lvItem.iItem = (int) SendMessageW(hwndList, LVM_GETSELECTIONMARK, 0, 0); 00552 lvItem.mask = TVIF_PARAM; 00553 SendMessageW(hwndList, LVM_GETITEMW, 0, (LPARAM)&lvItem); 00554 OnTopicChange(info, (void*) lvItem.lParam); 00555 return 0; 00556 } 00557 case TAB_SEARCH: { 00558 if(nmhdr->hwndFrom == info->search.hwndEdit) { 00559 char needle[100]; 00560 DWORD i, len; 00561 00562 len = GetWindowTextA(info->search.hwndEdit, needle, sizeof(needle)); 00563 if(!len) 00564 { 00565 FIXME("Unable to get search text.\n"); 00566 return 0; 00567 } 00568 /* Convert the requested text for comparison later against the 00569 * lower case version of HTML file contents. 00570 */ 00571 for(i=0;i<len;i++) 00572 needle[i] = tolower(needle[i]); 00573 InitSearch(info, needle); 00574 return 0; 00575 }else if(nmhdr->hwndFrom == info->search.hwndList) { 00576 HWND hwndList = info->search.hwndList; 00577 LVITEMW lvItem; 00578 00579 lvItem.iItem = (int) SendMessageW(hwndList, LVM_GETSELECTIONMARK, 0, 0); 00580 lvItem.mask = TVIF_PARAM; 00581 SendMessageW(hwndList, LVM_GETITEMW, 0, (LPARAM)&lvItem); 00582 OnTopicChange(info, (void*) lvItem.lParam); 00583 return 0; 00584 } 00585 break; 00586 } 00587 } 00588 break; 00589 } 00590 break; 00591 } 00592 default: 00593 return DefWindowProcW(hWnd, message, wParam, lParam); 00594 } 00595 00596 return 0; 00597 } 00598 00599 static void HH_RegisterChildWndClass(HHInfo *pHHInfo) 00600 { 00601 WNDCLASSEXW wcex; 00602 00603 wcex.cbSize = sizeof(WNDCLASSEXW); 00604 wcex.style = 0; 00605 wcex.lpfnWndProc = Child_WndProc; 00606 wcex.cbClsExtra = 0; 00607 wcex.cbWndExtra = 0; 00608 wcex.hInstance = hhctrl_hinstance; 00609 wcex.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION); 00610 wcex.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); 00611 wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); 00612 wcex.lpszMenuName = NULL; 00613 wcex.lpszClassName = szChildClass; 00614 wcex.hIconSm = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION); 00615 00616 RegisterClassExW(&wcex); 00617 } 00618 00619 /* Toolbar */ 00620 00621 #define ICON_SIZE 20 00622 00623 static void TB_OnClick(HWND hWnd, DWORD dwID) 00624 { 00625 HHInfo *info = (HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA); 00626 00627 switch (dwID) 00628 { 00629 case IDTB_STOP: 00630 DoPageAction(info, WB_STOP); 00631 break; 00632 case IDTB_REFRESH: 00633 DoPageAction(info, WB_REFRESH); 00634 break; 00635 case IDTB_BACK: 00636 DoPageAction(info, WB_GOBACK); 00637 break; 00638 case IDTB_HOME: 00639 NavigateToChm(info, info->pCHMInfo->szFile, info->WinType.pszHome); 00640 break; 00641 case IDTB_FORWARD: 00642 DoPageAction(info, WB_GOFORWARD); 00643 break; 00644 case IDTB_EXPAND: 00645 case IDTB_CONTRACT: 00646 case IDTB_SYNC: 00647 case IDTB_PRINT: 00648 case IDTB_OPTIONS: 00649 case IDTB_BROWSE_FWD: 00650 case IDTB_BROWSE_BACK: 00651 case IDTB_JUMP1: 00652 case IDTB_JUMP2: 00653 case IDTB_CUSTOMIZE: 00654 case IDTB_ZOOM: 00655 case IDTB_TOC_NEXT: 00656 case IDTB_TOC_PREV: 00657 break; 00658 } 00659 } 00660 00661 static void TB_AddButton(TBBUTTON *pButtons, DWORD dwIndex, DWORD dwID) 00662 { 00663 /* FIXME: Load the correct button bitmaps */ 00664 pButtons[dwIndex].iBitmap = STD_PRINT; 00665 pButtons[dwIndex].idCommand = dwID; 00666 pButtons[dwIndex].fsState = TBSTATE_ENABLED; 00667 pButtons[dwIndex].fsStyle = BTNS_BUTTON; 00668 pButtons[dwIndex].dwData = 0; 00669 pButtons[dwIndex].iString = 0; 00670 } 00671 00672 static void TB_AddButtonsFromFlags(TBBUTTON *pButtons, DWORD dwButtonFlags, LPDWORD pdwNumButtons) 00673 { 00674 *pdwNumButtons = 0; 00675 00676 if (dwButtonFlags & HHWIN_BUTTON_EXPAND) 00677 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_EXPAND); 00678 00679 if (dwButtonFlags & HHWIN_BUTTON_BACK) 00680 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_BACK); 00681 00682 if (dwButtonFlags & HHWIN_BUTTON_FORWARD) 00683 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_FORWARD); 00684 00685 if (dwButtonFlags & HHWIN_BUTTON_STOP) 00686 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_STOP); 00687 00688 if (dwButtonFlags & HHWIN_BUTTON_REFRESH) 00689 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_REFRESH); 00690 00691 if (dwButtonFlags & HHWIN_BUTTON_HOME) 00692 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_HOME); 00693 00694 if (dwButtonFlags & HHWIN_BUTTON_SYNC) 00695 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_SYNC); 00696 00697 if (dwButtonFlags & HHWIN_BUTTON_OPTIONS) 00698 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_OPTIONS); 00699 00700 if (dwButtonFlags & HHWIN_BUTTON_PRINT) 00701 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_PRINT); 00702 00703 if (dwButtonFlags & HHWIN_BUTTON_JUMP1) 00704 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_JUMP1); 00705 00706 if (dwButtonFlags & HHWIN_BUTTON_JUMP2) 00707 TB_AddButton(pButtons,(*pdwNumButtons)++, IDTB_JUMP2); 00708 00709 if (dwButtonFlags & HHWIN_BUTTON_ZOOM) 00710 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_ZOOM); 00711 00712 if (dwButtonFlags & HHWIN_BUTTON_TOC_NEXT) 00713 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_TOC_NEXT); 00714 00715 if (dwButtonFlags & HHWIN_BUTTON_TOC_PREV) 00716 TB_AddButton(pButtons, (*pdwNumButtons)++, IDTB_TOC_PREV); 00717 } 00718 00719 static BOOL HH_AddToolbar(HHInfo *pHHInfo) 00720 { 00721 HWND hToolbar; 00722 HWND hwndParent = pHHInfo->WinType.hwndHelp; 00723 DWORD toolbarFlags; 00724 TBBUTTON buttons[IDTB_TOC_PREV - IDTB_EXPAND]; 00725 TBADDBITMAP tbAB; 00726 DWORD dwStyles, dwExStyles; 00727 DWORD dwNumButtons, dwIndex; 00728 00729 if (pHHInfo->WinType.fsWinProperties & HHWIN_PARAM_TB_FLAGS) 00730 toolbarFlags = pHHInfo->WinType.fsToolBarFlags; 00731 else 00732 toolbarFlags = HHWIN_DEF_BUTTONS; 00733 00734 TB_AddButtonsFromFlags(buttons, toolbarFlags, &dwNumButtons); 00735 00736 dwStyles = WS_CHILDWINDOW | WS_VISIBLE | TBSTYLE_FLAT | 00737 TBSTYLE_WRAPABLE | TBSTYLE_TOOLTIPS | CCS_NODIVIDER; 00738 dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR; 00739 00740 hToolbar = CreateWindowExW(dwExStyles, TOOLBARCLASSNAMEW, NULL, dwStyles, 00741 0, 0, 0, 0, hwndParent, NULL, 00742 hhctrl_hinstance, NULL); 00743 if (!hToolbar) 00744 return FALSE; 00745 00746 SendMessageW(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(ICON_SIZE, ICON_SIZE)); 00747 SendMessageW(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); 00748 SendMessageW(hToolbar, WM_SETFONT, (WPARAM)pHHInfo->hFont, TRUE); 00749 00750 /* FIXME: Load correct icons for all buttons */ 00751 tbAB.hInst = HINST_COMMCTRL; 00752 tbAB.nID = IDB_STD_LARGE_COLOR; 00753 SendMessageW(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&tbAB); 00754 00755 for (dwIndex = 0; dwIndex < dwNumButtons; dwIndex++) 00756 { 00757 LPWSTR szBuf = HH_LoadString(buttons[dwIndex].idCommand); 00758 DWORD dwLen = strlenW(szBuf); 00759 szBuf[dwLen + 1] = 0; /* Double-null terminate */ 00760 00761 buttons[dwIndex].iString = (DWORD)SendMessageW(hToolbar, TB_ADDSTRINGW, 0, (LPARAM)szBuf); 00762 heap_free(szBuf); 00763 } 00764 00765 SendMessageW(hToolbar, TB_ADDBUTTONSW, dwNumButtons, (LPARAM)buttons); 00766 SendMessageW(hToolbar, TB_AUTOSIZE, 0, 0); 00767 ShowWindow(hToolbar, SW_SHOW); 00768 00769 pHHInfo->WinType.hwndToolBar = hToolbar; 00770 return TRUE; 00771 } 00772 00773 /* Navigation Pane */ 00774 00775 static void NP_GetNavigationRect(HHInfo *pHHInfo, RECT *rc) 00776 { 00777 HWND hwndParent = pHHInfo->WinType.hwndHelp; 00778 HWND hwndToolbar = pHHInfo->WinType.hwndToolBar; 00779 RECT rectWND, rectTB; 00780 00781 GetClientRect(hwndParent, &rectWND); 00782 GetClientRect(hwndToolbar, &rectTB); 00783 00784 rc->left = 0; 00785 rc->top = rectTB.bottom; 00786 rc->bottom = rectWND.bottom - rectTB.bottom; 00787 00788 if (!(pHHInfo->WinType.fsValidMembers & HHWIN_PARAM_NAV_WIDTH) && 00789 pHHInfo->WinType.iNavWidth == 0) 00790 { 00791 pHHInfo->WinType.iNavWidth = WINTYPE_DEFAULT_NAVWIDTH; 00792 } 00793 00794 rc->right = pHHInfo->WinType.iNavWidth; 00795 } 00796 00797 static DWORD NP_CreateTab(HINSTANCE hInstance, HWND hwndTabCtrl, DWORD index) 00798 { 00799 TCITEMW tie; 00800 LPWSTR tabText = HH_LoadString(index); 00801 DWORD ret; 00802 00803 tie.mask = TCIF_TEXT; 00804 tie.pszText = tabText; 00805 00806 ret = SendMessageW( hwndTabCtrl, TCM_INSERTITEMW, index, (LPARAM)&tie ); 00807 00808 heap_free(tabText); 00809 return ret; 00810 } 00811 00812 static BOOL HH_AddNavigationPane(HHInfo *info) 00813 { 00814 HWND hWnd, hwndTabCtrl; 00815 HWND hwndParent = info->WinType.hwndHelp; 00816 DWORD dwStyles = WS_CHILDWINDOW | WS_VISIBLE; 00817 DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR; 00818 RECT rc; 00819 00820 NP_GetNavigationRect(info, &rc); 00821 00822 hWnd = CreateWindowExW(dwExStyles, szChildClass, szEmpty, dwStyles, 00823 rc.left, rc.top, rc.right, rc.bottom, 00824 hwndParent, NULL, hhctrl_hinstance, NULL); 00825 if (!hWnd) 00826 return FALSE; 00827 00828 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)info); 00829 00830 hwndTabCtrl = CreateWindowExW(dwExStyles, WC_TABCONTROLW, szEmpty, dwStyles, 00831 0, TAB_TOP_PADDING, 00832 rc.right - TAB_RIGHT_PADDING, 00833 rc.bottom - TAB_TOP_PADDING, 00834 hWnd, NULL, hhctrl_hinstance, NULL); 00835 if (!hwndTabCtrl) 00836 return FALSE; 00837 00838 if (*info->WinType.pszToc) 00839 info->tabs[TAB_CONTENTS].id = NP_CreateTab(hhctrl_hinstance, hwndTabCtrl, IDS_CONTENTS); 00840 00841 if (*info->WinType.pszIndex) 00842 info->tabs[TAB_INDEX].id = NP_CreateTab(hhctrl_hinstance, hwndTabCtrl, IDS_INDEX); 00843 00844 if (info->WinType.fsWinProperties & HHWIN_PROP_TAB_SEARCH) 00845 info->tabs[TAB_SEARCH].id = NP_CreateTab(hhctrl_hinstance, hwndTabCtrl, IDS_SEARCH); 00846 00847 if (info->WinType.fsWinProperties & HHWIN_PROP_TAB_FAVORITES) 00848 info->tabs[TAB_FAVORITES].id = NP_CreateTab(hhctrl_hinstance, hwndTabCtrl, IDS_FAVORITES); 00849 00850 SendMessageW(hwndTabCtrl, WM_SETFONT, (WPARAM)info->hFont, TRUE); 00851 00852 info->hwndTabCtrl = hwndTabCtrl; 00853 info->WinType.hwndNavigation = hWnd; 00854 return TRUE; 00855 } 00856 00857 /* HTML Pane */ 00858 00859 static void HP_GetHTMLRect(HHInfo *info, RECT *rc) 00860 { 00861 RECT rectTB, rectWND, rectNP, rectSB; 00862 00863 GetClientRect(info->WinType.hwndHelp, &rectWND); 00864 GetClientRect(info->WinType.hwndToolBar, &rectTB); 00865 GetClientRect(info->WinType.hwndNavigation, &rectNP); 00866 GetClientRect(info->hwndSizeBar, &rectSB); 00867 00868 rc->left = rectNP.right + rectSB.right; 00869 rc->top = rectTB.bottom; 00870 rc->right = rectWND.right - rc->left; 00871 rc->bottom = rectWND.bottom - rectTB.bottom; 00872 } 00873 00874 static BOOL HH_AddHTMLPane(HHInfo *pHHInfo) 00875 { 00876 HWND hWnd; 00877 HWND hwndParent = pHHInfo->WinType.hwndHelp; 00878 DWORD dwStyles = WS_CHILDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN; 00879 DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_CLIENTEDGE; 00880 RECT rc; 00881 00882 HP_GetHTMLRect(pHHInfo, &rc); 00883 00884 hWnd = CreateWindowExW(dwExStyles, szChildClass, szEmpty, dwStyles, 00885 rc.left, rc.top, rc.right, rc.bottom, 00886 hwndParent, NULL, hhctrl_hinstance, NULL); 00887 if (!hWnd) 00888 return FALSE; 00889 00890 if (!InitWebBrowser(pHHInfo, hWnd)) 00891 return FALSE; 00892 00893 /* store the pointer to the HH info struct */ 00894 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)pHHInfo); 00895 00896 ShowWindow(hWnd, SW_SHOW); 00897 UpdateWindow(hWnd); 00898 00899 pHHInfo->WinType.hwndHTML = hWnd; 00900 return TRUE; 00901 } 00902 00903 static BOOL AddContentTab(HHInfo *info) 00904 { 00905 if(info->tabs[TAB_CONTENTS].id == -1) 00906 return TRUE; /* No "Contents" tab */ 00907 info->tabs[TAB_CONTENTS].hwnd = CreateWindowExW(WS_EX_CLIENTEDGE, WC_TREEVIEWW, 00908 szEmpty, WS_CHILD | WS_BORDER | 0x25, 50, 50, 100, 100, 00909 info->WinType.hwndNavigation, NULL, hhctrl_hinstance, NULL); 00910 if(!info->tabs[TAB_CONTENTS].hwnd) { 00911 ERR("Could not create treeview control\n"); 00912 return FALSE; 00913 } 00914 00915 ResizeTabChild(info, TAB_CONTENTS); 00916 ShowWindow(info->tabs[TAB_CONTENTS].hwnd, SW_SHOW); 00917 00918 return TRUE; 00919 } 00920 00921 static BOOL AddIndexTab(HHInfo *info) 00922 { 00923 char hidden_column[] = "Column"; 00924 LVCOLUMNA lvc; 00925 00926 if(info->tabs[TAB_INDEX].id == -1) 00927 return TRUE; /* No "Index" tab */ 00928 info->tabs[TAB_INDEX].hwnd = CreateWindowExW(WS_EX_CLIENTEDGE, WC_LISTVIEWW, 00929 szEmpty, WS_CHILD | WS_BORDER | LVS_SINGLESEL | LVS_REPORT | LVS_NOCOLUMNHEADER, 50, 50, 100, 100, 00930 info->WinType.hwndNavigation, NULL, hhctrl_hinstance, NULL); 00931 if(!info->tabs[TAB_INDEX].hwnd) { 00932 ERR("Could not create ListView control\n"); 00933 return FALSE; 00934 } 00935 memset(&lvc, 0, sizeof(lvc)); 00936 lvc.mask = LVCF_TEXT; 00937 lvc.pszText = hidden_column; 00938 if(SendMessageW(info->tabs[TAB_INDEX].hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM) &lvc) == -1) 00939 { 00940 ERR("Could not create ListView column\n"); 00941 return FALSE; 00942 } 00943 00944 ResizeTabChild(info, TAB_INDEX); 00945 ShowWindow(info->tabs[TAB_INDEX].hwnd, SW_HIDE); 00946 00947 return TRUE; 00948 } 00949 00950 static BOOL AddSearchTab(HHInfo *info) 00951 { 00952 HWND hwndList, hwndEdit, hwndContainer; 00953 char hidden_column[] = "Column"; 00954 WNDPROC editWndProc; 00955 LVCOLUMNA lvc; 00956 00957 if(info->tabs[TAB_SEARCH].id == -1) 00958 return TRUE; /* No "Search" tab */ 00959 hwndContainer = CreateWindowExW(WS_EX_CONTROLPARENT, szChildClass, szEmpty, 00960 WS_CHILD, 0, 0, 0, 0, info->WinType.hwndNavigation, 00961 NULL, hhctrl_hinstance, NULL); 00962 if(!hwndContainer) { 00963 ERR("Could not create search window container control.\n"); 00964 return FALSE; 00965 } 00966 hwndEdit = CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, szEmpty, WS_CHILD 00967 | WS_VISIBLE | ES_LEFT | SS_NOTIFY, 0, 0, 0, 0, 00968 hwndContainer, NULL, hhctrl_hinstance, NULL); 00969 if(!hwndEdit) { 00970 ERR("Could not create search ListView control.\n"); 00971 return FALSE; 00972 } 00973 if(SendMessageW(hwndEdit, WM_SETFONT, (WPARAM) info->hFont, (LPARAM) FALSE) == -1) 00974 { 00975 ERR("Could not set font for edit control.\n"); 00976 return FALSE; 00977 } 00978 editWndProc = (WNDPROC) SetWindowLongPtrW(hwndEdit, GWLP_WNDPROC, (LONG_PTR)EditChild_WndProc); 00979 if(!editWndProc) { 00980 ERR("Could not redirect messages for edit control.\n"); 00981 return FALSE; 00982 } 00983 SetWindowLongPtrW(hwndEdit, GWLP_USERDATA, (LONG_PTR)editWndProc); 00984 hwndList = CreateWindowExW(WS_EX_CLIENTEDGE, WC_LISTVIEWW, szEmpty, 00985 WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_SINGLESEL 00986 | LVS_REPORT | LVS_NOCOLUMNHEADER, 0, 0, 0, 0, 00987 hwndContainer, NULL, hhctrl_hinstance, NULL); 00988 if(!hwndList) { 00989 ERR("Could not create search ListView control.\n"); 00990 return FALSE; 00991 } 00992 memset(&lvc, 0, sizeof(lvc)); 00993 lvc.mask = LVCF_TEXT; 00994 lvc.pszText = hidden_column; 00995 if(SendMessageW(hwndList, LVM_INSERTCOLUMNA, 0, (LPARAM) &lvc) == -1) 00996 { 00997 ERR("Could not create ListView column\n"); 00998 return FALSE; 00999 } 01000 01001 info->search.hwndEdit = hwndEdit; 01002 info->search.hwndList = hwndList; 01003 info->search.hwndContainer = hwndContainer; 01004 info->tabs[TAB_SEARCH].hwnd = hwndContainer; 01005 01006 SetWindowLongPtrW(hwndContainer, GWLP_USERDATA, (LONG_PTR)info); 01007 01008 ResizeTabChild(info, TAB_SEARCH); 01009 01010 return TRUE; 01011 } 01012 01013 /* The Index tab's sub-topic popup */ 01014 01015 static void ResizePopupChild(HHInfo *info) 01016 { 01017 int scroll_width = GetSystemMetrics(SM_CXVSCROLL); 01018 int border_width = GetSystemMetrics(SM_CXBORDER); 01019 int edge_width = GetSystemMetrics(SM_CXEDGE); 01020 INT width, height; 01021 RECT rect; 01022 01023 if(!info) 01024 return; 01025 01026 GetClientRect(info->popup.hwndPopup, &rect); 01027 SetWindowPos(info->popup.hwndCallback, HWND_TOP, 0, 0, 01028 rect.right, rect.bottom, SWP_NOMOVE); 01029 01030 rect.left = TAB_MARGIN; 01031 rect.top = TAB_TOP_PADDING + TAB_MARGIN; 01032 rect.right -= TAB_RIGHT_PADDING + TAB_MARGIN; 01033 rect.bottom -= TAB_MARGIN; 01034 width = rect.right-rect.left; 01035 height = rect.bottom-rect.top; 01036 01037 SetWindowPos(info->popup.hwndList, NULL, rect.left, rect.top, width, height, 01038 SWP_NOZORDER | SWP_NOACTIVATE); 01039 01040 SendMessageW(info->popup.hwndList, LVM_SETCOLUMNWIDTH, 0, 01041 width-scroll_width-2*border_width-2*edge_width); 01042 } 01043 01044 static LRESULT CALLBACK HelpPopup_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 01045 { 01046 HHInfo *info = (HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA); 01047 01048 switch (message) 01049 { 01050 case WM_SIZE: 01051 ResizePopupChild(info); 01052 return 0; 01053 case WM_DESTROY: 01054 DestroyWindow(hWnd); 01055 return 0; 01056 case WM_CLOSE: 01057 ShowWindow(hWnd, SW_HIDE); 01058 return 0; 01059 01060 default: 01061 return DefWindowProcW(hWnd, message, wParam, lParam); 01062 } 01063 01064 return 0; 01065 } 01066 01067 static LRESULT CALLBACK PopupChild_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 01068 { 01069 switch (message) 01070 { 01071 case WM_NOTIFY: { 01072 NMHDR *nmhdr = (NMHDR*)lParam; 01073 switch(nmhdr->code) 01074 { 01075 case NM_DBLCLK: { 01076 HHInfo *info = (HHInfo*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); 01077 IndexSubItem *iter; 01078 01079 if(info == 0 || lParam == 0) 01080 return 0; 01081 iter = (IndexSubItem*) ((NMITEMACTIVATE *)lParam)->lParam; 01082 if(iter == 0) 01083 return 0; 01084 NavigateToChm(info, info->index->merge.chm_file, iter->local); 01085 ShowWindow(info->popup.hwndPopup, SW_HIDE); 01086 return 0; 01087 } 01088 case NM_RETURN: { 01089 HHInfo *info = (HHInfo*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); 01090 IndexSubItem *iter; 01091 LVITEMW lvItem; 01092 01093 if(info == 0) 01094 return 0; 01095 01096 lvItem.iItem = (int) SendMessageW(info->popup.hwndList, LVM_GETSELECTIONMARK, 0, 0); 01097 lvItem.mask = TVIF_PARAM; 01098 SendMessageW(info->popup.hwndList, LVM_GETITEMW, 0, (LPARAM)&lvItem); 01099 iter = (IndexSubItem*) lvItem.lParam; 01100 NavigateToChm(info, info->index->merge.chm_file, iter->local); 01101 ShowWindow(info->popup.hwndPopup, SW_HIDE); 01102 return 0; 01103 } 01104 } 01105 break; 01106 } 01107 default: 01108 return DefWindowProcW(hWnd, message, wParam, lParam); 01109 } 01110 01111 return 0; 01112 } 01113 01114 static BOOL AddIndexPopup(HHInfo *info) 01115 { 01116 static const WCHAR szPopupChildClass[] = {'H','H',' ','P','o','p','u','p',' ','C','h','i','l','d',0}; 01117 static const WCHAR windowCaptionW[] = {'S','e','l','e','c','t',' ','T','o','p','i','c',':',0}; 01118 static const WCHAR windowClassW[] = {'H','H',' ','P','o','p','u','p',0}; 01119 HWND hwndList, hwndPopup, hwndCallback; 01120 char hidden_column[] = "Column"; 01121 WNDCLASSEXW wcex; 01122 LVCOLUMNA lvc; 01123 01124 if(info->tabs[TAB_INDEX].id == -1) 01125 return TRUE; /* No "Index" tab */ 01126 01127 wcex.cbSize = sizeof(WNDCLASSEXW); 01128 wcex.style = CS_HREDRAW | CS_VREDRAW; 01129 wcex.lpfnWndProc = HelpPopup_WndProc; 01130 wcex.cbClsExtra = 0; 01131 wcex.cbWndExtra = 0; 01132 wcex.hInstance = hhctrl_hinstance; 01133 wcex.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION); 01134 wcex.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); 01135 wcex.hbrBackground = (HBRUSH)(COLOR_MENU + 1); 01136 wcex.lpszMenuName = NULL; 01137 wcex.lpszClassName = windowClassW; 01138 wcex.hIconSm = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION); 01139 RegisterClassExW(&wcex); 01140 01141 wcex.cbSize = sizeof(WNDCLASSEXW); 01142 wcex.style = 0; 01143 wcex.lpfnWndProc = PopupChild_WndProc; 01144 wcex.cbClsExtra = 0; 01145 wcex.cbWndExtra = 0; 01146 wcex.hInstance = hhctrl_hinstance; 01147 wcex.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION); 01148 wcex.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); 01149 wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); 01150 wcex.lpszMenuName = NULL; 01151 wcex.lpszClassName = szPopupChildClass; 01152 wcex.hIconSm = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION); 01153 RegisterClassExW(&wcex); 01154 01155 hwndPopup = CreateWindowExW(WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_APPWINDOW 01156 | WS_EX_WINDOWEDGE | WS_EX_RIGHTSCROLLBAR, 01157 windowClassW, windowCaptionW, WS_POPUPWINDOW 01158 | WS_OVERLAPPEDWINDOW | WS_VISIBLE 01159 | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CW_USEDEFAULT, 01160 CW_USEDEFAULT, 300, 200, info->WinType.hwndHelp, 01161 NULL, hhctrl_hinstance, NULL); 01162 if (!hwndPopup) 01163 return FALSE; 01164 01165 hwndCallback = CreateWindowExW(WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR, 01166 szPopupChildClass, szEmpty, WS_CHILDWINDOW | WS_VISIBLE, 01167 0, 0, 0, 0, 01168 hwndPopup, NULL, hhctrl_hinstance, NULL); 01169 if (!hwndCallback) 01170 return FALSE; 01171 01172 ShowWindow(hwndPopup, SW_HIDE); 01173 hwndList = CreateWindowExW(WS_EX_CLIENTEDGE, WC_LISTVIEWW, szEmpty, 01174 WS_CHILD | WS_BORDER | LVS_SINGLESEL | LVS_REPORT 01175 | LVS_NOCOLUMNHEADER, 50, 50, 100, 100, 01176 hwndCallback, NULL, hhctrl_hinstance, NULL); 01177 if(!hwndList) { 01178 ERR("Could not create popup ListView control\n"); 01179 return FALSE; 01180 } 01181 memset(&lvc, 0, sizeof(lvc)); 01182 lvc.mask = LVCF_TEXT; 01183 lvc.pszText = hidden_column; 01184 if(SendMessageW(hwndList, LVM_INSERTCOLUMNA, 0, (LPARAM) &lvc) == -1) 01185 { 01186 ERR("Could not create popup ListView column\n"); 01187 return FALSE; 01188 } 01189 01190 info->popup.hwndCallback = hwndCallback; 01191 info->popup.hwndPopup = hwndPopup; 01192 info->popup.hwndList = hwndList; 01193 SetWindowLongPtrW(hwndPopup, GWLP_USERDATA, (LONG_PTR)info); 01194 SetWindowLongPtrW(hwndCallback, GWLP_USERDATA, (LONG_PTR)info); 01195 01196 ResizePopupChild(info); 01197 ShowWindow(hwndList, SW_SHOW); 01198 01199 return TRUE; 01200 } 01201 01202 /* Viewer Window */ 01203 01204 static LRESULT Help_OnSize(HWND hWnd) 01205 { 01206 HHInfo *pHHInfo = (HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA); 01207 DWORD dwSize; 01208 RECT rc; 01209 01210 if (!pHHInfo) 01211 return 0; 01212 01213 NP_GetNavigationRect(pHHInfo, &rc); 01214 SetWindowPos(pHHInfo->WinType.hwndNavigation, HWND_TOP, 0, 0, 01215 rc.right, rc.bottom, SWP_NOMOVE); 01216 01217 SB_GetSizeBarRect(pHHInfo, &rc); 01218 SetWindowPos(pHHInfo->hwndSizeBar, HWND_TOP, rc.left, rc.top, 01219 rc.right, rc.bottom, SWP_SHOWWINDOW); 01220 01221 HP_GetHTMLRect(pHHInfo, &rc); 01222 SetWindowPos(pHHInfo->WinType.hwndHTML, HWND_TOP, rc.left, rc.top, 01223 rc.right, rc.bottom, SWP_SHOWWINDOW); 01224 01225 /* Resize browser window taking the frame size into account */ 01226 dwSize = GetSystemMetrics(SM_CXFRAME); 01227 ResizeWebBrowser(pHHInfo, rc.right - dwSize, rc.bottom - dwSize); 01228 01229 return 0; 01230 } 01231 01232 static LRESULT CALLBACK Help_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 01233 { 01234 switch (message) 01235 { 01236 case WM_COMMAND: 01237 if (HIWORD(wParam) == BN_CLICKED) 01238 TB_OnClick(hWnd, LOWORD(wParam)); 01239 break; 01240 case WM_SIZE: 01241 return Help_OnSize(hWnd); 01242 case WM_CLOSE: 01243 ReleaseHelpViewer((HHInfo *)GetWindowLongPtrW(hWnd, GWLP_USERDATA)); 01244 return 0; 01245 case WM_DESTROY: 01246 if(hh_process) 01247 PostQuitMessage(0); 01248 break; 01249 01250 default: 01251 return DefWindowProcW(hWnd, message, wParam, lParam); 01252 } 01253 01254 return 0; 01255 } 01256 01257 static BOOL HH_CreateHelpWindow(HHInfo *info) 01258 { 01259 HWND hWnd; 01260 RECT winPos = info->WinType.rcWindowPos; 01261 WNDCLASSEXW wcex; 01262 DWORD dwStyles, dwExStyles; 01263 DWORD x, y, width = 0, height = 0; 01264 LPCWSTR caption; 01265 01266 static const WCHAR windowClassW[] = { 01267 'H','H',' ', 'P','a','r','e','n','t',0 01268 }; 01269 01270 wcex.cbSize = sizeof(WNDCLASSEXW); 01271 wcex.style = CS_HREDRAW | CS_VREDRAW; 01272 wcex.lpfnWndProc = Help_WndProc; 01273 wcex.cbClsExtra = 0; 01274 wcex.cbWndExtra = 0; 01275 wcex.hInstance = hhctrl_hinstance; 01276 wcex.hIcon = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION); 01277 wcex.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); 01278 wcex.hbrBackground = (HBRUSH)(COLOR_MENU + 1); 01279 wcex.lpszMenuName = NULL; 01280 wcex.lpszClassName = windowClassW; 01281 wcex.hIconSm = LoadIconW(NULL, (LPCWSTR)IDI_APPLICATION); 01282 01283 RegisterClassExW(&wcex); 01284 01285 /* Read in window parameters if available */ 01286 if (info->WinType.fsValidMembers & HHWIN_PARAM_STYLES) 01287 dwStyles = info->WinType.dwStyles | WS_OVERLAPPEDWINDOW; 01288 else 01289 dwStyles = WS_OVERLAPPEDWINDOW | WS_VISIBLE | 01290 WS_CLIPSIBLINGS | WS_CLIPCHILDREN; 01291 01292 if (info->WinType.fsValidMembers & HHWIN_PARAM_EXSTYLES) 01293 dwExStyles = info->WinType.dwExStyles; 01294 else 01295 dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_APPWINDOW | 01296 WS_EX_WINDOWEDGE | WS_EX_RIGHTSCROLLBAR; 01297 01298 if (info->WinType.fsValidMembers & HHWIN_PARAM_RECT) 01299 { 01300 x = winPos.left; 01301 y = winPos.top; 01302 width = winPos.right - x; 01303 height = winPos.bottom - y; 01304 } 01305 if (!width || !height) 01306 { 01307 x = WINTYPE_DEFAULT_X; 01308 y = WINTYPE_DEFAULT_Y; 01309 width = WINTYPE_DEFAULT_WIDTH; 01310 height = WINTYPE_DEFAULT_HEIGHT; 01311 } 01312 01313 caption = info->WinType.pszCaption; 01314 if (!*caption) caption = info->pCHMInfo->defTitle; 01315 01316 hWnd = CreateWindowExW(dwExStyles, windowClassW, caption, 01317 dwStyles, x, y, width, height, NULL, NULL, hhctrl_hinstance, NULL); 01318 if (!hWnd) 01319 return FALSE; 01320 01321 ShowWindow(hWnd, SW_SHOW); 01322 UpdateWindow(hWnd); 01323 01324 /* store the pointer to the HH info struct */ 01325 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)info); 01326 01327 info->WinType.hwndHelp = hWnd; 01328 return TRUE; 01329 } 01330 01331 static void HH_CreateFont(HHInfo *pHHInfo) 01332 { 01333 LOGFONTW lf; 01334 01335 GetObjectW(GetStockObject(ANSI_VAR_FONT), sizeof(LOGFONTW), &lf); 01336 lf.lfWeight = FW_NORMAL; 01337 lf.lfItalic = FALSE; 01338 lf.lfUnderline = FALSE; 01339 01340 pHHInfo->hFont = CreateFontIndirectW(&lf); 01341 } 01342 01343 static void HH_InitRequiredControls(DWORD dwControls) 01344 { 01345 INITCOMMONCONTROLSEX icex; 01346 01347 icex.dwSize = sizeof(INITCOMMONCONTROLSEX); 01348 icex.dwICC = dwControls; 01349 InitCommonControlsEx(&icex); 01350 } 01351 01352 /* Creates the whole package */ 01353 static BOOL CreateViewer(HHInfo *pHHInfo) 01354 { 01355 HH_CreateFont(pHHInfo); 01356 01357 if (!HH_CreateHelpWindow(pHHInfo)) 01358 return FALSE; 01359 01360 HH_InitRequiredControls(ICC_BAR_CLASSES); 01361 01362 if (!HH_AddToolbar(pHHInfo)) 01363 return FALSE; 01364 01365 HH_RegisterChildWndClass(pHHInfo); 01366 01367 if (!HH_AddNavigationPane(pHHInfo)) 01368 return FALSE; 01369 01370 HH_RegisterSizeBarClass(pHHInfo); 01371 01372 if (!HH_AddSizeBar(pHHInfo)) 01373 return FALSE; 01374 01375 if (!HH_AddHTMLPane(pHHInfo)) 01376 return FALSE; 01377 01378 if (!AddContentTab(pHHInfo)) 01379 return FALSE; 01380 01381 if (!AddIndexTab(pHHInfo)) 01382 return FALSE; 01383 01384 if (!AddIndexPopup(pHHInfo)) 01385 return FALSE; 01386 01387 if (!AddSearchTab(pHHInfo)) 01388 return FALSE; 01389 01390 InitContent(pHHInfo); 01391 InitIndex(pHHInfo); 01392 01393 return TRUE; 01394 } 01395 01396 void ReleaseHelpViewer(HHInfo *info) 01397 { 01398 TRACE("(%p)\n", info); 01399 01400 if (!info) 01401 return; 01402 01403 /* Free allocated strings */ 01404 heap_free(info->pszType); 01405 heap_free(info->pszCaption); 01406 heap_free(info->pszToc); 01407 heap_free(info->pszIndex); 01408 heap_free(info->pszFile); 01409 heap_free(info->pszHome); 01410 heap_free(info->pszJump1); 01411 heap_free(info->pszJump2); 01412 heap_free(info->pszUrlJump1); 01413 heap_free(info->pszUrlJump2); 01414 01415 if (info->pCHMInfo) 01416 CloseCHM(info->pCHMInfo); 01417 01418 ReleaseWebBrowser(info); 01419 ReleaseContent(info); 01420 ReleaseIndex(info); 01421 ReleaseSearch(info); 01422 01423 if(info->WinType.hwndHelp) 01424 DestroyWindow(info->WinType.hwndHelp); 01425 01426 heap_free(info); 01427 OleUninitialize(); 01428 } 01429 01430 HHInfo *CreateHelpViewer(LPCWSTR filename) 01431 { 01432 HHInfo *info = heap_alloc_zero(sizeof(HHInfo)); 01433 int i; 01434 01435 /* Set the invalid tab ID (-1) as the default value for all 01436 * of the tabs, this matches a failed TCM_INSERTITEM call. 01437 */ 01438 for(i=0;i<sizeof(info->tabs)/sizeof(HHTab);i++) 01439 info->tabs[i].id = -1; 01440 01441 OleInitialize(NULL); 01442 01443 info->pCHMInfo = OpenCHM(filename); 01444 if(!info->pCHMInfo) { 01445 ReleaseHelpViewer(info); 01446 return NULL; 01447 } 01448 01449 if (!LoadWinTypeFromCHM(info)) { 01450 ReleaseHelpViewer(info); 01451 return NULL; 01452 } 01453 01454 if(!CreateViewer(info)) { 01455 ReleaseHelpViewer(info); 01456 return NULL; 01457 } 01458 01459 return info; 01460 } Generated on Sun May 27 2012 04:16:34 for ReactOS by
1.7.6.1
|