菜單懸浮

頭文件

#pragma once



#include "SivExtendCtrlLib.h"
// CTreeCtrlEx
typedef void (*DRAWCALLBACK)(CDC* pDC,void* pTree);


class CBitmapMenu : public CMenu
{
DECLARE_DYNAMIC(CBitmapMenu)


public:
CBitmapMenu();
virtual ~CBitmapMenu();


public:
virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
virtual void MeasureItem(LPMEASUREITEMSTRUCT /*lpMeasureItemStruct*/);
public:
void SetMenuWidth(int nWid);
void SetMenuHeight(int nHei);
void SetDrawCallBack(DRAWCALLBACK pFn);
void SetDrawBitmapHandle(CBitmap* pBitmap/*HBITMAP hBitmap*/);
private:
int m_nWid;
int m_nHei;
DRAWCALLBACK m_pfnDraw;
//HBITMAP m_hBitmap;
//CBitmap* m_pBitmap;
};


class SIV_EXTENDCTRL_API CTreeCtrlEx : public CTreeCtrl
{
DECLARE_DYNAMIC(CTreeCtrlEx)


public:
CTreeCtrlEx();
virtual ~CTreeCtrlEx();
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
virtual void PreSubclassWindow();


int m_nDrawItem;
private:
CBitmapMenu m_menu;
HBRUSH m_menuBackCl;
LONG m_nImageW;
LONG m_nImageH;
CPoint m_pt;


static void DrawMenuImage(CDC *pDC,void* pTree);
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);

};

源文件:

// TreeCtrlEx.cpp : implementation file
//


#include "stdafx.h"
#include "SivExtendCtrlLib.h"
#include "TreeCtrlEx.h"




// CTreeCtrlEx
IMPLEMENT_DYNAMIC(CBitmapMenu, CMenu)


CBitmapMenu::CBitmapMenu()
{
m_nWid=-1;
m_nHei=-1;
m_pfnDraw=NULL;
}


CBitmapMenu::~CBitmapMenu()
{
/*if(m_pBitmap!=NULL)
delete m_pBitmap;*/
}
void CBitmapMenu::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// TODO:  Add your code to draw the specified item
if(m_pfnDraw!=NULL)
{
CDC* pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
MENUINFO menuinfo;
menuinfo.cbSize=sizeof(MENUINFO);
menuinfo.fMask=MIM_MENUDATA;
GetMenuInfo(&menuinfo);
m_pfnDraw(pDC,(void*)(menuinfo.dwMenuData));
}
/*CDC* pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
Bitmap* bp=Bitmap::FromHBITMAP(m_pBitmap,NULL);
Graphics gh(pDC->m_hDC);
gh.DrawImage(bp,0,0,bp->GetWidth(),bp->GetHeight());
delete bp;*/
}
void CBitmapMenu::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
// TODO:  Add your code to determine the size of specified item
if(m_nWid!=-1)
  lpMeasureItemStruct->itemWidth=m_nWid;
if(m_nHei!=-1)
  lpMeasureItemStruct->itemHeight=m_nHei;
}
void CBitmapMenu::SetMenuWidth(int nWid)
{
m_nWid=nWid;
}
void CBitmapMenu::SetMenuHeight(int nHei)
{
m_nHei=nHei;
}
void CBitmapMenu::SetDrawCallBack(DRAWCALLBACK pFn)
{
m_pfnDraw=pFn;
}
//void CBitmapMenu::SetDrawBitmapHandle(CBitmap* pBitmap)
//{
// if(m_pBitmap!=NULL)
//   delete m_pBitmap;
//    m_pBitmap=pBitmap;
//}


IMPLEMENT_DYNAMIC(CTreeCtrlEx, CTreeCtrl)


CTreeCtrlEx::CTreeCtrlEx()
{
m_nDrawItem=0;
m_menuBackCl=CreateSolidBrush(RGB(255,255,255));
m_nImageW=-1;
m_nImageH=-1;
}


CTreeCtrlEx::~CTreeCtrlEx()
{
if(m_menu.GetSafeHmenu())
       m_menu.DestroyMenu();


DeleteObject(m_menuBackCl);
}




BEGIN_MESSAGE_MAP(CTreeCtrlEx, CTreeCtrl)
ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()


// CTreeCtrlEx message handlers
void CTreeCtrlEx::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
UINT uFlags;
HTREEITEM hItem = HitTest(point, &uFlags);
BOOL bHas=ItemHasChildren(hItem);
HTREEITEM hItemRoot=GetRootItem();
//BOOL bRoot=
/*if(m_menu.GetSafeHmenu())
{
SetFocus();
m_menu.DestroyMenu();
}*/


