小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

VC 界面美化原理

 浮 生 2009-01-22
VC 界面美化原理
2008-03-11 15:58

本文專題討論VC中的界面美化,適用于具有中等VC水平的讀者。讀者最好具有以下VC基礎(chǔ):

1. 大致了解MFC框架的基本運作原理;

2. 熟悉Windows消息機制,熟悉MFC的消息映射和反射機制;

3. 熟悉OOP理論和技術(shù);

本文根據(jù)筆者多年的開發(fā)經(jīng)驗,并結(jié)合簡單的例子一一展開,希望對讀者有所幫助。

1. 美化界面之開題篇

相信使用過《金山毒霸》、《瑞星殺毒》軟件的讀者應該還記得它們的精美界面:

圖1 瑞星殺毒軟件的精美界面

程序的功能如何如何強大是一回事,它的用戶界面則是另一回事。千萬不要忽視程序的用戶界面,因為它是給用戶最初最直接的印象,丑陋的界面、不友好的風格肯定會影響用戶對軟件程序的使用。

“受之以魚,不若授之以漁”,本教程并不會向你推薦《瑞星殺毒軟件》精美界面的具體實現(xiàn),而只是向你推薦一些常用的美化方法。

2. 美化界面之基礎(chǔ)篇

美化界面需要先熟悉Windows下的繪圖操作,并明白Windows的幕后繪圖操作,才能有的放矢,知道哪些可以使用,知道哪些可以避免……

2.1 Windows下的繪圖操作

熟悉DOS的讀者可能就知道:DOS下面的圖形操作很方便,進入圖形模式,整個屏幕就是你的了,你希望在哪畫個點,那個地方就會出現(xiàn)一個點,紅的、或者黃的,隨你的便。你也可以花點時間畫個按鈕,畫個你自己的菜單,等等……

Windows本身就是圖形界面,所以Windows下面的繪圖操作功能更豐富、簡單。要了解Windows下的繪圖操作,要實現(xiàn)Windows界面的美化,就必須了解MFC封裝的設(shè)備環(huán)境類和圖形對象類。

2.1.1 設(shè)備環(huán)境類

Windows下的繪圖操作說到底就是DC操作。DC(Device Context設(shè)備環(huán)境)對象是一個抽象的作圖環(huán)境,可能是對應屏幕,也可能是對應打印機或其它。這個環(huán)境是設(shè)備無關(guān)的,所以你在對不同的設(shè)備輸出時只需要使用不同的設(shè)備環(huán)境就行了,而作圖方式可以完全不變。這也就是Windows的設(shè)備無關(guān)性。

MFC的CDC類封裝了Windows API 中大部分的畫圖函數(shù)。CDC的常見操作函數(shù)包括:

Drawing-Attribute Functions:繪圖屬性操作,如:設(shè)置透明模式

Mapping Functions:映射操作

Coordinate Functions:坐標操作

Clipping Functions:剪切操作

Line-Output Functions:畫線操作

Simple Drawing Functions:簡單繪圖操作,如:繪制矩形框

Ellipse and Polygon Functions:橢圓/多邊形操作

Text Functions:文字輸出操作

Printer Escape Functions:打印操作

Scrolling Functions:滾動操作

*Bitmap Functions:位圖操作

*Region Functions:區(qū)域操作

*Font Functions:字體操作

*Color and Color Palette Functions:顏色/調(diào)色板操作

其中,標注*項會用到相應的圖形對象類,參見2.1.2內(nèi)容。

2.1.2 圖形對象類

設(shè)備環(huán)境不足以包含繪圖功能所需的所有繪圖特征,除了設(shè)備環(huán)境外, Windows還有其他一些圖形對象用來儲存繪圖特征。這些附加的功能包括從畫線的寬度和顏色到畫文本時所用的字體。圖形對象類封裝了所有六個圖形對象。

下面的表格列出了MFC的圖形對象類:

MFC類 圖形對象句柄 圖形對象目的

CBitmap HBITMAP 內(nèi)存中的位圖

