Duilib介面解析1—簡單的仿360視窗

最近開始研究Duilib,並逐個分析Duilib的demo例子,記錄下來方便更多的人學習 。介面執行起來如下圖所示,該Demo主要包含 BaseDialog.h和BaseDialog.cpp,以及介面佈局檔案的詳細解釋,每行註釋已經新增。

BaseDialog標頭檔案原始檔 以及佈局檔案如下,可自行下載Duilib 根據註釋學習該例子 只針對新手~~~

#ifndef BaseDialog_H
#define BaseDialog_H
#include "UIlib.h"
#include <map>
using namespace DuiLib;
//繼承自CWindowWnd  INotifyUI  
//擁有建立視窗和接受視窗事件通知的能力
class BaseDialog : public CWindowWnd, public INotifyUI
{
public:
BaseDialog(){};
protected:
//虛擬函式 用於設定視窗的CLASS NAME
virtual LPCTSTR GetWindowClassName() const { return _T("USHER TEST DLG"); }
//用於時間通告訊息回撥 
virtual void Notify(TNotifyUI& msg);
//處理
virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
// 自定義訊息對映
typedef HRESULT (BaseDialog::*CustomMsgHandler)(WPARAM, LPARAM, BOOL&);
typedef std::map<UINT, CustomMsgHandler> MessageMap;
virtual MessageMap* InitMessageMap();
// 自定義訊息處理 在視窗建立的時候
HRESULT OnCreate(WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//在視窗銷燬的時候
HRESULT OnDestory(WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//擦除視窗背景
HRESULT OnErasebkgnd(WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//尺寸改變的時候
HRESULT OnSize(WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//非客戶區重繪
HRESULT OnNcPaint(WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//非客戶區啟用
HRESULT OnNcActive(WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//非客戶區計算大小
HRESULT OnNcCalSize(WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//非客戶區點選測試
HRESULT OnNcHitTest(WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//系統命令處理
LRESULT OnSysCommand(WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//最大最小化資訊
LRESULT OnGetMinMaxInfo(WPARAM wParam, LPARAM lParam, BOOL& bHandled);
private:
CPaintManagerUI m_pm;
};
#endif // BaseDialog_H

#include "StdAfx.h"
#include "BaseDialog.h"
#include <memory>
//訊息通告
void BaseDialog::Notify(TNotifyUI& msg)
{   
//如果是點選訊息那麼通過控制元件名字判斷是哪個控制元件
if ( msg.sType == _T("click"))
{
if( msg.pSender == static_cast<CButtonUI*>(m_pm.FindControl(_T("minbtn"))) )
SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0);
if( msg.pSender == static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn"))) )
PostQuitMessage(0);
if( msg.pSender == static_cast<CButtonUI*>(m_pm.FindControl(_T("maxbtn"))) )
::IsZoomed(*this) ? SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0) : SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0);
if (msg.pSender == static_cast<CButtonUI*>(m_pm.FindControl(_T("check_normal")))) {
::MessageBox(NULL, L"開始掃描", L"提示", MB_OK);
}
}
}
//首先啟動訊息迴圈會進入此虛擬函式進行訊息處理 
LRESULT BaseDialog::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{  
//初始化訊息對映MAP  利用auto_ptr維護指標 static保證只建立一次
static std::auto_ptr<MessageMap> customMessageMap(InitMessageMap());
BOOL bHandled = TRUE;
LRESULT lRes = 0;
//將訊息在訊息對映map中進行查詢 找到響應的訊息處理函式
if ( customMessageMap->find(uMsg) != customMessageMap->end() )
{   
//typedef HRESULT (BaseDialog::*CustomMsgHandler)(WPARAM, LPARAM, BOOL&);  
//如果找到 查詢響應的訊息響應函式
CustomMsgHandler handler = (*customMessageMap)[uMsg];
//通過this->(*handler)進行訊息響應函式的呼叫
lRes = (this->*handler)(wParam, lParam, bHandled);
//如果 bHandled返回True沒有被修改那麼說明訊息已經被處理 返回
if ( bHandled ) return lRes;
}
//CPaintManagerUI丟給PaintManagerUI進行處理 如果處理了 那麼會返回True 否則返回false繼續走
if( m_pm.MessageHandler(uMsg, wParam, lParam, lRes) ) return lRes;
//最後丟給預設的windows訊息處理函式
return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
}
//初始化訊息迴圈對應的訊息響應函式
BaseDialog::MessageMap* BaseDialog::InitMessageMap()
{
MessageMap* map = new MessageMap;
(*map)[WM_CREATE] = &BaseDialog::OnCreate;
(*map)[WM_DESTROY] = &BaseDialog::OnDestory;
(*map)[WM_ERASEBKGND] = &BaseDialog::OnErasebkgnd;
(*map)[WM_SIZE] = &BaseDialog::OnSize;
(*map)[WM_NCPAINT] = &BaseDialog::OnNcPaint;
//以下三個訊息用於遮蔽系統標題欄
(*map)[WM_NCACTIVATE] = &BaseDialog::OnNcActive;
(*map)[WM_NCCALCSIZE] = &BaseDialog::OnNcCalSize;
(*map)[WM_NCHITTEST] = &BaseDialog::OnNcHitTest;
(*map)[WM_SYSCOMMAND] = &BaseDialog::OnSysCommand;
(*map)[WM_GETMINMAXINFO] = &BaseDialog::OnGetMinMaxInfo;
return map;
}
//視窗建立時候
HRESULT BaseDialog::OnCreate( WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
//獲取當前視窗風格
LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
styleValue &= ~WS_CAPTION;
//設定STYLE
::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
//初始化介面渲染器
m_pm.Init(m_hWnd); 
//D
CDialogBuilder builder;
//通過xml 以及渲染器渲染介面UI
CControlUI* pRoot = builder.Create(_T("main_dlg.xml"), (UINT)0, NULL, &m_pm);
//附加介面UI到對話方塊容器 
m_pm.AttachDialog(pRoot);
//增加訊息處理  因為實現了 INotifyUI介面
m_pm.AddNotifier(this);
return 0;
}
HRESULT BaseDialog::OnDestory( WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
//傳送退出訊息
::PostQuitMessage(0L);
return 0;
}
//擦除背景
HRESULT BaseDialog::OnErasebkgnd( WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{ 
return 1;
}
//當視窗的尺寸發生改編的時候
HRESULT BaseDialog::OnSize( WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{   
//在視窗大小改變的時候設定圓角
SIZE szRoundCorner = m_pm.GetRoundCorner();
if( !::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0) ) 
{
CRect rcWnd;
::GetWindowRect(*this, &rcWnd);
rcWnd.Offset(-rcWnd.left, -rcWnd.top);
rcWnd.right  ; 
rcWnd.bottom  ;
HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, 
rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy);
::SetWindowRgn(*this, hRgn, TRUE);
::DeleteObject(hRgn);
return 0;
}
bHandled = FALSE;
return 0;
}
HRESULT BaseDialog::OnNcPaint( WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
return 0;
}
HRESULT BaseDialog::OnNcActive( WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
if( ::IsIconic(*this) ) bHandled = FALSE;
return (wParam == 0) ? TRUE : FALSE;
}
//如果不處理那麼就會導致DUILIB 不停呼叫系統訊息進行處理
// 遮蔽系統標題欄 似乎不遮蔽一定會出問題
HRESULT BaseDialog::OnNcCalSize( WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{
return 0;
}
HRESULT BaseDialog::OnNcHitTest( WPARAM wParam, LPARAM lParam, BOOL& bHandled )
{  
//獲取客戶區相對座標
POINT pt; 
pt.x = GET_X_LPARAM(lParam); 
pt.y = GET_Y_LPARAM(lParam);
::ScreenToClient(*this, &pt);
//獲取客戶區域
RECT rcClient;
::GetClientRect(*this, &rcClient);
//如果視窗沒有最大化
if( !::IsZoomed(*this) ) 
{  
//獲取非客戶區域sizebox
RECT rcSizeBox = m_pm.GetSizeBox();
//如果y<視窗區域top sizebox.top 算上非客戶區
if( pt.y < rcClient.top   rcSizeBox.top ) 
{  
//判斷是否在左上邊
if( pt.x < rcClient.left   rcSizeBox.left ) return HTTOPLEFT;
//判斷是否在右上邊
if( pt.x > rcClient.right - rcSizeBox.right ) return HTTOPRIGHT;
//返回頂端測試
return HTTOP;
}
//否則在bottom
else if( pt.y > rcClient.bottom - rcSizeBox.bottom ) 
{   
//左下
if( pt.x < rcClient.left   rcSizeBox.left ) return HTBOTTOMLEFT;
//右下
if( pt.x > rcClient.right - rcSizeBox.right ) return HTBOTTOMRIGHT;
//預設下邊
return HTBOTTOM;
}
//如果不再 top 或者bottom 那麼就是在左邊 右邊的非客戶區
if( pt.x < rcClient.left   rcSizeBox.left ) return HTLEFT;
if( pt.x > rcClient.right - rcSizeBox.right ) return HTRIGHT;
}
//獲取標題欄的矩形區域  
//並且判斷滑鼠是否在該區域中 如果在返回
RECT rcCaption = m_pm.GetCaptionRect();
if( pt.x >= rcClient.left   rcCaption.left 
&& pt.x < rcClient.right - rcCaption.right
&& pt.y >= rcCaption.top 
&& pt.y < rcCaption.bottom ) 
{      
//ButtonUI OptionUI 只有這兩種型別當作標題欄
CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
if( pControl 
&& _tcscmp(pControl->GetClass(), _T("ButtonUI")) != 0 
&& _tcscmp(pControl->GetClass(), _T("OptionUI")) != 0 )
{
return HTCAPTION;
}
}
//其餘部分是客戶區
return HTCLIENT;
}
//系統命令處理
LRESULT BaseDialog::OnSysCommand(WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if( wParam == SC_CLOSE ) 
{
::PostQuitMessage(0L);
bHandled = TRUE;
return 0;
}
BOOL bZoomed = ::IsZoomed(*this);
LRESULT lRes = CWindowWnd::HandleMessage(WM_SYSCOMMAND, wParam, lParam);
return 1L;
}
LRESULT BaseDialog::OnGetMinMaxInfo(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-5;
lpMMI->ptMaxPosition.y	= rcWork.top-3;
lpMMI->ptMaxSize.x		= rcWork.right 10;
lpMMI->ptMaxSize.y		= rcWork.bottom 10;
bHandled = FALSE;
return 0;
}

<?xml version="1.0" encoding="utf-8"?>
<Window size="910,610" sizebox="10,10,12,12" roundcorner="0,0" caption="0,0,0,90" mininfo="910,610" bktrans="true" shadow="true" shadowimage="shadow.png" shadowtopleft="0,0,5,3" shadowtopright="205,0,5,3" shadowbottomleft="0,136,5,7" shadowbottomright="205,136,5,7">
<!--根據順序記錄字型可通過int 索引引用-->
<Font name="微軟雅黑" size="12" />
<Font name="微軟雅黑" size="16" />
<Font name="微軟雅黑" size="22" />
<Font name="宋體" size="15" />
<!--整體垂直佈局-->
<VerticalLayout   bkimage="file='bg.png'">
<!--容器的內邊距放置到一行  水平佔滿-->
<HorizontalLayout height="40" inset="0,3,0,0">
<!--titile標題的位置佔位 根據內容決定大小  在一個水平佈局中沒有設定寬度的佈局會預設填充所有內容-->
<HorizontalLayout>
<!--float true使用絕對定位  設定位置 文字顏色 字型索引0-->
<Text text="360安全衛士9.2" pos="15, 10, 200, 50" float="true" textcolor="#FFFFFF" font="0" />
</HorizontalLayout>
<!--徽章位置寬度40 height 30-->
<HorizontalLayout width="40" height="30">
<Button maxwidth="26" inset="200,10,0,0" normalimage="medal.png"/>
</HorizontalLayout>
<!---寬度是150的選單欄-->
<HorizontalLayout width="150">
<!--設定按鈕的 寬度 高度  普通圖片  hover圖片 按鈕按下的圖片-->
<Button name="skinbtn" maxwidth="27" maxheight="22" normalimage="skin_normal.png" hotimage="skin_hover.png" pushedimage="skin_pressed.png"/>
<Button name="feedbackbtn" maxwidth="27" maxheight="22" normalimage="feedback_normal.png" hotimage="feedback_hover.png" pushedimage="feedback_pressed.png"/>
<Button name="maxbtn" maxwidth="27" maxheight="22" normalimage="menu_normal.png" hotimage="menu_hover.png" pushedimage="menu_pressed.png"/>
<Button name="minbtn" maxwidth="27" maxheight="22" normalimage="min_normal.png" hotimage="min_hover.png" pushedimage="min_pressed.png"/>
<Button name="closebtn" maxwidth="27" maxheight="22" normalimage="close_normal.png" hotimage="close_hover.png" pushedimage="close_pressed.png"/>
</HorizontalLayout>
</HorizontalLayout>
<!--第二行工具按鈕 -->
<HorizontalLayout height="85">
<HorizontalLayout>
<!---前景背景圖片都是相對座標除非 float會變成絕對zu-->
<Option pos="15,10,85,85" float="true" align="bottom" text="電腦體檢"   textpadding="11,55,0,0" font="0" textcolor="#FFFFFF" selected="true" foreimage="file='ico_Examine.png' dest='11,5,59,53'" normalimage="toolbar_normal.png" hotimage="file='toolbar_hover.png' source='80,0,160,75'" pushedimage="file='toolbar_hover.png' source='80,0,160,75'" selectedimage="file='toolbar_hover.png' source='80,0,160,75'" group="main_toolbar" selected="true"/>
<Option pos="97,10,167,85" float="true" align="bottom" text="木馬查殺" textpadding="11,55,0,0" font="0" textcolor="#FFFFFF" selected="true" foreimage="file='ico_dsmain.png' dest='11,5,59,53'" normalimage="toolbar_normal.png" hotimage="file='toolbar_hover.png' source='80,0,160,75'" pushedimage="file='toolbar_hover.png' source='80,0,160,75'"  selectedimage="file='toolbar_hover.png' source='80,0,160,75'" group="main_toolbar" selected="false"/>
<Option pos="179,10,249,85" float="true" align="bottom" text="系統修復" textpadding="11,55,0,0" font="0" textcolor="#FFFFFF" selected="true" foreimage="file='ico_SysRepair.png' dest='11,5,59,53'" normalimage="toolbar_normal.png" hotimage="file='toolbar_hover.png' source='80,0,160,75'" pushedimage="file='toolbar_hover.png' source='80,0,160,75'"  selectedimage="file='toolbar_hover.png' source='80,0,160,75'" group="main_toolbar" selected="false"/>
<Option pos="261,10,331,85" float="true" align="bottom" text="電腦清理" textpadding="11,55,0,0" font="0" textcolor="#FFFFFF" selected="true" foreimage="file='ico_TraceCleaner.png' dest='11,5,59,53'" normalimage="toolbar_normal.png" hotimage="file='toolbar_hover.png' source='80,0,160,75'" pushedimage="file='toolbar_hover.png' source='80,0,160,75'"  selectedimage="file='toolbar_hover.png' source='80,0,160,75'" group="main_toolbar" selected="false"/>
<Option pos="343,10,413,85" float="true" align="bottom" text="優化加速" textpadding="11,55,0,0" font="0" textcolor="#FFFFFF" selected="true" foreimage="file='ico_SpeedupOpt.png' dest='11,5,59,53'" normalimage="toolbar_normal.png" hotimage="file='toolbar_hover.png' source='80,0,160,75'" pushedimage="file='toolbar_hover.png' source='80,0,160,75'"  selectedimage="file='toolbar_hover.png' source='80,0,160,75'" group="main_toolbar" selected="false"/>
<Option pos="425,10,495,85" float="true" align="bottom" text="電腦專家" textpadding="11,55,0,0" font="0" textcolor="#FFFFFF" selected="true" foreimage="file='ico_expert.png' dest='11,5,59,53'" normalimage="toolbar_normal.png" hotimage="file='toolbar_hover.png' source='80,0,160,75'" pushedimage="file='toolbar_hover.png' source='80,0,160,75'"  selectedimage="file='toolbar_hover.png' source='80,0,160,75'" group="main_toolbar" selected="false"/>
<Option pos="507,10,577,85" float="true" align="bottom" text="電腦門診" textpadding="11,55,0,0" font="0" textcolor="#FFFFFF" selected="true" foreimage="file='ico_diannaomenzhen.png' dest='11,5,59,53'" normalimage="toolbar_normal.png" hotimage="file='toolbar_hover.png' source='80,0,160,75'" pushedimage="file='toolbar_hover.png' source='80,0,160,75'"  selectedimage="file='toolbar_hover.png' source='80,0,160,75'" group="main_toolbar" selected="false"/>
<Option pos="589,10,659,85" float="true" align="bottom" text="軟體管家" textpadding="11,55,0,0" font="0" textcolor="#FFFFFF" selected="true" foreimage="file='ico_softmgr.png' dest='11,5,59,53'" normalimage="toolbar_normal.png" hotimage="file='toolbar_hover.png' source='80,0,160,75'" pushedimage="file='toolbar_hover.png' source='80,0,160,75'"  selectedimage="file='toolbar_hover.png' source='80,0,160,75'" group="main_toolbar" selected="false"/>
</HorizontalLayout>
<!---LOGO insert位置 相對位置  -->
<!--bkcolor="0xFFFF0000" insert是內部內容的相對位置  LayOut佈局預設是從右邊開始-->
<HorizontalLayout width="180" inset="10,15,1,0">
<Button maxwidth="148" maxheight="62" bkimage="file='logo.png'"/>
</HorizontalLayout>
</HorizontalLayout>
<!--窗體內容背景-->
<HorizontalLayout bkimage="1.bmp" bordercolor="0xFFFF0000" >
<!--垂直佈局-->
<VerticalLayout bordercolor="0xFFFF0000">
<!---pos如果是float=true,那麼是絕對佈局。控制元件那麼 指定位置和大小 如何不是那麼 只指定大小-->
<!---relativepos跟最大化後劇中顯示有關 前兩個是位移值  後兩個是縮放一般不寫 屬性列表沒有給出這個 前兩個是大小改變的時候橫縱向位移 預設單位50表示一個單位,  後兩個是縮放 x,y,scaleX,scaleY-->
<!---常用50,50,0,0 讓絕對定位擁有相對定位佈局的特性-->
<Button pos="50, 50, 196, 168"  bordercolor="0xFFFF0000" relativepos="50,50,0,0"  float="true" normalimage="error.png" />
<Text pos="250, 60, 350, 160" bordercolor="0xFFFF0000" relativepos="50,50,0,0"  float="true" text="您的電腦已經" font="1" textcolor="#1C1C1C" />
<Text pos="360, 55, 400, 160" bordercolor="0xFFFF0000" relativepos="50,50,0,0"  float="true" text="24" font="2" textcolor="#0000FF" />
<Text pos="400, 60, 500, 160" bordercolor="0xFFFF0000" relativepos="50,50,0,0"  float="true" text="天沒有體檢,建議立即體檢!" font="1" textcolor="#1C1C1C" />
<Text pos="250, 100, 350, 150" bordercolor="0xFFFF0000" relativepos="50,50,0,0"  float="true" text="系統可能已經存在大量風險,安全性和效能都在急速下降," font="0" textcolor="#555555" />
<Text pos="250, 120, 350, 150" bordercolor="0xFFFF0000" relativepos="50,50,0,0"  float="true" text="建議您每天堅持電腦體檢,提高電腦的安全和效能" font="0" textcolor="#555555" />
<Button pos="230, 250, 396, 316" name="check_normal" bordercolor="0xFFFF0000" relativepos="50,50,0,0"  float="true" normalimage="check_normal.png" hotimage="check_hover.png" pushedimage="check_pressed.png" />
</VerticalLayout>
<VerticalLayout width="250">
<!---對於此處來說50代表水平位置自動適應 垂直位置不變-->
<Button maxwidth="1"   bordercolor="0xFFFF0000"  minheight="1000" normalimage="fenge_line.png" />
<Button pos="10, 15, 230, 126"    bordercolor="0xFFFF0000" relativepos="50,0,0,0"  float="true" minheight="1000" normalimage="register_bg.png" />
<Button pos="0, 140, 245, 141"    bordercolor="0xFFFF0000" relativepos="50,0,0,0"  float="true" normalimage="rp_line.png" />
<Button pos="80, 140, 81, 225"    bordercolor="0xFFFF0000" relativepos="50,0,0,0"  float="true" normalimage="fenge_line.png" />
<Button pos="160, 140, 161, 225"  bordercolor="0xFFFF0000"  relativepos="50,0,0,0"  float="true" normalimage="fenge_line.png" />
<Button pos="15, 150, 65, 195"    bordercolor="0xFFFF0000" relativepos="50,0,0,0"  float="true" normalimage="firewall_open_normal.png" hotimage="firewall_open_hover.png"/>
<Text pos="10, 200, 65, 210"      bordercolor="0xFFFF0000" relativepos="50,0,0,0"  float="true" text="木馬防火牆" font="0" textcolor="#1C1C1C" />
<Button pos="95, 150, 145, 195"   bordercolor="0xFFFF0000"  relativepos="50,0,0,0"  float="true" normalimage="guard_open_normal.png" hotimage="guard_open_hover.png"/>
<Text pos="95, 200, 105, 210"     bordercolor="0xFFFF0000" relativepos="50,0,0,0"  float="true" text="360保鏢" font="0" textcolor="#1C1C1C" />
<Button pos="175, 150, 225, 195"  bordercolor="0xFFFF0000"  relativepos="50,0,0,0"  float="true" normalimage="payinsure_close_normal.png" hotimage="payinsure_close_hover.png"/>
<Text pos="175, 200, 185, 210"    bordercolor="0xFFFF0000" relativepos="50,0,0,0"  float="true" text="網購先賠" font="0" textcolor="#1C1C1C" />
<Button pos="0, 225, 245, 226"    bordercolor="0xFFFF0000"  relativepos="50,0,0,0"  float="true" normalimage="rp_line.png" />
</VerticalLayout>
</HorizontalLayout>
</VerticalLayout>
</Window>


程式碼加註釋下載地址…….

http://download.csdn.net/detail/yue7603835/9185031