From bacf5e0272c566c30e591152084daf2f684aebe8 Mon Sep 17 00:00:00 2001 From: Goraf Date: Fri, 5 Feb 2016 22:40:46 +0000 Subject: ContextHelp: initial commit (adopted) * working * 32/64-bit compilable git-svn-id: http://svn.miranda-ng.org/main/trunk@16225 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/ContextHelp/src/helpdlg.cpp | 735 ++++++++++++++++++++++++++++++++++++ 1 file changed, 735 insertions(+) create mode 100644 plugins/ContextHelp/src/helpdlg.cpp (limited to 'plugins/ContextHelp/src/helpdlg.cpp') diff --git a/plugins/ContextHelp/src/helpdlg.cpp b/plugins/ContextHelp/src/helpdlg.cpp new file mode 100644 index 0000000000..b035777a0f --- /dev/null +++ b/plugins/ContextHelp/src/helpdlg.cpp @@ -0,0 +1,735 @@ +/* +Miranda IM Help Plugin +Copyright (C) 2002 Richard Hughes, 2005-2007 H. Herkenrath + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program (Help-License.txt); if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +#include "stdafx.h" + + +#include + +extern HINSTANCE hInst; +HWND hwndHelpDlg; + +static int HelpDialogResize(HWND hwndDlg, LPARAM lParam, UTILRESIZECONTROL *urc) +{ + UNREFERENCED_PARAMETER(hwndDlg); + UNREFERENCED_PARAMETER(lParam); + switch (urc->wId) { + case IDC_CTLTEXT: +#ifdef EDITOR + case IDC_DLGID: + case IDC_MODULE: +#endif + return RD_ANCHORX_WIDTH | RD_ANCHORY_TOP; + case IDC_TEXT: + return RD_ANCHORX_WIDTH | RD_ANCHORY_HEIGHT; + } + return RD_ANCHORX_LEFT | RD_ANCHORY_TOP; +} + +#ifndef EDITOR +INT_PTR CALLBACK ShadowDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + UNREFERENCED_PARAMETER(wParam); + switch (msg) { + case WM_INITDIALOG: + { + BOOL(WINAPI *pfnSetLayeredWindowAttributes)(HWND, COLORREF, BYTE, DWORD); + *(FARPROC*)&pfnSetLayeredWindowAttributes = GetProcAddress(GetModuleHandleA("USER32"), "SetLayeredWindowAttributes"); + if (!pfnSetLayeredWindowAttributes) { + *(HANDLE*)lParam = NULL; // hwndShadowDlg reset + DestroyWindow(hwndDlg); + return FALSE; + } + EnableWindow(hwndDlg, FALSE); + SetWindowLongPtr(hwndDlg, GWL_EXSTYLE, GetWindowLongPtr(hwndDlg, GWL_EXSTYLE) | WS_EX_LAYERED); + pfnSetLayeredWindowAttributes(hwndDlg, RGB(0, 0, 0), 96, LWA_ALPHA); + return FALSE; + } + case WM_CTLCOLORDLG: + return (INT_PTR)GetSysColorBrush(COLOR_WINDOWFRAME); + } + return FALSE; +} + +// in client coordinates +int GetCharRangeRect(HWND hwndEdit, LONG *cpMin, LONG cpMax, RECT *rcRange) +{ + LONG cpLineBreak; + + LONG nLine, nLinePrev; + if (*cpMin>cpMax) + return 1; + nLine = SendMessage(hwndEdit, EM_EXLINEFROMCHAR, 0, *cpMin); + for (cpLineBreak = *cpMin + 1; cpLineBreak <= cpMax; cpLineBreak++) { + nLinePrev = nLine; + nLine = SendMessage(hwndEdit, EM_EXLINEFROMCHAR, 0, cpLineBreak); + if (nLine != nLinePrev) + break; + } + cpMax = cpLineBreak - 1; + + POINTL pt; + if (SendMessage(hwndEdit, EM_SETTYPOGRAPHYOPTIONS, 0, 0)) { // test for richedit v3.0 + SendMessage(hwndEdit, EM_POSFROMCHAR, (WPARAM)&pt, *cpMin); + rcRange->left = pt.x; + rcRange->top = pt.y; + SendMessage(hwndEdit, EM_POSFROMCHAR, (WPARAM)&pt, cpMax); + rcRange->right = pt.x; + rcRange->bottom = pt.y; + } + else { + DWORD pos; + pos = SendMessage(hwndEdit, EM_POSFROMCHAR, (WPARAM)*cpMin, 0); + POINTSTOPOINT(pt, MAKEPOINTS(pos)); + rcRange->left = pt.x; + rcRange->top = pt.y; + pos = SendMessage(hwndEdit, EM_POSFROMCHAR, (WPARAM)cpMax, 0); + POINTSTOPOINT(pt, MAKEPOINTS(pos)); + rcRange->right = pt.x; + rcRange->bottom = pt.y; + } + + FORMATRANGE fr; + ZeroMemory(&fr, sizeof(fr)); + fr.chrg.cpMin = *cpMin; + fr.chrg.cpMax = cpMax; + fr.hdc = fr.hdcTarget = GetDC(hwndEdit); + if (fr.hdc == NULL) + return 1; + SendMessage(hwndEdit, EM_FORMATRANGE, 0, (LPARAM)&fr); + PostMessage(hwndEdit, EM_FORMATRANGE, 0, 0); // clear memory + rcRange->bottom += MulDiv(fr.rc.bottom, GetDeviceCaps(fr.hdc, LOGPIXELSY), 1440); // twips to pixels + ReleaseDC(hwndEdit, fr.hdc); + + *cpMin = cpLineBreak; + return 0; +} + +static HCURSOR hHandCursor; +static LRESULT CALLBACK HelpSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) { + case WM_KEYDOWN: + if (GetKeyState(VK_CONTROL) & 0x8000 && wParam == 'C') { + SendMessage(GetParent(hwnd), M_CLIPBOARDCOPY, 0, 0); + return 0; + } + break; + case WM_LBUTTONDBLCLK: + DestroyWindow(GetParent(hwnd)); + return 0; + case WM_CONTEXTMENU: + return DefWindowProc(hwnd, msg, wParam, lParam); // redirect to parent + case WM_SETCURSOR: // not available via EN_MSGFILTER + if (GetDlgCtrlID((HWND)wParam) == IDC_TEXT) { + POINT pt; + DWORD pos; + CHARRANGE rng; + pos = GetMessagePos(); + POINTSTOPOINT(pt, MAKEPOINTS(pos)); + ScreenToClient((HWND)wParam, &pt); + pos = SendMessage((HWND)wParam, EM_CHARFROMPOS, 0, (WPARAM)&pt); + if (IsHyperlink(pos, &rng.cpMin, &rng.cpMax, NULL)) { + RECT rc; + while (!GetCharRangeRect((HWND)wParam, &rng.cpMin, rng.cpMax, &rc)) + if (PtInRect(&rc, pt)) { + SetCursor(hHandCursor); + return TRUE; + } + } + } + break; + } + return CallWindowProc((WNDPROC)GetWindowLongPtr(hwnd, GWLP_USERDATA), hwnd, msg, wParam, lParam); +} +#endif // !defined EDITOR + +INT_PTR CALLBACK HelpDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndCtl = (HWND)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + static LCID locale; +#ifndef EDITOR + static HWND hwndShadowDlg; + static HWND hwndToolTip; +#endif + + switch (msg) { + case WM_INITDIALOG: + hwndHelpDlg = hwndDlg; +#ifdef EDITOR + TranslateDialogDefault(hwndDlg); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DLGID), GWL_STYLE, GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DLGID), GWL_STYLE) | SS_ENDELLIPSIS); + SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETEVENTMASK, 0, ENM_KEYEVENTS); + { RECT rcDlg, rcWork; + if (SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, FALSE) && GetWindowRect(hwndDlg, &rcDlg)) + SetWindowPos(hwndDlg, 0, rcDlg.left, rcWork.bottom - rcDlg.bottom + rcDlg.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } +#else + { + RECT rc, rcBuf; + SendDlgItemMessage(hwndDlg, IDC_CTLTEXT, EM_GETRECT, 0, (LPARAM)&rcBuf); + SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_GETRECT, 0, (LPARAM)&rc); + rc.left = rcBuf.left; // sync richedit offset with edit + rc.right = rcBuf.right; + SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETRECTNP, 0, (LPARAM)&rc); + } + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CTLTEXT), GWLP_USERDATA, SetWindowLong(GetDlgItem(hwndDlg, IDC_CTLTEXT), GWLP_WNDPROC, (LONG)HelpSubclassProc)); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CARETSUCKER), GWLP_USERDATA, SetWindowLong(GetDlgItem(hwndDlg, IDC_CARETSUCKER), GWLP_WNDPROC, (LONG)HelpSubclassProc)); + SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETEVENTMASK, 0, ENM_KEYEVENTS | ENM_MOUSEEVENTS | ENM_REQUESTRESIZE); + SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_INFOBK)); + SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETEDITSTYLE, SES_EXTENDBACKCOLOR, SES_EXTENDBACKCOLOR); + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT), GWLP_USERDATA, SetWindowLong(GetDlgItem(hwndDlg, IDC_TEXT), GWLP_WNDPROC, (LONG)HelpSubclassProc)); + hwndShadowDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SHADOW), hwndDlg, ShadowDlgProc, (LPARAM)&hwndShadowDlg); + hwndToolTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP | TTS_NOPREFIX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL, hInst, NULL); + if (hwndToolTip != NULL) { + SetWindowPos(hwndToolTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + SendMessage(hwndToolTip, TTM_SETTIPBKCOLOR, GetSysColor(COLOR_WINDOW), 0); // yelleow on yellow looks silly + SendMessage(hwndToolTip, TTM_SETDELAYTIME, TTDT_AUTOMATIC, GetDoubleClickTime() * 3); + } + hHandCursor = (HCURSOR)LoadImage(NULL, IDC_HAND, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + if (hHandCursor == NULL) // use fallback out of miranda32.exe + hHandCursor = (HCURSOR)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(214), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); +#endif + SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETLANGOPTIONS, 0, SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_GETLANGOPTIONS, 0, 0) | IMF_UIFONTS); + SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + return TRUE; + case WM_SIZE: + { + /* UTILRESIZEDIALOG urd; + ZeroMemory(&urd,sizeof(urd)); + urd.cbSize=sizeof(urd); + urd.hInstance=hInst; + urd.hwndDlg=hwndDlg; + urd.lpTemplate=MAKEINTRESOURCEA(IDD_HELP); + urd.pfnResizer=HelpDialogResize; + CallService(MS_UTILS_RESIZEDIALOG,0,(LPARAM)&urd); */ + Utils_ResizeDialog(hwndDlg, hInst, MAKEINTRESOURCEA(IDD_HELP), HelpDialogResize); + InvalidateRect(hwndDlg, NULL, TRUE); +#ifdef EDITOR + break; +#endif + } +#ifndef EDITOR + case WM_MOVE: + if (IsWindow(hwndShadowDlg)) { + RECT rc; + HRGN hRgnShadow, hRgnDlg; + if (!GetWindowRect(hwndDlg, &rc)) + break; + hRgnShadow = CreateRectRgnIndirect(&rc); + if (hRgnShadow == NULL) + break; + OffsetRgn(hRgnShadow, 5, 5); + hRgnDlg = CreateRectRgnIndirect(&rc); + if (hRgnDlg == NULL) + break; + if (CombineRgn(hRgnShadow, hRgnShadow, hRgnDlg, RGN_DIFF) == ERROR) { + DeleteObject(hRgnShadow); + DeleteObject(hRgnDlg); + break; + } + DeleteObject(hRgnDlg); + OffsetRgn(hRgnShadow, -rc.left - 5, -rc.top - 5); + SetWindowRgn(hwndShadowDlg, hRgnShadow, FALSE); // system gets ownership of hRgnShadow + SetWindowPos(hwndShadowDlg, HWND_TOPMOST, rc.left + 5, rc.top + 5, rc.right - rc.left, rc.bottom - rc.top, SWP_SHOWWINDOW); + SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + } + break; + case WM_KEYDOWN: + if (GetKeyState(VK_CONTROL) & 0x8000 && wParam == 'C') { + SendMessage(hwndDlg, M_CLIPBOARDCOPY, 0, 0); + return TRUE; + } + break; + case WM_CONTEXTMENU: + { + HMENU hMenu; + POINT pt; + POINTSTOPOINT(pt, MAKEPOINTS(lParam)); + hMenu = CreatePopupMenu(); + AppendMenu(hMenu, MF_STRING, WM_COPY, TranslateT("&Copy")); + if (TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_HORPOSANIMATION | TPM_VERPOSANIMATION | TPM_RIGHTBUTTON | TPM_RETURNCMD | TPM_NONOTIFY, pt.x, pt.y, hwndDlg, NULL)) + SendMessage(hwndDlg, M_CLIPBOARDCOPY, 0, 0); + DestroyMenu(hMenu); + } + return 0; + case WM_LBUTTONDBLCLK: + DestroyWindow(hwndDlg); + return TRUE; + case M_CLIPBOARDCOPY: + { + HWND hwnd = GetFocus(); + if (hwnd == GetDlgItem(hwndDlg, IDC_CTLTEXT) || hwnd == GetDlgItem(hwndDlg, IDC_TEXT)) { + CHARRANGE sel; + ZeroMemory(&sel, sizeof(sel)); + SendMessage(hwnd, EM_GETSEL, (WPARAM)&sel.cpMin, (LPARAM)&sel.cpMax); + if (sel.cpMin != sel.cpMax) { + SendMessage(hwnd, WM_COPY, 0, 0); + return TRUE; + } + } + } + if (OpenClipboard(hwndDlg)) { + HGLOBAL hglb; + int cch, len; + EmptyClipboard(); + hglb = GlobalAlloc(GMEM_MOVEABLE, sizeof(LCID)); + if (hglb != NULL) { + LCID *plocale = (LCID*)GlobalLock(hglb); // look at !! + if (plocale != NULL) { + *plocale = locale; + GlobalUnlock(hglb); + if (!SetClipboardData(CF_LOCALE, hglb)) + GlobalFree(hglb); // shell takes ownership + } + else + GlobalFree(hglb); + } + cch = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_CTLTEXT)) + GetWindowTextLength(GetDlgItem(hwndDlg, IDC_TEXT)) + 3; + hglb = GlobalAlloc(GMEM_MOVEABLE, (cch + 1)*sizeof(TCHAR)); + if (hglb != NULL) { + TCHAR *pszText = (TCHAR*)GlobalLock(hglb); + if (pszText != NULL) { + if (!GetWindowText(GetDlgItem(hwndDlg, IDC_CTLTEXT), pszText, cch - 2)) pszText[0] = _T('\0'); + len = lstrlen(pszText); + if (GetWindowText(GetDlgItem(hwndDlg, IDC_TEXT), pszText + len + 2, cch - 2 - len) && len) { + pszText[len] = _T('\r'); + pszText[len + 1] = _T('\n'); + } + GlobalUnlock(hglb); + if (!SetClipboardData(CF_UNICODETEXT, hglb)) + GlobalFree(hglb); // shell takes ownership + } + else GlobalFree(hglb); + } + CloseClipboard(); + } + return TRUE; + case WM_CTLCOLORDLG: + case WM_CTLCOLORSTATIC: + SetTextColor((HDC)wParam, GetSysColor(COLOR_INFOTEXT)); + SetBkColor((HDC)wParam, GetSysColor(COLOR_INFOBK)); + return (BOOL)GetSysColorBrush(COLOR_INFOBK); + case WM_ACTIVATE: + if (LOWORD(wParam) != WA_INACTIVE) + break; + if (GetParent((HWND)lParam) == hwndDlg) + break; + // fall through + case WM_SYSCOLORCHANGE: + case WM_ACTIVATEAPP: + PostMessage(hwndDlg, WM_CLOSE, 0, 0); // no DestroyWindow() here! would cause recursion + break; +#endif // !defined EDITOR + case M_CHANGEHELPCONTROL: + if (hwndCtl == (HWND)lParam) + break; + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); + hwndCtl = (HWND)lParam; + SetDlgItemText(hwndDlg, IDC_CTLTEXT, NULL); +#ifdef EDITOR + { + TCHAR text[1024]; + char *szModule, *szDlgId; + + GetControlTitle(hwndCtl, text, sizeof(text)); + SetDlgItemText(hwndDlg, IDC_CTLTEXT, text); + mir_sntprintf(text, sizeof(text), TranslateT("Control ID: %d"), GetControlID(hwndCtl)); + SetDlgItemText(hwndDlg, IDC_CTLID, text); + + szDlgId = CreateDialogIdString(GetControlDialog(hwndCtl)); + mir_sntprintf(text, sizeof(text), TranslateT("Dialog ID: %hs"), (szDlgId != NULL) ? szDlgId : Translate("Unknown")); + mir_free(szDlgId); // does NULL check + SetDlgItemText(hwndDlg, IDC_DLGID, text); + + mir_sntprintf(text, sizeof(text), TranslateT("Type: %s"), TranslateTS(szControlTypeNames[GetControlType(hwndCtl)])); + SetDlgItemText(hwndDlg, IDC_CTLTYPE, text); + + szModule = GetControlModuleName(hwndCtl); + mir_sntprintf(text, sizeof(text), TranslateT("Module: %hs"), szModule ? szModule : Translate("Unknown")); + mir_free(szModule); // does NULL check + SetDlgItemText(hwndDlg, IDC_MODULE, text); + } +#endif // defined EDITOR + SetDlgItemText(hwndDlg, IDC_TEXT, NULL); + SendMessage(hwndDlg, M_LOADHELP, 0, 0); +#ifdef EDITOR + ShowWindow(hwndDlg, SW_SHOWNORMAL); +#else + SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_REQUESTRESIZE, 0, 0); + return FALSE; +#endif + return TRUE; + case M_HELPLOADFAILED: + if (hwndCtl != (HWND)lParam) + break; +#ifdef EDITOR + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT), TRUE); + { + TCHAR text[2024]; + GetControlTitle(hwndCtl, text, sizeof(text)); + SetDlgItemText(hwndDlg, IDC_CTLTEXT, text); + } +#else + SetDlgItemText(hwndDlg, IDC_CTLTEXT, TranslateT("No Help Pack installed!")); +#endif + SetDlgItemText(hwndDlg, IDC_TEXT, NULL); + MessageBeep(MB_ICONERROR); + break; +#ifdef EDITOR + case M_SAVECOMPLETE: +#endif + case M_HELPLOADED: + if (hwndCtl != (HWND)lParam) + break; + case M_LOADHELP: + { + TCHAR *szTitle; + char *szText; + char *szDlgId, *szModule; + UINT codepage; + BOOL isRTL; + int id, loading; +#ifdef EDITOR + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT), TRUE); +#endif + szDlgId = CreateDialogIdString(GetControlDialog(hwndCtl)); + szModule = GetControlModuleName(hwndCtl); + id = GetControlID(hwndCtl); +#ifndef EDITOR + // show id string instead of help text when 'ctrl' key pressed + if (msg == M_LOADHELP && GetAsyncKeyState(VK_CONTROL) & 0x8000) { + char *buf; + HWND hwnd; + buf = CreateControlIdentifier(szDlgId ? szDlgId : "unknown", szModule ? szModule : "unknown", id, hwndCtl); + hwnd = GetDlgItem(hwndDlg, IDC_CTLTEXT); + SetWindowTextA(hwnd, buf); // accepts NULL + SetDlgItemText(hwndDlg, IDC_TEXT, NULL); + mir_free(buf); // does NULL check + mir_free(szDlgId); // does NULL check + mir_free(szModule); // does NULL check + break; + } +#endif + if (szDlgId == NULL || szModule == NULL) { + SetDlgItemText(hwndDlg, IDC_TEXT, NULL); +#ifndef EDITOR + SetDlgItemText(hwndDlg, IDC_CTLTEXT, TranslateT("No help available for this item.")); +#endif + mir_free(szDlgId); // does NULL check + mir_free(szModule); // does NULL check + break; + } + + loading = GetControlHelp(hwndCtl, szDlgId, szModule, id, &szTitle, &szText, NULL, &locale, &codepage, &isRTL, (msg == M_HELPLOADED) ? GCHF_DONTLOAD : 0); + if (!loading) { + if (szText) + StreamInHtml(GetDlgItem(hwndDlg, IDC_TEXT), szText, codepage, RGB(255, 0, 0)); + else + SetDlgItemText(hwndDlg, IDC_TEXT, NULL); + if (szTitle) { + TCHAR buf[128]; + RECT rc; + HFONT hFontPrev; + DWORD exStyle; + HWND hwndCtlText; + HDC hdc; + hwndCtlText = GetDlgItem(hwndDlg, IDC_CTLTEXT); + exStyle = GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CTLTEXT), GWL_EXSTYLE); + hdc = GetDC(hwndCtlText); + { + DWORD(WINAPI *pfnGetLayout)(HDC); // obey right-to-left languages + *(FARPROC*)&pfnGetLayout = GetProcAddress(GetModuleHandleA("GDI32"), "GetLayout"); + if (pfnGetLayout) isRTL = (isRTL && !pfnGetLayout(hdc)); + if (isRTL) + exStyle |= WS_EX_RTLREADING | WS_EX_RIGHT; + else + exStyle &= ~(WS_EX_RTLREADING | WS_EX_RIGHT); + } + mir_sntprintf(buf, sizeof(buf) - 4, _T("%s"), szTitle); + if (hdc != NULL && hwndCtlText != NULL) { + SendMessage(hwndCtlText, EM_GETRECT, 0, (LPARAM)&rc); + hFontPrev = (HFONT)SelectObject(hdc, (HFONT)SendMessage(hwndCtlText, WM_GETFONT, 0, 0)); // look at !! + // doesn't actually draw the string due to DT_CALCRECT + DrawTextEx(hdc, buf, -1, &rc, DT_MODIFYSTRING | DT_CALCRECT | DT_EDITCONTROL | DT_END_ELLIPSIS | DT_INTERNAL | (isRTL ? (DT_RTLREADING | DT_RIGHT) : DT_LEFT) | DT_NOPREFIX | DT_SINGLELINE, NULL); + SelectObject(hdc, hFontPrev); + ReleaseDC(hwndCtlText, hdc); + } + SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_CTLTEXT), GWL_EXSTYLE, exStyle); + SetWindowText(hwndCtlText, buf); + } + else + SetDlgItemText(hwndDlg, IDC_CTLTEXT, NULL); + } + else { + if (msg == M_HELPLOADED) { + SetDlgItemText(hwndDlg, IDC_TEXT, NULL); +#ifndef EDITOR + SetDlgItemText(hwndDlg, IDC_CTLTEXT, TranslateT("No help available for this item.")); +#endif + } + else { +#ifdef EDITOR + EnableWindow(GetDlgItem(hwndDlg, IDC_TEXT), FALSE); + SetDlgItemText(hwndDlg, IDC_TEXT, TranslateT("Loading...")); +#else + SetDlgItemText(hwndDlg, IDC_CTLTEXT, TranslateT("Loading...")); + SetDlgItemText(hwndDlg, IDC_TEXT, NULL); +#endif + } + } + mir_free(szDlgId); + mir_free(szModule); + break; + } + case WM_NOTIFY: + switch (((NMHDR*)lParam)->idFrom) { + case IDC_TEXT: + switch (((NMHDR*)lParam)->code) { +#ifdef EDITOR + case EN_MSGFILTER: + switch (((MSGFILTER*)lParam)->msg) { + case WM_CHAR: + switch (((MSGFILTER*)lParam)->wParam) { + case 'B' - 'A' + 1: + case 'I' - 'A' + 1: + case 'U' - 'A' + 1: + case 'H' - 'A' + 1: + case 'L' - 'A' + 1: + case 'S' - 'A' + 1: + case 'G' - 'A' + 1: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + break; + case WM_KEYDOWN: + { + CHARFORMAT cf; + int changes = 0; + + ZeroMemory(&cf, sizeof(cf)); + if (!(GetKeyState(VK_CONTROL) & 0x8000)) + break; + cf.cbSize = sizeof(cf); + SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_GETCHARFORMAT, TRUE, (LPARAM)&cf); + switch (((MSGFILTER*)lParam)->wParam) { + case 'B': + cf.dwEffects ^= CFE_BOLD; + cf.dwMask = CFM_BOLD; + changes = 1; + break; + case 'I': + cf.dwEffects ^= CFE_ITALIC; + cf.dwMask = CFM_ITALIC; + changes = 1; + break; + case 'U': + cf.dwEffects ^= CFE_UNDERLINE; + cf.dwMask = CFM_UNDERLINE; + changes = 1; + break; + case 'L': + { + CHOOSECOLOR cc; + COLORREF custCol[16]; + ZeroMemory(&custCol, sizeof(custCol)); + ZeroMemory(&cc, sizeof(cc)); + cc.lStructSize = sizeof(cc); + cc.hwndOwner = hwndDlg; + cc.lpCustColors = custCol; + cc.rgbResult = cf.crTextColor; + cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT; + if (!ChooseColor(&cc)) + break; + cf.crTextColor = 0; + cf.dwEffects = 0; + if (cc.rgbResult) + cf.crTextColor = cc.rgbResult; + else cf.dwEffects = CFE_AUTOCOLOR; + cf.dwMask = CFM_COLOR; + changes = 1; + break; + } + case 'H': + cf.dwEffects ^= CFE_STRIKEOUT; + cf.dwMask = CFM_STRIKEOUT; + changes = 1; + break; + case VK_OEM_PLUS: + cf.yHeight = ((GetKeyState(VK_SHIFT) & 0x8000) ? TEXTSIZE_BIG : TEXTSIZE_NORMAL) * 10; + cf.dwMask = CFM_SIZE; + changes = 1; + break; + case VK_OEM_MINUS: + cf.yHeight = TEXTSIZE_SMALL * 10; + cf.dwMask = CFM_SIZE; + changes = 1; + break; + case 'S': + { + TCHAR szTitle[1024]; + char *szText, *szDlgId, *szModule; + if (!GetDlgItemText(hwndDlg, IDC_CTLTEXT, szTitle, sizeof(szTitle))) + break; + szDlgId = CreateDialogIdString(GetControlDialog(hwndCtl)); + if (szDlgId == NULL) + break; + szText = StreamOutHtml(GetDlgItem(hwndDlg, IDC_TEXT)); + szModule = GetControlModuleName(hwndCtl); + if (szModule == NULL) { + mir_free(szDlgId); + break; + } + SetControlHelp(szDlgId, szModule, GetControlID(hwndCtl), szTitle, szText, GetControlType(hwndCtl)); + mir_free(szText); + mir_free(szDlgId); + mir_free(szModule); + SaveDialogCache(); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + case 'G': + SendMessage(hwndDlg, M_LOADHELP, 0, 0); + SetWindowLong(hwndDlg, DWL_MSGRESULT, TRUE); + return TRUE; + } + if (changes) { + SendDlgItemMessage(hwndDlg, IDC_TEXT, EM_SETCHARFORMAT, SCF_WORD | SCF_SELECTION, (LPARAM)&cf); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + break; + } + } + break; +#else // defined EDITOR + case EN_MSGFILTER: + { + MSGFILTER *msgf = (MSGFILTER*)lParam; + switch (msgf->msg) { + case WM_LBUTTONUP: + { + POINT pt; + DWORD pos; + CHARRANGE sel; + char *pszLink; + HWND hwndEdit = msgf->nmhdr.hwndFrom; + + ZeroMemory(&sel, sizeof(sel)); + SendMessage(msgf->nmhdr.hwndFrom, EM_EXGETSEL, 0, (LPARAM)&sel); + if (sel.cpMin != sel.cpMax) + break; + POINTSTOPOINT(pt, MAKEPOINTS(msgf->lParam)); + pos = SendMessage(hwndEdit, EM_CHARFROMPOS, 0, (WPARAM)&pt); + if (IsHyperlink(pos, NULL, NULL, &pszLink)) { + Utils_OpenUrl(pszLink); // pszLink is MBCS string in CP_ACP + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, TRUE); + return TRUE; + } + } + break; + case WM_MOUSEMOVE: // register hyperlink tooltips when current + if (hwndToolTip != NULL) { + POINTL pt; + DWORD pos; + CHARRANGE rng; + char *pszLink; + + POINTSTOPOINT(pt, MAKEPOINTS(msgf->lParam)); + pos = SendMessage(msgf->nmhdr.hwndFrom, EM_CHARFROMPOS, 0, (WPARAM)&pt); + if (IsHyperlink(pos, &rng.cpMin, &rng.cpMax, &pszLink)) { // pszLink is MBCS in CP_ACP + TTTOOLINFOA ti = { 0 }; + ti.cbSize = sizeof(ti); + ti.hwnd = msgf->nmhdr.hwndFrom; + ti.uId = (UINT)rng.cpMin; + if (!SendMessage(hwndToolTip, TTM_GETTOOLINFOA, 0, (LPARAM)&ti)) { + LONG cpRectMin; + ti.uFlags = TTF_SUBCLASS; + ti.lpszText = pszLink; + cpRectMin = rng.cpMin; + while (!GetCharRangeRect(ti.hwnd, &rng.cpMin, rng.cpMax, &ti.rect)) { + ti.uId = (UINT)cpRectMin; + SendMessage(hwndToolTip, TTM_ADDTOOLA, 0, (LPARAM)&ti); + cpRectMin = rng.cpMin; + } + } + } + } + break; + } + } + break; + case EN_REQUESTRESIZE: + { + RECT rcDlg, rcEdit, rcCtl, rcNew; + REQRESIZE *rr = (REQRESIZE*)lParam; + POINT ptScreenBottomRight; + + if (!GetWindowRect(hwndDlg, &rcDlg)) + break; + if (!GetWindowRect(hwndCtl, &rcCtl)) + break; + if (!GetWindowRect(GetDlgItem(hwndDlg, IDC_TEXT), &rcEdit)) + break; + rcNew.left = rcCtl.left + 30; + rcNew.top = rcCtl.bottom + 10; + rcNew.right = rcNew.left + (rr->rc.right - rr->rc.left) + (rcDlg.right - rcDlg.left) - (rcEdit.right - rcEdit.left) + (GetWindowLongPtr(GetDlgItem(hwndDlg, IDC_TEXT), GWL_STYLE)&WS_VSCROLL ? GetSystemMetrics(SM_CXVSCROLL) : 0); + if (GetWindowTextLength(GetDlgItem(hwndDlg, IDC_TEXT))) + rcNew.bottom = rcNew.top + min(GetSystemMetrics(SM_CYSCREEN) / 5, (rr->rc.bottom - rr->rc.top) + (rcDlg.bottom - rcDlg.top) - (rcEdit.bottom - rcEdit.top)); + else + rcNew.bottom = rcNew.top + min(GetSystemMetrics(SM_CYSCREEN) / 5, (rcDlg.bottom - rcDlg.top) - (rcEdit.bottom - rcEdit.top)); + if (GetSystemMetrics(SM_CXVIRTUALSCREEN)) { + ptScreenBottomRight.x = GetSystemMetrics(SM_CXVIRTUALSCREEN) + GetSystemMetrics(SM_XVIRTUALSCREEN); + ptScreenBottomRight.y = GetSystemMetrics(SM_CYVIRTUALSCREEN) + GetSystemMetrics(SM_YVIRTUALSCREEN); + } + else { + ptScreenBottomRight.x = GetSystemMetrics(SM_CXSCREEN); + ptScreenBottomRight.y = GetSystemMetrics(SM_CYSCREEN); + } + if (rcNew.right >= ptScreenBottomRight.x) + OffsetRect(&rcNew, ptScreenBottomRight.x - rcNew.right, 0); + if (rcNew.bottom >= ptScreenBottomRight.y) + OffsetRect(&rcNew, 0, ptScreenBottomRight.y - rcNew.bottom); + SetWindowPos(hwndDlg, 0, rcNew.left, rcNew.top, rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, SWP_NOZORDER); + ShowWindow(hwndDlg, SW_SHOWNORMAL); + break; + } +#endif // defined EDITOR + } + } + break; + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDCANCEL: // WM_CLOSE + DestroyWindow(hwndDlg); + return TRUE; + } + break; + case WM_DESTROY: +#ifndef EDITOR + FreeHyperlinkData(); + if (IsWindow(hwndShadowDlg)) + DestroyWindow(hwndShadowDlg); + if (hwndToolTip != NULL) + DestroyWindow(hwndToolTip); +#endif + hwndHelpDlg = NULL; + break; + } + return FALSE; +} -- cgit v1.2.3