共用方式為


CTRLTEST 範例:實作自訂控制項

更新:2007 年 11 月

CTRLTEST 範例將會說明實作和使用自訂控制項的幾種技術:

  • 實作 CParsedEdit,這是一種來自其程式庫控制項類別的特殊編緝控制項的衍生功能,以及實作使用自訂控制項的三種方法。

  • 使用微調控制項。微調控制項具有小型的向上及向下箭號按鈕,可用來遞增或遞減數值。

  • 使用 CBitmapButton 進行 [自訂] 功能表命令的點陣圖按鈕實作。

  • 功能表及清單方塊的主控 (父視窗) 描繪。衍生自 CMenu 類別以及 CListBox 的對應控制項類別會以物件導向方式提供這項功能。

  • 使用無法由 Microsoft Visual C++ 資源編輯器維護的資源檔。這個示範將說明使用具有自訂控制項 (帶有標頭檔中由常數定義的樣式) 的對話方塊中 .rc2 檔的優缺點。

CTRLTEST 中的所有示範說明都透過功能表命令所開始的。

安全性注意事項:

這個程式碼範例僅供概念說明之用,同時因為範例中的程式碼撰寫並沒有周全的顧及所有安全性問題,所以本範例不適用於實際執行的應用程式或網站中。如果使用者擅自將範例程式碼用於其他意圖而導致連帶事件或重大損害時,Microsoft 將不承擔任何責任。

若要取得範例和指示以便進行安裝:

  • 按一下 Visual Studio [說明] 功能表上的 [範例]。

    如需詳細資訊,請參閱尋找範例檔案

  • 最新版的完整範例清單可從 Visual Studio 2008 範例網頁 (英文) 取得。

  • 您也可以將範例置於電腦硬碟中。根據預設,範例和讀我檔案都會複製到 \Program Files\Visual Studio 9.0\Samples\ 下的資料夾中。對於所有的 Visual Studio Express 版,所有範例都可在線上找到。

建置和執行範例

若要建置並執行 CTRLTEST 範例

  1. 開啟 Ctrltest.sln 方案。

  2. 在 [建置] 功能表上按一下 [建置]。

  3. 在 [偵錯] 功能表上,請按一下 [啟動但不偵錯]。

範例:實作和使用自訂控制項

您可以從 CWnd 衍生來實作一個自訂控制項,但是如果從在程式庫的控制項類別衍生的標準 Windows 控制項來借用這項功能,則可以採取更簡單的步驟。CTRLTEST 便是以這種作法來實作 CParsedEdit 這個特殊編輯控制項,該編輯控制項只接受指定的字元集做為包括數字、字母或非控制字元的使用者輸入。CParsedEdit 衍生自 CEdit,它具有可篩選字元的 OnChar 訊息處理常式 (Message Handler)。

[Simple] 功能表的命令實作說明了三個使用自訂控制項的方法。這些方法可以根據應用程式為對話方塊控制項的執行個體和 CParsedEdit 類別建立關聯的方式而有所不同。每一個 [Simple] 功能表命令都會顯示包含 CParsedEdit 控制項的四個執行個體的對話方塊。在這種對話方塊中輸入的資料都會傳送至偵錯埠,做為 TRACE 輸出。這三個 [Simple] 功能表命令分別是:

Test C++ Derived Class

CParsedEdit 控制項是對話方塊類別的資料成員。呼叫 CParsedEdit::CreateSet 可以明確地使用對話方塊的 OnInitDialog 函式來建立控制項。請參閱 Dertest.cpp。

Test WNDCLASS Registered

CParsedEdit 控制項會配置在對話方塊樣板資源中 (IDD_WNDCLASS_EDIT),表示識別為 "paredit" WNDCLASS 的自訂控制項。使用 Visual C++ 對話方塊編輯器檢查這些自訂控制項的屬性,是相當有用的作法。

  • Caption blank (標題空白),這會是 CParsedEdit 控制項中顯示的初始值。

  • Class:paredit,這是在呼叫對話方塊之前,CParsedEdit::RegisterControlClass 於 PAREDIT2.CPP 中登錄的 WNDCLASS 名稱。

  • Visible:checked,控制項可以看得見。

  • Tabstop:checked,使用者可定位至這個控制項。

  • Style:0x5081002、0x5081001、0x5081003、0x5081ffff 分別代表四個已剖析的編輯控制項。0x500000 樣式代表 WS_CHILD 和 WS_VISIBLE,0x1000 代表 WS_TABSTOP。所有的自訂控制項都有 WS_CHILD 樣式。當您核取 Visible 和 Tabstop 樣式時,對話方塊編輯器會自動設定 WS_VISIBLE 和 WS_TABSTOP 樣式。0x80000 代表 WS_BORDER。因為自訂控制項的對話方塊編輯器屬性頁會提供所有的視窗樣式 (例如 WS_BORDER),因此您必須在 \Microsoft Visual Studio .NET 2003\Vc7\PlatformSDK\Include\WINUSER.H 中查詢常數。0x0001、0x0002、0x0004 和 0x0ffff 這些樣式已定義於 PAREDIT.H,分別表示為 PES_NUMBERS、PES_LETTERS、PER_OTHERCHARS 和 PES_ALL。

  • 自訂控制項屬性頁中的十六進位樣式不會自行說明。如果使用符號樣式 (例如 PES_NUMBERS 和 PES_LETTERS) 對您來說非常重要,您可另行手動編輯不同的資源檔 (例如,RES\Ctrltest.rc2),這是已由資源編譯器在編譯時間包含、但在 Visual C++ 的編輯時間時不會讀取的個別資源檔。如需手動編輯 .rc2 檔中自訂控制項對話方塊的優缺點詳細討論,請參閱使用無法由 Microsoft Visual C++ 資源編輯器維護的資源檔。

