mfc添加气球式提示栏

时间:2021-10-20 03:30:49

//    TOOLTIPWND.H  添加气球式提示栏

#if !defined(AFX_TOOLTIPWND_H__2C52D3E4_2F5B_11D2_8FC9_000000000000__INCLUDED_)
#define AFX_TOOLTIPWND_H__2C52D3E4_2F5B_11D2_8FC9_000000000000__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

// ToolTipWnd.h : header file
//
// Written by Shankar (sshank@mailcity.com)
// Last Revised : August 29 1998.
// Copyright (c) 1998.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage whatsoever.
// Distribute freely.
// Send bug reports, bug fixes, enhancements. You can reach
// me at sshank@mailcity.com

// Acknowledgements:
// Thanks to Venkatesh who helped me in calculating the intersecting
// point in the ellipse.

/////////////////////////////////////////////////////////////////////////////
// CToolTipWnd window
struct BTOOLINFO {

    HWND    hwndTool;
    CString strToolText;
    COLORREF clrToolTextClr;

};

class CToolTipWnd : public CWnd
{

private:
// Construction
    LPCTSTR lpWndCls;
public:
    CToolTipWnd();
    HWND pCurrwnd;
    // Attributes
public:
    void RelayEvent(LPMSG);
    BOOL Create(CWnd*);
    bool m_bStuck;

    void AddTool(CWnd *pWnd, CString strText, COLORREF clrTextColor=NULL);
    void SetWidth(int iWidth) { m_iWidth = iWidth; }
    void SetHeight(int iHeight) { m_iHeight = iHeight; }
    void SetBkColor(COLORREF clrRef) { m_clrBkColor = clrRef; }
    void SetFrameColor(COLORREF clrRef) { m_clrFrameColor = clrRef; }
    void SetDefTextColor(COLORREF clrRef) { m_clrTextColor = clrRef; }
    void SetFontHeight(int iHeight) { m_iFontHeight = iHeight; }
    void SetFontName(CString strFontName) { m_strFontName = strFontName; }

private:
    CRgn rgn;
    CRgn rgnComb;
    CRgn rgnTri;
    CRect m_RectText;
    CFont m_fontText;
   
    CString m_strText;
    bool m_bMouseIn;
    COLORREF m_clrTextColor;
    COLORREF m_clrBkColor;
    COLORREF m_clrFrameColor;
    CMapPtrToPtr m_ToolPtr;
    int m_iWidth;
    int m_iHeight;
    int m_iFontHeight;
    CString m_strFontName;

    HWND m_hParentWnd;
public:

// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CToolTipWnd)
    protected:
    //}}AFX_VIRTUAL
   

// Implementation
public:
    virtual ~CToolTipWnd();

