Code:
//tooltip class:
const char tooltippropname[] = "propertytooltip";
const char tooltipclassprop[] = "classtooltip";
class tooltip
{
private:
HWND hwnd=NULL;
string strCaption="";
boolean blnvisible=false;
static LRESULT CALLBACK WndProcToolTip(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
WNDPROC oldproc = (WNDPROC)GetProp(GetParent(hwnd), tooltippropname);
if (oldproc == NULL)
MessageBox(NULL, "Can't find old procedure", "error", MB_OK | MB_ICONEXCLAMATION);
//add the instance class to inst pointer
tooltip *inst = (tooltip*)GetProp(hwnd, tooltipclassprop);
if (inst == NULL || msg == WM_NCCREATE)
{
inst = (tooltip*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
SetProp(hwnd, tooltipclassprop, (HANDLE)inst);
}
if (inst == NULL)
MessageBox(NULL, "Can't find the instance pointer", "error", MB_OK);
switch(msg)
{
case WM_WINDOWPOSCHANGED:
{
if(IsWindowVisible(inst->hwnd)==true)
{
SetWindowPos(inst->hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE);
SetFocus(inst->hwnd);
}
}
break;
case WM_ERASEBKGND:
{
return TRUE;
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(inst->hwnd, &ps);
HTHEME hTheme = OpenThemeData(inst->hwnd, L"TOOLTIP");
image imgtooltip(ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top);
DrawThemeBackground(hTheme,imgtooltip, TTP_STANDARD , TTSS_NORMAL,&ps.rcPaint, &ps.rcPaint);
RECT a=ps.rcPaint;
a.left=a.left+3;
DrawThemeText(hTheme, imgtooltip, TTP_STANDARD , TTSS_NORMAL, towstring(inst->strCaption).c_str(),-1,DT_LEFT|DT_HIDEPREFIX,0,&a);
CloseThemeData(hTheme);
region n(imgtooltip, GetPixel(imgtooltip,0,0));
SetWindowRgn(inst->hwnd,NULL,TRUE);
SetWindowRgn(inst->hwnd,n,TRUE);
//BitBlt(ps.hdc,0,0,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,imgtooltip,0,0,SRCCOPY);
TransparentBlt(ps.hdc,0,0,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top,imgtooltip,0,0,ps.rcPaint.right-ps.rcPaint.left,ps.rcPaint.bottom-ps.rcPaint.top, GetPixel(imgtooltip,0,0));
EndPaint(inst->hwnd, &ps);
}
break;
case WM_RBUTTONUP:
{
ShowWindow(inst->hwnd, FALSE);
RECT b;
GetWindowRect(GetParent(inst->hwnd),&b);
InvalidateRect(GetParent(inst->hwnd),&b,TRUE);
}
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
void setParent(HWND parent=WindowMain)
{
if (hwnd==NULL)
{
WNDCLASS tooltipclass;
HINSTANCE mod = (HINSTANCE)GetModuleHandle(NULL);
ZeroMemory(&tooltipclass, sizeof(WNDCLASS));
GetClassInfo(mod, TEXT("BUTTON"), &tooltipclass);
tooltipclass.hInstance = mod;
tooltipclass.lpszClassName = TEXT("tooltip");
tooltipclass.style=CS_DBLCLKS | CS_DROPSHADOW;
// store the old WNDPROC of the button window class
SetProp(parent, tooltippropname, (HANDLE)tooltipclass.lpfnWndProc);
// replace it with local WNDPROC
tooltipclass.lpfnWndProc = WndProcToolTip;
tooltipclass.hbrBackground = (HBRUSH) GetStockBrush(NULL_BRUSH);
// register the new window class"
RegisterClass(&tooltipclass);
hwnd = CreateWindowEx(
WS_EX_TOPMOST,
TEXT("tooltip"),//these must be the same of ButtonClass.lpszClassName.. registed class
strCaption.c_str(),
BS_OWNERDRAW |WS_TABSTOP| BS_NOTIFY | WS_CHILD, //onerdraw for add images
CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
parent,
0,
mod,
this);
if (hwnd == NULL)
MessageBox(NULL, "Can't create the control", "error", MB_OK);
if (SetProp(hwnd, tooltipclassprop, (HANDLE)this) == 0)
MessageBox(NULL, "can't set the class property", "error", MB_OK);
RECT textrect={0};
HDC txthdc=GetDC(hwnd);
DrawText (txthdc,strCaption.c_str(),-1,&textrect,DT_CALCRECT);
SetWindowPos(hwnd, HWND_TOP, 0, 0, textrect.right-textrect.left, textrect.bottom, SWP_NOMOVE | SWP_FRAMECHANGED | SWP_HIDEWINDOW);
RECT d;
GetClientRect(hwnd,&d);
InvalidateRect(hwnd,&d,TRUE);
}
else
{
SetParent(hwnd,parent);
}
}
public:
~tooltip()
{
DestroyWindow(hwnd);
}
tooltip(string text="")
{
strCaption=text;
setParent();
if(hwnd==NULL)
MessageBox(NULL,"error","error", MB_OK);
}
property<boolean> visible
{
Get(boolean)
{
return blnvisible;
},
Set(boolean blnVisible)
{
blnvisible=blnVisible;
if (blnvisible==true)
{
ShowWindow(hwnd,TRUE);
RECT d;
GetClientRect(hwnd,&d);
InvalidateRect(hwnd,&d,TRUE);
}
else
{
ShowWindow(hwnd,FALSE);
RECT b;
GetWindowRect(GetParent(hwnd),&b);
InvalidateRect(GetParent(hwnd),&b,TRUE);
}
}
};
void show(int posx, int posy)
{
blnvisible=true;
RECT textrect={0};
HDC txthdc=GetDC(hwnd);
DrawText (txthdc,strCaption.c_str(),-1,&textrect,DT_CALCRECT);
SetWindowPos(hwnd, HWND_TOP, posx, posy, textrect.right, textrect.bottom, SWP_NOMOVE | SWP_FRAMECHANGED);
RECT d;
GetClientRect(hwnd,&d);
InvalidateRect(hwnd,&d,TRUE);
}
void show()
{
//Getting mouse cursor coordenates
POINT a;
GetCursorPos(&a);
ScreenToClient(GetParent(hwnd),&a);
//Getting mouse cursor size
ICONINFO ii;
GetIconInfo(GetCursor(), &ii);
BITMAP bm;
GetObject( ii.hbmColor, sizeof( bm ), &bm );
//bm.bmHeight = ii.hbmColor ? bm.bmHeight : bm.bmHeight / 2;
//Show the ToolTip
blnvisible=true;
RECT textrect={0};
HDC txthdc=GetDC(hwnd);
DrawText (txthdc,strCaption.c_str(),-1,&textrect,DT_CALCRECT);
SetWindowPos(hwnd, HWND_TOP, a.x , a.y + bm.bmHeight/2 + 3, textrect.right, textrect.bottom, SWP_SHOWWINDOW| SWP_FRAMECHANGED | SWP_DRAWFRAME);
RECT d;
GetClientRect(hwnd,&d);
InvalidateRect(hwnd,&d,TRUE);
}
property<string> caption
{
Get(string)
{
return strCaption;
},
Set(string strtext)
{
strCaption=strtext;
RECT textrect={0};
HDC txthdc=GetDC(hwnd);
DrawText (txthdc,strCaption.c_str(),-1,&textrect,DT_CALCRECT);
SetWindowPos(hwnd, HWND_TOP, 0, 0, textrect.right-textrect.left, textrect.bottom, SWP_NOMOVE | SWP_FRAMECHANGED);
RECT b;
GetWindowRect(hwnd,&b);
InvalidateRect(hwnd,&b,TRUE);
}
};
};
the 1st time, the control is showed on top. but when the back control is drawed(wM_PAINT), i lose the top most