TN026: Rutinitas DDX dan DDV
Catatan
Catatan teknis berikut belum diperbarui sejak pertama kali disertakan dalam dokumentasi online. Akibatnya, beberapa prosedur dan topik mungkin kedaluarsa atau salah. Untuk informasi terbaru, disarankan agar Anda mencari topik yang menarik dalam indeks dokumentasi online.
Catatan ini menjelaskan arsitektur pertukaran data dialog (DDX) dan validasi data dialog (DDV). Ini juga menjelaskan bagaimana Anda menulis prosedur DDX_ atau DDV_ dan bagaimana Anda dapat memperluas ClassWizard untuk menggunakan rutinitas Anda.
Gambaran Umum Pertukaran Data Dialog
Semua fungsi data dialog dilakukan dengan kode C++. Tidak ada sumber daya khusus atau makro ajaib. Inti mekanisme adalah fungsi virtual yang ditimpa di setiap kelas dialog yang melakukan pertukaran dan validasi data dialog. Ini selalu ditemukan dalam bentuk ini:
void CMyDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX); // call base class
//{{AFX_DATA_MAP(CMyDialog)
<data_exchange_function_call>
<data_validation_function_call>
//}}AFX_DATA_MAP
}
Format khusus komentar AFX memungkinkan ClassWizard menemukan dan mengedit kode dalam fungsi ini. Kode yang tidak kompatibel dengan ClassWizard harus ditempatkan di luar komentar format khusus.
Dalam contoh di atas, <data_exchange_function_call> dalam bentuk:
DDX_Custom(pDX, nIDC, field);
dan <data_validation_function_call> bersifat opsional dan dalam bentuk:
DDV_Custom(pDX, field, ...);
Lebih dari satu pasangan DDX_/DDV_ dapat disertakan dalam setiap DoDataExchange
fungsi.
Lihat 'afxdd_.h' untuk daftar semua rutinitas pertukaran data dialog dan rutinitas validasi data dialog yang disediakan dengan MFC.
Data dialog hanyalah bahwa: data anggota di CMyDialog
kelas . Ini tidak disimpan dalam struct atau sesuatu yang serupa.
Catatan
Meskipun kami menyebutnya "data dialog", semua fitur tersedia di kelas apa pun yang berasal dari CWnd
dan tidak terbatas hanya pada dialog.
Nilai awal data diatur dalam konstruktor C++ standar, biasanya dalam blok dengan //{{AFX_DATA_INIT
komentar dan //}}AFX_DATA_INIT
.
CWnd::UpdateData
adalah operasi yang melakukan inisialisasi dan penanganan kesalahan di sekitar panggilan ke DoDataExchange
.
Anda dapat menghubungi CWnd::UpdateData
kapan saja untuk melakukan pertukaran dan validasi data. Secara default UpdateData
(TRUE) dipanggil dalam handler default CDialog::OnOK
dan UpdateData
(FALSE) dipanggil dalam default CDialog::OnInitDialog
.
Rutinitas DDV_ harus segera mengikuti rutinitas DDX_ untuk bidang tersebut.
Bagaimana Cara Kerjanya
Anda tidak perlu memahami hal berikut untuk menggunakan data dialog. Namun, memahami cara kerjanya di belakang layar akan membantu Anda menulis prosedur pertukaran atau validasi Anda sendiri.
Fungsi DoDataExchange
anggota mirip dengan Serialize
fungsi anggota - bertanggung jawab untuk mendapatkan atau mengatur data ke/dari formulir eksternal (dalam hal ini kontrol dalam dialog) dari/ke data anggota di kelas. Parameter pDX adalah konteks untuk melakukan pertukaran data dan mirip CArchive
dengan parameter dengan CObject::Serialize
. pDX (CDataExchange
objek) memiliki bendera arah seperti CArchive
memiliki bendera arah:
Jika
!m_bSaveAndValidate
, muat status data ke dalam kontrol.Jika
m_bSaveAndValidate
, maka atur status data dari kontrol.
Validasi hanya terjadi ketika m_bSaveAndValidate
diatur. Nilai m_bSaveAndValidate
ditentukan oleh parameter BOOL ke CWnd::UpdateData
.
Ada tiga anggota menarik CDataExchange
lainnya:
m_pDlgWnd
: Jendela (biasanya dialog) yang berisi kontrol. Hal ini untuk mencegah penelepon fungsi global DDX_ dan DDV_ harus meneruskan 'ini' ke setiap rutinitas DDX/DDV.PrepareCtrl
, danPrepareEditCtrl
: Menyiapkan kontrol dialog untuk pertukaran data. Menyimpan handel kontrol tersebut untuk mengatur fokus jika validasi gagal.PrepareCtrl
digunakan untuk kontrol non-edit danPrepareEditCtrl
digunakan untuk kontrol edit.Fail
: Dipanggil setelah memunculkan kotak pesan yang memperingatkan pengguna untuk kesalahan input. Rutinitas ini akan memulihkan fokus ke kontrol terakhir (panggilan terakhir kePrepareCtrl
atauPrepareEditCtrl
) dan melemparkan pengecualian. Fungsi anggota ini dapat dipanggil dari rutinitas DDX_ dan DDV_.
Ekstensi Pengguna
Ada beberapa cara untuk memperluas mekanisme DDX/DDV default. Anda dapat:
Tambahkan jenis data baru.
CTime
Tambahkan prosedur pertukaran baru (DDX_).
void PASCAL DDX_Time(CDataExchange* pDX, int nIDC, CTime& tm);
Tambahkan prosedur validasi baru (DDV_).
void PASCAL DDV_TimeFuture(CDataExchange* pDX, CTime tm, BOOL bFuture); // make sure time is in the future or past
Teruskan ekspresi arbitrer ke prosedur validasi.
DDV_MinMax(pDX, age, 0, m_maxAge);
Catatan
Ekspresi arbitrer tersebut tidak dapat diedit oleh ClassWizard dan oleh karena itu harus dipindahkan ke luar komentar format khusus (//{{AFX_DATA_MAP(CMyClass)).
Mintalah DoDataExchange
fungsi anggota menyertakan pernyataan C++ yang valid lainnya dengan pertukaran intermix dan panggilan fungsi validasi.
//{{AFX_DATA_MAP(CMyClass)
DDX_Check(pDX, IDC_SEX, m_bFemale);
DDX_Text(pDX, IDC_EDIT1, m_age);
//}}AFX_DATA_MAP
if (m_bFemale)
DDV_MinMax(pDX, age, 0, m_maxFemaleAge);
else
DDV_MinMax(pDX, age, 0, m_maxMaleAge);
Catatan
Seperti yang ditunjukkan di atas, kode tersebut tidak dapat diedit oleh ClassWizard dan harus digunakan hanya di luar komentar format khusus.
Dukungan ClassWizard
ClassWizard mendukung subset kustomisasi DDX/DDV dengan memungkinkan Anda mengintegrasikan DDX_ Anda sendiri dan DDV_ rutinitas ke antarmuka pengguna ClassWizard. Melakukan ini hanya bermanfaat biaya jika Anda berencana untuk menggunakan kembali rutinitas DDX dan DDV tertentu dalam proyek atau di banyak proyek.
Untuk melakukan ini, entri khusus dibuat di DDX.CLW (versi Visual C++ sebelumnya menyimpan informasi ini di APSTUDIO. INI) atau dalam proyek Anda . File CLW. Entri khusus dapat dimasukkan baik di bagian [Info Umum] dari proyek Anda. File CLW atau di bagian [ExtraDDX] dari file DDX.CLW di direktori \Program Files\Microsoft Visual Studio\Visual C++\bin. Anda mungkin perlu membuat file DDX.CLW jika belum ada. Jika Anda berencana untuk menggunakan rutinitas DDX_/DDV_ kustom hanya dalam proyek tertentu, tambahkan entri ke bagian [Info Umum] proyek Anda . File CLW sebagai gantinya. Jika Anda berencana untuk menggunakan rutinitas pada banyak proyek, tambahkan entri ke bagian [ExtraDDX] DDX.CLW.
Format umum entri khusus ini adalah:
ExtraDDXCount=n
di mana n adalah jumlah baris ExtraDDX? yang harus diikuti, dari formulir
ExtraDDX?=keys; vb-keys; prompt; jenis; initValue; DDX_Proc [; DDV_Proc; prompt1; arg1 [; prompt2; fmt2]]
Mana? adalah angka 1 - n yang menunjukkan jenis DDX mana dalam daftar yang sedang ditentukan.
Setiap bidang dibatasi oleh karakter ';'. Bidang dan tujuannya dijelaskan di bawah ini.
kunci
Daftar karakter tunggal yang menunjukkan dialog mana yang mengontrol jenis variabel ini diizinkan.
karakter Kontrol yang diizinkan E edit C kotak centang dua status c kotak centang tri-status R tombol radio pertama dalam grup L kotak daftar nonsorted l kotak daftar terurut M kotak kombo (dengan item edit) N daftar drop yang tidak diurai n daftar drop yang diurutkan 1 jika sisipan DDX harus ditambahkan ke kepala daftar (defaultnya ditambahkan ke ekor) Ini umumnya digunakan untuk rutinitas DDX yang mentransfer properti 'Kontrol'. vb-keys
Bidang ini hanya digunakan dalam produk 16-bit untuk kontrol VBX (kontrol VBX tidak didukung dalam produk 32-bit)
perintah
String untuk ditempatkan dalam kotak kombo Properti (tanpa tanda kutip)
jenis
Pengidentifikasi tunggal untuk jenis yang akan dipancarkan dalam file header. Dalam contoh kami di atas dengan DDX_Time, ini akan diatur ke CTime.
vb-keys
Tidak digunakan dalam versi ini dan harus selalu kosong
initValue
Nilai awal — 0 atau kosong. Jika kosong, maka tidak ada baris inisialisasi yang akan ditulis di bagian //{{AFX_DATA_INIT dari file implementasi. Entri kosong harus digunakan untuk objek C++ (seperti , ,
CTime
dan sebagainyaCString
) yang memiliki konstruktor yang menjamin inisialisasi yang benar.DDX_Proc
Pengidentifikasi tunggal untuk prosedur DDX_. Nama fungsi C++ harus dimulai dengan "DDX_," tetapi jangan sertakan "DDX_" dalam <pengidentifikasi DDX_Proc> . Dalam contoh di atas, <pengidentifikasi DDX_Proc> adalah Waktu. Ketika ClassWizard menulis panggilan fungsi ke file implementasi di bagian {{AFX_DATA_MAP, classWizard menambahkan nama ini ke DDX_, sehingga tiba di DDX_Time.
komentar
Komentar untuk ditampilkan dalam dialog untuk variabel dengan DDX ini. Tempatkan teks apa pun yang Anda inginkan di sini, dan biasanya berikan sesuatu yang menjelaskan operasi yang dilakukan oleh pasangan DDX/DDV.
DDV_Proc
Bagian DDV dari entri bersifat opsional. Tidak semua rutinitas DDX memiliki rutinitas DDV yang sesuai. Seringkali, lebih mudah untuk menyertakan fase validasi sebagai bagian integral dari transfer. Ini sering terjadi ketika rutinitas DDV Anda tidak memerlukan parameter apa pun, karena ClassWizard tidak mendukung rutinitas DDV tanpa parameter apa pun.
Arg
Pengidentifikasi tunggal untuk prosedur DDV_. Nama fungsi C++ harus dimulai dengan "DDV_", tetapi jangan sertakan "DDX_" dalam <pengidentifikasi DDX_Proc> .
arg diikuti oleh 1 atau 2 args DDV:
promptN
String untuk ditempatkan di atas item edit (dengan & untuk akselerator).
fmtN
Format karakter untuk jenis arg, salah satu dari:
karakter Jenis d int u int tidak bertanda D int panjang (yaitu, panjang) U panjang tidak ditandatangani (yaitu, DWORD) f float F ganda s string
Baca juga
Catatan Teknis menurut Angka
Catatan Teknis menurut Kategori