본문 바로가기
IT-개발,DB

[개발/MFC] 마우스가 위치한 곳의 정확한 단어를 얻기

by SB리치퍼슨 2012. 7. 22.

인터넷 익스플로러를 사용하면서 마우스가 위치한 곳의 링크나 문자열을 알아보고 싶을 때가 생긴다.

마우스가 위치한 곳의 단어나 링크를 알아보자.


[개발/MFC] 마우스가 위치한 곳의 정확한 단어를 얻기


마우스가 위치한 곳의 정확한 단어를 얻기

[출처] http://blog.naver.com/PostView.nhn?blogId=kkt3212&logNo=100052743892&parentCategoryNo=&categoryNo=&viewDate=&isShowPopularPosts=false&from=postView


마우스가 위치한 곳의 정확한 단어를 얻기

/**

   모든 IHTMLDocument2 문서에 도규먼트 와처를 다는 것 보다는 

   클릭시 마우스아래의 태그가 무엇인지를 파악하는 것이 더 낫다..

*/

#include <Oleacc.h>

#pragma comment(lib,_T("Oleacc.lib"))


/**

    문서의 좌측 상단을 기준으로 해당 Element가 Width, Height를 구하는데 부모 Element를 타고 올라가서 

상대값을 각각 합친다.

*/

void GetOffsetParentRecursion(long &left, long&top, CComQIPtr<IHTMLElement> &pElem)

{

long x=0,  y=0;

pElem->get_offsetLeft(&x);

pElem->get_offsetTop(&y) ;

left += x;

top += y;

CComQIPtr<IHTMLElement> pElemParent;

pElem->get_offsetParent(&pElemParent);

if( pElemParent)

GetOffsetParentRecursion(left, top, pElemParent);

}


/**

IHTMLElement가 있는 스크린 좌표의 left,top의 좌표 ,offsetHeight의 크기 좌표를 얻는다.

*/

bool    GetHtmlElementScreenXY(long& Screenleft, 

                               long& Screentop,

                               //long& offsetHeight,

  long& clientLeft,

  long& clientTop,

                               CComQIPtr<IHTMLDocument2> pDoc2 ,

                               CComQIPtr<IHTMLElement> pElem )

{       


long nBodyClientLeft =0, nBodyClientTop=0;    

    CComPtr<IHTMLElement> pBodyElem;

    pDoc2->get_body(&pBodyElem);

    if(pBodyElem)

    {

        CComQIPtr<IHTMLElement2> pBody = pBodyElem;

        if(pBody)

        {

            pBody->get_clientLeft(&nBodyClientLeft) ;

            pBody->get_clientTop (&nBodyClientTop) ;

        }

    }


    //문서 기준으로 해당 패스워드 필드가 존재하는 좌표를 구한다..

    //부모 Element를 타고 올라가서 모든 offsetLeft와 offsetTop을 합친다.

    long offsetLeftSum = 0, offsetTopSum = 0;

    GetOffsetParentRecursion(offsetLeftSum, offsetTopSum, pElem);

    

    //바디 클라이언트와 합쳐서 정확한 left, top을 구한다. IHTMLDocumnet2 기준이다.

    int nDocumnetLeft = nBodyClientLeft + offsetLeftSum ;

    int nDocumnetTop = nBodyClientTop + offsetTopSum;

    

    CComPtr<IHTMLWindow2> pWin2 ;

    pDoc2->get_parentWindow(&pWin2) ;

    if(! pWin2) 

        return false;

    

    CComQIPtr<IHTMLWindow3> pWin3  = pWin2;

    if( ! pWin3 )

        return false;

    

    long nScreenLeft =0, nScreenTop = 0; //프레임 문서의 왼쪽 위 좌표인데, 스크린 기준이다.

    pWin3->get_screenLeft(&nScreenLeft);

    pWin3->get_screenTop(&nScreenTop);

    

    //스크롤을 맨위로 맨왼쪽으로 옮겨야 해당 좌표기준이 맞게된다.

    //pWin2->scroll(0,0); 


    Screenleft = nScreenLeft + nDocumnetLeft;

    Screentop = nScreenTop + nDocumnetTop;

clientLeft = nDocumnetLeft;

clientTop = nDocumnetTop;

    //pElem->get_offsetHeight(&offsetHeight);

    return true;

}                