Test Dynamic Subclassed

控制項會配置在對話方塊樣板資源中 (Ctrltest.rc 中的 IDD_SUB_EDIT) 做為標準的編輯控制項。這些控制項會宣告為對話方塊類別的 CParsedEdit 資料成員。該對話方塊的 OnInitDialog 函式會呼叫可依序呼叫 CWnd::SubclassDlgItemCParsedEdit::SubClassEdit,為每個編輯控制項的特定執行個體和 CParsedEdit 類別建立關聯。請參閱 Paredit.cpp。

範例:微調控制項

CTRLTEST 範例包含了微調控制項的實作。微調控制項具有小型的向上及向下箭號按鈕,可用來遞增或遞減數值。

[Spin Control] 命令會呼叫具有四個 CParsedEdit 控制項 (每一個都和微調控制項關聯) 的對話方塊。在這個對話方塊中之 CParsedEdit 控制項所輸入的資料會經過篩選,只接受非負值的整數。使用者可以在 CParsedEdit 控制項中輸入值或使用關聯的微調控制項來輸入數值資料。

範例:點陣圖按鈕

下列的 [Custom] 功能表命令實作會解說 CBitmapButton 的使用方法:

  • Bitmap Button 1:該對話方塊建構函式會呼叫 CBitmapButton::LoadBitmaps,明確地載入三種按鈕狀態 (上移、下移及焦聚) 的點陣圖資源。

  • Bitmap Button 2:該對話方塊的 OnInitDialog 函式會呼叫 CBitmapButton::Autoload,根據下列命名慣例載入點陣圖資源。控制項的視窗文字將做為基底資源名稱,並再附加 U、D 和 F 字母,來分別為上移、下移及焦點等三個點陣圖影像建立資源名稱。例如,[確定] 按鈕的三個點陣圖資源分別命名為 OKU、OKD 和 OKF。

  • Bitmap Button 3:該對話方塊是上述第二個對話方塊的擴充功能,會使用第四個可能的按鈕狀態 (已停用)。若要使用這個對話方塊,請按一下向左或向右箭號的點陣圖按鈕,直到數字顯示為 1 (最低數字) 或 10 (最高數字)。到達數字上/下限時,該按鈕就會停用並顯示第四個點陣圖影像。停用狀態的點陣圖資源命名慣例的字尾是一個 X,與資源名稱 PREVX 和 NEXTX 所反映的結果一樣。

範例:主控描繪 (功能表和清單方塊)

許多種 Windows 控制項和功能表都有主控描繪功能,可以讓父 (或主控) 視窗在控制項的工作區 (Client Area) 中描繪它想要的任何圖案,而不是進行標準的控制項行為。對應的控制項類別和 CMenu 類別會以更方便的物件導向方式來提供這項功能,也就是由控制項或功能表類別來處理描繪作業,這種作法稱為「自繪」(Self Drawing)。

CTRLTEST 將說明在 [Custom] 功能表中實作下列命令的一般主控描繪技術:

  • Custom Menu:這個功能表項目會呼叫衍生自 CMenuCColorMenu 快顯功能表。每一個子功能表項目都會使用自繪功能,顯示八種色彩中的其中一種。此時會出現一個確認您在子功能表中選取顏色的訊息方塊。

  • Custom List Box:這個功能表項目會呼叫衍生自 CListBox、可顯示 CColorListBox 的對話方塊。該清單方塊有八個項目,每個項目都會使用自繪功能,以八種色彩的其中一種進行描繪。TRACE 輸出可以確認您在清單方塊的選取項目。

範例:使用無法由 Visual C++ 資料編輯器維護的資源檔

資源檔 CTRLTEST\RES\Ctrltest.rc2 示範的是 Visual C++ 資源編輯器無法以人們可讀取的 (Human-Readable) 格式進行維護的資源檔。即使資源編譯器仍能編譯 .rc2 檔並產生對等的二進位 .res 檔,但如果您想在 Visual C++ 中開啟 Ctrltest.rc2 後再進行儲存,就會流失一般人可以讀取的有用資訊。因此,已使用由 [Resource File Set Includes] 命令所指定的編譯時期指示詞,將 RES\Ctrltest.rc2 當做 #include 加入至 Ctrltest.rc。