    // Generated message map functions
protected:
    //{{AFX_MSG(CToolTipWnd)
    afx_msg void OnPaint();
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before

the previous line.

#endif // !defined(AFX_TOOLTIPWND_H__2C52D3E4_2F5B_11D2_8FC9_000000000000__INCLUDED_)


//    TOOLTIPWND.CPP


// ToolTipWnd.cpp : implementation file
//

#include "stdafx.h"
#include "ToolTipWnd.h"

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

/////////////////////////////////////////////////////////////////////////////
// CToolTipWnd

CToolTipWnd::CToolTipWnd()
{

    lpWndCls    = AfxRegisterWndClass(0);
   
    //Defaults
    m_bMouseIn    = false;
    m_bStuck    = false;
   
    m_iWidth = 100;
    m_iHeight = 60;

    m_clrBkColor = RGB(249,254,188); //light yellow
    m_clrFrameColor = RGB(0,0,255);  //blue
    m_clrTextColor = RGB(0,0,0);     //black

    m_iFontHeight = 14;
    m_strFontName = "Arial";

    pCurrwnd = NULL;
}

CToolTipWnd::~CToolTipWnd()
{

    BTOOLINFO *stToolInfo;
    CWnd *pWnd;
    for(POSITION pos = m_ToolPtr.GetStartPosition(); pos != NULL;)
    {
        m_ToolPtr.GetNextAssoc(pos, (void *&)pWnd, (void*&) stToolInfo);
        delete stToolInfo;
    }
    m_ToolPtr.RemoveAll();

}


BEGIN_MESSAGE_MAP(CToolTipWnd, CWnd)
    //{{AFX_MSG_MAP(CToolTipWnd)
    ON_WM_PAINT()
    ON_WM_CREATE()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CToolTipWnd message handlers
BOOL CToolTipWnd::Create(CWnd* pParentWnd)
{

    BOOL bRet = CWnd::CreateEx(NULL, lpWndCls, NULL,
        WS_POPUP, 0, 0, m_iWidth, m_iHeight,
        pParentWnd->GetSafeHwnd(), NULL, NULL);

    m_hParentWnd = pParentWnd->GetSafeHwnd();
   
    if(bRet)
        SetOwner(pParentWnd);

    return bRet;

}

void CToolTipWnd::OnPaint()
{
    CPaintDC dc(this); // device context for painting
   
    CRect rectCl;
    GetClientRect(&rectCl);

    CRgn rgnComb;   
    rgnComb.CreateRectRgn(rectCl.left+10,rectCl.top,rectCl.right,rectCl.bottom);

    int iRetComb = rgnComb.CombineRgn(&rgnTri, &rgn, RGN_OR);
    if(iRetComb==ERROR)
    {
        AfxMessageBox("ERROR in Combining Region");
        return;
    }

    CBrush pBrush;
    pBrush.CreateSolidBrush(m_clrFrameColor);
   
    CBrush pBrush1;
    pBrush1.CreateSolidBrush(m_clrBkColor);
   
    dc.FillRgn( &rgnComb, &pBrush1);
    dc.FrameRgn(&rgnComb, &pBrush, 2, 1);

    dc.SetBkMode(TRANSPARENT);
    dc.SetTextColor(m_clrTextColor);
   
    CFont *pFont = dc.SelectObject(&m_fontText);
    //dc.Rectangle(&m_RectText);

    CSize czTextWidth = dc.GetTextExtent(m_strText);
   
    if( czTextWidth.cx < m_RectText.Width())
        dc.DrawText(m_strText, m_RectText, DT_CENTER | DT_VCENTER |

DT_SINGLELINE);
    else
        dc.DrawText(m_strText, m_RectText, DT_CENTER | DT_WORDBREAK);
   
   

    dc.SelectObject(pFont);
   
}


int CToolTipWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CWnd::OnCreate(lpCreateStruct) == -1)
        return -1;
   
    CRect rectCl;
    GetClientRect(&rectCl);

    int x=0, y=0;
    CRect rectTemp;

    rectTemp = rectCl;
    rectTemp.left = rectTemp.left + 10;
   
    x = (int)( (float)((float)rectTemp.Width() / 2.0) / 1.41421);
    y = (int)( (float)((float)rectTemp.Height() / 2.0) / 1.41421);

    m_RectText.top = ( (rectTemp.Height() / 2) - y);
    m_RectText.left = ( (rectTemp.Width() / 2) - x) + 10;
    m_RectText.right = ( (rectTemp.Width() / 2) + x) + 10;
    m_RectText.bottom = ( (rectTemp.Height() / 2) + y);

    rgn.m_hObject = NULL;
    rgnTri.m_hObject = NULL;
    rgnComb.m_hObject = NULL;

    BOOL bRegRet = rgn.CreateEllipticRgn

(rectCl.left+10,rectCl.top,rectCl.right,rectCl.bottom);
       
    CPoint ptTri[3];
    ptTri[0].x = rectCl.left;
    ptTri[0].y = (rectCl.bottom / 2) - 10;

    ptTri[1].x = rectCl.left + 15;
    ptTri[1].y = (rectCl.bottom / 2) - 5;

    ptTri[2].x = rectCl.left + 15;
    ptTri[2].y = (rectCl.bottom / 2) + 5;
   
    ptTri[3].x = rectCl.left;
    ptTri[3].y = (rectCl.bottom / 2) - 10;

    BOOL bRegTriRet = rgnTri.CreatePolygonRgn(ptTri, 3, ALTERNATE);

    rgnComb.CreateRectRgn(rectCl.left+10,rectCl.top,rectCl.right,rectCl.bottom);
    int iRetComb = rgnComb.CombineRgn(&rgnTri, &rgn, RGN_OR);

    if(iRetComb == ERROR)
    {
        AfxMessageBox("ERROR in Combining Region");
        return -1;
    }

    int bRgnWnd = SetWindowRgn(rgnComb.operator HRGN( ), TRUE);   

    m_fontText.CreateFont(m_iFontHeight, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

0,m_strFontName);   
   
    return 0;
}

