WIN32SDK自绘Tooltip

来源:互联网 发布:印度软件外包公司 编辑:程序博客网 时间:2024/06/13 07:23

WIN32SDK自绘Tooltip


支持文字和图片穿插,可设置位,置字体颜色,字体,背景色


效果图:


用法你懂的。

看源码吧,注释里写的很清楚:

函数Polygon(...)使用参数轮廓点示意图

******************************************************************************************

tipinfo.class.h文件

******************************************************************************************

//////////////////////////////////////////////////////////////////////////////////// 信息提示类--cTooltip//////////////////////////////////////////////////////////////////////////////////#pragma once#include "stdafx.h"#include "main.h"// 提示信息数据类型#define TIPINFO_DATATYPE_TXT0#define TIPINFO_DATATYPE_BMP1/** 数据原型*/class INFODATA{public:INFODATA(unsigned dataid) :m_dataid(dataid) {}virtual int getid() = 0;// 友元声明friend bool operator == (const INFODATA&, const INFODATA&);friend bool operator != (const INFODATA&, const INFODATA&);protected:// 数据类型// 0: bmp// 1: txtunsigned m_dataid;};/** INFODATA 的 == 重载*/inline bool operator == (const INFODATA &a, const INFODATA &b) { return a.m_dataid == b.m_dataid; }/** INFODATA 的 != 重载*/inline bool operator != (const INFODATA &a, const INFODATA &b){ return a.m_dataid != b.m_dataid; }/** 图像提示信息*/class INFOBMP :public INFODATA {public:struct BMPDATA{HBITMAP bmp;int destw, desth;int srcw, srch;};public:/** @bmp: 位图句柄* @destw: 希望图像显示的宽度* @desth: 希望图像显示的高度* @srcw: 原始宽度* @srch: 原始高度* 注意:如果 w 或 h 一者为0将显示为一个字体方块哦尺寸(和一个汉字一样大小)*/INFOBMP(HBITMAP bmp, int destw = 0, int desth = 0, int srcw = 0, int srch = 0):INFODATA(TIPINFO_DATATYPE_BMP), m_bmp(BMPDATA{ bmp, destw, desth , srcw, srch}){}public:int getid() { return m_dataid; }// 返回数据类型BMPDATA getbmp() { return m_bmp; }// 返回数据BMPDATA m_bmp;// 图像数据};/** 文本提示信息*/class INFOTXT :public INFODATA {public:INFOTXT(char* txt):INFODATA(TIPINFO_DATATYPE_TXT), m_txt(txt){m_size = strlen(txt);}public:int getid() { return m_dataid; }// 返回数据类型char* m_txt;// 文本数据int m_size;};/** 提示信息* vector<INFODATA*>的数组* 为了断行方便每行数据(图片,文本)放到同一个数组vector<INFODATA*>之中*/struct TIPINFO{public:vector<vector<INFODATA*>> m_infos;};

******************************************************************************************
tooltip.class.cpp文件

******************************************************************************************

//////////////////////////////////////////////////////////////////////////////////// 信息数据类--cTooltip//////////////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "main.h"#include "tipinfo.class.h"


******************************************************************************************
tooltip.class.h文件

******************************************************************************************

