炫彩界面库源码分析---简单的应用程序过程分析
炫彩界面库免费开源后,可以方便使用。它的原理是DirectUI,直接绘制控件并做出相关响应,下面来一一分析。
一个简单的应用程序过程分析: 源码如下
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
XInitXCGUI(); //界面库初始化
//创建窗口
HWINDOW hWindow=XWnd_CreateWindow(400,200,300,200,L"炫彩界面库 - 窗口");
if(hWindow) //创建成功
XWnd_ShowWindow(hWindow,SW_SHOW); //显示窗口
else
return 0; //创建失败
XRunXCGUI(); //运行
return 0;
}
总体的过程分为四部分。
一.界面库初始化XInitXCGUI
二.创建普通窗口XWnd_CreateWindow
三.显示窗口XWnd_ShowWindow
四.运行消息循环XRunXCGUI
下面开始分析每个部分
一.界面库初始化XInitXCGUI
XInitXCGUI函数内部做了如下工作:
1、注册窗口
2、注册剪切板格式
3、初始化4个临界资源对象
4、创建后台线程
简化后代码
HMODULE hInstance = GetModuleHandle(NULL);
HMODULE hInsIcon = hInstance;
//注册窗口
WNDCLASSEXW wcex = {0};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = XCGUI_WndProc;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInsIcon,MAKEINTRESOURCE(IDI_ICON1));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = XCGUI_CLASS_NAME;
wcex.hIconSm = LoadIcon(hInsIcon,MAKEINTRESOURCE(IDI_SMALL));
::RegisterClassEx(&wcex)
//注册剪切板格式
g_clipborad_HTMLFormat=RegisterClipboardFormat(L"HTML Format");
g_clipbroad_RichEditFormat=RegisterClipboardFormat(L"XCGUI_RichEdit_Format");
Resource_Init(); //资源初始化
GdiplusStartupInput gdiplusStartInput;
GdiplusStartup(&gdiplusToken, &gdiplusStartInput, NULL);//GDI++
if(g_fun_init && FALSE==g_fun_init()) //UI文件解析库XML初始化
{
return FALSE;
}
//初始化临界资源对象
InitializeCriticalSection(&g_timer_CriticalSection);
InitializeCriticalSection(&g_CriticalSection_Animation_button);
InitializeCriticalSection(&g_CriticalSection_Animation_richEdit);
InitializeCriticalSection(&g_CriticalSection_WindowDraw);
//后台循环线程
g_hThread_Loop=CreateThread(NULL,0,XCGUI_Loop_ThreadProc,0,0,NULL);
if (NULL==g_hThread_Loop)
{
return FALSE;
}
return TRUE;
后台线程
/////////////////////////////////////////////////////////////////////
DWORD WINAPI XCGUI_Loop_ThreadProc(LPVOID lpParameter)
{
DWORD ms=20;//USER_TIMER_MINIMUM*2; //最小延时单位
while (1)
{
Sleep(ms);
if(NULL==g_hThread_Loop)
break;
DWORD timer=GetTickCount();
//处理定时器
EnterCriticalSection(&g_timer_CriticalSection);
if (g_hArray_Timer)
XCGUI_Loop_timer(timer);
LeaveCriticalSection(&g_timer_CriticalSection);
//////////////////////////////////////////////////////////////////////
//处理按钮动画
EnterCriticalSection(&g_CriticalSection_Animation_button);
if(g_hArray_Animation_button)
XCGUI_Loop_Animation(timer);
LeaveCriticalSection(&g_CriticalSection_Animation_button);
//////////RichEdit GIF/////////////////////////////////////////////////
EnterCriticalSection(&g_CriticalSection_Animation_richEdit);
if(g_hArray_Animation_RichEdit)
XCGUI_Loop_Animation_RichEdit(timer);
LeaveCriticalSection(&g_CriticalSection_Animation_richEdit);
/////////处理窗口绘制优化////////////////////
EnterCriticalSection(&g_CriticalSection_WindowDraw);
resource_manager_window_ *pWindowNode=resource_manager.pWindowList;
while (pWindowNode)
{
window_ *pWindow=(window_*)pWindowNode->hWindow;
if(pWindow->drawWindow.bValid)
{
PostMessage(pWindow->hWnd,XWM_DRAW_T,0,0);
}
pWindowNode=pWindowNode->pNext;
}
LeaveCriticalSection(&g_CriticalSection_WindowDraw);
}
if(g_hThread_Loop)
{
CloseHandle(g_hThread_Loop);
g_hThread_Loop=NULL;
}
return 0;
}
窗口消息回调函数
//总窗口消息过程
LRESULT CALLBACK XCGUI_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if(WM_CREATE==message)
{
LONG L=(LONG)(((LPCREATESTRUCT)lParam)->lpCreateParams);
SetWindowLong(hWnd,GWL_USERDATA,L);
window_ *pWindow=(window_*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
if(XC_IsHWINDOW((HWINDOW)pWindow))
{
windowProc_ *pFunT=pWindow->pWndProc;
while(pFunT)
{
if(((pFunWndMsgProc)pFunT->pFun)((HWINDOW)pWindow,message,wParam,lParam))
return 0;
pFunT=pFunT->pNext;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
window_ *pWindow=(window_*)GetWindowLong(hWnd,GWL_USERDATA);
if(FALSE==XC_IsHWINDOW((HWINDOW)pWindow))
return DefWindowProc(hWnd, message, wParam, lParam);
switch(message)
{
case WM_KILLFOCUS:
{
// XTRACE("失去焦点 \n");
}break;
case WM_SETFOCUS:
{
// XTRACE("获得焦点 \n");
}break;
}
windowProc_ *pFunT=pWindow->pWndProc;
while(pFunT)
{
if(((pFunWndMsgProc)pFunT->pFun)((HWINDOW)pWindow,message,wParam,lParam))
return 0;
pFunT=pFunT->pNext;
}
switch(message)
{
case WM_NCPAINT: return 0;
case WM_ERASEBKGND: return 1;
case WM_NCACTIVATE: return 1;
case WM_ACTIVATE:
{
//XTRACE("激活 WM_ACTIVATE \n");
XWnd_RedrawWnd((HWINDOW)pWindow);
}break;
case WM_NCCALCSIZE:
if(pWindow->transparentFlag & XC_WIND_TRANSPARENT_SHADOW)
{
if(wParam)
{
NCCALCSIZE_PARAMS *pInfo=(NCCALCSIZE_PARAMS*)lParam;
pInfo->rgrc[0].left+=XC_WIND_SHADOW_SIZE;
pInfo->rgrc[0].top+=XC_WIND_SHADOW_SIZE;
pInfo->rgrc[0].right-=XC_WIND_SHADOW_SIZE;
pInfo->rgrc[0].bottom-=XC_WIND_SHADOW_SIZE;
return 0;
}
}else
{
if(wParam)
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
二.创建普通窗口XWnd_CreateWindow
HWINDOW WINAPI XWnd_CreateWindow(int x,int y,int cx,int cy,wchar_t *pTitle,HWND hWndParent,int XCStyle)
{
window_ *pWindow=(window_*)malloc(sizeof(window_)); //创建结构体window_
if(pWindow)
{
memset(pWindow,0,sizeof(window_)); //结构体window_填充0
if(FALSE==Wnd_Init((HWINDOW)pWindow,NULL,NULL,pTitle,NULL,x,y,cx,cy,hWndParent,XCStyle,XC_WINDOW))
{
delete pWindow;
return NULL;
}
//g_fun_create_window函数指针是否存在
//存在时运行函数g_fun_create_window((HWINDOW)pWindow)
//不存在return (HWINDOW)pWindow;
//XML文件创建
if(g_fun_create_window && FALSE==g_fun_create_window((HWINDOW)pWindow))
{
return FALSE;
}
}
return (HWINDOW)pWindow;
}
里面主要调用了一个函数Wnd_Init 窗口初始化
函数简化后
BOOL Wnd_Init(HWINDOW hWindow,DWORD dwExStyle, wchar_t* lpClassName, wchar_t* lpWindowName,DWORD dwStyle,int x,int y,int cx,int cy,HWND hWndParent,int XCStyle,int exType)
{
HMODULE hModule=GetModuleHandle(NULL);
window_ *pWindow=(window_*)hWindow;
pWindow->exType=exType;
pWindow->xcStyle=XCStyle;
pWindow->hArrayEle=XArray_Create();
pWindow->hArrayEleNC=XArray_Create();
pWindow->hMenuBar=NULL;
pWindow->hToolBar=NULL;
pWindow->minWidth=150;
pWindow->minHeight=100;
pWindow->caretColor=RGB(0,0,0);
pWindow->chartletStyle|=XC_CS_STROKE_INNER;
pWindow->chartletStyle|=XC_CS_STROKE_OUTER;
pWindow->strokeOuter_color1=RGB(6,108,156);
pWindow->strokeOuter_color2=RGB(143,217,253);
pWindow->strokeInner_color1=RGB(6,108,156);
pWindow->strokeInner_color2=RGB(143,217,253);
pWindow->transparentAlpha=230;
pWindow->iconSize.cx=24;
pWindow->iconSize.cy=24;
pWindow->roundSize=5;
if(NULL==lpClassName)
lpClassName=XCGUI_CLASS_NAME;
if(NULL==lpWindowName)
lpWindowName=L"XCGUI-Window";
if(NULL==dwStyle)
dwStyle=WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
if(XCStyle & XC_SY_CENTER) //窗口居中
{
RECT rect;
SystemParametersInfo(SPI_GETWORKAREA,0,&rect,0);
x=(rect.right-rect.left)/2-cx/2;
y=(rect.bottom-rect.top)/2-cy/2;
}
if(dwStyle & WS_CAPTION)
{
dwStyle=dwStyle & ~WS_CAPTION;
}
((object_*)hWindow)->type=XC_WINDOW;
AddTypeDebug(hWindow,XC_WINDOW);
HWND hWnd = CreateWindowExW(dwExStyle,lpClassName,lpWindowName,dwStyle,
x, y, cx-1, cy, hWndParent, NULL, hModule, hWindow);
//DWORD err= GetLastError();
if(hWnd)
{
((object_*)hWindow)->type=XC_WINDOW;
pWindow->hWnd=hWnd;
Resource_AddWindow(hWindow); //往资源管理内添加窗口-----必须添加
pWindow->bkColor=RGB(255,255,255);
pWindow->hArray_msg=XArray_Create();
pWindow->hArray_NCmsg=XArray_Create();
::SetWindowPos(hWnd,NULL,0,0,cx,cy,SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
if(pWindow->xcStyle & XC_SY_ROUND)
{
HRGN hrgn = CreateRoundRectRgn(0,0,cx+1,cy+1,pWindow->roundSize,pWindow->roundSize);
SetWindowRgn(hWnd,hrgn,FALSE);
DeleteObject(hrgn);
}
if(XC_SY_CAPTION & XCStyle)
XWnd_SetCaptionHeight(hWindow,28);
if(XC_SY_BORDER & XCStyle)
{
XWnd_SetBorderSize(hWindow,8,8,8,8);
}
//注册消息
//分别往数组内添加要处理的消息
XWnd_RegisterMsgProc(hWindow,Wnd_WindowProc);//窗口过程
XWnd_RegisterNCMessage(hWindow,XWM_NCMOUSEMOVE,Wnd_OnNCMouseMove);
XWnd_RegisterNCMessage(hWindow,XWM_NCLBUTTONDOWN,Wnd_OnNCLButtonDown);
XWnd_RegisterNCMessage(hWindow,XWM_NCLBUTTONUP,Wnd_OnNCLButtonUp);
XWnd_RegisterNCMessage(hWindow,XWM_NCRBUTTONDOWN,Wnd_OnNCRButtonDown);
XWnd_RegisterNCMessage(hWindow,XWM_NCRBUTTONUP,Wnd_OnNCRButtonUp);
XWnd_RegisterNCMessage(hWindow,XWM_NCPAINT,Wnd_OnNCDrawWindow);
XWnd_RegisterNCMessage(hWindow,XWM_NCMOUSECLICK,Wnd_OnNCMouseClick);
XWnd_RegisterNCMessage(hWindow,XWM_NCMOUSEDBCLICK,Wnd_OnNCMouseDBClick);
XWnd_RegisterMessage(hWindow,WM_PAINT,Wnd_OnDrawWindow);
XWnd_RegisterMessage(hWindow,WM_DESTROY,Wnd_OnDestroy);
XWnd_RegisterMessage(hWindow,WM_NCDESTROY,Wnd_OnNCDestroy);
XWnd_RegisterMessage(hWindow,WM_MOUSEMOVE,Wnd_OnMouseMove);
XWnd_RegisterMessage(hWindow,WM_LBUTTONDOWN,Wnd_OnLButtonDown);
XWnd_RegisterMessage(hWindow,WM_LBUTTONUP,Wnd_OnLButtonUp);
XWnd_RegisterMessage(hWindow,WM_RBUTTONDOWN,Wnd_OnRButtonDown);
XWnd_RegisterMessage(hWindow,WM_RBUTTONUP,Wnd_OnRButtonUp);
XWnd_RegisterMessage(hWindow,WM_MOUSELEAVE,Wnd_OnMouseLeave);
XWnd_RegisterMessage(hWindow,WM_SIZE,Wnd_OnSize);
XWnd_RegisterMessage(hWindow,XWM_MOUSECLICK,Wnd_OnMouseClick);
XWnd_RegisterMessage(hWindow,XWM_MOUSEDBCLICK,Wnd_OnMouseDBClick);
XWnd_RegisterMessage(hWindow,XWM_DRAW_T,Wnd_OnDrawT);
XWnd_RegisterMessage(hWindow,XWM_REDRAW_ELE,Wnd_OnRedrawEle);
XWnd_RegisterMessage(hWindow,WM_SETFOCUS,Wnd_OnSetFocus);
XWnd_RegisterMessage(hWindow,WM_KILLFOCUS,Wnd_OnKillFocus);
XWnd_RegisterMessage(hWindow,WM_KEYDOWN,Wnd_OnKeyDown);
XWnd_RegisterMessage(hWindow,WM_TIMER,Wnd_OnTimer);
XWnd_RegisterMessage(hWindow,XWM_TIMER,Wnd_OnTimerEx);
XWnd_RegisterMessage(hWindow,WM_CHAR,Wnd_OnChar);
XWnd_RegisterMessage(hWindow,WM_CAPTURECHANGED,Wnd_OnCaptureChanged);
XWnd_RegisterMessage(hWindow,WM_MOUSEWHEEL,Wnd_OnMouseWheel);
XWnd_RegisterMessage(hWindow,XWM_REDRAW,Wnd_OnRedraw);
XWnd_RegisterMessage(hWindow,WM_GETMINMAXINFO,Wnd_OnMinMaxInfo);
//窗口最大化、最小化、关闭按钮
if(pWindow->xcStyle & XC_SY_CLOSE)
{
pWindow->hClose=XBtn_Create(1,1,40,20);
XWnd_AddEleNC(hWindow,pWindow->hClose);
Ele_SetType(pWindow->hClose,XC_BUTTON_CLOSE);
XEle_EnableFocus(pWindow->hClose,FALSE);
XEle_RegisterMessage(pWindow->hClose,XM_PAINT,Wnd_OnBtnCloseDraw);
XEle_RegisterEvent(pWindow->hClose,XE_BNCLICK,Wnd_OnEventBtnCloseClick);
}
if(pWindow->xcStyle & XC_SY_MAXIMIZE)
{
pWindow->hMaxinize=XBtn_Create(1,1,25,20);
XWnd_AddEleNC(hWindow,pWindow->hMaxinize);
Ele_SetType(pWindow->hMaxinize,XC_BUTTON_MAX);
XEle_EnableFocus(pWindow->hMaxinize,FALSE);
XEle_RegisterMessage(pWindow->hMaxinize,XM_PAINT,Wnd_OnBtnMaximizeDraw);
XEle_RegisterEvent(pWindow->hMaxinize,XE_BNCLICK,Wnd_OnEventBtnMaximizeClick);
}
if(pWindow->xcStyle & XC_SY_MINIMIZE) //最小化按钮
{
pWindow->hMinimize=XBtn_Create(1,1,25,20);
XWnd_AddEleNC(hWindow,pWindow->hMinimize);
Ele_SetType(pWindow->hMinimize,XC_BUTTON_MIN);
XEle_EnableFocus(pWindow->hMinimize,FALSE);
XEle_RegisterMessage(pWindow->hMinimize,XM_PAINT,Wnd_OnBtnMinimizeDraw);
XEle_RegisterEvent(pWindow->hMinimize,XE_BNCLICK,Wnd_OnEventBtnMinimizeClick);
}
//调整窗口
Wnd_AdjustCaption(hWindow,cx);
return TRUE;
}
return FALSE;
}
1.该函数首先是填充结构体window_内部成员的相关数值
2.调用了系统API窗口窗口CreateWindowExW
3.Resource_AddWindow(hWindow);//往资源管理内添加窗口-----必须添加
4.设置标题栏和边框等
5.注册窗口过程函数、注册非客户区消息、注册窗口标准消息
6.窗口最大化、最小化、关闭按钮
7.调整窗口
三.显示窗口XWnd_ShowWindow
四.运行消息循环XRunXCGUI
void WINAPI XRunXCGUI()
{
MSG msg;
// 主消息循环:
while (true)
{
if(Resource_GetWindowCount()<1)
break;
GetMessage(&msg, NULL, 0, 0);
TranslateMessage(&msg);
DispatchMessage(&msg);
}
XExitProcess();
}
XExitProcess 退出函数,处理了一些释放资源