CBrush HBRUSH 畫刷特性―填充某個圖形時所使用的顏色和模式

CFont HFONT 字體特性―寫文本時所使用的字體

CPalette HPALETTE 調(diào)色板顏色

CPen HPEN 畫筆特性―畫輪廓時所使用的線的粗細

CRgn HRGN 區(qū)域特性―包括定義它的點

表1 圖形對象類和它們封裝的句柄

使用CDC和圖形對象類,在Windows里繪圖還算是很簡單的。觀察以下的畫面:

圖2 使用CDC繪制出的按鈕

該畫面通過以下代碼自行繪制的假按鈕:

  1. BOOL CUi1View::PreCreateWindow(CREATESTRUCT& cs)   
  2. {   
  3.     //設(shè)置背景色   
  4.     //CBrush CUi1View::m_Back   
  5.      m_Back.CreateSolidBrush(::GetSysColor(COLOR_3DFACE));   
  6.   
  7.      cs.lpszClass = AfxRegisterWndClass(0, 0, m_Back, NULL);   
  8.     return CView::PreCreateWindow(cs);   
  9. }   
  10.   
  11. int CUi1View::OnCreate(LPCREATESTRUCT lpCreateStruct)   
  12. {   
  13.     if (CView::OnCreate(lpCreateStruct) == -1)   
  14.         return -1;   
  15.   
  16.     //創(chuàng)建字體   
  17.     //CFont CUi1View::m_Font   
  18.      m_Font.CreatePointFont(120, "Impact");   
  19.        
  20.     return 0;   
  21. }   
  22.   
  23. void CUi1View::OnDraw(CDC* pDC)   
  24. {   
  25.     //繪制按鈕框架   
  26.      pDC->DrawFrameControl(CRect(100, 100, 220, 160), DFC_BUTTON, DFCS_BUTTONPUSH);   
  27.   
  28.     //輸出文字   
  29.      pDC->SetBkMode(TRANSPARENT);   
  30.      pDC->TextOut(120, 120, "Hello, CFan!");   
  31. }  