//////////////////////////////////////////////////////////////////////////////////// 信息提示类--cTooltip// // <cTooltip class>// 提示信息类,通过气泡形状圆角窗口显示包括文本和图片的提示信息// // <总览>// 方法:bool lock() 锁定提示信息(只有提示信息锁定之后下列所有函数的操作才会有效)// 当前类调用 lock 会将会将上一个调用过lock函数的提示信息类改变为未锁定状态,// 即:同一时刻只能有一个提示信息类处于锁定状态// 方法:bool unlock() 解锁提示信息// 方法:bool settipinfo(TIPINFO tipinfo) 设置提示信息的内容// 方法:bool setshowposition(unsigned sp) 设置提示信息窗口相对于"父窗口(注释1)"的// 相对位置,避免遮挡或提示信息窗口显示在桌面以外的位置。// 方法:bool setshowposition(POINT ltanchor)  指定锚点坐标// 方法:bool showtip(HWND hparent, bool isshow) 显示或者隐藏提示信息窗口// 方法:bool setbkcolor(COLORREF color) 设置背景颜色,默认为RGB(45. 45, 45)// 方法:bool settxtcolor(COLORREF color) 设置字体颜色,默认为RGB(150, 150, 150)// 方法:bool setoutlinecolor(COLORREF color) 设置轮廓颜色// 方法:bool setfont(HFONT font) 设置字体,默认使用CreateFont(12, 6, 0, 0, 500, // 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, "新宋体")参数//// 效果示例://////////////////////////////////////////////////////////////////////////////////#pragma once#include "stdafx.h"#include "main.h"#include "tipinfo.class.h"#pragma region 自定义消息// 锁定提示信息// @wparam: cTooltip指针#define WMAPP_TT_LOCK(WM_APP + 2)// 解锁#define WMAPP_TT_UUNLOCK(WM_APP + 3)// 显示隐藏 tooltip 消息#define WMAPP_TT_SHOW(WM_APP + 4)#define WMAPP_TT_HIDE(WM_APP + 5)#pragma endregion 自定义消息// 显示位置宏#define SP_LEFT0// 左#define SP_RIGHT1// 右#define SP_TOP2// 上#define SP_BOTTOM3// 下/** 信息提示类*/class cTooltip{public:cTooltip(TIPINFO tipinfo, HWND hparent);~cTooltip() { this->__release(); }public:bool lock();// 锁定提示信息bool unlock();// 解锁提示信息bool settipinfo(TIPINFO tipinfo);// 设置提示信息bool setshowposition(unsigned sp);// 设置显示位置(相对于父窗口来说)bool setshowposition(POINT ltanchor);// 指定锚点坐标bool showtip(HWND hparent, bool isshow);// 显示或隐藏提示信息bool setbkcolor(COLORREF color);// 设置背景色bool settxtcolor(COLORREF color);// 设置字体颜色bool setoutlinecolor(COLORREF color);// 设置轮廓颜色bool setfont(HFONT font);// 设置字体private:void __release();void __cookedtipinfo();void __calwndrec();protected:// 提示数据vector<vector<INFODATA*>> m_infos;vector<vector<RECT>> m_infosarea;protected:// 窗体数据static unsigned count;// 计数器HWND m_wnd;// 窗口句柄bool m_locked;// 是否已锁定bool m_visible;// 是否可见HWND m_parent;// 父窗口COLORREF m_txtcolor;// 字体颜色COLORREF m_transparentcolor;// 透明色 HBRUSH m_brushtransparent;//  HFONT m_font;// 字体protected:// 轮廓数据HPEN m_outlinepen;// 轮廓颜色HBRUSH m_bkbrush;// 背景颜色POINT m_outline[11];// 轮廓, 颜色protected:RECT wndarea;// 信息提示窗口在屏幕上的位置RECT infoarea;// 提示信息在信息提示窗口中显示的位置protected:POINT m_anchor;// 锚点坐标(尖角指示器顶点在屏幕上的位置)int m_showposition;// 提示信息相对于m_parent(父窗口)或者m_anchor(锚点坐标)的显示位置public:WNDPROC oldttproc;static LRESULT CALLBACK ttproc(HWND, UINT, WPARAM, LPARAM);};

******************************************************************************************
tooltip.class.cpp文件

******************************************************************************************

