先上效果图(自己感觉还不错):
功能不完善,一是为了熟悉xml的写法,手写,不建议使用编辑器,二了为了理顺程序的流程,加入了部分注释。
xml文件
<?xml version="1.0" encoding="UTF-8"?>
<Window size="300,220" roundcorner="4,4">
<Font name="楷体" size="14" default="true" />
<Container bkimage="bk_image.png" >
<Label text="用户登录" float="true" pos="5, 5, 80, 20"/>
<Button name="closebtn" float="true" pos="275, 0, 300, 20" tooltip="退出程序" normalimage="file='frame_btn_close_normal.bmp' mask='#FFFF00FF'" hotimage="file='frame_btn_close_hot.bmp' mask='#FFFF00FF'" pushedimage="file='frame_btn_close_down.bmp' mask='#FFFF00FF'"/>
<Label text="{b}账号:{/b}" float="true" showhtml="true" pos="60, 105, 100, 125" />
<Label text="{b}密码:{/b}" float="true" showhtml="true" pos="60, 140, 100, 160" />
<Edit name="nameedit" float="true" pos="120, 105, 240, 125" />
<Edit name="passwdedit" password="true" float="true" pos="120, 140, 240, 160" />
<Button name="registerbtn" text="注册" float="true" bordercolor="#e50010" bordersize="1" bkcolor="#bcc1b4" tooltip="注册新帐号" pos="90,185,130,205" />
<Button name="loginbtn" text="登录" float="true" bordercolor="#e50010" bordersize="1" bkcolor="#bcc1b4" tooltip="登录帐号" pos="170,185,210,205" />
</Container>
</Window>
程序代码:
//2012.10.16 by l0g1n。
#include "stdafx.h"
class CFrameWindowWnd:public CWindowWnd,public INotifyUI
{
public:
CFrameWindowWnd(){};
LPCTSTR GetWindowClassName() const { return _T("UIMainFrame"); }
void OnPrepare()
{
}
void Notify(TNotifyUI& msg)
{
if(msg.sType==_T("windowinit"))
OnPrepare();
else if(msg.sType==_T("click"))
{
if(msg.pSender==m_pCloseBtn)
{
PostQuitMessage(0);
return;
}else if(msg.pSender==m_pRegisterBtn)
{
MessageBox(NULL,m_pNameEdit->GetText()+_T("\n")+m_pPasswdEdit->GetText(),_T("注册"),MB_OK);
return;
}else if(msg.pSender==m_pLoginBtn)
{
MessageBox(NULL,m_pNameEdit->GetText()+_T("\n")+m_pPasswdEdit->GetText(),_T("登录"),MB_OK);
return;
}
}
}
void Init()
{
m_pCloseBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn")));
m_pRegisterBtn=static_cast<CButtonUI*>(m_pm.FindControl(_T("registerbtn")));
m_pLoginBtn=static_cast<CButtonUI*>(m_pm.FindControl(_T("loginbtn")));
m_pNameEdit=static_cast<CEditUI*>(m_pm.FindControl(_T("nameedit")));
m_pPasswdEdit=static_cast<CEditUI*>(m_pm.FindControl(_T("passwdedit")));
}
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
styleValue &= ~WS_CAPTION;
::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
m_pm.Init(m_hWnd);
//m_pm.SetTransparent(100);
CDialogBuilder builder;
CControlUI* pRoot = builder.Create(_T("login.xml"), (UINT)0, NULL, &m_pm);
ASSERT(pRoot && "Failed to parse XML");
m_pm.AttachDialog(pRoot);
m_pm.AddNotifier(this);
Init();
return 0;
}
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
SIZE szRoundCorner = m_pm.GetRoundCorner();//这个是圆角,是椭圆的半径
//这里有个很巧妙的用法,在xml文件中一定要设置圆角(roundcorner),
//不然不会进入下面的if,也就会出现标题栏。
if( !::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0) ) {
CRect rcWnd;
::GetWindowRect(*this, &rcWnd);
rcWnd.Offset(-rcWnd.left, -rcWnd.top);
rcWnd.right++; rcWnd.bottom++;
RECT rc = { rcWnd.left, rcWnd.top + szRoundCorner.cx, rcWnd.right, rcWnd.bottom };
HRGN hRgn1 = ::CreateRectRgnIndirect( &rc );
HRGN hRgn2 = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom - szRoundCorner.cx, szRoundCorner.cx, szRoundCorner.cy);
::CombineRgn( hRgn1, hRgn1, hRgn2, RGN_OR );
::SetWindowRgn(*this, hRgn1, TRUE);
::DeleteObject(hRgn1);
::DeleteObject(hRgn2);
}
bHandled = FALSE;
return 0;
}
LRESULT OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
MONITORINFO oMonitor = {};
oMonitor.cbSize = sizeof(oMonitor);
::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor);
CRect rcWork = oMonitor.rcWork;
rcWork.Offset(-rcWork.left, -rcWork.top);
LPMINMAXINFO lpMMI = (LPMINMAXINFO) lParam;
lpMMI->ptMaxPosition.x = rcWork.left;
lpMMI->ptMaxPosition.y = rcWork.top;
lpMMI->ptMaxSize.x = rcWork.right;
lpMMI->ptMaxSize.y = rcWork.bottom;
bHandled = FALSE;
return 0;
}
LRESULT OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if( ::IsIconic(*this) ) bHandled = FALSE;
return (wParam == 0) ? TRUE : FALSE;
}
LRESULT OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
return 0;
}
LRESULT OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
POINT pt;
pt.x=GET_X_LPARAM(lParam);
pt.y=GET_Y_LPARAM(lParam);
::ScreenToClient(*this, &pt);
CControlUI* pControl=static_cast<CControlUI*>(m_pm.FindControl(pt));
if(pControl && _tcscmp(pControl->GetClass(),_T("ButtonUI"))!=0 && _tcscmp(pControl->GetClass(),_T("EditUI"))!=0)
return HTCAPTION;
return HTCLIENT;
}
LRESULT HandleMessage(UINT uMsg,WPARAM wParam,LPARAM lParam)
{
LRESULT lRes=0;
BOOL bHandled=TRUE;
switch(uMsg)
{
case WM_CREATE: lRes=OnCreate(uMsg,wParam,lParam,bHandled);break;
//能去除边框
case WM_NCCALCSIZE: lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled);break;
//去除显示的标题栏
case WM_SIZE: lRes=OnSize(uMsg,wParam,lParam,bHandled);break;
//解决按住左键或右键时会出现边框的问题
case WM_NCACTIVATE: lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break;
//实现按住窗口(除按钮外)拖动窗口
case WM_NCHITTEST: lRes=OnNcHitTest(uMsg,wParam,lParam,bHandled);break;
//获取边框最大最小值
case WM_GETMINMAXINFO: lRes=OnGetMinMaxInfo(uMsg,wParam,lParam,bHandled);break;
case WM_DESTROY: ::PostQuitMessage(0);break;
default: bHandled=FALSE;
}
if(bHandled)
return lRes;
if(m_pm.MessageHandler(uMsg,wParam,lParam,lRes))
return lRes;
return CWindowWnd::HandleMessage(uMsg,wParam,lParam);
}
public:
CPaintManagerUI m_pm;
private:
CButtonUI* m_pCloseBtn;
CButtonUI* m_pRegisterBtn;
CButtonUI* m_pLoginBtn;
CEditUI* m_pNameEdit;
CEditUI* m_pPasswdEdit;
};
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int iCmdShow)
{
CPaintManagerUI::SetInstance(hInstance);
CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath()+_T("skin"));
CPaintManagerUI::SetResourceZip(_T("skinRes"));
HRESULT hr=::CoInitialize(NULL);
if(FAILED(hr))
return 0;
CFrameWindowWnd* pFrame = new CFrameWindowWnd();
if(pFrame==NULL)
return 0;
pFrame->Create(NULL, NULL, UI_WNDSTYLE_FRAME,WS_EX_STATICEDGE | WS_EX_APPWINDOW,0,0,400,400);
pFrame->CenterWindow();
::ShowWindow(*pFrame,SW_SHOW);
CPaintManagerUI::MessageLoop();
::CoUninitialize();
return 0;
}