void CToolTipWnd::RelayEvent(LPMSG lpMsg)
{

    switch(lpMsg->message)
    {
    case WM_KEYDOWN:
            if(IsWindowVisible())
            {       
                ShowWindow(SW_HIDE);
            }
            break;

    case WM_LBUTTONDOWN:
    case WM_RBUTTONDOWN:
            if(IsWindowVisible())
            {
                ShowWindow(SW_HIDE);
            }
            break;

    case WM_MOUSEMOVE:
        {
            CWnd *pFocusWnd = AfxGetApp()->m_pMainWnd->GetFocus();
            if(pFocusWnd==NULL)
                break;
            CWnd* pWnd = CWnd::FromHandle(lpMsg->hwnd);

            HWND hWndTemp = ::GetParent(lpMsg->hwnd);
           
            CPoint pt;
            pt.x = lpMsg->pt.x;
            pt.y = lpMsg->pt.y;
           
            BTOOLINFO *stToolInfo;
            CWnd *pBToolWnd;
           
            for(POSITION pos = m_ToolPtr.GetStartPosition(); pos != NULL;)
            {
                m_ToolPtr.GetNextAssoc(pos, (void *&)pBToolWnd,

(void*&) stToolInfo);
               
                if(!m_bMouseIn)
                {
                    if(lpMsg->hwnd == stToolInfo->hwndTool)
                    {
                   
                        if(m_bStuck && IsWindowVisible())
                        {
                            SetWindowPos

(&wndTop,pt.x,pt.y,m_iWidth,m_iHeight,SWP_NOACTIVATE);
                            ShowWindow(SW_SHOWNOACTIVATE);
                        }

                        m_bMouseIn = true;
                        m_clrTextColor = stToolInfo-

>clrToolTextClr;
                        m_strText = stToolInfo->strToolText;
                       
                        SetWindowPos

(&wndTop,pt.x,pt.y,m_iWidth,m_iHeight,SWP_NOACTIVATE);
                        ShowWindow(SW_SHOWNOACTIVATE);
                       
                        pCurrwnd = stToolInfo->hwndTool;

                        break;
                    }
                }
                else
                {
                    CRect rect;
                    ::GetWindowRect(pCurrwnd, &rect);
                    if(m_bStuck && IsWindowVisible())
                    {
                        SetWindowPos

(&wndTop,pt.x,pt.y,m_iWidth,m_iHeight,SWP_NOACTIVATE);
                        ShowWindow(SW_SHOWNOACTIVATE);
                    }
                   
                   
                    CWnd* pWnd = CWnd::FromHandle(lpMsg->hwnd);
                    CWnd *WndPt = pWnd->WindowFromPoint(lpMsg-

>pt);
                    if(WndPt->GetSafeHwnd() != pCurrwnd)
                    {
                        m_bMouseIn = false;
                        ShowWindow(SW_HIDE);
                    }
                   

                    break;
                }
            }
           
        }   
        break; //WM_MOUSEMOVE
    }
    
}

void CToolTipWnd::AddTool(CWnd *pWnd, CString strText, COLORREF clrTextColor)
{

    BTOOLINFO *stToolInfo;

    if(!m_ToolPtr.Lookup( pWnd, ( void*& )  stToolInfo))
    {
        stToolInfo = new BTOOLINFO;
        stToolInfo->hwndTool = pWnd->GetSafeHwnd();
        stToolInfo->strToolText = strText;
        if(clrTextColor==NULL)
            stToolInfo->clrToolTextClr = m_clrTextColor;
        else
            stToolInfo->clrToolTextClr = clrTextColor;
   
        m_ToolPtr.SetAt(pWnd, stToolInfo);
    }

}

//使用方法
、Dlg类中添加变量
public:
CToolTipWnd m_BalloonToolTip;
//Dlg::OnInitDialg()添加初始化代码
、添加气球式提示栏
m_BalloonToolTip.Create(this);
m_BalloonToolTip.AddTool(GetDlgItem(IDC_ENABLE_BTN),"禁止/允许面板走纸按键", RGB

(255,0,0));

3、 Dlg::PreTranslateMessage(MSG* pMsg) 添加代码
 if(m_BalloonToolTip)
    m_BalloonToolTip.RelayEvent(pMsg);
  return CDialog::PreTranslateMessage(pMsg);


二 添加按钮 IDC_ENABLE_BTN
1,rc文件中BEGIN END之间添加
PUSHBUTTON      "禁止按键",IDC_ENABLE_BTN,119,83,46,16,BS_FLAT
2,Dlg::DoDataExchange(CDataExchange* pDX)添加
DDX_Control(pDX, IDC_ENABLE_BTN, m_btnEnable);
3,BEGIN_MESSAGE_MAP(*Dlg, CDialog)中添加点击消息
    ON_BN_CLICKED(IDC_ENABLE_BTN, OnEnableBtn)
   Dlg::OnEnableBtn() {}