BOOL CUi1View::PreCreateWindow(CREATESTRUCT& cs) { //設(shè)置背景色 //CBrush CUi1View::m_Back m_Back.CreateSolidBrush(::GetSysColor(COLOR_3DFACE)); cs.lpszClass = AfxRegisterWndClass(0, 0, m_Back, NULL); return CView::PreCreateWindow(cs); } int CUi1View::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; //創(chuàng)建字體 //CFont CUi1View::m_Font m_Font.CreatePointFont(120, "Impact"); return 0; } void CUi1View::OnDraw(CDC* pDC) { //繪制按鈕框架 pDC->DrawFrameControl(CRect(100, 100, 220, 160), DFC_BUTTON, DFCS_BUTTONPUSH); //輸出文字 pDC->SetBkMode(TRANSPARENT); pDC->TextOut(120, 120, "Hello, CFan!"); }

呵呵,不好意思,這并不是真的Windows按鈕,它只是一個假的空框子,當用戶在按鈕上點擊鼠標時,放心,什么事情都不會發(fā)生。

2.2 Windows的幕后繪圖操作

在Window中,如果所有的界面操作都由用戶代碼來實現(xiàn),那將是一個很浩大的工程。筆者曾經(jīng)在DOS設(shè)計過窗口圖形界面,代碼上千行,但實現(xiàn)的界面還是很古板、難看,除了我那個對編程一竅不通的女友,沒有一個人欣賞它L;而且,更要命的是,操作系統(tǒng),包括別的應用程序并不認識你的界面元素,這才是真正悲哀的。認識這些界面的只有你的程序,圖2中的按鈕永遠只是一個無用的框子。

有了Windows,一切都好辦了,Windows將諸如按鈕、菜單、工具欄等等這些通用界面的繪制及動作都交給了系統(tǒng),程序員就不用花心思再畫那些按鈕了,可以將更多的精力放在程序的功能實現(xiàn)方面。

所有的標準界面元素都被Windows封裝好了。Windows知道怎么畫你的菜單以及你的標注著“Hello, Cfan!”的按鈕。當CFan某個快樂的小編(譬如:小飛)點擊這個按鈕的時候,Windows也明白按鈕按下去的時候該有的模樣,甚至,當這個友好的按鈕獲取焦點時,Windows也會不失時機地為它準備一個虛框……

有利必有弊。你的不滿這時候產(chǎn)生了:你既想使用Windows的True Button,可也嫌它的界面不夠好看,譬如,你喜歡用藍色的粗體表達你對CFan的無限情懷(正如圖2那樣)――人心不足,有辦法嗎?有的。

3. 美化界面之實現(xiàn)篇

Windows還是給程序員留下了很多后門,通過一些途徑還是可以美化界面的。本章節(jié)我們系統(tǒng)學習一下Windows界面美化的實現(xiàn)。

3.1 美化界面的途徑

如何以合法的手段來達到美化界面的效果?一般美化界面的方法包括:

1. 使用MFC類的既有函數(shù),設(shè)定界面屬性;

2. 利用Windows的消息機制,截獲有用的Windows的消息。通過MFC的消息映射(Message Mapping)和反射(Message Reflecting)機制,在Windows準備或者正在繪制該元素時,偷偷修改它的狀態(tài)和行為,譬如:讓按鈕的邊框為紅色;

3. 利用MFC類的虛函數(shù)機制,重載有用的虛函數(shù)。在MFC框架調(diào)用該函數(shù)的時候,重新定義它的狀態(tài)和行為;

一般來說,應用程序可以通過以下兩種途徑來實現(xiàn)以上的方法:

1. 在父窗口里,截獲自身的或者由子元素(包括控件和菜單等元素)傳遞的關(guān)于界面繪制的消息;

2. 子類化子元素,或者為子元素準備一個新的類(一般來說該類必須繼承于MFC封裝的某個標準類,如:CButton)。在該子元素里,截獲自身的或者從父窗口反射過來的關(guān)于界面繪制的消息。譬如:用戶可以創(chuàng)建一個CXPButton類來實現(xiàn)具有XP風格的按鈕,CXPButton繼承于CButton。

對于應用程序,使用CXPButton類的途徑相對于對話框窗口和普通窗口分成兩種:

① 對話框窗口中,直接將原先綁定按鈕的CButton類替換成CXPButton類,或者在綁定變量時直接指定Control類型為CXPButton,如圖3所示:

7[7,737字節(jié)]

圖3 為按鈕指定CXPButton類型

②在普通窗口中,直接創(chuàng)建一個CXPButton類對象,然后在OnCreate()中調(diào)用CXPButton的Create方法;

以下的章節(jié)將綜合地使用以上的方法,請讀者朋友留心觀察。

3.2 使用MFC類的既有函數(shù)

在界面美化的專題中,MFC也并非一無是處。MFC類對于界面美化也做了部分的努力,以下是一些可以使用的,參數(shù)說明略去。

CWinApp::SetDialogBkColor

void SetDialogBkColor( COLORREF clrCtlBk = RGB(192, 192, 192), COLORREF clrCtlText = RGB(0, 0, 0) );

指定對話框的背景色和文本顏色。

CListCtrl::SetBkColor

CReBarCtrl::SetBkColor

CStatusBarCtrl::SetBkColor

CTreeCtrl::SetBkColor

COLORREF SetBkColor( COLORREF clr );

設(shè)定背景色。

CListCtrl::SetTextColor

CReBarCtrl::SetTextColor

CTreeCtrl::SetTextColor

COLORREF SetTextColor( COLORREF clr );

設(shè)定文本顏色。

CListCtrl::SetBkImage

BOOL SetBkImage( LVBKIMAGE* plvbkImage );

BOOL SetBkImage( HBITMAP hbm, BOOL fTile = TRUE, int xOffsetPercent = 0, int yOffsetPercent = 0);

BOOL SetBkImage( LPTSTR pszUrl, BOOL fTile = TRUE, int xOffsetPercent = 0, int yOffsetPercent = 0 );

設(shè)定列表控件的背景圖片。

CComboBoxEx::SetExtendedStyle

CListCtrl::SetExtendedStyle

CTabCtrl::SetExtendedStyle

CToolBarCtrl::SetExtendedStyle

DWORD SetExtendedStyle( DWORD dwExMask, DWORD dwExStyles );

設(shè)置控件的擴展屬性,例如:設(shè)置列表控件屬性帶有表格線。

圖4是個簡單應用MFC類的既有函數(shù)來改善Windows界面的例子:

MFC[13,190字節(jié)]

圖4 使用MFC類的既有函數(shù)美化界面

相關(guān)實現(xiàn)代碼如下:

  1. BOOL CUi2App::InitInstance()   
  2. {   
  3.     //…   
  4.     //設(shè)置對話框背景色和字體顏色   
  5.      SetDialogBkColor(RGB(128, 192, 255), RGB(0, 0, 255));   
  6.     //…   
  7. }   
  8.   
  9. BOOL CUi2Dlg::OnInitDialog()   
  10. {   
  11.     //…   
  12.     //設(shè)置列表控件屬性帶有表格線   
  13.     DWORD NewStyle = m_List.GetExtendedStyle();   
  14.      NewStyle |= LVS_EX_GRIDLINES;   
  15. m_List.SetExtendedStyle(NewStyle);   
  16.   
  17.     //設(shè)置列表控件字體顏色為紅色   
  18.      m_List.SetTextColor(RGB(255, 0, 0));   
  19.   
  20.     //填充數(shù)據(jù)   
  21.      m_List.InsertColumn(0, "QQ", LVCFMT_LEFT, 100);   
  22.      m_List.InsertColumn(1, "昵稱", LVCFMT_LEFT, 100);   
  23.   
  24.      m_List.InsertItem(0, "5854165");   
  25.      m_List.SetItemText(0, 1, "白喬");   
  26.   
  27.      m_List.InsertItem(1, "6823864");   
  28.      m_List.SetItemText(1, 1, "Satan");   
  29.     //…   
  30. }  
BOOL CUi2App::InitInstance() { //… //設(shè)置對話框背景色和字體顏色 SetDialogBkColor(RGB(128, 192, 255), RGB(0, 0, 255)); //… } BOOL CUi2Dlg::OnInitDialog() { //… //設(shè)置列表控件屬性帶有表格線 DWORD NewStyle = m_List.GetExtendedStyle(); NewStyle |= LVS_EX_GRIDLINES; m_List.SetExtendedStyle(NewStyle); //設(shè)置列表控件字體顏色為紅色 m_List.SetTextColor(RGB(255, 0, 0)); //填充數(shù)據(jù) m_List.InsertColumn(0, "QQ", LVCFMT_LEFT, 100); m_List.InsertColumn(1, "昵稱", LVCFMT_LEFT, 100); m_List.InsertItem(0, "5854165"); m_List.SetItemText(0, 1, "白喬"); m_List.InsertItem(1, "6823864"); m_List.SetItemText(1, 1, "Satan"); //… }

嗯,這樣的界面還算不錯吧?

3.3 使用Windows的消息機制

使用MFC類的既有函數(shù)來美化界面,其功能是有限的。既然Windows是通過消息機制進行通訊的,那么我們就可以通過截獲一些有用的消息來美化我們的界面,以下是一些有用的Windows消息:

WM_PAINT

WM_ERASEBKGND

WM_CTLCOLOR*

WM_DRAWITEM*

WM_MEASUREITEM*

NM_CUSTOMDRAW*

注意,標注*的消息是子元素發(fā)送給父窗口的通知消息,其它的為窗口或者子元素自身的消息。

3.3.1 WM_PAINT

WM_PAINT消息相信大家都很熟悉,一個窗口要重繪了,就會有一個WM_PAINT消息發(fā)送給窗口。

可以響應窗口的WM_PAINT,以更改它們的模樣。WM_PAINT的映射函數(shù)原型如下:

afx_msg void OnPaint();

控件也是窗口,所以控件也有WM_PAINT消息,通過消息映射我們完全可以定義控件的界面。如圖5所示:

WM_PAINT[9,133字節(jié)]

圖5 利用WM_ PAINT消息美化界面

實現(xiàn)代碼也很簡單:

  1. void CLazyStatic::OnPaint()   
  2. {   
  3.      CPaintDC dc(this); // device context for painting   
  4.        
  5.     //什么都不輸出,僅僅畫一個矩形框   
  6.      CRect rc;   
  7.      GetClientRect(&rc);   
  8.      dc.Rectangle(rc);      
  9. }   
void CLazyStatic::OnPaint() { CPaintDC dc(this); // device context for painting //什么都不輸出,僅僅畫一個矩形框 CRect rc; GetClientRect(&rc); dc.Rectangle(rc); }

哈哈,簡單吧?不過WM_PAINT確實絕了點,它要求應用程序完成元素界面的所有繪制過程,想象一下如何畫出一個完整的列表控件?太煩了吧。一般來說,很少有人喜歡使用WM_PAINT,還有其它更細致的消息。

3.3.2 WM_ERASEBKGND

Windows在向窗口發(fā)送WM_PAINT消息之前,總會發(fā)送一個WM_ERASEBKGND消息通知該窗口擦除背景,默認情況下,Windows將以窗口的背景色清除該窗口。

可以響應窗口(包括子元素)的WM_ERASEBKGND,以更改它們的背景。WM_ERASEBKGND的映射函數(shù)原型如下:

afx_msg BOOL OnEraseBkgnd( CDC* pDC );

返回值:

指定背景是否已清除,如果為FALSE,系統(tǒng)將自動清除

參數(shù):

pDC指定了繪制操作所使用的設(shè)備環(huán)境。

圖6是個簡單的例子,通過OnEraseBkgnd為對話框加載了一副位圖背景:

WM_ERASEBKGND[77,332字節(jié)]

圖6 利用WM_ ERASEBKGND消息美化界面

實現(xiàn)代碼也很簡單:

  1. BOOL CUi4Dlg::OnInitDialog()   
  2. {   
  3. //…   
  4.     //加載位圖   
  5.     //CBitmap m_Back;   
  6.      m_Back.LoadBitmap(IDB_BACK);   
  7.     //…   
  8. }   
  9.   
  10. BOOL CUi4Dlg::OnEraseBkgnd(CDC* pDC)   
  11. {   
  12.      CDC dc;   
  13.      dc.CreateCompatibleDC(pDC);   
  14.      dc.SelectObject(&m_Back);   
  15.   
  16.     //獲取BITMAP對象   
  17.      BITMAP hb;   
  18.      m_Back.GetBitmap(&hb);   
  19.   
  20.     //獲取窗口大小   
  21.      CRect rt;   
  22.      GetClientRect(&rt);   
  23.     //顯示位圖   
  24.      pDC->StretchBlt(0, 0, rt.Width(), rt.Height(),   
  25.          &dc, 0, 0, hb.bmWidth, hb.bmHeight, SRCCOPY);   
  26.   
  27.     return TRUE;   
  28. }   
  29.   
  30. HBRUSH CUi4Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)   
  31. {   
  32.     //設(shè)置透明背景模式   
  33.      pDC->SetBkMode(TRANSPARENT);   
  34.     //設(shè)置背景刷子為空   
  35.     return (HBRUSH)::GetStockObject(HOLLOW_BRUSH);   
  36. }   
BOOL CUi4Dlg::OnInitDialog() { //… //加載位圖 //CBitmap m_Back; m_Back.LoadBitmap(IDB_BACK); //… } BOOL CUi4Dlg::OnEraseBkgnd(CDC* pDC) { CDC dc; dc.CreateCompatibleDC(pDC); dc.SelectObject(&m_Back); //獲取BITMAP對象 BITMAP hb; m_Back.GetBitmap(&hb); //獲取窗口大小 CRect rt; GetClientRect(&rt); //顯示位圖 pDC->StretchBlt(0, 0, rt.Width(), rt.Height(), &dc, 0, 0, hb.bmWidth, hb.bmHeight, SRCCOPY); return TRUE; } HBRUSH CUi4Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { //設(shè)置透明背景模式 pDC->SetBkMode(TRANSPARENT); //設(shè)置背景刷子為空 return (HBRUSH)::GetStockObject(HOLLOW_BRUSH); }

同時別忘了響應OnCtlColor,否則窗口里面的控件就不透明了。OnCtlColor的內(nèi)容,詳見3.3.3章節(jié)。

3.3.3 WM_CTLCOLOR

在控件顯示之前,每一個控件都會向父對話框發(fā)送一個WM_CTLCOLOR消息要求獲取繪制所需要的顏色。WM_CTLCOLOR消息缺省處理函數(shù)CWnd::OnCtlColor返回一個HBRUSH類型的句柄,這樣,就可以設(shè)置前景和背景文本顏色,并為控件或者對話框的非文本區(qū)域選定一個刷子。

WM_CTLCOLOR的映射函數(shù)原型如下:

afx_msg HBRUSH OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor );

返回值:

用以指定背景的刷子

參數(shù):

pDC指定了繪制操作所使用的設(shè)備環(huán)境。

pWnd 控件指針

nCtlColor 指定控件類型,其取值如表2所示:

類型值 含義

CTLCOLOR_BTN 按鈕控件

CTLCOLOR_DLG 對話框

CTLCOLOR_EDIT 編輯控件

CTLCOLOR_LISTBOX 列表框

CTLCOLOR_MSGBOX 消息框

CTLCOLOR_SCROLLBAR 滾動條

CTLCOLOR_STATIC 靜態(tài)控件

表2 nCtlColor的類型值與含義

作為一個簡單的例子,觀察以下的代碼:

  1. BOOL CUi5Dlg::OnInitDialog()   
  2. {   
  3.     //…   
  4.     //創(chuàng)建字體   
  5.     //CFont CUi1View::m_Font1, CUi1View::m_Font2   
  6.      m_Font1.CreatePointFont(120, "Impact");   
  7.      m_Font3.CreatePointFont(120, "Arial");   
  8.        
  9.     return TRUE;  // return TRUE   unless you set the focus to a control   
  10. }   
  11.   
  12. HBRUSH CUi5Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)   
  13. {   
  14.     HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);   
  15.     if(nCtlColor == CTLCOLOR_STATIC)   
  16.      {   
  17.         //區(qū)分靜態(tài)控件   
  18.         switch(pWnd->GetDlgCtrlID())   
  19.          {   
  20.             case IDC_STATIC1:   
  21.              {   
  22.                  pDC->SelectObject(&m_Font1);   
  23.                  pDC->SetTextColor(RGB(0, 0, 255));   
  24.                 break;   
  25.              }   
  26.             case IDC_STATIC2:   
  27.              {   
  28.                  pDC->SelectObject(&m_Font2);   
  29.                  pDC->SetTextColor(RGB(255, 0, 0));   
  30.                 break;   
  31.              }   
  32.          }   
  33.      }   
  34.   
  35.     return hbr;   
  36. }   
BOOL CUi5Dlg::OnInitDialog() { //… //創(chuàng)建字體 //CFont CUi1View::m_Font1, CUi1View::m_Font2 m_Font1.CreatePointFont(120, "Impact"); m_Font3.CreatePointFont(120, "Arial"); return TRUE; // return TRUE unless you set the focus to a control } HBRUSH CUi5Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); if(nCtlColor == CTLCOLOR_STATIC) { //區(qū)分靜態(tài)控件 switch(pWnd->GetDlgCtrlID()) { case IDC_STATIC1: { pDC->SelectObject(&m_Font1); pDC->SetTextColor(RGB(0, 0, 255)); break; } case IDC_STATIC2: { pDC->SelectObject(&m_Font2); pDC->SetTextColor(RGB(255, 0, 0)); break; } } } return hbr; }

生成的界面如下:

WM_CTLCOLOR[9,407字節(jié)]

圖7 利用WM_CTLCOLOR消息美化界面

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多