www.gusucode.com > 一个VC++语法分析模块程序实例源码程序 > 一个VC++语法分析模块程序实例/CompileSys/CompileSys/IDE/HyperLink.cpp

    // HyperLink.cpp : implementation file
// Download: http://www.codesc.net

#include "stdafx.h"
#include "HyperLink.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define TOOLTIP_ID 1
/////////////////////////////////////////////////////////////////////////////
// CHyperLink

CHyperLink::CHyperLink()
{
	m_iHyperLinkSort=HLS_MAIL;
    m_hLinkCursor=NULL;                                //无光标
    m_crLinkColour=RGB(0,0,255);                       //蓝色
    m_crVisitedColour=RGB(0,255,0);                    //紫色
    m_crHoverColour=RGB(255,0,0);
    m_bOverControl=FALSE;                              // Cursor not yet over control
    m_bVisited=FALSE;                                  //未访问
    m_bUnderline=1;                                    //有下划线
    m_bAdjustToFit=TRUE;                               // Resize the window to fit the text?
    m_strURL.Empty();
}

CHyperLink::~CHyperLink()
{
    m_Font.DeleteObject();
}


BEGIN_MESSAGE_MAP(CHyperLink, CStatic)
	//{{AFX_MSG_MAP(CHyperLink)
	ON_WM_CTLCOLOR_REFLECT()
	ON_WM_SETCURSOR()
	ON_WM_MOUSEMOVE()
    ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHyperLink message handlers

BOOL CHyperLink::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	m_ToolTip.RelayEvent(pMsg);

	return CStatic::PreTranslateMessage(pMsg);
}

void CHyperLink::OnClicked()
{
	if(m_iHyperLinkSort==HLS_MAIL)
	{
		GotoMail(m_strMail,SW_SHOW);
		SetVisited();
		return;
	}

    int result=(int)GotoURL(m_strURL,SW_SHOW);
    m_bVisited=(result >HINSTANCE_ERROR);
    if(!m_bVisited) 
	{
        MessageBeep(MB_ICONEXCLAMATION);// Unable to follow link
        ReportError(result);
	}
	else 
        SetVisited();// Repaint to show visited colour
}

void CHyperLink::PreSubclassWindow() 
{
	// TODO: Add your specialized code here and/or call the base class
    // We want to get mouse clicks via STN_CLICKED
    DWORD dwStyle=GetStyle();

    ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);
    
    // Set the URL as the window text
    if (m_strURL.IsEmpty())
        GetWindowText(m_strURL);
	
    // Check that the window text isn't empty. If it is, set it as the URL.
    CString strWndText;
    GetWindowText(strWndText);
    if(strWndText.IsEmpty()) 
	{
        ASSERT(!m_strURL.IsEmpty());// Window and URL both NULL. DUH!
        SetWindowText(m_strURL);
    }
	
    //Create the font
    LOGFONT lf;
    GetFont()->GetLogFont(&lf);
    lf.lfUnderline=m_bUnderline;
    m_Font.CreateFontIndirect(&lf);
    SetFont(&m_Font);
	
    PositionWindow();        // Adjust size of window to fit URL if necessary
    SetDefaultCursor();      // Try and load up a "hand" cursor
	
    //Create the tooltip
    CRect rect; 
    GetClientRect(rect);
    m_ToolTip.Create(this);
    m_ToolTip.AddTool(this,m_strURL,rect,TOOLTIP_ID);
	
	CStatic::PreSubclassWindow();
}

HBRUSH CHyperLink::CtlColor(CDC* pDC, UINT nCtlColor) 
{
	// TODO: Change any attributes of the DC here
    ASSERT(nCtlColor == CTLCOLOR_STATIC);
	
    if (m_bOverControl)
        pDC->SetTextColor(m_crHoverColour);
    else if (m_bVisited)
        pDC->SetTextColor(m_crVisitedColour);
    else
        pDC->SetTextColor(m_crLinkColour);
	
    //transparent text.
    pDC->SetBkMode(TRANSPARENT);
    return (HBRUSH)GetStockObject(NULL_BRUSH);	
}

BOOL CHyperLink::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
    if (m_hLinkCursor)
    {
        ::SetCursor(m_hLinkCursor);
        return TRUE;
    }

    return FALSE;
}

