效果如图。
#ifndef __Fagex_CEGui_W32_H__
#define __Fagex_CEGui_W32_H__
#ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#endif // WIN32_LEAN_AND_MEAN
#include <string>
#include <map>
#include <vector>
namespace Fagex
{
// from "size_t" to DWORD
# pragma warning(disable: 4267)
//warning C4312: “类型转换”: 从“DWORD”转换到更大的“HBRUSH”
# pragma warning(disable: 4311)
//warning C4311: “类型转换”: 从“HBRUSH”到“LONG”的指针截断
# pragma warning(disable: 4312)
typedef std::string String;
} //namespace Fagex
#endif //__Fagex_CEGui_W32_H__
#ifndef __Fagex_CEGui_Window_H__
#define __Fagex_CEGui_Window_H__
#include " FagexStdHreaders.h "
namespace Fagex
{
class Point
{
public:
Point(int a, int b) : x(a), y(b) {};
int x, y;
};
class Line
{
public:
Line(const Point &p1, const Point &p2) : from(p1.x, p1.y), to(p2.x, p2.y) {};
Point from, to;
};
class CEGuiWindow
{
public:
//SetWindowLong SetLayeredWindowAttributes
#define WS_EX_LAYERED 0x00080000
#define LWA_COLORKEY 0x00000001
#define LWA_ALPHA 0x00000002
typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)(HWND hWnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags);
lpfnSetLayeredWindowAttributes SetLayeredWindowAttributes;
typedef LRESULT (CEGuiWindow::*pCEGuiWindowFunction)(WPARAM, LPARAM) ;
typedef struct tagMSGMAP_ENTRY
{
//UINT nMessage; // windows message
pCEGuiWindowFunction pfn; // routine to call (or special value)
}MSGMAP_ENTRY;
typedef std::map<UINT,MSGMAP_ENTRY> MessageEntries;
typedef std::vector<Line> LineVector;
public:
CEGuiWindow(HINSTANCE hInstance);
virtual ~CEGuiWindow();
int createWindow(const String& windowName = "window", HWND hWndParent = 0, int x = 100,int y = 100, int nWidth = 300, int nHeight = 300);
void setText(const String& title, const String& content, bool isUpdate = true);
virtual bool showWindow(int nCmdShow = 1);
bool showWindowAlapa(int nFrom, int to);
void setBkColour(COLORREF color);
void zoomWindow(const RECT &rect);
RECT mRect;
protected:
HWND mhWnd;
String mWindowName;
HINSTANCE mhInstance;
MessageEntries mMessageEntries;
String mTitle;
String mContent;
COLORREF mBKColor;
protected:
LRESULT OnWmKeyUp(WPARAM wParam,LPARAM lParam); //WM_PARINT
LRESULT OnWmNchittest(WPARAM wParam,LPARAM lParam); //WM_NCHITTEST
LRESULT OnWmDestroy(WPARAM wParam,LPARAM lParam); //WM_DESTROY
LRESULT OnWmPaint(WPARAM wParam,LPARAM lParam); //WM_PAINT
protected:
virtual bool initializeWindow();
virtual bool drawWindow();
virtual bool drawTitleContent();
static LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
LRESULT DefWndProc(UINT msg,WPARAM wParam,LPARAM lParam);
};
}
#endif // __Fagex_CEGui_Window_H__
// //FagexCEGuiWindow.cpp-----------------------------------------------
#include " FagexCEGuiWindow.h "
namespace Fagex
{
CEGuiWindow::CEGuiWindow(HINSTANCE hInstance) : mhInstance(hInstance), mhWnd( 0 ), mBKColor(RGB( 255 , 255 , 255 ))
{
HMODULE hUser32 = GetModuleHandle(TEXT( " USER32.DLL " ));
SetLayeredWindowAttributes = (lpfnSetLayeredWindowAttributes)GetProcAddress(hUser32, " SetLayeredWindowAttributes " );
}
// ----------------------------------------------------------------------------------------------------------------------
CEGuiWindow:: ~ CEGuiWindow()
{
OnWmDestroy( 0 , 0 );
HBRUSH hb = (HBRUSH)GetClassLong(mhWnd,GCL_HBRBACKGROUND);
UnregisterClass(mWindowName.c_str(),mhInstance);
DeleteObject(hb);
}
// ----------------------------------------------------------------------------------------------------------------------
int CEGuiWindow::createWindow( const String & winName, HWND hWndParent, int x, int y, int nWidth, int nHeight)
{
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof (wndclass);
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass.lpfnWndProc = CEGuiWindow::WndProc;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)CreateSolidBrush(mBKColor);
wndclass.hInstance = mhInstance;
wndclass.lpszClassName = winName.c_str();
wndclass.lpszMenuName = NULL;
wndclass.hIconSm = NULL;
RegisterClassEx( & wndclass);
mhWnd = CreateWindowEx( 0 ,
winName.c_str(),
winName.c_str(),
WS_POPUP | WS_EX_CLIENTEDGE,
x,
y,
nWidth,
nHeight,
hWndParent,
0 ,
mhInstance,
this );
mWindowName = winName;
if (mhWnd == NULL)
{
return - 1 ;
}
SetWindowLong(mhWnd,GWL_EXSTYLE, GetWindowLong(mhWnd,GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(mhWnd,NULL, 255 ,LWA_ALPHA);
return 1 ;
}
// ----------------------------------------------------------------------------------------------------------------------
LRESULT CALLBACK CEGuiWindow::WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
if (msg == WM_CREATE)
{ // Store pointer to Win32Window in user data area
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)(((LPCREATESTRUCT)lParam) -> lpCreateParams));
return 0 ;
}
CEGuiWindow * win = (CEGuiWindow * )GetWindowLongPtr(hWnd, GWLP_USERDATA);
if ( ! win)
return DefWindowProc(hWnd, msg, wParam, lParam);
return win -> DefWndProc(msg,wParam,lParam);
}
// ----------------------------------------------------------------------------------------------------------------------
LRESULT CEGuiWindow::DefWndProc(UINT msg, WPARAM wParam,LPARAM lParam)
{
CEGuiWindow::MessageEntries::iterator it = mMessageEntries.find(msg);
if (it != mMessageEntries.end())
{
LRESULT ret = ( this ->* it -> second.pfn)(wParam,lParam);
if (ret) return ret;
}
return DefWindowProc(mhWnd, msg, wParam, lParam);
}
// ----------------------------------------------------------------------------------------------------------------------
bool CEGuiWindow::initializeWindow()
{
MSGMAP_ENTRY m;
m.pfn = & CEGuiWindow::OnWmNchittest;
mMessageEntries[WM_NCHITTEST] = m;
m.pfn = & CEGuiWindow::OnWmDestroy;
mMessageEntries[WM_DESTROY] = m;
m.pfn = & CEGuiWindow::OnWmKeyUp;
mMessageEntries[WM_KEYUP] = m;
m.pfn = & CEGuiWindow::OnWmPaint;
mMessageEntries[WM_PAINT] = m;
return true ;
}
// ----------------------------------------------------------------------------------------------------------------------
bool CEGuiWindow::showWindow( int nCmdShow)
{
initializeWindow();
ShowWindow(mhWnd,nCmdShow);
UpdateWindow(mhWnd);
RECT rect;
GetWindowRect(mhWnd, & rect);
mRect = rect;
return true ;
}
// ----------------------------------------------------------------------------------------------------------------------
LRESULT CEGuiWindow::OnWmNchittest(WPARAM wParam,LPARAM lParam)
{
LRESULT nHitTest = DefWindowProc(mhWnd, WM_NCHITTEST, wParam, lParam);
// 如果鼠标左键按下, GetAsyncKeyState 的返回值小于0
if (nHitTest == HTCLIENT && GetAsyncKeyState(MK_LBUTTON) < 0 )
{
nHitTest = HTCAPTION;
}
return nHitTest;
}
// ----------------------------------------------------------------------------------------------------------------------
LRESULT CEGuiWindow::OnWmDestroy(WPARAM wParam,LPARAM lParam)
{
DestroyWindow(mhWnd);
PostQuitMessage( 0 );
return 0 ;
}
// ----------------------------------------------------------------------------------------------------------------------
LRESULT CEGuiWindow::OnWmPaint(WPARAM wParam,LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(mhWnd, & ps);
EndPaint(mhWnd, & ps);
drawTitleContent();
drawWindow();
// static int i = 0;
// i++;
// char sz[50];
// ZeroMemory(sz,50);
// sprintf(sz,"The tick is : %d",i);
// setText(sz,mContent,false);
return 1 ;
// return DefDlgProc(mhWnd,WM_PAINT,wParam,lParam);
}
// ----------------------------------------------------------------------------------------------------------------------
LRESULT CEGuiWindow::OnWmKeyUp(WPARAM wParam,LPARAM lParam)
{
switch (wParam)
{
case VK_ESCAPE:
PostQuitMessage( 0 );
return true ;
case ' Q ' :
showWindowAlapa( 255 , 0 );
PostMessage(mhWnd,WM_DESTROY, 0 , 0 );
return true ;;
}
return false ;
}
// ----------------------------------------------------------------------------------------------------------------------
bool CEGuiWindow::showWindowAlapa( int nFrom, int to)
{
for ( int i = 0 ; i < 20 ; ++ i)
{
SetLayeredWindowAttributes(mhWnd, NULL, nFrom + (to - nFrom) / 20 * i, LWA_ALPHA);
}
SetLayeredWindowAttributes(mhWnd, NULL, to, LWA_ALPHA);
return true ;
}
// -----------------------------------------------------------------------------------------------------------------------
void CEGuiWindow::setBkColour(COLORREF color)
{
mBKColor = color;
HBRUSH hb = (HBRUSH)SetClassLong(mhWnd, GCL_HBRBACKGROUND, (LONG)(HBRUSH)CreateSolidBrush(mBKColor));
DeleteObject(hb);
InvalidateRect(mhWnd, NULL, TRUE);
}
// ----------------------------------------------------------------------------------------------------------------------
void CEGuiWindow::setText( const String & title, const String & content, bool isUpdate)
{
mTitle = title;
mContent = content;
if (isUpdate)
InvalidateRect(mhWnd,NULL,TRUE);
}
// ----------------------------------------------------------------------------------------------------------------------
bool CEGuiWindow::drawWindow()
{
RECT rect, rectTmp;
GetClientRect(mhWnd, & rect);
rectTmp = rect;
int x = rectTmp.left + 20 ;
int y = rectTmp.top + 20 + 20 ;
int cx = rectTmp.right - 20 ;
int cy = y;
HDC hdc = GetDC(mhWnd);
LOGBRUSH lb;
lb.lbStyle = BS_SOLID;
lb.lbColor = RGB( 255 , 0 , 0 );
lb.lbHatch = 0 ;
HPEN hPen = ExtCreatePen(PS_COSMETIC | PS_SOLID, 1 , & lb, 0 , NULL);
HPEN hOldPen = (HPEN)SelectObject(hdc, hPen);
LineVector lines;
lines.push_back(Line(Point(x,y),Point(cx,cy)));
lines.push_back(Line(Point(rect.left,rect.top),Point(rect.right,rect.top)));
lines.push_back(Line(Point(rect.right - 1 , rect.top),Point(rect.right - 1 , rect.bottom)));
lines.push_back(Line(Point(rect.right, rect.bottom - 1 ),Point(rect.left, rect.bottom - 1 )));
lines.push_back(Line(Point(rect.left, rect.bottom),Point(rect.left, rect.top)));
for (LineVector::iterator it = lines.begin(); it != lines.end(); ++ it)
{
MoveToEx(hdc, it -> from.x , it -> from.y, NULL);
LineTo(hdc, it -> to.x , it -> to.y);
}
SelectObject(hdc, hOldPen);
DeleteObject(hPen);
ReleaseDC(mhWnd,hdc);
return true ;
}
// ----------------------------------------------------------------------------------------------------------------------
bool CEGuiWindow::drawTitleContent()
{
RECT rect, rectTmp;
GetClientRect(mhWnd, & rect);
rectTmp = rect;
HDC hdc = GetDC(mhWnd);
SetTextColor(hdc,RGB( 255 , 255 , 0 ));
SetBkMode(hdc,TRANSPARENT);
if ( ! mTitle.empty())
{
rectTmp.left = rect.left + 20 ;
rectTmp.top = rect.top + 20 ;
rectTmp.right = rect.right - 20 ;
rectTmp.bottom = rectTmp.top + 20 ;
DrawText(hdc,mTitle.c_str(),( int )mTitle.length(), & rectTmp, DT_LEFT | DT_END_ELLIPSIS); // 标题
}
LOGFONT lf;
ZeroMemory( & lf, sizeof (LOGFONT));
lf.lfHeight = 14 ;
lstrcpy(lf.lfFaceName, TEXT( " Arial " ));
HFONT hfont = CreateFontIndirect( & lf);
HFONT hOldFont = (HFONT)SelectObject(hdc, hfont);
// 内容
if ( ! mContent.empty())
{
rectTmp.left = rect.left + 20 ;
rectTmp.top = rect.top + 20 + 30 ;
rectTmp.right = rect.right - 20 ;
rectTmp.bottom = rect.bottom - 20 ;
int height = DrawText(hdc,mContent.c_str(),( int )mContent.length(), & rectTmp, DT_LEFT | DT_WORDBREAK | DT_END_ELLIPSIS);
rect.bottom = rectTmp.top + height + 20 ;
zoomWindow(rect);
}
SelectObject(hdc,hOldFont);
DeleteObject(hfont);
ReleaseDC(mhWnd,hdc);
return true ;
}
// ----------------------------------------------------------------------------------------------------------------------
void CEGuiWindow::zoomWindow( const RECT & rect)
{
RECT rc;
GetWindowRect(mhWnd, & rc);
if (rect.right - rect.left != rc.right - rc.left || rect.bottom - rect.top != rc.bottom - rc.top)
MoveWindow(mhWnd, rc.left, rc.top, rect.right - rect.left, rect.bottom - rect.top, TRUE);
}
}
//使用方式(对于指针,当然别忘了析构):
pWindow = new Fagex::CEGuiWindow(AfxGetInstanceHandle());
pWindow -> createWindow( " 1 " , this -> m_hWnd);
pWindow -> showWindow();
pWindow -> setBkColour(RGB( 0 , 40 , 0 ));
pWindow -> showWindowAlapa( 0 , 200 );
pWindow -> setText( " 你好这是标题 " , " hello world, 这里是演示内容! " );