//////////////////////////////////////////////////////////////////////////////////// 信息提示类--cTooltip//////////////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "main.h"#include "tooltip.class.h"#define INDICATOR_H4// 指示器高度#define INDICATOR_W4// 指示器宽度#define RADIUS3// 圆角半径unsigned cTooltip::count = 0;/** cTooltip 构造*/cTooltip::cTooltip(TIPINFO tipinfo, HWND hparent){// 初始化成员m_visible = false;m_infos = tipinfo.m_infos;m_txtcolor = RGB(150, 150, 150);m_outlinepen = CreatePen(PS_SOLID, 1, RGB(0, 102, 204));m_bkbrush = CreateSolidBrush(RGB(45, 45, 45));m_transparentcolor = RGB(255, 255, 255);m_brushtransparent = CreateSolidBrush(m_transparentcolor);m_font = CreateFont(12, 6, 0, 0, 500, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, "新宋体");m_wnd = 0;m_parent = hparent;oldttproc = nullptr;// 提示信息窗口默认位置:不指定左上角屏幕坐标,位于父窗口(m_parent)下方// 技巧提示:如果提示信息是关于按钮的,通常不需要指定窗口(m_wnd)左上角坐标,// 如果提示信息是关于比如文本编辑界面中的某行文本,通常应将// 窗口左上角坐标(m_ltanchor)设置为包含文本矩形的左下角坐标,相// 对位置(m_showposition)设置为SP_BOTTOM 可以达到较合理布局效果m_anchor = { LONG_MAX, LONG_MAX };m_showposition = SP_BOTTOM;/** 解析tipinfo数据*/ __cookedtipinfo();string classname = "No.";char cchar[32]; memset(cchar, 0, 32);_itoa_s(count, cchar, 10);classname += cchar; classname += "_tooltip";// 创建窗口m_wnd = CreateWindow("MDICLIENT", classname.c_str(),   WS_POPUP | WS_CLIPSIBLINGS,   0, 0, 0, 0,    appWnd, 0, appInst, 0 );if (m_wnd){SetWindowPos(m_wnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);SetWindowLong(m_wnd, GWL_EXSTYLE, GetWindowLong(m_wnd, GWL_EXSTYLE) | WS_EX_LAYERED);oldttproc = (WNDPROC)SetWindowLong(m_wnd, GWL_WNDPROC, (LONG)ttproc);SetLayeredWindowAttributes(m_wnd, m_transparentcolor, 0, LWA_COLORKEY);}}/** 锁定提示信息*/bool cTooltip::lock(){if (m_wnd)return (bool)SendMessage(m_wnd, WMAPP_TT_LOCK, (LONG)this, 0);elsereturn false;}/** 锁定提示信息*/bool cTooltip::lock(){    if (m_wnd)    {        SetWindowLong(m_wnd, GWL_WNDPROC, (LONG)ttproc);        return (bool)SendMessage(m_wnd, WMAPP_TT_LOCK, (LONG)this, 0);    } else{        return false;    }}/** 设置提示信息的内容*/bool cTooltip::settipinfo(TIPINFO tipinfo){if (!m_locked) return false;if (m_wnd){m_infos = tipinfo.m_infos;// 解析提示信息数据__cookedtipinfo();// 初始化wndarea__calwndrec();// 重置缓冲区和窗口位置SendMessage(m_wnd, WM_SIZE, 0, 0);if (m_visible)PostMessage(m_wnd, WM_PAINT, 0, 0);return true;} else{return false;}}/** 设置显示位置(相对于父窗口来说)* @sp: 相对于父窗口的位置参数,上下左右*/bool cTooltip::setshowposition(unsigned sp){if (!m_locked) return false;if (m_wnd && sp >= 0 && sp <= 3){m_showposition = sp;// 重新获取提示信息位置__cookedtipinfo();// 计算wndarea__calwndrec();// 重置缓冲区和窗口位置SendMessage(m_wnd, WM_SIZE, 0, 0);if (m_visible)PostMessage(m_wnd, WM_PAINT, 0, 0);return true;} else{return false;}}/** 指定锚点坐标*/bool cTooltip::setshowposition(POINT anchor){if (!m_locked) return false;if (m_wnd){m_anchor = anchor;// 计算wndarea__calwndrec();// 重置缓冲区和窗口位置SendMessage(m_wnd, WM_SIZE, 0, 0);if (m_visible)PostMessage(m_wnd, WM_PAINT, 0, 0);return true;} else{return false;}}/** 显示或隐藏提示信息* @hparent: 父窗口句柄* @isshow: true显示窗口,hparent为父窗口句柄;false隐藏窗口,hparent为0*/bool cTooltip::showtip(HWND hparent, bool ishow){if (!m_locked) return false;if (m_wnd){/** 如果窗口有效*/if (ishow){/** 显示窗口的命令*/m_parent = hparent;// 计算wndarea(信息提示窗口位置)__calwndrec();// 发送 WMAPP_TT_HIDE 隐藏上一个提示信息窗口// 通常窗口的隐藏是由用户通过 showtip(0, false) 来实现的,为了保险// 再发送一次.因为一次只能显示一条提示信息SendMessage(m_wnd, WMAPP_TT_HIDE, 0, 0);m_visible = true;//SetWindowPos(m_wnd, HWND_TOPMOST,wndarea.left, wndarea.top, wndarea.right, wndarea.bottom, 0);// 重置缓冲区和窗口位置SendMessage(m_wnd, WM_SIZE, 0, 0);// 显示当前提示信息窗口SendMessage(m_wnd, WMAPP_TT_SHOW, 0, 0);} else{/** 隐藏窗口的命令*/// 隐藏窗口SendMessage(m_wnd, WMAPP_TT_HIDE, 0, 0);m_visible = false;}return true;} else{/** 无效的窗口*/return false;}}/** 设置背景色*/bool cTooltip::setbkcolor(COLORREF color){if (!m_locked) return false;if (m_wnd){if (m_bkbrush) DeleteObject(m_bkbrush);m_bkbrush = CreateSolidBrush(color);if (m_visible)PostMessage(m_wnd, WM_PAINT, 0, 0);return true;} else{return false;}}/** 设置字体颜色*/bool cTooltip::settxtcolor(COLORREF color){if (!m_locked) return false;if (m_wnd){m_txtcolor = color;if (m_visible)PostMessage(m_wnd, WM_PAINT, 0, 0);return true;} else{return false;}}/** 设置轮廓颜色*/bool cTooltip::setoutlinecolor(COLORREF color){if (!m_locked) return false;if (m_wnd){if (m_outlinepen) DeleteObject(m_outlinepen);m_outlinepen = CreatePen(PS_SOLID, 1, color);if (m_visible)PostMessage(m_wnd, WM_PAINT, 0, 0);return true;} else{return false;}}/** 设置字体*/bool cTooltip::setfont(HFONT font){if (!m_locked) return false;if (m_wnd){m_font = font;// 重新解析tooltip__cookedtipinfo();// 计算wndarea__calwndrec();// 重置缓冲区和窗口位置SendMessage(m_wnd, WM_SIZE, 0, 0);if (m_visible)PostMessage(m_wnd, WM_PAINT, 0, 0);return true;} else{return false;}}/** 释放资源*/void cTooltip::__release(){m_infos.clear();for (unsigned row = 0; row < m_infos.size(); ++row){for (unsigned col = 0; col < m_infos.size(); ++col){switch (m_infos[row][col]->getid()){case TIPINFO_DATATYPE_TXT:delete (INFOTXT*)m_infos[row][col];m_infos[row][col] = 0;break;case TIPINFO_DATATYPE_BMP:delete (INFOBMP*)m_infos[row][col];m_infos[row][col] = 0;break;}}m_infos[row].clear();}m_infos.clear();if (m_wnd){ DestroyWindow(m_wnd); m_wnd = 0; }m_parent = 0;if (m_bkbrush){ DeleteObject(m_bkbrush); m_bkbrush = 0; }if (m_outlinepen){ DeleteObject(m_outlinepen); m_outlinepen = 0; }if (m_font){ DeleteObject(m_font); m_font = 0; }if (m_brushtransparent){ DeleteObject(m_brushtransparent); m_brushtransparent = 0; }oldttproc = nullptr;--count;}/** 解析提示信息数据* 通过解析 m_infos 初始化m_infossize,m_outline,infoarea* 请在__calwndrec之前调用*/void cTooltip::__cookedtipinfo(){m_infosarea.clear();infoarea = { 0, 0, 0, 0 };// 取得字体信息TEXTMETRIC tm;HDC hdc = GetDC(m_wnd);HFONT oldfont = (HFONT)SelectObject(hdc, m_font);GetTextMetrics(hdc, &tm);SelectObject(hdc, oldfont);// 初始化 m_infossizeSIZE nakedinfoarea = { 0, 0 };for (unsigned rowindex = 0; rowindex < m_infos.size(); ++rowindex){m_infosarea.push_back(vector<RECT>());int rowlen = 0;// 当前行总宽度int rowh = tm.tmHeight;// 当前行高度// 解析第row行提示信息for (unsigned ite = 0; ite < m_infos[rowindex].size(); ++ite){m_infosarea[rowindex].push_back(RECT());RECT &recitem = m_infosarea[rowindex][ite];if (m_infos[rowindex][ite]->getid() == TIPINFO_DATATYPE_TXT){/** 文本数据*/recitem.left = rowlen;recitem.right = ((INFOTXT*)m_infos[rowindex][ite])->m_size * tm.tmAveCharWidth;if (0 == rowindex)recitem.top = 0;elserecitem.top = m_infosarea[rowindex - 1][ite].top + m_infosarea[rowindex - 1][ite].bottom;recitem.bottom = tm.tmHeight;// 增加当前行宽度rowlen += recitem.right;} else if (m_infos[rowindex][ite]->getid() == TIPINFO_DATATYPE_BMP){/** 图像数据*/INFOBMP *bmp = ((INFOBMP*)m_infos[rowindex][ite]);if (bmp->m_bmp.desth == 0 || bmp->m_bmp.destw == 0){/** 如果图片高度为默认,则大小设置为一个方块字大小*/bmp->m_bmp.desth = tm.tmHeight;bmp->m_bmp.destw = tm.tmHeight;} else{if (bmp->m_bmp.desth > rowh)rowh = bmp->m_bmp.desth;}recitem.left = rowlen;recitem.right = bmp->m_bmp.destw;if (0 == rowindex)recitem.top = 0;elserecitem.top = m_infosarea[rowindex - 1][ite].top + m_infosarea[rowindex - 1][ite].bottom;recitem.bottom = bmp->m_bmp.desth;rowlen += ((INFOBMP*)m_infos[rowindex][ite])->m_bmp.destw;}}ReleaseDC(m_wnd, hdc);// 对齐文本和图片for (unsigned ite = 0; ite < m_infos[rowindex].size(); ++ite){m_infosarea[rowindex][ite].top += rowh - m_infosarea[rowindex][ite].bottom;}if (rowlen > nakedinfoarea.cx)nakedinfoarea.cx = rowlen;nakedinfoarea.cy += rowh;}// 计算infoarea(提示信息在信息提示窗口中显示的位置)switch (m_showposition){case SP_LEFT:#pragma region// 左上角m_outline[0] = { RADIUS, 0 };m_outline[1] = { m_outline[0].x - RADIUS, m_outline[0].y + RADIUS };// 左下角m_outline[2] = { m_outline[1].x, m_outline[1].y + nakedinfoarea.cy };m_outline[3] = { m_outline[2].x + RADIUS, m_outline[2].y + RADIUS };// 右下角m_outline[4] = { m_outline[3].x + nakedinfoarea.cx, m_outline[3].y };m_outline[5] = { m_outline[4].x + RADIUS, m_outline[4].y - RADIUS };// 右上角m_outline[9] = { m_outline[5].x, m_outline[1].y };m_outline[10] = { m_outline[4].x, m_outline[0].y };// 指示器m_outline[8] = { m_outline[9].x, m_outline[9].y + 2 };m_outline[7] = { m_outline[8].x + INDICATOR_H, m_outline[8].y };m_outline[6] = { m_outline[5].x, m_outline[8].y + INDICATOR_W };// 初始化infoareainfoarea = { RADIUS, RADIUS, nakedinfoarea.cx, nakedinfoarea.cy };break;#pragma endregioncase SP_BOTTOM:#pragma region// 左上角m_outline[0] = { RADIUS, INDICATOR_H };m_outline[1] = { m_outline[0].x - RADIUS, m_outline[0].y + RADIUS };// 左下角m_outline[2] = { m_outline[1].x, m_outline[1].y + nakedinfoarea.cy };m_outline[3] = { m_outline[2].x + RADIUS, m_outline[2].y + RADIUS };// 右下角m_outline[4] = { m_outline[3].x + nakedinfoarea.cx, m_outline[3].y };m_outline[5] = { m_outline[4].x + RADIUS, m_outline[2].y };// 计算右上角m_outline[6] = { m_outline[5].x, m_outline[1].y };m_outline[7] = { m_outline[4].x, m_outline[0].y };// 计算指示器m_outline[10] = { m_outline[0].x + 5, m_outline[0].y };m_outline[9] = { m_outline[10].x, 0 };m_outline[8] = { m_outline[9].x + INDICATOR_W, m_outline[0].y };// 初始化infoareainfoarea = { RADIUS, INDICATOR_H + RADIUS, nakedinfoarea.cx, nakedinfoarea.cy };break;#pragma endregioncase SP_RIGHT:#pragma region // 左上角m_outline[0] = { INDICATOR_H + RADIUS, 0 };m_outline[1] = { m_outline[0].x - RADIUS, m_outline[0].y + RADIUS };// 指示器m_outline[2] = { m_outline[1].x, m_outline[1].y + 2 };m_outline[3] = { 0, m_outline[2].y };m_outline[4] = { m_outline[2].x, m_outline[3].y + INDICATOR_W };// 左下角m_outline[5] = { m_outline[4].x, m_outline[1].y + nakedinfoarea.cy };m_outline[6] = { m_outline[5].x + RADIUS, m_outline[5].y + RADIUS };// 右下角m_outline[7] = { m_outline[6].x + nakedinfoarea.cx, m_outline[6].y };m_outline[8] = { m_outline[7].x + RADIUS, m_outline[5].y };// 右上角m_outline[9] = { m_outline[8].x, m_outline[1].y };m_outline[10] = { m_outline[7].x, m_outline[0].y };// 初始化infoareainfoarea = { INDICATOR_H + RADIUS, RADIUS, nakedinfoarea.cx, nakedinfoarea.cy };break;#pragma endregioncase SP_TOP:#pragma region// 左上角m_outline[0] = { RADIUS, 0 };m_outline[1] = { 0, m_outline[0].y + RADIUS };// 左下角m_outline[2] = { m_outline[1].x, m_outline[1].y + nakedinfoarea.cy };m_outline[3] = { m_outline[2].x + RADIUS, m_outline[2].y + RADIUS };// 指示器m_outline[4] = { m_outline[3].x + 5, m_outline[3].y };m_outline[5] = { m_outline[4].x, m_outline[4].y + INDICATOR_H };m_outline[6] = { m_outline[5].x + INDICATOR_W, m_outline[4].y };// 右下角m_outline[7] = { m_outline[3].x + nakedinfoarea.cx, m_outline[6].y };m_outline[8] = { m_outline[7].x + RADIUS, m_outline[2].y };// 右上角m_outline[9] = { m_outline[8].x, m_outline[1].y };m_outline[10] = { m_outline[7].x, m_outline[0].y };// 初始化infoareainfoarea = { RADIUS, RADIUS, nakedinfoarea.cx, nakedinfoarea.cy };break;#pragma endregion}}/** 计算wndarea* 请在__cookedtipinfo之后调用*/void cTooltip::__calwndrec(){// 计算wndarea(信息提示窗口位置)if (m_anchor.x != LONG_MAX && m_anchor.y != LONG_MAX){#pragma region 使用锚点坐标和相对位置参数来确定提示信息窗口的位置switch (m_showposition){case SP_LEFT:// 提示信息窗口位于锚点左侧wndarea.left = m_anchor.x - m_outline[7].x;wndarea.top = m_anchor.y - m_outline[7].y;wndarea.right = RADIUS * 2 + infoarea.right + INDICATOR_H + 5;wndarea.bottom = RADIUS * 2 + infoarea.bottom + 5;break;case SP_RIGHT:// 提示信息窗口位于锚点右侧wndarea.left = m_anchor.x - m_outline[3].x;wndarea.top = m_anchor.y - m_outline[3].y;wndarea.right = RADIUS * 2 + infoarea.right + INDICATOR_H + 5;wndarea.bottom = RADIUS * 2 + infoarea.bottom + 5;break;case SP_BOTTOM:// 提示信息窗口位于锚点底部wndarea.left = m_anchor.x - m_outline[9].x;wndarea.top = m_anchor.y - m_outline[9].y;wndarea.right = RADIUS * 2 + infoarea.right + 5;wndarea.bottom = RADIUS * 2 + infoarea.bottom + INDICATOR_H + 5;break;case SP_TOP:// 提示信息窗口位于锚点上边wndarea.left = m_anchor.x - m_outline[5].x;wndarea.top = m_anchor.y - m_outline[5].y;wndarea.right = RADIUS * 2 + infoarea.right + 5;wndarea.bottom = RADIUS * 2 + infoarea.bottom + INDICATOR_H + 5;break;}#pragma endregion} else{#pragma region 根据父窗口和相对位置参数来确定信息提示窗口的位置RECT parentrec;POINT virtualanchor;GetWindowRect(m_parent, &parentrec);switch (m_showposition){case SP_LEFT:virtualanchor = { parentrec.left, (parentrec.bottom + parentrec.top) / 2 };wndarea.left = virtualanchor.x - m_outline[7].x;wndarea.top = virtualanchor.y - m_outline[7].y;wndarea.right = RADIUS * 2 + infoarea.right + INDICATOR_H + 5;wndarea.bottom = RADIUS * 2 + infoarea.bottom + 5;break;case SP_RIGHT:virtualanchor = { parentrec.right, (parentrec.bottom + parentrec.top) / 2 };wndarea.left = virtualanchor.x - m_outline[3].x;wndarea.top = virtualanchor.y - m_outline[3].y;wndarea.right = RADIUS * 2 + infoarea.right + INDICATOR_H + 5;wndarea.bottom = RADIUS * 2 + infoarea.bottom + 5;break;case SP_BOTTOM:virtualanchor = { (parentrec.left + parentrec.right) / 2, parentrec.bottom };wndarea.left = virtualanchor.x - m_outline[9].x;wndarea.top = virtualanchor.y - m_outline[9].y;wndarea.right = RADIUS * 2 + infoarea.right + 5;wndarea.bottom = RADIUS * 2 + infoarea.bottom + INDICATOR_H + 5;break;case SP_TOP:virtualanchor = { (parentrec.left + parentrec.right) / 2, parentrec.top };wndarea.left = virtualanchor.x - m_outline[5].x;wndarea.top = virtualanchor.y - m_outline[5].y;wndarea.right = RADIUS * 2 + infoarea.right + 5;wndarea.bottom = RADIUS * 2 + infoarea.bottom + INDICATOR_H + 5;break;}#pragma endregion}}