下列為三種無法由 Visual C++ 資源編輯器維護、但一般人可以讀取的資訊類別。Ctrltest.rc2 示範了其中兩種類別:

  • 自訂控制項樣式符號:例如,"msctls_updown32" 是為微調控制項所定義的樣式。雖然 Visual C++ 在讀取 .rc2 檔時可以解譯這個符號,但是會將它以十六進位值寫回到該 .rc2 檔。

  • 標準 Windows 控制項所衍生之類別中的控制項內所使用的標準 Windows WS_ 或控制項樣式符號:例如,ES_AUTOHSCROLL 是為 IDD_SPIN_EDIT 對話方塊微調控制項所定義的樣式。雖然 Visual C++ 在讀取 .rc2 檔時可以解譯這些符號,但是會將它以十六進位值寫回到該 .rc2 檔。

  • .rc 檔中的算術:如 "IDC_EDIT1+2" 等用於識別 IDD_SPIN_EDIT 對話方塊控制項的運算式,會由 Visual C++ 以十六進位值寫回到該 .rc2 檔。

CTRLTEST 範例會示範在對話方塊具有以標頭檔常數定義樣式之自訂控制項時,使用 .rc2 檔的優缺點。IDD_WNDCLASS_EDITIDD_SPIN_EDIT 這兩個對話方塊的自訂控制項都有以符號定義的樣式,但 IDD_WNDCLASS 是指定於可由 Visual C++ 對話方塊編輯器編輯的 .rc 檔中,而 IDD_SPIN_EDIT 則是在只能手動編輯的 .rc2 檔中所指定的。

使用 .rc 檔和 .rc2 檔的差異將摘要說明如下。

使用 IDD_WNDCLASS_EDIT 對話方塊時,資源指令碼是定義於 Ctrltest.rc,而使用的是 IDD_SPIN_EDIT 對話方塊時,資源指令碼則會定義在 RES\Ctrltest.rc2。使用 IDD_WNDCLASS_EDIT 對話方塊時,WNDCLASS 自訂控制項是 "paredit",樣式常數會定義於 PAREDIT.H,且範例樣式常數為 PES_NUMBER。IDD_WNDCLASS_EDIT 可以由 Visual C++ 進行編輯,但無法使用 #define 樣式。IDD_SPIN_EDIT 無法由 Visual C++ 進行編輯,但可以使用 #define 樣式。

難以兩全其美的是,如果您使用 .rc2 檔,就可以為自訂控制項使用定義於標頭檔且一般人能夠讀取的符號樣式,但是卻不能使用 Visual C++ 對話方塊編輯器來編輯 .rc2 檔。使用 Visual C++ 配置對話方塊會比手動撰寫資源指令碼更容易,且撰寫資源指令碼比較容易發生錯誤。另一方面,當這些樣式是由 Visual C++ 對話方塊編輯器以十六進位顯示於自訂控制項屬性頁中時,這些樣式會無法自行記載。

關鍵字

本範例會使用下列關鍵字:

AfxGetInstanceHandle; AfxMessageBox; AfxThrowResourceException; CBitmapButton::AutoLoad; CDC::FillRect; CDC::FrameRect; CDialog::DoModal; CDialog::EndDialog; CDialog::OnInitDialog; CDialog::OnOK; CDialog::OnSetFont; CEdit::Create; CEdit::SetSel; CFrameWnd::Create; CListBox::AddString; CListBox::CompareItem; CListBox::DrawItem; CListBox::GetItemData; CListBox::MeasureItem; CMenu::AppendMenu; CMenu::CreateMenu; CMenu::Detach; CMenu::DrawItem; CMenu::EnableMenuItem; CMenu::FromHandle; CMenu::GetMenuString; CMenu::MeasureItem; CRect::Width; CStatic::Create; CString::Format; CString::LoadString; CWinApp::InitInstance; CWnd::Attach; CWnd::EnableWindow; CWnd::FromHandle; CWnd::GetDlgCtrlID; CWnd::GetDlgItem; CWnd::GetDlgItemInt; CWnd::GetMenu; CWnd::GetParent; CWnd::GetWindowRect; CWnd::GetWindowText; CWnd::IsWindowEnabled; CWnd::MessageBox; CWnd::OnChar; CWnd::OnCommand; CWnd::OnVScroll; CWnd::PostNcDestroy; CWnd::SendMessage; CWnd::SetDlgItemInt; CWnd::SetFocus; CWnd::SetFont; CWnd::SetWindowPos; CWnd::ShowWindow; CWnd::SubclassDlgItem; CallWindowProc; GetBValue; GetClassInfo; GetGValue; GetRValue; GetSystemMetrics; HIWORD; IsCharAlpha; IsCharAlphaNumeric; LOWORD; MAKEINTRESOURCE; MAKELONG; MessageBeep; ModifyMenu; RGB; RegisterClass; SetWindowLong

注意事項:

部分範例 (包括本範例) 尚未經過改寫,無法反映出目前在 Visual C++ 精靈、程式庫以及編譯器方面的變更,不過還是可以示範如何完成您要進行的工作。

請參閱

其他資源

MFC 範例