diff options
Diffstat (limited to 'src/modules/utils/hyperlink.cpp')
-rw-r--r-- | src/modules/utils/hyperlink.cpp | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/src/modules/utils/hyperlink.cpp b/src/modules/utils/hyperlink.cpp new file mode 100644 index 0000000000..62d307a958 --- /dev/null +++ b/src/modules/utils/hyperlink.cpp @@ -0,0 +1,274 @@ +/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2009 Miranda ICQ/IM project,
+all portions of this codebase are copyrighted to the people
+listed in contributors.txt.
+
+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; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+#include "commonheaders.h"
+
+struct HyperlinkWndData {
+ HFONT hEnableFont,hDisableFont;
+ RECT rcText;
+ COLORREF enableColor, disableColor, focusColor;
+ BYTE flags; /* see HLKF_* */
+};
+
+/* flags */
+#define HLKF_HASENABLECOLOR 0x1 /* dat->enableColor is not system default */
+#define HLKF_HASDISABLECOLOR 0x2 /* dat->disableColor is not system default */
+
+/* internal messages */
+#define HLK_MEASURETEXT (WM_USER+1)
+#define HLK_INVALIDATE (WM_USER+2)
+
+static LRESULT CALLBACK HyperlinkWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ struct HyperlinkWndData *dat=(struct HyperlinkWndData*)GetWindowLongPtr(hwnd,0);
+ switch(msg) {
+ case WM_NCCREATE:
+ dat=(struct HyperlinkWndData*)mir_calloc(sizeof(struct HyperlinkWndData));
+ if(dat==NULL) return FALSE; /* fail creation */
+ SetWindowLongPtr(hwnd,0,(LONG_PTR)dat); /* always succeeds */
+ /* fall thru */
+ case WM_SYSCOLORCHANGE:
+ if(!(dat->flags&HLKF_HASENABLECOLOR)) {
+ if(GetSysColorBrush(COLOR_HOTLIGHT)==NULL) dat->enableColor=RGB(0,0,255);
+ else dat->enableColor=GetSysColor(COLOR_HOTLIGHT);
+ dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
+ }
+ if(!(dat->flags&HLKF_HASDISABLECOLOR))
+ dat->disableColor=GetSysColor(COLOR_GRAYTEXT);
+ break;
+
+ case WM_SETFOCUS:
+ case WM_KILLFOCUS:
+ RedrawWindow(hwnd, NULL, NULL, RDW_INVALIDATE);
+ break;
+ case WM_MOUSEACTIVATE:
+ SetFocus(hwnd);
+ return MA_ACTIVATE;
+ case WM_GETDLGCODE:
+ {
+ if (lParam)
+ {
+ MSG *msg = (MSG *) lParam;
+ if (msg->message == WM_KEYDOWN)
+ {
+ if (msg->wParam == VK_TAB)
+ return 0;
+ if (msg->wParam == VK_ESCAPE)
+ return 0;
+ } else
+ if (msg->message == WM_CHAR)
+ {
+ if (msg->wParam == '\t')
+ return 0;
+ if (msg->wParam == 27)
+ return 0;
+ }
+ }
+ return DLGC_WANTMESSAGE;
+ }
+
+ case WM_KEYDOWN:
+ {
+ switch (wParam)
+ {
+ case VK_SPACE:
+ case VK_RETURN:
+ SendMessage(GetParent(hwnd),WM_COMMAND,MAKEWPARAM(GetDlgCtrlID(hwnd),STN_CLICKED),(LPARAM)hwnd);
+ break;
+ }
+ return 0;
+ }
+
+ case WM_LBUTTONDOWN:
+ { POINT pt;
+ POINTSTOPOINT(pt,MAKEPOINTS(lParam));
+ if(!PtInRect(&dat->rcText,pt)) break;
+ SendMessage(GetParent(hwnd),WM_COMMAND,MAKEWPARAM(GetDlgCtrlID(hwnd),STN_CLICKED),(LPARAM)hwnd);
+ return 0;
+ }
+ case WM_SETFONT:
+ { LOGFONT lf;
+ HFONT hFont;
+ if((HFONT)wParam==NULL) { /* use default system color */
+ dat->hEnableFont=dat->hDisableFont=NULL;
+ return 0;
+ }
+ if(GetObject((HFONT)wParam,sizeof(lf),&lf)) {
+ lf.lfUnderline=1;
+ hFont=CreateFontIndirect(&lf);
+ if(hFont!=NULL) {
+ dat->hEnableFont=hFont;
+ dat->hDisableFont=(HFONT)wParam;
+ if(LOWORD(lParam)) SendMessage(hwnd,HLK_INVALIDATE,0,0);
+ SendMessage(hwnd,HLK_MEASURETEXT,0,0);
+ }
+ }
+ return 0;
+ }
+ case WM_ERASEBKGND:
+ return TRUE;
+ case WM_ENABLE:
+ case HLK_INVALIDATE:
+ { RECT rcWnd;
+ POINT pt;
+ HWND hwndParent;
+ if(!GetWindowRect(hwnd,&rcWnd)) break;
+ pt.x=rcWnd.left;
+ pt.y=rcWnd.top;
+ hwndParent=GetParent(hwnd);
+ if(hwndParent==NULL) hwndParent=hwnd;
+ if(!ScreenToClient(hwndParent,&pt)) break;
+ rcWnd.right=pt.x+(rcWnd.right-rcWnd.left);
+ rcWnd.bottom=pt.y+(rcWnd.bottom-rcWnd.top);
+ rcWnd.left=pt.x;
+ rcWnd.top=pt.y;
+ InvalidateRect(hwndParent,&rcWnd,TRUE);
+ return 0;
+ }
+ case WM_GETFONT:
+ return (LRESULT)dat->hDisableFont;
+ case WM_CREATE:
+ case HLK_MEASURETEXT:
+ { TCHAR szText[256];
+ if(!GetWindowText(hwnd,szText,SIZEOF(szText))) return 0;
+ lParam=(LPARAM)szText;
+ /* fall thru */
+ case WM_SETTEXT:
+ { HFONT hPrevFont = NULL;
+ SIZE textSize;
+ RECT rc;
+ HDC hdc;
+ LONG style;
+ BOOL fMeasured=FALSE;
+ hdc=GetDC(hwnd);
+ if(hdc==NULL) return 0; /* text change failed */
+ if(dat->hEnableFont!=NULL) hPrevFont=(HFONT)SelectObject(hdc,dat->hEnableFont);
+ if(dat->hEnableFont==NULL || hPrevFont!=NULL) /* select failed? */
+ if(GetTextExtentPoint32(hdc,(TCHAR*)lParam,lstrlen((TCHAR*)lParam),&textSize))
+ if(GetClientRect(hwnd,&rc)) {
+ dat->rcText.top=0;
+ dat->rcText.bottom=dat->rcText.top+textSize.cy;
+ style=GetWindowLongPtr(hwnd,GWL_STYLE);
+ if(style&SS_CENTER) dat->rcText.left=(rc.right-textSize.cx)/2;
+ else if(style&SS_RIGHT) dat->rcText.left=rc.right-textSize.cx;
+ else dat->rcText.left=0;
+ dat->rcText.right=dat->rcText.left+textSize.cx;
+ fMeasured=TRUE;
+ }
+ if(dat->hEnableFont!=NULL && hPrevFont!=NULL) SelectObject(hdc,hPrevFont);
+ ReleaseDC(hwnd,hdc);
+ if(!fMeasured) return 0; /* text change failed */
+ SendMessage(hwnd,HLK_INVALIDATE,0,0);
+ break;
+ }}
+ case WM_SETCURSOR:
+ { POINT pt;
+ HCURSOR hCursor;
+ if(!GetCursorPos(&pt)) return FALSE;
+ if(!ScreenToClient(hwnd,&pt)) return FALSE;
+ if(PtInRect(&dat->rcText,pt)) {
+ hCursor=(HCURSOR)GetClassLongPtr(hwnd,GCLP_HCURSOR);
+ if(hCursor==NULL) hCursor=LoadCursor(NULL,IDC_HAND); /* Win2000+ */
+ }
+ else hCursor=LoadCursor(NULL,IDC_ARROW);
+ SetCursor(hCursor);
+ return TRUE;
+ }
+ case HLK_SETENABLECOLOUR:
+ { COLORREF prevColor=dat->enableColor;
+ dat->enableColor=(COLORREF)wParam;
+ dat->focusColor = RGB(GetRValue(dat->enableColor) / 2, GetGValue(dat->enableColor) / 2, GetBValue(dat->enableColor) / 2);
+ dat->flags|=HLKF_HASENABLECOLOR;
+ return (LRESULT)prevColor;
+ }
+ case HLK_SETDISABLECOLOUR:
+ { COLORREF prevColor=dat->disableColor;
+ dat->disableColor=(COLORREF)wParam;
+ dat->flags|=HLKF_HASDISABLECOLOR;
+ return (LRESULT)prevColor;
+ }
+ case WM_NCPAINT:
+ return 0;
+ case WM_PAINT:
+ { HFONT hPrevFont;
+ RECT rc;
+ TCHAR szText[256];
+ UINT alignFlag;
+ COLORREF textColor;
+ PAINTSTRUCT ps;
+ HDC hdc;
+
+ hdc=BeginPaint(hwnd,&ps);
+ if(hdc!=NULL) {
+ if(IsWindowEnabled(hwnd)) {
+ hPrevFont=(HFONT)SelectObject(hdc,dat->hEnableFont);
+ textColor = (GetFocus() == hwnd) ? dat->focusColor : dat->enableColor;
+ } else {
+ hPrevFont=(HFONT)SelectObject(hdc,dat->hDisableFont);
+ textColor=dat->disableColor;
+ }
+ if(GetClientRect(hwnd,&rc) && GetWindowText(hwnd,szText,SIZEOF(szText))) {
+ if (drawThemeParentBackground && IsWinVerXPPlus())
+ {
+ BOOL fSmoothing;
+ UINT fSmoothingType;
+ SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fSmoothing, 0);
+ SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &fSmoothingType, 0);
+ if (fSmoothing && fSmoothingType == FE_FONTSMOOTHINGCLEARTYPE)
+ drawThemeParentBackground(hwnd, hdc, &rc);
+ }
+ SetBkMode(hdc,TRANSPARENT);
+ SetTextColor(hdc,textColor);
+ alignFlag=(GetWindowLongPtr(hwnd,GWL_STYLE)&(SS_CENTER|SS_RIGHT|SS_LEFT));
+ DrawText(hdc,szText,-1,&rc,alignFlag|DT_NOPREFIX|DT_SINGLELINE|DT_TOP);
+ }
+ if(hPrevFont!=NULL) SelectObject(hdc,hPrevFont);
+ EndPaint(hwnd,&ps);
+ }
+ return 0;
+ }
+ case WM_NCDESTROY:
+ if(dat->hEnableFont!=NULL) DeleteObject(dat->hEnableFont);
+ mir_free(dat);
+ break;
+ }
+ return DefWindowProc(hwnd,msg,wParam,lParam);
+}
+
+int InitHyperlink(void)
+{
+ WNDCLASS wcl;
+
+ wcl.lpfnWndProc=HyperlinkWndProc;
+ wcl.cbClsExtra=0;
+ wcl.cbWndExtra=sizeof(struct HyperlinkWndData*);
+ wcl.hInstance=hMirandaInst;
+ if(IsWinVer2000Plus()) wcl.hCursor=NULL;
+ else wcl.hCursor=LoadCursor(wcl.hInstance,MAKEINTRESOURCE(IDC_HYPERLINKHAND));
+ wcl.lpszClassName=WNDCLASS_HYPERLINK;
+ wcl.hbrBackground=NULL;
+ wcl.hIcon=NULL;
+ wcl.lpszMenuName=NULL;
+ wcl.style=CS_HREDRAW|CS_VREDRAW|CS_GLOBALCLASS|CS_PARENTDC;
+ RegisterClass(&wcl); /* automatically unregistered on exit */
+ return 0;
+}
|