******************************************************************************************
tooltipMessageProc.cpp文件

******************************************************************************************

//////////////////////////////////////////////////////////////////////////////////// 信息提示类消息处理//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////// 信息提示类消息处理//////////////////////////////////////////////////////////////////////////////////#include "stdafx.h"#include "main.h"#include "tooltip.class.h"/** tooltip 消息处理*/LRESULT CALLBACK cTooltip::ttproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam){#pragma regionHDC hdc;RECT rec;PAINTSTRUCT ps;HBITMAP oldbmp = 0;// 提示信息类数据static bool islocked = false;//  是否已锁定static cTooltip *ptt = nullptr;//  当前显示的提示信息类// 缓冲区static bool isbufferinited = false;static HDC bufferdc = 0;static HBITMAP bufferbmp = 0;HDC naughtybuffer = 0;#pragma endregionif (!islocked){/** 锁定提示信息,初始化ptt*/switch (message){case WMAPP_TT_LOCK:// 锁定信息#pragma regionif (wparam != 0 && ((cTooltip*)wparam)->m_wnd != 0){islocked = true;// 初始化pttptt = (cTooltip*)wparam;ptt->m_locked = true;return true;} else{return false;}#pragma endregioncase WM_PAINT:#pragma regionBeginPaint(hwnd, &ps);EndPaint(hwnd, &ps);break;#pragma endregion}} else {/** ptt已经初始化*/POINT psrc = { 0, 0 };switch (message){case WMAPP_TT_LOCK:// 重新锁定#pragma regionif ((cTooltip*)wparam != ptt && wparam != 0){ShowWindow(ptt->m_wnd, SW_HIDE);                    ptt->m_locked = false;                    ptt->m_visible = false;                    SetWindowLong(ptt->m_wnd, GWL_WNDPROC, (LONG)ptt->oldttproc);                    ptt = nullptr;                    // 销毁缓冲区                    isbufferinited = false;                    if (bufferdc) { ReleaseDC(hwnd, bufferdc); bufferdc = 0; }                    if (bufferbmp) { DeleteObject(bufferbmp); bufferbmp = 0; }                    ptt = (cTooltip*)wparam;                    SetWindowLong(ptt->m_wnd, GWL_WNDPROC, (LONG)ptt->ttproc);                    ptt->m_locked = true;                    ptt->m_visible = true;                    SendMessage(ptt->m_wnd, WM_SIZE, 0, 0);                    ShowWindow(ptt->m_wnd, SW_SHOW);return true;} else{return false;}#pragma endregioncase WMAPP_TT_UUNLOCK:// 解锁信息#pragma regionislocked = false;ptt->m_locked = false;ptt->m_visible = false;                                SetWindowLong(ptt->m_wnd, GWL_WNDPROC, (LONG)ptt->oldttproc);                                ptt = nullptr;// 销毁缓冲区isbufferinited = false;if (bufferdc) { ReleaseDC(hwnd, bufferdc); bufferdc = 0; }if (bufferbmp) { DeleteObject(bufferbmp); bufferbmp = 0; }return true;#pragma endregioncase WMAPP_TT_SHOW:// 显示窗口#pragma regionptt->m_visible = true;if (!isbufferinited)SendMessage(hwnd, WM_SIZE, 0, 0);// 显示窗口ShowWindow(hwnd, SW_SHOW);SendMessage(hwnd, WM_PAINT, 0, 0);break;#pragma endregioncase WMAPP_TT_HIDE:// 隐藏窗口#pragma regionptt->m_visible = false;// 隐藏窗口ShowWindow(hwnd, SW_HIDE);SendMessage(hwnd, WM_PAINT, 0, 0);break;#pragma endregioncase WM_SIZE:#pragma regionSetWindowPos(hwnd, HWND_TOPMOST, ptt->wndarea.left, ptt->wndarea.top, ptt->wndarea.right, ptt->wndarea.bottom, 0);hdc = GetDC(hwnd);GetClientRect(hwnd, &rec);// 初始化缓冲区isbufferinited = true;bufferdc = CreateCompatibleDC(hdc);bufferbmp = CreateCompatibleBitmap(hdc, rec.right, rec.bottom);naughtybuffer = CreateCompatibleDC(bufferdc);SelectObject(bufferdc, bufferbmp);ReleaseDC(hwnd, hdc);break;#pragma endregioncase WM_PAINT:#pragma regionBeginPaint(hwnd, &ps);EndPaint(hwnd, &ps);hdc = GetDC(hwnd);GetClientRect(hwnd, &rec);naughtybuffer = CreateCompatibleDC(bufferdc);// 绘制背景FillRect(bufferdc, &rec, ptt->m_brushtransparent);// 绘制轮廓和背景SelectObject(bufferdc, ptt->m_outlinepen);SelectObject(bufferdc, ptt->m_bkbrush);Polygon(bufferdc, ptt->m_outline, 11);SelectObject(bufferdc, ptt->m_font);SetTextColor(bufferdc, ptt->m_txtcolor);SetBkMode(bufferdc, TRANSPARENT);// 开始依次绘制所有提示信息for (unsigned row = 0; row < ptt->m_infos.size(); ++row){INFOTXT* pinfotxt = nullptr;INFOBMP* pinfobmp = nullptr;for (unsigned col = 0; col < ptt->m_infos[row].size(); ++col){switch (ptt->m_infos[row][col]->getid()){case TIPINFO_DATATYPE_TXT:// 如果这条提示信息是文本pinfotxt = (INFOTXT*)ptt->m_infos[row][col];TextOut(bufferdc,ptt->infoarea.left + ptt->m_infosarea[row][col].left,ptt->infoarea.top + ptt->m_infosarea[row][col].top,pinfotxt->m_txt, pinfotxt->m_size);break;case TIPINFO_DATATYPE_BMP:// 如果这条提示信息是图片pinfobmp = (INFOBMP*)ptt->m_infos[row][col];oldbmp = (HBITMAP)SelectObject(naughtybuffer, pinfobmp->m_bmp.bmp);StretchBlt(bufferdc,   ptt->infoarea.left + ptt->m_infosarea[row][col].left,   ptt->infoarea.top + ptt->m_infosarea[row][col].top,   pinfobmp->m_bmp.destw, pinfobmp->m_bmp.desth,   naughtybuffer, 0, 0,   pinfobmp->m_bmp.srcw, pinfobmp->m_bmp.srcw,   SRCCOPY   );SelectObject(naughtybuffer, oldbmp);break;}}}// 更新屏幕BitBlt(hdc, 0, 0, rec.right, rec.bottom, bufferdc, 0, 0, SRCCOPY);ReleaseDC(hwnd, hdc);ReleaseDC(hwnd, naughtybuffer);break;#pragma endregioncase WM_ERASEBKGND:#pragma regionreturn true;#pragma endregioncase WM_DESTROY:#pragma regionptt->m_wnd = 0;ptt->m_locked = false;ptt = nullptr;// 释放缓冲区isbufferinited = false;if (bufferdc) { ReleaseDC(hwnd, bufferdc); bufferdc = 0; }if (bufferbmp) { DeleteObject(bufferbmp); bufferbmp = 0; }break;#pragma endregiondefault:return CallWindowProc(ptt->oldttproc, hwnd, message, wparam, lparam);}}return 0;}


本篇结束

                                             
0 0