void CHyperLink::OnMouseMove(UINT nFlags, CPoint point) 
{
	// TODO: Add your message handler code here and/or call default	
	CStatic::OnMouseMove(nFlags, point);
	
    if(m_bOverControl)// Cursor is currently over control
    {
        CRect rect;
        GetClientRect(rect);
		
        if(!rect.PtInRect(point))
        {
            m_bOverControl=FALSE;
            ReleaseCapture();
            RedrawWindow();

            return;
        }
    }
    else//Cursor has just moved over control
    {
        m_bOverControl=TRUE;
        RedrawWindow();
        SetCapture();
    }	
}

/////////////////////////////////////////////////////////
//CHyperLink operations
void CHyperLink::SetURL(CString strURL)
{
    m_strURL=strURL;
	m_iHyperLinkSort=HLS_URL;

    if(::IsWindow(GetSafeHwnd()))
	{
        PositionWindow();
        m_ToolTip.UpdateTipText(strURL,this,TOOLTIP_ID);
    }
}

void CHyperLink::SetMail(CString strMail)
{
    m_strMail=strMail;
	m_iHyperLinkSort=HLS_MAIL;

    if(::IsWindow(GetSafeHwnd()))
	{
        PositionWindow();
        m_ToolTip.UpdateTipText(strMail,this,TOOLTIP_ID);
    }
}

void CHyperLink::SetColours(COLORREF crLinkColour, COLORREF crVisitedColour,
                            COLORREF crHoverColour /* = -1 */) 
{ 
    m_crLinkColour=crLinkColour; 
    m_crVisitedColour=crVisitedColour;

	if(crHoverColour==-1)
		m_crHoverColour=::GetSysColor(COLOR_HIGHLIGHT);
	else
		m_crHoverColour=crHoverColour;

    if (::IsWindow(m_hWnd))
        Invalidate(); 
}

void CHyperLink::SetVisited(BOOL bVisited /* = TRUE */) 
{ 
    m_bVisited = bVisited; 

    if (::IsWindow(GetSafeHwnd()))
        Invalidate(); 
}

void CHyperLink::SetLinkCursor(HCURSOR hCursor)
{ 
    m_hLinkCursor = hCursor;
    if (m_hLinkCursor == NULL)
        SetDefaultCursor();
}

void CHyperLink::SetUnderline(BOOL bUnderline /* = TRUE */)
{
    m_bUnderline=bUnderline;

    if(::IsWindow(GetSafeHwnd()))
    {
        LOGFONT lf;
        GetFont()->GetLogFont(&lf);
        lf.lfUnderline = m_bUnderline;

        m_Font.DeleteObject();
        m_Font.CreateFontIndirect(&lf);
        SetFont(&m_Font);

        Invalidate(); 
    }
}

void CHyperLink::SetAutoSize(BOOL bAutoSize /* = TRUE */)
{
    m_bAdjustToFit=bAutoSize;

    if(::IsWindow(GetSafeHwnd()))
        PositionWindow();
}

void CHyperLink::PositionWindow()
{
    if (!::IsWindow(GetSafeHwnd()) || !m_bAdjustToFit) 
        return;

    // Get the current window position
    CRect rect;
    GetWindowRect(rect);

    CWnd* pParent = GetParent();
    if(pParent)
        pParent->ScreenToClient(rect);

    // Get the size of the window text
    CString strWndText;
    GetWindowText(strWndText);

    CDC* pDC = GetDC();
    CFont* pOldFont=pDC->SelectObject(&m_Font);
    CSize Extent=pDC->GetTextExtent(strWndText);
    pDC->SelectObject(pOldFont);
    ReleaseDC(pDC);

    // Get the text justification via the window style
    DWORD dwStyle = GetStyle();

    // Recalc the window size and position based on the text justification
    if(dwStyle & SS_CENTERIMAGE)
        rect.DeflateRect(0,(rect.Height()-Extent.cy)/2);
    else
        rect.bottom=rect.top+Extent.cy;

    if(dwStyle & SS_CENTER)   
        rect.DeflateRect((rect.Width()-Extent.cx)/2,0);
    else 
		if(dwStyle & SS_RIGHT) 
			rect.left=rect.right-Extent.cx;
		else // SS_LEFT = 0, so we can't test for it explicitly 
			rect.right=rect.left+Extent.cx;

    // Move the window
    SetWindowPos(NULL,rect.left,rect.top,rect.Width(),rect.Height(),SWP_NOZORDER);
}

/////////////////////////////////////////////////////////////////////////////
// CHyperLink implementation