void CBDBand::UserClick()

    try

    {    

        POINT ptScreen;

   ::GetCursorPos(&ptScreen);

   CComPtr<IAccessible> pAccess;

   CComVariant var;

   HRESULT hr = AccessibleObjectFromPoint(ptScreen, &pAccess, &var) ;

   if( FAILED(hr)) 

   {

       throw FALSE;    

   }


        CComQIPtr<IServiceProvider > pSP = pAccess;

        if(!pSP)

            throw FALSE;


        CComPtr<IHTMLElement> pElem;

        pSP->QueryService(IID_IHTMLElement, IID_IHTMLElement, (void**)&pElem);

        if(!pElem)

            throw FALSE;


        //Alt가 눌려져 있는가?

        BOOL bSearchDic = (0x8000 & GetAsyncKeyState(VK_MENU)) == 0x8000;


        if(bSearchDic)

        {


            CComPtr<IDispatch>  pDocDisp;

            pElem->get_document(&pDocDisp);

            if( !pDocDisp)

                throw FALSE;

            

            CComQIPtr<IHTMLDocument2> pDoc2 = pDocDisp;

            if( ! pDoc2)

                throw FALSE;


            CComPtr<IHTMLElement> pBodyElem;

            pDoc2->get_body(&pBodyElem);

            if( ! pBodyElem)

                throw FALSE;


            CComQIPtr<IHTMLBodyElement> pBody = pBodyElem;

            if( ! pBody)

                throw FALSE;


            CComQIPtr<IHTMLTxtRange> spHTMLTxtRange;

            pBody->createTextRange(&spHTMLTxtRange);

            if( ! spHTMLTxtRange)

                throw FALSE;

            CComQIPtr<IHTMLElement> pElem2 = pElem;

            if( !pElem2)

                throw FALSE;


            long ScreenLeft, ScreenTop, ClientLeft, ClientTop;

            if( ! GetHtmlElementScreenXY(ScreenLeft, ScreenTop, ClientLeft, ClientTop, pDoc2, pElem2))

                throw FALSE;

            POINT pt;

            GetCursorPos(&pt);

            long dx = pt.x - ScreenLeft;

            long dy = pt.y - ScreenTop;

            

            long ClientX = ClientLeft + dx;

            long ClientY = ClientTop + dy;                       


            spHTMLTxtRange->moveToPoint(ClientX, ClientY);            


            CComBSTR bsText;

CComBSTR bsUnit(L"word");

VARIANT_BOOL bSuccess;

spHTMLTxtRange->expand(bsUnit, &bSuccess);

spHTMLTxtRange->get_text(&bsText);

            CString sKeyword(bsText);

            

            sKeyword.Replace(" ","");

            m_strSearchDic = sKeyword;


            if(m_strSearchDic.GetLength())

            {

                m_bUserClickedLink = TRUE;

                m_wndToolBar.PostMessage(OCM_COMMAND, IDM_DIC_SEARCH, 0);

            }

        

        }else

        {    

            CComBSTR bsTagName;        

            while(TRUE)

            {            

                if(FAILED(pElem->get_tagName(&bsTagName)))

                    break;

                bsTagName.ToUpper();


if (bsTagName == L"BODY")

break; // did not click a link


       if (bsTagName == L"A" ||

       bsTagName == L"AREA" ||

       bsTagName == L"INPUT" ||

       bsTagName == L"IMG")

                {

                    m_bUserClickedLink=TRUE; 

                    g_dwClickTime = GetTickCount();

                    break;

                }   

                

           CComPtr<IHTMLElement> spParentElem;

hr = pElem->get_parentElement(&spParentElem);

if (FAILED(hr) || !spParentElem)

break;

pElem = spParentElem;

            }

        }

    }catch(...)

    {

        m_bUserClickedLink=TRUE; 

    }    

}


반응형

댓글