4,设置按钮内容
SetDlgItemText(IDC_ENABLE_BTN,"允许按键");
Resource.h添加
#define IDC_ENABLE_BTN                  1007

三 CListBox添加
Dlg类的AFX_DATA中添加
CListBox    m_ctlList;
Dlg::DoDataExchange(CDataExchange* pDX)的//{{AFX_DATA_MAP()中添加
    DDX_Control(pDX, IDC_LIST_ANY, m_ctlList);
使用
 m_ctlList.InsertString(-1,"连接打印机失败...");
rc文件添加listbox
  LISTBOX         IDC_LIST_ANY,13,54,91,152,LBS_SORT |
                    LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
Resource.h文件中添加
    #define IDC_LIST_ANY                    1004
四,显示和隐藏右边界面
添加按钮
 #define IDC_SETDIP_BTN                  1010
 PUSHBUTTON      "设置DIP",IDC_SETDIP_BTN,188,141,46,16,BS_FLAT
dlg类中定义并AFX_DATA_MAP中 绑定变量
    CButton    m_btnSetdip;
DDX_Control(pDX, IDC_SETDIP_BTN, m_btnSetdip);
BEGIN_MESSAGE_MAP 添加点击消息
ON_BN_CLICKED(IDC_SETDIP_BTN, OnSetdipBtn)
添加消息OnSetdipBtn
    static BOOL bExpand = TRUE;
    ExpandDialog(IDC_DIVIDER, bExpand);
    bExpand = !bExpand;   
Dlg::ExpandDialog(int nResourceID, BOOL bExpand)
{
    static CRect rcLarge;
    static CRect rcSmall;
    CString sExpand;

    if(rcLarge.IsRectNull())
    {
       CRect rcLandmark;
       CWnd* pWndLandmark = GetDlgItem(nResourceID);
       ASSERT(pWndLandmark);
       GetWindowRect(rcLarge);
       pWndLandmark->GetWindowRect(rcLandmark);
       rcSmall = rcLarge;
       rcSmall.right = rcLandmark.left;
    }
    if(bExpand)
    {
         SetWindowPos(NULL, 0, 0, rcLarge.Width(), rcLarge.Height(),
         SWP_NOMOVE | SWP_NOZORDER);
         sExpand = "设置DIP<<";
    }
    else
    {
        SetWindowPos(NULL, 0, 0, rcSmall.Width(), rcSmall.Height(),
        SWP_NOMOVE | SWP_NOZORDER);
        sExpand = "设置DIP>>";
    }
    SetDlgItemText(IDC_SETDIP_BTN, sExpand);
}
rc中picture Properties IDC_DIVIDER 添加
  CONTROL         "",IDC_DIVIDER,"Static",SS_BLACKFRAME,257,7,170,205
#define IDC_DIVIDER                     1034
使用 ExpandDialog(IDC_DIVIDER, bExpand);

五 添加COMBOBOX
1, rc文件中添加 COMBOBOX        IDC_COMBO_PORT,44,17,44,58,CBS_DROPDOWNLIST |
                    CBS_UPPERCASE | WS_VSCROLL | WS_TABSTOP,
                    WS_EX_DLGMODALFRAME
    #define IDC_COMBO_PORT                  1000
添加 列表
//
// Dialog Info
//

IDD_POS2000DEMO_DIALOG DLGINIT
BEGIN
    IDC_COMBO_PORT, 0x403, 5, 0
0x4f43, 0x314d, "\000"
    IDC_COMBO_PORT, 0x403, 5, 0
0x4f43, 0x324d, "\000"
    IDC_COMBO_PORT, 0x403, 5, 0
0x4f43, 0x334d, "\000"
    IDC_COMBO_PORT, 0x403, 5, 0
0x544c, 0x3150, "\000"
    IDC_COMBO_PORT, 0x403, 5, 0
0x544c, 0x3250, "\000"
    IDC_COMBO_BAUD, 0x403, 5, 0
0x3639, 0x3030, "\000"
    IDC_COMBO_BAUD, 0x403, 6, 0
0x3931, 0x3032, 0x0030,
    IDC_COMBO_BAUD, 0x403, 6, 0
0x3833, 0x3034, 0x0030,
END
Dlg::DoDataExchange(CDataExchange* pDX) 绑定变量
DDX_CBIndex(pDX, IDC_COMBO_PORT, m_Port);
消息函数BEGIN_MESSAGE_MAP(
ON_CBN_SELCHANGE(IDC_COMBO_PORT, OnSelchangeComboPort)

5使其无效GetDlgItem(IDC_COMBO_BAUD)->EnableWindow(false);