// The following appeared in Paul DiLascia's Jan 1998 MSJ articles.
// It loads a "hand" cursor from the winhlp32.exe module
void CHyperLink::SetDefaultCursor()
{
    if(m_hLinkCursor == NULL)                // No cursor handle - load our own
    {
        // Get the windows directory
        CString strWndDir;
        GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH),MAX_PATH);
        strWndDir.ReleaseBuffer();

        strWndDir+=_T("\\winhlp32.exe");
        // This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
        HMODULE hModule = LoadLibrary(strWndDir);
        if(hModule)
		{
            HCURSOR hHandCursor=::LoadCursor(hModule, MAKEINTRESOURCE(106));
            if (hHandCursor)
                m_hLinkCursor=CopyCursor(hHandCursor);
        }
        FreeLibrary(hModule);
    }
}

LONG CHyperLink::GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata)
{
    HKEY hkey;
    LONG retval=RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey);

    if(retval==ERROR_SUCCESS) 
	{
        long datasize=MAX_PATH;
        TCHAR data[MAX_PATH];
        RegQueryValue(hkey,NULL,data,&datasize);
        lstrcpy(retdata,data);
        RegCloseKey(hkey);
    }

    return retval;
}

void CHyperLink::ReportError(int nError)
{
    CString str;
    switch (nError) 
	{
        case 0:                
			str="The operating system is out\nof memory or resources.";
			break;

        case SE_ERR_PNF:         
			str = "The specified path was not found."; 
			break;

        case SE_ERR_FNF:         
			str="The specified file was not found.";
			break;

        case ERROR_BAD_FORMAT:    
			str="The .EXE file is invalid\n(non-Win32 .EXE or error in .EXE image).";
			break;

        case SE_ERR_ACCESSDENIED:   
			str="The operating system denied\naccess to the specified file.";
			break;

        case SE_ERR_ASSOCINCOMPLETE:
			str="The filename association is\nincomplete or invalid."; 
			break;

        case SE_ERR_DDEBUSY:       
			str="The DDE transaction could not\nbe completed because other DDE transactions\nwere being processed.";
			break;

        case SE_ERR_DDEFAIL:      
			str="The DDE transaction failed."; 
			break;

        case SE_ERR_DDETIMEOUT:  
			str="The DDE transaction could not\nbe completed because the request timed out.";
			break;

        case SE_ERR_DLLNOTFOUND:    
			str="The specified dynamic-link library was not found.";
			break;

        case SE_ERR_NOASSOC:    
			str="There is no application associated\nwith the given filename extension.";
			break;

        case SE_ERR_OOM:       
			str="There was not enough memory to complete the operation."; 
			break;

        case SE_ERR_SHARE:     
			str="A sharing violation occurred. ";

        default:              
			str.Format("Unknown Error (%d) occurred.",nError);
			break;
    }
    str="Unable to open hyperlink:\n\n"+str;
    AfxMessageBox(str,MB_ICONEXCLAMATION | MB_OK);
}

HINSTANCE CHyperLink::GotoURL(LPCTSTR url, int showcmd)
{
    TCHAR key[MAX_PATH + MAX_PATH];

    // First try ShellExecute()
    HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd);

    // If it failed, get the .htm regkey and lookup the program
    if((UINT)result <= HINSTANCE_ERROR)
	{
        if(GetRegKey(HKEY_CLASSES_ROOT,_T(".htm"), key)==ERROR_SUCCESS) 
		{
            lstrcat(key, _T("\\shell\\open\\command"));

            if(GetRegKey(HKEY_CLASSES_ROOT,key,key)==ERROR_SUCCESS)
			{
                TCHAR *pos;
                pos=_tcsstr(key,_T("\"%1\""));
                if(pos == NULL)//No quotes found
				{                     
                    pos=strstr(key,_T("%1"));// Check for %1, without quotes 
                    if(pos==NULL)// No parameter at all...
                        pos=key+lstrlen(key)-1;
                    else
                        *pos='\0';// Remove the parameter
                }
                else
                    *pos='\0';// Remove the parameter

                lstrcat(pos,_T(" "));
                lstrcat(pos,url);
                result=(HINSTANCE)WinExec(key,showcmd);
            }
        }
    }

    return result;
}

void CHyperLink::GotoMail(CString strMail,int iShowCmd)
{
	ShellExecute(NULL,"open","mailto:"+strMail,"","",iShowCmd);
}