if ((hItem != NULL) && (TVHT_ONITEMICON & uFlags)&&!bHas && hItemRoot!=hItem)
{
CPoint pt=point;
ClientToScreen(&pt);


CImageList *pImg = GetImageList( TVSIL_NORMAL );
IMAGEINFO imageinfo;
int nItem,nSelItem;
GetItemImage(hItem,nItem,nSelItem);
pImg->GetImageInfo( nItem, &imageinfo );

LONG nImageW=imageinfo.rcImage.right-imageinfo.rcImage.left;
LONG nImageH=imageinfo.rcImage.bottom-imageinfo.rcImage.top;


m_nImageW=nImageW;
        m_nImageH=nImageH;


RECT r;
        GetItemRect(hItem, &r, TRUE);
m_pt.x=r.left-nImageW-4;
m_pt.y=r.top+2;
ClientToScreen(&m_pt);
if(!m_menu.GetSafeHmenu())
{
TRACE(L"menu create\n");
if (m_menu.CreatePopupMenu())
{
//
//CBitmap *bmp = CBitmap::FromHandle(imageinfo.hbmImage);
//m_menu.SetDrawBitmapHandle(imageinfo.hbmImage);
MENUINFO menuinfo;
menuinfo.cbSize = sizeof(MENUINFO); 
menuinfo.fMask =MIM_MENUDATA|MIM_BACKGROUND/*|MIM_STYLE*/; 
menuinfo.dwMenuData = reinterpret_cast<ULONG_PTR>(this); 
menuinfo.hbrBack=m_menuBackCl;
menuinfo.dwStyle=/*MNS_MODELESS*/MNS_AUTODISMISS;


m_menu.SetMenuInfo(&menuinfo);


m_nDrawItem=nItem;
m_menu.SetDrawCallBack(DrawMenuImage);


int nCX=::GetSystemMetrics(SM_CXMENUCHECK);
nImageW=nImageW*2-nCX;
nImageH=nImageH*2-5;


m_menu.SetMenuWidth(nImageW);
m_menu.SetMenuHeight(nImageH);
UINT nFlag = MF_OWNERDRAW|MFS_DISABLED;
m_menu.AppendMenu(nFlag,0,L"");
UINT index = m_menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, m_pt.x, m_pt.y,this);
if(m_menu.GetSafeHmenu())
  m_menu.DestroyMenu();
}
}

/*else
{
CPoint pt=point;
ClientToScreen(&pt);


CImageList *pImg = GetImageList( TVSIL_NORMAL );
IMAGEINFO imageinfo;
int nItem,nSelItem;
GetItemImage(hItem,nItem,nSelItem);
pImg->GetImageInfo( nItem, &imageinfo );


LONG nImageW=imageinfo.rcImage.right-imageinfo.rcImage.left;
LONG nImageH=imageinfo.rcImage.bottom-imageinfo.rcImage.top;
RECT r;
GetItemRect(hItem, &r, TRUE);
pt.x=r.left-nImageW-4;
pt.y=r.top+2;
ClientToScreen(&pt);


UINT index = m_menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD, pt.x, pt.y, this);
}*/
}


/*HTREEITEM hitem = HitTest( point, &nFlags );
if( nFlags & TVHT_ONITEMLABEL  )
{
ScreenToClient(&point);
CPoint pt=point;
ClientToScreen(&pt);




}*/

CTreeCtrl::OnMouseMove(nFlags, point);
}




void CTreeCtrlEx::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class

CTreeCtrl::PreSubclassWindow();
}


void CTreeCtrlEx::DrawMenuImage(CDC *pDC,void* pTree)
{
if(pTree==NULL)
  return ;


CImageList *pImg = ((CTreeCtrlEx*)pTree)->GetImageList( TVSIL_NORMAL);
IMAGEINFO imageinfo;
pImg->GetImageInfo( ((CTreeCtrlEx*)pTree)->m_nDrawItem, &imageinfo );


CImageList tmpList;
tmpList.Create(pImg);
tmpList.Copy(0,((CTreeCtrlEx*)pTree)->m_nDrawItem,ILCF_SWAP);
CDC dcMem; 
CBitmap destBitmap;
LONG nImageW=imageinfo.rcImage.right-imageinfo.rcImage.left;
LONG nImageH=imageinfo.rcImage.bottom-imageinfo.rcImage.top;


dcMem.CreateCompatibleDC (pDC); 
destBitmap.CreateCompatibleBitmap (pDC, nImageW, nImageH);
CBitmap* pBmpOld =dcMem.SelectObject(&destBitmap);
BOOL b=tmpList.Draw(&dcMem, 0,CPoint (0,0),ILD_NORMAL);//DrawIndirect (&dcMem, 0, CPoint (0, 0),CSize (nImageW, nImageH), CPoint (0, 0));


int nCX=::GetSystemMetrics(SM_CXMENUCHECK);
int nImageWNew=nImageW*2-nCX;
int nImageHNew=nImageH*2-5;


pDC->SetStretchBltMode(HALFTONE) ;
pDC->StretchBlt(0,0,/*nImageWNew*/nImageW*2-3,nImageHNew,&dcMem,0,0,nImageW,nImageH,SRCCOPY);
//pDC->BitBlt(0,0,nImageW,nImageH,&dcMem,0,0,SRCCOPY);


dcMem.SelectObject(pBmpOld);
destBitmap.DeleteObject();
dcMem.DeleteDC();
/*Bitmap* bp=Bitmap::FromHBITMAP(imageinfo.hbmImage,NULL);
Graphics gh(pDC->m_hDC);
gh.DrawImage(bp,0,0,bp->GetWidth(),bp->GetHeight());
delete bp;*/
}

LRESULT CTreeCtrlEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
if(message==WM_ENTERIDLE)
{
CPoint pt,pt1;
GetCursorPos(&pt);
ScreenToClient(&pt);


pt1=m_pt;
ScreenToClient(&pt1);
CRect rc;
rc.left=pt1.x;
rc.top=pt1.y;
rc.right=rc.left+m_nImageW*2+3;
rc.bottom=rc.top+m_nImageH*2;


if(!rc.PtInRect(pt))
{
if(m_menu.GetSafeHmenu())
{
SendMessage(WM_CANCELMODE);
m_menu.DestroyMenu();
}
}
}

return CTreeCtrl::WindowProc(message, wParam, lParam);
}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章